/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* 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.
*
* Redistributions 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 the 'Xith3D Project Group' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.render.preprocessing;
import org.openmali.FastMath;
import org.openmali.spatial.bodies.Classifier;
import org.openmali.vecmath2.Tuple3f;
import org.xith3d.render.ClipperInfo;
import org.xith3d.render.ScissorRect;
import org.xith3d.render.states.StateSortable;
import org.xith3d.render.states.StateSortableMap;
import org.xith3d.render.states.StateUnit;
import org.xith3d.scenegraph.Node;
/**
* A render atom is a discrete chunk of geometry and shader that will be drawn.
* Render atoms are submitted to a rendering peer which is API specific.
*
* @author David Yazel
* @author Marvin Froehlich (aka Qudus)
*/
public abstract class RenderAtom< T extends Node > extends StateSortable
{
private final T node;
private final boolean hasOrderedState;
private final StateUnit[] stateUnits;
private int numStateUnits;
//private Transform3D transform;
private Classifier.Classification classify;
private float squaredDistanceToView;
private boolean hasPlainDistance = false;
private float distanceToView;
private float zValue;
@SuppressWarnings("unchecked")
private Comparable customComparable = null;
protected boolean translucent = false;
private StateSortableMap map = new StateSortableMap();
/**
* Sets the values to compare by.
*
* @param squaredDistanceToView the absolute distance to the current View.
* @param zValue the z-value of the absolute translation
* @param customComparable the custom comparable object
*/
@SuppressWarnings("unchecked")
public final void setCompareIndicators( float squaredDistanceToView, float zValue, Comparable customComparable )
{
this.squaredDistanceToView = squaredDistanceToView;
this.hasPlainDistance = false;
this.zValue = zValue;
this.customComparable = customComparable;
}
/**
* @return the absolute (squared) distance to the current View.
*/
public final float getSquaredDistanceToView()
{
return ( squaredDistanceToView );
}
/**
* @return the absolute distance to the current View.
*/
public final float getDistanceToView()
{
if ( !hasPlainDistance )
{
this.distanceToView = FastMath.sqrt( squaredDistanceToView );
this.hasPlainDistance = true;
}
return ( distanceToView );
}
/**
* @return the z-value of the absolute translation
*/
public final float getZValue()
{
return ( zValue );
}
/**
* Returns the custom comparable object.
*
* @return the custom comparable object
*/
@SuppressWarnings("unchecked")
public final Comparable getCustomComparable()
{
return ( customComparable );
}
public void setClassification( Classifier.Classification classify )
{
this.classify = classify;
}
public Classifier.Classification getClassification()
{
return ( classify );
}
/**
* Gets the position of the geometry (usually from transformed bounds
*
* @param p
*/
public abstract < Tup extends Tuple3f > Tup getPosition( Tup p );
/**
* @return the box, which is clipped using glScissor
*/
public final ScissorRect getScissorRect()
{
return ( node.getInheritedNodeAttributes().getScissorRect() );
}
/**
* @return the the ClipperInfo
*/
public final ClipperInfo getClipper()
{
return ( node.getInheritedNodeAttributes().getClipper() );
}
public final T getNode()
{
return ( node );
}
public final int getNumStateUnits()
{
return ( numStateUnits );
}
/**
* Removes all shaders from the list
*/
public void clearStateUnits()
{
numStateUnits = 0;
}
public final void updateStateMap( StateUnit stateUnit )
{
map.map[ stateUnit.getStateType() ] = stateUnit;
map.mapID[ stateUnit.getStateType() ] = stateUnit.getStateId();
map.calcHash();
}
/**
* updates a shader to the atom's list of shaders. Does not work well if
* shader changes its translucent status.
*
* @param stateUnit
*/
public void updateStateUnit( StateUnit stateUnit )
{
final StateUnit oldShader = stateUnits[ stateUnit.getStateType() ];
if ( oldShader == stateUnit )
return;
if ( oldShader == null )
{
stateUnits[ stateUnit.getStateType() ] = stateUnit;
if ( stateUnit.isTranslucent() )
translucent = true;
}
else
{
if ( oldShader.isTranslucent() != stateUnit.isTranslucent() )
{
throw new UnsupportedOperationException("Updating StateUnits that change translucent status not implemented");
}
stateUnits[ stateUnit.getStateType() ] = stateUnit;
}
updateStateMap( stateUnit );
}
public final StateSortableMap getSortableStates()
{
return ( map );
}
public final StateUnit[] getStateUnits()
{
return ( stateUnits );
}
public final StateUnit getStateUnit( int index )
{
return ( stateUnits[ index ] );
}
public boolean isTranslucent()
{
return ( translucent );
}
/**
* {@inheritDoc}
*/
@Override
public final long getStateId()
{
return ( -1L );
}
/**
* @return the ordered state for this render atom. If this is not in an
* ordered group then this returns null. The ordered state is
*/
public final OrderedState getOrderedState()
{
if ( !hasOrderedState || ( getNode() == null ) )
return ( null );
return ( getNode().getOrderedState() );
}
public RenderAtom( int stateType, T node, boolean hasOrderedState )
{
super( stateType );
this.node = node;
this.hasOrderedState = hasOrderedState;
this.stateUnits = new StateUnit[ StateUnit.MAX_STATE_TYPES ];
this.numStateUnits = 0;
updateCachedStateId();
}
}