Scripting 3D in Flash
      by senocular

Solid Pyramids
This example has two fully solid pyramids. One uses the visibility function for backface culling and the other uses separate movieclips for faces and uses swapDepths for each of those clips to properly arrange them. Those depths are based on an average z of the 3 points making up each face.

[ two drawn solid pyramids ]

Steps to Create Animation

  1. This example starts off similar to the previous only here, there are 2 scenes, one for each of the pyramids which are to operate independent of each other. The focalLength will be used in both, so that can remain a single variable.

  1. Following that, the visibility function can be added. This will be used in the first pyramid for backface culling taking three of the points making up a face in the pyramid and determining visibility of that face based on slope and position of each point in relation to each other. The second pyramid will not use this function in favor of having each face as a movieclip and using swapDepths to properly overlap each face.

  1. Next are the make point functions. This example will actually drop the make2DPoint function all together. One of the reasons is that for the second pyramid using swapDepths to arrange faces, a depth or z value will be needed for each converted 2D point to determine the depth of the face. Secondly, a 2D point is just a 3D point minus one property, z, so why not just drop the 2D point if the 3D point can be used instead (which it needs to be to get that z value to figure for depth). The make3DPoint function itself has not changed.

  1. Now for the Transform3DPointsTo2DPoints work horse. The only change here is the using of the make3DPoint for the 2D points in the transformed array. Technically the point will still be 2D, at least in its x and y values, but the z value will be the 3D point which is retained for determining depths etc.

  1. And now the pyramid can be defined. A pyramid is fairly easy - only three points.

  1. Because there are two scenes, 2 separate onEnterFrame functions will be defined for both, each using a separate technique of creating a filled pyramid. The first will be the one with backface culling using the isVisibleBetween function defined earlier. The isVisibleBetween function is used to determine, given 3 points, whether the face made by those points is visible or not. If its not, then you shouldn't bother drawing the face. So, each time a face is to be drawn between any three points (which happens four times for each face every frame), isVisibleBetween needs to be called for those points in an if check to make sure the drawing should proceed. If not, on to the next face. An added mouseIsDown variable is used to disable the beginFill function if the mouse is being pressed (Key.isDown(1) checks for the left mouse button being pressed if you weren't already aware of that). Note that everything is being drawn directly in the current scene movieclip.

  1. This second pyramid uses separate movieclips to draw its faces and each face is then swapped to an appropriate depth to keep overlapping appropriate and the pyramid appear solid. Each clip has its own specific face drawn within it every frame (whether its technically visible or not) and an average values of the z values for each point is in that face is used to swap each clip to the right depth keeping those clips that need to be on top, on top. When the mouse is pressed, for this pyramid, you can see the lines which were previously invisible or hidden by movieclip(s) on top whereas in the other pyramid they are not seen since they aren't even drawn. Of course, before implementing the function, the clips will need to be created for each face.

 SUGGESTION: Tips for Speed Optimization
Flash isn't fast. Remember that. Flash has a lot to put up with in terms of showing things on the screen as well as calculating everything it needs to at the request of your Actionscript. Because the Flash player is meant to be a light and lean plugin, there can only be so much done to enhance its speed. With that in mind, you will need to keep your actionscript as proficient and efficient as you can when dealing with a lot of operations that need to be calculated every frame - as is the case with 3D in Flash. Here are some tips you can apply to your code to help speed things up. Remember, every little bit counts:
  • Shorter variable names run faster (be careful not to sacrifice too much clarity of your code for this slight speed boost). myLongVariableName would perform slow in comparison to myV. You can assign a long variable to a shorter variable name if its going to be accessed repeatedly.
     
  • Bracket or 'associative array' syntax for referencing properties in an object or array can be much slower than normal dot syntax property referencing. For example, myObject["property"] is much slower than myObject.property. Because arrays use this syntax, inherently accessing array values is quite slow in comparison to normal object properties. If you can use an object instead of an array, do so. You can assign an bracket-accessed variable to a single short variable name if its going to be accessed repeatedly.
     
  • Local variables in function calls created with the var keyword are faster than other variables. Be sure not to reinitialize var variables within a loop block, however, as that would not be as efficient. Instead, declare any local variables used in loops outside the loop first.
     
  • Function calls on the whole can take time to process. The fewer function calls you make the less overhead you have in processing your script.
     
  • Along those same lines, don't process things more than once if you can just reuse the result of the first calculation. An example being the Math.sin() and Math.cos() calls. They only needed to be called a total of 3 times each for each frame of animation in a 3D environment. There's no need to call them repeatedly with the same values if they don't need to be. This not only applies to function calls but any other operation even if as simple as an addition of two numbers. Save that result in a variable and reuse it again later instead of re-calculating.
     
  • For..in loops can be faster than normal for loops. You may have to, however, when using a for..in loop, use checks to make sure you are looping through the correct properties which cause a script to run slower than if it was performed with a normal for loop. Also, for..in loops are not faster when used with very large arrays.
     
  • Generally subtraction is slightly faster than addition. Because of this, a way to speed up addition would be to subtract the negative of what you're adding. In other words, x = y+1; becomes x = y - (-1);
     
  • Pre-increment can also be slightly faster than post-increment. --x; over x--; Be wary of their uses in loops, however, as each will be treated differently.
     
  • One of the biggest boosts in speed, sadly, is through using deprecated functions such as random over Math.random and things like tellTarget instead of with. tellTarget can be as much as 25 times faster than with, though since these methods are technically no longer supported, you'll have to be cautious how much you use them. It might not be long where they will become obsolete and ineffective.

Advantages in Separated Faces
Using the separate movieclips for each face opens up some possibilities in terms of interaction with those faces. As movieclips, each face is completely separate from the other faces in the shape. Being that they are all their own individual clips, you can assign clip specific actions to certain and single faces. For example, a single face can act as a button. A 3D object with interactive button-faces? Exciting, isn't it?

 




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.