Alternativa3D MetalMiku
/**
* Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/lDml
*/
// 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;
}
}
}