/**
* 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.spatial.bodies.Classifier;
import org.xith3d.render.states.StateSortable;
import org.xith3d.scenegraph.Node;
/**
* A collection of RenderAtoms that will be prioritized and sorted for
* rendering.
*
* @author David Yazel
* @author Marvin Froehlich (aka Qudus)
*/
public final class RenderBin
{
public static final class DynamicAtomArray
{
private RenderAtom< ? >[] atoms;
private int lastSize;
private int size;
public final RenderAtom< ? >[] getRawArray()
{
return ( atoms );
}
/**
* @return the actual current size of the dynamic array
*/
public final int size()
{
return ( size );
}
/**
* Clears the array by resetting the size indicator to "0".
*/
public final void clear()
{
lastSize = size;
for ( int i = 0; i < size; i++ ) atoms[i] = null;
size = 0;
}
/**
* Ensures that all atoms ever been in the render bin are freed for garbage collection
*/
public final void cleanUp()
{
if ( lastSize <= size )
return;
//for ( int i = size; i < lastSize; i++ ) atoms[i] = null;
}
private final void ensureCapacity( int cap )
{
final int oldCapacity = atoms.length;
if ( cap > oldCapacity )
{
final RenderAtom< ? >[] oldData = atoms;
final int newCapacity = ( oldCapacity * 3 ) / 2 + 1;
atoms = new RenderAtom[ newCapacity ];
System.arraycopy( oldData, 0, atoms, 0, oldCapacity );
}
}
/**
* Appends the specified element to the array and increases the size
* indicator.
*
* @return the same given element back again (convenience)
*/
public final RenderAtom< ? > append( RenderAtom< ? > atom )
{
ensureCapacity( size + 1 );
atoms[ size ] = atom;
//atom.setLocalIndex( size );
size++;
return ( atom );
}
/**
* @param index
*
* @return the element at the specified index.
*/
public final RenderAtom< ? > get( int index )
{
//if ( index >= size )
// throw new ArrayIndexOutOfBoundsException( String.valueOf( index ) ) );
return ( atoms[ index ] );
}
public DynamicAtomArray( int initialCapacity )
{
this.atoms = new RenderAtom[ initialCapacity ];
this.size = 0;
}
}
private final RenderBinType type;
private final String name;
private final DynamicAtomArray atoms;
private int iterationPointer = 0;
public final RenderBinType getType()
{
return ( type );
}
public final String getName()
{
return ( name );
}
/**
* @return the DynamicAtomArray containing all RenderBuckets in this RenderBin.
*/
public final DynamicAtomArray getAtoms()
{
return ( atoms );
}
/**
* @return the number of currently contained RenderAtoms
*/
public final int size()
{
return ( atoms.size() );
}
/**
* Removes all Atoms from the RenderBin.
*/
public final void clear()
{
atoms.clear();
}
/**
* Removes unused atoms from the RenderBin
*/
public final void shrink()
{
atoms.cleanUp();
}
/**
* @return the RenderAtom with the specified index in the list.
*
* @param index the deserved Atom's RenderBucket's index.
*/
public final RenderAtom< ? extends Node > getAtom( int index )
{
return ( atoms.get( index ) );
}
/**
* Must be called at the beginning when the Atoms list is to be iterated.
*/
public final void resetIterationPointer()
{
iterationPointer = 0;
}
/**
* @return the next RenderAtom in the iteration.<br>
* Returns <i>null</i>, if no more atoms are available.
*/
public final RenderAtom< ? extends Node > getNextAtom()
{
if ( iterationPointer >= atoms.size() )
return ( null );
return ( atoms.get( iterationPointer++ ) );
}
/**
* Adds a RenderAtom to the chain of RenderAtoms. Atoms in this chain
* (similar to a LinkedList) will be rendered.
*
* @param atom the RenderAtom to be added
* @param classify
* @param frameId
*/
public final void addAtom( RenderAtom< ? extends Node > atom, Classifier.Classification classify, long frameId )
{
atoms.append( atom );
atom.setClassification( classify );
}
public void dump( org.xith3d.render.preprocessing.sorting.StatePriorities priorities )
{
System.out.println( "" );
RenderAtom< ? extends Node > atom;
for ( int j = 0; j < atoms.size(); j++ )
{
System.out.print( "Atom " + j + ": " );
atom = atoms.get( j );
for ( int i = 0; i < priorities.numStatePriorities; i++ )
{
StateSortable ss1 = atom.getSortableStates().map[ priorities.statePriorities[ i ] ];
if ( ss1 == null )
System.out.print( " " + priorities.statePriorities[ i ] + ":-1" );
else
{
long bid1 = atom.getSortableStates().map[ priorities.statePriorities[ i ] ].getStateId();
System.out.print( " " + priorities.statePriorities[ i ] + ":" + bid1 );
}
}
System.out.println( "" );
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString()
{
return ( this.getClass().getSimpleName() + " \"" + getName() + "\" with " + size() + " atoms" );
}
public RenderBin( RenderBinType type, String name, int initialCapacity )
{
super();
this.type = type;
this.name = name;
this.atoms = new DynamicAtomArray( initialCapacity );
}
}