org.jtrfp.trcl.gpu.Model.java Source code

Java tutorial

Introduction

Here is the source code for org.jtrfp.trcl.gpu.Model.java

Source

/*******************************************************************************
 * This file is part of TERMINAL RECALL
 * Copyright (c) 2012-2014 Chuck Ritola
 * Part of the jTRFP.org project
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     chuck - initial API and implementation
 ******************************************************************************/
package org.jtrfp.trcl.gpu;

import java.util.ArrayList;

import javax.media.opengl.GL3;

import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.jtrfp.trcl.Controller;
import org.jtrfp.trcl.LineSegment;
import org.jtrfp.trcl.RenderMode;
import org.jtrfp.trcl.Sequencer;
import org.jtrfp.trcl.Tickable;
import org.jtrfp.trcl.TransparentTriangleList;
import org.jtrfp.trcl.Triangle;
import org.jtrfp.trcl.TriangleList;
import org.jtrfp.trcl.core.TR;
import org.jtrfp.trcl.core.TRFutureTask;
import org.jtrfp.trcl.core.TextureDescription;

public class Model {
    // [FRAME][LIST]
    private ArrayList<ArrayList<Triangle>> tLists = new ArrayList<ArrayList<Triangle>>();
    private ArrayList<ArrayList<Triangle>> ttLists = new ArrayList<ArrayList<Triangle>>();
    private ArrayList<ArrayList<LineSegment>> lsLists = new ArrayList<ArrayList<LineSegment>>();
    private TransparentTriangleList ttpList;
    private TriangleList tpList;
    private int frameDelay;
    private boolean smoothAnimation;
    private String debugName = "[unnamed]";
    private boolean animateUV = false;
    private Controller controller;
    private final TR tr;
    private long animationUpdateThresholdMillis = 0;
    private static final long ANIMATION_UPDATE_INTERVAL = 10;
    private final ArrayList<Tickable> tickableAnimators = new ArrayList<Tickable>();
    private volatile boolean animated = false;
    private boolean modelFinalized = false;

    public Model(boolean smoothAnimation, TR tr) {
        this.tr = tr;
        this.smoothAnimation = smoothAnimation;
        // Frame zero
        tLists.add(new ArrayList<Triangle>());
        lsLists.add(new ArrayList<LineSegment>());
        ttLists.add(new ArrayList<Triangle>());
    }

    public TriangleList getTriangleList() {
        return tpList;
    }

    public TransparentTriangleList getTransparentTriangleList() {
        return ttpList;
    }

    public ArrayList<ArrayList<Triangle>> getRawTriangleLists() {
        return tLists;
    }

    public ArrayList<ArrayList<Triangle>> getRawTransparentTriangleLists() {
        return ttLists;
    }

    ArrayList<ArrayList<LineSegment>> getRawLineSegmentLists() {
        return lsLists;
    }

    /**
     * Sets up formal GPU primitive lists
     * 
     * @return
     */
    public Model finalizeModel() {
        if (modelFinalized)
            return this;
        modelFinalized = true;
        if (animated)//Discard frame zero
        {
            tLists.remove(0);
            ttLists.remove(0);
        }
        Controller c = controller;
        if (c == null) {
            if (frameDelay == 0)
                frameDelay = 1;
            c = new Sequencer(getFrameDelayInMillis(), tLists.size(), true);
        }
        Triangle[][] tris = new Triangle[tLists.size()][];
        for (int i = 0; i < tLists.size(); i++) {
            tris[i] = tLists.get(i).toArray(new Triangle[] {});
        } // Get all frames for each triangle
        if (tris[0].length != 0) {
            tpList = new TriangleList(tris, getFrameDelayInMillis(), debugName, animateUV, c, tr, this);
            tpList.uploadToGPU();
        } // end if(length!=0)
        else
            tpList = null;

        Triangle[][] ttris = new Triangle[ttLists.size()][];
        for (int i = 0; i < ttLists.size(); i++) {
            ttris[i] = ttLists.get(i).toArray(new Triangle[] {});
        } // Get all frames for each triangle
        if (ttris[0].length != 0) {
            ttpList = new TransparentTriangleList(ttris, getFrameDelayInMillis(), debugName, animateUV, c, tr,
                    this);
            ttpList.uploadToGPU();
        } // end if(length!=0)
        else
            ttpList = null;
        return this;
    }// end finalizeModel()

    public void addFrame(Model m) {
        if (!animated)
            animated = true;
        // Opaque Triangles
        {
            tLists.add(m.getRawTriangleLists().get(0));
        }
        // Transparent triangles
        {
            ttLists.add(m.getRawTransparentTriangleLists().get(0));
        }
        // Line Segs
        {
            lsLists.add(m.getRawLineSegmentLists().get(0));
        }
    }// end addFrame(...)

    /**
     * 
     * @return`The time between frames in milliseconds
     * @since Jan 5, 2013
     */
    public int getFrameDelayInMillis() {
        return frameDelay;
    }

    /**
     * @param frameDelay
     *            the frameDelay to set
     */
    public void setFrameDelayInMillis(int frameDelayInMillis) {
        if (frameDelayInMillis <= 0)
            throw new IllegalArgumentException(
                    "Frame interval in millis is intolerably zero or negative: " + frameDelayInMillis);
        this.frameDelay = frameDelayInMillis;
    }

    public void addTriangle(Triangle triangle) {
        if (triangle.isAlphaBlended()) {
            ttLists.get(0).add(triangle);
        } else
            tLists.get(0).add(triangle);
    }

    public void addLineSegment(LineSegment seg) {
        lsLists.get(0).add(seg);
    }

    public void addTriangles(Triangle[] tris) {
        for (Triangle t : tris) {
            addTriangle(t);
        }
    }

    public void addLineSegments(LineSegment[] lss) {
        for (LineSegment ls : lss) {
            addLineSegment(ls);
        }
    }// end addLineSegments

    /**
     * @return the smoothAnimation
     */
    public boolean isSmoothAnimation() {
        return smoothAnimation;
    }

    /**
     * @param smoothAnimation
     *            the smoothAnimation to set
     */
    public void setSmoothAnimation(boolean smoothAnimation) {
        this.smoothAnimation = smoothAnimation;
    }

    public static Model buildCube(double w, double h, double d, TextureDescription tunnelTexturePalette,
            double[] origin, boolean hasAlpha, TR tr) {
        return buildCube(w, h, d, tunnelTexturePalette, origin, 0, 0, 1, 1, hasAlpha, tr);
    }

    public static Model buildCube(double w, double h, double d, TextureDescription tunnelTexturePalette,
            double[] origin, TR tr) {
        return buildCube(w, h, d, tunnelTexturePalette, origin, 0, 0, 1, 1, tr);
    }

    public static Model buildCube(double w, double h, double d, TextureDescription tunnelTexturePalette,
            double[] origin, double u0, double v0, double u1, double v1, TR tr) {
        return buildCube(w, h, d, tunnelTexturePalette, origin, u0, v0, u1, v1, false, tr);
    }

    public static Model buildCube(double w, double h, double d, TextureDescription tunnelTexturePalette,
            double[] origin, double u0, double v0, double u1, double v1, boolean hasAlpha, TR tr) {
        return buildCube(w, h, d, tunnelTexturePalette, origin, u0, v0, u1, v1, hasAlpha, true, tr);
    }

    public static Model buildCube(double w, double h, double d, TextureDescription tunnelTexturePalette,
            double[] origin, double u0, double v0, double u1, double v1, boolean hasAlpha, boolean hasNorm, TR tr) {
        Model m = new Model(false, tr);
        // Front
        m.addTriangles(Triangle.quad2Triangles(
                new double[] { 0 - origin[0], w - origin[0], w - origin[0], 0 - origin[0] },
                new double[] { h - origin[1], h - origin[1], 0 - origin[1], 0 - origin[1] },
                new double[] { 0 - origin[2], 0 - origin[2], 0 - origin[2], 0 - origin[2] },
                new double[] { u0, u1, u1, u0 }, new double[] { v1, v1, v0, v0 }, tunnelTexturePalette,
                RenderMode.STATIC, hasAlpha, hasNorm ? Vector3D.MINUS_K : Vector3D.ZERO, "Model.buildCube.front"));
        // Left
        m.addTriangles(Triangle.quad2Triangles(
                new double[] { 0 - origin[0], 0 - origin[0], 0 - origin[0], 0 - origin[0] },
                new double[] { h - origin[1], h - origin[1], 0 - origin[1], 0 - origin[1] },
                new double[] { 0 - origin[2], d - origin[2], d - origin[2], 0 - origin[2] },

                new double[] { u0, u1, u1, u0 }, new double[] { v1, v1, v0, v0 }, tunnelTexturePalette,
                RenderMode.STATIC, hasAlpha, hasNorm ? Vector3D.MINUS_I : Vector3D.ZERO, "Model.buildCube.left"));
        // Right
        m.addTriangles(Triangle.quad2Triangles(
                new double[] { w - origin[0], w - origin[0], w - origin[0], w - origin[0] },
                new double[] { h - origin[1], h - origin[1], 0 - origin[1], 0 - origin[1] },
                new double[] { 0 - origin[2], d - origin[2], d - origin[2], 0 - origin[2] },

                new double[] { u0, u1, u1, u0 }, new double[] { v1, v1, v0, v0 }, tunnelTexturePalette,
                RenderMode.STATIC, hasAlpha, hasNorm ? Vector3D.PLUS_I : Vector3D.ZERO, "Model.buildCube.right"));
        // Back
        m.addTriangles(Triangle.quad2Triangles(
                new double[] { 0 - origin[0], w - origin[0], w - origin[0], 0 - origin[0] },
                new double[] { 0 - origin[1], 0 - origin[1], h - origin[1], h - origin[1] },
                new double[] { d - origin[2], d - origin[2], d - origin[2], d - origin[2] },

                new double[] { u0, u1, u1, u0 }, new double[] { v0, v0, v1, v1 }, tunnelTexturePalette,
                RenderMode.STATIC, hasAlpha, hasNorm ? Vector3D.PLUS_K : Vector3D.ZERO, "Model.buildCube.back"));
        return m;
    }// end buildCube

    /**
     * @return the debugName
     */
    public String getDebugName() {
        return debugName;
    }

    /**
     * @param debugName
     *            the debugName to set
     */
    public void setDebugName(String debugName) {
        this.debugName = debugName;
    }

    /**
     * @return the animateUV
     */
    public boolean isAnimateUV() {
        return animateUV;
    }

    /**
     * @param animateUV
     *            the animateUV to set
     */
    public void setAnimateUV(boolean animateUV) {
        this.animateUV = animateUV;
    }

    /**
     * @param controller
     *            the controller to set
     */
    public void setController(Controller controller) {
        this.controller = controller;
    }

    /**
     * @return the controller
     */
    public Controller getController() {
        return controller;
    }

    public void proposeAnimationUpdate() {
        long currentTimeMillis = System.currentTimeMillis();
        if (currentTimeMillis > animationUpdateThresholdMillis) {
            synchronized (tickableAnimators) {
                final int size = tickableAnimators.size();
                for (int i = 0; i < size; i++) {
                    final Tickable t = tickableAnimators.get(i);
                    if (t != null)
                        tickableAnimators.get(i).tick();
                } //end for(animators)
                animationUpdateThresholdMillis = currentTimeMillis + ANIMATION_UPDATE_INTERVAL;
            } //end sync(tickableAnimators)
        } // end if(time to update)
    }// end proposeAnimationUpdate()

    public void addTickableAnimator(Tickable t) {
        tickableAnimators.add(t);
    }
}// end Model