2009年4月29日 星期三

簡單的FK(Forward Kinematics)Algorithm

這是從討論以FK轉換化學鍵方位的文章看來的公式
[X',Y',Z',1]t=Mrt(i,theta)[X,Y,Z,1]t

[X',Y',Z',1]t為轉換後的頂點
Mrt為旋轉平移矩陣
[X,Y,Z,1]t為轉換後的頂點
i代表各根骨頭
theta為各Bone Joint的旋轉角度

PV3D Bone FK(Forward Kinematics)試作--回眸轉臂

經過好幾天眼睛幾乎快脫窗的測試
終於確認原本的四元數(Quaternion)旋轉矩陣運算程式碼無誤
需要在Blender建模階段將骨頭(Bone)與頂點(Vertex)對應關係處理好
正向運動(Forward Kinematics)才能順利運轉

當初搞不定PV3D的DAE類別
一來可能就是產生的檔案太大(50frames動輒超出1M)
二來就是建模階段的對應關係沒處理好(有時會出現骨頭位置喬好後,切換到編輯模式竟然會跑出Mesh的範圍)
所以才無法正常運作

目前關節部位(Joints)的旋轉還要加上權重值的運算才不會產生扭曲
以下是展示程式


頂點:1146
面數:2268
SWF檔案:169K
[Demo]

2009年4月22日 星期三

PV3D Bone FK(Forward Kinematics)試作-美女變怪獸

最近嘗試實作FK(Forward Kinematics)
本來的想法是讓美女彎個腰
移動Spine牽動Neck再牽動Head
可惜在Blender建立骨頭與頂點對應關係時沒處理好
美女就變成怪獸了

頂點:762
面數:1500
SWF檔案:157K
[Demo]

2009年4月2日 星期四

PV3D Bone Rotation and Quaternion

PV3D的DAE類別測試了許久
總是會遇到一些大大小小的障礙
搜遍了NABBLE的討論文章
也找不到適合我的解決之道
無奈只好捲起袖子試著"重新發明輪子"
K了一些硬梆梆的有關數學及三D理論的網路文章
硬著頭皮寫下這個很粗糙的程式碼
主要是將人物四肢所屬的頂點索引塞到不同的Group
再分別以不同的四元數(Quaternion)旋轉之
當然還有很多細節還沒處理好
不過時間有限
先這樣子留個紀錄......


[demo]


package {
import flash.utils.Dictionary;

import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.*;
import org.papervision3d.core.proto.MaterialObject3D;

public class CubeMan extends TriangleMesh3D {
private var ve:Array;
private var fa:Array;
private var vertGroupDict:Dictionary = new Dictionary();

public function aaa(material : MaterialObject3D ) {
super( material, new Array(), new Array() );
ve = this.geometry.vertices;
fa = this.geometry.faces;
v(1.000000,-1.000000,1.000000);
v(1.000000,-1.000000,-1.000000);
v(-1.000000,-1.000000,-1.000000);
v(-1.000000,-1.000000,1.000000);
v(1.000000,1.000000,0.999999);
v(0.999999,1.000000,-1.000001);
v(-1.000000,1.000000,-1.000000);
v(-1.000000,1.000000,1.000000);
v(-1.000000,-1.000000,-2.806856);
v(-1.000000,1.000000,-2.806855);
v(1.000000,-1.000000,-2.806856);
v(0.999999,1.000000,-2.806856);
v(1.000000,-1.000000,-4.640568);
v(-1.000001,-1.000000,-4.640568);
v(-1.000001,1.000000,-4.640568);
v(0.999999,1.000000,-4.640569);
v(-1.000001,-1.000000,-6.226972);
v(-1.000001,1.000000,-6.226972);
v(0.999999,-1.000000,-6.226972);
v(0.999999,1.000000,-6.226973);
v(2.975521,-1.000000,-4.640568);
v(2.975521,-1.000000,-6.226972);
v(2.975520,1.000000,-6.226973);
v(2.975521,1.000000,-4.640569);
v(-3.035387,1.000000,-4.640568);
v(-3.035387,1.000000,-6.226972);
v(-3.035387,-1.000000,-6.226972);
v(-3.035387,-1.000000,-4.640568);
v(0.999999,0.999999,-9.615506);
v(2.975520,1.000000,-9.615506);
v(2.975521,-1.000000,-9.615505);
v(0.999999,-1.000001,-9.615505);
v(0.999999,0.999996,-15.988734);
v(0.999999,-1.000004,-15.988733);
v(2.975521,-1.000003,-15.988733);
v(2.975520,0.999996,-15.988734);
v(-1.000001,-0.999999,-9.610606);
v(-3.035387,-1.000000,-9.610606);
v(-3.035387,1.000000,-9.610606);
v(-1.000001,1.000001,-9.610606);
v(-1.000001,-0.999999,-15.983833);
v(-1.000001,1.000001,-15.983833);
v(-3.035387,1.000000,-15.983833);
v(-3.035387,-1.000000,-15.983833);
v(-0.999999,-1.000000,2.229123);
v(-1.000000,1.000000,2.229123);
v(1.000000,-1.000000,2.229122);
v(1.000001,1.000000,2.229122);
v(-0.999999,-1.000000,2.229123);
v(1.000000,-1.000000,2.229122);
v(-1.000000,1.000000,2.229123);
v(1.000001,1.000000,2.229122);
v(-0.999999,-0.999999,4.732891);
v(-0.999999,1.000001,4.732890);
v(1.000001,-0.999999,4.732890);
v(1.000001,1.000001,4.732890);
v(1.000000,-1.000000,1.000000);
v(1.000000,1.000000,0.999999);
v(1.000000,-1.000000,-1.000000);
v(0.999999,1.000000,-1.000001);
v(3.994711,-1.000000,0.999999);
v(3.994711,-1.000000,-1.000001);
v(3.994712,1.000000,0.999998);
v(3.994711,1.000000,-1.000002);
v(8.607256,-1.000000,0.999996);
v(8.607256,1.000000,0.999996);
v(8.607256,-1.000000,-1.000004);
v(8.607255,1.000000,-1.000004);
v(8.607256,-1.000000,-1.000004);
v(8.607256,-1.000000,0.999996);
v(8.607255,1.000000,-1.000004);
v(8.607256,1.000000,0.999996);
v(12.600204,1.000001,0.999994);
v(12.600204,-0.999999,0.999994);
v(12.600203,1.000001,-1.000006);
v(12.600204,-0.999999,-1.000005);
v(-4.202740,-1.000000,1.000000);
v(-4.202740,1.000000,1.000000);
v(-4.202740,-1.000000,-1.000000);
v(-4.202740,1.000000,-1.000000);
v(-8.722494,-1.000000,-0.999998);
v(-8.722494,-1.000000,1.000003);
v(-8.722494,1.000000,-0.999997);
v(-8.722494,1.000000,1.000002);
v(-12.583741,1.000000,1.000002);
v(-12.583741,-1.000000,1.000003);
v(-12.583741,1.000000,-0.999997);
v(-12.583741,-1.000000,-0.999998);

f(87,86,84);
f(87,84,85);
f(81,80,87);
f(81,87,85);
f(82,83,84);
f(82,84,86);
f(80,82,86);
f(80,86,87);
f(83,81,85);
f(83,85,84);
f(77,76,81);
f(77,81,83);
f(78,79,82);
f(78,82,80);
f(79,77,82);
f(77,83,82);
f(76,78,80);
f(76,80,81);
f(3,2,76);
f(2,78,76);
f(6,7,77);
f(6,77,79);
f(2,6,79);
f(2,79,78);
f(7,3,77);
f(3,76,77);
f(73,72,75);
f(72,74,75);
f(68,69,73);
f(68,73,75);
f(71,70,74);
f(71,74,72);
f(70,68,74);
f(68,75,74);
f(69,71,73);
f(71,72,73);
f(64,65,71);
f(64,71,69);
f(67,66,68);
f(67,68,70);
f(65,67,70);
f(65,70,71);
f(66,64,69);
f(66,69,68);
f(61,60,64);
f(61,64,66);
f(62,63,67);
f(62,67,65);
f(63,61,67);
f(61,66,67);
f(60,62,64);
f(62,65,64);
f(56,57,60);
f(57,62,60);
f(59,58,63);
f(58,61,63);
f(57,59,63);
f(57,63,62);
f(58,56,60);
f(58,60,61);
f(1,0,56);
f(1,56,58);
f(4,5,59);
f(4,59,57);
f(5,1,58);
f(5,58,59);
f(0,4,57);
f(0,57,56);
f(55,54,53);
f(54,52,53);
f(49,48,52);
f(49,52,54);
f(50,51,55);
f(50,55,53);
f(51,49,55);
f(49,54,55);
f(48,50,53);
f(48,53,52);
f(44,45,50);
f(44,50,48);
f(47,46,49);
f(47,49,51);
f(45,47,51);
f(45,51,50);
f(46,44,48);
f(46,48,49);
f(0,3,44);
f(0,44,46);
f(7,4,47);
f(7,47,45);
f(4,0,46);
f(4,46,47);
f(3,7,45);
f(3,45,44);
f(40,41,42);
f(40,42,43);
f(37,36,40);
f(37,40,43);
f(38,37,43);
f(38,43,42);
f(39,38,42);
f(39,42,41);
f(36,39,41);
f(36,41,40);
f(16,17,36);
f(17,39,36);
f(17,25,38);
f(17,38,39);
f(25,26,37);
f(25,37,38);
f(26,16,36);
f(26,36,37);
f(32,33,35);
f(33,34,35);
f(29,28,32);
f(29,32,35);
f(30,29,35);
f(30,35,34);
f(31,30,34);
f(31,34,33);
f(28,31,33);
f(28,33,32);
f(19,18,31);
f(19,31,28);
f(18,21,30);
f(18,30,31);
f(21,22,30);
f(22,29,30);
f(22,19,28);
f(22,28,29);
f(24,27,25);
f(27,26,25);
f(14,13,27);
f(14,27,24);
f(13,16,27);
f(16,26,27);
f(17,14,24);
f(17,24,25);
f(20,23,21);
f(23,22,21);
f(12,15,23);
f(12,23,20);
f(15,19,22);
f(15,22,23);
f(18,12,21);
f(12,20,21);
f(18,19,16);
f(19,17,16);
f(13,12,18);
f(13,18,16);
f(15,14,17);
f(15,17,19);
f(9,8,14);
f(8,13,14);
f(10,11,12);
f(11,15,12);
f(11,9,14);
f(11,14,15);
f(8,10,12);
f(8,12,13);
f(2,1,8);
f(1,10,8);
f(5,6,9);
f(5,9,11);
f(1,5,10);
f(5,11,10);
f(6,2,9);
f(2,8,9);
f(4,7,5);
f(7,6,5);
f(0,1,2);
f(0,2,3);


/*GroupName=LeftHand.002*/
vertGroupDict["LeftHand.002"]= new Array();
vertGroupDict["LeftHand.002"].push(76);
vertGroupDict["LeftHand.002"].push(77);
vertGroupDict["LeftHand.002"].push(79);
vertGroupDict["LeftHand.002"].push(80);
vertGroupDict["LeftHand.002"].push(81);
vertGroupDict["LeftHand.002"].push(82);
vertGroupDict["LeftHand.002"].push(83);
vertGroupDict["LeftHand.002"].push(84);
vertGroupDict["LeftHand.002"].push(85);
vertGroupDict["LeftHand.002"].push(86);
vertGroupDict["LeftHand.002"].push(87);

/*GroupName=RightHand.002*/
vertGroupDict["RightHand.002"]= new Array();
vertGroupDict["RightHand.002"].push(62);
vertGroupDict["RightHand.002"].push(63);
vertGroupDict["RightHand.002"].push(64);
vertGroupDict["RightHand.002"].push(65);
vertGroupDict["RightHand.002"].push(66);
vertGroupDict["RightHand.002"].push(67);
vertGroupDict["RightHand.002"].push(68);
vertGroupDict["RightHand.002"].push(69);
vertGroupDict["RightHand.002"].push(70);
vertGroupDict["RightHand.002"].push(71);
vertGroupDict["RightHand.002"].push(72);
vertGroupDict["RightHand.002"].push(73);
vertGroupDict["RightHand.002"].push(74);
vertGroupDict["RightHand.002"].push(75);



/*GroupName=LeftLeg.1*/
vertGroupDict["LeftLeg.1"]= new Array();
vertGroupDict["LeftLeg.1"].push(17);
vertGroupDict["LeftLeg.1"].push(25);
vertGroupDict["LeftLeg.1"].push(26);
vertGroupDict["LeftLeg.1"].push(36);
vertGroupDict["LeftLeg.1"].push(37);
vertGroupDict["LeftLeg.1"].push(38);
vertGroupDict["LeftLeg.1"].push(39);
vertGroupDict["LeftLeg.1"].push(40);
vertGroupDict["LeftLeg.1"].push(41);
vertGroupDict["LeftLeg.1"].push(42);
vertGroupDict["LeftLeg.1"].push(43);


/*GroupName=RightLeg.1*/
vertGroupDict["RightLeg.1"]= new Array();
vertGroupDict["RightLeg.1"].push(18);
vertGroupDict["RightLeg.1"].push(19);
vertGroupDict["RightLeg.1"].push(21);
vertGroupDict["RightLeg.1"].push(22);
vertGroupDict["RightLeg.1"].push(28);
vertGroupDict["RightLeg.1"].push(29);
vertGroupDict["RightLeg.1"].push(30);
vertGroupDict["RightLeg.1"].push(31);
vertGroupDict["RightLeg.1"].push(32);
vertGroupDict["RightLeg.1"].push(33);
vertGroupDict["RightLeg.1"].push(34);
vertGroupDict["RightLeg.1"].push(35);

this.x = 0.070997;
this.y = 0.051119;
this.z = 6.759333;

this.rotationX = 0.000000;
this.rotationY = 0.000000;
this.rotationZ = 0.000000;

this.scaleX = 1.000000;
this.scaleY = 1.000000;
this.scaleZ = 1.000000;

this.geometry.ready = true;

}
public function v(x:Number, y:Number, z:Number):void {
ve.push(new Vertex3D(x, y, z));
}


public function f(vertexIndex1:Number, vertexIndex2:Number, vertexIndex3:Number):void {
var face:Triangle3D = new Triangle3D(this, [ve[vertexIndex1], ve[vertexIndex2], ve[vertexIndex3]], null, []);
fa.push(face);
}

private var counter : int = 0;
private var theta:Number = (Math.PI/20);
public function apply():void {
var rQ : Quaternion;
var vs:Array = vertGroupDict["RightHand.002"];
var vc:int = vs.length;
var vsl:Array = vertGroupDict["LeftHand.002"];
var vcl:int = vsl.length;
var vsrr:Array = vertGroupDict["RightLeg.1"];
var vcrr:int = vsl.length;
var vsll:Array = vertGroupDict["LeftLeg.1"];
var vcll:int = vsl.length;

counter++;
if(counter==5)
{
counter = 0;
theta = -theta;
}
for (var i:int = 0; i < vc; i++) {
var v:Vertex3D = ve[vs[i]];
var n:Number3D = v.toNumber3D();
rQ = Quaternion.createFromAxisAngle(0,1,0,theta);
Matrix3D.multiplyVector4x4(rQ.matrix, n);
v.x = n.x;
v.y = n.y;
v.z = n.z;

}

for (var i:int = 0; i < vcl; i++) {
var v:Vertex3D = ve[vsl[i]];
var n:Number3D = v.toNumber3D();
rQ = Quaternion.createFromAxisAngle(0,1,0,-theta);
Matrix3D.multiplyVector4x4(rQ.matrix, n);
v.x = n.x;
v.y = n.y;
v.z = n.z;

}

for (var i:int = 0; i < vcrr; i++) {
var v:Vertex3D = ve[vsrr[i]];
var n:Number3D = v.toNumber3D();
rQ = Quaternion.createFromAxisAngle(1,0,0,theta);
Matrix3D.multiplyVector4x4(rQ.matrix, n);
v.x = n.x;
v.y = n.y;
v.z = n.z;

}


for (var i:int = 0; i < vcll; i++) {
var v:Vertex3D = ve[vsll[i]];
var n:Number3D = v.toNumber3D();
rQ = Quaternion.createFromAxisAngle(1,0,0,-theta);
Matrix3D.multiplyVector4x4(rQ.matrix, n);
v.x = n.x;
v.y = n.y;
v.z = n.z;

}


}

}
}