package edu.ohiou.cs456_badabing.sceneapi.basic;
import java.util.LinkedList;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
/**
*
Super class for all other nodes in the tree.
*
* Description: Super class for all other nodes in the tree.
*
* Copyright: Lev A Neiman 2008
*
* Company: Ohio University EECS
*
* @author Lev A Neiman
* @version 1.0
*/
public class ANode
{
/**
* how far away is this node from its parent?
*/
protected Coordinate translation;
/**
* returns translation
* @return Coordinate
*/
public synchronized Coordinate translation()
{
return translation;
}
/**
* how big is this node compared to its parent? 1.0 is same size.
*/
protected Coordinate scale;
public synchronized Coordinate scale()
{
return scale;
}
/**
* what is the vector about which this node is rotated, relative to its parent?
*/
protected Coordinate rotation;
public synchronized Coordinate rotation()
{
return rotation;
}
/**
* what is the angle of rotation about that vector?
*/
public float rotation_angle;
/**
* if display_list == -1 then we know it can't refer to valid OpenGL display list, since they cannot be negative.
*/
protected static final int no_disp_list = -1;
/**
* if this does not equal to -1 then it refers to some Display List in memory.
*/
protected int display_list = no_disp_list;
/**
* if this is true, then modelview matrix is not pushed and poped around rendering this node.
*/
protected boolean ppop;
/**
* prbl should make this private later on if i still use it.
*/
protected String name = "no name";
public synchronized String getName( )
{
return name;
}
public synchronized void setName( String name )
{
this.name = name;
}
// tree info.
/**
* References to the children nodes. Uses Java's LinkedList data structure.
*/
protected LinkedList children;
/**
* reference to the parent node.
*/
protected ANode parent; /**
*
*/
public boolean show = true;
/**
* initializes member variables to their default values.
*/
private void init( )
{
translation = new Coordinate( );
scale = new Coordinate( 1, 1, 1 );
rotation = new Coordinate( );
rotation_angle = 0;
ppop = true;
children = new LinkedList();
}
/**
* default constructor
*/
public ANode()
{
init( );
}
/**
* constructor
* @param name String - name for this node.
*/
public ANode( String name )
{
init( );
this.name = name;
}
/**
* constructor
* @param list int - display list that this node will call.
*/
public ANode( int list )
{
init( );
display_list = list;
}
/**
* add child to this node.
* @param child ANode
*/
public synchronized void addChild( ANode child )
{
children.add( child );
child.setParent( this );
}
/**
* set parent on this node.
* @param parent ANode
*/
public synchronized void setParent( ANode parent ){ this.parent = parent; }
/**
* This method should be typically called from render in all derived classes.
* This one just modifies the current ModelView matrix by this node's offset, rotation and scale.
* @param g GLAutoDrawable
*/
public void render( GLAutoDrawable g )
{
GL gl = g.getGL();
gl.glTranslated( translation.getX(), translation.getY(), translation.getZ() ); // modify current model view matrix with this translation.
gl.glScaled( scale.getX( ), scale.getY( ), scale.getZ( ) ); // scale relative to the parent.
gl.glRotated( rotation_angle, rotation.getX(), rotation.getY(), rotation.getZ() ); // rotate around rotation by rotation_angle
if( display_list != no_disp_list && show ) gl.glCallList( display_list ); // if needed, call display list.
}
public static void hideTree( ANode root )
{
if( root == null ) return;
root.show = false;
for( Object kid : root.children )
{
hideTree( (ANode)kid );
}
}
public static void showTree( ANode root )
{
if( root == null ) return;
root.show = true;
for( Object kid : root.children )
{
showTree( (ANode)kid );
}
}
/**
* This static function renders the tree with root as the root.
* @param contex GLAutoDrawable
* @param root ANode
*/
static public void renderTree( GLAutoDrawable contex, ANode root )
{
GL gl = contex.getGL();
if( root.pushPop( ) ) gl.glPushMatrix(); // push current model view matrix on the stack, if pushPop is true
root.render( contex ); // render current node. This will potentialy affect modelview matrix.
for( Object child : root.children ){ renderTree( contex, ((ANode)child) );} // render the children. Notice that modelview matrix affecting these children is modified by previous call to root.render()
if( root.pushPop( ) ) gl.glPopMatrix(); // // pop current model view matrix from the stack, if pushPop is true
}
/**
* counts the number of nodes in the tree with root as root.
* @param root ANode - root to the tree to count nodes of.
* @return int - number of nodes in root.
*/
static public int countNodes( ANode root )
{
return countNodes( root, 0 );
}
/**
* counts the number of nodes in the tree with root as root.
* @param root ANode - root to the tree to count nodes of.
* @param count int - current count.
* @return int - number of nodes in root.
*/
static private int countNodes( ANode root, int count )
{
int c = count + 1;
if( root.children.size() == 0 ) { return c; }
for( Object n : root.children )
{
c += countNodes( (ANode)n, count);
}
return c;
}
public boolean pushPop( ){ return ppop; }
public void setPushPop( boolean a ){ ppop = a; }
/**
* computes a normal between (a-c)x(b-c)
* @param a Coordinate
* @param b Coordinate
* @param c Coordinate
* @return Coordinate
*/
public static Coordinate getNormal( Coordinate a, Coordinate b, Coordinate c )
{
Coordinate tmp = new Coordinate( -c.getX(), -c.getY(), -c.getZ() );
a.add( tmp );
b.add( tmp );
double i = ( a.getY() * b.getZ() - a.getZ() * b.getY() );
double j = ( a.getX() * b.getZ() - a.getZ() * b.getX() );
double k = ( a.getX() * b.getY() - a.getY() * b.getX() );
a.add( c );
b.add( c );
Coordinate ret = new Coordinate( i, -j, k );
return ret;
}
/**
* renders a simple cube.
* @param g GLAutoDrawable
*/
public static void drawCube( GLAutoDrawable g )
{
GL gl = g.getGL();
gl.glBegin(gl.GL_QUADS); // Draw The Cube Using quads
gl.glColor3d(1.0,1.0,1.0); // Color Blue
gl.glNormal3f( 0, 1, 0 );
gl.glVertex3f( 0.5f, 0.5f,-0.5f); // Top Right Of The Quad (Top)
gl.glVertex3f(-0.5f, 0.5f,-0.5f); // Top Left Of The Quad (Top)
gl.glVertex3f(-0.5f, 0.5f, 0.5f); // Bottom Left Of The Quad (Top)
gl.glVertex3f( 0.5f, 0.5f, 0.5f); // Bottom Right Of The Quad (Top)
gl.glNormal3f( 0, -1, 0 );
gl.glColor3d(1.0,1.0,0.0); // Color Orange
gl.glVertex3f( 0.5f,-0.5f, 0.5f); // Top Right Of The Quad (Bottom)
gl.glVertex3f(-0.5f,-0.5f, 0.5f); // Top Left Of The Quad (Bottom)
gl.glVertex3f(-0.5f,-0.5f,-0.5f); // Bottom Left Of The Quad (Bottom)
gl.glVertex3f( 0.5f,-0.5f,-0.5f); // Bottom Right Of The Quad (Bottom)
gl.glNormal3f( 0, 0, 1 );
gl.glColor3f(1,0.0f,0.0f); // Color Red
gl.glVertex3f( 0.5f, 0.5f, 0.5f); // Top Right Of The Quad (Front)
gl.glVertex3f(-0.5f, 0.5f, 0.5f); // Top Left Of The Quad (Front)
gl.glVertex3f(-0.5f,-0.5f, 0.5f); // Bottom Left Of The Quad (Front)
gl.glVertex3f( 0.5f,-0.5f, 0.5f); // Bottom Right Of The Quad (Front)
gl.glNormal3f( 0, 0, -1 );
gl.glColor3d(1.0,1.0,0.0); // Color Yellow
gl.glVertex3f( 0.5f,-0.5f,-0.5f); // Top Right Of The Quad (Back)
gl.glVertex3f(-0.5f,-0.5f,-0.5f); // Top Left Of The Quad (Back)
gl.glVertex3f(-0.5f, 0.5f,-0.5f); // Bottom Left Of The Quad (Back)
gl.glVertex3f( 0.5f, 0.5f,-0.5f); // Bottom Right Of The Quad (Back)
gl.glNormal3f( -1, 0, 0 );
gl.glColor3f(0.0f,0.0f,1); // Color Blue
gl.glVertex3f(-0.5f, 0.5f, 0.5f); // Top Right Of The Quad (Left)
gl.glVertex3f(-0.5f, 0.5f,-0.5f); // Top Left Of The Quad (Left)
gl.glVertex3f(-0.5f,-0.5f,-0.5f); // Bottom Left Of The Quad (Left)
gl.glVertex3f(-0.5f,-0.5f, 0.5f); // Bottom Right Of The Quad (Left)
gl.glNormal3f( 1, 0, 0 );
gl.glColor3f(1,0.0f,1); // Color Violet
gl.glVertex3f( 0.5f, 0.5f,-0.5f); // Top Right Of The Quad (Right)
gl.glVertex3f( 0.5f, 0.5f, 0.5f); // Top Left Of The Quad (Right)
gl.glVertex3f( 0.5f,-0.5f, 0.5f); // Bottom Left Of The Quad (Right)
gl.glVertex3f( 0.5f,-0.5f,-0.5f); // Bottom Right Of The Quad (Right)
gl.glEnd(); // End Drawing The Cube
}
}