Java tutorial
package org.meanworks.engine.scene; import static org.lwjgl.opengl.GL11.GL_QUADS; import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL11.glBegin; import static org.lwjgl.opengl.GL11.glColor3f; import static org.lwjgl.opengl.GL11.glDisable; import static org.lwjgl.opengl.GL11.glEnd; import static org.lwjgl.opengl.GL11.glPopMatrix; import static org.lwjgl.opengl.GL11.glPushMatrix; import java.util.List; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Matrix4f; import org.meanworks.engine.RenderState; import org.meanworks.engine.bounding.AABoundingBox; import org.meanworks.engine.math.Transform; import org.meanworks.engine.util.QueuedLinkedList; /** * Copyright (C) 2013 Steffen Evensen * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. * * @author Meanz */ public class Node { /* * The name of the node */ private String nodeName; /* * The parent node of this node */ private Node parent; /* * The children of this node */ private QueuedLinkedList<Node> children = new QueuedLinkedList<>(); /* * Whether or not this node inherits transforms from it's parent */ private NodeInheritance nodeInheritance; /* * The culling method for this node */ private CullHint cullHint; /* * The culling box for this node */ private AABoundingBox cullingBox; /* * The transform of this node */ private Transform transform; /* * The global transform matrix of this node */ private Matrix4f globalTransform; /* * Whether something changed with this node, Calls to update all other sub * nodes. */ private boolean needsUpdate; /** * Construct a new node */ public Node(String nodeName) { this.nodeName = nodeName; cullHint = CullHint.PARENT_CULL; transform = new Transform(); nodeInheritance = NodeInheritance.INHERIT_NONE; needsUpdate = true; cullingBox = new AABoundingBox(); globalTransform = new Matrix4f(); } /** * Construct a new node */ public Node() { this("node_" + Scene.getNextNodeId()); } /** * Get the culling box of this node * * @return */ public AABoundingBox getCullingBox() { return cullingBox; } /** * Get the cull hint of this node * * @return */ public CullHint getCullHint() { return cullHint; } /** * Get the name of this node * * @return */ public String getName() { return nodeName; } /** * Get the children of this node * * @return */ public List<Node> getChildren() { return children.list(); } /** * Add a child to this node * * @param child */ public void addChild(Node child) { if (child != null) { child.setParent(this); children.add(child); } } /** * Remvoe a child from this node * * @param child */ public void removeChild(Node child) { if (child != null) { child.setParent(null); children.remove(child); } } /** * Get the parent node of this node * * @return */ public Node getParent() { return parent; } /** * Set the parent node of this node * * @param parent */ public void setParent(Node parent) { this.parent = parent; } /** * Get the transform of this node * * @return */ public Transform getTransform() { return transform; } /** * */ public void updateCullingBox() { // Pass the request down the hierarchy to see if updates are needed } /** * Get the global transform matrix for this node * * @return */ public Matrix4f getGlobalTransform() { return globalTransform; } /** * Get the transform matrix of this node */ public void calculateTransformMatrix() { if (nodeInheritance == NodeInheritance.INHERIT_NONE) { if (needsUpdate) { globalTransform = transform.getTransformMatrix(); } } else if (nodeInheritance == NodeInheritance.INHERIT_TRANSFORM) { final Node _parent = parent; if (_parent != null) { if (_parent.needsUpdate || needsUpdate) { globalTransform = Matrix4f.mul(_parent.getGlobalTransform(), transform.getTransformMatrix(), null); needsUpdate = true; } } else { globalTransform = transform.getTransformMatrix(); } } else { throw new UnsupportedOperationException("Can not handle such node inheritance yet."); } } /** * Update method called from the Application */ public final void doUpdate() { /* * Update the children list */ children.processQueues(); /* * Update transform if needed */ updateCullingBox(); /* * Check if our transform has updated */ if (transform.isChanged()) { needsUpdate = true; transform.unflagChange(); } /* * Send the transform update */ calculateTransformMatrix(); /* * Send the update request to the class that extends this node */ update(); } /** * Called after the update method */ public final void doPostUpdate() { // Unflag update flag if (needsUpdate) { needsUpdate = false; } } /** * Render method called from the Application */ public final void doRender() { // renderNodeBox(); render(); RenderState.addRenderedObject(); } /** * Update this node */ public void update() { }; /** * Render this node */ public void render() { }; /** * */ public void renderNodeBox() { glDisable(GL_TEXTURE_2D); // ImmediateRenderer.setModelMatrix(getTransformMatrix()); glPushMatrix(); final Matrix4f transf = getGlobalTransform(); GL11.glTranslatef(transf.m30, transf.m31, transf.m32); glColor3f(1.0f, 0.0f, 0.0f); glBegin(GL_QUADS); { drawCube(0.5f, 0.5f, 0.5f); } glEnd(); glColor3f(1.0f, 1.0f, 1.0f); glPopMatrix(); } public static void drawCube(float w, float h, float l) { final float minx = -(w / 2); final float miny = -(h / 2); final float minz = -(l / 2); final float maxx = (w / 2); final float maxy = (h / 2); final float maxz = (l / 2); // Quad 1 GL11.glNormal3f(1, 0, 0); GL11.glTexCoord2f(0, 1); GL11.glVertex3f(maxx, maxy, maxz); // V2 GL11.glTexCoord2f(0, 0); GL11.glVertex3f(maxx, miny, maxz); // V1 GL11.glTexCoord2f(1, 0); GL11.glVertex3f(maxx, miny, minz); // V3 GL11.glTexCoord2f(1, 1); GL11.glVertex3f(maxx, maxy, minz); // V4 // Quad 2 GL11.glNormal3f(0, 0, -1); GL11.glTexCoord2f(0, 1); GL11.glVertex3f(maxx, maxy, minz); // V4 GL11.glTexCoord2f(0, 0); GL11.glVertex3f(maxx, miny, minz); // V3 GL11.glTexCoord2f(1, 0); GL11.glVertex3f(minx, miny, minz); // V5 GL11.glTexCoord2f(1, 1); GL11.glVertex3f(minx, maxy, minz); // V6 // Quad 3 GL11.glNormal3f(-1, 0, 0); GL11.glTexCoord2f(0, 1); GL11.glVertex3f(minx, maxy, minz); // V6 GL11.glTexCoord2f(0, 0); GL11.glVertex3f(minx, miny, minz); // V5 GL11.glTexCoord2f(1, 0); GL11.glVertex3f(minx, miny, maxz); // V7 GL11.glTexCoord2f(1, 1); GL11.glVertex3f(minx, maxy, maxz); // V8 // Quad 4 GL11.glNormal3f(0, 0, 1); GL11.glTexCoord2f(0, 1); GL11.glVertex3f(minx, maxy, maxz); // V8 GL11.glTexCoord2f(0, 0); GL11.glVertex3f(minx, miny, maxz); // V7 GL11.glTexCoord2f(1, 0); GL11.glVertex3f(maxx, miny, maxz); // V1 GL11.glTexCoord2f(1, 1); GL11.glVertex3f(maxx, maxy, maxz); // V2 // Quad 5 GL11.glNormal3f(0, 1, 0); GL11.glTexCoord2f(0, 1); GL11.glVertex3f(minx, maxy, minz); // V6 GL11.glTexCoord2f(0, 0); GL11.glVertex3f(minx, maxy, maxz); // V8 GL11.glTexCoord2f(1, 0); GL11.glVertex3f(maxx, maxy, maxz); // V2 GL11.glTexCoord2f(1, 1); GL11.glVertex3f(maxx, maxy, minz); // V4 // Quad 6 GL11.glNormal3f(0, -1, 0); GL11.glTexCoord2f(0, 1); GL11.glVertex3f(minx, miny, maxz); // V7 GL11.glTexCoord2f(0, 0); GL11.glVertex3f(minx, miny, minz); // V5 GL11.glTexCoord2f(1, 0); GL11.glVertex3f(maxx, miny, minz); // V3 GL11.glTexCoord2f(1, 1); GL11.glVertex3f(maxx, miny, maxz); // V1 } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ public String toString() { return nodeName == null ? "nullNode" : nodeName; } }