Sep 7, 2014

46. Translate and Rotate

A rotation needs an axis and an angle. Here we have two rotations on two sphere objects. The two are translated by 3 x-units.




Sphere1 is blue and shown in Wireframe so the individual faces can be seen.


        // *** 1. Start (Sphere1 attached to node1)
        Sphere sph1 = new Sphere(8, 16, 1);
        Geometry geom1 = new Geometry("Sphere1", sph1);
        Material mat1 = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Blue);
        mat1.getAdditionalRenderState().setWireframe(true);
        geom1.setMaterial(mat1);
        node1.attachChild(geom1);
        // *** 1. End



Sphere2 is green and also shown in Wireframe.


        // *** 2. Start (Sphere2 attached to node2)
        Sphere sph2 = new Sphere(8, 16, 1);
        Geometry geom2 = new Geometry("Sphere2", sph2);
        Material mat2 = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat2.setColor("Color", ColorRGBA.Green);
        mat2.getAdditionalRenderState().setWireframe(true);
        geom2.setMaterial(mat2);
        node2.attachChild(geom2);
        // *** 2. End



axis1 is a red arrow at 45 degrees to +x axis in xy plane. Rotation for sphere1 is based on this axis.


        // *** 3. Start (Arrow1,+45 deg to +x axis, node1)
        Vector3f axis1 = new Vector3f(2f,2f,0f);
        Arrow arrow1 = new Arrow(axis1);
        Geometry geoArrow1 = new Geometry("geoArrow1",arrow1);
        Material matArrow1 = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        matArrow1.setColor("Color", ColorRGBA.Red);
        geoArrow1.setMaterial(matArrow1);
        node1.attachChild(geoArrow1);
        // *** 3. End



axis2 is -45 degree to +x axis in xy-plane. It will be used for axis of rotation for sphere2.


        // *** 4. Start (Arrow2,-45 deg to +x axis, node2)
        Vector3f axis2 = new Vector3f(2f,-2f,0f);
        Arrow arrow2 = new Arrow(axis2);
        Geometry geoArrow2 = new Geometry("geoArrow2",arrow2);
        Material matArrow2 = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        matArrow2.setColor("Color", ColorRGBA.Red);
        geoArrow2.setMaterial(matArrow2);
        node2.attachChild(geoArrow2);
        // *** 4. End



node2 is translated, so arrow2 and sphere2, can be clearly seen, so they are not overlapping.


        // *** 5. Start (Move node2 by 3 units right)
        node2.setLocalTranslation(3,0,0);
        // *** 5. End



Understanding Quaternion math is not necessary in using them. We use fromAngleAxis() and give the angle and axis.


        // *** 6. Start (Quaternions)
        quat1 = new Quaternion();
        quat1.fromAngleAxis(FastMath.DEG_TO_RAD, axis1);
        quat2 = new Quaternion();
        quat2.fromAngleAxis(FastMath.DEG_TO_RAD, axis2);
        // *** 6. End



In the simpleUpdate(), we rotate by 1 degree per frame for of two spheres.


        // *** 7. Start (Rotations (1 deg/frame) using Quaternions)
        node1.rotate(quat1);
        //node1.rotate(FastMath.DEG_TO_RAD,
        //FastMath.DEG_TO_RAD,0); // or this
        node2.rotate(quat2);
        //node2.rotate(FastMath.DEG_TO_RAD,
        //-FastMath.DEG_TO_RAD,0); // or this
        // *** 7. End



// JMonkey46.java

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.debug.Arrow;
import com.jme3.scene.shape.Sphere;

public class JMonkey46 extends SimpleApplication {
    public static void main(String[] args) {
        JMonkey46 app = new JMonkey46();
        app.start();
    }
    
    Quaternion quat1,quat2;
    Node node1,node2;

    @Override
    public void simpleInitApp() {
        viewPort.setBackgroundColor(ColorRGBA.White);
        flyCam.setEnabled(false);
        node1 = new Node("node1");
        node2 = new Node("node2");
        
        // *** 1. Start (Sphere1 attached to node1)
        Sphere sph1 = new Sphere(8, 16, 1);
        Geometry geom1 = new Geometry("Sphere1", sph1);
        Material mat1 = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Blue);
        mat1.getAdditionalRenderState().setWireframe(true);
        geom1.setMaterial(mat1);
        node1.attachChild(geom1);
        // *** 1. End
        
        // *** 2. Start (Sphere2 attached to node2)
        Sphere sph2 = new Sphere(8, 16, 1);
        Geometry geom2 = new Geometry("Sphere2", sph2);
        Material mat2 = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat2.setColor("Color", ColorRGBA.Green);
        mat2.getAdditionalRenderState().setWireframe(true);
        geom2.setMaterial(mat2);
        node2.attachChild(geom2);
        // *** 2. End
        
        // *** 3. Start (Arrow1,+45 deg to +x axis, node1)
        Vector3f axis1 = new Vector3f(2f,2f,0f);
        Arrow arrow1 = new Arrow(axis1);
        Geometry geoArrow1 = new Geometry("geoArrow1",arrow1);
        Material matArrow1 = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        matArrow1.setColor("Color", ColorRGBA.Red);
        geoArrow1.setMaterial(matArrow1);
        node1.attachChild(geoArrow1);
        // *** 3. End
        
        // *** 4. Start (Arrow2,-45 deg to +x axis, node2)
        Vector3f axis2 = new Vector3f(2f,-2f,0f);
        Arrow arrow2 = new Arrow(axis2);
        Geometry geoArrow2 = new Geometry("geoArrow2",arrow2);
        Material matArrow2 = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        matArrow2.setColor("Color", ColorRGBA.Red);
        geoArrow2.setMaterial(matArrow2);
        node2.attachChild(geoArrow2);
        // *** 4. End
        
        // *** 5. Start (Move node2 by 3 units right)
        node2.setLocalTranslation(3,0,0);
        // *** 5. End
        
        rootNode.attachChild(node1);
        rootNode.attachChild(node2);
        
        // *** 6. Start (Quaternions)
        quat1 = new Quaternion();
        quat1.fromAngleAxis(FastMath.DEG_TO_RAD, axis1);
        quat2 = new Quaternion();
        quat2.fromAngleAxis(FastMath.DEG_TO_RAD, axis2);
        // *** 6. End
    }

    @Override
    public void simpleUpdate(float tpf) {
        // *** 7. Start (Rotations (1 deg/frame) using Quaternions)
        node1.rotate(quat1);
        //node1.rotate(FastMath.DEG_TO_RAD,
        //FastMath.DEG_TO_RAD,0); // or this
        node2.rotate(quat2);
        //node2.rotate(FastMath.DEG_TO_RAD,
        //-FastMath.DEG_TO_RAD,0); // or this
        // *** 7. End
    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
}


Output:


Sep 6, 2014

45. Scale


A vector multiplied by a positive number results in vector in the same direction.




We use this example vector, with origin located at 0,0,0.


        // *** 1. Start (vec=x+1.5y+2z) (Blue)
        Vector3f vec = new Vector3f(1.0f,1.5f,2.0f);
        Arrow arrow = new Arrow(vec);
        arrow.setLineWidth(3);
        Geometry geoArrow = new Geometry("arrow",arrow);
        geoArrow.setMaterial(mat);
        rootNode.attachChild(geoArrow);
        // *** 1. End



We can use math functions to write the magnitude, and we can multiply the vector by the inverse of this number.


        // *** 2. Start (normalizing vector using math)
        float magnitude = FastMath.sqrt(
                vec.x*vec.x+vec.y*vec.y+vec.z*vec.z);
        Vector3f normMath = vec.mult(1f/magnitude);
        System.out.println("normMath = " + normMath);
        // *** 2. End



We could also normalize with Vector3f methods.


        // *** 3. Start (normalized vecotor) (Red)
        Vector3f vecNorm = vec.normalize();
        vec.normalizeLocal(); // In-place normalization
        System.out.print("vec = " + vec + ", vecNorm = " + vecNorm);
        Arrow arrow1 = new Arrow(vec);
        arrow1.setLineWidth(3);
        Geometry geoArrow1 = new Geometry("arrowNorm",arrow1);
        geoArrow1.setMaterial(mat1);
        rootNode.attachChild(geoArrow1);
        // *** 3. End



We create an opposite direction vector from the normalized vector.


        // *** 4. Start (Opposite) (Green)
        vec.negateLocal(); // In place negation
        Arrow arrow2 = new Arrow(vec);
        arrow2.setLineWidth(3);
        Geometry geoArrow2 = new Geometry("arrowNormNeg",arrow2);
        geoArrow2.setMaterial(mat2);
        rootNode.attachChild(geoArrow2);
        // *** 4. End



The three components (x,y,z) are shown. For the y and z arrows, we translate in either x or both x and y.


        // *** 5. Start (Components) (Yellow)
        Vector3f vecCopy = new Vector3f(1.0f,1.5f,2.0f);
        Vector3f vecX = new Vector3f(vecCopy.x,0,0); // only x
        Arrow arrowX = new Arrow(vecX); 
        arrowX.setLineWidth(2);
        Geometry geoArrowX = new Geometry("arrowX",arrowX);
        geoArrowX.setMaterial(mat3);
        rootNode.attachChild(geoArrowX);
        Vector3f vecY = new Vector3f(0,vecCopy.y,0); // only y
        Arrow arrowY = new Arrow(vecY);
        arrowY.setLineWidth(3);
        Geometry geoArrowY = new Geometry("arrowY",arrowY);
        geoArrowY.setLocalTranslation(vecX); // displaced in x
        geoArrowY.setMaterial(mat3);
        rootNode.attachChild(geoArrowY);
        Arrow arrowZ = new Arrow(new Vector3f(0,0,vecCopy.z));
        arrowZ.setLineWidth(4);
        Geometry geoArrowZ = new Geometry("arrowZ",arrowZ);
        geoArrowZ.setLocalTranslation(
                new Vector3f(
                vecCopy.x,vecCopy.y,0)); // displaced in x,y
        geoArrowZ.setMaterial(mat3);
        rootNode.attachChild(geoArrowZ);
        // *** 5. End



// JMonkey45.java

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.debug.Arrow;

public class JMonkey45 extends SimpleApplication {

    public static void main(String[] args) {
        JMonkey45 app = new JMonkey45();
        app.start();
    }
    
    @Override
    public void simpleInitApp() {
        viewPort.setBackgroundColor(ColorRGBA.LightGray);
        flyCam.setEnabled(false);
        Material mat = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Blue);
        Material mat1 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Red);
        Material mat2 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat2.setColor("Color", ColorRGBA.Green);
        Material mat3 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat3.setColor("Color", ColorRGBA.Yellow);
        
        // *** 1. Start (vec=x+1.5y+2z) (Blue)
        Vector3f vec = new Vector3f(1.0f,1.5f,2.0f);
        Arrow arrow = new Arrow(vec);
        arrow.setLineWidth(3);
        Geometry geoArrow = new Geometry("arrow",arrow);
        geoArrow.setMaterial(mat);
        rootNode.attachChild(geoArrow);
        // *** 1. End
        
        // *** 2. Start (normalizing vector using math)
        float magnitude = FastMath.sqrt(
                vec.x*vec.x+vec.y*vec.y+vec.z*vec.z);
        Vector3f normMath = vec.mult(1f/magnitude);
        System.out.println("normMath = " + normMath);
        // *** 2. End
        
        // *** 3. Start (normalized vecotor) (Red)
        Vector3f vecNorm = vec.normalize();
        vec.normalizeLocal(); // In-place normalization
        System.out.print("vec = " + vec + ", vecNorm = " + vecNorm);
        Arrow arrow1 = new Arrow(vec);
        arrow1.setLineWidth(3);
        Geometry geoArrow1 = new Geometry("arrowNorm",arrow1);
        geoArrow1.setMaterial(mat1);
        rootNode.attachChild(geoArrow1);
        // *** 3. End
        
        // *** 4. Start (Opposite) (Green)
        vec.negateLocal(); // In place negation
        Arrow arrow2 = new Arrow(vec);
        arrow2.setLineWidth(3);
        Geometry geoArrow2 = new Geometry("arrowNormNeg",arrow2);
        geoArrow2.setMaterial(mat2);
        rootNode.attachChild(geoArrow2);
        // *** 4. End
        
        // *** 5. Start (Components) (Yellow)
        Vector3f vecCopy = new Vector3f(1.0f,1.5f,2.0f);
        Vector3f vecX = new Vector3f(vecCopy.x,0,0); // only x
        Arrow arrowX = new Arrow(vecX); 
        arrowX.setLineWidth(2);
        Geometry geoArrowX = new Geometry("arrowX",arrowX);
        geoArrowX.setMaterial(mat3);
        rootNode.attachChild(geoArrowX);
        Vector3f vecY = new Vector3f(0,vecCopy.y,0); // only y
        Arrow arrowY = new Arrow(vecY);
        arrowY.setLineWidth(3);
        Geometry geoArrowY = new Geometry("arrowY",arrowY);
        geoArrowY.setLocalTranslation(vecX); // displaced in x
        geoArrowY.setMaterial(mat3);
        rootNode.attachChild(geoArrowY);
        Arrow arrowZ = new Arrow(new Vector3f(0,0,vecCopy.z));
        arrowZ.setLineWidth(4);
        Geometry geoArrowZ = new Geometry("arrowZ",arrowZ);
        geoArrowZ.setLocalTranslation(
                new Vector3f(
                vecCopy.x,vecCopy.y,0)); // displaced in x,y
        geoArrowZ.setMaterial(mat3);
        rootNode.attachChild(geoArrowZ);
        // *** 5. End
    }

    @Override
    public void simpleUpdate(float tpf) {
        rootNode.rotate(tpf,tpf,tpf);
     }

    @Override
    public void simpleRender(RenderManager rm) {
    }
}


Output: