private var diffuse:Array = [1.0, 1.0, 1.0]; private var ambient:Array = [0.125, 0.125, 0.125];
private var lineColor:Array = [0.5, 0.5, 0.5]; private var pointColor:Array = [1.0, 1.0, 1.0];
private var vertex:Array; private var normal:Vector3d; private var center:Vector3d;
// CONSTRUCTORS public function Face(...args) { switch(args.length) { case 0: var scale:Number = 1.0; vertex = new Array(NUM_VERTEX); for (var i:int = 0; i < vertex.length; i++) { vertex[i] = new Vector3d(DEF_VERTEX[i]); vertex[i].multiplyEqual(scale); }
normal = new Vector3d(0.0, 0.0, 1.0); center = new Vector3d(0.0, 0.0, 0.0);
// デバッグ /*Debug.trace(vertex[0].get(0) + " " + vertex[0].get(1) + " " + vertex[0].get(2) + "\n" + vertex[1].get(0) + " " + vertex[1].get(1) + " " + vertex[1].get(2) + "\n" + vertex[2].get(0) + " " + vertex[2].get(1) + " " + vertex[2].get(2) );*/ break; case 1: if (args[0] is Number) { scale = args[0]; vertex = new Array(NUM_VERTEX); for (i = 0; i < vertex.length; i++) { vertex[i] = new Vector3d(DEF_VERTEX[i]); vertex[i].multiplyEqual(scale); }
normal = new Vector3d(0.0, 0.0, 1.0); center = new Vector3d(0.0, 0.0, 0.0); } else if (args[0] is Array) { var v:Array = args[0]; if (v[0] is Vector3d) { vertex = new Array(NUM_VERTEX); for (i = 0; i < vertex.length; i++) { vertex[i] = v[i].copy(); }
private function calculateNormal():void { var v0:Vector3d = new Vector3d(vertex[0]); var v1:Vector3d = new Vector3d(vertex[1]); var v2:Vector3d = new Vector3d(vertex[2]); var v21:Vector3d = v2.subtract(v1); // v21 = v2 - v1 var v01:Vector3d = v0.subtract(v1); // v01 = v0 - v1
normal = v21.cross(v01); // n = v21 × v01 normal.normalize();
private function calculateCenter():void { center.setValue(0.0, 0.0, 0.0); for (var i:int = 0; i < vertex.length; i++) { center.addEqual(vertex[i]); } center.divideEqual(vertex.length); }
public function fillPolygon(g:Graphics):void { var v2d:Array = new Array(vertex.length); for (var i:int = 0; i < vertex.length; i++) { v2d[i] = new Vector2d(vertex[i].getX(), vertex[i].getY()); }
var x:Array = new Array(vertex.length); var y:Array = new Array(vertex.length);
package { /** * 2次元ベクトルクラス * @author pick */ public class Vector2d { // PUBLIC MEMBERS public static const DIMENSION:int = 2;
// PRIVATE MEMBERS private var vec:Array;
// CONSTRUCTORS public function Vector2d(...args) { switch(args.length) { case 0: vec = new Array(DIMENSION); vec[0] = 0.0; vec[1] = 0.0; break; case 2: var x:Number = args[0]; var y:Number = args[1]; vec = new Array(DIMENSION); vec[0] = x; vec[1] = y; break; } }
public function add(v:Vector2d):Vector2d { var dstV:Vector2d = new Vector2d(); for (var i:int = 0; i < DIMENSION; i++) { dstV.vec[i] = vec[i] + v.vec[i]; }
return dstV; }
public function subtract(v:Vector2d):Vector2d { var dstV:Vector2d = new Vector2d(); for (var i:int = 0; i < DIMENSION;i++ ) { dstV.vec[i] = vec[i] - v.vec[i]; }
return dstV; }
public function dot(v:Vector2d):Number { var dot:Number = 0.0; for (var i:int = 0; i < DIMENSION; i++ ) { dot += vec[i] * v.vec[i]; }
return dot; }
public function set(index:int, value:Number):void { if (index < 0 || index >= DIMENSION) { return; }
vec[index] = value; }
public function get(index:int):Number { if (index < 0 || index >= DIMENSION) { return 0.0; }
return vec[index]; }
public function getVec():Array { return vec; }
public function getX():Number { return get(0); }
public function getY():Number { return get(1); }
public function length():Number { return Math.sqrt(dot(this)); }
public function normalize():Number { var l:Number = length(); if (l == 0.0) { return 0.0;; }
for (var i:int = 0; i < DIMENSION;i++ ) { vec[i] /= l; }
return l; }
public function rotate(angle:Number):Vector2d { var v:Vector2d = new Vector2d(); var radian:Number = degreeToRadian(angle); var cos:Number = Math.cos(radian); var sin:Number = Math.sin(radian);
v.vec[0] = cos * vec[0] + -sin * vec[1]; v.vec[1] = sin * vec[0] + cos * vec[1];
return v; }
public function degreeToRadian(degree:Number):Number { return (degree * Math.PI / 180.0); }
}
}
vector3d.as
package { /** * 3次元ベクトルクラス * @author pick */ public class Vector3d { // PUBLIC MEMBERS public static const DIMENSION:int = 3;
// PRIVATE MEMBERS private var vec:Array;
// CONSTRUCTORS public function Vector3d(...args) { switch(args.length) { case 0: vec = new Array(DIMENSION); vec[0] = 0.0; vec[1] = 0.0; vec[2] = 0.0; break; case 1: if(args[0] is Array){ var v:Array = args[0]; vec = new Array(DIMENSION); vec[0] = v[0]; vec[1] = v[1]; vec[2] = v[2]; } else if (args[0] is Vector3d) { var v3d:Vector3d = args[0]; vec = new Array(DIMENSION); vec[0] = v3d.vec[0]; vec[1] = v3d.vec[1]; vec[2] = v3d.vec[2]; }
break; case 3: var x:Number = args[0]; var y:Number = args[1]; var z:Number = args[2]; vec = new Array(DIMENSION); vec[0] = x; vec[1] = y; vec[2] = z; break; } }
public function add(v:Vector3d):Vector3d { var dstV:Vector3d = new Vector3d(); for (var i:int = 0; i < DIMENSION; i++ ) { dstV.vec[i] = vec[i] + v.vec[i]; }
return dstV;
}
public function subtract(v:Vector3d):Vector3d { var dstV:Vector3d = new Vector3d(); for (var i:int = 0; i < DIMENSION;i++ ) { dstV.vec[i] = vec[i] - v.vec[i]; }
return dstV; }
public function multiply(scalar:Number):Vector3d { var v:Vector3d = new Vector3d(); for (var i:int = 0; i < DIMENSION; i++) { v.vec[i] = vec[i] * scalar; }
return v; }
public function addEqual(...args):void { if (args[0] is Number) { var scalar:Number = args[0]; for (var i:int = 0; i < DIMENSION; i++) { vec[i] += scalar; } } else if(args[0] is Vector3d) { var v:Vector3d = args[0]; for (i = 0; i < DIMENSION; i++) { vec[i] += v.vec[i]; } } }
public function multiplyEqual(scalar:Number):void { for (var i:int = 0; i < DIMENSION; i++) { vec[i] *= scalar; } }
public function divideEqual(scalar:Number):void { if (scalar == 0.0) { return; }
for (var i:int = 0; i < DIMENSION; i++) { vec[i] /= scalar; }
}
public function dot(v:Vector3d):Number { var dot:Number = 0.0; for (var i:int = 0; i < DIMENSION;i++ ) { dot += vec[i] * v.vec[i]; }
return dot; }
public function cross(v:Vector3d):Vector3d { var cross:Vector3d = new Vector3d(); for (var i:int = 0; i < DIMENSION;i++ ) { cross.vec[i] = vec[(i + 1) % DIMENSION] * v.vec[(i + 2) % DIMENSION] - vec[(i + 2) % DIMENSION] * v.vec[(i + 1) % DIMENSION]; }
return cross; }
public function length():Number { return Math.sqrt(dot(this)); }
public function normalize():Number { var l:Number = length(); if (l == 0.0) { return 0.0;; }
for (var i:int = 0; i < DIMENSION;i++ ) { vec[i] /= l; }
return l; }
public function angle(v:Vector2d):Number { var normal1:Vector2d = new Vector2d(vec); normal1.normalize(); var normal2:Vector2d = new Vector2d(v.getVec); normal2.normalize();
var cos:Number = normal1.dot(normal2);
return (radianToDegree(Math.acos(cos))); }
public function radianToDegree(radian:Number):Number { return (radian * 180.0 / Math.PI); }
public function set(index:int, value:Number):void { if (index < 0 || index >= DIMENSION) { return; }
vec[index] = value; }
public function get(index:int):Number { if (index < 0 || index >= DIMENSION) { return 0.0; }
return vec[index]; }
public function getX():Number { return get(0); }
public function getY():Number { return get(1); }
public function getZ():Number { return get(2); }
public function setX(value:Number):void { set(0, value); }
public function setY(value:Number):void { set(1, value); }
public function setZ(value:Number):void { set(2, value); }
public function setValue(...args):void { switch(args.length) { case 1: var v:Array = args[0]; for (var i:int = 0; i < DIMENSION; i++) { set(i, v[i]); } break; case 3: var x:Number = args[0]; var y:Number = args[1]; var z:Number = args[2]; setX(x); setY(y); setZ(z); break; } }
public function copy():Vector3d { return (new Vector3d(vec)); }
}
}
Mtrix4x4d.as
package { /** * 4×4行列クラス * @author pick */ public class Matrix4x4d { // PUBLIC MEMBERS public static const DIMENSION:int = 4;
// PRIVATE MEMBERS private var mat:Array;
// CONSTRUCTORS public function Matrix4x4d(...args) { switch(args.length) { case 0: mat = new Array(DIMENSION); for (var i:int = 0; i < DIMENSION; i++ ) { mat[i] = new Array(DIMENSION); for (var j:int = 0; j < DIMENSION;j++ ) { mat[i][j] = 0.0; } }
makeIdentity(); break; case 1: var m:Array = args[0]; mat = new Array(DIMENSION); for (i = 0; i < DIMENSION; i++ ) { mat[i] = new Array(DIMENSION); for (j = 0; j < DIMENSION;j++ ) { mat[i][j] = 0.0; } }
setValue(m); break; } }
public function makeIdentity():void { for (var i:int = 0; i < DIMENSION;i++ ) { for (var j:int = 0; j < DIMENSION;j++ ) { mat[i][j] = (i == j ? 1.0 : 0.0); } } }
public function setValue(m:Array):void { for (var i:int = 0; i < DIMENSION;i++ ) { for (var j:int = 0; j < DIMENSION;j++ ) { set(i, j, m[i][j]); } } }
public function set(i:int, j:int, value:Number):void { if ((i < 0 || i >= DIMENSION) && (j < 0 || j >= DIMENSION)) { return; }
mat[i][j] = value; }
public function add(m:Matrix4x4d):Matrix4x4d { var dstM:Matrix4x4d = new Matrix4x4d(); for (var i:int = 0; i < DIMENSION;i++ ) { for (var j:int = 0; j < DIMENSION;j++ ) { dstM.mat[i][j] = mat[i][j] + m.mat[i][j]; } }
return dstM; }
public function subtract(m:Matrix4x4d):Matrix4x4d { var dstM:Matrix4x4d = new Matrix4x4d(); for (var i:int = 0; i < DIMENSION;i++ ) { for (var j:int = 0; j < DIMENSION;j++ ) { dstM.mat[i][j] = mat[i][j] - m.mat[i][j]; } }
return dstM; }
public function multiply(scalar:Number):Matrix4x4d { var m:Matrix4x4d = new Matrix4x4d(); for (var i:int = 0; i < DIMENSION; i++) { for (var j:int = 0; j < DIMENSION; j++) { m.mat[i][j] = mat[i][j] * scalar; } }
return m; }
public function addEqual(...args):void { if (args[0] is Number) { var scalar:Number = args[0]; for (var i:int = 0; i < DIMENSION; i++) { for (var j:int = 0; j < DIMENSION; j++) { mat[i][j] += scalar; } } } else if (args[0] is Matrix4x4d) { var m:Matrix4x4d = args[0]; for (i = 0; i < DIMENSION; i++) { for (j = 0; j < DIMENSION; j++) { mat[i][j] += m.mat[i][j]; } } }
}
public function multiplyEqual(scalar:Number):void { for (var i:int = 0; i < DIMENSION; i++) { for (var j:int = 0; j < DIMENSION; j++) { mat[i][j] *= scalar; } } }
public function getValue(m:Array):void { for (var i:int = 0; i < DIMENSION;i++ ) { for (var j:int = 0; j < DIMENSION;j++ ) { m[i][j] = get(i, j); } } }
public function get(i:int, j:int):Number { if ((i < 0 || i >= DIMENSION) && (j < 0 || j >= DIMENSION)) {
}
return mat[i][j]; }
public function multiplyRight(m:Matrix4x4d):Matrix4x4d { var dstM:Matrix4x4d = new Matrix4x4d(); for (var i:int = 0; i < DIMENSION; i++) { for (var j:int = 0; j < DIMENSION; j++) { dstM.mat[i][j] = 0.0; for (var k:int = 0; k < DIMENSION; k++) { dstM.mat[i][j] += mat[i][k] * m.mat[k][j]; } } }
return dstM; }
public function multiplyVecRight(v:Vector3d):Vector3d { var dstV:Vector3d = new Vector3d();
public function makeView(to:Vector3d, from:Vector3d, up:Vector3d):void { var zeroVec:Vector3d = new Vector3d(0.0, 0.0, 0.0); var dir:Vector3d; var y:Vector3d = new Vector3d(0.0, 1.0, 0.0); var z:Vector3d = new Vector3d(0.0, 0.0, 1.0); var minusZ:Vector3d = new Vector3d(0.0, 0.0, -1.0); var axis:Vector3d; var angle:Number; var cos:Number; var sin:Number;
dir = to.subtract(from); dir.normalize();
var dirZX:Vector3d = dir.copy(); dirZX.setY(0.0); dirZX.normalize();
var rotDirMat1:Matrix4x4d = new Matrix4x4d(); rotDirMat1.makeIdentity();
axis = minusZ.cross(dirZX); if (axis.length() > 0.0) { cos = minusZ.dot(dirZX); sin = axis.length(); angle = radianToDegree(Math.atan2( sin, cos )); axis.normalize(); rotDirMat1.makeRotation(axis, angle); }
var rotDirMat2:Matrix4x4d = new Matrix4x4d(); rotDirMat2.makeIdentity(); axis = dirZX.cross(dir); if (axis.length() > 0.0) { cos = dirZX.dot(dir); sin = axis.length(); angle = radianToDegree(Math.atan2(sin, cos)); axis.normalize(); rotDirMat2.makeRotation(axis, angle); } var rotMat1:Matrix4x4d = rotDirMat2.multiplyRight(rotDirMat1);
var proj:Number; var projVec:Vector3d; var normalUp:Vector3d; var verticalUp:Vector3d; var verticalY:Vector3d; normalUp = up; normalUp.normalize(); proj = normalUp.dot(dir); projVec = dir.multiply(proj); verticalUp = normalUp.subtract(projVec); proj = y.dot(dir); projVec = dir.multiply(proj); verticalY = y.subtract(projVec); axis = verticalY.cross(verticalUp);
var rotMat2:Matrix4x4d = new Matrix4x4d(); rotMat2.makeIdentity(); if (axis.length() > 0.0) { cos = verticalY.dot(verticalUp); sin = axis.length(); angle = radianToDegree(Math.atan2(sin, cos)); axis.normalize(); rotMat2.makeRotation(axis, angle); }
var rotMat:Matrix4x4d = rotMat2.multiplyRight(rotMat1);
var trans:Vector3d; var transMat:Matrix4x4d = new Matrix4x4d(); transMat.makeIdentity(); trans = from; transMat.makeTranslation(trans);
var viewMat:Matrix4x4d; viewMat = transMat.multiplyRight(rotMat); viewMat.invert();
viewMat.getValue(mat); }
public function invert():Boolean { var cofactorMat:Array = new Array(DIMENSION); for (var i:int = 0; i < DIMENSION;i++ ) { cofactorMat[i] = new Array(DIMENSION); for (var j:int = 0; j < DIMENSION;j++ ) { cofactorMat[i][j] = 0.0; } }
var _det:Number; var status:Boolean;
for (var row:int = 0; row < DIMENSION; row++) { for (var col:int = 0; col < DIMENSION; col++) { cofactorMat[row][col] = cofactor(col, row); } }
_det = det();
if (_det != 0.0) { for (row = 0; row < DIMENSION; row++) { for (col = 0; col < DIMENSION; col++) { mat[row][col] = cofactorMat[row][col] / _det; } } status = true; } else { status = false; }
return status; }
private function det(...args):Number { switch(args.length) { case 0: var det:Number;
if (DIMENSION == 1) { det = mat[0][0]; } else { det = 0.0; for (var j:int = 0; j < DIMENSION; j++) { det += mat[0][j] * cofactor(mat, DIMENSION, 0, j); } }
break; case 2: var mat:Array = args[0]; var dimension:int = args[1];
det;
if (DIMENSION == 1) { det = mat[0][0]; } else { det = 0.0; for (j = 0; j < dimension; j++) { det += mat[0][j] * cofactor(mat, dimension, 0, j); } }
break; } return det; }
public function cofactor(...args):Number { switch(args.length) { case 2: var i:int = args[0]; var j:int = args[1];
var cofactor:Number = 0.0; var m:Array = new Array(DIMENSION); for (i = 0; i < DIMENSION;i++ ) { m[i] = new Array(DIMENSION); for (j = 0; j < DIMENSION;j++ ) { m[i][j] = 0.0; } }
for (var k:int = 0; k < dimension; k++) { for (var l:int = 0; l < dimension; l++) { if (k < i && l < j) { m[k][l] = mat[k][l]; } else if (k < i && l > j) { m[k][l - 1] = mat[k][l]; } else if (k > i && l < j) { m[k - 1][l] = mat[k][l]; } else if (k > i && l > j) { m[k - 1][l - 1] = mat[k][l]; } } }
cofactor = Math.pow(-1.0, i + j) * det(m, dimension - 1); break; case 4: var mat:Array = args[0]; var dimension:int = args[1]; i = args[2]; j = args[3];
cofactor = 0.0; m = new Array(DIMENSION); for (i = 0; i < DIMENSION;i++ ) { m[i] = new Array(DIMENSION); for (j = 0; j < DIMENSION;j++ ) { m[i][j] = 0.0; } }
for (k = 0; k < dimension; k++) { for (l = 0; l < dimension; l++) { if (k < i && l < j) { m[k][l] = mat[k][l]; } else if (k < i && l > j) { m[k][l - 1] = mat[k][l]; } else if (k > i && l < j) { m[k - 1][l] = mat[k][l]; } else if (k > i && l > j) { m[k - 1][l - 1] = mat[k][l]; } } }