Forked from: makc3d's why not Klein bottle diff:202 why not another Klein bottle makc3d forked:2favorite:7lines:166license : MIT License modified : 2012-10-23 16:11:42 Embed Tweet package { import alternativ7.engine3d.containers.ConflictContainer; import alternativ7.engine3d.core.Camera3D; import alternativ7.engine3d.core.Face; import alternativ7.engine3d.core.Object3DContainer; import alternativ7.engine3d.core.Sorting; import alternativ7.engine3d.core.View; import alternativ7.engine3d.materials.FillMaterial; import flash.display.Sprite; import flash.events.Event; import flash.geom.Matrix3D; import flash.geom.Vector3D; /** * Because Klein bottles are fun... * @author makc */ [SWF(backgroundColor="0")] public class AlternativaKleinBottle extends Sprite { public var camera:Camera3D; public var bottle:KleinBottleMesh; public function AlternativaKleinBottle () { stage.quality = "low"; camera = new Camera3D; camera.view = new View (465, 465); addChild (camera.view); camera.z = -30; camera.fov = 0.6 * Math.PI; Object3DContainer (new ConflictContainer).addChild (camera); var m1:FillMaterial = new FillMaterial (0xFFFFFF, 0.95); var m2:FillMaterial = new FillMaterial (0x7F7F7F, 0.95); bottle = new KleinBottleMesh (3); var f:Face; for each (f in bottle.facesEven) f.material = m1; for each (f in bottle.facesOdd) f.material = m2; bottle.sorting = Sorting.DYNAMIC_BSP; camera.parent.addChild (bottle); addEventListener (Event.ENTER_FRAME, loop); } public var t:Number = 0; public function loop (e:Event):void { t += 1e-3; if (t >= 1) t -= 1; var m:Matrix3D = interpolatePathMatrix (t, 5e-4); m.prependRotation (-30, Vector3D.X_AXIS); camera.matrix = m; camera.render (); } public function interpolatePathMatrix (t:Number, dt:Number):Matrix3D { var p:Vector3D = interpolateVector3D (bottle.path, t); var q:Vector3D = interpolateVector3D (bottle.path, t + dt); q.decrementBy (p); q.normalize (); var n:Vector3D = interpolateVector3D (bottle.pathNormals, t); var m:Vector3D = q.crossProduct (n); n = m.crossProduct (q); n.normalize (); var c:Vector3D = q.crossProduct (n); return new Matrix3D (Vector.<Number> ([ /* x */ c.x, c.y, c.z, 0, /* y */ -n.x, -n.y, -n.z, 0, /* z */ q.x, q.y, q.z, 0, /* t */ p.x, p.y, p.z, 1 ])); } public function interpolateVector3D (vs:Vector.<Vector3D>, t:Number, s:Number = 0.4):Vector3D { // cardinal spline // see http://wonderfl.net/c/vnCf/read var i2:int = int (t * vs.length * 0.999999); var i1:int = (i2 + vs.length - 1) % vs.length; var i3:int = (i2 + 1) % vs.length; var i4:int = (i2 + 2) % vs.length; var V1:Vector3D = vs [i1]; var V2:Vector3D = vs [i2]; var V3:Vector3D = vs [i3]; var V4:Vector3D = vs [i4]; t = t * vs.length - i2; return new Vector3D ( // x s * ( -t * t * t + 2 * t * t - t) * V1.x + s * ( -t * t * t + t * t) * V2.x + (2 * t * t * t - 3 * t * t + 1) * V2.x + s * (t * t * t - 2 * t * t + t) * V3.x + ( -2 * t * t * t + 3 * t * t) * V3.x + s * (t * t * t - t * t) * V4.x, // y s * ( -t * t * t + 2 * t * t - t) * V1.y + s * ( -t * t * t + t * t) * V2.y + (2 * t * t * t - 3 * t * t + 1) * V2.y + s * (t * t * t - 2 * t * t + t) * V3.y + ( -2 * t * t * t + 3 * t * t) * V3.y + s * (t * t * t - t * t) * V4.y, // z s * ( -t * t * t + 2 * t * t - t) * V1.z + s * ( -t * t * t + t * t) * V2.z + (2 * t * t * t - 3 * t * t + 1) * V2.z + s * (t * t * t - 2 * t * t + t) * V3.z + ( -2 * t * t * t + 3 * t * t) * V3.z + s * (t * t * t - t * t) * V4.z ); } } } import alternativ7.engine3d.core.Face; import alternativ7.engine3d.core.Vertex; import alternativ7.engine3d.objects.Mesh; import flash.geom.Vector3D; class KleinBottleMesh extends Mesh { public var facesEven:Vector.<Face> = new Vector.<Face>; public var facesOdd:Vector.<Face> = new Vector.<Face>; public var path:Vector.<Vector3D> = new Vector.<Vector3D>; public var pathNormals:Vector.<Vector3D> = new Vector.<Vector3D>; public function KleinBottleMesh (quality:uint = 1) { var vs:Array = []; var q:int = Math.max (1, 2 * quality); var i_max:int = Math.max (4, 8 * int (q / 2) + 1); var j_max:int = Math.max (3, 2 * q + 1); // this code is from http://wonderfl.net/c/6RzY/read // it could use some love too, but I don't feel like var pi:Number = Math.PI, pi2:Number = pi*2; var u:Number, v:Number, r:Number, vx:Number, vy:Number, vz:Number; for (var i:int = 0; i <= i_max; i++) { vs [i] = []; for (var j:int = 0; j <= j_max; j++) { u = pi2 * i / (i_max + 1); v = pi2 * j / (j_max + 1); r = 5*(1 - Math.cos(u)/2); if(u <= pi) { vx = (6*Math.cos(u)*(1 + Math.sin(u)) + r*Math.cos(u)*Math.cos(v)); vy = (16*Math.sin(u) + r*Math.sin(u)*Math.cos(v)); }else if(u > pi) { vx = (6*Math.cos(u)*(1 + Math.sin(u)) + r*Math.cos(v + Math.PI)); vy = (16*Math.sin(u)); } vz = r*Math.sin(v); u = i / i_max; v = j / j_max; vs [i][j] = addVertex (vx, vy, vz, u, v); } } // now make faces var fp:Array = []; for (i = 0; i <= i_max; i++) { var i1:int = (i + 1) % (i_max + 1); for (j = 0; j <= j_max; j++) { var j1:int = (j + 1) % (j_max + 1); if (i < i1) { var j0:int = j; var j2:int = j1; } else { j0 = (2 * j_max - j - (q - 1)) % (j_max + 1); j2 = (j0 + j_max) % (j_max + 1); } var fa:Vector.<Face> = ((i + j) % 2 == 0) ? facesEven : facesOdd; // can't just add quad face here because it wouldn't be flat fa.push (addTriFace (vs[i][j], vs[i][j1], vs[i1][j0])); fa.push (addTriFace (vs[i1][j0], vs[i][j1], vs[i1][j2])); // ironically, one-sided surface has to be double-sided mesh fa.push (addTriFace (vs[i1][j0], vs[i][j1], vs[i][j])); fa.push (addTriFace (vs[i1][j2], vs[i][j1], vs[i1][j0])); if (j == (j_max - q) >> 1) { // save some data to build the path through bottle fp.push (fa [fa.length - 1]); } } } calculateNormals (); // build path path.length = fp.length * 2; pathNormals.length = path.length; for (j = 0; j < 2; j++) { for (i = 0; i < fp.length; i++) { var f:Face = Face (fp[i]); var n:Vector3D = f.normal.clone (); if (j > 0) n.negate (); var k:int = j * fp.length + i; path [k] = new Vector3D ( (f.vertices [0].x + f.vertices [1].x + f.vertices [2].x) / 3, (f.vertices [0].y + f.vertices [1].y + f.vertices [2].y) / 3, (f.vertices [0].z + f.vertices [1].z + f.vertices [2].z) / 3 ); path [k].incrementBy (n); path [k].incrementBy (n); pathNormals [k] = n; } } k = 0; } } Code Fullscreen Preview Fullscreen Nyarineko 9re siouxcitizen.. fakestar0826.. tjoen matacat narutohyper : クラインの壺 Vector3D crossProduct incrementBy Math.cos negate length decrementBy Math.sin clone Vector3D.X_AXIS Math.max normalize Vector Math.PI addEventListener Event.ENTER_FRAME push addChild Event Array sort new page view favorite forked pv2247 Klein bottle trip in anaglyph makc3d forked:1 favorite:9lines:180 (diff:37) tag: 3D Alternativa3D7.6 alternativa anaglyph stereo3D pv412 forked from: why not another K.. kahin forked:2 favorite:0lines:167 (diff:3)