-
I almost have shadows working in a 3d engine in flash, need help on a little problem
Hi
I am using a modified version of the 3d system given in the book "actionscript animation"
it works well except that the shadows do not render properly, I am completely stumped as to what to do.
as you will be able to see from the code (no movieclips required) the shadows only seem to join 2 of their points, thus not filling themselves.
any help would be greatly appreciated
thanks
Code:
var points:Array = new Array();
var triangles:Array = new Array();
var shadowPoints:Array = new Array();
var shadowTriangles:Array = new Array();
var fl:Number = 500;
var vpX:Number = Stage.width / 2;
var vpY:Number = Stage.height / 2;
var zOffset:Number = 500;
var bottom:Number = 300;
var light:Object = new Object();
var basePoints:Number;
var angle:Number = 0;
var centerZ:Number = 0;
var centerX:Number = 0;
var radius:Number = 500;
var speed:Number = 0.1;
init();
function init() {
light.x = 100;
light.y = -900;
light.z = 100;
light.brightness = 100;
points[0] = {x: 0, y: 100, z: 0};
points[1] = {x: 100, y: 250, z:-100};
points[2] = {x:-100, y: 250, z:-100};
points[3] = {x:-100, y: 250, z: 100};
points[4] = {x: 100, y: 250, z: 100};
triangles[0] = {a:0, b:1, c:2, col:0xffcc00};
triangles[1] = {a:0, b:2, c:3, col:0xffcc00};
triangles[2] = {a:0, b:3, c:4, col:0xffcc00};
triangles[3] = {a:0, b:4, c:1, col:0xffcc00};
triangles[4] = {a:1, b:3, c:2, col:0xffcc00};
triangles[5] = {a:1, b:4, c:3, col:0xffcc00};
for (var j:Number=0;j<triangles.length;j++)
{
shadowTriangles[j] = {a:triangles[j].a, b:triangles[j].b, c:triangles[j].b, col:0x000000, isShadow:true};
}
}
function onEnterFrame():Void {
var numPoints:Number = points.length;
makeShadows()
for (var i:Number=0;i<numPoints;i++) {
var point:MovieClip = points[i];
var scale:Number = fl / (fl + point.z + zOffset);
point.xPos = vpX + point.x * scale;
point.yPos = vpY + point.y * scale;
}
light.z = centerZ + Math.cos(angle) * radius;
light.x = centerX + Math.sin(angle) * radius;
angle += speed;
clear();
triangles.sort(triSort);
for(var i:Number=0;i<shadowTriangles.length;i++)
{
renderShadows(shadowTriangles[i]);
}
for(var i:Number =0;i<triangles.length;i++)
{
renderTriangle(triangles[i]);
}
}
function makeShadows()
{
for (var i:Number=0;i<points.length;i++)
{
var point:MovieClip = points[i];
var sunDifferenceX = point.x - light.x;
var sunDifferenceY = point.y - light.y;
var sunDifferenceZ = point.z - light.z;
var sunBearing:Number = Math.atan2(sunDifferenceZ, sunDifferenceX);
var sunElevation:Number = Math.atan2(sunDifferenceY, Math.sqrt(sunDifferenceX*sunDifferenceX + sunDifferenceZ*sunDifferenceZ));
var radius:Number = Math.tan(sunElevation)* (bottom - point.y);
var bearing:Number = sunBearing;
var Xpos:Number = point.x + Math.cos(bearing) * radius;
var Zpos:Number = point.z + Math.sin(bearing) * radius;
shadowPoints[i] = {x:Xpos , y:bottom ,z:Zpos};
var scale:Number = fl / (fl + shadowPoints[i].z + zOffset);
shadowPoints[i].xPos = vpX + shadowPoints[i].x * scale;
shadowPoints[i].yPos = vpY + shadowPoints[i].y * scale;
}
}
function renderShadows(tri:Object):Void
{
var pointA:Object = shadowPoints[tri.a];
var pointB:Object = shadowPoints[tri.b];
var pointC:Object = shadowPoints[tri.c];
lineStyle(1);
beginFill(0x000000,100);
moveTo(pointA.xPos, pointA.yPos);
lineTo(pointB.xPos, pointB.yPos);
lineTo(pointC.xPos, pointC.yPos);
lineTo(pointA.xPos, pointA.yPos);
endFill();
}
function renderTriangle(tri:Object):Void
{
var pointA:Object = points[tri.a];
var pointB:Object = points[tri.b];
var pointC:Object = points[tri.c];
if(isBackFace(pointA, pointB, pointC))
{
return;
}
var col:Number = getTriangleColor(tri);
lineStyle(0,0,0)
beginFill(col, 100);
moveTo(pointA.xPos, pointA.yPos);
lineTo(pointB.xPos, pointB.yPos);
lineTo(pointC.xPos, pointC.yPos);
lineTo(pointA.xPos, pointA.yPos);
endFill();
}
function isBackFace(pointA:Object, pointB:Object, pointC:Object):Boolean
{
var cax:Number = pointC.xPos - pointA.xPos;
var cay:Number = pointC.yPos - pointA.yPos;
var bcx:Number = pointB.xPos - pointC.xPos;
var bcy:Number = pointB.yPos - pointC.yPos;
return cax * bcy > cay * bcx;
}
function triSort(triA:Object, triB:Object):Number
{
var zA:Number = Math.min(points[triA.a].z, points[triA.b].z);
zA = Math.min(zA, points[triA.c].z);
var zB:Number = Math.min(points[triB.a].z, points[triB.b].z);
zB = Math.min(zB, points[triB.c].z);
if(zA < zB)
{
return 1;
}
else
{
return -1;
}
}
function getTriangleColor(tri:Object):Number
{
var pointA:Object = points[tri.a];
var pointB:Object = points[tri.b];
var pointC:Object = points[tri.c];
var lightFactor:Number = getLightFactor(pointA, pointB, pointC);
var red:Number = tri.col >> 16;
var green:Number = tri.col >> 8 & 0xff;
var blue:Number = tri.col & 0xff;
red *= lightFactor;
green *= lightFactor;
blue *= lightFactor;
return red << 16 | green << 8 | blue;
}
function getLightFactor(ptA:Object, ptB:Object, ptC:Object):Number
{
var ab:Object = new Object();
ab.x = ptA.x - ptB.x;
ab.y = ptA.y - ptB.y;
ab.z = ptA.z - ptB.z;
var bc:Object = new Object();
bc.x = ptB.x - ptC.x;
bc.y = ptB.y - ptC.y;
bc.z = ptB.z - ptC.z;
var norm:Object = new Object();
norm.x = (ab.y * bc.z) - (ab.z * bc.y);
norm.y = -((ab.x * bc.z) - (ab.z * bc.x));
norm.z = (ab.x * bc.y) - (ab.y * bc.x);
var dotProd:Number = norm.x * light.x +
norm.y * light.y +
norm.z * light.z;
var normMag:Number = Math.sqrt(norm.x * norm.x +
norm.y * norm.y +
norm.z * norm.z);
var lightMag:Number = Math.sqrt(light.x * light.x +
light.y * light.y +
light.z * light.z);
return (Math.acos(dotProd / (normMag * lightMag)) / Math.PI) * light.brightness / 100;
}
-
All 1s and 0s
Hi,
Just a coding error (see italics)
code:
for (var j:Number=0;j<triangles.length;j++)
{
shadowTriangles[j] = {a:triangles[j].a, b:triangles[j].b, c:triangles[j].c, col:0x000000, isShadow:true};
}
Hope this helps.
"If I have seen further, it is by standing on the shoulders of giants." - Sir Isaac Newton
-
thanks for that, but I have found a better way to do this, the shadowTriangles are identical to the triangles, they just refer to different points.
I just used the regular triangles, eliminating the need for the shadowtrianlges.
Code:
var points:Array = new Array();
var triangles:Array = new Array();
var shadowPoints:Array = new Array();
var shadowTriangles:Array = new Array();
var fl:Number = 500;
var vpX:Number = Stage.width / 2;
var vpY:Number = Stage.height / 2;
var zOffset:Number = 50;
var xOffset:Number = 0;
var bottom:Number = 250;
var light:Object = new Object();
var basePoints:Number;
var angle:Number = 0.5;
var centerZ:Number = 0;
var centerX:Number = 0;
var radius:Number = 10000;
var speed:Number = 0.01;
init();
function init() {
light.x = -100;
light.y = -400;
light.z = -100;
light.brightness = 100;
var numFaces:Number = 150;
var radius:Number = 100;
var length:Number = 200
var index:Number = 0;
for(var i:Number = 0;i<numFaces;i++)
{
var angle:Number = Math.PI * 2 / numFaces * i;
var x:Number = Math.cos(angle) * radius;
var y:Number = Math.sin(angle) * radius;
points[index] = {x:x, y:y, z:length/2 - length};
points[index + 1] = {x:x, y:y, z:length/2};
index += 2;
}
points[points.length+1] = {x:0, y:0, z:length/2 - length};
points[points.length+1] = {x:0, y:0, z:length/2};
index = 0;
pointsNo = points.length
for(var i:Number = 0;i<numFaces-1;i++)
{
triangles[index] = {a:index, b:index + 1, c:index + 3, col:0x6666cc};
triangles[index+1] = {a:index, b:index + 3, c:index + 2, col:0x6666cc};
//triangles[index+2] = {a:pointsNo, b:index, c:index + 1, col:0x6666cc};
//triangles[index+3] = {a:pointsNo - 1, b:index + 3, c:index + 2, col:0x6666cc};
index += 2;
}
triangles[index] = {a:index, b:index + 1, c:1, col:0x6666cc};
triangles[index+1] = {a:index, b:1, c:0, col:0x6666cc};
/*
index = 0;
pointsNo = points.length
for(var i:Number = 0;i<numFaces-2;i++)
{
triNo = triangles.length
triangles[triNo+1] = {a:pointsNo, b:index, c:index + 1, col:0x6666cc};
//triangles[index+3] = {a:pointsNo - 1, b:index + 3, c:index + 2, col:0x6666cc};
index += 1;
}
*/
/*
points[0] = {x: 0, y: 100, z: 0};
points[1] = {x: 100, y: 250, z:-100};
points[2] = {x:-100, y: 250, z:-100};
points[3] = {x:-100, y: 250, z: 100};
points[4] = {x: 100, y: 250, z: 100};
triangles[0] = {a:0, b:1, c:2, col:0xffcc00};
triangles[1] = {a:0, b:2, c:3, col:0xffcc00};
triangles[2] = {a:0, b:3, c:4, col:0xffcc00};
triangles[3] = {a:0, b:4, c:1, col:0xffcc00};
triangles[4] = {a:1, b:3, c:2, col:0xffcc00};
triangles[5] = {a:1, b:4, c:3, col:0xffcc00};
points[5] = {x: 200, y: 100, z: 0};
points[6] = {x: 300, y: 250, z:-100};
points[7] = {x:100, y: 250, z:-100};
points[8] = {x:100, y: 250, z: 100};
points[9] = {x: 300, y: 250, z: 100};
triangles[6] = {a:5, b:6, c:7, col:0xffcc00};
triangles[7] = {a:5, b:7, c:8, col:0xffcc00};
triangles[8] = {a:5, b:8, c:9, col:0xffcc00};
triangles[9] = {a:5, b:9, c:6, col:0xffcc00};
triangles[10] = {a:6, b:8, c:7, col:0xffcc00};
triangles[11] = {a:6, b:9, c:8, col:0xffcc00};
*/
}
function onEnterFrame():Void {
if(Key.isDown(Key.LEFT))
{
xOffset -= 10;
}
else if(Key.isDown(Key.RIGHT))
{
xOffset += 10;
}
if(Key.isDown(Key.UP))
{
zOffset += 10;
}
else if(Key.isDown(Key.DOWN))
{
zOffset -= 10;
}
makeShadows()
var numPoints:Number = points.length;
for (var i:Number=0;i<numPoints;i++) {
var point:MovieClip = points[i];
var angleY:Number = (_xmouse - vpX) * .0003;
var cosY:Number = Math.cos(angleY);
var sinY:Number = Math.sin(angleY);
var angleX:Number = (_ymouse - vpY) * .0003;
var cosX:Number = Math.cos(angleX);
var sinX:Number = Math.sin(angleX);
var x1:Number = point.x * cosY - point.z * sinY;
var z1:Number = point.z * cosY + point.x * sinY;
var y1:Number = point.y * cosX - z1 * sinX;
var z2:Number = z1 * cosX + point.y * sinX;
point.x = x1;
point.y = y1;
point.z = z2;
var scale:Number = fl / (fl + point.z + zOffset);
point.xPos = vpX + (point.x + xOffset) * scale;
point.yPos = vpY + point.y * scale;
}
light.z = centerZ + Math.cos(angle) * radius;
light.x = centerX + Math.sin(angle) * radius;
//angle += speed;
clear();
triangles.sort(triSort);
for(var i:Number =0;i<triangles.length;i++)
{
renderTriangle(triangles[i],true);
}
for(var i:Number =0;i<triangles.length;i++)
{
renderTriangle(triangles[i],false);
}
}
function makeShadows()
{
for (var i:Number=0;i<points.length;i++)
{
var point:MovieClip = points[i];
var sunDifferenceX = point.x - light.x;
var sunDifferenceY = point.y - light.y;
var sunDifferenceZ = point.z - light.z;
var sunBearing:Number = Math.atan2(sunDifferenceZ, sunDifferenceX);
var sunElevation:Number = Math.atan2(sunDifferenceY, Math.sqrt(sunDifferenceX*sunDifferenceX + sunDifferenceZ*sunDifferenceZ));
var radius:Number = Math.tan(sunElevation)* (bottom - point.y);
var bearing:Number = sunBearing;
var Xpos:Number = point.x + Math.cos(bearing) * radius;
var Zpos:Number = point.z + Math.sin(bearing) * radius;
shadowPoints[i] = {x:Xpos , y:bottom ,z:Zpos};
var scale:Number = fl / (fl + shadowPoints[i].z + zOffset);
shadowPoints[i].xPos = vpX + (shadowPoints[i].x + xOffset) * scale;
shadowPoints[i].yPos = vpY + shadowPoints[i].y * scale;
}
}
function renderTriangle(tri:Object,isShadow:Boolean):Void
{
if (isShadow)
{
var pointA:Object = shadowPoints[tri.a];
var pointB:Object = shadowPoints[tri.b];
var pointC:Object = shadowPoints[tri.c];
col = 0xCCCCCC
lineStyle(0,0,0)
beginFill(col, 100);
moveTo(pointA.xPos, pointA.yPos);
lineTo(pointB.xPos, pointB.yPos);
lineTo(pointC.xPos, pointC.yPos);
lineTo(pointA.xPos, pointA.yPos);
endFill();
}
var pointA:Object = points[tri.a];
var pointB:Object = points[tri.b];
var pointC:Object = points[tri.c];
var col:Number = getTriangleColor(tri);
if(isBackFace(pointA, pointB, pointC))
{
//return;
}
lineStyle(0,0,0)
beginFill(col, 100);
moveTo(pointA.xPos, pointA.yPos);
lineTo(pointB.xPos, pointB.yPos);
lineTo(pointC.xPos, pointC.yPos);
lineTo(pointA.xPos, pointA.yPos);
endFill();
}
function isBackFace(pointA:Object, pointB:Object, pointC:Object):Boolean
{
var cax:Number = pointC.xPos - pointA.xPos;
var cay:Number = pointC.yPos - pointA.yPos;
var bcx:Number = pointB.xPos - pointC.xPos;
var bcy:Number = pointB.yPos - pointC.yPos;
return cax * bcy > cay * bcx;
}
function triSort(triA:Object, triB:Object):Number
{
var zA:Number = Math.min(points[triA.a].z, points[triA.b].z);
zA = Math.min(zA, points[triA.c].z);
var zB:Number = Math.min(points[triB.a].z, points[triB.b].z);
zB = Math.min(zB, points[triB.c].z);
if(zA < zB)
{
return 1;
}
else
{
return -1;
}
}
function getTriangleColor(tri:Object):Number
{
var pointA:Object = points[tri.a];
var pointB:Object = points[tri.b];
var pointC:Object = points[tri.c];
var lightFactor:Number = getLightFactor(pointA, pointB, pointC);
var red:Number = tri.col >> 16;
var green:Number = tri.col >> 8 & 0xff;
var blue:Number = tri.col & 0xff;
red *= lightFactor;
green *= lightFactor;
blue *= lightFactor;
return red << 16 | green << 8 | blue;
}
function getLightFactor(ptA:Object, ptB:Object, ptC:Object):Number
{
var ab:Object = new Object();
ab.x = ptA.x - ptB.x;
ab.y = ptA.y - ptB.y;
ab.z = ptA.z - ptB.z;
var bc:Object = new Object();
bc.x = ptB.x - ptC.x;
bc.y = ptB.y - ptC.y;
bc.z = ptB.z - ptC.z;
var norm:Object = new Object();
norm.x = (ab.y * bc.z) - (ab.z * bc.y);
norm.y = -((ab.x * bc.z) - (ab.z * bc.x));
norm.z = (ab.x * bc.y) - (ab.y * bc.x);
var dotProd:Number = norm.x * light.x +
norm.y * light.y +
norm.z * light.z;
var normMag:Number = Math.sqrt(norm.x * norm.x +
norm.y * norm.y +
norm.z * norm.z);
var lightMag:Number = Math.sqrt(light.x * light.x +
light.y * light.y +
light.z * light.z);
return (Math.acos(dotProd / (normMag * lightMag)) / Math.PI) * light.brightness / 100;
}
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|