package com.akjava.gwt.three.client.gwt.boneanimation;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import com.akjava.gwt.lib.client.LogUtils;
import com.akjava.gwt.three.client.java.utils.GWTThreeUtils;
import com.akjava.gwt.three.client.js.THREE;
import com.akjava.gwt.three.client.js.math.Euler;
import com.akjava.gwt.three.client.js.math.Matrix4;
import com.akjava.gwt.three.client.js.math.Quaternion;
import com.akjava.gwt.three.client.js.math.Vector3;
import com.google.gwt.core.client.JsArray;
public class AnimationBonesData {
private List<AngleAndPosition> bonesMatrixs;
private List<Vector3> baseBonePositions;
private List<Vector3> baseBoneRelativePositions;
public List<AngleAndPosition> getBonesAngleAndMatrixs() {
return bonesMatrixs;
}
public void setBonesAngleAndMatrixs(List<AngleAndPosition> bonesMatrixs) {
this.bonesMatrixs = bonesMatrixs;
}
public static List<Matrix4> cloneMatrix(List<Matrix4> matrixs){
List<Matrix4> ret=new ArrayList<Matrix4>();
for(int i=0;i<matrixs.size();i++){
ret.add((Matrix4)matrixs.get(i).clone().cast());
}
return ret;
}
public static List<AngleAndPosition> cloneAngleAndMatrix(List<AngleAndPosition> matrixs){
List<AngleAndPosition> ret=new ArrayList<AngleAndPosition>();
for(int i=0;i<matrixs.size();i++){
ret.add(matrixs.get(i).clone());
}
return ret;
}
JsArray<AnimationBone> bones;
public AnimationBonesData(JsArray<AnimationBone> bones,List<AngleAndPosition> bonesMatrix){
this.bonesMatrixs=bonesMatrix;
this.bones=bones;
bonePath=boneToPath(bones);
baseBonePositions=boneToPositions(bones);
baseBoneRelativePositions=boneToRelativePositions(bones);
}
/*
* same as bone hierachy
*/
public Vector3 getBaseBoneRelativePosition(int index){
return baseBoneRelativePositions.get(index);
}
/*
* absolute position self+parents
*/
public Vector3 getBaseBonePosition(int index){
return baseBonePositions.get(index);
}
public Vector3 getBaseParentBonePosition(int index){
return baseBonePositions.get(bones.get(index).getParent());
}
public static List<Vector3> boneToPositions(JsArray<AnimationBone> bones){
List<Vector3> positions=new ArrayList<Vector3>();
for(int i=0;i<bones.length();i++){
AnimationBone bone=bones.get(i);
Vector3 bpos=AnimationBone.jsArrayToVector3(bone.getPos());
if(bone.getParent()!=-1){
Vector3 parentPos=positions.get(bone.getParent());
bpos.addSelf(parentPos);
}
positions.add(bpos);
}
return positions;
}
public static List<Vector3> boneToRelativePositions(JsArray<AnimationBone> bones){
List<Vector3> positions=new ArrayList<Vector3>();
for(int i=0;i<bones.length();i++){
AnimationBone bone=bones.get(i);
Vector3 bpos=AnimationBone.jsArrayToVector3(bone.getPos());
positions.add(bpos);
}
return positions;
}
private List<List<Integer>> bonePath;
public int getLength(){
return bones.length();
}
public Vector3 getBonePosition(String name){
return getBonePosition(getBoneIndex(name));
}
public Vector3 getBonePosition(String name,boolean endSite){
return getBonePosition(getBoneIndex(name),endSite);
}
public Vector3 getParentAngles(int index){
List<Integer> path=bonePath.get(index);
Vector3 angle=THREE.Vector3();
Matrix4 matrix=THREE.Matrix4();
for(int j=0;j<path.size()-1;j++){//last is boneself
angle.addSelf(bonesMatrixs.get(path.get(j)).getDegreeAngle());
}
return angle;
}
public List<Integer> getBonePath(int index){
return bonePath.get(index);
}
public Vector3 getBonePosition(int index){
return getBonePosition(index,false);
}
public Vector3 getBonePosition(int index,boolean endSite){
List<Integer> path=bonePath.get(index);
Vector3 pos=getMatrixPosition(path.get(path.size()-1));
int size=path.size()-1;
if(endSite){
size=path.size();
}
Matrix4 matrix=THREE.Matrix4();
for(int j=0;j<size;j++){//last is boneself
Matrix4 mx=bonesMatrixs.get(path.get(j)).getMatrix();
matrix.multiplyMatrices(matrix, mx);
}
pos.applyProjection(matrix);
return pos;
}
public Vector3 getParentPosition(String name){
return getParentPosition(getBoneIndex(name));
}
//dont call 0(root)
public Vector3 getParentPosition(int parent){
int index=bones.get(parent).getParent();
List<Integer> path=bonePath.get(index);
Matrix4 tmpmx=bonesMatrixs.get(path.get(path.size()-1)).getMatrix();
Vector3 pos=THREE.Vector3();
pos.setFromMatrixPosition(tmpmx);
Matrix4 matrix=THREE.Matrix4();
for(int j=0;j<path.size()-1;j++){//last is boneself
// log(""+path.get(j));
Matrix4 mx=bonesMatrixs.get(path.get(j)).getMatrix();
matrix.multiplyMatrices(matrix, mx);
}
matrix.multiplyVector3(pos);
return pos;
}
public int getBoneIndex(String name){
for(int i=0;i<bones.length();i++){
if(bones.get(i).getName().equals(name)){
return i;
}
}
return -1;
}
public String getBoneName(int index){
return bones.get(index).getName();
}
public AngleAndPosition getBoneAngleAndMatrix(String name){
return getBoneAngleAndMatrix(getBoneIndex(name));
}
public void setBoneAngleAndMatrix(int index,AngleAndPosition matrix){
bonesMatrixs.set(index,matrix);
}
public AngleAndPosition getBoneAngleAndMatrix(int index){
return bonesMatrixs.get(index);
}
public Vector3 getMatrixPosition(int index){
/*
Matrix4 pos= bonesMatrixs.get(index).getMatrix();
return GWTThreeUtils.toPositionVec(pos);
*/
return bonesMatrixs.get(index).getPosition().clone();
}
public static List<AngleAndPosition> boneToAngleAndMatrix(JsArray<AnimationBone> bones,@Nullable AnimationData animationData,int animationIndex){
List<AngleAndPosition> boneMatrix=new ArrayList<AngleAndPosition>();
for(int i=0;i<bones.length();i++){
if(animationData==null){//make from bone
Vector3 pos=THREE.Vector3().fromArray(bones.get(i).getPos());
//watch out sometime not getRot(),only get rotq;//TODO case only has getRot
Quaternion q=THREE.Quaternion().fromArray(bones.get(i).getRotq());
//meybe zero
Euler euler=THREE.Euler().setFromQuaternion(q, "XYZ", false);
Vector3 angle=GWTThreeUtils.radiantToDegree(euler);
Matrix4 m1=THREE.Matrix4().makeTranslation(pos.getX(), pos.getY(), pos.getZ());
Matrix4 m2=THREE.Matrix4().makeRotationFromQuaternion(q);
m1.multiply(m2);
boneMatrix.add(new AngleAndPosition(angle,pos,m1));
continue;
}
AnimationHierarchyItem item=animationData.getHierarchy().get(i);
AnimationKey motion=item.getKeys().get(animationIndex);
//Matrix4 mx=THREE.Matrix4();
Vector3 motionPos=GWTThreeUtils.jsArrayToVector3(motion.getPos());
//mx.setTranslation(motionPos.getX(), motionPos.getY(), motionPos.getZ());
//mx.setRotationFromQuaternion(GWTThreeUtils.jsArrayToQuaternion(motion.getRot()));
Matrix4 mx=THREE.Matrix4().makeTranslation(motionPos.getX(), motionPos.getY(), motionPos.getZ());
Matrix4 mx2=THREE.Matrix4().makeRotationFromQuaternion(GWTThreeUtils.jsArrayToQuaternion(motion.getRot()));
mx.multiply(mx2);
/*
Matrix4 mx2=THREE.Matrix4();
mx2.setRotationFromQuaternion(motion.getRot());
mx.multiplySelf(mx2);
*/
/*
Vector3 rot=GWTThreeUtils.toDegreeAngle(mx2);
//LogUtils.log("before-angle:"+ThreeLog.get(rot));
//LogUtils.log(mx2);
//LogUtils.log(rot);
Vector3 rotR=GWTThreeUtils.degreeToRagiant(rot);
//LogUtils.log("rot:"+ThreeLog.get(rotR));
//LogUtils.log("rot-r:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(rotR)));
Matrix4 changed=GWTThreeUtils.rotationToMatrix4(rotR);
Vector3 tmpVec=THREE.Vector3();
tmpVec.setRotationFromMatrix(changed);
*/
//LogUtils.log("mx:"+ThreeLog.get(tmpVec));
//LogUtils.log("mx-r:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(tmpVec)));
//LogUtils.log("after-angle:"+ThreeLog.get(GWTThreeUtils.toDegreeAngle(changed)));
//LogUtils.log(changed);
/*
Vector3 tmpRot=THREE.Vector3();
tmpRot.setRotationFromMatrix(mx);
Vector3 tmpPos=THREE.Vector3();
tmpPos.setPositionFromMatrix(mx);
*/
//LogUtils.log(tmpPos.getX()+","+tmpPos.getY()+","+tmpPos.getZ());
//LogUtils.log(Math.toDegrees(tmpRot.))
boneMatrix.add(new AngleAndPosition(motion.getAngle(),motionPos,mx));
}
return boneMatrix;
}
public static List<Matrix4> boneToMatrix(JsArray<AnimationBone> bones,AnimationData animationData,int index){
List<Matrix4> boneMatrix=new ArrayList<Matrix4>();
//analyze bone matrix
for(int i=0;i<bones.length();i++){
AnimationHierarchyItem item=animationData.getHierarchy().get(i);
AnimationKey motion=item.getKeys().get(index);
//log(bone.getName());
Vector3 motionPos=GWTThreeUtils.jsArrayToVector3(motion.getPos());
Matrix4 mx=THREE.Matrix4().makeTranslation(motionPos.getX(), motionPos.getY(), motionPos.getZ());
//seems same as bone
// LogUtils.log(motionPos);
//mx.setTranslation(motionPos.getX(), motionPos.getY(), motionPos.getZ());
Matrix4 mx2=THREE.Matrix4().makeRotationFromQuaternion(GWTThreeUtils.jsArrayToQuaternion(motion.getRot()));
//mx2.setRotationFromQuaternion();
mx.multiply(mx2);
Vector3 rot=GWTThreeUtils.toDegreeAngle(mx2);
//LogUtils.log("before-angle:"+ThreeLog.get(rot));
//LogUtils.log(mx2);
//LogUtils.log(rot);
Vector3 rotR=GWTThreeUtils.degreeToRagiant(rot);
//LogUtils.log("rot:"+ThreeLog.get(rotR));
//LogUtils.log("rot-r:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(rotR)));
Matrix4 changed=GWTThreeUtils.rotationToMatrix4(rotR);
Vector3 tmpVec=THREE.Vector3();
tmpVec.getRotationFromMatrix(changed);
//LogUtils.log("mx:"+ThreeLog.get(tmpVec));
//LogUtils.log("mx-r:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(tmpVec)));
//LogUtils.log("after-angle:"+ThreeLog.get(GWTThreeUtils.toDegreeAngle(changed)));
//LogUtils.log(changed);
/*
Vector3 tmpRot=THREE.Vector3();
tmpRot.setRotationFromMatrix(mx);
Vector3 tmpPos=THREE.Vector3();
tmpPos.setPositionFromMatrix(mx);
*/
//LogUtils.log(tmpPos.getX()+","+tmpPos.getY()+","+tmpPos.getZ());
//LogUtils.log(Math.toDegrees(tmpRot.))
boneMatrix.add(mx);
}
return boneMatrix;
}
public static List<List<Integer>> boneToPath(JsArray<AnimationBone> bones){
List<List<Integer>> data=new ArrayList<List<Integer>>();
for(int i=0;i<bones.length();i++){
List<Integer> path=new ArrayList<Integer>();
AnimationBone bone=bones.get(i);
path.add(i);
data.add(path);
while(bone.getParent()!=-1){
//path.add(bone.getParent());
path.add(0,bone.getParent());
bone=bones.get(bone.getParent());
}
}
return data;
}
}