This one is spawn of MediumAttributes demo. It demonstrates application of MediumAttributes class to Sprite3D objects, as well as usage of new things in coming 3.0.3, RotationUtil and StarField classes.
Here is the code for Flash CS3 document class. Create new FLA file, set it to 550×300, 24 fps, add two movie clips set to export for ActionScript as TI_1 and TI_2. Set the document class to Ties, and you're done.
package { import fl.motion.Color; import flash.display.Sprite; import flash.events.Event; import sandy.core.* import sandy.core.data.* import sandy.core.scenegraph.* import sandy.materials.* import sandy.materials.attributes.* import sandy.util.RotationUtil import caurina.transitions.Tweener public class Ties extends Sprite { private var ties:Array = []; private var world:World3D = World3D.getInstance (); private var cam_tg:TransformGroup = new TransformGroup (); private var rHlp:RotationUtil = new RotationUtil (); private var medium:MediumAttributes; public function Ties () { world.container = this; world.camera = new Camera3D (550, 300); // create a single attributes instance for all objects medium = new MediumAttributes (0xFF000000, new Vector (0, 0, 300), new Vector (0, 0, 500)); var mat:Material = new Material (new MaterialAttributes (medium)); var scene:Group = new Group ("root"); for (var i:int = 0; i < 100; i++) { ties [i] = new Sprite3D ("tie" + i, (Math.random() > 0.5) ? new TI_1 : new TI_2, 0.4); ties [i].autoCenter = false; ties [i].fixedAngle = true; ties [i].material = mat; ties [i].x = 10 * (i - 50); ties [i].y = 200 * (Math.random () - Math.random ()); ties [i].z = 1000 * (Math.random () - Math.random ()); scene.addChild (ties [i]); } scene.addChild (generateStarSphere ()); scene.addChild (cam_tg); cam_tg.addChild (world.camera); rHlp.obj = cam_tg; world.root = scene; addEventListener (Event.ENTER_FRAME, onEnterFrame); } private function generateStarSphere ():StarField { var sf:StarField = new StarField ("background"); // generate ~6.5K stars equally distributed on sphere var R:Number = 5e2; for (var i:int = -50; i < 50; i++) { var lat:Number = (Math.PI / 2) * i / 50; // circle at lat has lesser length than equator, // so we will put less stars there for (var j:int = 0; j < 100 * Math.cos (lat); j++) { var d:Number = (2 * Math.PI) / (100 * Math.cos (lat) + 1); var lon:Number = d * j; var d_lat:Number = d * (Math.random() - Math.random()); var d_lon:Number = d * (Math.random() - Math.random()); // add a star at lon + d_lon, lat + d_lat sf.stars.push (new Vertex ( R * Math.cos(lon + d_lon) * Math.cos(lat + d_lat), R * Math.sin(lon + d_lon) * Math.cos(lat + d_lat), R * Math.sin(lat + d_lat)) ); sf.starColors.push (0xFF000000 + Color.interpolateColor(0x8080FF, 0xFFFFFF, Math.random()) ); } } return sf; } private function onEnterFrame (event:Event):void { var a:Number = Math.PI * (mouseX - (550/2)) / 200; var x0:Number = 400 * Math.sin (a); var y0:Number = 300 - 2 * mouseY; var z0:Number = 400 * Math.cos (a); rHlp.reset (); rHlp.enableRoll = true; rHlp.out0 = cam_tg.out; rHlp.roll0 = 0; rHlp.out1 = new Vector (x0, y0, z0); rHlp.roll1 = 0; Tweener.addTween (rHlp, {t:1, time:1} ); for (var i:int = 0; i < ties.length; i++) { ties [i].z -= 10; if (ties [i].z < -500) ties [i].z = 500; } world.render (); } } }