Pyramid2Cube.java Source code

Java tutorial

Introduction

Here is the source code for Pyramid2Cube.java

Source

/*
 * @(#)Pyramid2Cube.java 1.18 02/10/21 13:45:50
 * 
 * Copyright (c) 1996-2002 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *  - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *  - Redistribution in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGES.
 * 
 * You acknowledge that Software is not designed,licensed or intended for use in
 * the design, construction, operation or maintenance of any nuclear facility.
 */

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.util.Enumeration;

import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Morph;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.SimpleUniverse;

public class Pyramid2Cube extends Applet {

    private SimpleUniverse u = null;

    private BranchGroup createSceneGraph() {
        // Create the root of the branch graph
        BranchGroup objRoot = new BranchGroup();

        // Create a Transformgroup to scale all objects so they
        // appear in the scene.
        TransformGroup objScale = new TransformGroup();
        Transform3D t3d = new Transform3D();
        t3d.setScale(0.4);
        objScale.setTransform(t3d);
        objRoot.addChild(objScale);

        // Create a bounds for the background and behavior
        BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);

        // Set up the background
        Color3f bgColor = new Color3f(0.05f, 0.05f, 0.2f);
        Background bg = new Background(bgColor);
        bg.setApplicationBounds(bounds);
        objScale.addChild(bg);

        //
        // Create the transform group nodes for the 3 original objects
        // and the morphed object. Add them to the root of the
        // branch graph.
        //
        TransformGroup objTrans[] = new TransformGroup[4];

        for (int i = 0; i < 4; i++) {
            objTrans[i] = new TransformGroup();
            objScale.addChild(objTrans[i]);
        }

        Transform3D tr = new Transform3D();
        Transform3D rotY15 = new Transform3D();
        rotY15.rotY(15.0 * Math.PI / 180.0);

        objTrans[0].getTransform(tr);
        tr.setTranslation(new Vector3d(-3.0, 1.5, -6.5));
        tr.mul(rotY15);
        objTrans[0].setTransform(tr);

        objTrans[1].getTransform(tr);
        tr.setTranslation(new Vector3d(0.0, 1.5, -6.5));
        tr.mul(rotY15);
        objTrans[1].setTransform(tr);

        objTrans[2].getTransform(tr);
        tr.setTranslation(new Vector3d(3.0, 1.5, -6.5));
        tr.mul(rotY15);
        objTrans[2].setTransform(tr);

        objTrans[3].getTransform(tr);
        tr.setTranslation(new Vector3d(0.0, -2.0, -5.0));
        tr.mul(rotY15);
        objTrans[3].setTransform(tr);

        // Now create simple geometries.

        QuadArray g[] = new QuadArray[3];
        Shape3D shape[] = new Shape3D[3];
        for (int i = 0; i < 3; i++) {
            g[i] = null;
            shape[i] = null;
        }

        g[0] = new ColorPyramidUp();
        g[1] = new ColorCube();
        g[2] = new ColorPyramidDown();

        Appearance a = new Appearance();

        for (int i = 0; i < 3; i++) {
            shape[i] = new Shape3D(g[i], a);
            objTrans[i].addChild(shape[i]);
        }

        //
        // Create a Morph node, and set the appearance and input geometry
        // arrays. Set the Morph node's capability bits to allow the weights
        // to be modified at runtime.
        //
        Morph morph = new Morph((GeometryArray[]) g, a);
        morph.setCapability(Morph.ALLOW_WEIGHTS_READ);
        morph.setCapability(Morph.ALLOW_WEIGHTS_WRITE);

        objTrans[3].addChild(morph);

        // Now create the Alpha object that controls the speed of the
        // morphing operation.
        Alpha morphAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE | Alpha.DECREASING_ENABLE, 0, 0, 4000, 1000, 500,
                4000, 1000, 500);

        // Finally, create the morphing behavior
        MorphingBehavior mBeh = new MorphingBehavior(morphAlpha, morph);
        mBeh.setSchedulingBounds(bounds);
        objScale.addChild(mBeh);

        return objRoot;
    }

    public Pyramid2Cube() {
    }

    public void init() {
        setLayout(new BorderLayout());
        GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

        Canvas3D c = new Canvas3D(config);
        add("Center", c);

        // Create a simple scene and attach it to the virtual universe
        BranchGroup scene = createSceneGraph();
        u = new SimpleUniverse(c);

        // This will move the ViewPlatform back a bit so the
        // objects in the scene can be viewed.
        u.getViewingPlatform().setNominalViewingTransform();

        u.addBranchGraph(scene);
    }

    public void destroy() {
        u.cleanup();
    }

    public static void main(String[] args) {
        new MainFrame(new Pyramid2Cube(), 700, 700);
    }
}

class ColorPyramidUp extends QuadArray {
    private static final float[] verts = {
            // front face
            1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 1.0f,
            // back face
            -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f,
            // right face
            1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f,
            // left face
            -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, -1.0f,
            // top face
            0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
            // bottom face
            -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, };

    private static final float[] colors = {

            // front face (cyan)
            0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
            // back face (magenta)
            1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
            // right face (yellow)
            1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
            // left face (blue)
            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
            // top face (green)
            0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
            // bottom face (red)
            1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,

    };

    ColorPyramidUp() {
        super(24, QuadArray.COORDINATES | QuadArray.COLOR_3);

        setCoordinates(0, verts);
        setColors(0, colors);
    }
}

class ColorCube extends QuadArray {
    private static final float[] verts = {
            // front face
            1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
            // back face
            -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
            // right face
            1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
            // left face
            -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
            // top face
            1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
            // bottom face
            -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, };

    private static final float[] colors = {
            // front face (red)
            1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
            // back face (green)
            0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
            // right face (blue)
            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
            // left face (yellow)
            1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
            // top face (magenta)
            1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
            // bottom face (cyan)
            0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, };

    ColorCube() {
        super(24, QuadArray.COORDINATES | QuadArray.COLOR_3);

        setCoordinates(0, verts);
        setColors(0, colors);
    }
}

class ColorPyramidDown extends QuadArray {
    private static final float[] verts = {
            // front face
            0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
            // back face
            0.0f, -1.0f, 0.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, -1.0f, 0.0f,
            // right face
            0.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
            // left face
            0.0f, -1.0f, 0.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 0.0f, -1.0f, 0.0f,
            // top face
            1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
            // bottom face
            0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, };

    private static final float[] colors = {
            // front face (green)
            0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
            // back face (red)
            1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
            // right face (yellow)
            1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
            // left face (magenta)
            1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
            // top face (blue)
            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
            // bottom face (cyan)
            0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, };

    ColorPyramidDown() {
        super(24, QuadArray.COORDINATES | QuadArray.COLOR_3);

        setCoordinates(0, verts);
        setColors(0, colors);
    }
}

//User-defined morphing behavior class

class MorphingBehavior extends Behavior {

    Alpha alpha;

    Morph morph;

    double weights[];

    WakeupOnElapsedFrames w = new WakeupOnElapsedFrames(0);

    // Override Behavior's initialize method to setup wakeup criteria
    public void initialize() {
        alpha.setStartTime(System.currentTimeMillis());

        // Establish initial wakeup criteria
        wakeupOn(w);
    }

    // Override Behavior's stimulus method to handle the event
    public void processStimulus(Enumeration criteria) {

        // NOTE: This assumes 3 objects. It should be generalized to
        // "n" objects.

        double val = alpha.value();
        if (val < 0.5) {
            double a = val * 2.0;
            weights[0] = 1.0 - a;
            weights[1] = a;
            weights[2] = 0.0;
        } else {
            double a = (val - 0.5) * 2.0;
            weights[0] = 0.0;
            weights[1] = 1.0f - a;
            weights[2] = a;
        }

        morph.setWeights(weights);

        // Set wakeup criteria for next time
        wakeupOn(w);
    }

    public MorphingBehavior(Alpha a, Morph m) {
        alpha = a;
        morph = m;
        weights = morph.getWeights();
    }
}