/*
*
* CCD-IK
* based on Inverse kinematics and geometric constraints for articulated figure manipulation
* http://summit.sfu.ca/item/5706
* and
* http://www.tmps.org/index.php?CCD-IK%20and%20Particle-IK
*
* Copyright (C) 2011-2012 aki@akjava.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.akjava.gwt.threetest.client;
import java.util.ArrayList;
import java.util.List;
import com.akjava.gwt.three.client.gwt.boneanimation.ik.CDDIK;
import com.akjava.gwt.three.client.gwt.materials.MeshBasicMaterialParameter;
import com.akjava.gwt.three.client.java.utils.GWTGeometryUtils;
import com.akjava.gwt.three.client.java.utils.GWTThreeUtils;
import com.akjava.gwt.three.client.js.THREE;
import com.akjava.gwt.three.client.js.cameras.Camera;
import com.akjava.gwt.three.client.js.core.Object3D;
import com.akjava.gwt.three.client.js.lights.Light;
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.Vector3;
import com.akjava.gwt.three.client.js.objects.Mesh;
import com.akjava.gwt.three.client.js.renderers.WebGLRenderer;
import com.akjava.gwt.three.client.js.scenes.Scene;
import com.akjava.gwt.threetest.client.resources.Bundles;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.FocusPanel;
public class IKBoneDemo extends AbstractDemo{
//private Timer timer;
@Override
public void start(final WebGLRenderer renderer,final int width,final int height,FocusPanel panel) {
super.start(renderer, width, height, panel);
renderer.setClearColor(0xffffff, 1);
final Scene scene=THREE.Scene();
final Camera camera=THREE.PerspectiveCamera(35,(double)width/height,.1,10000);
cameraControle.setPositionZ(50);
scene.add(camera);
Light pointLight = THREE.PointLight(0xffffff);
pointLight.setPosition(0, 10, 300);
scene.add(pointLight);
root=THREE.Object3D();
scene.add(root);
targetMesh = THREE.Mesh(THREE.BoxGeometry(.5, .5, .5),
THREE.MeshBasicMaterial(MeshBasicMaterialParameter.create().color(0x0000ff)));
root.add(targetMesh);
targetMesh.setPosition(targetPos);
joints = new ArrayList<Object3D>();
Object3D parent=THREE.Object3D();
joints.add(parent);
root.add(parent);
for(int i=0;i<4;i++){
int color=0xff0000;
if(i==3){
color=0x00ff00;
}
if(i==3){
hand=THREE.Mesh(THREE.BoxGeometry(.5, .5, .5),
THREE.MeshBasicMaterial(MeshBasicMaterialParameter.create().color(color)));
parent.add(hand);
Vector3 pos=THREE.Vector3(2, 0, 0);
hand.setPosition(pos);
parent.add(GWTGeometryUtils.createLineMesh(THREE.Vector3(), pos, 0x888888));
}else{
final Mesh mesh=THREE.Mesh(THREE.BoxGeometry(.5, .5, .5),
THREE.MeshBasicMaterial(MeshBasicMaterialParameter.create().color(color)));
parent.add(mesh);
Vector3 pos=THREE.Vector3(2, 0, 0);
mesh.setPosition(pos);
parent.add(GWTGeometryUtils.createLineMesh(THREE.Vector3(), pos, 0x888888));
Object3D joint=THREE.Object3D();
joint.setPosition(pos);
joints.add(joint);
parent.add(joint);
parent=joint;
}
}
panel.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(!steping){
Vector3 tpos=GWTThreeUtils.toWebGLXY(event.getX(), event.getY(), camera, width, height);
tpos.setZ(0);
targetPos=tpos;
targetMesh.setPosition(targetPos);
//log(ret);
steped=0;
steping=true;
}
}
});
/*
*/
last=System.currentTimeMillis();
Timer timer = new Timer(){
public void run(){
MainWidget.stats.begin();
camera.setPosition(cameraControle.getPositionX(), cameraControle.getPositionY(), cameraControle.getPositionZ());
//not allow rotation.this version not good at rotation.
//root.setRotation(cameraControle.getRagiantRotattionX(), cameraControle.getRagiantRotattionY(), cameraControle.getRagiantRotattionZ());
renderer.render(scene, camera);
if(steping){
long c=System.currentTimeMillis();
if(last+100<c){
doStep();
steped++;
if(steped==20){
steping=false;
}
last=c;
}
}
MainWidget.stats.end();
}
};
startTimer(timer);
}
long last;
private boolean steping;
int steped;
private Object3D root;
private int index=3;
private List<Object3D> joints;
private Mesh hand;
Vector3 targetPos=THREE.Vector3(0, 0, 0);
private Mesh targetMesh;
private CDDIK cddik=new CDDIK();
public void doStep(){
//Vector3 handPos=hand.getMatrixWorld().getPosition();
Vector3 handPos=THREE.Vector3().setFromMatrixPosition(hand.getMatrixWorld());
Object3D joint=joints.get(index);
//Vector3 jointPos=joint.getMatrixWorld().getPosition();
Vector3 jointPos=THREE.Vector3().setFromMatrixPosition(joint.getMatrixWorld());
//GWT.log("h0");
Matrix4 beforeRot=THREE.Matrix4();
beforeRot.makeRotationFromEuler(joint.getRotation());
//GWT.log("h1");
Matrix4 rotated=cddik.doStep(handPos, jointPos, beforeRot, targetPos);
//GWT.log("h2");
if(rotated==null){
GWT.log("rotated:null");
steping=false;
return;
}
Vector3 vec=THREE.Vector3();
vec.getRotationFromMatrix(rotated);
//log("name:"+joint.getName()+",before:"+ThreeLog.getAsDegree(joint.getRotation())+",after:"+ThreeLog.getAsDegree(vec));
joint.getRotation().set(vec.getX(), vec.getY(), vec.getZ(), Euler.XYZ);
joint.updateMatrixWorld(true);
index--;
if(index<0){
index=joints.size()-1;
}
}
@Override
public String getName() {
return "CDD-IK Bone";
}
@Override
public String getHowToHtml(){
return Bundles.INSTANCE.cdd().getText();
}
}