com.akjava.gwt.threetest.client.AngleDemo.java Source code

Java tutorial

Introduction

Here is the source code for com.akjava.gwt.threetest.client.AngleDemo.java

Source

/*
 * 
 * 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.THREE;
import com.akjava.gwt.three.client.cameras.Camera;
import com.akjava.gwt.three.client.core.Matrix4;
import com.akjava.gwt.three.client.core.Object3D;
import com.akjava.gwt.three.client.core.Vector3;
import com.akjava.gwt.three.client.gwt.GWTGeometryUtils;
import com.akjava.gwt.three.client.gwt.GWTThreeUtils;
import com.akjava.gwt.three.client.gwt.ThreeLog;
import com.akjava.gwt.three.client.lights.Light;
import com.akjava.gwt.three.client.objects.Mesh;
import com.akjava.gwt.three.client.renderers.WebGLRenderer;
import com.akjava.gwt.three.client.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.CubeGeometry(.5, .5, .5), THREE.MeshBasicMaterial().color(0x0000ff).build());
        root.add(rootMesh);

        Mesh mesh1 = THREE.Mesh(THREE.CubeGeometry(1, 1, 1), THREE.MeshBasicMaterial().color(0x00ff00).build());
        mesh1.setPosition(targetPos);
        root.add(mesh1);
        root.add(GWTGeometryUtils.createLineMesh(root.getPosition(), targetPos, 0xcccccc));

        Mesh mesh2 = THREE.Mesh(THREE.CubeGeometry(.5, .5, .5), THREE.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.CubeGeometry(.5, .5, .5), THREE.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.CubeGeometry(.75, .75, .75),
                THREE.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.CubeGeometry(1, 1, 1), THREE.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.CubeGeometry(1, 1, 1), THREE.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.CubeGeometry(1, 1, 1), THREE.MeshBasicMaterial().color(0x888888).build());
        root.add(mm);
        mm.setPosition(line);

        timer = new Timer() {
            public void run() {
                root.setRotation(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();
    }
}