javax.media.j3d.GeometryArrayRetained Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java3d-core Show documentation
Show all versions of java3d-core Show documentation
Java3D Core And Java3D Util Libraries
The newest version!
/*
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
package javax.media.j3d;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import javax.vecmath.Color3b;
import javax.vecmath.Color3f;
import javax.vecmath.Color4b;
import javax.vecmath.Color4f;
import javax.vecmath.Point2d;
import javax.vecmath.Point2f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Point4d;
import javax.vecmath.Point4f;
import javax.vecmath.TexCoord2f;
import javax.vecmath.TexCoord3f;
import javax.vecmath.TexCoord4f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;
/**
* The GeometryArray object contains arrays of positional coordinates,
* colors, normals and/or texture coordinates that describe
* point, line, or surface geometry. It is extended to create
* the various primitive types (e.g., lines, triangle_strips, etc.)
*/
abstract class GeometryArrayRetained extends GeometryRetained{
// XXXX: Memory footprint reduction. Should have separate object to
// to contain specific data such as a ByRef object for
// all ByRef related data. So that incases where no
// ByRef is needed, the ByRef object reference is
// set to null. Hence saving memory!
// Need object such as Texture, D3d and ByRef ...
//
// Contains a bitset indicating which components are present
int vertexFormat;
// Whether this geometry was ever rendered as transparent
int c4fAllocated = 0;
// Total Number of vertices
int vertexCount;
// number of vertices used in rendering
int validVertexCount;
// The vertex data in packed format
float vertexData[];
// vertex data in packed format for each screen in multi-screen situation
// if alpha values of each vertex are to be updated
private float mvertexData[][];
//
// The following offset/stride values are internally computed
// from the format
//
// Stride (in words) from one vertex to the next
int stride;
// Stride (in words) from one texture coordinate to the next
int texCoordStride;
// Offset (in words) within each vertex of the coordinate position
int coordinateOffset;
// Offset (in words) within each vertex of the normal
int normalOffset;
// Offset (in words) within each vertex of the color
int colorOffset;
// Offset (in words) within each vertex of the texture coordinate
int textureOffset;
// Offset (in words) within each vertex of each vertex attribute
int[] vertexAttrOffsets;
// Stride (size) of all vertex attributes
int vertexAttrStride;
// alpha value for transparency and texture blending
private float[] lastAlpha = new float[1];
float lastScreenAlpha = -1;
int colorChanged = 0;
// byte to float scale factor
static final float ByteToFloatScale = 1.0f/255.0f;
// float to byte scale factor
static final float FloatToByteScale = 255.0f;
// Set flag indicating that we are in the updater. This flag
// can be used by the various setRef methods to inhibit any
// update messages
boolean inUpdater = false;
// Array List used for messages
ArrayList gaList = new ArrayList(1);
// Target threads to be notified when morph changes
static final int targetThreads = (J3dThread.UPDATE_RENDER |
J3dThread.UPDATE_GEOMETRY);
// used for byReference geometry
float[] floatRefCoords = null;
double[] doubleRefCoords = null;
Point3d[] p3dRefCoords = null;
Point3f[] p3fRefCoords = null;
// Used for NIO buffer geometry
J3DBuffer coordRefBuffer = null;
FloatBuffer floatBufferRefCoords = null;
DoubleBuffer doubleBufferRefCoords = null;
// Initial index to use for rendering
int initialCoordIndex = 0;
int initialColorIndex = 0;
int initialNormalIndex = 0;
int[] initialTexCoordIndex = null;
int[] initialVertexAttrIndex = null;
int initialVertexIndex = 0;
// used for byReference colors
float[] floatRefColors = null;
byte[] byteRefColors = null;
Color3f[] c3fRefColors = null;
Color4f[] c4fRefColors = null;
Color3b[] c3bRefColors = null;
Color4b[] c4bRefColors = null;
// Used for NIO buffer colors
J3DBuffer colorRefBuffer = null;
FloatBuffer floatBufferRefColors = null;
ByteBuffer byteBufferRefColors = null;
// flag to indicate if the "by reference" component is already set
int vertexType = 0;
static final int PF = 0x1;
static final int PD = 0x2;
static final int P3F = 0x4;
static final int P3D = 0x8;
static final int VERTEX_DEFINED = PF | PD | P3F | P3D;
static final int CF = 0x10;
static final int CUB = 0x20;
static final int C3F = 0x40;
static final int C4F = 0x80;
static final int C3UB = 0x100;
static final int C4UB = 0x200;
static final int COLOR_DEFINED = CF | CUB | C3F | C4F| C3UB | C4UB;
static final int NF = 0x400;
static final int N3F = 0x800;
static final int NORMAL_DEFINED = NF | N3F;
static final int TF = 0x1000;
static final int T2F = 0x2000;
static final int T3F = 0x4000;
static final int TEXCOORD_DEFINED = TF | T2F | T3F;
static final int AF = 0x8000;
static final int VATTR_DEFINED = AF;
// Flag word indicating the type of by-ref texCoord. We will copy this to
// the vertexType field only when the references for all texture coordinate
// sets are set to non-null values.
private int texCoordType = 0;
// Flag word indicating the type of by-ref vertex attr. We will copy this to
// the vertexType field only when the references for all vertex attrs
// are set to non-null values.
private int vertexAttrType = 0;
// flag for execute geometry array when by reference
static final int COORD_FLOAT = 0x01;
static final int COORD_DOUBLE = 0x02;
static final int COLOR_FLOAT = 0x04;
static final int COLOR_BYTE = 0x08;
static final int NORMAL_FLOAT = 0x10;
static final int TEXCOORD_FLOAT = 0x20;
static final int VATTR_FLOAT = 0x40;
// used by "by reference" normals
float[] floatRefNormals = null;
Vector3f[] v3fRefNormals = null;
// Used for NIO buffer normals
J3DBuffer normalRefBuffer = null;
FloatBuffer floatBufferRefNormals = null;
// used for "by reference" vertex attrs
float[][] floatRefVertexAttrs = null;
// Used for NIO buffer vertex attrs
J3DBuffer[] vertexAttrsRefBuffer = null;
FloatBuffer[] floatBufferRefVertexAttrs = null;
// used by "by reference" tex coords
Object[] refTexCoords = null;
TexCoord2f[] t2fRefTexCoords = null;
TexCoord3f[] t3fRefTexCoords = null;
// Used for NIO buffer tex coords
J3DBuffer[] refTexCoordsBuffer = null;
//FloatBufferWrapper[] floatBufferRefTexCoords = null;
// used by interleaved array
float[] interLeavedVertexData = null;
// used by interleaved NIO buffer
J3DBuffer interleavedVertexBuffer = null;
FloatBuffer interleavedFloatBufferImpl = null;
// pointers used, when transparency is turned on
// or when its an object such as C3F, P3F etc ..
float[] mirrorFloatRefCoords = null;
double[] mirrorDoubleRefCoords = null;
float[] mirrorFloatRefNormals = null;
float[][] mirrorFloatRefVertexAttrs = null;
float[] mirrorFloatRefTexCoords = null;
Object[] mirrorRefTexCoords = null;
float[][] mirrorFloatRefColors = new float[1][];
byte[][] mirrorUnsignedByteRefColors= new byte[1][];
float[][] mirrorInterleavedColorPointer = null;
// boolean to determine if a mirror was allocated
int mirrorVertexAllocated = 0;
int mirrorColorAllocated = 0;
boolean mirrorNormalAllocated = false;
// Some dirty bits for GeometryArrays
static final int COORDINATE_CHANGED = 0x01;
static final int NORMAL_CHANGED = 0x02;
static final int COLOR_CHANGED = 0x04;
static final int TEXTURE_CHANGED = 0x08;
static final int BOUNDS_CHANGED = 0x10;
static final int INDEX_CHANGED = 0x20;
static final int STRIPCOUNT_CHANGED = 0x40;
static final int VATTR_CHANGED = 0x80;
static final int VERTEX_CHANGED = COORDINATE_CHANGED |
NORMAL_CHANGED |
COLOR_CHANGED |
TEXTURE_CHANGED |
VATTR_CHANGED;
static final int defaultTexCoordSetMap[] = {0};
int texCoordSetCount = 0;
int [] texCoordSetMap = null;
// this array contains offset to the texCoord data for each
// texture unit. -1 means no corresponding texCoord data offset
int [] texCoordSetMapOffset = null;
// Vertex attribute information
int vertexAttrCount = 0;
int[] vertexAttrSizes = null;
// This point to a list of VertexBuffers in a Vector structure
// Each element correspond to a D3D context that create this VB.
// Note that this GeometryArray can be used by multiple ctx.
int dirtyFlag;
// each bit corresponds to a unique renderer if shared context
// or a unique canvas otherwise
int resourceCreationMask = 0x0;
// Fix for Issue 5
//
// Replace the per-canvas reference count with a per-RenderBin set
// of users. The per-RenderBin set of users of this display list
// is defined as a HashMap where:
//
// key = the RenderBin
// value = a set of RenderAtomListInfo objects using this
// geometry array for display list purposes
private HashMap> dlistUsers = null;
// timestamp used to create display list. This is either
// one per renderer for useSharedCtx, or one per Canvas for non-shared
// ctx
private long[] timeStampPerDlist = new long[2];
// Unique display list Id, if this geometry is shared
int dlistId = -1;
Integer dlistObj = null;
// A list of pre-defined bits to indicate which component
// in this Texture object changed.
// static final int DLIST_CREATE_CHANGED = 0x01;
static final int INIT_MIRROR_GEOMETRY = 0x02;
// A list of Universes that this Geometry is referenced in Morph from
ArrayList morphUniverseList = null;
// A list of ArrayLists which contain all the MorphRetained objects
// refering to this geometry. Each list corresponds to the universe
// above.
ArrayList> morphUserLists = null;
// The following variables are only used in compile mode
// Offset of a geometry array into the merged array
int[] geoOffset;
// vertexcount of a geometry array in a merge array
int[] compileVcount;
boolean isCompiled = false;
boolean isShared = false;
IndexedGeometryArrayRetained cloneSourceArray = null;
static final double EPS = 1.0e-13;
GeometryArrayRetained() {
dirtyFlag = INDEX_CHANGED|VERTEX_CHANGED;
lastAlpha[0] = 1.0f;
}
@Override
void setLive(boolean inBackgroundGroup, int refCount) {
dirtyFlag = VERTEX_CHANGED|INDEX_CHANGED;
isEditable = !isWriteStatic();
super.doSetLive(inBackgroundGroup, refCount);
super.markAsLive();
// Send message to RenderingAttribute structure to obtain a dlistId
// System.err.println("Geometry - "+this+"refCount = "+this.refCount);
if (this.refCount > 1) {
// Send to rendering attribute structure,
/*
J3dMessage createMessage = new J3dMessage();
createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
createMessage.type = J3dMessage.GEOMETRYARRAY_CHANGED;
createMessage.universe = null;
createMessage.args[0] = this;
createMessage.args[1]= new Integer(DLIST_CREATE_CHANGED);
VirtualUniverse.mc.processMessage(createMessage);
*/
isShared = true;
} // Clone geometry only for the first setLive
else {
// If geometry is indexed and use_index_coord is false, unindexify
// otherwise, set mirrorGeometry to null (from previous clearLive)
if (this instanceof IndexedGeometryArrayRetained) {
// Send to rendering attribute structure,
J3dMessage createMessage = new J3dMessage();
createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
createMessage.type = J3dMessage.GEOMETRY_CHANGED;
createMessage.universe = null;
createMessage.args[0] = null;
createMessage.args[1]= this;
createMessage.args[2]= new Integer(INIT_MIRROR_GEOMETRY);
VirtualUniverse.mc.processMessage(createMessage);
}
}
}
@Override
void clearLive(int refCount) {
super.clearLive(refCount);
if (this.refCount <= 0) {
isShared = false;
}
}
@Override
void computeBoundingBox() {
// System.err.println("computeBoundingBox ....");
if (boundsDirty && VirtualUniverse.mc.cacheAutoComputedBounds) {
for(ArrayList users : userLists) {
for(Shape3DRetained shape : users)
shape.dirtyBoundsCache();
}
}
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
// by copy
computeBoundingBox(initialVertexIndex, vertexData);
} else if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { // USE_NIO_BUFFER
//System.err.println("vertexFormat & GeometryArray.USE_NIO_BUFFER");
if((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
computeBoundingBox(initialCoordIndex, interleavedFloatBufferImpl);
} else if((vertexType & PF) != 0) {
computeBoundingBox(floatBufferRefCoords);
} else if((vertexType & PD) != 0) {
computeBoundingBox(doubleBufferRefCoords);
}
} else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
//System.err.println("vertexFormat & GeometryArray.INTERLEAVED");
computeBoundingBox(initialCoordIndex, interLeavedVertexData);
} else if ((vertexType & PF) != 0) {
//System.err.println("vertexType & PF");
computeBoundingBox(floatRefCoords);
} else if ((vertexType & P3F) != 0) {
//System.err.println("vertexType & P3F");
computeBoundingBox(p3fRefCoords);
} else if ((vertexType & P3D) != 0) {
//System.err.println("vertexType & P3D");
computeBoundingBox(p3dRefCoords);
} else if ((vertexType & PD) != 0) {
//System.err.println("vertexType & PD");
computeBoundingBox(doubleRefCoords);
}
}
// NullGeometry is true only for byRef case
void processCoordsChanged(boolean nullGeo) {
/*
System.err.println("processCoordsChanged : nullGeo " + nullGeo);
System.err.println("Before :processCoordsChanged : geoBounds ");
System.err.println(geoBounds);
*/
if (nullGeo) {
synchronized(geoBounds) {
geoBounds.setLower(-1.0, -1.0, -1.0);
geoBounds.setUpper(1.0, 1.0, 1.0);
boundsDirty = false;
}
synchronized(centroid) {
recompCentroid = false;
geoBounds.getCenter(this.centroid);
}
}
else {
// re-compute centroid if used
synchronized(centroid) {
recompCentroid = true;
}
synchronized(geoBounds) {
boundsDirty = true;
computeBoundingBox();
}
/*
System.err.println("After :processCoordsChanged : geoBounds ");
System.err.println(geoBounds);
*/
}
}
void computeBoundingBox(int vIndex, float[] vdata) {
int i, offset;
double xmin, xmax, ymin, ymax, zmin, zmax;
//System.err.println("Before : computeBoundingBox : geoBounds ");
// System.err.println(geoBounds);
synchronized(geoBounds) {
// If autobounds compute is false then return
// It is possible that user call getBounds() before
// this Geometry add to live scene graph.
if ((computeGeoBounds == 0) && (refCount > 0)) {
return;
}
if (!boundsDirty)
return;
// Initial offset
offset = vIndex * stride+coordinateOffset;
// Compute the bounding box
xmin = xmax = vdata[offset];
ymin = ymax = vdata[offset+1];
zmin = zmax = vdata[offset+2];
offset += stride;
for (i=1; i xmax)
xmax = vdata[offset];
if (vdata[offset] < xmin)
xmin = vdata[offset];
if (vdata[offset+1] > ymax)
ymax = vdata[offset+1];
if (vdata[offset+1] < ymin)
ymin = vdata[offset+1];
if (vdata[offset+2] > zmax)
zmax = vdata[offset+2];
if (vdata[offset+2] < zmin)
zmin = vdata[offset+2];
offset += stride;
}
geoBounds.setUpper(xmax, ymax, zmax);
geoBounds.setLower(xmin, ymin, zmin);
boundsDirty = false;
}
/*
System.err.println("After : computeBoundingBox : geoBounds ");
System.err.println(geoBounds);
*/
}
// Compute boundingbox for interleaved nio buffer
void computeBoundingBox(int vIndex, FloatBuffer vdata) {
int i, offset;
double xmin, xmax, ymin, ymax, zmin, zmax;
synchronized(geoBounds) {
// If autobounds compute is false then return
if ((computeGeoBounds == 0) && (refCount > 0)) {
return;
}
if (!boundsDirty)
return;
// Initial offset
offset = vIndex * stride+coordinateOffset;
// Compute the bounding box
xmin = xmax = vdata.get(offset);
ymin = ymax = vdata.get(offset+1);
zmin = zmax = vdata.get(offset+2);
offset += stride;
for (i=1; i xmax)
xmax = vdata.get(offset);
if (vdata.get(offset) < xmin)
xmin = vdata.get(offset);
if (vdata.get(offset+1) > ymax)
ymax = vdata.get(offset+1);
if (vdata.get(offset+1) < ymin)
ymin = vdata.get(offset+1);
if (vdata.get(offset+2) > zmax)
zmax = vdata.get(offset+2);
if (vdata.get(offset+2) < zmin)
zmin = vdata.get(offset+2);
offset += stride;
}
geoBounds.setUpper(xmax, ymax, zmax);
geoBounds.setLower(xmin, ymin, zmin);
boundsDirty = false;
}
}
// compute bounding box for coord with nio buffer
void computeBoundingBox( DoubleBuffer buffer) {
int i, j, k, sIndex;
double xmin, xmax, ymin, ymax, zmin, zmax;
synchronized(geoBounds) {
// If autobounds compute is false then return
if ((computeGeoBounds == 0) && (refCount > 0)) {
return;
}
if (!boundsDirty)
return;
sIndex = initialCoordIndex;
int maxIndex = 3*validVertexCount;
// Compute the bounding box
xmin = xmax = buffer.get(sIndex++);
ymin = ymax = buffer.get(sIndex++);
zmin = zmax = buffer.get(sIndex++);
for (i=sIndex; i xmax)
xmax = buffer.get(i);
if (buffer.get(i) < xmin)
xmin = buffer.get(i);
if (buffer.get(j) > ymax)
ymax = buffer.get(j);
if (buffer.get(j) < ymin)
ymin = buffer.get(j);
if (buffer.get(k) > zmax)
zmax = buffer.get(k);
if (buffer.get(k) < zmin)
zmin = buffer.get(k);
}
geoBounds.setUpper(xmax, ymax, zmax);
geoBounds.setLower(xmin, ymin, zmin);
boundsDirty = false;
}
}
// compute bounding box for coord with nio buffer
void computeBoundingBox( FloatBuffer buffer) {
int i, j, k, sIndex;
double xmin, xmax, ymin, ymax, zmin, zmax;
synchronized(geoBounds) {
// If autobounds compute is false then return
if ((computeGeoBounds == 0) && (refCount > 0)) {
return;
}
if (!boundsDirty)
return;
sIndex = initialCoordIndex;
int maxIndex = 3*validVertexCount;
// Compute the bounding box
xmin = xmax = buffer.get(sIndex++);
ymin = ymax = buffer.get(sIndex++);
zmin = zmax = buffer.get(sIndex++);
for (i=sIndex; i xmax)
xmax = buffer.get(i);
if (buffer.get(i) < xmin)
xmin = buffer.get(i);
if (buffer.get(j) > ymax)
ymax = buffer.get(j);
if (buffer.get(j) < ymin)
ymin = buffer.get(j);
if (buffer.get(k) > zmax)
zmax = buffer.get(k);
if (buffer.get(k) < zmin)
zmin = buffer.get(k);
}
geoBounds.setUpper(xmax, ymax, zmax);
geoBounds.setLower(xmin, ymin, zmin);
boundsDirty = false;
}
}
void computeBoundingBox(float[] coords) {
// System.err.println("GeometryArrayRetained : computeBoundingBox(float[] coords)");
int i, j, k, sIndex;
double xmin, xmax, ymin, ymax, zmin, zmax;
synchronized(geoBounds) {
// If autobounds compute is false then return
if ((computeGeoBounds == 0) && (refCount > 0)) {
return;
}
if (!boundsDirty)
return;
sIndex = initialCoordIndex;
int maxIndex = 3*validVertexCount;
// Compute the bounding box
xmin = xmax = coords[sIndex++];
ymin = ymax = coords[sIndex++];
zmin = zmax = coords[sIndex++];
for (i=sIndex; i xmax)
xmax = coords[i];
if (coords[i] < xmin)
xmin = coords[i];
if (coords[j] > ymax)
ymax = coords[j];
if (coords[j] < ymin)
ymin = coords[j];
if (coords[k] > zmax)
zmax = coords[k];
if (coords[k] < zmin)
zmin = coords[k];
}
geoBounds.setUpper(xmax, ymax, zmax);
// System.err.println("max(" + xmax + ", " + ymax + ", " + zmax + ")");
geoBounds.setLower(xmin, ymin, zmin);
// System.err.println("min(" + xmin + ", " + ymin + ", " + zmin + ")");
boundsDirty = false;
}
}
void computeBoundingBox(double[] coords) {
int i, j, k, sIndex;
double xmin, xmax, ymin, ymax, zmin, zmax;
synchronized(geoBounds) {
// If autobounds compute is false then return
if ((computeGeoBounds == 0) && (refCount > 0)) {
return;
}
if (!boundsDirty)
return;
sIndex = initialCoordIndex;
int maxIndex = 3*validVertexCount;
// Compute the bounding box
xmin = xmax = coords[sIndex++];
ymin = ymax = coords[sIndex++];
zmin = zmax = coords[sIndex++];
for (i=sIndex; i xmax)
xmax = coords[i];
if (coords[i] < xmin)
xmin = coords[i];
if (coords[j] > ymax)
ymax = coords[j];
if (coords[j] < ymin)
ymin = coords[j];
if (coords[k] > zmax)
zmax = coords[k];
if (coords[k] < zmin)
zmin = coords[k];
}
geoBounds.setUpper(xmax, ymax, zmax);
geoBounds.setLower(xmin, ymin, zmin);
boundsDirty = false;
}
}
void computeBoundingBox(Point3f[] coords) {
double xmin, xmax, ymin, ymax, zmin, zmax;
Point3f p;
synchronized(geoBounds) {
// If autobounds compute is false then return
if ((computeGeoBounds == 0) && (refCount > 0)) {
return;
}
if (!boundsDirty)
return;
// Compute the bounding box
xmin = xmax = coords[initialCoordIndex].x;
ymin = ymax = coords[initialCoordIndex].y;
zmin = zmax = coords[initialCoordIndex].z;
for (int i=initialCoordIndex+1; i xmax) xmax = p.x;
if (p.x < xmin) xmin = p.x;
if (p.y > ymax) ymax = p.y;
if (p.y < ymin) ymin = p.y;
if (p.z > zmax) zmax = p.z;
if (p.z < zmin) zmin = p.z;
}
geoBounds.setUpper(xmax, ymax, zmax);
geoBounds.setLower(xmin, ymin, zmin);
boundsDirty = false;
}
}
void computeBoundingBox(Point3d[] coords) {
double xmin, xmax, ymin, ymax, zmin, zmax;
Point3d p;
synchronized(geoBounds) {
// If autobounds compute is false then return
if ((computeGeoBounds == 0) && (refCount > 0)) {
return;
}
if (!boundsDirty)
return;
// Compute the bounding box
xmin = xmax = coords[initialCoordIndex].x;
ymin = ymax = coords[initialCoordIndex].y;
zmin = zmax = coords[initialCoordIndex].z;
for (int i=initialCoordIndex+1; i xmax) xmax = p.x;
if (p.x < xmin) xmin = p.x;
if (p.y > ymax) ymax = p.y;
if (p.y < ymin) ymin = p.y;
if (p.z > zmax) zmax = p.z;
if (p.z < zmin) zmin = p.z;
}
geoBounds.setUpper(xmax, ymax, zmax);
geoBounds.setLower(xmin, ymin, zmin);
boundsDirty = false;
}
}
@Override
synchronized void update() {
}
void setupMirrorVertexPointer(int vType) {
int i, index;
switch (vType) {
case PF:
if (floatRefCoords == null) {
if ((vertexType & VERTEX_DEFINED) == PF) {
vertexType &= ~PF;
mirrorFloatRefCoords = null;
mirrorVertexAllocated &= ~PF;
}
}
else {
vertexType |= PF;
mirrorFloatRefCoords = floatRefCoords;
mirrorVertexAllocated &= ~PF;
}
break;
case PD:
if (doubleRefCoords == null) {
if ((vertexType & VERTEX_DEFINED) == PD) {
mirrorDoubleRefCoords = null;
mirrorVertexAllocated &= ~PD;
vertexType &= ~PD;
}
vertexType &= ~PD;
}
else {
vertexType |= PD;
mirrorDoubleRefCoords = doubleRefCoords;
mirrorVertexAllocated &= ~PD;
}
break;
case P3F:
if (p3fRefCoords == null) {
vertexType &= ~P3F;
// Don't set the mirrorFloatRefCoords to null,
// may be able to re-use
// mirrorFloatRefCoords = null;
}
else {
vertexType |= P3F;
if ((mirrorVertexAllocated & PF) == 0) {
mirrorFloatRefCoords = new float[vertexCount * 3];
mirrorVertexAllocated |= PF;
}
index = initialCoordIndex * 3;
for ( i=initialCoordIndex; i= 0.0;
/*
System.err.println("updateAlphaInFloatRefColors ** : lastAlpha[screen] " +
lastAlpha[screen]);
System.err.println("((colorChanged & (1<= 0.0;
/*
System.err.println("updateAlphaInByteRefColors ## : lastAlpha[screen] " +
lastAlpha[screen]);
System.err.println("((colorChanged & (1< 0) {
for (int i = oldSize; i < screen+1; i++) {
cfData[i] = new float[stride * vertexCount];
System.arraycopy(cfData[0], 0, cfData[i], 0,
stride * vertexCount);
lastAlpha[i] = lastAlpha[0];
}
}
mvertexData = cfData;
// Issue 113 - since we copied the data from screen 0, we don't need
// to do any further special processing.
}
assert lastAlpha[screen] >= 0.0;
if ((colorChanged & (1<= 0.0;
if ((colorChanged & (1<= 0 implies one pass for one texture unit state
@Override
void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
boolean updateAlpha, float alpha,
int screen,
boolean ignoreVertexColors) {
int cdirty;
boolean useAlpha = false;
Object[] retVal;
// Check for by-copy case
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
float[] vdata;
synchronized (this) {
cdirty = dirtyFlag;
if (updateAlpha && !ignoreVertexColors) {
// update the alpha values
retVal = updateAlphaInVertexData(cv, screen, alpha);
useAlpha = (retVal[0] == Boolean.TRUE);
vdata = (float[])retVal[1];
// D3D only
if (alpha != lastScreenAlpha) {
// handle multiple screen case
lastScreenAlpha = alpha;
cdirty |= COLOR_CHANGED;
}
} else {
vdata = vertexData;
// if transparency switch between on/off
if (lastScreenAlpha != -1) {
lastScreenAlpha = -1;
cdirty |= COLOR_CHANGED;
}
}
// geomLock is get in MasterControl when
// RenderBin render the geometry. So it is safe
// just to set the dirty flag here
dirtyFlag = 0;
}
Pipeline.getPipeline().execute(cv.ctx,
this, geoType, isNonUniformScale,
useAlpha,
ignoreVertexColors,
initialVertexIndex,
validVertexCount,
((vertexFormat & GeometryArray.COLOR) != 0)?(vertexFormat|GeometryArray.COLOR_4):vertexFormat,
texCoordSetCount, texCoordSetMap,
(texCoordSetMap == null) ? 0 : texCoordSetMap.length,
texCoordSetMapOffset,
cv.numActiveTexUnit,
vertexAttrCount, vertexAttrSizes,
vdata, null,
cdirty);
}
//By reference with java array
else if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
// interleaved data
if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
if(interLeavedVertexData == null)
return;
float[] cdata = null;
synchronized (this) {
cdirty = dirtyFlag;
if (updateAlpha && !ignoreVertexColors) {
// update the alpha values
retVal = updateAlphaInInterLeavedData(cv, screen, alpha);
useAlpha = (retVal[0] == Boolean.TRUE);
cdata = (float[])retVal[1];
if (alpha != lastScreenAlpha) {
lastScreenAlpha = alpha;
cdirty |= COLOR_CHANGED;
}
} else {
// if transparency switch between on/off
if (lastScreenAlpha != -1) {
lastScreenAlpha = -1;
cdirty |= COLOR_CHANGED;
}
}
dirtyFlag = 0;
}
Pipeline.getPipeline().execute(cv.ctx,
this, geoType, isNonUniformScale,
useAlpha,
ignoreVertexColors,
initialVertexIndex,
validVertexCount,
vertexFormat,
texCoordSetCount, texCoordSetMap,
(texCoordSetMap == null) ? 0 : texCoordSetMap.length,
texCoordSetMapOffset,
cv.numActiveTexUnit,
vertexAttrCount, vertexAttrSizes,
interLeavedVertexData, cdata,
cdirty);
} // end of interleaved case
// non interleaved data
else {
// Check if a vertexformat is set, but the array is null
// if yes, don't draw anything
if ((vertexType == 0) ||
((vertexType & VERTEX_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.COLOR) != 0) &&
(vertexType & COLOR_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.NORMALS) != 0) &&
(vertexType & NORMAL_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) &&
(vertexType & VATTR_DEFINED) == 0) ||
(((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) &&
(vertexType & TEXCOORD_DEFINED) == 0)) {
return;
} else {
byte[] cbdata = null;
float[] cfdata = null;
if ((vertexType & (CF | C3F | C4F )) != 0) {
synchronized (this) {
cdirty = dirtyFlag;
if (updateAlpha && !ignoreVertexColors) {
cfdata = updateAlphaInFloatRefColors(cv, screen, alpha);
if (alpha != lastScreenAlpha) {
lastScreenAlpha = alpha;
cdirty |= COLOR_CHANGED;
}
} else {
cfdata = mirrorFloatRefColors[0];
// if transparency switch between on/off
if (lastScreenAlpha != -1) {
lastScreenAlpha = -1;
cdirty |= COLOR_CHANGED;
}
}
dirtyFlag = 0;
}
} // end of color in float format
else if ((vertexType & (CUB| C3UB | C4UB)) != 0) {
synchronized (this) {
cdirty = dirtyFlag;
if (updateAlpha && !ignoreVertexColors) {
cbdata = updateAlphaInByteRefColors(cv, screen, alpha);
if (alpha != lastScreenAlpha) {
lastScreenAlpha = alpha;
cdirty |= COLOR_CHANGED;
}
} else {
cbdata = mirrorUnsignedByteRefColors[0];
// if transparency switch between on/off
if (lastScreenAlpha != -1) {
lastScreenAlpha = -1;
cdirty |= COLOR_CHANGED;
}
}
dirtyFlag = 0;
}
} // end of color in byte format
else {
cdirty = dirtyFlag;
}
// setup vdefined to passed to native code
int vdefined = 0;
if((vertexType & (PF | P3F)) != 0)
vdefined |= COORD_FLOAT;
if((vertexType & (PD | P3D)) != 0)
vdefined |= COORD_DOUBLE;
if((vertexType & (CF | C3F | C4F)) != 0)
vdefined |= COLOR_FLOAT;
if((vertexType & (CUB| C3UB | C4UB)) != 0)
vdefined |= COLOR_BYTE;
if((vertexType & NORMAL_DEFINED) != 0)
vdefined |= NORMAL_FLOAT;
if((vertexType & VATTR_DEFINED) != 0)
vdefined |= VATTR_FLOAT;
if((vertexType & TEXCOORD_DEFINED) != 0)
vdefined |= TEXCOORD_FLOAT;
Pipeline.getPipeline().executeVA(cv.ctx,
this, geoType, isNonUniformScale,
ignoreVertexColors,
validVertexCount,
(vertexFormat | c4fAllocated),
vdefined,
initialCoordIndex,
mirrorFloatRefCoords, mirrorDoubleRefCoords,
initialColorIndex, cfdata, cbdata,
initialNormalIndex, mirrorFloatRefNormals,
vertexAttrCount, vertexAttrSizes,
initialVertexAttrIndex, mirrorFloatRefVertexAttrs,
((texCoordSetMap == null) ? 0:texCoordSetMap.length),
texCoordSetMap,
cv.numActiveTexUnit,
initialTexCoordIndex,texCoordStride,
mirrorRefTexCoords, cdirty);
}// end of all vertex data being set
}// end of non interleaved case
}// end of by reference with java array
//By reference with nio buffer
else {
// interleaved data
if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
if ( interleavedFloatBufferImpl == null)
return;
float[] cdata = null;
synchronized (this) {
cdirty = dirtyFlag;
if (updateAlpha && !ignoreVertexColors) {
// update the alpha values
// XXXX: to handle alpha case
retVal = updateAlphaInInterLeavedData(cv, screen, alpha);
useAlpha = (retVal[0] == Boolean.TRUE);
cdata = (float[])retVal[1];
if (alpha != lastScreenAlpha) {
lastScreenAlpha = alpha;
cdirty |= COLOR_CHANGED;
}
} else {
// XXXX: to handle alpha case
cdata = null;
// if transparency switch between on/off
if (lastScreenAlpha != -1) {
lastScreenAlpha = -1;
cdirty |= COLOR_CHANGED;
}
}
dirtyFlag = 0;
}
Pipeline.getPipeline().executeInterleavedBuffer(cv.ctx,
this, geoType, isNonUniformScale,
useAlpha,
ignoreVertexColors,
initialVertexIndex,
validVertexCount,
vertexFormat,
texCoordSetCount, texCoordSetMap,
(texCoordSetMap == null) ? 0 : texCoordSetMap.length,
texCoordSetMapOffset,
cv.numActiveTexUnit,
interleavedFloatBufferImpl, cdata,
cdirty);
} // end of interleaved case
// non interleaved data
else {
// Check if a vertexformat is set, but the array is null
// if yes, don't draw anything
if ((vertexType == 0) ||
((vertexType & VERTEX_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.COLOR) != 0) &&
(vertexType & COLOR_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.NORMALS) != 0) &&
(vertexType & NORMAL_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) &&
(vertexType & VATTR_DEFINED) == 0) ||
(((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) &&
(vertexType & TEXCOORD_DEFINED) == 0)) {
return;
} else {
byte[] cbdata = null;
float[] cfdata = null;
if ((vertexType & CF ) != 0) {
synchronized (this) {
cdirty = dirtyFlag;
if (updateAlpha && !ignoreVertexColors) {
cfdata = updateAlphaInFloatRefColors(cv,
screen, alpha);
if (alpha != lastScreenAlpha) {
lastScreenAlpha = alpha;
cdirty |= COLOR_CHANGED;
}
} else {
// XXXX: handle transparency case
//cfdata = null;
cfdata = mirrorFloatRefColors[0];
// if transparency switch between on/off
if (lastScreenAlpha != -1) {
lastScreenAlpha = -1;
cdirty |= COLOR_CHANGED;
}
}
dirtyFlag = 0;
}
} // end of color in float format
else if ((vertexType & CUB) != 0) {
synchronized (this) {
cdirty = dirtyFlag;
if (updateAlpha && !ignoreVertexColors) {
cbdata = updateAlphaInByteRefColors(
cv, screen, alpha);
if (alpha != lastScreenAlpha) {
lastScreenAlpha = alpha;
cdirty |= COLOR_CHANGED;
}
} else {
// XXXX: handle transparency case
//cbdata = null;
cbdata = mirrorUnsignedByteRefColors[0];
// if transparency switch between on/off
if (lastScreenAlpha != -1) {
lastScreenAlpha = -1;
cdirty |= COLOR_CHANGED;
}
}
dirtyFlag = 0;
}
} // end of color in byte format
else {
cdirty = dirtyFlag;
}
Buffer vcoord = null;
Buffer cdataBuffer = null;
FloatBuffer normal=null;
int vdefined = 0;
if((vertexType & PF) != 0) {
vdefined |= COORD_FLOAT;
vcoord = floatBufferRefCoords;
} else if((vertexType & PD ) != 0) {
vdefined |= COORD_DOUBLE;
vcoord = doubleBufferRefCoords;
}
if((vertexType & CF ) != 0) {
vdefined |= COLOR_FLOAT;
cdataBuffer = floatBufferRefColors;
} else if((vertexType & CUB) != 0) {
vdefined |= COLOR_BYTE;
cdataBuffer = byteBufferRefColors;
}
if((vertexType & NORMAL_DEFINED) != 0) {
vdefined |= NORMAL_FLOAT;
normal = floatBufferRefNormals;
}
if ((vertexType & VATTR_DEFINED) != 0) {
vdefined |= VATTR_FLOAT;
}
if((vertexType & TEXCOORD_DEFINED) != 0)
vdefined |= TEXCOORD_FLOAT;
Pipeline.getPipeline().executeVABuffer(cv.ctx,
this, geoType, isNonUniformScale,
ignoreVertexColors,
validVertexCount,
(vertexFormat | c4fAllocated),
vdefined,
initialCoordIndex,
vcoord,
initialColorIndex,
cdataBuffer,
cfdata, cbdata,
initialNormalIndex,
normal,
vertexAttrCount, vertexAttrSizes,
initialVertexAttrIndex,
floatBufferRefVertexAttrs,
((texCoordSetMap == null) ? 0:texCoordSetMap.length),
texCoordSetMap,
cv.numActiveTexUnit,
initialTexCoordIndex,texCoordStride,
refTexCoords, cdirty);
}// end of all vertex data being set
}// end of non interleaved case
}// end of by reference with nio-buffer case
}
void buildGA(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
boolean updateAlpha, float alpha, boolean ignoreVertexColors,
Transform3D xform, Transform3D nxform) {
float[] vdata = null;
// NIO buffers are no longer supported in display lists
assert (vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0;
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
vdata = vertexData;
}
else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0 &&
((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0)) {
vdata = interLeavedVertexData;
}
if (vdata != null) {
/*
System.err.println("calling native buildGA()");
System.err.println("geoType = "+geoType+" initialVertexIndex = "+initialVertexIndex+" validVertexCount = "+validVertexCount+" vertexFormat = "+vertexFormat+" vertexData = "+vertexData);
*/
Pipeline.getPipeline().buildGA(cv.ctx,
this, geoType, isNonUniformScale,
updateAlpha, alpha, ignoreVertexColors,
initialVertexIndex,
validVertexCount, vertexFormat,
texCoordSetCount, texCoordSetMap,
(texCoordSetMap == null) ? 0 : texCoordSetMap.length,
texCoordSetMapOffset,
vertexAttrCount, vertexAttrSizes,
(xform == null) ? null : xform.mat,
(nxform == null) ? null : nxform.mat,
vdata);
}
else {
// Check if a vertexformat is set, but the array is null
// if yes, don't draw anything
if ((vertexType == 0) ||
((vertexType & VERTEX_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.COLOR) != 0) &&
(vertexType & COLOR_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.NORMALS) != 0) &&
(vertexType & NORMAL_DEFINED) == 0) ||
(((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) &&
(vertexType & VATTR_DEFINED) == 0) ||
(((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) &&
(vertexType & TEXCOORD_DEFINED) == 0)) {
return;
}
// Either non-interleaved, by-ref or nio buffer
if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
// Java array case
// setup vdefined to passed to native code
int vdefined = 0;
if((vertexType & (PF | P3F)) != 0)
vdefined |= COORD_FLOAT;
if((vertexType & (PD | P3D)) != 0)
vdefined |= COORD_DOUBLE;
if((vertexType & (CF | C3F | C4F)) != 0)
vdefined |= COLOR_FLOAT;
if((vertexType & (CUB| C3UB | C4UB)) != 0)
vdefined |= COLOR_BYTE;
if((vertexType & NORMAL_DEFINED) != 0)
vdefined |= NORMAL_FLOAT;
if((vertexType & VATTR_DEFINED) != 0)
vdefined |= VATTR_FLOAT;
if((vertexType & TEXCOORD_DEFINED) != 0)
vdefined |= TEXCOORD_FLOAT;
Pipeline.getPipeline().buildGAForByRef(cv.ctx,
this, geoType, isNonUniformScale,
updateAlpha, alpha,
ignoreVertexColors,
validVertexCount,
vertexFormat,
vdefined,
initialCoordIndex,
mirrorFloatRefCoords, mirrorDoubleRefCoords,
initialColorIndex, mirrorFloatRefColors[0], mirrorUnsignedByteRefColors[0],
initialNormalIndex, mirrorFloatRefNormals,
vertexAttrCount, vertexAttrSizes,
initialVertexAttrIndex, mirrorFloatRefVertexAttrs,
((texCoordSetMap == null) ? 0:texCoordSetMap.length),
texCoordSetMap,
initialTexCoordIndex,texCoordStride,
mirrorRefTexCoords,
(xform == null) ? null : xform.mat,
(nxform == null) ? null : nxform.mat);
}
/*
// NOTE: NIO buffers are no longer supported in display lists.
// This was never enabled by default anyway (only when the
// optimizeForSpace property was set to false), so it wasn't
// well-tested. If future support is desired, we will need to
// add vertex attributes to buildGAForBuffer. There are no plans
// to ever do this.
else {
// NIO Buffer case
Object vcoord = null, cdataBuffer=null, normal=null;
int vdefined = 0;
if((vertexType & PF) != 0) {
vdefined |= COORD_FLOAT;
vcoord = floatBufferRefCoords.getBufferAsObject();
} else if((vertexType & PD ) != 0) {
vdefined |= COORD_DOUBLE;
vcoord = doubleBufferRefCoords.getBufferAsObject();
}
if((vertexType & CF ) != 0) {
vdefined |= COLOR_FLOAT;
cdataBuffer = floatBufferRefColors.getBufferAsObject();
} else if((vertexType & CUB) != 0) {
vdefined |= COLOR_BYTE;
cdataBuffer = byteBufferRefColors.getBufferAsObject();
}
if((vertexType & NORMAL_DEFINED) != 0) {
vdefined |= NORMAL_FLOAT;
normal = floatBufferRefNormals.getBufferAsObject();
}
if((vertexType & TEXCOORD_DEFINED) != 0)
vdefined |= TEXCOORD_FLOAT;
// NOTE : need to add vertex attrs
Pipeline.getPipeline().buildGAForBuffer(cv.ctx,
this, geoType, isNonUniformScale,
updateAlpha, alpha,
ignoreVertexColors,
validVertexCount,
vertexFormat,
vdefined,
initialCoordIndex,
vcoord,
initialColorIndex,cdataBuffer,
initialNormalIndex, normal,
((texCoordSetMap == null) ? 0:texCoordSetMap.length),
texCoordSetMap,
initialTexCoordIndex,texCoordStride,
refTexCoords,
(xform == null) ? null : xform.mat,
(nxform == null) ? null : nxform.mat);
}
*/
}
}
void unIndexify(IndexedGeometryArrayRetained src) {
if ((src.vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
unIndexifyJavaArray(src);
}
else {
unIndexifyNIOBuffer(src);
}
}
private void unIndexifyJavaArray(IndexedGeometryArrayRetained src) {
// System.err.println("unIndexifyJavaArray");
int vOffset = 0, srcOffset, tOffset = 0;
int index, colorStride = 0;
float[] vdata = null;
int i;
int start, end;
start = src.initialIndexIndex;
end = src.initialIndexIndex + src.validIndexCount;
// If its either "normal" data or interleaved data then ..
if (((src.vertexFormat & GeometryArray.BY_REFERENCE) == 0) ||
((src.vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
if ((src.vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
vdata = src.vertexData;
if ((src.vertexFormat & GeometryArray.COLOR) != 0)
colorStride = 4;
}
else if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
vdata = src.interLeavedVertexData;
if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
colorStride = 4;
else if ((src.vertexFormat & GeometryArray.COLOR) != 0)
colorStride = 3;
}
// System.err.println("===> start = "+start+" end = "+end);
for (index= start; index < end; index++) {
if ((vertexFormat & GeometryArray.NORMALS) != 0){
System.arraycopy(vdata,
src.indexNormal[index]*src.stride + src.normalOffset,
vertexData, vOffset + normalOffset, 3);
}
if (colorStride == 4){
// System.err.println("===> copying color3");
System.arraycopy(vdata,
src.indexColor[index]*src.stride + src.colorOffset,
vertexData, vOffset + colorOffset, colorStride);
} else if (colorStride == 3) {
// System.err.println("===> copying color4");
System.arraycopy(vdata,
src.indexColor[index]*src.stride + src.colorOffset,
vertexData, vOffset + colorOffset, colorStride);
vertexData[vOffset + colorOffset + 3] = 1.0f;
}
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
int tcOffset = vOffset + textureOffset;
int interleavedOffset = 0;
for (i = 0; i < texCoordSetCount;
i++, tcOffset += texCoordStride) {
if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
interleavedOffset = i * texCoordStride;
}
System.arraycopy(vdata,
(src.indexTexCoord[i][index])*src.stride + src.textureOffset + interleavedOffset,
vertexData, tcOffset, texCoordStride);
}
}
if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
// vertex attributes can't be interleaved
assert (src.vertexFormat & GeometryArray.INTERLEAVED) == 0;
for (i = 0; i < vertexAttrCount; i++) {
int vaOffset = vOffset + vertexAttrOffsets[i];
System.arraycopy(vdata,
(src.indexVertexAttr[i][index])*src.stride + src.vertexAttrOffsets[i],
vertexData, vaOffset, vertexAttrSizes[i]);
}
}
if ((vertexFormat & GeometryArray.COORDINATES) != 0){
// System.err.println("===> copying coords");
System.arraycopy(vdata,
src.indexCoord[index]*src.stride
+ src.coordinateOffset,
vertexData,
vOffset + coordinateOffset, 3);
}
vOffset += stride;
}
} else {
if ((vertexFormat & GeometryArray.NORMALS) != 0) {
vOffset = normalOffset;
switch ((src.vertexType & NORMAL_DEFINED)) {
case NF:
for (index=start; index < end; index++) {
System.arraycopy(src.floatRefNormals,
src.indexNormal[index]*3,
vertexData,
vOffset, 3);
vOffset += stride;
}
break;
case N3F:
for (index=start; index < end; index++) {
srcOffset = src.indexNormal[index];
vertexData[vOffset] = src.v3fRefNormals[srcOffset].x;
vertexData[vOffset+1] = src.v3fRefNormals[srcOffset].y;
vertexData[vOffset+2] = src.v3fRefNormals[srcOffset].z;
vOffset += stride;
}
break;
default:
break;
}
}
if ((vertexFormat & GeometryArray.COLOR) != 0) {
vOffset = colorOffset;
int multiplier = 3;
if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
multiplier = 4;
switch ((src.vertexType & COLOR_DEFINED)) {
case CF:
for (index=start; index < end; index++) {
if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
System.arraycopy(src.floatRefColors,
src.indexColor[index]*multiplier,
vertexData,
vOffset, 4);
}
else {
System.arraycopy(src.floatRefColors,
src.indexColor[index]*multiplier,
vertexData,
vOffset, 3);
vertexData[vOffset+3] = 1.0f;
}
vOffset += stride;
}
break;
case CUB:
for (index=start; index < end; index++) {
srcOffset = src.indexColor[index] * multiplier;
vertexData[vOffset] = (src.byteRefColors[srcOffset] & 0xff) * ByteToFloatScale;
vertexData[vOffset+1] = (src.byteRefColors[srcOffset+1] & 0xff) * ByteToFloatScale;
vertexData[vOffset+2] = (src.byteRefColors[srcOffset+2] & 0xff) * ByteToFloatScale;
if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
vertexData[vOffset+3] = (src.byteRefColors[srcOffset+3] & 0xff) * ByteToFloatScale;
}
else {
vertexData[vOffset+3] = 1.0f;
}
vOffset += stride;
}
break;
case C3F:
for (index=start; index < end; index++) {
srcOffset = src.indexColor[index];
vertexData[vOffset] = src.c3fRefColors[srcOffset].x;
vertexData[vOffset+1] = src.c3fRefColors[srcOffset].y;
vertexData[vOffset+2] = src.c3fRefColors[srcOffset].z;
vertexData[vOffset+3] = 1.0f;
vOffset += stride;
}
break;
case C4F:
for (index=start; index < end; index++) {
srcOffset = src.indexColor[index];
vertexData[vOffset] = src.c4fRefColors[srcOffset].x;
vertexData[vOffset+1] = src.c4fRefColors[srcOffset].y;
vertexData[vOffset+2] = src.c4fRefColors[srcOffset].z;
vertexData[vOffset+3] = src.c4fRefColors[srcOffset].w;
vOffset += stride;
}
break;
case C3UB:
for (index=start; index < end; index++) {
srcOffset = src.indexColor[index];
vertexData[vOffset] = (src.c3bRefColors[srcOffset].x & 0xff) * ByteToFloatScale;
vertexData[vOffset+1] = (src.c3bRefColors[srcOffset].y & 0xff) * ByteToFloatScale;
vertexData[vOffset+2] = (src.c3bRefColors[srcOffset].z & 0xff) * ByteToFloatScale;
vertexData[vOffset+3] = 1.0f;
vOffset += stride;
}
break;
case C4UB:
for (index=start; index < end; index++) {
srcOffset = src.indexColor[index];
vertexData[vOffset] = (src.c4bRefColors[srcOffset].x & 0xff) * ByteToFloatScale;
vertexData[vOffset+1] = (src.c4bRefColors[srcOffset].y & 0xff) * ByteToFloatScale;
vertexData[vOffset+2] = (src.c4bRefColors[srcOffset].z & 0xff) * ByteToFloatScale;
vertexData[vOffset+3] = (src.c4bRefColors[srcOffset].w & 0xff) * ByteToFloatScale;
vOffset += stride;
}
break;
default:
break;
}
}
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
vOffset = textureOffset;
switch ((src.vertexType & TEXCOORD_DEFINED)) {
case TF:
for (index=start; index < end; index++) {
for (i = 0, tOffset = vOffset;
i < texCoordSetCount; i++) {
System.arraycopy(src.refTexCoords[i],
src.indexTexCoord[i][index]*texCoordStride,
vertexData, tOffset, texCoordStride);
tOffset += texCoordStride;
}
vOffset += stride;
}
break;
case T2F:
for (index=start; index < end; index++) {
for (i = 0, tOffset = vOffset;
i < texCoordSetCount; i++) {
srcOffset = src.indexTexCoord[i][index];
vertexData[tOffset] =
((TexCoord2f[])src.refTexCoords[i])[srcOffset].x;
vertexData[tOffset+1] =
((TexCoord2f[])src.refTexCoords[i])[srcOffset].y;
tOffset += texCoordStride;
}
vOffset += stride;
}
break;
case T3F:
for (index=start; index < end; index++) {
for (i = 0, tOffset = vOffset;
i < texCoordSetCount; i++) {
srcOffset = src.indexTexCoord[i][index];
vertexData[tOffset] =
((TexCoord3f[])src.refTexCoords[i])[srcOffset].x;
vertexData[tOffset+1] =
((TexCoord3f[])src.refTexCoords[i])[srcOffset].y;
vertexData[tOffset+2] =
((TexCoord3f[])src.refTexCoords[i])[srcOffset].z;
tOffset += texCoordStride;
}
vOffset += stride;
}
break;
default:
break;
}
}
if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
vOffset = 0;
switch (src.vertexType & VATTR_DEFINED) {
case AF:
for (index=start; index < end; index++) {
for (i = 0; i < vertexAttrCount; i++) {
int vaOffset = vOffset + vertexAttrOffsets[i];
System.arraycopy(src.floatRefVertexAttrs[i],
src.indexVertexAttr[i][index]*vertexAttrSizes[i],
vertexData, vaOffset, vertexAttrSizes[i]);
}
vOffset += stride;
}
break;
}
}
if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
vOffset = coordinateOffset;
switch ((src.vertexType & VERTEX_DEFINED)) {
case PF:
for (index=start; index < end; index++) {
System.arraycopy(src.floatRefCoords,
src.indexCoord[index]*3,
vertexData,
vOffset, 3);
vOffset += stride;
}
break;
case PD:
for (index=start; index < end; index++) {
srcOffset = src.indexCoord[index] * 3;
vertexData[vOffset] = (float)src.doubleRefCoords[srcOffset];
vertexData[vOffset+1] = (float)src.doubleRefCoords[srcOffset+1];
vertexData[vOffset+2] = (float)src.doubleRefCoords[srcOffset+2];
vOffset += stride;
}
break;
case P3F:
for (index=start; index < end; index++) {
srcOffset = src.indexCoord[index];
vertexData[vOffset] = src.p3fRefCoords[srcOffset].x;
vertexData[vOffset+1] = src.p3fRefCoords[srcOffset].y;
vertexData[vOffset+2] = src.p3fRefCoords[srcOffset].z;
vOffset += stride;
}
break;
case P3D:
for (index=start; index < end; index++) {
srcOffset = src.indexCoord[index];
vertexData[vOffset] = (float)src.p3dRefCoords[srcOffset].x;
vertexData[vOffset+1] = (float)src.p3dRefCoords[srcOffset].y;
vertexData[vOffset+2] = (float)src.p3dRefCoords[srcOffset].z;
vOffset += stride;
}
break;
default:
break;
}
}
}
}
private void unIndexifyNIOBuffer(IndexedGeometryArrayRetained src) {
// System.err.println("unIndexifyNIOBuffer");
int vOffset = 0, srcOffset, tOffset = 0;
int index, colorStride = 0;
int i;
int start, end;
start = src.initialIndexIndex;
end = src.initialIndexIndex + src.validIndexCount;
// If its interleaved data then ..
if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
colorStride = 4;
else if ((src.vertexFormat & GeometryArray.COLOR) != 0)
colorStride = 3;
// System.err.println("===> start = "+start+" end = "+end);
for (index= start; index < end; index++) {
if ((vertexFormat & GeometryArray.NORMALS) != 0){
src.interleavedFloatBufferImpl.position(src.indexNormal[index]*src.stride + src.normalOffset);
src.interleavedFloatBufferImpl.get(vertexData, vOffset + normalOffset, 3);
}
if (colorStride == 4){
src.interleavedFloatBufferImpl.position(src.indexColor[index]*src.stride + src.colorOffset);
src.interleavedFloatBufferImpl.get(vertexData, vOffset + colorOffset, colorStride);
} else if (colorStride == 3) {
src.interleavedFloatBufferImpl.position(src.indexColor[index]*src.stride + src.colorOffset);
src.interleavedFloatBufferImpl.get(vertexData, vOffset + colorOffset, colorStride);
vertexData[vOffset + colorOffset + 3] = 1.0f;
}
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
int tcOffset = vOffset + textureOffset;
for (i = 0; i < texCoordSetCount;
i++, tcOffset += texCoordStride) {
src.interleavedFloatBufferImpl.position((src.indexTexCoord[i][index])*src.stride +
src.textureOffset);
src.interleavedFloatBufferImpl.get(vertexData, tcOffset, texCoordStride);
}
}
if ((vertexFormat & GeometryArray.COORDINATES) != 0){
src.interleavedFloatBufferImpl.position(src.indexCoord[index]*src.stride + src.coordinateOffset );
src.interleavedFloatBufferImpl.get(vertexData, vOffset + coordinateOffset, 3);
}
vOffset += stride;
}
} else {
if ((vertexFormat & GeometryArray.NORMALS) != 0){
vOffset = normalOffset;
if ((src.vertexType & NORMAL_DEFINED) != 0) {
for (index=start; index < end; index++) {
src.floatBufferRefNormals.position(src.indexNormal[index]*3);
src.floatBufferRefNormals.get(vertexData, vOffset, 3);
vOffset += stride;
}
}
}
if ((vertexFormat & GeometryArray.COLOR) != 0){
vOffset = colorOffset;
int multiplier = 3;
if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
multiplier = 4;
switch ((src.vertexType & COLOR_DEFINED)) {
case CF:
for (index=start; index < end; index++) {
if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
src.floatBufferRefColors.position(src.indexColor[index]*multiplier);
src.floatBufferRefColors.get(vertexData, vOffset, 4);
}
else {
src.floatBufferRefColors.position(src.indexColor[index]*multiplier);
src.floatBufferRefColors.get(vertexData, vOffset, 3);
vertexData[vOffset+3] = 1.0f;
}
vOffset += stride;
}
break;
case CUB:
for (index=start; index < end; index++) {
srcOffset = src.indexColor[index] * multiplier;
vertexData[vOffset] = (src.byteBufferRefColors.get(srcOffset) & 0xff) * ByteToFloatScale;
vertexData[vOffset+1] = (src.byteBufferRefColors.get(srcOffset+1) & 0xff) * ByteToFloatScale;
vertexData[vOffset+2] = (src.byteBufferRefColors.get(srcOffset+2) & 0xff) * ByteToFloatScale;
if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
vertexData[vOffset+3] = (src.byteBufferRefColors.get(srcOffset+3) & 0xff) * ByteToFloatScale;
}
else {
vertexData[vOffset+3] = 1.0f;
}
vOffset += stride;
}
break;
default:
break;
}
}
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
vOffset = textureOffset;
if ((src.vertexType & TEXCOORD_DEFINED) != 0) {
for (index=start; index < end; index++) {
for (i = 0, tOffset = vOffset;
i < texCoordSetCount; i++) {
FloatBuffer texBuffer = (FloatBuffer)src.refTexCoordsBuffer[i].getROBuffer();
texBuffer.position(src.indexTexCoord[i][index]*texCoordStride);
texBuffer.get(vertexData, tOffset, texCoordStride);
tOffset += texCoordStride;
}
vOffset += stride;
}
}
}
if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
vOffset = 0;
if ((src.vertexType & VATTR_DEFINED) == AF) {
for (index=start; index < end; index++) {
for (i = 0; i < vertexAttrCount; i++) {
int vaOffset = vOffset + vertexAttrOffsets[i];
FloatBuffer vaBuffer = src.floatBufferRefVertexAttrs[i];
vaBuffer.position(src.indexVertexAttr[i][index]*vertexAttrSizes[i]);
vaBuffer.get(vertexData, vaOffset, vertexAttrSizes[i]);
}
vOffset += stride;
}
}
}
if ((vertexFormat & GeometryArray.COORDINATES) != 0){
vOffset = coordinateOffset;
switch ((src.vertexType & VERTEX_DEFINED)) {
case PF:
for (index=start; index < end; index++) {
src.floatBufferRefCoords.position(src.indexCoord[index]*3);
src.floatBufferRefCoords.get(vertexData, vOffset, 3);
vOffset += stride;
}
break;
case PD:
for (index=start; index < end; index++) {
srcOffset = src.indexCoord[index] * 3;
vertexData[vOffset] = (float)src.doubleBufferRefCoords.get(srcOffset);
vertexData[vOffset+1] = (float)src.doubleBufferRefCoords.get(srcOffset+1);
vertexData[vOffset+2] = (float)src.doubleBufferRefCoords.get(srcOffset+2);
vOffset += stride;
}
break;
default:
break;
}
}
}
}
/**
* Returns the vertex stride in numbers of floats as a function
* of the vertexFormat.
* @return the stride in floats for this vertex array
*/
int stride()
{
int stride = 0;
if((this.vertexFormat & GeometryArray.COORDINATES) != 0) stride += 3;
if((this.vertexFormat & GeometryArray.NORMALS) != 0) stride += 3;
if ((this.vertexFormat & GeometryArray.COLOR) != 0) {
if ((this.vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
// By copy
stride += 4;
} else {
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
stride += 3;
}
else {
stride += 4;
}
}
}
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
if ((this.vertexFormat &
GeometryArray.TEXTURE_COORDINATE_2) != 0) {
texCoordStride = 2;
} else if ((this.vertexFormat &
GeometryArray.TEXTURE_COORDINATE_3) != 0) {
texCoordStride = 3;
} else if ((this.vertexFormat &
GeometryArray.TEXTURE_COORDINATE_4) != 0) {
texCoordStride = 4;
}
stride += texCoordStride * texCoordSetCount;
}
if ((this.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
stride += vertexAttrStride;
}
//System.err.println("stride() = " + stride);
return stride;
}
int[] texCoordSetMapOffset()
{
if (texCoordSetMap == null)
return null;
texCoordSetMapOffset = new int[texCoordSetMap.length];
for (int i = 0; i < texCoordSetMap.length; i++) {
if (texCoordSetMap[i] == -1) {
texCoordSetMapOffset[i] = -1;
} else {
texCoordSetMapOffset[i] = texCoordSetMap[i] * texCoordStride;
}
}
return texCoordSetMapOffset;
}
/**
* Returns the stride of the set of vertex attributes. This is the
* sum of the sizes of each vertex attribute.
* @return the stride of the vertex attribute data
*/
int vertexAttrStride() {
int sum = 0;
for (int i = 0; i < vertexAttrCount; i++) {
sum += vertexAttrSizes[i];
}
return sum;
}
/**
* Returns the offset in number of floats from the start of a vertex to
* each per-vertex vertex attribute.
* @return array of offsets in floats vertex start to the vertex attribute data
*/
int[] vertexAttrOffsets() {
int[] offsets;
// Create array of offsets to the start of each vertex attribute.
// The offset of the first attribute is always 0. If no vertex attributes exist,
// then we will allocate an array of length 1 to avoid some checking elsewhere.
if (vertexAttrCount > 0) {
offsets = new int[vertexAttrCount];
}
else {
offsets = new int[1];
}
offsets[0] = 0;
for (int i = 1; i < vertexAttrCount; i++) {
offsets[i] = offsets[i-1] + vertexAttrSizes[i-1];
}
return offsets;
}
/**
* Returns the offset in number of floats from the start of a vertex to
* the per-vertex texture coordinate data.
* texture coordinate data always follows vertex attribute data
* @return the offset in floats vertex start to the tetxure data
*/
int textureOffset()
{
int offset = vertexAttrOffsets[0];
if ((this.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
offset += vertexAttrStride;
}
return offset;
}
/**
* Returns the offset in number of floats from the start of a vertex to
* the per-vertex color data.
* color data always follows texture data
* @param vertexFormat the vertex format for this array
* @return the offset in floats vertex start to the color data
*/
int colorOffset()
{
int offset = textureOffset;
if((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0)
offset += 2 * texCoordSetCount;
else if((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0)
offset += 3 * texCoordSetCount;
else if((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0)
offset += 4 * texCoordSetCount;
return offset;
}
/**
* Returns the offset in number of floats from the start of a vertex to
* the per-vertex normal data.
* normal data always follows color data
* @return the offset in floats from the start of a vertex to the normal
*/
int normalOffset()
{
int offset = colorOffset;
if ((this.vertexFormat & GeometryArray.COLOR) != 0) {
if ((this.vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
offset += 4;
} else {
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
offset += 3;
}
else {
offset += 4;
}
}
}
return offset;
}
/**
* Returns the offset in number of floats from the start of a vertex to
* the per vertex coordinate data.
* @return the offset in floats vertex start to the coordinate data
*/
int coordinateOffset()
{
int offset = normalOffset;
if ((this.vertexFormat & GeometryArray.NORMALS) != 0) offset += 3;
return offset;
}
/**
* Returns number of vertices in the GeometryArray
* @return vertexCount number of vertices in the GeometryArray
*/
int getVertexCount(){
return vertexCount;
}
/**
* Returns vertexFormat in the GeometryArray
* @return vertexFormat format of vertices in the GeometryArray
*/
@Override
int getVertexFormat(){
return vertexFormat;
}
/**
* Retrieves the number of vertex attributes in this GeometryArray
* object.
*
* @return the number of vertex attributes in this GeometryArray
* object
*/
int getVertexAttrCount() {
return vertexAttrCount;
}
/**
* Retrieves the vertex attribute sizes array from this
* GeometryArray object.
*
* @param vertexAttrSizes an array that will receive a copy of
* the vertex attribute sizes array. The array must hold at least
* vertexAttrCount
elements.
*/
void getVertexAttrSizes(int[] vertexAttrSizes) {
for (int i = 0; i < vertexAttrCount; i++) {
vertexAttrSizes[i] = this.vertexAttrSizes[i];
}
}
void sendDataChangedMessage(boolean coordinatesChanged) {
J3dMessage[] m;
int i, j, k, numShapeMessages, numMorphMessages;
synchronized(liveStateLock) {
if (source != null && source.isLive()) {
// System.err.println("In GeometryArrayRetained - ");
// Send a message to renderBin to rebuild the display list or
// process the vertex array accordingly
// XXXX: Should I send one per universe, isn't display list
// shared by all context/universes?
int threads = J3dThread.UPDATE_RENDER;
// If the geometry type is Indexed then we need to clone the geometry
// We also need to update the cachedChangedFrequent flag
threads |= J3dThread.UPDATE_RENDERING_ATTRIBUTES;
synchronized (universeList) {
numShapeMessages = universeList.size();
m = new J3dMessage[numShapeMessages];
k = 0;
for (i = 0; i < numShapeMessages; i++, k++) {
gaList.clear();
ArrayList shapeList = userLists.get(i);
for (j = 0; j < shapeList.size(); j++) {
Shape3DRetained s = shapeList.get(j);
LeafRetained src = (LeafRetained)s.sourceNode;
// Should only need to update distinct localBounds.
if (coordinatesChanged && src.boundsAutoCompute) {
src.boundsDirty = true;
}
}
for (j = 0; j < shapeList.size(); j++) {
Shape3DRetained s = shapeList.get(j);
LeafRetained src = (LeafRetained)s.sourceNode;
if (src.boundsDirty) {
// update combine bounds of mirrorShape3Ds. So we need to
// use its bounds and not localBounds.
// bounds is actually a reference to
// mirrorShape3D.source.localBounds.
src.updateBounds();
src.boundsDirty = false;
}
gaList.add(Shape3DRetained.getGeomAtom(s));
}
m[k] = new J3dMessage();
m[k].type = J3dMessage.GEOMETRY_CHANGED;
// Who to send this message to ?
m[k].threads = threads;
m[k].args[0] = gaList.toArray();
m[k].args[1] = this;
m[k].args[2]= null;
m[k].args[3] = new Integer(changedFrequent);
m[k].universe = universeList.get(i);
}
VirtualUniverse.mc.processMessage(m);
}
if (morphUniverseList != null) {
synchronized (morphUniverseList) {
numMorphMessages = morphUniverseList.size();
// take care of morph that is referencing this geometry
if (numMorphMessages > 0) {
synchronized (morphUniverseList) {
for (i = 0; i < numMorphMessages; i++, k++) {
ArrayList morphList = morphUserLists.get(i);
for (j = 0; j < morphList.size(); j++) {
morphList.get(j).updateMorphedGeometryArray(this, coordinatesChanged);
}
}
}
}
}
}
}
}
}
/**
* Sets the coordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param coordinate an array of 3 values containing the new coordinate
*/
void setCoordinate(int index, float coordinate[]) {
int offset = this.stride * index + coordinateOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
this.vertexData[offset] = coordinate[0];
this.vertexData[offset+1]= coordinate[1];
this.vertexData[offset+2]= coordinate[2];
if (isLive) {
geomLock.unLock();
}
if (inUpdater || (source == null)) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param coordinate an array of 3 values containing the new coordinate
*/
void setCoordinate(int index, double coordinate[]) {
int offset = this.stride * index + coordinateOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
this.vertexData[offset] = (float)coordinate[0];
this.vertexData[offset+1]= (float)coordinate[1];
this.vertexData[offset+2]= (float)coordinate[2];
if(isLive) {
geomLock.unLock();
}
if (inUpdater || (source == null)) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param coordinate a vector containing the new coordinate
*/
void setCoordinate(int index, Point3f coordinate) {
int offset = this.stride * index + coordinateOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
this.vertexData[offset] = coordinate.x;
this.vertexData[offset+1]= coordinate.y;
this.vertexData[offset+2]= coordinate.z;
if(isLive) {
geomLock.unLock();
}
if (inUpdater || (source == null)) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param coordinate a vector containing the new coordinate
*/
void setCoordinate(int index, Point3d coordinate) {
int offset = this.stride * index + coordinateOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
this.vertexData[offset] = (float)coordinate.x;
this.vertexData[offset+1]= (float)coordinate.y;
this.vertexData[offset+2]= (float)coordinate.z;
if(isLive) {
geomLock.unLock();
}
if (inUpdater || source == null ) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param coordinates an array of 3*n values containing n new coordinates
*/
void setCoordinates(int index, float coordinates[]) {
int offset = this.stride * index + coordinateOffset;
int i, j, num = coordinates.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
for (i=0, j= offset;i < num; i+=3, j+= this.stride)
{
this.vertexData[j] = coordinates[i];
this.vertexData[j+1]= coordinates[i+1];
this.vertexData[j+2]= coordinates[i+2];
}
if(isLive) {
geomLock.unLock();
}
if (inUpdater ||source == null ) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param coordinates an array of 3*n values containing n new coordinates
*/
void setCoordinates(int index, double coordinates[]) {
int offset = this.stride * index + coordinateOffset;
int i, j, num = coordinates.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
for (i=0, j= offset;i < num; i+=3, j+= this.stride)
{
this.vertexData[j] = (float)coordinates[i];
this.vertexData[j+1]= (float)coordinates[i+1];
this.vertexData[j+2]= (float)coordinates[i+2];
}
if(isLive) {
geomLock.unLock();
}
if (inUpdater ||source == null ) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param coordinates an array of vectors containing new coordinates
*/
void setCoordinates(int index, Point3f coordinates[]) {
int offset = this.stride * index + coordinateOffset;
int i, j, num = coordinates.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
this.vertexData[j] = coordinates[i].x;
this.vertexData[j+1]= coordinates[i].y;
this.vertexData[j+2]= coordinates[i].z;
}
if(isLive) {
geomLock.unLock();
}
if (inUpdater ||source == null ) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param coordinates an array of vectors containing new coordinates
*/
void setCoordinates(int index, Point3d coordinates[]) {
int offset = this.stride * index + coordinateOffset;
int i, j, num = coordinates.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
this.vertexData[j] = (float)coordinates[i].x;
this.vertexData[j+1]= (float)coordinates[i].y;
this.vertexData[j+2]= (float)coordinates[i].z;
}
if(isLive) {
geomLock.unLock();
}
if (inUpdater ||source == null ) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinates associated with the vertices starting at
* the specified index for this object using coordinate data starting
* from vertex index start
for length
vertices.
* @param index the vertex index
* @param coordinates an array of vectors containing new coordinates
* @param start starting vertex index of data in coordinates
.
* @param length number of vertices to be copied.
*/
void setCoordinates(int index, float coordinates[], int start, int length) {
int offset = this.stride * index + coordinateOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
for (i= start * 3, j= offset; i < (start+length) * 3;
i+=3, j+= this.stride) {
this.vertexData[j] = coordinates[i];
this.vertexData[j+1]= coordinates[i+1];
this.vertexData[j+2]= coordinates[i+2];
}
if(isLive) {
geomLock.unLock();
}
if (inUpdater ||source == null ) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinates associated with the vertices starting at
* the specified index for this object using coordinate data starting
* from vertex index start
for length
vertices.
* @param index the vertex index
* @param coordinates an array of 3*n values containing n new coordinates
* @param start starting vertex index of data in coordinates
.
* @param length number of vertices to be copied.
*/
void setCoordinates(int index, double coordinates[], int start, int length) {
int offset = this.stride * index + coordinateOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
for (i= start*3, j= offset; i < (start+length)*3;
i+=3, j+= this.stride) {
this.vertexData[j] = (float)coordinates[i];
this.vertexData[j+1]= (float)coordinates[i+1];
this.vertexData[j+2]= (float)coordinates[i+2];
}
if(isLive) {
geomLock.unLock();
}
if (inUpdater || (source == null)) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinates associated with the vertices starting at
* the specified index for this object using coordinate data starting
* from vertex index start
for length
vertices.
* @param index the vertex index
* @param coordinates an array of vectors containing new coordinates
* @param start starting vertex index of data in coordinates
.
* @param length number of vertices to be copied.
*/
void setCoordinates(int index, Point3f coordinates[], int start,
int length) {
int offset = this.stride * index + coordinateOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
for (i=start, j= offset;i < start + length; i++, j+= this.stride) {
this.vertexData[j] = coordinates[i].x;
this.vertexData[j+1]= coordinates[i].y;
this.vertexData[j+2]= coordinates[i].z;
}
if(isLive) {
geomLock.unLock();
}
if (inUpdater || (source == null)) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the coordinates associated with the vertices starting at
* the specified index for this object using coordinate data starting
* from vertex index start
for length
vertices.
* @param index the vertex index
* @param coordinates an array of vectors containing new coordinates
* @param start starting vertex index of data in coordinates
.
* @param length number of vertices to be copied.
*/
void setCoordinates(int index, Point3d coordinates[], int start,
int length) {
int offset = this.stride * index + coordinateOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
for (i=start, j= offset;i < start + length; i++, j+= this.stride) {
this.vertexData[j] = (float)coordinates[i].x;
this.vertexData[j+1]= (float)coordinates[i].y;
this.vertexData[j+2]= (float)coordinates[i].z;
}
if(isLive) {
geomLock.unLock();
}
if (inUpdater || (source == null)) {
return;
}
if (!isLive) {
boundsDirty = true;
return;
}
// Compute geo's bounds
processCoordsChanged(false);
sendDataChangedMessage(true);
}
/**
* Sets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color an array of 3 or 4 values containing the new color
*/
void setColor(int index, float color[]) {
int offset = this.stride*index + colorOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
this.vertexData[offset] = color[0];
this.vertexData[offset+1] = color[1];
this.vertexData[offset+2] = color[2];
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
this.vertexData[offset+3] = color[3]*lastAlpha[0];
else
this.vertexData[offset+3] = lastAlpha[0];
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color an array of 3 or 4 values containing the new color
*/
void setColor(int index, byte color[]) {
int offset = this.stride*index + colorOffset;
boolean isLive = source!=null && source.isLive();
if(isLive) {
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
this.vertexData[offset] = (color[0] & 0xff) * ByteToFloatScale;
this.vertexData[offset+1] = (color[1] & 0xff) * ByteToFloatScale;
this.vertexData[offset+2] = (color[2] & 0xff) * ByteToFloatScale;
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
this.vertexData[offset+3] = ((color[3] & 0xff)* ByteToFloatScale)*lastAlpha[0];
else
this.vertexData[offset+3] = lastAlpha[0];
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color a vector containing the new color
*/
void setColor(int index, Color3f color) {
int offset = this.stride*index + colorOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
this.vertexData[offset] = color.x;
this.vertexData[offset+1] = color.y;
this.vertexData[offset+2] = color.z;
this.vertexData[offset+3] = lastAlpha[0];
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color a vector containing the new color
*/
void setColor(int index, Color4f color) {
int offset = this.stride*index + colorOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
this.vertexData[offset] = color.x;
this.vertexData[offset+1] = color.y;
this.vertexData[offset+2] = color.z;
this.vertexData[offset+3] = color.w*lastAlpha[0];
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color a vector containing the new color
*/
void setColor(int index, Color3b color) {
int offset = this.stride*index + colorOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
this.vertexData[offset] = (color.x & 0xff) * ByteToFloatScale;
this.vertexData[offset+1] = (color.y & 0xff) * ByteToFloatScale;
this.vertexData[offset+2] = (color.z & 0xff) * ByteToFloatScale;
this.vertexData[offset+3] = lastAlpha[0];
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color a vector containing the new color
*/
void setColor(int index, Color4b color) {
int offset = this.stride*index + colorOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
this.vertexData[offset] = (color.x & 0xff) * ByteToFloatScale;
this.vertexData[offset+1] = (color.y & 0xff) * ByteToFloatScale;
this.vertexData[offset+2] = (color.z & 0xff) * ByteToFloatScale;
this.vertexData[offset+3] = ((color.w & 0xff) * ByteToFloatScale)*lastAlpha[0];
if(isLive){
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values containing n new colors
*/
void setColors(int index, float colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
{
for (i=0, j= offset;i < num; i+= 4, j+= this.stride)
{
this.vertexData[j] = colors[i];
this.vertexData[j+1] = colors[i+1];
this.vertexData[j+2] = colors[i+2];
this.vertexData[j+3] = colors[i+3]*lastAlpha[0];
}
}
else
{
for (i=0, j= offset;i < num; i+= 3, j+= this.stride)
{
this.vertexData[j] = colors[i];
this.vertexData[j+1] = colors[i+1];
this.vertexData[j+2] = colors[i+2];
this.vertexData[j+3] = lastAlpha[0];
}
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values containing n new colors
*/
void setColors(int index, byte colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
{
for (i=0, j= offset;i < num; i+= 4, j+= this.stride)
{
this.vertexData[j] = (colors[i] & 0xff) * ByteToFloatScale;
this.vertexData[j+1] = (colors[i+1] & 0xff) * ByteToFloatScale;
this.vertexData[j+2] = (colors[i+2] & 0xff) * ByteToFloatScale;
this.vertexData[j+3] = ((colors[i+3] & 0xff) * ByteToFloatScale)*lastAlpha[0];
}
}
else
{
for (i=0, j= offset;i < num; i+= 3, j+= this.stride)
{
this.vertexData[j] = (colors[i] & 0xff) * ByteToFloatScale;
this.vertexData[j+1] = (colors[i+1] & 0xff) * ByteToFloatScale;
this.vertexData[j+2] = (colors[i+2] & 0xff) * ByteToFloatScale;
this.vertexData[j+3] = lastAlpha[0];
}
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of vectors containing new colors
*/
void setColors(int index, Color3f colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
this.vertexData[j] = colors[i].x;
this.vertexData[j+1] = colors[i].y;
this.vertexData[j+2] = colors[i].z;
this.vertexData[j+3] = lastAlpha[0];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of vectors containing new colors
*/
void setColors(int index, Color4f colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
this.vertexData[j] = colors[i].x;
this.vertexData[j+1] = colors[i].y;
this.vertexData[j+2] = colors[i].z;
this.vertexData[j+3] = colors[i].w*lastAlpha[0];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of vectors containing new colors
*/
void setColors(int index, Color3b colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
this.vertexData[j] = (colors[i].x & 0xff) * ByteToFloatScale;
this.vertexData[j+1] = (colors[i].y & 0xff) * ByteToFloatScale;
this.vertexData[j+2] = (colors[i].z & 0xff) * ByteToFloatScale;
this.vertexData[j+3] = lastAlpha[0];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of vectors containing new colors
*/
void setColors(int index, Color4b colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
this.vertexData[j] = (colors[i].x & 0xff) * ByteToFloatScale;
this.vertexData[j+1] = (colors[i].y & 0xff) * ByteToFloatScale;
this.vertexData[j+2] = (colors[i].z & 0xff) * ByteToFloatScale;
this.vertexData[j+3] = ((colors[i].w & 0xff) * ByteToFloatScale)*lastAlpha[0];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index for this object using data in color
s
* starting at index start
for length
colors.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values containing n new colors
* @param start starting color index of data in colors
.
* @param length number of colors to be copied.
*/
void setColors(int index, float colors[], int start, int length) {
int offset = this.stride*index + colorOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
for (i = start * 4, j = offset; i < (start + length) * 4;
i += 4, j += this.stride) {
this.vertexData[j] = colors[i];
this.vertexData[j+1] = colors[i+1];
this.vertexData[j+2] = colors[i+2];
this.vertexData[j+3] = colors[i+3]*lastAlpha[0];
}
} else {
for (i = start * 3, j = offset; i < (start + length) * 3;
i += 3, j += this.stride) {
this.vertexData[j] = colors[i];
this.vertexData[j+1] = colors[i+1];
this.vertexData[j+2] = colors[i+2];
this.vertexData[j+3] = lastAlpha[0];
}
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index for this object using data in color
s
* starting at index start
for length
colors.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values containing n new colors
* @param start starting color index of data in colors
.
* @param length number of colors to be copied.
*/
void setColors(int index, byte colors[], int start, int length) {
int offset = this.stride*index + colorOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
for (i = start * 4, j = offset; i < (start + length) * 4;
i += 4, j += this.stride) {
this.vertexData[j] = (colors[i] & 0xff) * ByteToFloatScale;
this.vertexData[j+1] = (colors[i+1] & 0xff) * ByteToFloatScale;
this.vertexData[j+2] = (colors[i+2] & 0xff) * ByteToFloatScale;
this.vertexData[j+3] = ((colors[i+3] & 0xff) * ByteToFloatScale)*lastAlpha[0];
}
} else {
for (i = start * 3, j = offset; i < (start + length) * 3;
i += 3, j += this.stride) {
this.vertexData[j] = (colors[i] & 0xff) * ByteToFloatScale;
this.vertexData[j+1] = (colors[i+1] & 0xff) * ByteToFloatScale;
this.vertexData[j+2] = (colors[i+2] & 0xff) * ByteToFloatScale;
this.vertexData[j+3] = lastAlpha[0];
}
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index for this object using data in color
s
* starting at index start
for length
colors.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values containing n new colors
* @param start starting color index of data in colors
.
* @param length number of colors to be copied.
*/
void setColors(int index, Color3f colors[], int start, int length) {
int offset = this.stride*index + colorOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = colors[i].x;
this.vertexData[j+1] = colors[i].y;
this.vertexData[j+2] = colors[i].z;
this.vertexData[j+3] = lastAlpha[0];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index for this object using data in color
s
* starting at index start
for length
colors.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values containing n new colors
* @param start starting color index of data in colors
.
* @param length number of colors to be copied.
*/
void setColors(int index, Color4f colors[], int start, int length) {
int offset = this.stride*index + colorOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = colors[i].x;
this.vertexData[j+1] = colors[i].y;
this.vertexData[j+2] = colors[i].z;
this.vertexData[j+3] = colors[i].w*lastAlpha[0];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index for this object using data in color
s
* starting at index start
for length
colors.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values containing n new colors
* @param start starting color index of data in colors
.
* @param length number of colors to be copied.
*/
void setColors(int index, Color3b colors[], int start, int length) {
int offset = this.stride*index + colorOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = (colors[i].x & 0xff) * ByteToFloatScale;
this.vertexData[j+1] = (colors[i].y & 0xff) * ByteToFloatScale;
this.vertexData[j+2] = (colors[i].z & 0xff) * ByteToFloatScale;
this.vertexData[j+3] = lastAlpha[0];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the colors associated with the vertices starting at
* the specified index for this object using data in color
s
* starting at index start
for length
colors.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values containing n new colors
* @param start starting color index of data in colors
.
* @param length number of colors to be copied.
*/
void setColors(int index, Color4b colors[], int start, int length) {
int offset = this.stride*index + colorOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = (colors[i].x & 0xff) * ByteToFloatScale;
this.vertexData[j+1] = (colors[i].y & 0xff) * ByteToFloatScale;
this.vertexData[j+2] = (colors[i].z & 0xff) * ByteToFloatScale;
this.vertexData[j+3] = ((colors[i].w & 0xff) * ByteToFloatScale)*lastAlpha[0];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the normal associated with the vertex at
* the specified index.
* @param index the vertex index
* @param normal the new normal
*/
void setNormal(int index, float normal[]) {
int offset = this.stride*index + normalOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
this.vertexData[offset] = normal[0];
this.vertexData[offset+1] = normal[1];
this.vertexData[offset+2] = normal[2];
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the normal associated with the vertex at
* the specified index.
* @param index the vertex index
* @param normal the vector containing the new normal
*/
void setNormal(int index, Vector3f normal) {
int offset = this.stride*index + normalOffset;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
this.vertexData[offset] = normal.x;
this.vertexData[offset+1] = normal.y;
this.vertexData[offset+2] = normal.z;
if(isLive){
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the normals associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param normals the new normals
*/
void setNormals(int index, float normals[]) {
int offset = this.stride*index + normalOffset;
int i, j, num = normals.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
for (i=0, j= offset;i < num;i += 3, j+= this.stride)
{
this.vertexData[j] = normals[i];
this.vertexData[j+1] = normals[i+1];
this.vertexData[j+2] = normals[i+2];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the normals associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param normals the vector containing the new normals
*/
void setNormals(int index, Vector3f normals[]) {
int offset = this.stride*index + normalOffset;
int i, j, num = normals.length;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
for (i=0, j= offset;i < num;i++, j+= this.stride)
{
this.vertexData[j] = normals[i].x;
this.vertexData[j+1] = normals[i].y;
this.vertexData[j+2] = normals[i].z;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the normals associated with the vertices starting at
* the specified index for this object using data in normals
* starting at index start
and ending at index start+length
.
* @param index the vertex index
* @param normals the new normals
* @param start starting normal index of data in colors
.
* @param length number of normals to be copied.
*/
void setNormals(int index, float normals[], int start, int length) {
int offset = this.stride*index + normalOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
for (i = start * 3, j = offset; i < (start + length) * 3;
i+=3, j += this.stride) {
this.vertexData[j] = normals[i];
this.vertexData[j+1] = normals[i+1];
this.vertexData[j+2] = normals[i+2];
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the normals associated with the vertices starting at
* the specified index for this object using data in normals
* starting at index start
and ending at index start+length
.
* @param index the vertex index
* @param normals the new normals
* @param start starting normal index of data in colors
.
* @param length number of normals to be copied.
*/
void setNormals(int index, Vector3f normals[], int start, int length) {
int offset = this.stride*index + normalOffset;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = normals[i].x;
this.vertexData[j+1] = normals[i].y;
this.vertexData[j+2] = normals[i].z;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the texture coordinates associated with the vertices starting at
* the specified index for this object using data in texCoords
* starting at index start
and ending at index start+length
.
* @param index the vertex index
* @param texCoords the new texture coordinates
* @param start starting texture coordinate index of data in texCoords
.
* @param length number of texture Coordinates to be copied.
*/
void setTextureCoordinates(int texCoordSet, int index, float texCoords[],
int start, int length) {
if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j, k;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
for (i = start * 4, j = offset, k = 0; k < length;
j += this.stride, k++) {
this.vertexData[j] = texCoords[i++];
this.vertexData[j+1] = texCoords[i++];
this.vertexData[j+2] = texCoords[i++];
this.vertexData[j+3] = texCoords[i++];
}
} else if ((this.vertexFormat &
GeometryArray.TEXTURE_COORDINATE_3) != 0) {
for (i = start * 3, j = offset, k = 0; k < length;
j += this.stride, k++) {
this.vertexData[j] = texCoords[i++];
this.vertexData[j+1] = texCoords[i++];
this.vertexData[j+2] = texCoords[i++];
}
} else {
for (i = start * 2, j = offset, k = 0; k < length;
j += this.stride, k++) {
this.vertexData[j] = texCoords[i++];
this.vertexData[j+1] = texCoords[i++];
}
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the texture coordinates associated with the vertices starting at
* the specified index for this object using data in texCoords
* starting at index start
and ending at index start+length
.
* @param index the vertex index
* @param texCoords the new texture coordinates
* @param start starting texture coordinate index of data in texCoords
.
* @param length number of texture Coordinates to be copied.
*/
void setTextureCoordinates(int texCoordSet, int index, Point2f texCoords[],
int start, int length) {
if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = texCoords[i].x;
this.vertexData[j+1] = texCoords[i].y;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the texture coordinates associated with the vertices starting at
* the specified index for this object using data in texCoords
* starting at index start
and ending at index start+length
.
* @param index the vertex index
* @param texCoords the new texture coordinates
* @param start starting texture coordinate index of data in texCoords
.
* @param length number of texture Coordinates to be copied.
*/
void setTextureCoordinates(int texCoordSet, int index, Point3f texCoords[],
int start, int length) {
if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = texCoords[i].x;
this.vertexData[j+1] = texCoords[i].y;
this.vertexData[j+2] = texCoords[i].z;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the texture coordinates associated with the vertices starting at
* the specified index for this object using data in texCoords
* starting at index start
and ending at index start+length
.
* @param index the vertex index
* @param texCoords the new texture coordinates
* @param start starting texture coordinate index of data in texCoords
.
* @param length number of texture Coordinates to be copied.
*/
void setTextureCoordinates(int texCoordSet, int index, TexCoord2f texCoords[],
int start, int length) {
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = texCoords[i].x;
this.vertexData[j+1] = texCoords[i].y;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the texture coordinates associated with the vertices starting at
* the specified index for this object using data in texCoords
* starting at index start
and ending at index start+length
.
* @param index the vertex index
* @param texCoords the new texture coordinates
* @param start starting texture coordinate index of data in texCoords
.
* @param length number of texture Coordinates to be copied.
*/
void setTextureCoordinates(int texCoordSet, int index,
TexCoord3f texCoords[],
int start, int length) {
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = texCoords[i].x;
this.vertexData[j+1] = texCoords[i].y;
this.vertexData[j+2] = texCoords[i].z;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the texture coordinates associated with the vertices starting at
* the specified index for this object using data in texCoords
* starting at index start
and ending at index start+length
.
* @param index the vertex index
* @param texCoords the new texture coordinates
* @param start starting texture coordinate index of data in texCoords
.
* @param length number of texture Coordinates to be copied.
*/
void setTextureCoordinates(int texCoordSet, int index,
TexCoord4f texCoords[],
int start, int length) {
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j;
for (i = start, j = offset; i < start+length; i++, j += this.stride) {
this.vertexData[j] = texCoords[i].x;
this.vertexData[j+1] = texCoords[i].y;
this.vertexData[j+2] = texCoords[i].z;
this.vertexData[j+3] = texCoords[i].w;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the vertex attribute associated with the vertex at the
* specified index in the specified vertex attribute number for
* this object.
*
* @param vertexAttrNum vertex attribute number in this geometry array
* @param index destination vertex index in this geometry array
* @param vertexAttr the Point2f containing the new vertex attribute
*/
void setVertexAttr(int vertexAttrNum, int index,
Point2f vertexAttr) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
this.vertexData[offset] = vertexAttr.x;
this.vertexData[offset+1] = vertexAttr.y;
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the vertex attribute associated with the vertex at the
* specified index in the specified vertex attribute number for
* this object.
*
* @param vertexAttrNum vertex attribute number in this geometry array
* @param index destination vertex index in this geometry array
* @param vertexAttr the Point3f containing the new vertex attribute
*/
void setVertexAttr(int vertexAttrNum, int index,
Point3f vertexAttr) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
this.vertexData[offset] = vertexAttr.x;
this.vertexData[offset+1] = vertexAttr.y;
this.vertexData[offset+2] = vertexAttr.z;
if (isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the vertex attribute associated with the vertex at the
* specified index in the specified vertex attribute number for
* this object.
*
* @param vertexAttrNum vertex attribute number in this geometry array
* @param index destination vertex index in this geometry array
* @param vertexAttr the Point4f containing the new vertex attribute
*/
void setVertexAttr(int vertexAttrNum, int index,
Point4f vertexAttr) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
this.vertexData[offset] = vertexAttr.x;
this.vertexData[offset+1] = vertexAttr.y;
this.vertexData[offset+2] = vertexAttr.z;
this.vertexData[offset+3] = vertexAttr.w;
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the vertex attributes associated with the vertices
* starting at the specified index in the specified vertex
* attribute number for this object using data in
* vertexAttrs
starting at index start
and
* ending at index start+length
.
*
* @param index starting destination vertex index in this geometry array
* @param vertexAttrs source array of 1*n, 2*n, 3*n, or 4*n values
* containing n new vertex attributes
* @param start starting source vertex index in vertexAttrs
* array.
* @param length number of vertex attributes to be copied.
*/
void setVertexAttrs(int vertexAttrNum, int index,
float[] vertexAttrs,
int start, int length) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int size = vertexAttrSizes[vertexAttrNum];
int i, j, k;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
for (i = start * size, j = offset, k = 0; k < length; i += size, j += this.stride, k++) {
for (int ii = 0; ii < size; ii++) {
this.vertexData[j+ii] = vertexAttrs[i+ii];
}
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the vertex attributes associated with the vertices
* starting at the specified index in the specified vertex
* attribute number for this object using data in
* vertexAttrs
starting at index start
and
* ending at index start+length
.
*
* @param vertexAttrNum vertex attribute number in this geometry array
* @param index starting destination vertex index in this geometry array
* @param vertexAttrs source array of Point2f objects containing new
* vertex attributes
* @param start starting source vertex index in vertexAttrs
* array.
* @param length number of vertex attributes to be copied.
*/
void setVertexAttrs(int vertexAttrNum, int index,
Point2f[] vertexAttrs,
int start, int length) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int i, j, k;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) {
this.vertexData[j] = vertexAttrs[i].x;
this.vertexData[j+1] = vertexAttrs[i].y;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the vertex attributes associated with the vertices
* starting at the specified index in the specified vertex
* attribute number for this object using data in
* vertexAttrs
starting at index start
and
* ending at index start+length
.
*
* @param vertexAttrNum vertex attribute number in this geometry array
* @param index starting destination vertex index in this geometry array
* @param vertexAttrs source array of Point3f objects containing new
* vertex attributes
* @param start starting source vertex index in vertexAttrs
* array.
* @param length number of vertex attributes to be copied.
*/
void setVertexAttrs(int vertexAttrNum, int index,
Point3f[] vertexAttrs,
int start, int length) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int i, j, k;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) {
this.vertexData[j] = vertexAttrs[i].x;
this.vertexData[j+1] = vertexAttrs[i].y;
this.vertexData[j+2] = vertexAttrs[i].z;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Sets the vertex attributes associated with the vertices
* starting at the specified index in the specified vertex
* attribute number for this object using data in
* vertexAttrs
starting at index start
and
* ending at index start+length
.
*
* @param vertexAttrNum vertex attribute number in this geometry array
* @param index starting destination vertex index in this geometry array
* @param vertexAttrs source array of Point4f objects containing new
* vertex attributes
* @param start starting source vertex index in vertexAttrs
* array.
* @param length number of vertex attributes to be copied.
*/
void setVertexAttrs(int vertexAttrNum, int index,
Point4f[] vertexAttrs,
int start, int length) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int i, j, k;
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) {
this.vertexData[j] = vertexAttrs[i].x;
this.vertexData[j+1] = vertexAttrs[i].y;
this.vertexData[j+2] = vertexAttrs[i].z;
this.vertexData[j+3] = vertexAttrs[i].w;
}
if(isLive) {
geomLock.unLock();
sendDataChangedMessage(false);
}
}
/**
* Gets the coordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param coordinate an array of 3 values that will receive the new coordinate
*/
void getCoordinate(int index, float coordinate[]) {
int offset = this.stride*index + coordinateOffset;
coordinate[0]= this.vertexData[offset];
coordinate[1]= this.vertexData[offset+1];
coordinate[2]= this.vertexData[offset+2];
}
/**
* Gets the coordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param coordinate an array of 3 values that will receive the new coordinate
*/
void getCoordinate(int index, double coordinate[]) {
int offset = this.stride*index + coordinateOffset;
coordinate[0]= (double)this.vertexData[offset];
coordinate[1]= (double)this.vertexData[offset+1];
coordinate[2]= (double)this.vertexData[offset+2];
}
/**
* Gets the coordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param coordinate a vector that will receive the new coordinate
*/
void getCoordinate(int index, Point3f coordinate) {
int offset = this.stride*index + coordinateOffset;
coordinate.x = this.vertexData[offset];
coordinate.y = this.vertexData[offset+1];
coordinate.z = this.vertexData[offset+2];
}
/**
* Gets the coordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param coordinate a vector that will receive the new coordinate
*/
void getCoordinate(int index, Point3d coordinate) {
int offset = this.stride*index + coordinateOffset;
coordinate.x = (double)this.vertexData[offset];
coordinate.y = (double)this.vertexData[offset+1];
coordinate.z = (double)this.vertexData[offset+2];
}
/**
* Gets the coordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param coordinates an array of 3*n values that will receive new coordinates
*/
void getCoordinates(int index, float coordinates[]) {
int offset = this.stride*index + coordinateOffset;
int i, j, num = coordinates.length;
for (i=0,j= offset;i < num;i +=3, j += this.stride)
{
coordinates[i] = this.vertexData[j];
coordinates[i+1]= this.vertexData[j+1];
coordinates[i+2]= this.vertexData[j+2];
}
}
/**
* Gets the coordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param coordinates an array of 3*n values that will receive new coordinates
*/
void getCoordinates(int index, double coordinates[]) {
int offset = this.stride*index + coordinateOffset;
int i, j, num = coordinates.length;
for (i=0,j= offset;i < num;i +=3, j += this.stride)
{
coordinates[i] = (double)this.vertexData[j];
coordinates[i+1]= (double)this.vertexData[j+1];
coordinates[i+2]= (double)this.vertexData[j+2];
}
}
/**
* Gets the coordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param coordinates an array of vectors that will receive new coordinates
*/
void getCoordinates(int index, Point3f coordinates[]) {
int offset = this.stride*index + coordinateOffset;
int i, j, num = coordinates.length;
for (i=0,j= offset;i < num;i++, j += this.stride)
{
coordinates[i].x = this.vertexData[j];
coordinates[i].y = this.vertexData[j+1];
coordinates[i].z = this.vertexData[j+2];
}
}
/**
* Gets the coordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param coordinates an array of vectors that will receive new coordinates
*/
void getCoordinates(int index, Point3d coordinates[]) {
int offset = this.stride*index + coordinateOffset;
int i, j, num = coordinates.length;
for (i=0,j= offset;i < num;i++, j += this.stride)
{
coordinates[i].x = (double)this.vertexData[j];
coordinates[i].y = (double)this.vertexData[j+1];
coordinates[i].z = (double)this.vertexData[j+2];
}
}
/**
* Gets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color an array of 3 or 4 values that will receive the new color
*/
void getColor(int index, float color[]) {
int offset = this.stride*index + colorOffset;
color[0]= this.vertexData[offset];
color[1]= this.vertexData[offset+1];
color[2]= this.vertexData[offset+2];
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
color[3]= this.vertexData[offset+3]/lastAlpha[0];
}
/**
* Gets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color an array of 3 or 4 values that will receive the new color
*/
void getColor(int index, byte color[]) {
int offset = this.stride*index + colorOffset;
color[0]= (byte)(this.vertexData[offset] * FloatToByteScale);
color[1]= (byte)(this.vertexData[offset+1] * FloatToByteScale);
color[2]= (byte)(this.vertexData[offset+2] * FloatToByteScale);
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
color[3]= (byte)((this.vertexData[offset+3]/lastAlpha[0]) * FloatToByteScale);
}
/**
* Gets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color a vector that will receive the new color
*/
void getColor(int index, Color3f color) {
int offset = this.stride*index + colorOffset;
color.x = this.vertexData[offset];
color.y = this.vertexData[offset+1];
color.z = this.vertexData[offset+2];
}
/**
* Gets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color a vector that will receive the new color
*/
void getColor(int index, Color4f color) {
int offset = this.stride*index + colorOffset;
color.x = this.vertexData[offset];
color.y = this.vertexData[offset+1];
color.z = this.vertexData[offset+2];
color.w= this.vertexData[offset+3]/lastAlpha[0];
}
/**
* Gets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color a vector that will receive the new color
*/
void getColor(int index, Color3b color) {
int offset = this.stride*index + colorOffset;
color.x = (byte)(this.vertexData[offset] * FloatToByteScale);
color.y = (byte)(this.vertexData[offset+1] * FloatToByteScale);
color.z = (byte)(this.vertexData[offset+2] * FloatToByteScale);
}
/**
* Gets the color associated with the vertex at
* the specified index.
* @param index the vertex index
* @param color a vector that will receive the new color
*/
void getColor(int index, Color4b color) {
int offset = this.stride*index + colorOffset;
color.x = (byte)(this.vertexData[offset] * FloatToByteScale);
color.y = (byte)(this.vertexData[offset+1] * FloatToByteScale);
color.z = (byte)(this.vertexData[offset+2] * FloatToByteScale);
color.w = (byte)((this.vertexData[offset+3]/lastAlpha[0]) * FloatToByteScale);
}
/**
* Gets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values that will receive n new colors
*/
void getColors(int index, float colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
float val = 1.0f/lastAlpha[0];
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
{
for (i=0, j= offset;i < num; i+= 4, j+= this.stride)
{
colors[i] = this.vertexData[j];
colors[i+1]= this.vertexData[j+1];
colors[i+2]= this.vertexData[j+2];
colors[i+3]= this.vertexData[j+3] * val;
}
}
else
{
for (i=0, j= offset;i < num; i+= 3, j+= this.stride)
{
colors[i] = this.vertexData[j];
colors[i+1]= this.vertexData[j+1];
colors[i+2]= this.vertexData[j+2];
}
}
}
/**
* Gets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of 3*n or 4*n values that will receive new colors
*/
void getColors(int index, byte colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
float val = 1.0f/lastAlpha[0];
if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
{
for (i=0, j= offset;i < num; i+= 4, j+= this.stride)
{
colors[i] = (byte)(this.vertexData[j] * FloatToByteScale);
colors[i+1]= (byte)(this.vertexData[j+1] * FloatToByteScale);
colors[i+2]= (byte)(this.vertexData[j+2] * FloatToByteScale);
colors[i+3]= (byte)((this.vertexData[j+3] * val) * FloatToByteScale);
}
}
else
{
for (i=0, j= offset;i < num; i+= 3, j+= this.stride)
{
colors[i] = (byte)(this.vertexData[j] * FloatToByteScale);
colors[i+1]= (byte)(this.vertexData[j+1] * FloatToByteScale);
colors[i+2]= (byte)(this.vertexData[j+2] * FloatToByteScale);
}
}
}
/**
* Gets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of vectors that will receive new colors
*/
void getColors(int index, Color3f colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
colors[i].x = this.vertexData[j];
colors[i].y = this.vertexData[j+1];
colors[i].z = this.vertexData[j+2];
}
}
/**
* Gets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of vectors that will receive new colors
*/
void getColors(int index, Color4f colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
float val = 1.0f/lastAlpha[0];
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
colors[i].x = this.vertexData[j];
colors[i].y = this.vertexData[j+1];
colors[i].z = this.vertexData[j+2];
colors[i].w = this.vertexData[j+3] * val;
}
}
/**
* Gets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of vectors that will receive new colors
*/
void getColors(int index, Color3b colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
colors[i].x = (byte)(this.vertexData[j] * FloatToByteScale);
colors[i].y = (byte)(this.vertexData[j+1] * FloatToByteScale);
colors[i].z = (byte)(this.vertexData[j+2] * FloatToByteScale);
}
}
/**
* Gets the colors associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param colors an array of vectors that will receive new colors
*/
void getColors(int index, Color4b colors[]) {
int offset = this.stride*index + colorOffset;
int i, j, num = colors.length;
float val = 1.0f/lastAlpha[0];
for (i=0, j= offset;i < num; i++, j+= this.stride)
{
colors[i].x = (byte)(this.vertexData[j] * FloatToByteScale);
colors[i].y = (byte)(this.vertexData[j+1] * FloatToByteScale);
colors[i].z = (byte)(this.vertexData[j+2] * FloatToByteScale);
colors[i].w = (byte)(this.vertexData[j+3] * val * FloatToByteScale);
}
}
/**
* Gets the normal associated with the vertex at
* the specified index.
* @param index the vertex index
* @param normal array that will receive the new normal
*/
void getNormal(int index, float normal[]) {
int offset = this.stride*index + normalOffset;
normal[0]= this.vertexData[offset];
normal[1]= this.vertexData[offset+1];
normal[2]= this.vertexData[offset+2];
}
/**
* Gets the normal associated with the vertex at
* the specified index.
* @param index the vertex index
* @param normal the vector that will receive the new normal
*/
void getNormal(int index, Vector3f normal) {
int offset = this.stride*index + normalOffset;
normal.x= this.vertexData[offset];
normal.y= this.vertexData[offset+1];
normal.z= this.vertexData[offset+2];
}
/**
* Gets the normals associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param normals array that will receive the new normals
*/
void getNormals(int index, float normals[]) {
int offset = this.stride*index + normalOffset;
int i, j, num = normals.length;
for (i=0, j= offset;i < num;i+=3, j+= this.stride)
{
normals[i] = this.vertexData[j];
normals[i+1]= this.vertexData[j+1];
normals[i+2]= this.vertexData[j+2];
}
}
/**
* Gets the normals associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param normals the vector that will receive the new normals
*/
void getNormals(int index, Vector3f normals[]) {
int offset = this.stride*index + normalOffset;
int i, j, num = normals.length;
for (i=0, j= offset;i < num;i++, j+= this.stride)
{
normals[i].x= this.vertexData[j];
normals[i].y= this.vertexData[j+1];
normals[i].z= this.vertexData[j+2];
}
}
/**
* Gets the texture co-ordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param texCoord array that will receive the new texture co-ordinate
*/
void getTextureCoordinate(int texCoordSet, int index, float texCoord[]) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
texCoord[0]= this.vertexData[offset];
texCoord[1]= this.vertexData[offset+1];
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
texCoord[2]= this.vertexData[offset+2];
} else if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_4)
!= 0) {
texCoord[2]= this.vertexData[offset+2];
texCoord[3]= this.vertexData[offset+3];
}
}
/**
* Gets the texture co-ordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param texCoord the vector that will receive the new texture co-ordinates
*/
void getTextureCoordinate(int texCoordSet, int index, TexCoord2f texCoord) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
texCoord.x= this.vertexData[offset];
texCoord.y= this.vertexData[offset+1];
}
/**
* Gets the texture co-ordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param texCoord the vector that will receive the new texture co-ordinates
*/
void getTextureCoordinate(int texCoordSet, int index, TexCoord3f texCoord) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
texCoord.x= this.vertexData[offset];
texCoord.y= this.vertexData[offset+1];
texCoord.z= this.vertexData[offset+2];
}
/**
* Gets the texture co-ordinate associated with the vertex at
* the specified index.
* @param index the vertex index
* @param texCoord the vector that will receive the new texture co-ordinates
*/
void getTextureCoordinate(int texCoordSet, int index, TexCoord4f texCoord) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
texCoord.x= this.vertexData[offset];
texCoord.y= this.vertexData[offset+1];
texCoord.z= this.vertexData[offset+2];
texCoord.w= this.vertexData[offset+3];
}
/**
* Gets the texture co-ordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param texCoords array that will receive the new texture co-ordinates
*/
void getTextureCoordinates(int texCoordSet, int index, float texCoords[]) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j, num = texCoords.length;
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
for (i=0, j= offset;i < num;i+=4, j+= this.stride)
{
texCoords[i]= this.vertexData[j];
texCoords[i+1]= this.vertexData[j+1];
texCoords[i+2]= this.vertexData[j+2];
texCoords[i+3]= this.vertexData[j+3];
}
} else if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_3)
!= 0) {
for (i=0, j= offset;i < num;i+=3, j+= this.stride)
{
texCoords[i]= this.vertexData[j];
texCoords[i+1]= this.vertexData[j+1];
texCoords[i+2]= this.vertexData[j+2];
}
} else {
for (i=0, j= offset;i < num;i+=2, j+= this.stride)
{
texCoords[i]= this.vertexData[j];
texCoords[i+1]= this.vertexData[j+1];
}
}
}
/**
* Gets the texture co-ordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param texCoords the vector that will receive the new texture co-ordinates
*/
void getTextureCoordinates(int texCoordSet, int index,
TexCoord2f texCoords[]) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j, num = texCoords.length;
for (i=0, j= offset;i < num;i++, j+= this.stride)
{
texCoords[i].x= this.vertexData[j];
texCoords[i].y= this.vertexData[j+1];
}
}
/**
* Gets the texture co-ordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param texCoords the vector that will receive the new texture co-ordinates
*/
void getTextureCoordinates(int texCoordSet, int index, TexCoord3f texCoords[]) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j, num = texCoords.length;
for (i=0, j= offset;i < num;i++, j+= this.stride)
{
texCoords[i].x= this.vertexData[j];
texCoords[i].y= this.vertexData[j+1];
texCoords[i].z= this.vertexData[j+2];
}
}
/**
* Gets the texture co-ordinates associated with the vertices starting at
* the specified index.
* @param index the vertex index
* @param texCoords the vector that will receive the new texture co-ordinates
*/
void getTextureCoordinates(int texCoordSet, int index, TexCoord4f texCoords[]) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j, num = texCoords.length;
for (i=0, j= offset;i < num;i++, j+= this.stride)
{
texCoords[i].x= this.vertexData[j];
texCoords[i].y= this.vertexData[j+1];
texCoords[i].z= this.vertexData[j+2];
texCoords[i].w= this.vertexData[j+3];
}
}
void getTextureCoordinates(int texCoordSet, int index,
Point2f texCoords[]) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j, num = texCoords.length;
for (i=0, j= offset;i < num;i++, j+= this.stride)
{
texCoords[i].x= this.vertexData[j];
texCoords[i].y= this.vertexData[j+1];
}
}
void getTextureCoordinates(int texCoordSet, int index, Point3f texCoords[]) {
int offset = this.stride*index + textureOffset +
texCoordSet * texCoordStride;
int i, j, num = texCoords.length;
for (i=0, j= offset;i < num;i++, j+= this.stride)
{
texCoords[i].x= this.vertexData[j];
texCoords[i].y= this.vertexData[j+1];
texCoords[i].z= this.vertexData[j+2];
}
}
/**
* Gets the vertex attribute associated with the vertex at
* the specified index in the specified vertex attribute number
* for this object.
*/
public void getVertexAttr(int vertexAttrNum, int index,
float[] vertexAttr) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int size = vertexAttrSizes[vertexAttrNum];
for (int i = 0; i < size; i++) {
vertexAttr[i] = this.vertexData[offset+i];
}
}
/**
* Gets the vertex attribute associated with the vertex at
* the specified index in the specified vertex attribute number
* for this object.
*/
public void getVertexAttr(int vertexAttrNum, int index,
Point2f vertexAttr) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
vertexAttr.x = this.vertexData[offset];
vertexAttr.y = this.vertexData[offset+1];
}
/**
* Gets the vertex attribute associated with the vertex at
* the specified index in the specified vertex attribute number
* for this object.
*/
public void getVertexAttr(int vertexAttrNum, int index,
Point3f vertexAttr) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
vertexAttr.x = this.vertexData[offset];
vertexAttr.y = this.vertexData[offset+1];
vertexAttr.z = this.vertexData[offset+2];
}
/**
* Gets the vertex attribute associated with the vertex at
* the specified index in the specified vertex attribute number
* for this object.
*/
public void getVertexAttr(int vertexAttrNum, int index,
Point4f vertexAttr) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
vertexAttr.x = this.vertexData[offset];
vertexAttr.y = this.vertexData[offset+1];
vertexAttr.z = this.vertexData[offset+2];
vertexAttr.w = this.vertexData[offset+3];
}
/**
* Gets the vertex attributes associated with the vertices starting at
* the specified index in the specified vertex attribute number
* for this object.
*/
public void getVertexAttrs(int vertexAttrNum, int index,
float[] vertexAttrs) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int size = vertexAttrSizes[vertexAttrNum];
int i, j, k;
for (i = 0, j = offset;
((i < vertexAttrs.length) && (j < this.vertexData.length)) ;
i += size, j += this.stride) {
for (k = 0; k < size; k++) {
vertexAttrs[i+k] = this.vertexData[j+k];
}
}
}
/**
* Gets the vertex attributes associated with the vertices starting at
* the specified index in the specified vertex attribute number
* for this object.
*/
public void getVertexAttrs(int vertexAttrNum, int index,
Point2f[] vertexAttrs) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int i, j;
for (i = 0, j = offset;
((i < vertexAttrs.length) && (j < this.vertexData.length)) ;
i++, j += this.stride) {
vertexAttrs[i].x = this.vertexData[j];
vertexAttrs[i].y = this.vertexData[j+1];
}
}
/**
* Gets the vertex attributes associated with the vertices starting at
* the specified index in the specified vertex attribute number
* for this object.
*/
public void getVertexAttrs(int vertexAttrNum, int index,
Point3f[] vertexAttrs) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int i, j;
for (i = 0, j = offset;
((i < vertexAttrs.length) && (j < this.vertexData.length)) ;
i++, j += this.stride) {
vertexAttrs[i].x = this.vertexData[j];
vertexAttrs[i].y = this.vertexData[j+1];
vertexAttrs[i].z = this.vertexData[j+2];
}
}
/**
* Gets the vertex attributes associated with the vertices starting at
* the specified index in the specified vertex attribute number
* for this object.
*/
public void getVertexAttrs(int vertexAttrNum, int index,
Point4f[] vertexAttrs) {
int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
int i, j;
for (i = 0, j = offset;
((i < vertexAttrs.length) && (j < this.vertexData.length)) ;
i++, j += this.stride) {
vertexAttrs[i].x = this.vertexData[j];
vertexAttrs[i].y = this.vertexData[j+1];
vertexAttrs[i].z = this.vertexData[j+2];
vertexAttrs[i].w = this.vertexData[j+3];
}
}
/**
* Updates geometry array data.
*/
void updateData(GeometryUpdater updater) {
boolean nullGeo = false;
// Add yourself to obtain the geometry lock
// and Thread.currentThread().sleep until you get the lock
geomLock.getLock();
inUpdater = true;
updater.updateData((Geometry)source);
inUpdater = false;
if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) {
if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
// XXXX: handle the nio buffer
if (!(this instanceof IndexedGeometryArrayRetained) ||
(vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
setupMirrorInterleavedColorPointer(false);
nullGeo = (interleavedFloatBufferImpl == null);
}
else {
setupMirrorColorPointer((vertexType & COLOR_DEFINED), false);
nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
}
}
}
else {
if (!(this instanceof IndexedGeometryArrayRetained) ||
(vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
setupMirrorInterleavedColorPointer(false);
nullGeo = (interLeavedVertexData == null);
}
else {
setupMirrorVertexPointer(vertexType & VERTEX_DEFINED);
setupMirrorColorPointer((vertexType & COLOR_DEFINED), false);
setupMirrorNormalPointer(vertexType & NORMAL_DEFINED);
setupMirrorTexCoordPointer(texCoordType);
setupMirrorVertexAttrPointer(vertexAttrType);
nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
}
}
}
//NVaidya
// User may or may not have changed indices in updater callback.
// We need to presume that the user may indeed have and, thus, will
// need to recompute maxCoordIndex unconditionally while
// geomLock is still locked.
if ((vertexFormat & GeometryArray.BY_REFERENCE_INDICES) != 0) {
assert (this instanceof IndexedGeometryArrayRetained);
if (((IndexedGeometryArrayRetained)this).getCoordIndicesRef() == null) {
nullGeo = true;
}
((IndexedGeometryArrayRetained)this).doPostUpdaterUpdate();
}
}
dirtyFlag |= VERTEX_CHANGED;
colorChanged = 0xffff;
geomLock.unLock();
if (source != null && source.isLive()) {
processCoordsChanged(nullGeo);
sendDataChangedMessage(true);
}
}
boolean intersectBoundingBox( Point3d coordinates[],
BoundingBox box,
double dist[],
Point3d iPnt) {
int i;
int out[] = new int[6];
//Do trivial vertex test.
for(i=0; i<6; i++)
out[i] = 0;
for(i=0; i= box.lower.x) && (coordinates[i].x <= box.upper.x) &&
(coordinates[i].y >= box.lower.y) && (coordinates[i].y <= box.upper.y) &&
(coordinates[i].z >= box.lower.z) && (coordinates[i].z <= box.upper.z))
// We're done! It's inside the boundingbox.
return true;
else {
if(coordinates[i].x < box.lower.x)
out[0]++; // left
if(coordinates[i].y < box.lower.y)
out[1]++; // bottom
if(coordinates[i].z < box.lower.z)
out[2]++; // back
if(coordinates[i].x > box.upper.x)
out[3]++; // right
if(coordinates[i].y > box.upper.y)
out[4]++; // top
if(coordinates[i].z > box.upper.z)
out[5]++; // front
}
}
if((out[0] == coordinates.length) || (out[1] == coordinates.length) ||
(out[2] == coordinates.length) || (out[3] == coordinates.length) ||
(out[4] == coordinates.length) || (out[5] == coordinates.length))
// we're done. primitive is outside of boundingbox.
return false;
// Setup bounding planes.
Point3d pCoor[] = new Point3d[4];
for(i=0; i<4; i++)
pCoor[i] = new Point3d();
Point3d boxCenter = new Point3d();
box.getCenter(boxCenter);
// left plane.
pCoor[0].set(box.lower.x, box.lower.y, box.lower.z);
pCoor[1].set(box.lower.x, box.lower.y, box.upper.z);
pCoor[2].set(box.lower.x, box.upper.y, box.upper.z);
pCoor[3].set(box.lower.x, box.upper.y, box.lower.z);
if (intersectPolygon(pCoor, coordinates)) {
if (dist != null) {
computeMinDistance(pCoor, boxCenter, null, dist, iPnt);
}
return true;
}
// right plane.
pCoor[0].set(box.upper.x, box.lower.y, box.lower.z);
pCoor[1].set(box.upper.x, box.upper.y, box.lower.z);
pCoor[2].set(box.upper.x, box.upper.y, box.upper.z);
pCoor[3].set(box.upper.x, box.lower.y, box.upper.z);
if (intersectPolygon(pCoor, coordinates)) {
if (dist != null) {
computeMinDistance(pCoor, boxCenter, null, dist, iPnt);
}
return true;
}
// bottom plane.
pCoor[0].set(box.upper.x, box.lower.y, box.upper.z);
pCoor[1].set(box.lower.x, box.lower.y, box.upper.z);
pCoor[2].set(box.lower.x, box.lower.y, box.lower.z);
pCoor[3].set(box.upper.x, box.lower.y, box.lower.z);
if (intersectPolygon(pCoor, coordinates)) {
if (dist != null) {
computeMinDistance(pCoor, boxCenter, null, dist, iPnt);
}
return true;
}
// top plane.
pCoor[0].set(box.upper.x, box.upper.y, box.upper.z);
pCoor[1].set(box.upper.x, box.upper.y, box.lower.z);
pCoor[2].set(box.lower.x, box.upper.y, box.lower.z);
pCoor[3].set(box.lower.x, box.upper.y, box.upper.z);
if (intersectPolygon(pCoor, coordinates)) {
if (dist != null) {
computeMinDistance(pCoor, boxCenter, null, dist, iPnt);
}
return true;
}
// front plane.
pCoor[0].set(box.upper.x, box.upper.y, box.upper.z);
pCoor[1].set(box.lower.x, box.upper.y, box.upper.z);
pCoor[2].set(box.lower.x, box.lower.y, box.upper.z);
pCoor[3].set(box.upper.x, box.lower.y, box.upper.z);
if (intersectPolygon(pCoor, coordinates)) {
if (dist != null) {
computeMinDistance(pCoor, boxCenter, null, dist, iPnt);
}
return true;
}
// back plane.
pCoor[0].set(box.upper.x, box.upper.y, box.lower.z);
pCoor[1].set(box.upper.x, box.lower.y, box.lower.z);
pCoor[2].set(box.lower.x, box.lower.y, box.lower.z);
pCoor[3].set(box.lower.x, box.upper.y, box.lower.z);
if (intersectPolygon(pCoor, coordinates)) {
if (dist != null) {
computeMinDistance(pCoor, boxCenter, null, dist, iPnt);
}
return true;
}
return false;
}
boolean intersectBoundingSphere(Point3d coordinates[],
BoundingSphere sphere,
double dist[],
Point3d iPnt)
{
int i, j;
Vector3d tempV3D = new Vector3d();
boolean esFlag;
//Do trivial vertex test.
for (i=0; i 0.0)
break;
}
for(j=i; j 0.0)
break;
}
if(j == (coordinates.length-1)) {
// System.err.println("(1) Degenerate polygon.");
return false; // Degenerate polygon.
}
/*
for(i=0; i sphere.radius) {
return false;
}
tq = pNrmDotPa / nLenSq;
q.x = sphere.center.x + tq * pNrm.x;
q.y = sphere.center.y + tq * pNrm.y;
q.z = sphere.center.z + tq * pNrm.z;
// PolyPnt2D Test.
if (pointIntersectPolygon2D( pNrm, coordinates, q)) {
if (dist != null) {
computeMinDistance(coordinates,
sphere.getCenter(),
pNrm,
dist, iPnt);
}
return true;
}
return false;
}
boolean intersectBoundingPolytope(Point3d coordinates[],
BoundingPolytope polytope,
double dist[],
Point3d iPnt)
{
boolean debug = false;
Point4d tP4d = new Point4d();
// this is a multiplier to the halfplane distance coefficients
double distanceSign = -1.0;
if(coordinates.length == 2) {
// we'll handle line separately.
if (polytope.intersect( coordinates[0],
coordinates[1], tP4d)) {
if (dist != null) {
polytope.getCenter(iPnt);
double x = tP4d.x - iPnt.x;
double y = tP4d.y - iPnt.y;
double z = tP4d.z - iPnt.z;
dist[0] = Math.sqrt(x * x + y * y + z * z);
iPnt.x = tP4d.x;
iPnt.y = tP4d.y;
iPnt.z = tP4d.z;
}
return true;
}
return false;
}
// It is a triangle or a quad.
// first test to see if any of the coordinates are all inside of the
// intersection polytope's half planes
// essentially do a matrix multiply of the constraintMatrix K*3 with
// the input coordinates 3*1 = K*1 vector
if (debug) {
System.err.println("The value of the input vertices are: ");
for(int i=0; i < coordinates.length; i++) {
System.err.println("The " +i+ " th vertex is: " + coordinates[i]);
}
System.err.println("The value of the input bounding Polytope's planes =");
for(int i=0; i < polytope.planes.length; i++) {
System.err.println("The " +i+ " th plane is: " + polytope.planes[i]);
}
}
// the direction for the intersection cost function
double centers[] = new double[4];
centers[0] = 0.8; centers[1] = 0.9; centers[2] = 1.1; centers[3] = 1.2;
boolean intersection = true;
boolean PreTest = false;
if(PreTest) {
// for each coordinate, test it with each half plane
for( int i=0; i < coordinates.length; i++) {
for (int j=0; j < polytope.planes.length; j++) {
if ( ( polytope.planes[j].x * coordinates[i].x +
polytope.planes[j].y * coordinates[i].y +
polytope.planes[j].z*coordinates[i].z) <=
(distanceSign)*polytope.planes[j].w){
// the point satisfies this particular hyperplane
intersection = true;
} else {
// the point fails this hyper plane try with a new hyper plane
intersection = false;
break;
}
}
if(intersection) {
// a point was found to be completely inside the bounding hull
if (dist != null) {
computeMinDistance(coordinates,
polytope.getCenter(),
null,
dist, iPnt);
}
return true;
}
}
} // end of pretest
// at this point all points are outside of the bounding hull
// build the problem tableau for the linear program
int numberCols = polytope.planes.length + 2 + coordinates.length + 1;
int numberRows = 1 + coordinates.length;
double problemTableau[][] = new double[numberRows][numberCols];
// compute -Mtrans = -A*P
for( int i = 0; i < polytope.planes.length; i++) {
for( int j=0; j < coordinates.length; j++) {
problemTableau[j][i] = (-1.0)* (polytope.planes[i].x*coordinates[j].x+
polytope.planes[i].y*coordinates[j].y+
polytope.planes[i].z*coordinates[j].z);
}
}
// add the other rows
for(int i = 0; i < coordinates.length; i++) {
problemTableau[i][polytope.planes.length] = -1.0;
problemTableau[i][polytope.planes.length + 1] = 1.0;
for(int j=0; j < coordinates.length; j++) {
if ( i==j ) {
problemTableau[i][j + polytope.planes.length + 2] = 1.0;
} else {
problemTableau[i][j + polytope.planes.length + 2] = 0.0;
}
// place the last column elements the Ci's
problemTableau[i][numberCols - 1] = centers[i];
}
}
// place the final rows value
for(int j = 0; j < polytope.planes.length; j++) {
problemTableau[numberRows - 1][j] =
(distanceSign)*polytope.planes[j].w;
}
problemTableau[numberRows - 1][polytope.planes.length] = 1.0;
problemTableau[numberRows - 1][polytope.planes.length+1] = -1.0;
for(int j = 0; j < coordinates.length; j++) {
problemTableau[numberRows - 1][polytope.planes.length+2+j] = 0.0;
}
if(debug) {
System.err.println("The value of the problem tableau is: " );
for(int i=0; i < problemTableau.length; i++) {
for(int j=0; j < problemTableau[0].length; j++) {
System.err.print(problemTableau[i][j] + " ");
}
System.err.println();
}
}
double distance = generalStandardSimplexSolver(problemTableau,
Float.NEGATIVE_INFINITY);
if(debug) {
System.err.println("The value returned by the general standard simplex = " +
distance);
}
if (distance == Float.POSITIVE_INFINITY) {
return false;
}
if (dist != null) {
computeMinDistance(coordinates,
polytope.getCenter(),
null,
dist, iPnt);
}
return true;
}
// optimized version using arrays of doubles, but using the standard simplex
// method to solve the LP tableau. This version has not been optimized to
// work with a particular size input tableau and is much slower than some
// of the other variants...supposedly
double generalStandardSimplexSolver(double problemTableau[][],
double stopingValue) {
boolean debug = false;
int numRow = problemTableau.length;
int numCol = problemTableau[0].length;
boolean optimal = false;
int i, pivotRowIndex, pivotColIndex;
double maxElement, element, endElement, ratio, prevRatio;
double multiplier;
if(debug) {
System.err.println("The number of rows is : " + numRow);
System.err.println("The number of columns is : " + numCol);
}
// until the optimal solution is found continue to do
// iterations of the simplex method
while(!optimal) {
if(debug) {
System.err.println("input problem tableau is:");
for(int k=0; k < numRow; k++) {
for(int j=0; j < numCol; j++) {
System.err.println("kth, jth value is:" +k+" "+j+" : " +
problemTableau[k][j]);
}
}
}
// test to see if the current solution is optimal
// check all bottom row elements except the right most one and
// if all positive or zero its optimal
for(i = 0, maxElement = 0, pivotColIndex = -1; i < numCol - 1; i++) {
// a bottom row element
element = problemTableau[numRow - 1][i];
if( element < maxElement) {
maxElement = element;
pivotColIndex = i;
}
}
// if there is no negative non-zero element then we
// have found an optimal solution (the last row of the tableau)
if(pivotColIndex == -1) {
// found an optimal solution
//System.err.println("Found an optimal solution");
optimal = true;
}
//System.err.println("The value of maxElement is:" + maxElement);
if(!optimal) {
// Case when the solution is not optimal but not known to be
// either unbounded or infeasable
// from the above we have found the maximum negative element in
// bottom row, we have also found the column for this value
// the pivotColIndex represents this
// initialize the values for the algorithm, -1 for pivotRowIndex
// indicates no solution
prevRatio = Float.POSITIVE_INFINITY;
ratio = 0.0;
pivotRowIndex = -1;
// note if all of the elements in the pivot column are zero or
// negative the problem is unbounded.
for(i = 0; i < numRow - 1; i++) {
element = problemTableau[i][pivotColIndex]; // r value
endElement = problemTableau[i][numCol-1]; // s value
// pivot according to the rule that we want to choose the row
// with smallest s/r ratio see third case
// currently we ignore valuse of r==0 (case 1) and cases where the
// ratio is negative, i.e. either r or s are negative (case 2)
if(element == 0) {
if(debug) {
System.err.println("Division by zero has occurred");
System.err.println("Within the linear program solver");
System.err.println("Ignoring the zero as a potential pivot");
}
} else if ( (element < 0.0) || (endElement < 0.0) ){
if(debug) {
System.err.println("Ignoring cases where element is negative");
System.err.println("The value of element is: " + element);
System.err.println("The value of end Element is: " + endElement);
}
} else {
ratio = endElement/element; // should be s/r
if(debug) {
System.err.println("The value of element is: " + element);
System.err.println("The value of endElement is: " + endElement);
System.err.println("The value of ratio is: " + ratio);
System.err.println("The value of prevRatio is: " + prevRatio);
System.err.println("Value of ratio <= prevRatio is :" +
(ratio <= prevRatio));
}
if(ratio <= prevRatio) {
if(debug) {
System.err.println("updating prevRatio with ratio");
}
prevRatio = ratio;
pivotRowIndex = i;
}
}
}
// if the pivotRowIndex is still -1 then we know the pivotColumn
// has no viable pivot points and the solution is unbounded or
// infeasable (all pivot elements were either zero or negative or
// the right most value was negative (the later shouldn't happen?)
if(pivotRowIndex == -1) {
if(debug) {
System.err.println("UNABLE TO FIND SOLUTION");
System.err.println("The system is infeasable or unbounded");
}
return(Float.POSITIVE_INFINITY);
}
// we now have the pivot row and col all that remains is
// to divide through by this value and subtract the appropriate
// multiple of the pivot row from all other rows to obtain
// a tableau which has a column of all zeros and one 1 in the
// intersection of pivot row and col
// divide through by the pivot value
double pivotValue = problemTableau[pivotRowIndex][pivotColIndex];
if(debug) {
System.err.println("The value of row index is: " + pivotRowIndex);
System.err.println("The value of col index is: " + pivotColIndex);
System.err.println("The value of pivotValue is: " + pivotValue);
}
// divide through by s on the pivot row to obtain a 1 in pivot col
for(i = 0; i < numCol; i++) {
problemTableau[pivotRowIndex][i] =
problemTableau[pivotRowIndex][i] / pivotValue;
}
// subtract appropriate multiple of pivot row from all other rows
// to zero out all rows except the final row and the pivot row
for(i = 0; i < numRow; i++) {
if(i != pivotRowIndex) {
multiplier = problemTableau[i][pivotColIndex];
for(int j=0; j < numCol; j++) {
problemTableau[i][j] = problemTableau[i][j] -
multiplier * problemTableau[pivotRowIndex][j];
}
}
}
}
// case when the element is optimal
}
return(problemTableau[numRow - 1][numCol - 1]);
}
boolean edgeIntersectSphere(BoundingSphere sphere, Point3d start,
Point3d end)
{
double abLenSq, acLenSq, apLenSq, abDotAp, radiusSq;
Vector3d ab = new Vector3d();
Vector3d ap = new Vector3d();
ab.x = end.x - start.x;
ab.y = end.y - start.y;
ab.z = end.z - start.z;
ap.x = sphere.center.x - start.x;
ap.y = sphere.center.y - start.y;
ap.z = sphere.center.z - start.z;
abDotAp = ab.dot(ap);
if(abDotAp < 0.0) {
return false; // line segment points away from sphere.
}
abLenSq = ab.lengthSquared();
acLenSq = abDotAp * abDotAp / abLenSq;
if(acLenSq < abLenSq) {
return false; // C doesn't lies between end points of edge.
}
radiusSq = sphere.radius * sphere.radius;
apLenSq = ap.lengthSquared();
if((apLenSq - acLenSq) <= radiusSq) {
return true;
}
return false;
}
double det2D(Point2d a, Point2d b, Point2d p)
{
return (((p).x - (a).x) * ((a).y - (b).y) +
((a).y - (p).y) * ((a).x - (b).x));
}
// Assume coord is CCW.
boolean pointIntersectPolygon2D(Vector3d normal, Point3d[] coord,
Point3d point)
{
double absNrmX, absNrmY, absNrmZ;
Point2d coord2D[] = new Point2d[coord.length];
Point2d pnt = new Point2d();
int i, j, axis;
// Project 3d points onto 2d plane.
// Note : Area of polygon is not preserve in this projection, but
// it doesn't matter here.
// Find the axis of projection.
absNrmX = Math.abs(normal.x);
absNrmY = Math.abs(normal.y);
absNrmZ = Math.abs(normal.z);
if(absNrmX > absNrmY)
axis = 0;
else
axis = 1;
if(axis == 0) {
if(absNrmX < absNrmZ)
axis = 2;
}
else if(axis == 1) {
if(absNrmY < absNrmZ)
axis = 2;
}
// System.err.println("Normal " + normal + " axis " + axis );
for(i=0; i0.0)
;
else
return false;
else
if(det2D(coord2D[j], coord2D[0], pnt)>0.0)
;
else
return false;
}
return true;
}
boolean edgeIntersectPlane(Vector3d normal, Point3d pnt, Point3d start,
Point3d end, Point3d iPnt)
{
Vector3d tempV3d = new Vector3d();
Vector3d direction = new Vector3d();
double pD, pNrmDotrDir, tr;
// Compute plane D.
tempV3d.set(pnt);
pD = normal.dot(tempV3d);
direction.x = end.x - start.x;
direction.y = end.y - start.y;
direction.z = end.z - start.z;
pNrmDotrDir = normal.dot(direction);
// edge is parallel to plane.
if(pNrmDotrDir== 0.0) {
// System.err.println("Edge is parallel to plane.");
return false;
}
tempV3d.set(start);
tr = (pD - normal.dot(tempV3d))/ pNrmDotrDir;
// Edge intersects the plane behind the edge's start.
// or exceed the edge's length.
if((tr < 0.0 ) || (tr > 1.0 )) {
// System.err.println("Edge intersects the plane behind the start or exceed end.");
return false;
}
iPnt.x = start.x + tr * direction.x;
iPnt.y = start.y + tr * direction.y;
iPnt.z = start.z + tr * direction.z;
return true;
}
// Assume coord is CCW.
boolean edgeIntersectPolygon2D(Vector3d normal, Point3d[] coord,
Point3d[] seg)
{
double absNrmX, absNrmY, absNrmZ;
Point2d coord2D[] = new Point2d[coord.length];
Point2d seg2D[] = new Point2d[2];
int i, j, axis;
// Project 3d points onto 2d plane.
// Note : Area of polygon is not preserve in this projection, but
// it doesn't matter here.
// Find the axis of projection.
absNrmX = Math.abs(normal.x);
absNrmY = Math.abs(normal.y);
absNrmZ = Math.abs(normal.z);
if(absNrmX > absNrmY)
axis = 0;
else
axis = 1;
if(axis == 0) {
if(absNrmX < absNrmZ)
axis = 2;
}
else if(axis == 1) {
if(absNrmY < absNrmZ)
axis = 2;
}
// System.err.println("Normal " + normal + " axis " + axis );
for(i=0; i nAbsY) {
if(nAbsX > nAbsZ) {
i0 = 1; // nAbsX is greatest.
i1 = 2;
}
else {
i0 = 0; // nAbsZ is greatest.
i1 = 1;
}
} else { // nAbsX <= nAbsY
if(nAbsZ > nAbsY) {
i0 = 0; // nAbsZ is greatest.
i1 = 1;
}
else {
i0 = 0; // nAbsY is greatest.
i1 = 2;
}
}
return pointInTri(v0, u0, u1, u2, i0, i1);
}
boolean pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2,
int i0, int i1) {
double a, b, c, d0, d1, d2;
// is T1 completely inside T2 ?
// check if v0 is inside tri(u0,u1,u2)
a = getCompValue(u1, u0, i1);
b = -(getCompValue(u1, u0, i0));
c = -a * getCompValue(u0, i0) - b * getCompValue(u0, i1);
d0 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
a = getCompValue(u2, u1, i1);
b = -(getCompValue(u2, u1, i0));
c = -a * getCompValue(u1, i0) - b * getCompValue(u1, i1);
d1 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
a = getCompValue(u0, u2, i1);
b = -(getCompValue(u0, u2, i0));
c = -a * getCompValue(u2, i0) - b * getCompValue(u2, i1);
d2 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
if(d0*d1>0.0) {
if(d0*d2>0.0) {
return true;
}
}
return false;
}
// this edge to edge test is based on Franlin Antonio's gem:
// "Faster line segment intersection", in Graphics Gems III, pp 199-202
boolean edgeAgainstEdge(Point3d v0, Point3d u0, Point3d u1, double aX, double aY,
int i0, int i1) {
double bX, bY, cX, cY, e, d, f;
bX = getCompValue(u0, u1,i0);
bY = getCompValue(u0, u1, i1);
cX = getCompValue(v0, u0, i0);
cY = getCompValue(v0, u0, i1);
f = aY * bX - aX * bY;
d = bY * cX - bX * cY;
if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) {
e = aX * cY - aY * cX;
if(f>0) {
if(e>=0 && e<=f)
return true;
}
else {
if(e<=0 && e>=f)
return true;
}
}
return false;
}
boolean edgeAgainstTriEdges(Point3d v0, Point3d v1, Point3d u0,
Point3d u1, Point3d u2, int i0, int i1) {
double aX, aY;
// aX = v1[i0] - v0[i0];
// aY = v1[i1] - v0[i1];
aX = getCompValue(v1, v0, i0);
aY = getCompValue(v1, v0, i1);
// test edge u0, u1 against v0, v1
if(edgeAgainstEdge(v0, u0, u1, aX, aY, i0, i1))
return true;
// test edge u1, u2 against v0, v1
if(edgeAgainstEdge(v0, u1, u2, aX, aY, i0, i1))
return true;
// test edge u2, u0 against v0, v1
if(edgeAgainstEdge(v0, u2, u0, aX, aY, i0, i1))
return true;
return false;
}
boolean coplanarTriTri(Vector3d normal, Point3d v0, Point3d v1, Point3d v2,
Point3d u0, Point3d u1, Point3d u2) {
double nAbsX, nAbsY, nAbsZ;
int i0, i1;
// first project onto an axis-aligned plane, that maximizes the area
// of the triangles, compute indices i0, i1.
nAbsX = Math.abs(normal.x);
nAbsY = Math.abs(normal.y);
nAbsZ = Math.abs(normal.z);
if(nAbsX > nAbsY) {
if(nAbsX > nAbsZ) {
i0 = 1; // nAbsX is greatest.
i1 = 2;
}
else {
i0 = 0; // nAbsZ is greatest.
i1 = 1;
}
}
else { // nAbsX <= nAbsY
if(nAbsZ > nAbsY) {
i0 = 0; // nAbsZ is greatest.
i1 = 1;
}
else {
i0 = 0; // nAbsY is greatest.
i1 = 2;
}
}
// test all edges of triangle 1 against the edges of triangle 2
if(edgeAgainstTriEdges(v0, v1, u0, u1, u2, i0, i1))
return true;
if(edgeAgainstTriEdges(v1, v2, u0, u1, u2, i0, i1))
return true;
if(edgeAgainstTriEdges(v2, v0, u0, u1, u2, i0, i1))
return true;
// finally, test if tri1 is totally contained in tri2 or vice versa.
if(pointInTri(v0, u0, u1, u2, i0, i1))
return true;
if(pointInTri(u0, v0, v1, v2, i0, i1))
return true;
return false;
}
boolean intersectTriPnt(Point3d v0, Point3d v1, Point3d v2, Point3d u) {
Vector3d e1 = new Vector3d();
Vector3d e2 = new Vector3d();
Vector3d n1 = new Vector3d();
Vector3d tempV3d = new Vector3d();
double d1, du;
// compute plane equation of triange(coord1)
e1.x = v1.x - v0.x;
e1.y = v1.y - v0.y;
e1.z = v1.z - v0.z;
e2.x = v2.x - v0.x;
e2.y = v2.y - v0.y;
e2.z = v2.z - v0.z;
n1.cross(e1,e2);
if(n1.length() == 0.0) {
// System.err.println("(1) Degenerate triangle.");
return false; // Degenerate triangle.
}
tempV3d.set(v0);
d1 = - n1.dot(tempV3d); // plane equation 1: n1.x + d1 = 0
// put u to compute signed distance to the plane.
tempV3d.set(u);
du = n1.dot(tempV3d) + d1;
// coplanarity robustness check
if(Math.abs(du) nAbsY) {
if(nAbsX > nAbsZ) {
i0 = 1; // nAbsX is greatest.
i1 = 2;
}
else {
i0 = 0; // nAbsZ is greatest.
i1 = 1;
}
}
else { // nAbsX <= nAbsY
if(nAbsZ > nAbsY) {
i0 = 0; // nAbsZ is greatest.
i1 = 1;
}
else {
i0 = 0; // nAbsY is greatest.
i1 = 2;
}
}
// finally, test if u is totally contained in tri.
if(pointInTri(u, v0, v1, v2, i0, i1)) {
return true;
}
return false;
}
/**
* Return flag indicating whether two triangles intersect. This
* uses Tomas Moller's code for fast triangle-triangle
* intersection from his "Real-Time Rendering" book.
*
* The code is now divisionless. It tests for separating by planes
* parallel to either triangle. If neither separate the
* triangles, then two cases are considered. First case is if the
* normals to the triangles are parallel. In that case, the
* triangles are coplanar and a sequence of tests are made to see
* if edges of each triangle intersect the other triangle. If the
* normals are not parallel, then the two triangles can intersect
* only on the line of intersection of the two planes. The
* intervals of intersection of the triangles with the line of
* intersection of the two planes are computed and tested for
* overlap.
*/
boolean intersectTriTri(Point3d v0, Point3d v1, Point3d v2,
Point3d u0, Point3d u1, Point3d u2) {
// System.err.println("In intersectTriTri ...");
Vector3d e1 = new Vector3d();
Vector3d e2 = new Vector3d();
Vector3d n1 = new Vector3d();
Vector3d n2 = new Vector3d();
Vector3d tempV3d = new Vector3d();
double d1, d2;
double du0, du1, du2, dv0, dv1, dv2;
double du0du1, du0du2, dv0dv1, dv0dv2;
int index;
double vp0=0.0, vp1=0.0, vp2=0.0;
double up0=0.0, up1=0.0, up2=0.0;
double bb, cc, max;
// compute plane equation of triange(coord1)
e1.x = v1.x - v0.x;
e1.y = v1.y - v0.y;
e1.z = v1.z - v0.z;
e2.x = v2.x - v0.x;
e2.y = v2.y - v0.y;
e2.z = v2.z - v0.z;
n1.cross(e1,e2);
if(n1.length() == 0.0) {
// System.err.println("(1) Degenerate triangle.");
return false; // Degenerate triangle.
}
tempV3d.set(v0);
d1 = - n1.dot(tempV3d); // plane equation 1: n1.x + d1 = 0
// put u0, u1, and u2 into plane equation 1
// to compute signed distance to the plane.
tempV3d.set(u0);
du0 = n1.dot(tempV3d) + d1;
tempV3d.set(u1);
du1 = n1.dot(tempV3d) + d1;
tempV3d.set(u2);
du2 = n1.dot(tempV3d) + d1;
// coplanarity robustness check
if(Math.abs(du0)0.0 && du0du2>0.0) {
// System.err.println("In intersectTriTri : du0du1>0.0 && du0du2>0.0");
return false;
}
// compute plane of triangle(coord2)
e1.x = u1.x - u0.x;
e1.y = u1.y - u0.y;
e1.z = u1.z - u0.z;
e2.x = u2.x - u0.x;
e2.y = u2.y - u0.y;
e2.z = u2.z - u0.z;
n2.cross(e1,e2);
if(n2.length() == 0.0) {
// System.err.println("(2) Degenerate triangle.");
return false; // Degenerate triangle.
}
tempV3d.set(u0);
d2 = - n2.dot(tempV3d); // plane equation 2: n2.x + d2 = 0
// put v0, v1, and v2 into plane equation 2
// to compute signed distance to the plane.
tempV3d.set(v0);
dv0 = n2.dot(tempV3d) + d2;
tempV3d.set(v1);
dv1 = n2.dot(tempV3d) + d2;
tempV3d.set(v2);
dv2 = n2.dot(tempV3d) + d2;
// coplanarity robustness check
if(Math.abs(dv0)0.0 && dv0dv2>0.0) {
// System.err.println("In intersectTriTri : dv0dv1>0.0 && dv0dv2>0.0");
return false;
}
// compute direction of intersection line.
tempV3d.cross(n1, n2);
// compute and index to the largest component of tempV3d.
max = Math.abs(tempV3d.x);
index = 0;
bb = Math.abs(tempV3d.y);
cc = Math.abs(tempV3d.z);
if(bb>max) {
max=bb;
index=1;
}
if(cc>max) {
max=cc;
index=2;
}
// this is the simplified projection onto L.
switch (index) {
case 0:
vp0 = v0.x;
vp1 = v1.x;
vp2 = v2.x;
up0 = u0.x;
up1 = u1.x;
up2 = u2.x;
break;
case 1:
vp0 = v0.y;
vp1 = v1.y;
vp2 = v2.y;
up0 = u0.y;
up1 = u1.y;
up2 = u2.y;
break;
case 2:
vp0 = v0.z;
vp1 = v1.z;
vp2 = v2.z;
up0 = u0.z;
up1 = u1.z;
up2 = u2.z;
break;
}
// compute intereval for triangle 1.
double a=0.0, b=0.0, c=0.0, x0=0.0, x1=0.0;
if(dv0dv1>0.0) {
// here we know that dv0dv2 <= 0.0 that is dv0 and dv1 are on the same side,
// dv2 on the other side or on the plane.
a = vp2; b = (vp0 - vp2) * dv2; c = (vp1 - vp2) * dv2;
x0 = dv2 - dv0; x1 = dv2 - dv1;
}
else if(dv0dv2>0.0) {
// here we know that dv0dv1<=0.0
a = vp1; b = (vp0 - vp1) * dv1; c = (vp2 - vp1) * dv1;
x0 = dv1 - dv0; x1 = dv1 - dv2;
}
else if((dv1*dv2>0.0) || (dv0 != 0.0)) {
// here we know that dv0vd1<=0.0 or that dv0!=0.0
a = vp0; b = (vp1 - vp0) * dv0; c = (vp2 - vp0) * dv0;
x0 = dv0 - dv1; x1 = dv0 - dv2;
}
else if(dv1 != 0.0) {
a = vp1; b = (vp0 - vp1) * dv1; c = (vp2 - vp1) * dv1;
x0 = dv1 - dv0; x1 = dv1 - dv2;
}
else if(dv2 != 0.0) {
a = vp2; b = (vp0 - vp2) * dv2; c = (vp1 - vp2) * dv2;
x0 = dv2 - dv0; x1 = dv2 - dv1;
}
else {
// triangles are coplanar
boolean toreturn = coplanarTriTri(n1, v0, v1, v2, u0, u1, u2);
return toreturn;
}
// compute intereval for triangle 2.
double d=0.0, e=0.0, f=0.0, y0=0.0, y1=0.0;
if(du0du1>0.0) {
// here we know that du0du2 <= 0.0 that is du0 and du1 are on the same side,
// du2 on the other side or on the plane.
d = up2; e = (up0 - up2) * du2; f = (up1 - up2) * du2;
y0 = du2 - du0; y1 = du2 - du1;
}
else if(du0du2>0.0) {
// here we know that du0du1<=0.0
d = up1; e = (up0 - up1) * du1; f = (up2 - up1) * du1;
y0 = du1 - du0; y1 = du1 - du2;
}
else if((du1*du2>0.0) || (du0 != 0.0)) {
// here we know that du0du1<=0.0 or that D0!=0.0
d = up0; e = (up1 - up0) * du0; f = (up2 - up0) * du0;
y0 = du0 - du1; y1 = du0 - du2;
}
else if(du1 != 0.0) {
d = up1; e = (up0 - up1) * du1; f = (up2 - up1) * du1;
y0 = du1 - du0; y1 = du1 - du2;
}
else if(du2 != 0.0) {
d = up2; e = (up0 - up2) * du2; f = (up1 - up2) * du2;
y0 = du2 - du0; y1 = du2 - du1;
}
else {
// triangles are coplanar
// System.err.println("In intersectTriTri : coplanarTriTri test 2");
boolean toreturn = coplanarTriTri(n2, v0, v1, v2, u0, u1, u2);
return toreturn;
}
double xx, yy, xxyy, tmp, isect1S, isect1E, isect2S, isect2E;
xx = x0 * x1;
yy = y0 * y1;
xxyy = xx * yy;
tmp = a * xxyy;
isect1S = tmp + b * x1 * yy;
isect1E = tmp + c * x0 * yy;
tmp = d * xxyy;
isect2S = tmp + e * y1 * xx;
isect2E = tmp + f * y0 * xx;
// sort so that isect1S <= isect1E
if(isect1S > isect1E) {
tmp = isect1S;
isect1S = isect1E;
isect1E = tmp;
}
// sort so that isect2S <= isect2E
if(isect2S > isect2E) {
tmp = isect2S;
isect2S = isect2E;
isect2E = tmp;
}
if(isect1E 0.0)
break;
}
for(j=i; j 0.0)
break;
}
if(j == (coord1.length-1)) {
// System.err.println("(1) Degenerate polygon.");
return false; // Degenerate polygon.
}
/*
for(i=0; i1) {
break;
}
}
}
if (j==0) {
return false;
}
if (coord2.length < 3) {
boolean toreturn = pointIntersectPolygon2D(pNrm, coord1, seg[0]);
return toreturn;
} else {
boolean toreturn = edgeIntersectPolygon2D(pNrm, coord1, seg);
return toreturn;
}
}
/**
* Return true if triangle or quad intersects with ray and the
* distance is stored in dist[0] and the intersect point in iPnt
* (if iPnt is not null).
*/
boolean intersectRay(Point3d coordinates[], PickRay ray, double dist[],
Point3d iPnt) {
return intersectRayOrSegment(coordinates, ray.direction, ray.origin,
dist, iPnt, false);
}
/**
* Return true if triangle or quad intersects with segment and
* the distance is stored in dist[0].
*/
boolean intersectSegment( Point3d coordinates[], Point3d start, Point3d end,
double dist[], Point3d iPnt ) {
boolean result;
Vector3d direction = new Vector3d();
direction.x = end.x - start.x;
direction.y = end.y - start.y;
direction.z = end.z - start.z;
result = intersectRayOrSegment(coordinates, direction, start, dist, iPnt, true);
return result;
}
/**
* Return true if triangle or quad intersects with ray and the distance is
* stored in pr.
*/
boolean intersectRayOrSegment(Point3d coordinates[],
Vector3d direction, Point3d origin,
double dist[], Point3d iPnt, boolean isSegment) {
Vector3d vec0, vec1, pNrm, tempV3d;
vec0 = new Vector3d();
vec1 = new Vector3d();
pNrm = new Vector3d();
double absNrmX, absNrmY, absNrmZ, pD = 0.0;
double pNrmDotrDir = 0.0;
boolean isIntersect = false;
int i, j, k=0, l = 0;
// Compute plane normal.
for (i=0; i 0.0) {
break;
}
}
for (j=l; j 0.0) {
break;
}
}
pNrm.cross(vec0,vec1);
if ((vec1.length() == 0) || (pNrm.length() == 0)) {
// degenerate to line if vec0.length() == 0
// or vec0.length > 0 and vec0 parallel to vec1
k = (l == 0 ? coordinates.length-1: l-1);
isIntersect = intersectLineAndRay(coordinates[l],
coordinates[k],
origin,
direction,
dist,
iPnt);
// put the Vectors on the freelist
return isIntersect;
}
// It is possible that Quad is degenerate to Triangle
// at this point
pNrmDotrDir = pNrm.dot(direction);
// Ray is parallel to plane.
if (pNrmDotrDir == 0.0) {
// Ray is parallel to plane
// Check line/triangle intersection on plane.
for (i=0; i < coordinates.length ;i++) {
if (i != coordinates.length-1) {
k = i+1;
} else {
k = 0;
}
if (intersectLineAndRay(coordinates[i],
coordinates[k],
origin,
direction,
dist,
iPnt)) {
isIntersect = true;
break;
}
}
return isIntersect;
}
// Plane equation: (p - p0)*pNrm = 0 or p*pNrm = pD;
tempV3d = new Vector3d();
tempV3d.set(coordinates[0]);
pD = pNrm.dot(tempV3d);
tempV3d.set(origin);
// Substitute Ray equation:
// p = origin + pi.distance*direction
// into the above Plane equation
dist[0] = (pD - pNrm.dot(tempV3d))/ pNrmDotrDir;
// Ray intersects the plane behind the ray's origin.
if ((dist[0] < -EPS ) ||
(isSegment && (dist[0] > 1.0+EPS))) {
// Ray intersects the plane behind the ray's origin
// or intersect point not fall in Segment
return false;
}
// Now, one thing for sure the ray intersect the plane.
// Find the intersection point.
if (iPnt == null) {
iPnt = new Point3d();
}
iPnt.x = origin.x + direction.x * dist[0];
iPnt.y = origin.y + direction.y * dist[0];
iPnt.z = origin.z + direction.z * dist[0];
// Project 3d points onto 2d plane
// Find the axis so that area of projection is maximize.
absNrmX = Math.abs(pNrm.x);
absNrmY = Math.abs(pNrm.y);
absNrmZ = Math.abs(pNrm.z);
// All sign of (y - y0) (x1 - x0) - (x - x0) (y1 - y0)
// must agree.
double sign, t, lastSign = 0;
Point3d p0 = coordinates[coordinates.length-1];
Point3d p1 = coordinates[0];
isIntersect = true;
if (absNrmX > absNrmY) {
if (absNrmX < absNrmZ) {
for (i=0; i < coordinates.length; i++) {
p0 = coordinates[i];
p1 = (i != coordinates.length-1 ? coordinates[i+1]: coordinates[0]);
sign = (iPnt.y - p0.y)*(p1.x - p0.x) -
(iPnt.x - p0.x)*(p1.y - p0.y);
if (isNonZero(sign)) {
if (sign*lastSign < 0) {
isIntersect = false;
break;
}
lastSign = sign;
} else { // point on line, check inside interval
t = p1.y - p0.y;
if (isNonZero(t)) {
t = (iPnt.y - p0.y)/t;
isIntersect = ((t > -EPS) && (t < 1+EPS));
break;
} else {
t = p1.x - p0.x;
if (isNonZero(t)) {
t = (iPnt.x - p0.x)/t;
isIntersect = ((t > -EPS) && (t < 1+EPS));
break;
} else {
// Ignore degenerate line=>point happen when Quad => Triangle.
// Note that by next round sign*lastSign = 0 so it will
// not pass the interest test. This should only happen once in the
// loop because we already check for degenerate geometry before.
}
}
}
}
} else {
for (i=0; i -EPS) && (t < 1+EPS));
break;
} else {
t = p1.z - p0.z;
if (isNonZero(t)) {
t = (iPnt.z - p0.z)/t;
isIntersect = ((t > -EPS) && (t < 1+EPS));
break;
} else {
//degenerate line=>point
}
}
}
}
}
} else {
if (absNrmY < absNrmZ) {
for (i=0; i -EPS) && (t < 1+EPS));
break;
} else {
t = p1.x - p0.x;
if (isNonZero(t)) {
t = (iPnt.x - p0.x)/t;
isIntersect = ((t > -EPS) && (t < 1+EPS));
break;
} else {
//degenerate line=>point
}
}
}
}
} else {
for (i=0; i -EPS) && (t < 1+EPS));
break;
} else {
t = p1.z - p0.z;
if (isNonZero(t)) {
t = (iPnt.z - p0.z)/t;
isIntersect = ((t > -EPS) && (t < 1+EPS));
break;
} else {
//degenerate line=>point
}
}
}
}
}
}
if (isIntersect) {
dist[0] *= direction.length();
}
return isIntersect;
}
static final boolean isNonZero(double v) {
return ((v > EPS) || (v < -EPS));
}
/**
* Return true if point is on the inside of halfspace test. The
* halfspace is partition by the plane of triangle or quad.
*/
boolean inside( Point3d coordinates[], PickPoint point, int ccw ) {
Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
Vector3d pNrm = new Vector3d();
double pD = 0.0;
Vector3d tempV3d = new Vector3d();
int i, j;
// Compute plane normal.
for(i=0; i 0.0)
break;
}
for(j=i; j 0.0)
break;
}
if(j == (coordinates.length-1)) {
// System.err.println("(1) Degenerate polygon.");
return false; // Degenerate polygon.
}
/*
System.err.println("Ray orgin : " + ray.origin + " dir " + ray.direction);
System.err.println("Triangle/Quad :");
for(i=0; i (temp + EPS)))
return false;
}
if(flag < 2) {
temp = ori.z + dist[0] * dir.z;
if((pnt.z < (temp - EPS)) || (pnt.z > (temp + EPS)))
return false;
}
return true;
}
boolean intersectLineAndRay(Point3d start, Point3d end,
Point3d ori, Vector3d dir, double dist[],
Point3d iPnt) {
double m00, m01, m10, m11;
double mInv00, mInv01, mInv10, mInv11;
double dmt, t, s, tmp1, tmp2;
Vector3d lDir;
// System.err.println("GeometryArrayRetained : intersectLineAndRay");
// System.err.println("start " + start + " end " + end );
// System.err.println("ori " + ori + " dir " + dir);
lDir = new Vector3d();
lDir.x = (end.x - start.x);
lDir.y = (end.y - start.y);
lDir.z = (end.z - start.z);
m00 = lDir.x;
m01 = -dir.x;
m10 = lDir.y;
m11 = -dir.y;
// Get the determinant.
dmt = (m00 * m11) - (m10 * m01);
if (dmt==0.0) { // No solution, check degenerate line
boolean isIntersect = false;
if ((lDir.x == 0) && (lDir.y == 0) && (lDir.z == 0)) {
isIntersect = intersectPntAndRay(start, ori, dir, dist);
if (isIntersect && (iPnt != null)) {
iPnt.set(start);
}
}
return isIntersect;
}
// Find the inverse.
tmp1 = 1/dmt;
mInv00 = tmp1 * m11;
mInv01 = tmp1 * (-m01);
mInv10 = tmp1 * (-m10);
mInv11 = tmp1 * m00;
tmp1 = ori.x - start.x;
tmp2 = ori.y - start.y;
t = mInv00 * tmp1 + mInv01 * tmp2;
s = mInv10 * tmp1 + mInv11 * tmp2;
if(s<0.0) { // Before the origin of ray.
// System.err.println("Before the origin of ray " + s);
return false;
}
if((t<0)||(t>1.0)) {// Before or after the end points of line.
// System.err.println("Before or after the end points of line. " + t);
return false;
}
tmp1 = ori.z + s * dir.z;
tmp2 = start.z + t * lDir.z;
if((tmp1 < (tmp2 - EPS)) || (tmp1 > (tmp2 + EPS))) {
// System.err.println("No intersection : tmp1 " + tmp1 + " tmp2 " + tmp2);
return false;
}
dist[0] = s;
if (iPnt != null) {
// compute point of intersection.
iPnt.x = ori.x + dir.x * dist[0];
iPnt.y = ori.y + dir.y * dist[0];
iPnt.z = ori.z + dir.z * dist[0];
}
// System.err.println("Intersected : tmp1 " + tmp1 + " tmp2 " + tmp2);
return true;
}
/**
Return true if triangle or quad intersects with cylinder. The
distance is stored in dist.
*/
boolean intersectCylinder(Point3d coordinates[], PickCylinder cyl,
double dist[], Point3d iPnt) {
Point3d origin = new Point3d();
Point3d end = new Point3d();
Vector3d direction = new Vector3d();
Point3d iPnt1 = new Point3d();
Vector3d originToIpnt = new Vector3d();
if (iPnt == null) {
iPnt = new Point3d();
}
// Get cylinder information
cyl.getOrigin (origin);
cyl.getDirection (direction);
double radius = cyl.getRadius ();
if (cyl instanceof PickCylinderSegment) {
((PickCylinderSegment)cyl).getEnd (end);
}
// If the ray intersects, we're good (do not do this if we only have
// a segment
if (coordinates.length > 2) {
if (cyl instanceof PickCylinderRay) {
if (intersectRay(coordinates,
new PickRay(origin, direction),
dist, iPnt)) {
return true;
}
}
else {
if (intersectSegment(coordinates, origin, end, dist, iPnt)) {
return true;
}
}
}
// Ray doesn't intersect, check distance to edges
double sqDistToEdge;
int j;
for (int i=0; i 2) {
if (cone instanceof PickConeRay) {
if (intersectRay(coordinates,
new PickRay (origin, direction),
dist, iPnt)) {
return true;
}
}
else {
if (intersectSegment(coordinates, origin, end, dist, iPnt)) {
return true;
}
}
}
// Ray doesn't intersect, check distance to edges
double sqDistToEdge;
int j = 0;
for (int i=0; i= coords.getROBuffer().limit()) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
}
} else if (coords.getROBuffer().limit() < (3*(initialCoordIndex+validVertexCount))) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
}
// lock the geometry and start to do real work
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
coordRefBuffer = coords;
if(coords == null) {
floatBufferRefCoords = null;
doubleBufferRefCoords = null;
// XXXX: if not mix java array with nio buffer
// vertexType can be used as vertexTypeBuffer
vertexType &= ~PD;
vertexType &= ~PF;
}else {
switch (coords.bufferType) {
case FLOAT:
floatBufferRefCoords = (FloatBuffer)coords.getROBuffer();
doubleBufferRefCoords = null;
vertexType |= PF;
vertexType &= ~PD;
break;
case DOUBLE:
floatBufferRefCoords = null;
doubleBufferRefCoords = (DoubleBuffer)coords.getROBuffer();
vertexType |= PD;
vertexType &= ~PF;
break;
default:
break;
}
}
// need not call setupMirrorVertexPointer() since
// we are not going to set mirror in NIO buffer case
// XXXX: if we need to mix java array with buffer,
// we may need to consider setupMirrorVertexPointer()
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && source != null) {
if (isLive) {
processCoordsChanged((coords == null));
sendDataChangedMessage(true);
} else {
boundsDirty = true;
}
}
}
J3DBuffer getCoordRefBuffer() {
return coordRefBuffer;
}
void setCoordRefFloat(float[] coords) {
// If non-null coordinate and vertType is either defined
// to be something other than PF, then issue an error
if (coords != null) {
if ((vertexType & VERTEX_DEFINED) != 0 &&
(vertexType & VERTEX_DEFINED) != PF) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (3 * idx.maxCoordIndex >= coords.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
}
} else if (coords.length < 3 * (initialCoordIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
floatRefCoords = coords;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (coords == null)
vertexType &= ~PF;
else
vertexType |= PF;
}
else {
setupMirrorVertexPointer(PF);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && source != null) {
if (isLive) {
processCoordsChanged(coords == null);
sendDataChangedMessage(true);
} else {
boundsDirty = true;
}
}
}
float[] getCoordRefFloat() {
return floatRefCoords;
}
void setCoordRefDouble(double[] coords) {
if (coords != null) {
if ((vertexType & VERTEX_DEFINED) != 0 &&
(vertexType & VERTEX_DEFINED) != PD) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (3 * idx.maxCoordIndex >= coords.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
}
} else if (coords.length < 3 * (initialCoordIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
doubleRefCoords = coords;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (coords == null)
vertexType &= ~PD;
else
vertexType |= PD;
}
else {
setupMirrorVertexPointer(PD);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && source != null) {
if (isLive) {
processCoordsChanged(coords == null);
sendDataChangedMessage(true);
} else {
boundsDirty = true;
}
}
}
double[] getCoordRefDouble() {
return doubleRefCoords;
}
void setCoordRef3f(Point3f[] coords) {
if (coords != null) {
if ((vertexType & VERTEX_DEFINED) != 0 &&
(vertexType & VERTEX_DEFINED) != P3F) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxCoordIndex >= coords.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
}
} else if (coords.length < (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
p3fRefCoords = coords;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (coords == null)
vertexType &= ~P3F;
else
vertexType |= P3F;
}
else {
setupMirrorVertexPointer(P3F);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && source != null) {
if (isLive) {
processCoordsChanged(coords == null);
sendDataChangedMessage(true);
} else {
boundsDirty = true;
}
}
}
Point3f[] getCoordRef3f() {
return p3fRefCoords;
}
void setCoordRef3d(Point3d[] coords) {
if (coords != null) {
if ((vertexType & VERTEX_DEFINED) != 0 &&
(vertexType & VERTEX_DEFINED) != P3D) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxCoordIndex >= coords.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
}
} else if (coords.length < (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
p3dRefCoords = coords;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (coords == null)
vertexType &= ~P3D;
else
vertexType |= P3D;
} else {
setupMirrorVertexPointer(P3D);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && source != null) {
if (isLive) {
processCoordsChanged(coords == null);
sendDataChangedMessage(true);
} else {
boundsDirty = true;
}
}
}
Point3d[] getCoordRef3d() {
return p3dRefCoords;
}
void setColorRefFloat(float[] colors) {
if (colors != null) {
if ((vertexType & COLOR_DEFINED) != 0 &&
(vertexType & COLOR_DEFINED) != CF) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if ((vertexFormat & GeometryArray.COLOR) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray123"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (getColorStride() * idx.maxColorIndex >= colors.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
} else if (colors.length < getColorStride() * (initialColorIndex+ validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
floatRefColors = colors;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (colors == null)
vertexType &= ~CF;
else
vertexType |= CF;
}
else {
setupMirrorColorPointer(CF, false);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
float[] getColorRefFloat() {
return floatRefColors;
}
// set the color with nio buffer
void setColorRefBuffer(J3DBuffer colors) {
if (colors != null) {
switch(colors.bufferType) {
case FLOAT:
assert ((FloatBuffer)colors.getROBuffer()).isDirect();
break;
case BYTE:
assert ((ByteBuffer)colors.getROBuffer()).isDirect();
break;
case NULL:
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray115"));
default:
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
}
if ((vertexFormat & GeometryArray.COLOR) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray123"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (getColorStride() * idx.maxColorIndex >= colors.getROBuffer().limit()) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
} else if (colors.getROBuffer().limit() <
getColorStride() * (initialColorIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
colorRefBuffer = colors;
if(colors == null) {
floatBufferRefColors = null;
byteBufferRefColors = null;
} else {
switch (colors.bufferType) {
case FLOAT:
floatBufferRefColors = (FloatBuffer)colors.getROBuffer();
byteBufferRefColors = null;
break;
case BYTE:
byteBufferRefColors = (ByteBuffer)colors.getROBuffer();
floatBufferRefColors = null;
break;
default:
break;
}
}
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if(colors == null) {
vertexType &= ~CF;
vertexType &= ~CUB;
} else {
switch (colors.bufferType) {
case FLOAT:
vertexType |= CF;
vertexType &= ~CUB;
break;
case BYTE:
vertexType |= CUB;
vertexType &= ~CF;
break;
default:
break;
}
}
}
else {
setupMirrorColorPointer(CF|CUB, false);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
// return the color data in nio buffer format
J3DBuffer getColorRefBuffer() {
return colorRefBuffer;
}
void setColorRefByte(byte[] colors) {
if (colors != null) {
if ((vertexType & COLOR_DEFINED) != 0 &&
(vertexType & COLOR_DEFINED) != CUB) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if ((vertexFormat & GeometryArray.COLOR) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray123"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (getColorStride() * idx.maxColorIndex >= colors.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
} else if (colors.length < getColorStride() * (initialColorIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
byteRefColors = colors;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (colors == null)
vertexType &= ~CUB;
else
vertexType |= CUB;
}
else {
setupMirrorColorPointer(CUB, false);
}
if(isLive){
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
byte[] getColorRefByte() {
return byteRefColors;
}
void setColorRef3f(Color3f[] colors) {
if (colors != null) {
if ((vertexType & COLOR_DEFINED) != 0 &&
(vertexType & COLOR_DEFINED) != C3F) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if ((vertexFormat & GeometryArray.COLOR_3) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray92"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxColorIndex >= colors.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
} else if (colors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
c3fRefColors = colors;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (colors == null)
vertexType &= ~C3F;
else
vertexType |= C3F;
}
else {
setupMirrorColorPointer(C3F, false);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
Color3f[] getColorRef3f() {
return c3fRefColors;
}
void setColorRef4f(Color4f[] colors) {
if (colors != null) {
if ((vertexType & COLOR_DEFINED) != 0 &&
(vertexType & COLOR_DEFINED) != C4F) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if ((vertexFormat & GeometryArray.COLOR_4) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray93"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxColorIndex >= colors.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
} else if (colors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
c4fRefColors = colors;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (colors == null)
vertexType &= ~C4F;
else
vertexType |= C4F;
}
else {
setupMirrorColorPointer(C4F, false);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
Color4f[] getColorRef4f() {
return c4fRefColors;
}
void setColorRef3b(Color3b[] colors) {
if (colors != null) {
if ((vertexType & COLOR_DEFINED) != 0 &&
(vertexType & COLOR_DEFINED) != C3UB) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if ((vertexFormat & GeometryArray.COLOR_3) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray92"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxColorIndex >= colors.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
} else if (colors.length < (initialColorIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
c3bRefColors = colors;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (colors == null)
vertexType &= ~C3UB;
else
vertexType |= C3UB;
}
else {
setupMirrorColorPointer(C3UB, false);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
Color3b[] getColorRef3b() {
return c3bRefColors;
}
void setColorRef4b(Color4b[] colors) {
if (colors != null) {
if ((vertexType & COLOR_DEFINED) != 0 &&
(vertexType & COLOR_DEFINED) != C4UB) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if ((vertexFormat & GeometryArray.COLOR_4) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray93"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this;
if (idx.maxColorIndex >= colors.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
} else if (colors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
c4bRefColors = colors;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (colors == null)
vertexType &= ~C4UB;
else
vertexType |= C4UB;
}
else {
setupMirrorColorPointer(C4UB, false);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
Color4b[] getColorRef4b() {
return c4bRefColors;
}
void setNormalRefFloat(float[] normals) {
if (normals != null) {
if ((vertexType & NORMAL_DEFINED) != 0 &&
(vertexType & NORMAL_DEFINED) != NF) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if ((vertexFormat & GeometryArray.NORMALS) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray122"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxNormalIndex*3 >= normals.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray26"));
}
} else if (normals.length < 3 * (initialNormalIndex + validVertexCount )) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
floatRefNormals = normals;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (normals == null)
vertexType &= ~NF;
else
vertexType |= NF;
}
else {
setupMirrorNormalPointer(NF);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
float[] getNormalRefFloat() {
return floatRefNormals;
}
// setup the normal with nio buffer
void setNormalRefBuffer(J3DBuffer normals) {
FloatBuffer bufferImpl = null;
if (normals != null) {
if(normals.bufferType != J3DBuffer.Type.FLOAT)
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
bufferImpl = (FloatBuffer)normals.getROBuffer();
assert bufferImpl.isDirect();
if ((vertexFormat & GeometryArray.NORMALS) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray122"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxNormalIndex * 3 >=
((FloatBuffer)normals.getROBuffer()).limit()) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray26"));
}
} else if (bufferImpl.limit() < 3 * (initialNormalIndex + validVertexCount )) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
normalRefBuffer = normals;
if (normals == null) {
vertexType &= ~NF;
floatBufferRefNormals = null;
}
else {
vertexType |= NF;
floatBufferRefNormals = bufferImpl;
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
J3DBuffer getNormalRefBuffer() {
return normalRefBuffer;
}
void setNormalRef3f(Vector3f[] normals) {
if (normals != null) {
if ((vertexType & NORMAL_DEFINED) != 0 &&
(vertexType & NORMAL_DEFINED) != N3F) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
}
if ((vertexFormat & GeometryArray.NORMALS) == 0) {
throw new IllegalStateException(J3dI18N.getString("GeometryArray122"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxNormalIndex >= normals.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray26"));
}
} else if (normals.length < (initialNormalIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
v3fRefNormals = normals;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
if (normals == null)
vertexType &= ~N3F;
else
vertexType |= N3F;
}
else {
setupMirrorNormalPointer(N3F);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
Vector3f[] getNormalRef3f() {
return v3fRefNormals;
}
final int getColorStride() {
return ((vertexFormat & GeometryArray.WITH_ALPHA) != 0 ? 4 : 3);
}
final int getTexStride() {
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
return 2;
}
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
return 3;
}
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
return 4;
}
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray121"));
}
void setTexCoordRefFloat(int texCoordSet, float[] texCoords) {
if (texCoordType != 0 && texCoordType != TF) {
if (texCoords != null) {
throw new IllegalArgumentException(
J3dI18N.getString("GeometryArray98"));
}
return;
}
if (texCoords != null) {
int ts = getTexStride();
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxTexCoordIndices[texCoordSet]*ts >= texCoords.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray25"));
}
} else if (texCoords.length < ts*(initialTexCoordIndex[texCoordSet]+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray113"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
refTexCoords[texCoordSet] = texCoords;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
texCoordType = TF;
validateTexCoordPointerType();
}
else {
setupMirrorTexCoordPointer(texCoordSet, TF);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
float[] getTexCoordRefFloat(int texCoordSet) {
return ((float[])refTexCoords[texCoordSet]);
}
// set the tex coord with nio buffer
void setTexCoordRefBuffer(int texCoordSet, J3DBuffer texCoords) {
FloatBuffer bufferImpl = null;
if (texCoords != null) {
if(texCoords.bufferType != J3DBuffer.Type.FLOAT)
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
bufferImpl = (FloatBuffer)texCoords.getROBuffer();
int bufferSize = bufferImpl.limit();
assert bufferImpl.isDirect();
int ts = getTexStride();
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxTexCoordIndices[texCoordSet] * ts >= bufferSize) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray25"));
}
} else if (bufferSize < ts*(initialTexCoordIndex[texCoordSet] + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray113"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
// refTexCoordsBuffer contains J3DBuffer object for tex coord
refTexCoordsBuffer[texCoordSet] = texCoords;
if (texCoords == null) {
refTexCoords[texCoordSet] = null;
}
else {
// refTexCoords contains NIOBuffer object for tex coord
refTexCoords[texCoordSet] = bufferImpl;
}
texCoordType = TF;
validateTexCoordPointerType();
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
J3DBuffer getTexCoordRefBuffer(int texCoordSet) {
return refTexCoordsBuffer[texCoordSet];
}
void setTexCoordRef2f(int texCoordSet, TexCoord2f[] texCoords) {
if (texCoordType != 0 && texCoordType != T2F) {
if (texCoords != null) {
throw new IllegalArgumentException(
J3dI18N.getString("GeometryArray98"));
}
return;
}
if (texCoords != null) {
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) == 0) {
throw new IllegalStateException(
J3dI18N.getString("GeometryArray94"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxTexCoordIndices[texCoordSet] >= texCoords.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray25"));
}
} else if (texCoords.length < (initialTexCoordIndex[texCoordSet] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray113"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
refTexCoords[texCoordSet] = texCoords;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
texCoordType = T2F;
validateTexCoordPointerType();
}
else {
setupMirrorTexCoordPointer(texCoordSet, T2F);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
TexCoord2f[] getTexCoordRef2f(int texCoordSet) {
if (refTexCoords != null && refTexCoords[texCoordSet] != null &&
refTexCoords[texCoordSet] instanceof TexCoord2f[]) {
return ((TexCoord2f[])refTexCoords[texCoordSet]);
} else {
return null;
}
}
void setTexCoordRef3f(int texCoordSet, TexCoord3f[] texCoords) {
if (texCoordType != 0 && texCoordType != T3F) {
if (texCoords != null) {
throw new IllegalArgumentException(
J3dI18N.getString("GeometryArray98"));
}
return;
}
if (texCoords != null) {
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) == 0) {
throw new IllegalStateException(
J3dI18N.getString("GeometryArray95"));
}
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxTexCoordIndices[texCoordSet] >= texCoords.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray25"));
}
} else if (texCoords.length < (initialTexCoordIndex[texCoordSet] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray113"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
refTexCoords[texCoordSet] = texCoords;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
texCoordType = T3F;
validateTexCoordPointerType();
}
else {
setupMirrorTexCoordPointer(texCoordSet, T3F);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
TexCoord3f[] getTexCoordRef3f(int texCoordSet) {
if (refTexCoords != null && refTexCoords[texCoordSet] != null &&
refTexCoords[texCoordSet] instanceof TexCoord3f[]) {
return ((TexCoord3f[])refTexCoords[texCoordSet]);
} else {
return null;
}
}
/**
* Sets the float vertex attribute array reference for the
* specified vertex attribute number to the specified array.
*/
void setVertexAttrRefFloat(int vertexAttrNum, float[] vertexAttrs) {
// XXXX: Add the following test if we ever add double-precision types
/*
if (vertexAttrType != 0 && vertexAttrType != AF) {
if (vertexAttrs != null) {
// XXXX: new exception string
throw new IllegalArgumentException(
J3dI18N.getString("GeometryArray98-XXX"));
}
return;
}
*/
if (vertexAttrs != null) {
int sz = vertexAttrSizes[vertexAttrNum];
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (sz*idx.maxVertexAttrIndices[vertexAttrNum] >= vertexAttrs.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30"));
}
} else if (vertexAttrs.length < sz*(initialVertexAttrIndex[vertexAttrNum] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray129"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
floatRefVertexAttrs[vertexAttrNum] = vertexAttrs;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
vertexAttrType = AF;
validateVertexAttrPointerType();
}
else {
setupMirrorVertexAttrPointer(vertexAttrNum, AF);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
/**
* Gets the float vertex attribute array reference for the specified
* vertex attribute number.
*/
float[] getVertexAttrRefFloat(int vertexAttrNum) {
return floatRefVertexAttrs[vertexAttrNum];
}
/**
* Sets the vertex attribute buffer reference for the specified
* vertex attribute number to the specified buffer object.
*/
void setVertexAttrRefBuffer(int vertexAttrNum, J3DBuffer vertexAttrs) {
FloatBuffer bufferImpl = null;
if (vertexAttrs != null) {
if(vertexAttrs.bufferType != J3DBuffer.Type.FLOAT)
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
bufferImpl = (FloatBuffer)vertexAttrs.getROBuffer();
int bufferSize = bufferImpl.limit();
assert bufferImpl.isDirect();
int sz = vertexAttrSizes[vertexAttrNum];
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (idx.maxVertexAttrIndices[vertexAttrNum] * sz >= bufferSize) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30"));
}
} else if (bufferSize < sz*(initialVertexAttrIndex[vertexAttrNum] + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray129"));
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
vertexAttrsRefBuffer[vertexAttrNum] = vertexAttrs;
if (vertexAttrs == null) {
floatBufferRefVertexAttrs[vertexAttrNum] = null;
}
else {
floatBufferRefVertexAttrs[vertexAttrNum] = bufferImpl;
}
vertexAttrType = AF;
validateVertexAttrPointerType();
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
sendDataChangedMessage(false);
}
}
/**
* Gets the vertex attribute array buffer reference for the specified
* vertex attribute number.
*/
J3DBuffer getVertexAttrRefBuffer(int vertexAttrNum) {
return vertexAttrsRefBuffer[vertexAttrNum];
}
void setInterleavedVertices(float[] vertexData) {
if (vertexData != null) {
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (stride * idx.maxCoordIndex >= vertexData.length) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
}
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
for (int i = 0; i < texCoordSetCount; i++) {
if (stride * idx.maxTexCoordIndices[i] >= vertexData.length) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("IndexedGeometryArray25"));
}
}
}
if (((this.vertexFormat & GeometryArray.COLOR) != 0) &&
(stride * idx.maxColorIndex >= vertexData.length)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
if (((this.vertexFormat & GeometryArray.NORMALS) != 0) &&
(stride * idx.maxNormalIndex >= vertexData.length)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray26"));
}
} else {
if (vertexData.length < (stride * (initialVertexIndex+validVertexCount)))
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
}
}
// If the geometry has been rendered transparent, then make a copy
// of the color pointer with 4f
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VERTEX_CHANGED;
colorChanged = 0xffff;
interLeavedVertexData = vertexData;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
setupMirrorInterleavedColorPointer(false);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
processCoordsChanged(vertexData == null);
sendDataChangedMessage(true);
}
}
// set the interleaved vertex with NIO buffer
void setInterleavedVertexBuffer(J3DBuffer vertexData) {
FloatBuffer bufferImpl = null;
if (vertexData != null ){
if (vertexData.bufferType != J3DBuffer.Type.FLOAT)
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
bufferImpl = (FloatBuffer)vertexData.getROBuffer();
assert bufferImpl.isDirect();
int bufferSize = bufferImpl.limit();
if (this instanceof IndexedGeometryArrayRetained) {
IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
if (stride * idx.maxCoordIndex >= bufferSize) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
}
if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
for (int i = 0; i < texCoordSetCount; i++) {
if (stride * idx.maxTexCoordIndices[i] >= bufferSize) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("IndexedGeometryArray25"));
}
}
}
if (((this.vertexFormat & GeometryArray.COLOR) != 0) &&
(stride * idx.maxColorIndex >= bufferSize)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
}
if (((this.vertexFormat & GeometryArray.NORMALS) != 0) &&
(stride * idx.maxNormalIndex >= bufferSize)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
}
} else {
if (bufferSize < (stride * (initialVertexIndex+validVertexCount)))
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
}
}
// If the geometry has been rendered transparent, then make a copy
// of the color pointer with 4f
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VERTEX_CHANGED;
colorChanged = 0xffff;
interleavedVertexBuffer = vertexData;
if(vertexData == null)
interleavedFloatBufferImpl = null;
else
interleavedFloatBufferImpl = bufferImpl;
if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
setupMirrorInterleavedColorPointer(false);
}
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
processCoordsChanged(vertexData == null);
sendDataChangedMessage(true);
}
}
float[] getInterleavedVertices() {
return interLeavedVertexData;
}
J3DBuffer getInterleavedVertexBuffer() {
return interleavedVertexBuffer;
}
void setValidVertexCount(int validVertexCount) {
boolean nullGeo = false;
if (validVertexCount < 0) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray110"));
}
if ((initialVertexIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray100"));
}
if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
// Interleaved, by-ref
// use nio buffer for interleaved data
if(( vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0 && interleavedFloatBufferImpl != null){
if(interleavedFloatBufferImpl.limit() < stride * (initialVertexIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
}
}
//use java array for interleaved data
else if( interLeavedVertexData != null) {
if(interLeavedVertexData.length < stride * (initialVertexIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
}
}
else {
nullGeo = true;
}
} else if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) {
// Non-interleaved, by-ref
if ((initialCoordIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray104"));
}
if ((initialColorIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray101"));
}
if ((initialNormalIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray102"));
}
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
for (int i = 0; i < texCoordSetCount; i++) {
if ((initialTexCoordIndex[i] + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString(
"GeometryArray103"));
}
}
}
if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
for (int i = 0; i < vertexAttrCount; i++) {
if ((initialVertexAttrIndex[i] + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString(
"GeometryArray130"));
}
}
}
if ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0) {
nullGeo = true;
}
if (( vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
// by reference with nio buffer
switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
case PF:
if(floatBufferRefCoords.limit() < 3 * (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
case PD:
if(doubleBufferRefCoords.limit() < 3 * (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
}
switch ((vertexType & COLOR_DEFINED)) {
case CF:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
if (floatBufferRefColors.limit() < 3 * (initialColorIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
if (floatBufferRefColors.limit() < 4 * (initialColorIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
break;
case CUB:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
if (byteBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
if (byteBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
break;
}
switch ((vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
case TF:
FloatBuffer texBuffer;
for (int i = 0; i < texCoordSetCount; i++) {
texBuffer = (FloatBuffer)refTexCoordsBuffer[i].getROBuffer();
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
if (texBuffer.limit() < 2 * (initialTexCoordIndex[i] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
if (texBuffer.limit() < 3 * (initialTexCoordIndex[i] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
if (texBuffer.limit() < 4 * (initialTexCoordIndex[i] + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
}
}
break;
}
switch ((vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
case NF:
if (floatBufferRefNormals.limit() < 3 * (initialNormalIndex + validVertexCount )) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
break;
}
switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) {
case AF:
for (int i = 0; i < vertexAttrCount; i++) {
int sz = vertexAttrSizes[i];
if (floatBufferRefVertexAttrs[i].limit() <
(sz * (initialVertexAttrIndex[i] + validVertexCount)) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray129"));
}
}
break;
}
}
// By reference with java array
else {
switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
case PF:
if (floatRefCoords.length < 3 * (initialCoordIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
case PD:
if (doubleRefCoords.length < 3 * (initialCoordIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
case P3F:
if (p3fRefCoords.length < (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
case P3D:
if (p3dRefCoords.length < (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
}
switch ((vertexType & COLOR_DEFINED)) {
case CF:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
if (floatRefColors.length < 3 * (initialColorIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
if (floatRefColors.length < 4 * (initialColorIndex+ validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
break;
case CUB:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
if (byteRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
if (byteRefColors.length < 4 * (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
break;
case C3F:
if (c3fRefColors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
break;
case C4F:
if (c4fRefColors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
break;
case C3UB:
if (c3bRefColors.length < (initialColorIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
break;
case C4UB:
if (c4bRefColors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
break;
}
switch ((vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
case TF:
for (int i = 0; i < texCoordSetCount; i++) {
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
if (((float[])refTexCoords[i]).length < 2 * (initialTexCoordIndex[i] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
if (((float[])refTexCoords[i]).length < 3 * (initialTexCoordIndex[i] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
if (((float[])refTexCoords[i]).length < 4 * (initialTexCoordIndex[i] + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
}
}
}
break;
case T2F:
for (int i = 0; i < texCoordSetCount; i++) {
if (((TexCoord2f[])refTexCoords[i]).length < (initialTexCoordIndex[i] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
}
break;
case T3F:
for (int i = 0; i < texCoordSetCount; i++) {
if (((TexCoord3f[])refTexCoords[i]).length < (initialTexCoordIndex[i] + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
}
break;
}
switch ((vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
case NF:
if (floatRefNormals.length < 3 * (initialNormalIndex + validVertexCount )) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
break;
case N3F:
if (v3fRefNormals.length < (initialNormalIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
}
switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) {
case AF:
for (int i = 0; i < vertexAttrCount; i++) {
int sz = vertexAttrSizes[i];
if (floatRefVertexAttrs[i].length <
(sz * (initialVertexAttrIndex[i] + validVertexCount)) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray129"));
}
}
break;
}
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VERTEX_CHANGED;
this.validVertexCount = validVertexCount;
if(isLive){
geomLock.unLock();
}
if (!inUpdater && isLive) {
processCoordsChanged(nullGeo);
sendDataChangedMessage(true);
}
}
int getValidVertexCount() {
return validVertexCount;
}
//Used for interleaved data (array or nio buffer)
void setInitialVertexIndex(int initialVertexIndex) {
boolean nullGeo = false;
if ((initialVertexIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray100"));
}
if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0 && interleavedFloatBufferImpl != null) {
if(interleavedFloatBufferImpl.limit() < stride * (initialVertexIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
}
}
// interleaved data using java array
else if(interLeavedVertexData != null) {
if (interLeavedVertexData.length < stride * (initialVertexIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
}
}
else {
nullGeo = (vertexFormat & GeometryArray.INTERLEAVED) != 0; // Only for byRef
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VERTEX_CHANGED;
this.initialVertexIndex = initialVertexIndex;
if(isLive) {
geomLock.unLock();
}
if (!inUpdater && isLive) {
processCoordsChanged(nullGeo);
sendDataChangedMessage(true);
}
}
int getInitialVertexIndex() {
return initialVertexIndex;
}
void setInitialCoordIndex(int initialCoordIndex) {
if ((initialCoordIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray104"));
}
// use NIO buffer
if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0){
switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
case PF:
if(floatBufferRefCoords.limit() < (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
case PD:
if(doubleBufferRefCoords.limit() < (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
}
} else {
switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
case PF:
if (floatRefCoords.length < 3 * (initialCoordIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
case PD:
if (doubleRefCoords.length < 3 * (initialCoordIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
case P3F:
if (p3fRefCoords.length < (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
case P3D:
if (p3dRefCoords.length < (initialCoordIndex+validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
}
break;
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COORDINATE_CHANGED;
this.initialCoordIndex = initialCoordIndex;
dirtyFlag |= COORDINATE_CHANGED;
if(isLive) {
geomLock.unLock();
}
// Send a message, since bounds changed
if (!inUpdater && isLive) {
processCoordsChanged((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
sendDataChangedMessage(true);
}
}
int getInitialCoordIndex() {
return initialCoordIndex;
}
void setInitialColorIndex(int initialColorIndex) {
if ((initialColorIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray101"));
}
// NIO BUFFER CASE
if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0){
switch ((vertexType & COLOR_DEFINED)) {
case CF:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
if (floatBufferRefColors.limit() < 3 * (initialColorIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
if (floatBufferRefColors.limit() < 4 * (initialColorIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
break;
case CUB:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
if (byteBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
if (byteBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
break;
}
}
// Java ARRAY CASE
else {
switch ((vertexType & COLOR_DEFINED)) {
case CF:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
if (floatRefColors.length < 3 * (initialColorIndex+validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
if (floatRefColors.length < 4 * (initialColorIndex+ validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
break;
case CUB:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
if (byteRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
if (byteRefColors.length < 4 * (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
}
break;
case C3F:
if (c3fRefColors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
break;
case C4F:
if (c4fRefColors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
break;
case C3UB:
if (c3bRefColors.length < (initialColorIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
break;
case C4UB:
if (c4bRefColors.length < (initialColorIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
}
break;
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= COLOR_CHANGED;
colorChanged = 0xffff;
this.initialColorIndex = initialColorIndex;
if(isLive) {
geomLock.unLock();
}
// There is no need to send message for by reference, since we
// use VA
}
int getInitialColorIndex() {
return initialColorIndex;
}
void setInitialNormalIndex(int initialNormalIndex) {
if ((initialNormalIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray102"));
}
if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0){
if((vertexType & NORMAL_DEFINED) == NF){
if (floatBufferRefNormals.limit() < 3 * (initialNormalIndex + validVertexCount )) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
}
} else {
switch((vertexType & NORMAL_DEFINED)){
case NF:
if (floatRefNormals.length < 3 * (initialNormalIndex + validVertexCount )) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
break;
case N3F:
if (v3fRefNormals.length < (initialNormalIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
}
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= NORMAL_CHANGED;
this.initialNormalIndex = initialNormalIndex;
if(isLive) {
geomLock.unLock();
}
// There is no need to send message for by reference, since we
// use VA
}
int getInitialNormalIndex() {
return initialNormalIndex;
}
/**
* Sets the initial vertex attribute index for the specified
* vertex attribute number for this GeometryArray object.
*/
void setInitialVertexAttrIndex(int vertexAttrNum,
int initialVertexAttrIndex) {
if ((initialVertexAttrIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray130"));
}
int sz = vertexAttrSizes[vertexAttrNum];
int minLength = sz * (initialVertexAttrIndex + validVertexCount);
if ((vertexType & VATTR_DEFINED) == AF) {
if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
if (floatBufferRefVertexAttrs[vertexAttrNum].limit() < minLength) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray129"));
}
} else {
if (floatRefVertexAttrs[vertexAttrNum].length < minLength ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray129"));
}
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= VATTR_CHANGED;
this.initialVertexAttrIndex[vertexAttrNum] = initialVertexAttrIndex;
if(isLive) {
geomLock.unLock();
}
// There is no need to send message for by reference, since we
// use VA
}
/**
* Gets the initial vertex attribute index for the specified
* vertex attribute number for this GeometryArray object.
*/
int getInitialVertexAttrIndex(int vertexAttrNum) {
return initialVertexAttrIndex[vertexAttrNum];
}
void setInitialTexCoordIndex(int texCoordSet, int initialTexCoordIndex) {
if ((initialTexCoordIndex + validVertexCount) > vertexCount) {
throw new IllegalArgumentException(J3dI18N.getString("GeometryArray103"));
}
if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0){
if((vertexType & TEXCOORD_DEFINED) == TF) {
FloatBuffer texBuffer = (FloatBuffer)refTexCoordsBuffer[texCoordSet].getROBuffer();
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
if (texBuffer.limit() < 2 * (initialTexCoordIndex+ validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
if (texBuffer.limit() < 3 * (initialTexCoordIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
if (texBuffer.limit() < 4 * (initialTexCoordIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
}
}
} else {
switch ((vertexType & TEXCOORD_DEFINED)) {
case TF:
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
if (((float[])refTexCoords[texCoordSet]).length < 2 * (initialTexCoordIndex+ validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
if (((float[])refTexCoords[texCoordSet]).length < 3 * (initialTexCoordIndex + validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
if (((float[])refTexCoords[texCoordSet]).length < 4 * (initialTexCoordIndex + validVertexCount)) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
}
break;
case T2F:
if (((TexCoord2f[])refTexCoords[texCoordSet]).length < (initialTexCoordIndex+ validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
break;
case T3F:
if (((TexCoord3f[])refTexCoords[texCoordSet]).length < (initialTexCoordIndex+ validVertexCount) ) {
throw new ArrayIndexOutOfBoundsException(
J3dI18N.getString("GeometryArray113"));
}
break;
}
}
boolean isLive = source!=null && source.isLive();
if(isLive){
geomLock.getLock();
}
dirtyFlag |= TEXTURE_CHANGED;
this.initialTexCoordIndex[texCoordSet] = initialTexCoordIndex;
if(isLive) {
geomLock.unLock();
}
// There is no need to send message for by reference, since we
// use VA
}
int getInitialTexCoordIndex(int texCoordSet) {
return initialTexCoordIndex[texCoordSet];
}
int getTexCoordSetCount() {
return this.texCoordSetCount;
}
int getTexCoordSetMapLength() {
if (this.texCoordSetMap != null)
return this.texCoordSetMap.length;
else
return 0;
}
void getTexCoordSetMap(int [] texCoordSetMap) {
if (this.texCoordSetMap!=null) {
for (int i = 0; i < this.texCoordSetMap.length; i++) {
texCoordSetMap[i] = this.texCoordSetMap[i];
}
}
}
void freeDlistId() {
if (dlistId != -1) {
VirtualUniverse.mc.freeDisplayListId(dlistObj);
dlistId = -1;
}
}
void assignDlistId() {
if (dlistId == -1) {
dlistObj = VirtualUniverse.mc.getDisplayListId();
dlistId = dlistObj.intValue();
}
}
// Add the specified render atom as a user of this geometry array
// (for the specified render bin)
void addDlistUser(RenderBin renderBin, RenderAtomListInfo ra) {
if (dlistUsers == null)
dlistUsers = new HashMap>(2, 1.0f);
HashSet raSet = dlistUsers.get(renderBin);
if (raSet == null) {
raSet = new HashSet();
dlistUsers.put(renderBin, raSet);
}
raSet.add(ra);
}
// Remove the specified render atom from the set of users of this
// geometry array (for the specified render bin)
void removeDlistUser(RenderBin renderBin, RenderAtomListInfo ra) {
if (dlistUsers == null)
return;
HashSet raSet = dlistUsers.get(renderBin);
if (raSet == null)
return;
raSet.remove(ra);
}
// Returns true if the set of render atoms using this geometry
// array in the specified render bin is empty.
boolean isDlistUserSetEmpty(RenderBin renderBin) {
if (dlistUsers == null)
return true;
HashSet raSet = dlistUsers.get(renderBin);
if (raSet == null) {
return true;
}
return raSet.isEmpty();
}
// This method is used for debugging only
int numDlistUsers(RenderBin renderBin) {
if (isDlistUserSetEmpty(renderBin))
return 0;
HashSet raSet = dlistUsers.get(renderBin);
return raSet.size();
}
void setDlistTimeStamp(int rdrBit, long timeStamp) {
int index = getIndex(rdrBit);
if (index >= timeStampPerDlist.length) {
long[] newList = new long[index * 2];
for (int i = 0; i < timeStampPerDlist.length; i++) {
newList[i] = timeStampPerDlist[i];
}
timeStampPerDlist = newList;
}
timeStampPerDlist[index] = timeStamp;
}
long getDlistTimeStamp(int rdrBit) {
int index = getIndex(rdrBit);
// If index is greater than what currently exists, increase
// the array and return zero
if (index >= timeStampPerDlist.length) {
setDlistTimeStamp(rdrBit, 0);
}
return timeStampPerDlist[index];
}
int getIndex(int bit) {
int num = 0;
while (bit > 0) {
num++;
bit >>= 1;
}
return num;
}
boolean isWriteStatic() {
if (source.getCapability(GeometryArray.ALLOW_COORDINATE_WRITE ) ||
source.getCapability(GeometryArray.ALLOW_COLOR_WRITE) ||
source.getCapability(GeometryArray.ALLOW_NORMAL_WRITE) ||
source.getCapability(GeometryArray.ALLOW_TEXCOORD_WRITE) ||
source.getCapability(GeometryArray.ALLOW_VERTEX_ATTR_WRITE) ||
source.getCapability(GeometryArray.ALLOW_COUNT_WRITE) ||
source.getCapability(GeometryArray.ALLOW_REF_DATA_WRITE))
return false;
return true;
}
/**
* The functions below are only used in compile mode
*/
void setCompiled(ArrayList curList) {
int i;
int num = curList.size();
int offset = 0;
geoOffset = new int[num];
compileVcount = new int[num];
int vcount = 0, vformat = 0;
vcount = 0;
isCompiled = true;
if (num > 0)
source = ((SceneGraphObjectRetained)curList.get(0)).source;
for (i = 0; i < num; i++) {
// Build the back mapping
GeometryArrayRetained geo = (GeometryArrayRetained)curList.get(i);
((GeometryArray)geo.source).retained = this;
compileVcount[i] = geo.getValidVertexCount();
vcount += geo.getValidVertexCount();
geoOffset[i] = offset;
offset += geo.stride() * compileVcount[i];
vformat = geo.getVertexFormat();
}
createGeometryArrayData(vcount, vformat);
// Assign the initial and valid fields
validVertexCount = vcount;
initialVertexIndex = 0;
mergeGeometryArrays(curList);
}
/*
// Ununsed
int getVertexCount(int index) {
return compileVcount[index];
}
int getValidVertexCount(int index) {
return compileVcount[index];
}
int getInitialVertexIndex(int index) {
return 0;
}
*/
void mergeGeometryArrays(ArrayList list) {
float[] curVertexData;
int length, srcOffset;
int curOffset = 0;
// We only merge if the texCoordSetCount is 1 and there are no
// vertex attrs
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
texCoordSetCount = 1;
texCoordSetMap = new int[1];
texCoordSetMap[0] = 1;
}
for (int i = 0; i < list.size(); i++) {
GeometryArrayRetained geo = (GeometryArrayRetained)list.get(i);
// Take into account the validVertexCount and initialVertexIndex
curVertexData = geo.vertexData;
length = geo.validVertexCount * stride;
srcOffset = geo.initialVertexIndex * stride;
System.arraycopy(curVertexData, srcOffset, this.vertexData, curOffset,
length);
curOffset += length;
// assign geoBounds
geoBounds.combine(geo.geoBounds);
}
geoBounds.getCenter(this.centroid);
}
boolean isMergeable() {
// For now, turn off by ref geometry
if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0)
return false;
if (!isStatic())
return false;
// If there is more than one set of texture coordinate set defined
// then don't merge geometry (we avoid dealing with texCoordSetMap
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0 &&
(texCoordSetCount > 1 ||
texCoordSetMap != null && texCoordSetMap.length > 1)) {
return false;
}
// We will avoid merging geometry if there are any vertex attributes.
if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
return false;
}
// If intersect is allowed turn off merging
if (source.getCapability(Geometry.ALLOW_INTERSECT))
return false;
return true;
}
@Override
void compile(CompileState compState) {
super.compile(compState);
if ((vertexFormat & GeometryArray.NORMALS) != 0) {
compState.needNormalsTransform = true;
}
}
@Override
void mergeTransform(TransformGroupRetained xform) {
if (geoBounds != null) {
geoBounds.transform(xform.transform);
}
}
// This adds a MorphRetained to the list of users of this geometry
void addMorphUser(MorphRetained m) {
int index;
if(morphUniverseList == null) {
morphUniverseList = new ArrayList(1);
morphUserLists = new ArrayList>(1);
}
synchronized (morphUniverseList) {
if (morphUniverseList.contains(m.universe)) {
index = morphUniverseList.indexOf(m.universe);
morphUserLists.get(index).add(m);
} else {
morphUniverseList.add(m.universe);
ArrayList morphList = new ArrayList(5);
morphList.add(m);
morphUserLists.add(morphList);
}
}
}
// This adds a MorphRetained to the list of users of this geometry
void removeMorphUser(MorphRetained m) {
int index;
if(morphUniverseList == null)
return;
synchronized (morphUniverseList) {
index = morphUniverseList.indexOf(m.universe);
ArrayList morphList = morphUserLists.get(index);
morphList.remove(morphList.indexOf(m));
if (morphList.size() == 0) {
morphUserLists.remove(index);
morphUniverseList.remove(index);
}
}
}
// Initialize mirror object when geometry is first setLived
void initMirrorGeometry() {
geomLock.getLock();
if (this instanceof IndexedGeometryArrayRetained) {
if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) {
mirrorGeometry =
((IndexedGeometryArrayRetained)this).cloneNonIndexedGeometry();
}
else {
mirrorGeometry = null;
}
}
geomLock.unLock();
}
// Update Mirror Object in response to change in geometry
void updateMirrorGeometry() {
geomLock.getLock();
if (this instanceof IndexedGeometryArrayRetained) {
if (mirrorGeometry != null) {
mirrorGeometry =
((IndexedGeometryArrayRetained)this).cloneNonIndexedGeometry();
}
}
geomLock.unLock();
}
// Used by the picking intersect routines
void getVertexData(int i, Point3d pnts) {
int offset;
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
offset = stride * i + coordinateOffset;
pnts.x = this.vertexData[offset];
pnts.y = this.vertexData[offset+1];
pnts.z = this.vertexData[offset+2];
return;
}
if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0 ) {
if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
offset = stride * i + coordinateOffset;
pnts.x = this.interLeavedVertexData[offset];
pnts.y = this.interLeavedVertexData[offset+1];
pnts.z = this.interLeavedVertexData[offset+2];
}
else {
switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
case GeometryArrayRetained.PF:
offset = i*3;
pnts.x = this.floatRefCoords[offset];
pnts.y = this.floatRefCoords[offset+1];
pnts.z = this.floatRefCoords[offset+2];
break;
case GeometryArrayRetained.PD:
offset = i*3;
pnts.x = this.doubleRefCoords[offset];
pnts.y = this.doubleRefCoords[offset+1];
pnts.z = this.doubleRefCoords[offset+2];
break;
case GeometryArrayRetained.P3F:
pnts.x = this.p3fRefCoords[i].x;
pnts.y = this.p3fRefCoords[i].y;
pnts.z = this.p3fRefCoords[i].z;
break;
case GeometryArrayRetained.P3D:
pnts.x = this.p3dRefCoords[i].x;
pnts.y = this.p3dRefCoords[i].y;
pnts.z = this.p3dRefCoords[i].z;
break;
}
}
}// end of non nio buffer
else { // NIO BUFFER
if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
offset = stride * i + coordinateOffset;
pnts.x = this.interleavedFloatBufferImpl.get(offset);
pnts.y = this.interleavedFloatBufferImpl.get(offset+1);
pnts.z = this.interleavedFloatBufferImpl.get(offset+2);
}
else {
switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
case GeometryArrayRetained.PF:
offset = i*3;
pnts.x = this.floatBufferRefCoords.get(offset);
pnts.y = this.floatBufferRefCoords.get(offset+1);
pnts.z = this.floatBufferRefCoords.get(offset+2);
break;
case GeometryArrayRetained.PD:
offset = i*3;
pnts.x = this.doubleBufferRefCoords.get(offset);
pnts.y = this.doubleBufferRefCoords.get(offset+1);
pnts.z = this.doubleBufferRefCoords.get(offset+2);
break;
}
}
} // end of nio buffer
}
void getCrossValue(Point3d p1, Point3d p2, Vector3d value) {
value.x += p1.y*p2.z - p1.z*p2.y;
value.y += p2.x*p1.z - p2.z*p1.x;
value.z += p1.x*p2.y - p1.y*p2.x;
}
@Override
boolean intersect(Transform3D thisLocalToVworld,
Transform3D otherLocalToVworld, GeometryRetained geom) {
Transform3D t3d = new Transform3D();
boolean isIntersect = false;
if (geom instanceof GeometryArrayRetained ) {
GeometryArrayRetained geomArray = (GeometryArrayRetained) geom;
if (geomArray.validVertexCount >= validVertexCount) {
t3d.invert(otherLocalToVworld);
t3d.mul(thisLocalToVworld);
isIntersect = intersect(t3d, geom);
} else {
t3d.invert(thisLocalToVworld);
t3d.mul(otherLocalToVworld);
isIntersect = geomArray.intersect(t3d, this);
}
} else {
t3d.invert(thisLocalToVworld);
t3d.mul(otherLocalToVworld);
isIntersect = geom.intersect(t3d, this);
}
return isIntersect;
}
int getNumCoordCount() {
int count = 0;
if ((vertexFormat & GeometryArray.COORDINATES) != 0){
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0){
count = vertexCount;
return count;
}
if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
case PF:
count = floatRefCoords.length/3;
break;
case PD:
count = doubleRefCoords.length/3;
break;
case P3F:
count = p3fRefCoords.length;
break;
case P3D:
count = p3dRefCoords.length;
break;
}
}
else {
count = interLeavedVertexData.length/stride;
}
}
else { // nio buffer
if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
case PF:
count = floatBufferRefCoords.limit()/3; // XXXX: limit or capacity?
break;
case PD:
count = doubleBufferRefCoords.limit()/3;
break;
}
}
else {
count = interleavedFloatBufferImpl.limit()/stride;
}
}
}
return count;
}
int getNumColorCount() {
int count = 0;
if ((vertexFormat & GeometryArray.COLOR) != 0){
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0){
count = vertexCount;
return count;
}
if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
switch ((vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
case CF:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
count = floatRefColors.length/3;
}
else if ((vertexFormat & GeometryArray.COLOR_4)== GeometryArray.COLOR_4){
count = floatRefColors.length/4;
}
break;
case CUB:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
count = byteRefColors.length/3;
}
else if ((vertexFormat & GeometryArray.COLOR_4)== GeometryArray.COLOR_4){
count = byteRefColors.length/4;
}
break;
case C3F:
count = c3fRefColors.length;
break;
case C4F:
count = c4fRefColors.length;
break;
case C3UB:
count = c3bRefColors.length;
break;
case C4UB:
count = c4bRefColors.length;
break;
}
}
else {
count = interLeavedVertexData.length/stride;
}
} // end of non nio buffer
else {
if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
switch ((vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
case CF:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
count = floatBufferRefColors.limit()/3;
}
else if ((vertexFormat & GeometryArray.COLOR_4)== GeometryArray.COLOR_4){
count = floatBufferRefColors.limit()/4;
}
break;
case CUB:
if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
count = byteBufferRefColors.limit()/3;
}
else if ((vertexFormat & GeometryArray.COLOR_4)== GeometryArray.COLOR_4){
count = byteBufferRefColors.limit()/4;
}
break;
}
}
else {
count = interleavedFloatBufferImpl.limit()/stride;
}
} // end of nio buffer
}
return count;
}
int getNumNormalCount() {
int count = 0;
if ((vertexFormat & GeometryArray.NORMALS) != 0){
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0){
count = vertexCount;
return count;
}
if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
switch ((vertexType & NORMAL_DEFINED)) {
case NF:
count = floatRefNormals.length/3;
break;
case N3F:
count = v3fRefNormals.length;
break;
}
}
else {
count = interLeavedVertexData.length/stride;
}
} // end of non nio buffer
else {
if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
if ((vertexType & NORMAL_DEFINED) == NF ) {
count = floatBufferRefNormals.limit()/3;
}
}
else {
count = interleavedFloatBufferImpl.limit()/stride;
}
}
}
return count;
}
int getNumTexCoordCount(int i) {
int count = 0;
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0){
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0){
count = vertexCount;
return count;
}
if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
switch ((vertexType & TEXCOORD_DEFINED)) {
case TF:
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
count = ((float[])refTexCoords[i]).length/2;
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
count = ((float[])refTexCoords[i]).length/3;
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
count = ((float[])refTexCoords[i]).length/4;
}
break;
case T2F:
count = ((TexCoord2f[])refTexCoords[i]).length;
break;
case T3F:
count = ((TexCoord3f[])refTexCoords[i]).length;
}
}
else {
count = interLeavedVertexData.length/stride;
}
}
else { // nio buffer
if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
if ((vertexType & TEXCOORD_DEFINED) == TF) {
FloatBuffer texBuffer = (FloatBuffer)refTexCoordsBuffer[i].getROBuffer();
if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
count = texBuffer.limit()/2;
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
count = texBuffer.limit()/3;
} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
count = texBuffer.limit()/4;
}
}
}
else {
count = interleavedFloatBufferImpl.limit()/stride;
}
}
}
return count;
}
// NOTE: we don't need a getNumVertexAttrCount method, since getNum*Count
// is only called by Morph, which doesn't support vertex attrs
// Found the min distance from center to the point/line/tri/quad
// form by dist[]
void computeMinDistance(Point3d coordinates[], Point3d center,
Vector3d normal,
double dist[], Point3d iPnt) {
double x, y, z;
int i, j;
if (coordinates.length == 1) {
// a point
iPnt.x = coordinates[0].x;
iPnt.y = coordinates[0].y;
iPnt.z = coordinates[0].z;
x = iPnt.x - center.x;
y = iPnt.y - center.y;
z = iPnt.z - center.z;
dist[0] = Math.sqrt(x*x + y*y + z*z);
return;
}
if (coordinates.length == 2) {
// a line
dist[0] = Math.sqrt(Utils.ptToSegSquare(center, coordinates[0], coordinates[1], iPnt));
return;
}
double normalLen = 0;
if (normal == null) {
Vector3d vec0 = new Vector3d();
Vector3d vec1 = new Vector3d();
normal = new Vector3d();
// compute plane normal for coordinates.
for (i=0; i 0.0)
break;
}
for (j=i; j 0.0)
break;
}
if (j == (coordinates.length-1)) {
// Degenerate polygon, check with edge only
normal = null;
} else {
normal.cross(vec0,vec1);
}
}
if (normal != null) {
normalLen = normal.length();
if ( normalLen == 0.0) {
// Degenerate polygon, check with edge only
normal = null;
}
}
if (coordinates.length == 3) {
// a triangle
if (normal != null) {
double d = -(normal.x*coordinates[0].x +
normal.y*coordinates[0].y +
normal.z*coordinates[0].z);
dist[0] = (normal.x*center.x + normal.y*center.y +
normal.z*center.z +
d)/normalLen;
iPnt.x = center.x - dist[0]*normal.x/normalLen;
iPnt.y = center.y - dist[0]*normal.y/normalLen;
iPnt.z = center.z - dist[0]*normal.z/normalLen;
if (pointInTri(iPnt, coordinates[0], coordinates[1],
coordinates[2], normal)) {
return;
}
}
// checking point to line distance
double minDist;
Point3d minPnt = new Point3d();
dist[0] = Utils.ptToSegSquare(center, coordinates[0], coordinates[1], iPnt);
minDist = Utils.ptToSegSquare(center, coordinates[1], coordinates[2], minPnt);
if (minDist < dist[0]) {
dist[0] = minDist;
iPnt.x = minPnt.x;
iPnt.y = minPnt.y;
iPnt.z = minPnt.z;
}
minDist = Utils.ptToSegSquare(center, coordinates[2], coordinates[0], minPnt);
if (minDist < dist[0]) {
dist[0] = minDist;
iPnt.x = minPnt.x;
iPnt.y = minPnt.y;
iPnt.z = minPnt.z;
}
dist[0] = Math.sqrt(dist[0]);
return;
}
// a quad
if (normal != null) {
double d = -(normal.x*coordinates[0].x +
normal.y*coordinates[0].y +
normal.z*coordinates[0].z);
dist[0] = (normal.x*center.x + normal.y*center.y +
normal.z*center.z +
d)/normalLen;
iPnt.x = center.x - dist[0]*normal.x/normalLen;
iPnt.y = center.y - dist[0]*normal.y/normalLen;
iPnt.z = center.z - dist[0]*normal.z/normalLen;
if (pointInTri(iPnt, coordinates[0], coordinates[1],
coordinates[2], normal) ||
pointInTri(iPnt, coordinates[1], coordinates[2],
coordinates[3], normal)) {
return;
}
}
// checking point to line distance
double minDist;
Point3d minPnt = new Point3d();
dist[0] = Utils.ptToSegSquare(center, coordinates[0], coordinates[1], iPnt);
minDist = Utils.ptToSegSquare(center, coordinates[1], coordinates[2], minPnt);
if (minDist < dist[0]) {
dist[0] = minDist;
iPnt.x = minPnt.x;
iPnt.y = minPnt.y;
iPnt.z = minPnt.z;
}
minDist = Utils.ptToSegSquare(center, coordinates[2], coordinates[3], minPnt);
if (minDist < dist[0]) {
dist[0] = minDist;
iPnt.x = minPnt.x;
iPnt.y = minPnt.y;
iPnt.z = minPnt.z;
}
minDist = Utils.ptToSegSquare(center, coordinates[3], coordinates[0], minPnt);
if (minDist < dist[0]) {
dist[0] = minDist;
iPnt.x = minPnt.x;
iPnt.y = minPnt.y;
iPnt.z = minPnt.z;
}
dist[0] = Math.sqrt(dist[0]);
}
@Override
void handleFrequencyChange(int bit) {
int mask = 0;
if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
if ((bit == GeometryArray.ALLOW_COORDINATE_WRITE) ||
(((vertexFormat & GeometryArray.COLOR) != 0) &&
bit == GeometryArray.ALLOW_COLOR_WRITE)||
(((vertexFormat & GeometryArray.NORMALS) != 0) &&
bit == GeometryArray.ALLOW_NORMAL_WRITE) ||
(((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) &&
bit == GeometryArray.ALLOW_TEXCOORD_WRITE) ||
(((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) &&
bit == GeometryArray.ALLOW_VERTEX_ATTR_WRITE) ||
(bit == GeometryArray.ALLOW_COUNT_WRITE)) {
mask = 1;
}
}
else {
if (bit == GeometryArray.ALLOW_REF_DATA_WRITE)
mask = 1;
}
if (mask != 0) {
setFrequencyChangeMask(bit, mask);
}
}
int getTexCoordType() {
return texCoordType;
}
int getVertexAttrType() {
return vertexAttrType;
}
}