こんにちわ。
タイトルの通り、アフィン変換を使って、指定角へ回転させるようとしています。
http://www.gumob.com/3d/3d.html左側のテキストフィールドに表示される数字ですが、それぞれ
pMode 現在のモード(switch文で切り替えています)
pX,pY,pZ 現在のXYZ座標
degX,degY,degZ 各XYZ軸に対する角度
tDegX,tDegY,tDegZ ターゲット角度
右下にある四角いボタンをクリックすると、その角度へ回転するようにしています。
が、実際にクリックすると、挙動が怪しい・・・
かれこれ2?3日この状態で、一向に抜け出せません・・・
degX,degY,degZの値は、正常にターゲット角へ収束しているのですが。
全体は、
ターゲット角を指定し、
setTargetDegree(引数x,引数y,引数z)
現在の角度をターゲット角に近ける
setAngle();
ラジアン角に変換し
degreeToRadian()
アフィン変換を行い
rotateMe()
更に透視変換を行い
persTransform();
回転各がターゲット角と同じになったらデフォルトモードに(何もしないモード)
setRotateModeToDefault ();
といった流れになっています。
どなたか原因がお分かりになる方いましたら、ご教授お願いします・・・
最終的には、テキストが三次元空間に浮いていて、クリックすると、そのテキストが全面に出てきて、他は背面に移動するような物?を考えています。
以下ソースです。長いかな・・・
main.as
//初期設定を保存するクラス
function initPointClass(){
this.pArray = new Array();
this.pArray[0] = {x:0, y:0, z:-160, txt:"moe0"};
// 今のところ一つだけでテスト
/*
this.pArray[1] = {x:-60, y:120, z:-80, txt:"moe1"};
this.pArray[2] = {x:-120, y:-90, z:0, txt:"moe2"};
*/
}
// インスタンスを生成
function main() {
Object.registerClass("p_mc", Point3dClass);
for (var i = 0; i<initPoint.pArray.length; i++) {
var props = {};
props.pX = initPoint.pArray[i].x;
props.pY = initPoint.pArray[i].y;
props.pZ = initPoint.pArray[i].z;
this.attachMovie("p_mc", "p"+i, i, props);
this["p"+i].p_txt.text = initPoint.pArray[i].txt;
this["p"+i].pMode ="reset";
delete props;
}
}
initPoint = new initPointClass();
main();
Point3d.as
//
// Point3dClass
//
function Point3dClass() {
// 定数
this.PI0 = Math.PI;
this.PI1 = Math.PI/180;
this.PI2 = 180/Math.PI;
// 原点
this.pXo = 0;
this.pYo = 0;
this.pZo = 200;
// 視点
this.vp = 0;
// XYZ座標(常時更新)
this.pX, this.pY, this.pZ;
// デフォルトの座標
this.defPX, this.defPY, this.defPZ;
// 回転角(常時更新)
this.degX, this.degY, this.degZ;
// デフォルトの回転角
this.defDegX, this.defDegY, this.defDegZ;
// ターゲットとする角度
this.tDegX, this.tDegY, this.tDegZ;
// ラジアン角(常時更新)
this.radX, this.radY, this.radZ;
// 半径(常時更新)
this.radius;
// モード管理用
this.pMode;
// 初期パラメータを突っ込む
this.getDegree();
this.setDefaultParam();
}
Point3dClass.prototype = new MovieClip();
// set default parameter
Point3dClass.prototype.setDefaultParam = function(){
this.defPX = this.pX;
this.defPY = this.pY;
this.defPZ = this.pZ;
this.defDegX = this.degX;
this.defDegY = this.degY;
this.defDegZ = this.degZ;
}
// change view point
Point3dClass.prototype.changeVp = function(arg) {
if (Math.round(this.vp) == arg) {
this.vp = arg;
} else {
this.vp += (arg-this.vp)/10;
}
};
// get temporary radius
Point3dClass.prototype.getRadius = function() {
this.radius = Math.sqrt(this.pX*this.pX+this.pY*this.pY+this.pZ*this.pZ);
};
// get temporary degree
Point3dClass.prototype.getDegree = function() {
this.degX = Math.atan2(this.pY, this.pZ)*this.PI2;
this.degY = Math.atan2(this.pX, this.pZ)*this.PI2;
this.degZ = Math.atan2(this.pY, this.pX)*this.PI2;
// converting the return value of atan2
if(this.degX<0){
this.degX += 360;
}
if(this.degY<0){
this.degY += 360;
}
if(this.degZ<0){
this.degZ += 360;
}
};
// set target degree
Point3dClass.prototype.setTargetDegree = function(arg0, arg1, arg2) {
var arg0, arg1, arg2;
if(this.degX!=arg0){
this.tDegX = arg0;
}
if(this.degY!=arg1){
this.tDegY = arg1;
}
if(this.degZ!=arg2){
this.tDegZ = arg2;
}
};
// change degree to target
Point3dClass.prototype.setAngle = function() {
// rotate around X axis
if (Math.round(this.degX) != Math.round(this.tDegX)) {
this.degX += (this.tDegX-this.degX)/5;
if (this.degX>=360) {
this.degX -= 360;
} else if (this.degX<=0) {
this.degX += 360;
}
}
// rotate around Y axis
if (Math.round(this.degY) != Math.round(this.tDegY)) {
this.degY += (this.tDegY-this.degY)/5;
if (this.degY>=360) {
this.degY -= 360;
} else if (this.degY<=0) {
this.degY += 360;
}
}
// rotate around Z axis
if (Math.round(this.degZ) != Math.round(this.tDegZ)) {
this.degZ += (this.tDegZ-this.degZ)/5;
if (this.degZ>=360) {
this.degZ -= 360;
} else if (this.degZ<=0) {
this.degZ += 360;
}
}
};
// set pMode to default
Point3dClass.prototype.setRotateModeToDefault = function(){
if (Math.round(this.degX) == Math.round(this.tDegX) && Math.round(this.degY) == Math.round(this.tDegY) && Math.round(this.degZ) == Math.round(this.tDegZ)) {
this.degX = Math.round(this.degX);
this.degY = Math.round(this.degY);
this.degZ = Math.round(this.degZ);
this.pMode = "default";
}
}
// convert degree to radian
Point3dClass.prototype.degreeToRadian = function() {
this.radX = this.degX*(this.PI1);
this.radY = this.degY*(this.PI1);
this.radZ = this.degZ*(this.PI1);
};
// rotate clip (affin transformation)
Point3dClass.prototype.rotateMe = function() {
// rotate around X axis
y = this.pY*Math.cos(this.radX)-this.pZ*Math.sin(this.radX);
z = this.pY*Math.sin(this.radX)+this.pZ*Math.cos(this.radX);
this.pY = y;
this.pZ = z;
// rotate around Y axis
x = this.pX*Math.cos(this.radY)+this.pZ*Math.sin(this.radY);
z = -this.pX*Math.sin(this.radY)+this.pZ*Math.cos(this.radY);
this.pX = x;
this.pZ = z;
// rotate around Z axis
x = this.pX*Math.cos(this.radZ)-this.pY*Math.sin(this.radZ);
y = this.pX*Math.sin(this.radZ)+this.pY*Math.cos(this.radZ);
this.pX = x;
this.pY = y;
};
// scaling (affin transformation)
Point3dClass.prototype.scaleMe = function(arg) {
var arg;
this.pX = arg*this.pX;
this.pY = arg*this.pY;
this.pZ = arg*this.pZ;
}
// parallel displacement (affin transformation)
Point3dClass.prototype.displaceMe = function(arg0, arg1, arg2) {
var arg0, arg1, arg2;
this.pX = this.pX+arg0;
this.pY = this.pY+arg1;
this.pZ = this.pZ+arg2;
}
// scale clip & set postion (perspective transformation)
Point3dClass.prototype.persTransform = function() {
var x, y, z;
z = this.pZ+this.pZo;
if (z>0) {
_visible = true;
x = this.pX*this.vp/z;
y = this.pY*this.vp/z;
this._x = x+this.pXo;
this._y = y+this.pYo;
this._xscale = Math.round(100*this.vp/z);
this._yscale = Math.round(100*this.vp/z);
this._alpha = Math.min(100, Math.round(100*this.vp/z));
this.swapDepths(1000-Math.round(this.pZ));
} else {
_visible = false;
}
};
//
// event handler
//
Point3dClass.prototype.onRelease = function() {
for(var i=0; i < initPoint.pArray.length; i++){
if(i==this._name.slice(1)){
this.setTargetDegree(0,0,0);
this.setVelocity();
this.pMode = "rotateToTarget";
trace(this._name);
}else{
_parent.main["p"+i].setTargetDegree(_parent.main["p"+i].defDegX, _parent.main["p"+i].defDegY, _parent.main["p"+i].defDegZ);
_parent.main["p"+i].setVelocity();
_parent.main["p"+i].pMode = "rotateToTarget";
}
}
};
Point3dClass.prototype.onEnterFrame = function() {
switch (this.pMode) {
case "rotateToTarget" :
this.setAngle();
this.degreeToRadian();
this.rotateMe();
this.persTransform();
this.setRotateModeToDefault ();
break;
case "scale" :
break;
case "reset" :
this.changeVp(120);
this.persTransform();
break;
case "default" :
break;
}
this.output();
};
// output data on text field
Point3dClass.prototype.output = function() {
with (this) {
// point mode
data_mc.pMode_txt = "pMode : "+pMode;
// radius
data_mc.radius_txt = "radius : "+Math.sqrt(pX*pX+pY*pY+pZ*pZ);
// position
data_mc.pX_txt = "pX : "+pX;
data_mc.pY_txt = "pY : "+pY;
data_mc.pZ_txt = "pZ : "+pZ;
// radian
data_mc.radX_txt = "radX : "+radX;
data_mc.radY_txt = "radY : "+radY;
data_mc.radZ_txt = "radZ : "+radZ;
// degree
data_mc.degX_txt = "degX : "+degX;
data_mc.degY_txt = "degY : "+degY;
data_mc.degZ_txt = "degZ : "+degZ;
//target degree
data_mc.tDegX_txt = "tDegX : "+tDegX;
data_mc.tDegY_txt = "tDegY : "+tDegY;
data_mc.tDegZ_txt = "tDegZ : "+tDegZ;
}
};