/* * * 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 com.akjava.gwt.three.client.java.ThreeLog; 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.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.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.FocusPanel; public class AngleDemo 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); final Scene scene=THREE.Scene(); final Camera camera=THREE.PerspectiveCamera(35,(double)width/height,.1,10000); camera.getPosition().set(0, 0, 100); scene.add(camera); Light pointLight = THREE.PointLight(0xffffff); pointLight.setPosition(0, 10, 300); scene.add(pointLight); root=THREE.Object3D(); scene.add(root); rootMesh = THREE.Mesh(THREE.BoxGeometry(.5, .5, .5), THREEDep.MeshBasicMaterial().color(0x0000ff).build()); root.add(rootMesh); Mesh mesh1=THREE.Mesh(THREE.BoxGeometry(1, 1, 1), THREEDep.MeshBasicMaterial().color(0x00ff00).build()); mesh1.setPosition(targetPos); root.add(mesh1); root.add(GWTGeometryUtils.createLineMesh(root.getPosition(), targetPos, 0xcccccc)); Mesh mesh2=THREE.Mesh(THREE.BoxGeometry(.5, .5, .5), THREEDep.MeshBasicMaterial().color(0xff0000).build()); mesh2.setPosition(jointPos); root.add(mesh2); root.add(GWTGeometryUtils.createLineMesh(root.getPosition(), jointPos, 0xcccccc)); log("joint-angle:"+ThreeLog.get(posToDegreeAngle(jointPos))); log("target-angle:"+ThreeLog.get(posToDegreeAngle(targetPos))); //DO-X double angleXJoint=Math.atan2(jointPos.getZ(),jointPos.getY()); double angleXTarget=Math.atan2(targetPos.getZ(),targetPos.getY()); log("target-angle:"+Math.toDegrees(angleXTarget)); double diffX=angleXTarget-angleXJoint; Matrix4 mxX=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(diffX, 0, 0)); Vector3 newPosX=jointPos.clone(); mxX.multiplyVector3(newPosX); Mesh meshX=THREE.Mesh(THREE.BoxGeometry(.5, .5, .5), THREEDep.MeshBasicMaterial().color(0x00ffff).build()); meshX.setPosition(newPosX); double angleXMovec=Math.atan2(newPosX.getZ(),newPosX.getY()); log("newpos-angle:"+Math.toDegrees(angleXMovec)); root.add(meshX); //root.add(GWTGeometryUtils.createLineMesh(root.getPosition(), newPosX, 0xcccccc)); log("angleX-moved:"+ThreeLog.get(posToDegreeAngle(newPosX))); //DO-Y double angleYJoint=Math.atan2(newPosX.getX(),newPosX.getZ()); double angleYTarget=Math.atan2(targetPos.getX(),targetPos.getZ()); log("target-angleY:"+Math.toDegrees(angleYTarget)); double diffY=angleYTarget-angleYJoint; Matrix4 mxY=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, diffY, 0)); Vector3 newPosY=newPosX.clone(); mxY.multiplyVector3(newPosY); Mesh meshY=THREE.Mesh(THREE.BoxGeometry(.75, .75, .75), THREEDep.MeshBasicMaterial().color(0x00ffff).build()); meshY.setPosition(newPosY); double angleYMoved=Math.atan2(newPosY.getX(),newPosY.getZ()); log("newpos-angle:"+Math.toDegrees(angleYMoved)); root.add(meshY); //root.add(GWTGeometryUtils.createLineMesh(root.getPosition(), newPosY, 0xcccccc)); log("angleY-moved:"+ThreeLog.get(posToDegreeAngle(newPosY))); //DO-Z double angleJoint=Math.atan2(newPosY.getY(), newPosY.getX()); double angleTarget=Math.atan2(targetPos.getY(), targetPos.getX()); log("target-angle:Z"+Math.toDegrees(angleTarget)); double diff=angleTarget-angleJoint; Matrix4 mx=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, 0, diff)); Vector3 newPosZ=newPosY.clone(); mx.multiplyVector3(newPosZ); Mesh meshZ=THREE.Mesh(THREE.BoxGeometry(1, 1, 1), THREEDep.MeshBasicMaterial().color(0x00ffff).build()); meshZ.setPosition(newPosZ); double angleZNew=Math.atan2(newPosZ.getY(), newPosZ.getX()); log("newpos-angle:"+Math.toDegrees(angleZNew)); root.add(meshZ); root.add(GWTGeometryUtils.createLineMesh(root.getPosition(), newPosZ, 0xcccccc)); log("angleZ-moved:"+ThreeLog.get(posToDegreeAngle(newPosZ))); Vector3 diffAngle=getTwoPointAngle(jointPos,targetPos); log("diff-angle:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(diffAngle))); Mesh meshFinal=THREE.Mesh(THREE.BoxGeometry(1, 1, 1), THREEDep.MeshBasicMaterial().color(0x333333).build()); Vector3 jAngle=getPointAngle(jointPos); log("jAngle:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(jAngle))); Vector3 finalPos=jointPos.clone(); log("final-pos:"+ThreeLog.get(finalPos)); Vector3 jointAngle=GWTThreeUtils.degreeToRagiant(posToDegreeAngle(jointPos)); log("jposAngle:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(jointAngle))); diffAngle.addSelf(jAngle); Matrix4 finalMatrix=GWTThreeUtils.rotationToMatrix4(diffAngle); log(GWTThreeUtils.rotationToMatrix4(diffAngle)); /* Matrix4 mX=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(diffAngle.getX(), 0, 0)); Matrix4 mY=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, diffAngle.getY(), 0)); Matrix4 mZ=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, 0, diffAngle.getZ())); mX.multiplySelf(mY); mX.multiplySelf(mZ); log(mX); */ //Vector3 atanAngle=getAtanAngle(jointPos,targetPos); //log("atanAngle:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(atanAngle))); //Matrix4 atanMatrix=GWTThreeUtils.rotationToMatrix4(atanAngle); finalMatrix.multiplyVector3(finalPos); meshFinal.setPosition(finalPos); //meshFinal.setRotation(GWTThreeUtils.degreeToRagiant(newAngle)); root.add(meshFinal); Vector3 mAngle=getPointAngle(targetPos); Matrix4 mmx=GWTThreeUtils.rotationToMatrix4(mAngle); Vector3 line=THREE.Vector3(0,15,0); mmx.multiplyVector3(line); Mesh mm=THREE.Mesh(THREE.BoxGeometry(1, 1, 1), THREEDep.MeshBasicMaterial().color(0x888888).build()); root.add(mm); mm.setPosition(line); timer = new Timer(){ public void run(){ root.getRotation().set(Math.toRadians(angleX),Math.toRadians(angleY),Math.toRadians(0)); renderer.render(scene, camera); } }; timer.scheduleRepeating(1000/60); } public Vector3 getAtanAngle(Vector3 jointPos,Vector3 targetPos){ //DO-X double angleXJoint=Math.atan2(jointPos.getZ(),jointPos.getY()); double angleXTarget=Math.atan2(targetPos.getZ(),targetPos.getY()); double diffX=angleXTarget-angleXJoint; Matrix4 mxX=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(diffX, 0, 0)); Vector3 newPosX=jointPos.clone(); mxX.multiplyVector3(newPosX); //DO-Y double angleYJoint=Math.atan2(jointPos.getX(),jointPos.getZ()); double angleYTarget=Math.atan2(targetPos.getX(),targetPos.getZ()); double diffY=angleYTarget-angleYJoint; Matrix4 mxY=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, diffY, 0)); Vector3 newPosY=newPosX; mxY.multiplyVector3(newPosY); //DO-Z double angleJoint=Math.atan2(jointPos.getY(), jointPos.getX()); double angleTarget=Math.atan2(targetPos.getY(), targetPos.getX()); double diffZ=angleTarget-angleJoint; Matrix4 mx=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, 0, diffZ)); Vector3 newPosZ=newPosY; mx.multiplyVector3(newPosZ); log("debug:"+ThreeLog.get(posToDegreeAngle(newPosZ))); return THREE.Vector3(diffX,diffY,diffZ); } public Vector3 getPointAngle(Vector3 jointPos){ //DO-X double angleXJoint=Math.atan2(jointPos.getZ(),jointPos.getY()); double diffX=angleXJoint; Matrix4 mxX=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(diffX, 0, 0)); Vector3 newPosX=jointPos.clone(); mxX.multiplyVector3(newPosX); //DO-Y double angleYJoint=Math.atan2(newPosX.getX(),newPosX.getZ()); double diffY=angleYJoint; Matrix4 mxY=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, diffY, 0)); Vector3 newPosY=newPosX; mxY.multiplyVector3(newPosY); //DO-Z double angleJoint=Math.atan2(newPosY.getY(), newPosY.getX()); double diffZ=angleJoint; Matrix4 mx=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, 0, diffZ)); Vector3 newPosZ=newPosY; mx.multiplyVector3(newPosZ); log("debug:"+ThreeLog.get(posToDegreeAngle(newPosZ))); return THREE.Vector3(diffX,diffY,diffZ); } /** * @param jointPos * @param targetPos * @return */ public Vector3 getTwoPointAngle(Vector3 jointPos,Vector3 targetPos){ //DO-X double angleXJoint=Math.atan2(jointPos.getZ(),jointPos.getY()); double angleXTarget=Math.atan2(targetPos.getZ(),targetPos.getY()); double diffX=angleXTarget-angleXJoint; Matrix4 mxX=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(diffX, 0, 0)); Vector3 newPosX=jointPos.clone(); mxX.multiplyVector3(newPosX); //DO-Y double angleYJoint=Math.atan2(newPosX.getX(),newPosX.getZ()); double angleYTarget=Math.atan2(targetPos.getX(),targetPos.getZ()); double diffY=angleYTarget-angleYJoint; Matrix4 mxY=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, diffY, 0)); Vector3 newPosY=newPosX; mxY.multiplyVector3(newPosY); //DO-Z double angleJoint=Math.atan2(newPosY.getY(), newPosY.getX()); double angleTarget=Math.atan2(targetPos.getY(), targetPos.getX()); double diffZ=angleTarget-angleJoint; Matrix4 mx=GWTThreeUtils.rotationToMatrix4(THREE.Vector3(0, 0, diffZ)); Vector3 newPosZ=newPosY; mx.multiplyVector3(newPosZ); log("debug:"+ThreeLog.get(posToDegreeAngle(newPosZ))); return THREE.Vector3(diffX,diffY,diffZ); } public Vector3 posToDegreeAngle(Vector3 pos){ double x=Math.atan2(pos.getZ(),pos.getY()); double y=Math.atan2(pos.getX(),pos.getZ()); double z=Math.atan2(pos.getY(),pos.getX()); return THREE.Vector3(Math.toDegrees(x),Math.toDegrees(y),Math.toDegrees(z)); } private Object3D root; Vector3 targetPos=THREE.Vector3(-12, -15, 21); Vector3 jointPos=THREE.Vector3(5, 10, 0); private Mesh rootMesh; int angleX=0; int angleY=0; @Override public void onMouseMove(MouseMoveEvent event) { if(!mouseDown){ return; } int diffX=event.getX()-mouseDownX; int diffY=event.getY()-mouseDownY; mouseDownX=event.getX(); mouseDownY=event.getY(); angleX+=diffY; angleY+=diffX; } protected boolean mouseDown; protected int mouseDownX; protected int mouseDownY; @Override public void onMouseDown(MouseDownEvent event) { mouseDown=true; mouseDownX=event.getX(); mouseDownY=event.getY(); } @Override public void onMouseUp(MouseUpEvent event) { mouseDown=false; } @Override public void onMouseOut(MouseOutEvent event) { mouseDown=false; } @Override public String getName() { return "Angle test"; } @Override public String getHowToHtml(){ return Bundles.INSTANCE.howto_default().getText(); } }