III. 3D Engines are Fun!

I believe this engine started at ultrashock, doing x/y rotation. There are a lot of different ways to rotate points, but this one is common because x/y corresponds to the mouses x/y position on the screen. The math behind it deserves it’s own tutorial :D

I like to simulate a camera change, not a point change, when rotating the mass in order to keep the original points. So we need to start with a mock-camera that’ll rotate everything:

// start with 10 degree angle rotation, and then make it redraw the shape when the mouse moves
// change the 5 to prefrence. Stage.width/2 means middle of the screen. redraw is our render function

mass.ayaxis = 10; mass.axaxis = 10;
mass.onMouseMove = function()
{
        this.axaxis+= (_root._xmouse - Stage.width/2)/5;
        this.ayaxis+= (_root._ymouse - Stage.height/2)/5;
        redraw(mass, axaxis, ayaxis);
}

The next step is to make it actually show up. There might be a few objects with their own rotation guidelines and rotation triggers, so lets attach all drawings to our mass object just in case. So:

function redraw(mc, xAngle, yAngle)
{
        // figures out the new coordinates
        rotate3D(mc, xAngle, yAngle);
       
        // clear the previously rendered shape
        mc.clear();
       
        //for each shape in our mass
        for (x = 0; x < mc.shapes.length; x++)
        {
                // red fill with alpha opacity of 20
                mc.beginFill(0xff0000, 20);
                // black 1pt outline with alpha 20
                mc.lineStyle(1, 0x000000, 20);
               
                // start at our first point
                mc.moveTo(mc.pts[mc.shapes[x][0]].sx, mc.pts[mc.shapes[x][0]].sy);
               
                for (var k = 1; k < mc.shapes[x].length; k++)
                {
                        // and draw to our last point
                        mc.lineTo(mc.pts[mc.shapes[x][k]].sx, mc.pts[mc.shapes[x][k]].sy);
                }
               
                // connect the last dot to the original and end the fill
                mc.lineTo(mc.pts[mc.shapes[x][0]].sx, mc.pts[mc.shapes[x][0]].sy);
                mc.endFill();
        }
}

Rotate world function

We still need to tell flash how to rotate the points given an x and y angle. So:

function rotate3D(mcArray, xa, ya)
{
        // perspective scale, lower to make interesting
        camdepth = 300;
        c = mcArray;
        rad = Math.PI/180;
        cosYangle = Math.cos(ya*rad);
        sinYangle = Math.sin(ya*rad);
        cosXangle = Math.cos(xa*rad);
        sinXangle = Math.sin(xa*rad);
       
        // figure out the rotated coordinates and rendering position
        p = mcArray.pts;
        for (i = 0; i < mcArray.pts.length; i++)
        {
                tempz = (p[i].z*cosYangle)-(p[i].x*sinYangle);
                tmpx = (p[i].z*sinYangle)+(p[i].x*cosYangle);
                tmpz = (p[i].y*sinXangle)+(tempz*cosXangle);
                tmpy = (p[i].y*cosXangle)-(tempz*sinXangle);
               
                // the actual screen coords
                zratio = camdepth/(tmpz +camdepth);
                p[i].sx = (Stage.width/2)+ tmpx *zratio;
                p[i].sy = (Stage.height/2) - tmpy *zratio;
        }
}

That's it! Move the code segments into your first frame (maybe organize it a bit - functions in one frame, shape/point definitions in another)

Thoughts etc

  • Curves. Add another property set: .cx, .cy, .cz (curve point in space) as well as .scx, .scy. You will need to add the curve manip to rotate as well as render
  • curveTo with above method wouldn't work, check were-here on what type of curve it is
  • styles - lineAlpha (negative means no line), lineThickness, lineColor, fillAlpha (negative means no fill), fillColor
  • shading - You can darken the side pieces, or decrease their alpha, to provie more emphasis on the real shape
  • It's easy to mod. There are a lot of prototypes out there as well. It's light weight, but if you want to render multiple objects, make sure the render routine is called for several objects at the same time to help speed.