/**
* Copyright Kay ( http://wonderfl.net/user/Kay )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/5bk4
*/
// forked from Kay's Rotation Dice with flat shading, Bad Example
// forked from Kay's Rotation Dice
// forked from Kay's Running Man
// forked from Kay's Rotation Cubes #2-2
// forked from Kay's Rotation Cubes #2
// forked from Kay's Rotation Cubes
/*
* addChildやrotationXなど2Dインスタンスで使い慣れたメソッドを用いて
* 3Dオブジェクトやカメラをコントロールする3Dエンジン
* マテリアルにシェーディング
* ・3Dオブジェクトに法線情報を登録しておく
* ・面ごとにBitmapDataを用意せず、3Dオブジェクトに対して1枚のBitmapDataとし
* 部分的にフラットシェーディングすることにより、BitmapDataの数を減らす
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import net.hires.debug.Stats;
[ SWF (width = '465', height = '465', backgroundColor = '0xcc6666', frameRate = '60') ]
public class Main extends Sprite {
private var scene:Scene3D;
private var canvas:Sprite;
private var objects:Array = new Array();
public function Main():void {
addChild( new Stats() );
canvas = new Sprite();
canvas.x=stage.stageWidth/2;
canvas.y=stage.stageHeight/2;
addChild(canvas);
scene = new Scene3D(canvas);
var count:uint = 0;
for (var h:uint = 0; h < 3; h++) {
for (var v:uint = 0; v < 3; v++) {
for (var d:uint = 0; d < 3; d++) {
var joint:Joint3D = new Joint3D();
joint.x = 150*h-150;
joint.y = 150*v-150;
joint.z = 150*d-150;
scene.addChild(joint);
var cube:Cube3D = new Cube3D(60,60,60);
cube.rotationX = Math.random()*360;
cube.rotationY = Math.random()*360;
cube.rotationZ = Math.random()*360;
if (count%2 == 0) {
cube.textureURL = 'http://assets.wonderfl.net/images/related_images/3/3b/3b09/3b09a86482a443328c0ecdaeb7da224206c18c54';
} else {
cube.textureURL = 'http://assets.wonderfl.net/images/related_images/b/bc/bc42/bc42848ee2f3341eb50db22a9dea6bc88c5f3b72m';
}
count++;
joint.addChild(cube);
objects.push(cube);
}
}
}
scene.camera.fieldOfView = 90;
addEventListener(Event.ENTER_FRAME,xRotation);
}
private function xRotation(e:Event):void {
for each (var object:Object in objects) {
object.rotationX+=3;
object.rotationY+=2;
}
scene.camera.rotationX = -canvas.mouseY/5;
scene.camera.rotationY = canvas.mouseX/5;
scene.render();
}
}
}
import flash.display.Sprite;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import flash.geom.Utils3D;
import flash.geom.PerspectiveProjection;
import frocessing.color.ColorHSL;
import flash.filters.ColorMatrixFilter;
class Scene3D extends Sprite {
public var camera:Camera3D;
public var position:Vector3D;
public var canvas:Sprite;
public var objects:Array;
public var matrix3D:Matrix3D;
public function Scene3D(sprite:Sprite):void {
camera=new Camera3D();
canvas=sprite;
matrix3D = new Matrix3D();
}
public function render():void {
objects = new Array();
getAllChildren(this);
canvas.graphics.clear();
matrix3D = new Matrix3D();
matrix3D.appendRotation(camera.rotationX, Vector3D.X_AXIS);
matrix3D.appendRotation(camera.rotationY, Vector3D.Y_AXIS);
matrix3D.appendRotation(camera.rotationZ, Vector3D.Z_AXIS);
var cameraAngle:Vector3D = new Vector3D(camera.x,camera.y,camera.z+camera.proj.focalLength);
cameraAngle = matrix3D.transformVector(cameraAngle);
matrix3D.appendTranslation(cameraAngle.x, cameraAngle.y, cameraAngle.z);
var viewPoint:Vector3D = new Vector3D(cameraAngle.x, cameraAngle.y, -cameraAngle.z);
var lite3D:Vector3D = new Vector3D(-20,50,50);
lite3D.normalize();
var dispParts:Array = new Array();
for each (var object:Object in objects) {
object.matrix3D = new Matrix3D();
object.matrix3D.appendRotation(object.rotationX,Vector3D.X_AXIS);
object.matrix3D.appendRotation(object.rotationY,Vector3D.Y_AXIS);
object.matrix3D.appendRotation(object.rotationZ,Vector3D.Z_AXIS);
object.matrix3D.prependTranslation(object.x,object.y,object.z);
object.matrix3D.append(object.parent.matrix3D);
if (object.verts.length) {
var realVerts3D:Vector.<Number> = new Vector.<Number>();
object.matrix3D.transformVectors(object.verts, realVerts3D);
object.uvtDatas = new Vector.<Number>();
var numUvDatas:int = object.uvDatas.length/2;
for (var u:int = 0; u < numUvDatas; u++) {
object.uvtDatas.push(object.uvDatas[u*2], object.uvDatas[u*2+1], 0);
}
object.projVerts2D = new Vector.<Number>();
Utils3D.projectVectors(camera.matrix3D, realVerts3D, object.projVerts2D, object.uvtDatas);
if (object.texture != null) {
object.shaded = object.texture.clone();
}
var numParts:int = object.parts.length;
for (var i:uint = 0; i < numParts; i++) {
var nX:Number = 0;
var nY:Number = 0;
var nZ:Number = 0;
var numIndex:uint = object.parts[i].indices.length;
for (var j:uint = 0; j < numIndex; j++) {
nX += realVerts3D[ object.parts[i].indices[j]*3 + 0 ];
nY += realVerts3D[ object.parts[i].indices[j]*3 + 1 ];
nZ += realVerts3D[ object.parts[i].indices[j]*3 + 2 ];
}
object.parts[i].x = nX/numIndex;
object.parts[i].y = nY/numIndex;
object.parts[i].z = nZ/numIndex;
var vCenter:Vector3D = new Vector3D(object.parts[i].x,object.parts[i].y,object.parts[i].z);
object.parts[i].distance = Vector3D.distance(viewPoint, vCenter);
var normal:Vector3D = object.matrix3D.transformVector(object.parts[i].normal);
normal = normal.subtract(vCenter);
normal.normalize();
var vView:Vector3D = vCenter.subtract(new Vector3D(0,0,-camera.focalLength));
vView.normalize();
var dotProduct:Number = vView.dotProduct(normal);
if (dotProduct > 0) {
object.parts[i].shadowRatio = lite3D.dotProduct(normal);
if (object.texture != null) {
var ratio:Number = object.parts[i].shadowRatio/2;
var shadeMatrix:Array = new Array(1,0,0,ratio,0,
0,1,0,ratio,0,
0,0,1,ratio,0,
0,0,0,1,0);
var raX:Number = object.uvDatas[object.parts[i].indices[0]*2] * object.shaded.width;
var raY:Number = object.uvDatas[object.parts[i].indices[0]*2+1] * object.shaded.height;
var raWidth:Number = (object.uvDatas[object.parts[i].indices[1]*2 ]-object.uvDatas[object.parts[i].indices[0]*2 ]) * object.shaded.width;
var raHeight:Number = (object.uvDatas[object.parts[i].indices[2]*2+1]-object.uvDatas[object.parts[i].indices[0]*2+1]) * object.shaded.height;
var rectangle:Rectangle = new Rectangle(raX,raY,raWidth,raHeight);
var colorFilter:ColorMatrixFilter = new ColorMatrixFilter(shadeMatrix);
object.shaded.applyFilter(object.shaded, rectangle, new Point(raX,raY), colorFilter);
}
dispParts.push(object.parts[i]);
}
}
}
}
dispParts.sortOn(["z","distance"], [Array.NUMERIC|Array.DESCENDING,Array.NUMERIC|Array.DESCENDING]);
var numDispParts:uint = dispParts.length;
for (i = 0; i < numDispParts; i++) {
if (dispParts[i].object.texture != null) {
canvas.graphics.beginBitmapFill(dispParts[i].object.shaded);
canvas.graphics.drawTriangles(dispParts[i].object.projVerts2D, dispParts[i].indices, dispParts[i].object.uvtDatas);
} else {
var hsl:ColorHSL = dispParts[i].object.colorHSL.clone();
var l:Number = hsl.l;
hsl.l = l + dispParts[i].shadowRatio/10;
var color:int = hsl.value;
canvas.graphics.beginFill(color);
canvas.graphics.drawTriangles(dispParts[i].object.projVerts2D, dispParts[i].indices);
}
canvas.graphics.endFill();
}
}
public function getAllChildren(container:Object):void {
var numChild:uint = container.numChildren;
for (var i:uint = 0; i < numChild; i++) {
var child:Object = container.getChildAt(i);
objects.push(child);
if (child.numChildren > 0) {
getAllChildren(child);
}
}
}
public function getNormal(verts:Vector.<Number>):Vector3D {
var normal:Vector3D = new Vector3D();
return normal;
}
}
class Part {
public var indices:Vector.<int>;
public var verts:Vector.<Number>;
public var distance:Number;
public var object:Object;
public var x:Number;
public var y:Number;
public var z:Number;
public var normal:Vector3D;
public var shadowRatio:Number;
public function Part(obj:Object):void {
object = obj;
indices = new Vector.<int>();
}
}
class Camera3D extends Sprite {
public var nDistance:Number;
public var matrix3D:Matrix3D;
public var fllow:Boolean=false;
public var proj:PerspectiveProjection;
public var normal:Vector3D;
public function Camera3D(nNum:Number = 55):void {
proj = new PerspectiveProjection();
fieldOfView = nNum;
}
public function set focalLength(nNum:Number):void {
proj.focalLength = nNum;
setting();
}
public function get focalLength():Number {
return proj.focalLength;
}
public function set fieldOfView(nNum:Number):void {
proj.fieldOfView = nNum;
setting();
}
public function get fieldOfView():Number {
return proj.fieldOfView;
}
public function set projectionCenter(nP:Point):void {
proj.projectionCenter = nP;
setting();
}
public function get projectionCenter():Point {
return proj.projectionCenter;
}
public function setting():void {
matrix3D = new Matrix3D();
matrix3D.appendTranslation(0,0,focalLength);
matrix3D.append(proj.toMatrix3D());
normal = Vector3D.Z_AXIS;
}
}
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.events.Event;
class Object3D extends Sprite {
public var matrix3D:Matrix3D = new Matrix3D();
public var verts:Vector.<Number> = new Vector.<Number>();
public var indices:Vector.<int> = new Vector.<int>();
public var uvDatas:Vector.<Number> = new Vector.<Number>();
public var uvtDatas:Vector.<Number>;
public var parts:Array;
public var projVerts2D:Vector.<Number>;
public var texture:BitmapData;
public var shaded:BitmapData;
public var colorHSL:ColorHSL = new ColorHSL(0,0,0.5);
public var loader:Loader;
public function Object3D():void {
}
public function set color(nRGB:int):void {
colorHSL.r = nRGB >> 16 & 0xff;
colorHSL.g = nRGB >> 8 & 0xff;
colorHSL.b = nRGB & 0xff;
}
public function get color():int {
return colorHSL.value;
}
public function offsetV(nX:Number, nY:Number, nZ:Number):void {
var matrix3D:Matrix3D = new Matrix3D();
matrix3D.prependTranslation(nX,nY,nZ);
matrix3D.transformVectors(verts,verts);
}
public function set textureURL(url:String):void {
loader = new Loader();
var urlReq:URLRequest = new URLRequest(url);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loader.load(urlReq, new LoaderContext(true));
}
private function loadComplete(e:Event):void {
texture = new BitmapData(e.target.width, e.target.height,false,0xff0000ff);
texture.draw(e.target.content);
}
}
class Joint3D extends Object3D {
public function Joint3D():void {
}
}
class Cube3D extends Object3D {
public function Cube3D(nWidth:Number=100, nHeight:Number=100, nDepth:Number=100):void {
nWidth/=2;
nHeight/=2;
nDepth/=2;
verts.push(-nWidth,-nHeight, nDepth);
verts.push( nWidth,-nHeight, nDepth);
verts.push(-nWidth,-nHeight,-nDepth);
verts.push( nWidth,-nHeight,-nDepth);
verts.push( nWidth,-nHeight, nDepth);
verts.push(-nWidth,-nHeight, nDepth);
verts.push(-nWidth,-nHeight,-nDepth);
verts.push(-nWidth, nHeight,-nDepth);
verts.push( nWidth, nHeight,-nDepth);
verts.push( nWidth, nHeight, nDepth);
verts.push(-nWidth, nHeight, nDepth);
verts.push(-nWidth, nHeight,-nDepth);
verts.push(-nWidth, nHeight, nDepth);
verts.push( nWidth, nHeight, nDepth);
uvDatas.push(0/4,0/3, 1/4,0/3);
uvDatas.push(0/4,1/3, 1/4,1/3, 2/4,1/3, 3/4,1/3, 4/4,1/3);
uvDatas.push(0/4,2/3, 1/4,2/3, 2/4,2/3, 3/4,2/3, 4/4,2/3);
uvDatas.push(0/4,3/3, 1/4,3/3);
parts = new Array();
for (var i:int = 0; i < 6; i++) {
var part:Part = new Part(this);
switch (i) {
case 0:
part.indices.push(0,1, 2, 3, 2,1);
part.normal = new Vector3D(0,-1,0);
break; // Top
case 1:
part.indices.push(2,3, 7, 8, 7,3);
part.normal = new Vector3D(0,0,-1);
break; // Front
case 2:
part.indices.push(3,4, 8, 9, 8,4);
part.normal = new Vector3D(1,0,0);
break; // Right
case 3:
part.indices.push(4,5, 9, 10, 9,5);
part.normal = new Vector3D(0,0,1);
break; // Back
case 4:
part.indices.push(5,6,10, 11,10,6);
part.normal = new Vector3D(-1,0,0);
break; // Left
case 5:
part.indices.push(7,8,12, 13,12,8);
part.normal = new Vector3D(0,1,0);
break; // Bottom
}
parts.push(part);
}
}
}