Blame |
Last modification |
View Log
| RSS feed
package com.gebauz.bauzoid.graphics.renderstates;
import com.gebauz.bauzoid.app.BauzoidException;
import com.gebauz.bauzoid.math.Matrix4;
/** RenderStates
* Manage render states, tracking changes, supporting locking, and applying state switches only if necessary.
* Usage example:
* renderStates.blending.setBlendingMode(BlendingStates.BlendingMode.MULTIPLY);
* // ... set other render states
* renderStates.activate();
* // ...render object...
* renderStates.deactivate();
*
* All Render State Objects have three kinds of internal values: target, current, and default.
*
* Target values are those set by the user - those are the states the user wishes to set.
*
* Current values are those that the system is tracking, the current state. Each render state
* compares the target with the current value and only performs a state change when they differ
* to prevent unnecessary state changes.
*
* Default values are the base values that are set initially or when calling reset.
*
*/
public class RenderStates
{
public static final int NUM_TEXTURE_STAGES = 2;
public static final int MAX_VERTEX_BUFFER_ID = 8;
public BlendingStates blending = new BlendingStates(this);
public CullingStates culling = new CullingStates(this);
public DepthTestStates depthTest = new DepthTestStates(this);
public ScissorStates scissor = new ScissorStates(this);
private TextureStage[] mTextureStages = new TextureStage[NUM_TEXTURE_STAGES];
private boolean mLocked = false;
public static final int MATRIX_STACK_SIZE = 16;
//public Matrix4 modelViewProjection;
public Matrix4 model = Matrix4.createIdentity();
public Matrix4 view = Matrix4.createIdentity();
public Matrix4 projection = Matrix4.createIdentity();
private Matrix4[] mModelStack = new Matrix4[MATRIX_STACK_SIZE];
private Matrix4[] mViewStack = new Matrix4[MATRIX_STACK_SIZE];
private Matrix4[] mProjectionStack = new Matrix4[MATRIX_STACK_SIZE];
private int mModelStackCurrentIndex = 0;
private int mViewStackCurrentIndex = 0;
private int mProjectionStackCurrentIndex = 0;
/** Constructor. */
public RenderStates()
{
for (int i = 0; i < NUM_TEXTURE_STAGES; i++)
{
mTextureStages[i] = new TextureStage(this, i);
}
for (int i = 0; i < MATRIX_STACK_SIZE; i++)
{
mModelStack[i] = Matrix4.createIdentity();
mViewStack[i] = Matrix4.createIdentity();
mProjectionStack[i] = Matrix4.createIdentity();
}
}
/** Initialize render states. */
public void initialize() throws BauzoidException
{
blending.initialize();
culling.initialize();
depthTest.initialize();
scissor.initialize();
for (int i = 0; i < NUM_TEXTURE_STAGES; i++)
{
mTextureStages[i].initialize();
}
}
/** Activate renderstates - calls activate(false). */
public void activate()
{
activate(false);
}
/** Activate render states with force parameter. */
public void activate(boolean force)
{
blending.activate(force);
culling.activate(force);
depthTest.activate(force);
scissor.activate(force);
}
/** Reset to default values. */
public void reset()
{
blending.reset();
culling.reset();
depthTest.reset();
scissor.reset();
}
/** Deactivate render states. */
public void deactivate()
{
reset();
activate(false);
}
/** Check if the renderstates are locked. */
public boolean isLocked()
{
return mLocked;
}
/** Lock renderstates. */
public void lock(boolean lock)
{
mLocked = lock;
}
/** Get a texture stage. */
public final TextureStage getTextureStage(int index)
{
return mTextureStages[index];
}
/** Multiply matrices and return the full model-view-projection matrix. */
public final Matrix4 getModelViewProjection()
{
Matrix4 mvpMatrix = Matrix4.multiply(model, view);
mvpMatrix = Matrix4.multiply(mvpMatrix, projection);
return mvpMatrix;
}
public final void getModelViewProjection(Matrix4 target)
{
Matrix4.multiply(target, model, view);
Matrix4.multiply(target, target, projection);
}
/** Push current model matrix to stack. */
public final void pushModelMatrix()
{
if (mModelStackCurrentIndex >= MATRIX_STACK_SIZE)
return;
// Create copy so that calling code can work on a different matrix without affecting anything
mModelStack[mModelStackCurrentIndex].copyFrom(model);
mModelStackCurrentIndex++;
}
/** Pop current model matrix from stack. */
public final void popModelMatrix()
{
if (mModelStackCurrentIndex <= 0)
return;
mModelStackCurrentIndex--;
model.copyFrom(mModelStack[mModelStackCurrentIndex]);
}
/** Push current model matrix to stack. */
public final void pushViewMatrix()
{
if (mViewStackCurrentIndex >= MATRIX_STACK_SIZE)
return;
mViewStack[mViewStackCurrentIndex].copyFrom(view);
mViewStackCurrentIndex++;
}
/** Pop current model matrix from stack. */
public final void popViewMatrix()
{
if (mViewStackCurrentIndex <= 0)
return;
mViewStackCurrentIndex--;
view.copyFrom(mViewStack[mViewStackCurrentIndex]);
}
/** Push current model matrix to stack. */
public final void pushProjectionMatrix()
{
if (mProjectionStackCurrentIndex >= MATRIX_STACK_SIZE)
return;
mProjectionStack[mProjectionStackCurrentIndex].copyFrom(projection);
mProjectionStackCurrentIndex++;
}
/** Pop current model matrix from stack. */
public final void popProjectionMatrix()
{
if (mProjectionStackCurrentIndex <= 0)
return;
mProjectionStackCurrentIndex--;
projection.copyFrom(mProjectionStack[mProjectionStackCurrentIndex]);
}
}