package rajawali;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import rajawali.bounds.BoundingBox;
import rajawali.lights.ALight;
import rajawali.materials.AMaterial;
import rajawali.materials.ColorPickerMaterial;
import rajawali.materials.TextureInfo;
import rajawali.materials.TextureManager.TextureType;
import rajawali.math.Number3D;
import rajawali.util.ObjectColorPicker.ColorPickerInfo;
import rajawali.util.RajLog;
import rajawali.visitors.INode;
import rajawali.visitors.INodeVisitor;
import android.graphics.Color;
import android.opengl.GLES20;
import android.opengl.GLU;
import android.opengl.Matrix;
/**
* This is the main object that all other 3D objects inherit from.
*
* @author dennis.ippel
*
*/
public class BaseObject3D extends ATransformable3D implements Comparable<BaseObject3D>, INode {
protected float[] mMVPMatrix = new float[16];
protected float[] mMMatrix = new float[16];
protected float[] mProjMatrix;
protected float[] mScalematrix = new float[16];
protected float[] mTranslateMatrix = new float[16];
protected float[] mRotateMatrix = new float[16];
protected float[] mRotateMatrixTmp = new float[16];
protected float[] mTmpMatrix = new float[16];
protected AMaterial mMaterial;
protected List<ALight> mLights;
protected Geometry3D mGeometry;
protected List<BaseObject3D> mChildren;
protected String mName;
protected boolean mDoubleSided = false;
protected boolean mBackSided = false;
protected boolean mTransparent = false;
protected boolean mForcedDepth = false;
protected boolean mHasCubemapTexture = false;
protected boolean mIsVisible = true;
protected boolean mShowBoundingVolume = false;
protected int mDrawingMode = GLES20.GL_TRIANGLES;
protected int mElementsBufferType = GLES20.GL_UNSIGNED_INT;
protected boolean mIsContainerOnly = true;
protected int mPickingColor;
protected boolean mIsPickingEnabled = false;
protected float[] mPickingColorArray;
protected boolean mFrustumTest = false;
protected boolean mIsInFrustum;
protected boolean mRenderChildrenAsBatch = false;
protected boolean mIsPartOfBatch = false;
protected boolean mManageMaterial = true;
protected boolean mEnableBlending = false;
protected int mBlendFuncSFactor;
protected int mBlendFuncDFactor;
protected boolean mEnableDepthTest = true;
protected boolean mEnableDepthMask = true;
public BaseObject3D() {
super();
mChildren = Collections.synchronizedList(new CopyOnWriteArrayList<BaseObject3D>());
mGeometry = new Geometry3D();
mLights = Collections.synchronizedList(new CopyOnWriteArrayList<ALight>());
//Initialize the matrices to identity
Matrix.setIdentityM(mMMatrix, 0);
Matrix.setIdentityM(mScalematrix, 0);
Matrix.setIdentityM(mRotateMatrix, 0);
Matrix.setIdentityM(mRotateMatrixTmp, 0);
Matrix.setIdentityM(mTranslateMatrix, 0);
Matrix.setIdentityM(mTmpMatrix, 0);
}
public BaseObject3D(String name) {
this();
mName = name;
}
/**
* Creates a BaseObject3D from a serialized file. A serialized file can be a BaseObject3D but also a
* VertexAnimationObject3D.
*
* A serialized file can be created by the MeshExporter class. Example: <code>
Cube cube = new Cube(2);
MeshExporter exporter = new MeshExporter(cube);
exporter.export("myobject.ser", ExportType.SERIALIZED);
</code> This saves the serialized file to
* the SD card.
*
* @param ser
*/
public BaseObject3D(SerializedObject3D ser) {
this();
setData(ser);
}
/**
* Passes the data to the Geometry3D instance. Vertex Buffer Objects (VBOs) will be created.
*
* @param vertexBufferInfo
* The handle to the vertex buffer
* @param normalBufferInfo
* The handle to the normal buffer
* @param textureCoords
* A float array containing texture coordinates
* @param colors
* A float array containing color values (rgba)
* @param indices
* An integer array containing face indices
*/
public void setData(BufferInfo vertexBufferInfo, BufferInfo normalBufferInfo, float[] textureCoords,
float[] colors, int[] indices) {
mGeometry.setData(vertexBufferInfo, normalBufferInfo, textureCoords, colors, indices);
mIsContainerOnly = false;
mElementsBufferType = mGeometry.areOnlyShortBuffersSupported() ? GLES20.GL_UNSIGNED_SHORT
: GLES20.GL_UNSIGNED_INT;
}
/**
* Passes the data to the Geometry3D instance. Vertex Buffer Objects (VBOs) will be created.
*
* @param vertices
* A float array containing vertex data
* @param normals
* A float array containing normal data
* @param textureCoords
* A float array containing texture coordinates
* @param colors
* A float array containing color values (rgba)
* @param indices
* An integer array containing face indices
*/
public void setData(float[] vertices, float[] normals, float[] textureCoords, float[] colors, int[] indices) {
setData(vertices, GLES20.GL_STATIC_DRAW, normals, GLES20.GL_STATIC_DRAW, textureCoords, GLES20.GL_STATIC_DRAW,
colors, GLES20.GL_STATIC_DRAW, indices, GLES20.GL_STATIC_DRAW);
}
/**
* Passes serialized data to the Geometry3D instance. Vertex Buffer Objects (VBOs) will be created.
*
* A serialized file can be created by the MeshExporter class. Example: <code>
Cube cube = new Cube(2);
MeshExporter exporter = new MeshExporter(cube);
exporter.export("myobject.ser", ExportType.SERIALIZED);
</code> This saves the serialized file to
* the SD card.
*
* @param ser
*/
public void setData(SerializedObject3D ser) {
setData(ser.getVertices(), ser.getNormals(), ser.getTextureCoords(), ser.getColors(), ser.getIndices());
}
public void setData(float[] vertices, int verticesUsage, float[] normals, int normalsUsage, float[] textureCoords,
int textureCoordsUsage,
float[] colors, int colorsUsage, int[] indices, int indicesUsage) {
mGeometry.setData(vertices, verticesUsage, normals, normalsUsage, textureCoords, textureCoordsUsage, colors,
colorsUsage, indices, indicesUsage);
mIsContainerOnly = false;
mElementsBufferType = mGeometry.areOnlyShortBuffersSupported() ? GLES20.GL_UNSIGNED_SHORT
: GLES20.GL_UNSIGNED_INT;
}
/**
* Executed before the rendering process starts
*/
protected void preRender() {
mGeometry.validateBuffers();
}
public void render(Camera camera, float[] projMatrix, float[] vMatrix, ColorPickerInfo pickerInfo) {
render(camera, projMatrix, vMatrix, null, pickerInfo);
}
/**
* Renders the object
*
* @param camera
* The camera
* @param projMatrix
* The projection matrix
* @param vMatrix
* The view matrix
* @param parentMatrix
* This object's parent matrix
* @param pickerInfo
* The current color picker info. This is only used when an object is touched.
*/
public void render(Camera camera, float[] projMatrix, float[] vMatrix, final float[] parentMatrix,
ColorPickerInfo pickerInfo) {
if (!mIsVisible && !mRenderChildrenAsBatch)
return;
preRender();
// -- move view matrix transformation first
Matrix.setIdentityM(mMMatrix, 0);
Matrix.setIdentityM(mScalematrix, 0);
Matrix.scaleM(mScalematrix, 0, mScale.x, mScale.y, mScale.z);
Matrix.setIdentityM(mRotateMatrix, 0);
setOrientation();
if (mLookAt == null) {
mOrientation.toRotationMatrix(mRotateMatrix);
} else {
System.arraycopy(mLookAtMatrix, 0, mRotateMatrix, 0, 16);
}
Matrix.translateM(mMMatrix, 0, mPosition.x, mPosition.y, mPosition.z);
Matrix.setIdentityM(mTmpMatrix, 0);
Matrix.multiplyMM(mTmpMatrix, 0, mMMatrix, 0, mScalematrix, 0);
Matrix.multiplyMM(mMMatrix, 0, mTmpMatrix, 0, mRotateMatrix, 0);
if (parentMatrix != null) {
Matrix.multiplyMM(mTmpMatrix, 0, parentMatrix, 0, mMMatrix, 0);
System.arraycopy(mTmpMatrix, 0, mMMatrix, 0, 16);
}
Matrix.multiplyMM(mMVPMatrix, 0, vMatrix, 0, mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, projMatrix, 0, mMVPMatrix, 0);
mIsInFrustum = true; // only if mFrustrumTest == true it check frustum
if (mFrustumTest && mGeometry.hasBoundingBox()) {
BoundingBox bbox = mGeometry.getBoundingBox();
bbox.transform(mMMatrix);
if (!camera.mFrustum.boundsInFrustum(bbox)) {
mIsInFrustum = false;
}
}
if (!mIsContainerOnly && mIsInFrustum) {
mProjMatrix = projMatrix;
if (!mDoubleSided) {
GLES20.glEnable(GLES20.GL_CULL_FACE);
if (mBackSided) {
GLES20.glCullFace(GLES20.GL_FRONT);
} else {
GLES20.glCullFace(GLES20.GL_BACK);
GLES20.glFrontFace(GLES20.GL_CCW);
}
}
if (mEnableBlending && !(pickerInfo != null && mIsPickingEnabled)) {
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(mBlendFuncSFactor, mBlendFuncDFactor);
} else {
GLES20.glDisable(GLES20.GL_BLEND);
}
if (mEnableDepthTest)
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
else
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(mEnableDepthMask);
if (pickerInfo != null && mIsPickingEnabled) {
ColorPickerMaterial pickerMat = pickerInfo.getPicker().getMaterial();
pickerMat.setPickingColor(mPickingColorArray);
pickerMat.useProgram();
pickerMat.setCamera(camera);
pickerMat.setVertices(mGeometry.getVertexBufferInfo().bufferHandle);
} else {
if (!mIsPartOfBatch) {
if (mMaterial == null) {
RajLog.e("[" + this.getClass().getName()
+ "] This object can't renderer because there's no material attached to it.");
throw new RuntimeException(
"This object can't renderer because there's no material attached to it.");
}
mMaterial.useProgram();
setShaderParams(camera);
mMaterial.bindTextures();
mMaterial.setTextureCoords(mGeometry.getTexCoordBufferInfo().bufferHandle, mHasCubemapTexture);
mMaterial.setNormals(mGeometry.getNormalBufferInfo().bufferHandle);
mMaterial.setCamera(camera);
mMaterial.setVertices(mGeometry.getVertexBufferInfo().bufferHandle);
}
if (mMaterial.getUseColor())
mMaterial.setColors(mGeometry.getColorBufferInfo().bufferHandle);
}
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
if (pickerInfo == null)
{
mMaterial.setMVPMatrix(mMVPMatrix);
mMaterial.setModelMatrix(mMMatrix);
mMaterial.setViewMatrix(vMatrix);
if(mIsVisible)
{
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mGeometry.getIndexBufferInfo().bufferHandle);
GLES20.glDrawElements(mDrawingMode, mGeometry.getNumIndices(), mElementsBufferType, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
}
if (!mIsPartOfBatch && !mRenderChildrenAsBatch) {
mMaterial.unbindTextures();
}
} else if (pickerInfo != null && mIsPickingEnabled) {
ColorPickerMaterial pickerMat = pickerInfo.getPicker().getMaterial();
pickerMat.setMVPMatrix(mMVPMatrix);
pickerMat.setModelMatrix(mMMatrix);
pickerMat.setViewMatrix(vMatrix);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mGeometry.getIndexBufferInfo().bufferHandle);
GLES20.glDrawElements(mDrawingMode, mGeometry.getNumIndices(), mElementsBufferType, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
pickerMat.unbindTextures();
}
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
}
if (mShowBoundingVolume) {
if (mGeometry.hasBoundingBox())
mGeometry.getBoundingBox().drawBoundingVolume(camera, projMatrix, vMatrix, mMMatrix);
if (mGeometry.hasBoundingSphere())
mGeometry.getBoundingSphere().drawBoundingVolume(camera, projMatrix, vMatrix, mMMatrix);
}
// Draw children without frustum test
for (int i = 0, j = mChildren.size(); i < j; i++)
mChildren.get(i).render(camera, projMatrix, vMatrix, mMMatrix, pickerInfo);
if (mRenderChildrenAsBatch) {
mMaterial.unbindTextures();
}
}
/**
* Optimized version of Matrix.rotateM(). Apparently the native version does a lot of float[] allocations.
*
* @see http://groups.google.com/group/android-developers/browse_thread/thread/b30dd2a437cfb076?pli=1
*
* @param m
* The matrix
* @param mOffset
* Matrix offset
* @param a
* The angle
* @param x
* x axis
* @param y
* y axis
* @param z
* z axis
*/
protected void rotateM(float[] m, int mOffset, float a, float x, float y, float z) {
Matrix.setIdentityM(mRotateMatrixTmp, 0);
Matrix.setRotateM(mRotateMatrixTmp, 0, a, x, y, z);
System.arraycopy(m, 0, mTmpMatrix, 0, 16);
Matrix.multiplyMM(m, mOffset, mTmpMatrix, mOffset, mRotateMatrixTmp, 0);
}
/**
* This is where the parameters for the shaders are set. It is called every frame.
*
* @param camera
*/
protected void setShaderParams(Camera camera) {
mMaterial.setLightParams();
};
/**
* Adds a texture to this object
*
* @parameter textureInfo
*/
public void addTexture(TextureInfo textureInfo) {
if (mMaterial == null) {
RajLog.e("[" + getClass().getName() + "] Material is null. Please add a material before adding a texture.");
throw new RuntimeException("Material is null. Please add a material first.");
}
if (mLights.size() > 0 && textureInfo.getTextureType() != TextureType.SPHERE_MAP) {
mMaterial.setUseColor(false);
}
mMaterial.addTexture(textureInfo);
}
public void removeTexture(TextureInfo textureInfo) {
mMaterial.removeTexture(textureInfo);
}
protected void checkGlError(String op) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
RajLog.e(op + ": glError " + error + " in class " + this.getClass().getName());
throw new RuntimeException(op + ": glError " + error);
}
}
/**
* The reload method is called whenever the OpenGL context needs to be re-created. When the OpenGL context was lost,
* the vertex, uv coord, index etc data needs to be re-uploaded.
*/
public void reload() {
if (!mIsContainerOnly) {
if (mManageMaterial)
mMaterial.reload();
mGeometry.reload();
}
for (int i = 0, j = mChildren.size(); i < j; i++)
mChildren.get(i).reload();
if (mGeometry.hasBoundingBox() && mGeometry.getBoundingBox().getVisual() != null)
mGeometry.getBoundingBox().getVisual().reload();
if (mGeometry.hasBoundingSphere() && mGeometry.getBoundingSphere().getVisual() != null)
mGeometry.getBoundingSphere().getVisual().reload();
}
public void isContainer(boolean isContainer) {
mIsContainerOnly = isContainer;
}
public boolean isContainer() {
return mIsContainerOnly;
}
/**
* Maps screen coordinates to object coordinates
*
* @param x
* @param y
* @param viewportWidth
* @param viewportHeight
* @param eyeZ
*/
public void setScreenCoordinates(float x, float y, int viewportWidth, int viewportHeight, float eyeZ) {
float[] r1 = new float[16];
int[] viewport = new int[] { 0, 0, viewportWidth, viewportHeight };
float[] modelMatrix = new float[16];
Matrix.setIdentityM(modelMatrix, 0);
GLU.gluUnProject(x, viewportHeight - y, 0.0f, modelMatrix, 0, mProjMatrix, 0, viewport, 0, r1, 0);
setPosition(r1[0] * eyeZ, r1[1] * -eyeZ, 0);
}
public float[] getModelMatrix() {
return mMMatrix;
}
public boolean isDoubleSided() {
return mDoubleSided;
}
public boolean isBackSided() {
return mBackSided;
}
public boolean isVisible() {
return mIsVisible;
}
public void setDoubleSided(boolean doubleSided) {
this.mDoubleSided = doubleSided;
}
public void setBackSided(boolean backSided) {
this.mBackSided = backSided;
}
public boolean isTransparent() {
return mTransparent;
}
/**
* Use this together with the alpha channel when calling BaseObject3D.setColor(): 0xaarrggbb. So for 50% transparent
* red, set transparent to true and call: * <code>setColor(0x7fff0000);</code>
*
* @param transparent
*/
public void setTransparent(boolean value) {
this.mTransparent = value;
mEnableBlending = value;
setBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
mEnableDepthMask = !value;
}
public void setLights(List<ALight> lights) {
mLights = lights;
for (int i = 0; i < mChildren.size(); ++i)
mChildren.get(i).setLights(lights);
if (mMaterial != null)
mMaterial.setLights(mLights);
}
/**
* Adds a light to this object.
*
* @param light
*/
public void addLight(ALight light) {
mLights.add(light);
for (int i = 0; i < mChildren.size(); ++i)
mChildren.get(i).setLights(mLights);
if (mMaterial != null)
mMaterial.setLights(mLights);
}
/**
* @deprecated Use addLight() instead
* @param light
*/
@Deprecated
public void setLight(ALight light) {
addLight(light);
}
/**
* @deprecated use getLight(int index) instead
* @return
*/
@Deprecated
public ALight getLight() {
return mLights.get(0);
}
public ALight getLight(int index) {
return mLights.get(index);
}
public int getDrawingMode() {
return mDrawingMode;
}
/**
* Sets the OpenGL drawing mode. GLES20.GL_TRIANGLES is the default. Other values can be GL_LINES, GL_LINE_LOOP,
* GL_LINE_LOOP, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP
*
*
* @param drawingMode
*/
public void setDrawingMode(int drawingMode) {
this.mDrawingMode = drawingMode;
}
/**
* Compares one object's depth to another object's depth
*/
public int compareTo(BaseObject3D another) {
if (mForcedDepth)
return -1;
if (mPosition.z < another.getZ())
return 1;
else if (mPosition.z > another.getZ())
return -1;
else
return 0;
}
public void addChild(BaseObject3D child) {
mChildren.add(child);
if (mRenderChildrenAsBatch)
child.setPartOfBatch(true);
}
public boolean removeChild(BaseObject3D child) {
return mChildren.remove(child);
}
public int getNumChildren() {
return mChildren.size();
}
public BaseObject3D getChildAt(int index) {
return mChildren.get(index);
}
public BaseObject3D getChildByName(String name) {
for (int i = 0, j = mChildren.size(); i < j; i++)
if (mChildren.get(i).getName().equals(name))
return mChildren.get(i);
return null;
}
public Geometry3D getGeometry() {
return mGeometry;
}
public void setMaterial(AMaterial material) {
setMaterial(material, true);
material.setLights(mLights);
}
public AMaterial getMaterial() {
return mMaterial;
}
public void setMaterial(AMaterial material, boolean copyTextures) {
if (mMaterial != null && copyTextures)
mMaterial.copyTexturesTo(material);
else if (mMaterial != null && !copyTextures)
mMaterial.getTextureInfoList().clear();
mMaterial = null;
mMaterial = material;
}
public void setName(String name) {
mName = name;
}
public String getName() {
return mName;
}
public boolean isForcedDepth() {
return mForcedDepth;
}
public void setForcedDepth(boolean forcedDepth) {
this.mForcedDepth = forcedDepth;
}
public ArrayList<TextureInfo> getTextureInfoList() {
if (mMaterial != null) {
ArrayList<TextureInfo> ti = mMaterial.getTextureInfoList();
for (int i = 0, j = mChildren.size(); i < j; i++)
ti.addAll(mChildren.get(i).getTextureInfoList());
return ti;
}
return new ArrayList<TextureInfo>();
}
public SerializedObject3D toSerializedObject3D() {
SerializedObject3D ser = new SerializedObject3D(
mGeometry.getVertices() != null ? mGeometry.getVertices().capacity() : 0,
mGeometry.getNormals() != null ? mGeometry.getNormals().capacity() : 0,
mGeometry.getTextureCoords() != null ? mGeometry.getTextureCoords().capacity() : 0,
mGeometry.getColors() != null ? mGeometry.getColors().capacity() : 0,
mGeometry.getIndices() != null ? mGeometry.getIndices().capacity() : 0);
int i;
if (mGeometry.getVertices() != null)
for (i = 0; i < mGeometry.getVertices().capacity(); i++)
ser.getVertices()[i] = mGeometry.getVertices().get(i);
if (mGeometry.getNormals() != null)
for (i = 0; i < mGeometry.getNormals().capacity(); i++)
ser.getNormals()[i] = mGeometry.getNormals().get(i);
if (mGeometry.getTextureCoords() != null)
for (i = 0; i < mGeometry.getTextureCoords().capacity(); i++)
ser.getTextureCoords()[i] = mGeometry.getTextureCoords().get(i);
if (mGeometry.getColors() != null)
for (i = 0; i < mGeometry.getColors().capacity(); i++)
ser.getColors()[i] = mGeometry.getColors().get(i);
if (mGeometry.getIndices() != null)
{
if (!mGeometry.areOnlyShortBuffersSupported()) {
IntBuffer buff = (IntBuffer) mGeometry.getIndices();
for (i = 0; i < mGeometry.getIndices().capacity(); i++)
ser.getIndices()[i] = buff.get(i);
} else {
ShortBuffer buff = (ShortBuffer) mGeometry.getIndices();
for (i = 0; i < mGeometry.getIndices().capacity(); i++)
ser.getIndices()[i] = buff.get(i);
}
}
return ser;
}
protected void cloneTo(BaseObject3D clone, boolean copyMaterial) {
clone.getGeometry().copyFromGeometry3D(mGeometry);
clone.isContainer(mIsContainerOnly);
if (copyMaterial)
clone.setMaterial(mMaterial, false);
clone.mElementsBufferType = mGeometry.areOnlyShortBuffersSupported() ? GLES20.GL_UNSIGNED_SHORT
: GLES20.GL_UNSIGNED_INT;
clone.mTransparent = this.mTransparent;
clone.mEnableBlending = this.mEnableBlending;
clone.mBlendFuncSFactor = this.mBlendFuncSFactor;
clone.mBlendFuncDFactor = this.mBlendFuncDFactor;
clone.mEnableDepthTest = this.mEnableDepthTest;
clone.mEnableDepthMask = this.mEnableDepthMask;
}
public BaseObject3D clone(boolean copyMaterial) {
BaseObject3D clone = new BaseObject3D();
cloneTo(clone, copyMaterial);
clone.setRotation(getRotation());
clone.setScale(getScale());
return clone;
}
public BaseObject3D clone() {
return clone(true);
}
public void setVisible(boolean visible) {
mIsVisible = visible;
}
public void setColor(int color) {
setColor(color, false);
}
public void setColor(int color, boolean createNewBuffer) {
mGeometry.setColor(Color.red(color) / 255f, Color.green(color) / 255f, Color.blue(color) / 255f,
Color.alpha(color) / 255f, createNewBuffer);
if (mMaterial != null) {
mMaterial.setUseColor(true);
}
}
public void setColor(Number3D color) {
setColor(Color.rgb((int) (color.x * 255), (int) (color.y * 255), (int) (color.z * 255)));
}
public int getPickingColor() {
return mPickingColor;
}
public void setPickingColor(int pickingColor) {
if (mPickingColorArray == null)
mPickingColorArray = new float[4];
this.mPickingColor = pickingColor;
mPickingColorArray[0] = Color.red(pickingColor) / 255f;
mPickingColorArray[1] = Color.green(pickingColor) / 255f;
mPickingColorArray[2] = Color.blue(pickingColor) / 255f;
mPickingColorArray[3] = Color.alpha(pickingColor) / 255f;
mIsPickingEnabled = true;
}
public void setShowBoundingVolume(boolean showBoundingVolume) {
this.mShowBoundingVolume = showBoundingVolume;
}
public float[] getRotationMatrix() {
return mRotateMatrix;
}
public void setFrustumTest(boolean value) {
mFrustumTest = value;
}
public void accept(INodeVisitor visitor) {
visitor.apply(this);
}
public boolean isInFrustum() {
return mIsInFrustum;
}
public boolean getRenderChildrenAsBatch()
{
return mRenderChildrenAsBatch;
}
public void setRenderChildrenAsBatch(boolean renderChildrenAsBatch)
{
this.mRenderChildrenAsBatch = renderChildrenAsBatch;
}
public boolean isPartOfBatch()
{
return mIsPartOfBatch;
}
public void setPartOfBatch(boolean isPartOfBatch)
{
this.mIsPartOfBatch = isPartOfBatch;
}
public boolean getManageMaterial()
{
return mManageMaterial;
}
public void setManageMaterial(boolean manageMaterial)
{
this.mManageMaterial = manageMaterial;
}
public void setBlendingEnabled(boolean value) {
mEnableBlending = value;
}
public boolean isBlendingEnabled() {
return mEnableBlending;
}
public void setBlendFunc(int sFactor, int dFactor) {
mBlendFuncSFactor = sFactor;
mBlendFuncDFactor = dFactor;
}
public void setDepthTestEnabled(boolean value) {
mEnableDepthTest = value;
}
public boolean isDepthTestEnabled() {
return mEnableDepthTest;
}
public void setDepthMaskEnabled(boolean value) {
mEnableDepthMask = value;
}
public boolean isDepthMaskEnabled() {
return mEnableDepthMask;
}
public void destroy() {
if (mLights != null)
mLights.clear();
if (mGeometry != null)
mGeometry.destroy();
if (mMaterial != null)
mMaterial.destroy();
mLights = null;
mMaterial = null;
mGeometry = null;
for (int i = 0, j = mChildren.size(); i < j; i++)
mChildren.get(i).destroy();
mChildren.clear();
}
}