Forked from: narutohyper's Alternativa3D Tips 読み込んだ、3DSモデルの中身を操作する diff:693 Alternativa3D MetalMiku narutohyper forked:1favorite:11lines:449license : MIT License modified : 2010-10-19 11:14:02 Embed Tweet // forked from narutohyper's Alternativa3D Tips 読み込んだ、3DSモデルの中身を操作する // forked from clockmaker's [Alternativa3D] Negi Miku package { import alternativ5.engine3d.materials.FillMaterial; import alternativ5.engine3d.primitives.Plane; import alternativ5.engine3d.primitives.Cone; import alternativ5.engine3d.core.Object3D; import alternativ5.engine3d.core.Mesh; import alternativ5.engine3d.events.MouseEvent3D import alternativ5.engine3d.loaders.*; import alternativ5.types.Point3D; import alternativ5.types.Texture; import alternativ5.utils.* import flash.display.Loader; import flash.display.Sprite; import flash.display.BlendMode; import flash.display.BitmapData; import flash.display.Bitmap; import flash.display.StageQuality; import flash.display.GradientType; import flash.events.MouseEvent; import flash.events.Event; import flash.net.URLRequest; import flash.system.LoaderContext; import flash.system.Security; import flash.text.*; import flash.geom.Matrix; import flash.utils.*; [SWF(width = 465, height = 465, frameRate = 60,backgroundColor=0x000000)] /** */ public class SimpleDemo extends Sprite { public static const CROSSDOMAIN:String = "http://marubayashi.net/crossdomain.xml"; private var bmd:BitmapData; private var mcm:TextureEnvironmentMaterial public function SimpleDemo():void { var img:Loader=new Loader(); Security.loadPolicyFile(CROSSDOMAIN); img.load(new URLRequest('http://marubayashi.net/archive/sample/images/environment/e.jpg')); img.contentLoaderInfo.addEventListener(Event.COMPLETE, img1Complete); function img1Complete (e:Event):void { img.contentLoaderInfo.removeEventListener(Event.COMPLETE, img1Complete); bmd=new BitmapData(200,200,false,0x000000) bmd.draw(img.content) mcm=new TextureEnvironmentMaterial(null, new Texture(bmd),1,1.0,true,true) init() } } private function init():void { // テンプレートを作成します var template:BasicTemplate = new BasicTemplate(); addChild(template); template.camera.z = -500; // FPS display launch FPS.init(stage); var context:LoaderContext = new LoaderContext(); var loader:Loader3DS = new Loader3DS(); loader.addEventListener(Event.COMPLETE, loadCompleteHandler); loader.load("http://clockmaker.jp/labs/090807_alternativa3d/test.3ds", context); var lm:Object3D; var rarm:Mesh var negi:Mesh var near:Mesh var far:Mesh function loadCompleteHandler(e:Event):void { template.scene.root.addChild(loader.content); loader.content.scaleX = loader.content.scaleY = loader.content.scaleZ = 20; lm=loader.content //読み込んだ3ds(Object3D)の子Objectにはnameがわかれば個別にアクセスできるようになります //自分で作成したモデルなどでは、問題ありませんが、もし名前等がわからない場合は //以下のような方法で調べます //メソッド[Object3D.forEach()]ですべての子Object3Dにアクセスできます lm.forEach(test) function test():void { //traceで('R_arm'、'negi'、'miku_near'、'miku_far'という名前のMeshが確認できます) //ついでに、3dsモデルのゴミ掃除をします if(this is Mesh) { //サーフェースに属していないFacsを削除します。 MeshUtils.removeSingularFaces(Mesh(this)); //直線上に存在する、Faceの頂点になっていない点を削除します MeshUtils.removeUselessVertices(Mesh(this)); //使われていない、孤立した点を削除します MeshUtils.removeIsolatedVertices(Mesh(this)); //同じ座標で複数存在する点を、一つにまとめます MeshUtils.autoWeldVertices(Mesh(this), 0.01); //重なっている、面を統合します。 MeshUtils.autoWeldFaces(Mesh(this), 0.01, 0.001); this.cloneMaterialToAllSurfaces(mcm); } } //名前がわかれば、Object3D.getChildByNameでアクセスできます。 rarm=Mesh(lm.getChildByName('R_arm')); negi=Mesh(lm.getChildByName('negi')); near=Mesh(lm.getChildByName('miku_near')); far =Mesh(lm.getChildByName('miku_far')); var angle:Number=0 //lm.rotationX=MathUtils.toRadian(90); rarm.rotationX += 10 * Math.PI / 180; negi.rotationX += 10 * Math.PI / 180; //毎Frame毎のレンダリングを中止 template.stopRendering() stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); // ---------------------------------------------- // Mouse Interactive // ---------------------------------------------- var isOribiting:Boolean; var cameraPitch:Number = 200; var cameraYaw:Number = 180; var previousMouseX:Number; var previousMouseY:Number; rarm.rotationX = MathUtils.toRadian(0); negi.rotationX = MathUtils.toRadian(0); singleRender(null); function onMouseDown(event:MouseEvent=null):void { isOribiting = true; previousMouseX = event.stageX; previousMouseY = event.stageY; rarm.rotationX = MathUtils.toRadian(20); negi.rotationX = MathUtils.toRadian(20); rarm.rotationZ = MathUtils.toRadian(0); negi.rotationZ = MathUtils.toRadian(0); rarm.y=0.05; negi.y=0.05; rarm.z=0.2; negi.z=0.2; singleRender(null); } function onMouseUp(event:MouseEvent=null):void { isOribiting = false; stage.quality = StageQuality.HIGH; rarm.rotationX = MathUtils.toRadian(0); negi.rotationX = MathUtils.toRadian(0); rarm.rotationZ = MathUtils.toRadian(0); negi.rotationZ = MathUtils.toRadian(0); rarm.y=0; negi.y=0; rarm.z=0; negi.z=0; singleRender(null); } function onMouseMove(event:MouseEvent=null):void { var differenceX:Number = event.stageX - previousMouseX; var differenceY:Number = event.stageY - previousMouseY; if(isOribiting) { stage.quality = StageQuality.MEDIUM; cameraPitch += differenceY; cameraYaw += differenceX * 0.25; previousMouseX = event.stageX; previousMouseY = event.stageY; singleRender(null); } } function singleRender(e:Event):void { // Mouse Interactive template.camera.x = 500 * Math.sin(cameraYaw * Math.PI / 180); template.camera.y = 500 * Math.cos(cameraYaw * Math.PI / 180); template.camera.z = cameraPitch; template.cameraContoller.lookAt(new Point3D()); // Scene calculating template.singleRender() } } } } } import alternativ5.engine3d.alternativa3d; import alternativ5.engine3d.core.Camera3D; import alternativ5.engine3d.core.PolyPrimitive; import alternativ5.engine3d.display.Skin; import alternativ5.engine3d.materials.DrawPoint; import alternativ5.engine3d.materials.Material; import alternativ5.engine3d.materials.TextureMaterial; import alternativ5.engine3d.materials.TextureMaterialPrecision; import alternativ5.types.Matrix3D; import alternativ5.types.Point3D; import alternativ5.types.Texture; import alternativ5.types.alternativatypes; import alternativ5.utils.MathUtils; import flash.display.BlendMode; import flash.display.Graphics; import flash.display.Shape; import flash.geom.Matrix; use namespace alternativatypes; use namespace alternativa3d; class TextureEnvironmentMaterial extends TextureMaterial { private static const reflectionMatrix:Matrix = new Matrix(); private static var shapes:Array = new Array(); private var _reflection:Texture; private var _reflectionBlendMode:String; private var _reflectiveness:Number; private var gfx:Graphics; public function TextureEnvironmentMaterial(texture:Texture = null, reflection:Texture = null, reflectiveness:Number = 1.0, alpha:Number = 1.0, repeat:Boolean = false, smooth:Boolean = false, blendMode:String = BlendMode.NORMAL, precision:Number = TextureMaterialPrecision.MEDIUM, reflectionBlendMode:String = BlendMode.NORMAL) { super(texture, alpha, repeat, smooth, blendMode, -1, 0, precision); _reflection = reflection; _reflectiveness = reflectiveness; _reflectionBlendMode = reflectionBlendMode; } override alternativa3d function canDraw(primitive:PolyPrimitive):Boolean { return _reflection != null || _texture != null; } override alternativa3d function clear(skin:Skin):void { skin.gfx.clear(); var count:int = skin.numChildren; for (var i:int = 0; i < count; i++) { var shape:Shape = skin.removeChildAt(0) as Shape; shape.graphics.clear(); shapes.push(shape); } } /** * @private * @inheritDoc */ override alternativa3d function draw(camera:Camera3D, skin:Skin, length:uint, points:Array):void { if (_reflectiveness < 1) { super.draw(camera, skin, length, points); } if (_reflectiveness > 0) { var gfx:Graphics; if (_reflectiveness < 1) { var shape:Shape = shapes.pop(); if (shape == null) { shape = new Shape(); } skin.addChild(shape); gfx = shape.graphics; shape.alpha = _reflectiveness; shape.blendMode = _reflectionBlendMode; } else { skin.alpha = _reflectiveness; skin.blendMode = _blendMode; gfx = skin.gfx; } var cameraMatrix:Matrix3D = camera.cameraMatrix; var normal:Point3D = skin.primitive.face.globalNormal; var normalInCamX:Number = normal.x*cameraMatrix.a + normal.y*cameraMatrix.b + normal.z*cameraMatrix.c; var normalInCamY:Number = normal.x*cameraMatrix.e + normal.y*cameraMatrix.f + normal.z*cameraMatrix.g; var normalInCamZ:Number = normal.x*cameraMatrix.i + normal.y*cameraMatrix.j + normal.z*cameraMatrix.k; var focalLength:Number = camera.focalLength; var apoint:DrawPoint = points[0]; var bpoint:DrawPoint = points[1]; var cpoint:DrawPoint = points[2]; var ax:Number = apoint.x*focalLength/apoint.z; var ay:Number = apoint.y*focalLength/apoint.z; var bx:Number = bpoint.x*focalLength/bpoint.z; var by:Number = bpoint.y*focalLength/bpoint.z; var cx:Number; var cy:Number; var vx:Number; var vy:Number; var vz:Number; var rx:Number; var ry:Number; var rz:Number; var nx:Number; var ny:Number; var nz:Number; var dot:Number; var len:Number; var aN:Boolean; var bN:Boolean; var cN:Boolean; vx = apoint.x; vy = apoint.y; vz = apoint.z; dot = vx*normalInCamX + vy*normalInCamY + vz*normalInCamZ; rx = vx - 2*dot*normalInCamX; ry = vy - 2*dot*normalInCamY; rz = vz - 2*dot*normalInCamZ; len = Math.sqrt(rx*rx + ry*ry + rz*rz); nx = rx*0.5; ny = ry*0.5; nz = (rz - len)*0.5; len = Math.sqrt(nx*nx + ny*ny + nz*nz); nx /= len; ny /= len; aN = (nz > 0); var au:Number = 0.5 + nx*0.5; var av:Number = 0.5 - ny*0.5; vx = bpoint.x; vy = bpoint.y; vz = bpoint.z; dot = vx*normalInCamX + vy*normalInCamY + vz*normalInCamZ; rx = vx - 2*dot*normalInCamX; ry = vy - 2*dot*normalInCamY; rz = vz - 2*dot*normalInCamZ; len = Math.sqrt(rx*rx + ry*ry + rz*rz); nx = rx*0.5; ny = ry*0.5; nz = (rz - len)*0.5; len = Math.sqrt(nx*nx + ny*ny + nz*nz); nx /= len; ny /= len; bN = (nz > 0); var bu:Number = 0.5 + nx*0.5; var bv:Number = 0.5 - ny*0.5; for (var i:int = 1; i < length; i++) { cpoint = points[i]; cx = cpoint.x*focalLength/cpoint.z; cy = cpoint.y*focalLength/cpoint.z; vx = cpoint.x; vy = cpoint.y; vz = cpoint.z; dot = vx*normalInCamX + vy*normalInCamY + vz*normalInCamZ; rx = vx - 2*dot*normalInCamX; ry = vy - 2*dot*normalInCamY; rz = vz - 2*dot*normalInCamZ; len = Math.sqrt(rx*rx + ry*ry + rz*rz); nx = rx*0.5; ny = ry*0.5; nz = (rz - len)*0.5; len = Math.sqrt(nx*nx + ny*ny + nz*nz); nx /= len; ny /= len; cN = (nz > 0); var cu:Number = 0.5 + nx*0.5; var cv:Number = 0.5 - ny*0.5; var abx:Number = bx - ax; var aby:Number = by - ay; var acx:Number = cx - ax; var acy:Number = cy - ay; var abu:Number = bu - au; var abv:Number = bv - av; var acu:Number = cu - au; var acv:Number = cv - av; var det:Number = abu*acv - abv*acu; var w:Number = _reflection._width; var h:Number = _reflection._height; reflectionMatrix.a = (acv*abx - abv*acx)/det; reflectionMatrix.b = (acv*aby - abv*acy)/det; reflectionMatrix.c = (acu*abx - abu*acx)/det; reflectionMatrix.d = (acu*aby - abu*acy)/det; reflectionMatrix.tx = (av - 1)*reflectionMatrix.c - au*reflectionMatrix.a + ax; reflectionMatrix.ty = (av - 1)*reflectionMatrix.d - au*reflectionMatrix.b + ay; reflectionMatrix.a /= w; reflectionMatrix.b /= w; reflectionMatrix.c /= h; reflectionMatrix.d /= h; gfx.beginBitmapFill(_reflection._bitmapData, reflectionMatrix, true, true); gfx.moveTo(ax, ay); gfx.lineTo(bx, by); gfx.lineTo(cx, cy); bx = cx; by = cy; bu = cu; bv = cv; } } } private function lookAtMatrix(dx:Number, dy:Number, dz:Number):Matrix3D { return Matrix3D.rotationMatrix(Math.atan2(dz, Math.sqrt(dx * dx + dy * dy) - MathUtils.DEG90), 0, -Math.atan2(dx, dy)); } /** * @private */ private function drawTriangle(ax:Number, ay:Number, au:Number, av:Number, bx:Number, by:Number, bu:Number, bv:Number, cx:Number, cy:Number, cu:Number, cv:Number):void { var abx:Number = bx - ax; var aby:Number = by - ay; var acx:Number = cx - ax; var acy:Number = cy - ay; var abu:Number = bu - au; var abv:Number = bv - av; var acu:Number = cu - au; var acv:Number = cv - av; var det:Number = abu*acv - abv*acu; var w:Number = _reflection._width; var h:Number = _reflection._height; reflectionMatrix.a = (acv*abx - abv*acx)/det; reflectionMatrix.b = (acv*aby - abv*acy)/det; reflectionMatrix.c = (acu*abx - abu*acx)/det; reflectionMatrix.d = (acu*aby - abu*acy)/det; reflectionMatrix.tx = (av - 1)*reflectionMatrix.c - au*reflectionMatrix.a + ax; reflectionMatrix.ty = (av - 1)*reflectionMatrix.d - au*reflectionMatrix.b + ay; reflectionMatrix.a /= w; reflectionMatrix.b /= w; reflectionMatrix.c /= h; reflectionMatrix.d /= h; gfx.beginBitmapFill(_reflection._bitmapData, reflectionMatrix, true, true); gfx.moveTo(ax, ay); gfx.lineTo(bx, by); gfx.lineTo(cx, cy); } /** * @inheritDoc */ override public function clone():Material { var res:TextureEnvironmentMaterial = new TextureEnvironmentMaterial(_texture, _reflection, _reflectiveness, _alpha, _repeat, _smooth, _blendMode, _precision); return res; } } import alternativ5.engine3d.controllers.CameraController; import alternativ5.engine3d.core.Camera3D; import alternativ5.engine3d.core.Object3D; import alternativ5.engine3d.core.Scene3D; import alternativ5.engine3d.display.View; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.events.Event; /** * BasicTemplate for Alternativa3D * Alternativa3Dを扱いやすくするためのテンプレートです * @author Yasu */ class BasicTemplate extends Sprite{ /** * シーンインスタンスです。 */ public var scene:Scene3D; /** * ビューインスタンスです。 */ public var view:View; /** * カメラインスタンスです。 */ public var camera:Camera3D; /** * カメラコントローラーです。 */ public var cameraContoller:CameraController; private var _viewWidth:int; private var _viewHeight:int; private var _scaleToStage:Boolean; /** * 新しい BasicTemplate インスタンスを作成します。 * @param viewWidth * @param viewHeight * @param scaleToStage */ public function BasicTemplate(viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true) { _viewWidth = viewWidth; _viewHeight = viewHeight; _scaleToStage = scaleToStage; // Creating scene scene = new Scene3D(); scene.splitAnalysis = false; // not analysis for performance scene.root = new Object3D(); // Adding camera camera = new Camera3D(); camera.z = -1000; scene.root.addChild(camera); // camera contoller cameraContoller = new CameraController(this); cameraContoller.camera = camera; // set view view = new View(); view.camera = camera; addChild(view); // stage if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } /** * 初期化されたときに実行されるイベントです。 * 初期化時に実行したい処理をオーバーライドして記述します。 */ protected function atInit():void {} /** * 初期化されたときに実行されるイベントです。 * 初期化時に実行したい処理を記述します。 */ private var _onInit:Function = function():void { }; public function get onInit():Function { return _onInit; } public function set onInit(value:Function):void { _onInit = value; } /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング前に実行したい処理をオーバーライドして記述します。 */ protected function atPreRender():void {} /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング前に実行したい処理を記述します。 */ private var _onPreRender:Function = function():void{}; public function get onPreRender():Function { return _onPreRender; } public function set onPreRender(value:Function):void { _onPreRender = value; } /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング後に実行したい処理をオーバーライドして記述します。 */ protected function atPostRender():void { } /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング後に実行したい処理を記述します。 */ protected var _onPostRender:Function = function():void{}; public function get onPostRender():Function { return _onPostRender; } public function set onPostRender(value:Function):void { _onPostRender = value; } /** * レンダリングを開始します。 */ public function startRendering():void { addEventListener(Event.ENTER_FRAME, onRenderTick); } /** * レンダリングを停止します。 */ public function stopRendering():void { removeEventListener(Event.ENTER_FRAME, onRenderTick); } /** * シングルレンダリング(レンダリングを一回だけ)を実行します。 */ public function singleRender():void { onRenderTick(); } /** * @private */ private function init(e:Event = null):void { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.quality = StageQuality.HIGH; // resize stage.addEventListener(Event.RESIZE, onResize); onResize(null); // render startRendering(); atInit(); _onInit(); } /** * @private */ private function onRenderTick(e:Event = null):void { atPostRender(); _onPostRender(); scene.calculate(); atPreRender(); _onPreRender(); } /** * @private */ private function onResize(event:Event = null):void { if (_scaleToStage) { view.width = stage.stageWidth; view.height = stage.stageHeight; }else { view.width = _viewWidth; view.height = _viewHeight; } } } Code Fullscreen Preview Fullscreen yurinohana vinylsheet siouxcitizen.. OKASUKE 178ep3 Nyarineko PROT830 Murai smallwind191.. : Alternativa3D h1ro : Alternativa3D clockmaker : Alternativa3D環境マップなねぎみく Alternativa3D rotationX Math.sqrt AntiAliasType.NORMAL rotationZ namespace Boolean test ty tx scaleZ root alpha Math.atan2 addEventListener height width Event.RESIZE stage scaleY clone sort new page view favorite forked pv0 forked from: Alternativa3D Met.. wodemengbin forked:0 favorite:0lines:449 (diff:1)