Forked from: malczak's octo2sphere diff:1 forked from: octo2sphere dotf forked:0favorite:0lines:157license : All rights reserved modified : 2009-11-13 15:40:27 Embed Tweet // forked from malczak's octo2sphere /* catmull-clark transformation */ package { import flash.display.*; import flash.geom.*; import flash.filters.*; import flash.events.*; import flash.utils.*; import flash.text.*; [SWF(width="400", height="400", backgroundColor="0xffffff", frameRate="8")] /** * @author : Mateusz Malczak (http://segfaultlabs.com) */ public class sphere extends MovieClip { private var m3d : Matrix3D; private var s : BitmapData; private var R :Number; private var t :Timer; private var tf : TextField; private var vs:Vector.<Number> = new Vector.<Number>(0,false); private var vsp:Vector.<Number> = new Vector.<Number>(0,false); private var fs:Vector.<int> = new Vector.<int>(0,false); private var uvt:Vector.<Number> = new Vector.<Number>(0,false); public function sphere():void { s = new BitmapData(320,320); var tmp0:BitmapData = new BitmapData(320,320); s.perlinNoise(320,320,8,Math.random(),true,true,BitmapDataChannel.BLUE,false); tmp0.perlinNoise(320,320,8,Math.random(),true,true,BitmapDataChannel.GREEN,false); s.draw( tmp0, null, null, BlendMode.ADD ); tmp0.perlinNoise(320,320,8,Math.random(),true,true,BitmapDataChannel.BLUE,false); s.draw( tmp0, null, null, BlendMode.ADD ); tmp0.perlinNoise(320,320,8,Math.random(),true,true,BitmapDataChannel.ALPHA,false); s.draw( tmp0, null, null, BlendMode.ADD ); tmp0.dispose(); R = 160; /* sphere radius */ var pi4:Number = Math.PI*0.25; var pi2:Number = 90 * Math.PI / 180; /* octohedra vertices */ vs.push( 0, -R, 0 ); vs.push( R * Math.sin(pi4),0, R* Math.cos(pi4) ); pi4 += pi2; vs.push( R * Math.sin(pi4),0, R* Math.cos(pi4) ); pi4 += pi2; vs.push( R * Math.sin(pi4),0, R* Math.cos(pi4) ); pi4 += pi2; vs.push( R * Math.sin(pi4),0, R* Math.cos(pi4) ); pi4 = Math.PI*0.25; /* one vertex extra to get proper bitmap textring */ vs.push( R * Math.sin(pi4),0, R* Math.cos(pi4) ); vs.push( 0, R, 0 ); /* faces */ fs.push( 0,1,2 ); fs.push( 0,2,3 ); fs.push( 0,3,4 ); fs.push( 0,4,5 ); fs.push( 0,1,5 ); fs.push( 6,2,1 ); fs.push( 6,3,2 ); fs.push( 6,4,3 ); fs.push( 6,5,4 ); fs.push( 6,1,5 ); /* texturing */ uvt.push( 0.5 ,0 , 0 ); uvt.push( 0 ,0.5, 0 ); uvt.push( 0.25,0.5, 0 ); uvt.push( 0.50,0.5, 0 ); uvt.push( 0.75,0.5, 0 ); uvt.push( 1 ,0.5, 0 ); uvt.push( 0.5 ,1 , 0 ); vsp.length = vs.length/3*2; m3d = new Matrix3D(); m3d.appendRotation(30,Vector3D.Y_AXIS ); m3d.appendRotation(30,Vector3D.X_AXIS ); m3d.appendTranslation( 200, 200, 300 ); var pp:PerspectiveProjection = transform.perspectiveProjection; pp.fieldOfView = 60; pp.focalLength = 200; pp.projectionCenter = new Point(200,200); transform.perspectiveProjection = pp; addEventListener( Event.ENTER_FRAME, ef ); t = new Timer(5000,5); t.addEventListener( TimerEvent.TIMER, subdivide ); t.start(); draw(); tf = new TextField(); tf.autoSize = "left"; tf.text = "octahedra transformed into sphere\nvertices : "+vs.length/3; addChild(tf); } /** * catmull-clark division, without duplicating edge division */ public function subdivide( evt:Event ):void { var cnt:int = fs.length; var i:int, j:int, k:int, n:int; var i3:int, j3:int, k3:int; var n1:int, n2:int, n3:int; var v:Vector3D = new Vector3D(); var done:Object = {}; n = vs.length/3; var e:String = ""; while ( cnt>0 ) { i = fs.shift(); j = fs.shift(); k = fs.shift(); i3 = i*3; j3 = j*3; k3 = k*3; e = Math.max(i,j)+""+Math.min(i,j); if ( done[e]==null ) { v.x = 0.5*(vs[i3 ] + vs[j3 ]); v.y = 0.5*(vs[i3+1] + vs[j3+1]); v.z = 0.5*(vs[i3+2] + vs[j3+2]); v.scaleBy(R/v.length); vs.push(v.x,v.y,v.z); uvt.push( (uvt[i3]+uvt[j3])/2, (uvt[i3+1]+uvt[j3+1])/2, 0 ); done[e] = n1 = n; n+=1; } else n1 = done[e]; e = Math.max(j,k)+""+Math.min(j,k); if ( done[e]==null ) { v.x = 0.5*(vs[j3] + vs[k3]); v.y = 0.5*(vs[j3+1] + vs[k3+1]); v.z = 0.5*(vs[j3+2]+vs[k3+2]); v.scaleBy(R/v.length); vs.push(v.x,v.y,v.z); uvt.push( (uvt[j3]+uvt[k3])/2, (uvt[j3+1]+uvt[k3+1])/2, 0 ); done[e] = n2 = n; n+=1 } else n2 = done[e]; e = Math.max(k,i)+""+Math.min(k,i); if ( done[e]==null ) { v.x = 0.5*(vs[k3] + vs[i3]); v.y = 0.5*(vs[k3+1] + vs[i3+1]); v.z = 0.5*(vs[k3+2]+vs[i3+2]); v.scaleBy(R/v.length); vs.push(v.x,v.y,v.z); uvt.push( (uvt[k3]+uvt[i3])/2, (uvt[k3+1]+uvt[i3+1])/2, 0 ); done[e] = n3 = n; n+=1; } else n3 = done[e]; fs.push( i, n1, n3 ); fs.push( n1, j, n2 ); fs.push( n3, n2, k ); fs.push( n3, n1, n2 ); cnt -= 3; }; done = null; vsp.length = vs.length/3*2; tf.text = tf.text + "\nvertices : "+n; } public function draw():void { graphics.clear(); Utils3D.projectVectors( m3d, vs, vsp, uvt ); graphics.lineStyle(1,0x000000,0.6,true,LineScaleMode.NONE); graphics.beginBitmapFill(s,null,false,true); graphics.drawTriangles( vsp, fs, uvt, "positive" ); }; public function ef( evt:Event ):void { m3d.prependRotation( 15, Vector3D.Y_AXIS ); m3d.prependRotation( 2, Vector3D.X_AXIS ); draw(); } } } Code Fullscreen Preview Fullscreen