00001: /*
00002: * $RCSfile: GeometryArrayRetained.java,v $
00003: *
00004: * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
00005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
00006: *
00007: * This code is free software; you can redistribute it and/or modify it
00008: * under the terms of the GNU General Public License version 2 only, as
00009: * published by the Free Software Foundation. Sun designates this
00010: * particular file as subject to the "Classpath" exception as provided
00011: * by Sun in the LICENSE file that accompanied this code.
00012: *
00013: * This code is distributed in the hope that it will be useful, but WITHOUT
00014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00016: * version 2 for more details (a copy is included in the LICENSE file that
00017: * accompanied this code).
00018: *
00019: * You should have received a copy of the GNU General Public License version
00020: * 2 along with this work; if not, write to the Free Software Foundation,
00021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
00022: *
00023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
00024: * CA 95054 USA or visit www.sun.com if you need additional information or
00025: * have any questions.
00026: *
00027: * $Revision: 1.12 $
00028: * $Date: 2008/02/28 20:17:22 $
00029: * $State: Exp $
00030: */
00031:
00032: package javax.media.j3d;
00033:
00034: import com.sun.j3d.internal.Distance;
00035: import javax.vecmath.*;
00036: import java.lang.Math;
00037: import java.util.ArrayList;
00038: import java.util.Set;
00039: import java.util.HashSet;
00040: import java.util.HashMap;
00041: import java.util.Vector;
00042: import java.util.Enumeration;
00043: import com.sun.j3d.internal.ByteBufferWrapper;
00044: import com.sun.j3d.internal.BufferWrapper;
00045: import com.sun.j3d.internal.FloatBufferWrapper;
00046: import com.sun.j3d.internal.DoubleBufferWrapper;
00047:
00048: /**
00049: * The GeometryArray object contains arrays of positional coordinates,
00050: * colors, normals and/or texture coordinates that describe
00051: * point, line, or surface geometry. It is extended to create
00052: * the various primitive types (e.g., lines, triangle_strips, etc.)
00053: */
00054:
00055: abstract class GeometryArrayRetained extends GeometryRetained {
00056:
00057: // XXXX: Memory footprint reduction. Should have separate object to
00058: // to contain specific data such as a ByRef object for
00059: // all ByRef related data. So that incases where no
00060: // ByRef is needed, the ByRef object reference is
00061: // set to null. Hence saving memory!
00062: // Need object such as Texture, D3d and ByRef ...
00063: //
00064:
00065: // Contains a bitset indicating which components are present
00066: int vertexFormat;
00067:
00068: // Whether this geometry was ever rendered as transparent
00069: int c4fAllocated = 0;
00070:
00071: // Total Number of vertices
00072: int vertexCount;
00073:
00074: // number of vertices used in rendering
00075: int validVertexCount;
00076:
00077: // The vertex data in packed format
00078: float vertexData[];
00079:
00080: // vertex data in packed format for each screen in multi-screen situation
00081: // if alpha values of each vertex are to be updated
00082: private float mvertexData[][];
00083:
00084: //
00085: // The following offset/stride values are internally computed
00086: // from the format
00087: //
00088:
00089: // Stride (in words) from one vertex to the next
00090: int stride;
00091:
00092: // Stride (in words) from one texture coordinate to the next
00093: int texCoordStride;
00094:
00095: // Offset (in words) within each vertex of the coordinate position
00096: int coordinateOffset;
00097:
00098: // Offset (in words) within each vertex of the normal
00099: int normalOffset;
00100:
00101: // Offset (in words) within each vertex of the color
00102: int colorOffset;
00103:
00104: // Offset (in words) within each vertex of the texture coordinate
00105: int textureOffset;
00106:
00107: // Offset (in words) within each vertex of each vertex attribute
00108: int[] vertexAttrOffsets;
00109:
00110: // Stride (size) of all vertex attributes
00111: int vertexAttrStride;
00112:
00113: // alpha value for transparency and texture blending
00114: private float[] lastAlpha = new float[1];
00115: float lastScreenAlpha = -1;
00116:
00117: int colorChanged = 0;
00118:
00119: // byte to float scale factor
00120: static final float ByteToFloatScale = 1.0f / 255.0f;
00121:
00122: // float to byte scale factor
00123: static final float FloatToByteScale = 255.0f;
00124:
00125: // Set flag indicating that we are in the updater. This flag
00126: // can be used by the various setRef methods to inhibit any
00127: // update messages
00128: boolean inUpdater = false;
00129:
00130: // Array List used for messages
00131: ArrayList gaList = new ArrayList(1);
00132:
00133: // Target threads to be notified when morph changes
00134: static final int targetThreads = (J3dThread.UPDATE_RENDER | J3dThread.UPDATE_GEOMETRY);
00135:
00136: // used for byReference geometry
00137: float[] floatRefCoords = null;
00138: double[] doubleRefCoords = null;
00139: Point3d[] p3dRefCoords = null;
00140: Point3f[] p3fRefCoords = null;
00141:
00142: // Used for NIO buffer geometry
00143: J3DBuffer coordRefBuffer = null;
00144: FloatBufferWrapper floatBufferRefCoords = null;
00145: DoubleBufferWrapper doubleBufferRefCoords = null;
00146:
00147: // Initial index to use for rendering
00148: int initialCoordIndex = 0;
00149: int initialColorIndex = 0;
00150: int initialNormalIndex = 0;
00151: int[] initialTexCoordIndex = null;
00152: int[] initialVertexAttrIndex = null;
00153: int initialVertexIndex = 0;
00154:
00155: // used for byReference colors
00156: float[] floatRefColors = null;
00157: byte[] byteRefColors = null;
00158: Color3f[] c3fRefColors = null;
00159: Color4f[] c4fRefColors = null;
00160: Color3b[] c3bRefColors = null;
00161: Color4b[] c4bRefColors = null;
00162:
00163: // Used for NIO buffer colors
00164: J3DBuffer colorRefBuffer = null;
00165: FloatBufferWrapper floatBufferRefColors = null;
00166: ByteBufferWrapper byteBufferRefColors = null;
00167:
00168: // flag to indicate if the "by reference" component is already set
00169: int vertexType = 0;
00170: static final int PF = 0x1;
00171: static final int PD = 0x2;
00172: static final int P3F = 0x4;
00173: static final int P3D = 0x8;
00174: static final int VERTEX_DEFINED = PF | PD | P3F | P3D;
00175:
00176: static final int CF = 0x10;
00177: static final int CUB = 0x20;
00178: static final int C3F = 0x40;
00179: static final int C4F = 0x80;
00180: static final int C3UB = 0x100;
00181: static final int C4UB = 0x200;
00182: static final int COLOR_DEFINED = CF | CUB | C3F | C4F | C3UB | C4UB;
00183:
00184: static final int NF = 0x400;
00185: static final int N3F = 0x800;
00186: static final int NORMAL_DEFINED = NF | N3F;
00187:
00188: static final int TF = 0x1000;
00189: static final int T2F = 0x2000;
00190: static final int T3F = 0x4000;
00191: static final int TEXCOORD_DEFINED = TF | T2F | T3F;
00192:
00193: static final int AF = 0x8000;
00194: static final int VATTR_DEFINED = AF;
00195:
00196: // Flag word indicating the type of by-ref texCoord. We will copy this to
00197: // the vertexType field only when the references for all texture coordinate
00198: // sets are set to non-null values.
00199: private int texCoordType = 0;
00200:
00201: // Flag word indicating the type of by-ref vertex attr. We will copy this to
00202: // the vertexType field only when the references for all vertex attrs
00203: // are set to non-null values.
00204: private int vertexAttrType = 0;
00205:
00206: // flag for execute geometry array when by reference
00207: static final int COORD_FLOAT = 0x01;
00208: static final int COORD_DOUBLE = 0x02;
00209: static final int COLOR_FLOAT = 0x04;
00210: static final int COLOR_BYTE = 0x08;
00211: static final int NORMAL_FLOAT = 0x10;
00212: static final int TEXCOORD_FLOAT = 0x20;
00213: static final int VATTR_FLOAT = 0x40;
00214:
00215: // used by "by reference" normals
00216: float[] floatRefNormals = null;
00217: Vector3f[] v3fRefNormals = null;
00218:
00219: // Used for NIO buffer normals
00220: J3DBuffer normalRefBuffer = null;
00221: FloatBufferWrapper floatBufferRefNormals = null;
00222:
00223: // used for "by reference" vertex attrs
00224: float[][] floatRefVertexAttrs = null;
00225:
00226: // Used for NIO buffer vertex attrs
00227: J3DBuffer[] vertexAttrsRefBuffer = null;
00228: FloatBufferWrapper[] floatBufferRefVertexAttrs = null;
00229: Object[] nioFloatBufferRefVertexAttrs = null;
00230:
00231: // used by "by reference" tex coords
00232: Object[] refTexCoords = null;
00233: TexCoord2f[] t2fRefTexCoords = null;
00234: TexCoord3f[] t3fRefTexCoords = null;
00235:
00236: // Used for NIO buffer tex coords
00237: Object[] refTexCoordsBuffer = null;
00238: //FloatBufferWrapper[] floatBufferRefTexCoords = null;
00239:
00240: // used by interleaved array
00241: float[] interLeavedVertexData = null;
00242:
00243: // used by interleaved NIO buffer
00244: J3DBuffer interleavedVertexBuffer = null;
00245: FloatBufferWrapper interleavedFloatBufferImpl = null;
00246:
00247: // pointers used, when transparency is turned on
00248: // or when its an object such as C3F, P3F etc ..
00249: float[] mirrorFloatRefCoords = null;
00250: double[] mirrorDoubleRefCoords = null;
00251: float[] mirrorFloatRefNormals = null;
00252: float[][] mirrorFloatRefVertexAttrs = null;
00253: float[] mirrorFloatRefTexCoords = null;
00254: Object[] mirrorRefTexCoords = null;
00255:
00256: float[][] mirrorFloatRefColors = new float[1][];
00257: byte[][] mirrorUnsignedByteRefColors = new byte[1][];
00258: float[][] mirrorInterleavedColorPointer = null;
00259:
00260: // boolean to determine if a mirror was allocated
00261: int mirrorVertexAllocated = 0;
00262: int mirrorColorAllocated = 0;
00263: boolean mirrorNormalAllocated = false;
00264:
00265: // Some dirty bits for GeometryArrays
00266: static final int COORDINATE_CHANGED = 0x01;
00267: static final int NORMAL_CHANGED = 0x02;
00268: static final int COLOR_CHANGED = 0x04;
00269: static final int TEXTURE_CHANGED = 0x08;
00270: static final int BOUNDS_CHANGED = 0x10;
00271: static final int INDEX_CHANGED = 0x20;
00272: static final int STRIPCOUNT_CHANGED = 0x40;
00273: static final int VATTR_CHANGED = 0x80;
00274: static final int VERTEX_CHANGED = COORDINATE_CHANGED
00275: | NORMAL_CHANGED | COLOR_CHANGED | TEXTURE_CHANGED
00276: | VATTR_CHANGED;
00277:
00278: static final int defaultTexCoordSetMap[] = { 0 };
00279: int texCoordSetCount = 0;
00280: int[] texCoordSetMap = null;
00281:
00282: // this array contains offset to the texCoord data for each
00283: // texture unit. -1 means no corresponding texCoord data offset
00284: int[] texCoordSetMapOffset = null;
00285:
00286: // Vertex attribute information
00287: int vertexAttrCount = 0;
00288: int[] vertexAttrSizes = null;
00289:
00290: // This point to a list of VertexBuffers in a Vector structure
00291: // Each element correspond to a D3D context that create this VB.
00292: // Note that this GeometryArray can be used by multiple ctx.
00293: long pVertexBuffers = 0;
00294: int dirtyFlag;
00295:
00296: // each bit corresponds to a unique renderer if shared context
00297: // or a unique canvas otherwise
00298: int resourceCreationMask = 0x0;
00299:
00300: // Fix for Issue 5
00301: //
00302: // Replace the per-canvas reference count with a per-RenderBin set
00303: // of users. The per-RenderBin set of users of this display list
00304: // is defined as a HashMap where:
00305: //
00306: // key = the RenderBin
00307: // value = a set of RenderAtomListInfo objects using this
00308: // geometry array for display list purposes
00309: private HashMap dlistUsers = null;
00310:
00311: // timestamp used to create display list. This is either
00312: // one per renderer for useSharedCtx, or one per Canvas for non-shared
00313: // ctx
00314: private long[] timeStampPerDlist = new long[2];
00315:
00316: // Unique display list Id, if this geometry is shared
00317: int dlistId = -1;
00318: Integer dlistObj = null;
00319:
00320: // A list of pre-defined bits to indicate which component
00321: // in this Texture object changed.
00322: // static final int DLIST_CREATE_CHANGED = 0x01;
00323: static final int INIT_MIRROR_GEOMETRY = 0x02;
00324:
00325: // A list of Universes that this Geometry is referenced in Morph from
00326: ArrayList morphUniverseList = null;
00327:
00328: // A list of ArrayLists which contain all the MorphRetained objects
00329: // refering to this geometry. Each list corresponds to the universe
00330: // above.
00331: ArrayList morphUserLists = null;
00332:
00333: // The following variables are only used in compile mode
00334:
00335: // Offset of a geometry array into the merged array
00336: int[] geoOffset;
00337:
00338: // vertexcount of a geometry array in a merge array
00339: int[] compileVcount;
00340:
00341: boolean isCompiled = false;
00342:
00343: boolean isShared = false;
00344:
00345: IndexedGeometryArrayRetained cloneSourceArray = null;
00346:
00347: static final double EPS = 1.0e-13;
00348:
00349: void freeD3DArray(boolean deleteVB) {
00350: assert VirtualUniverse.mc.isD3D();
00351: Pipeline.getPipeline().freeD3DArray(this , deleteVB);
00352: }
00353:
00354: GeometryArrayRetained() {
00355: dirtyFlag = INDEX_CHANGED | VERTEX_CHANGED;
00356: lastAlpha[0] = 1.0f;
00357: }
00358:
00359: void setLive(boolean inBackgroundGroup, int refCount) {
00360: dirtyFlag = VERTEX_CHANGED | INDEX_CHANGED;
00361: isEditable = !isWriteStatic();
00362: super .doSetLive(inBackgroundGroup, refCount);
00363: super .markAsLive();
00364: // Send message to RenderingAttribute structure to obtain a dlistId
00365: // System.err.println("Geometry - "+this+"refCount = "+this.refCount);
00366: if (this .refCount > 1) {
00367: // Send to rendering attribute structure,
00368: /*
00369: J3dMessage createMessage = new J3dMessage();
00370: createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
00371: createMessage.type = J3dMessage.GEOMETRYARRAY_CHANGED;
00372: createMessage.universe = null;
00373: createMessage.args[0] = this;
00374: createMessage.args[1]= new Integer(DLIST_CREATE_CHANGED);
00375: VirtualUniverse.mc.processMessage(createMessage);
00376: */
00377: isShared = true;
00378: } // Clone geometry only for the first setLive
00379: else {
00380: // If geometry is indexed and use_index_coord is false, unindexify
00381: // otherwise, set mirrorGeometry to null (from previous clearLive)
00382: if (this instanceof IndexedGeometryArrayRetained) {
00383: // Send to rendering attribute structure,
00384: J3dMessage createMessage = new J3dMessage();
00385: createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
00386: createMessage.type = J3dMessage.GEOMETRY_CHANGED;
00387: createMessage.universe = null;
00388: createMessage.args[0] = null;
00389: createMessage.args[1] = this ;
00390: createMessage.args[2] = new Integer(
00391: INIT_MIRROR_GEOMETRY);
00392: VirtualUniverse.mc.processMessage(createMessage);
00393: }
00394: }
00395:
00396: }
00397:
00398: void clearLive(int refCount) {
00399: super .clearLive(refCount);
00400:
00401: if (this .refCount <= 0) {
00402: if (pVertexBuffers != 0) {
00403: J3dMessage renderMessage = new J3dMessage();
00404: renderMessage.threads = J3dThread.RENDER_THREAD;
00405: renderMessage.type = J3dMessage.RENDER_IMMEDIATE;
00406: renderMessage.universe = null;
00407: renderMessage.view = null;
00408: renderMessage.args[0] = null;
00409: renderMessage.args[1] = this ;
00410: // Any one renderer is fine since VB store the ctx
00411: // where it is created.
00412: Enumeration e = Screen3D.deviceRendererMap.elements();
00413: Renderer rdr = (Renderer) e.nextElement();
00414: rdr.rendererStructure.addMessage(renderMessage);
00415: VirtualUniverse.mc.setWorkForRequestRenderer();
00416: }
00417: isShared = false;
00418: }
00419: }
00420:
00421: void computeBoundingBox() {
00422:
00423: // System.err.println("computeBoundingBox ....");
00424:
00425: if (boundsDirty && VirtualUniverse.mc.cacheAutoComputedBounds) {
00426: for (ArrayList<Shape3DRetained> users : userLists) {
00427: for (Shape3DRetained shape : users)
00428: shape.dirtyBoundsCache();
00429: }
00430: }
00431:
00432: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
00433: // by copy
00434: computeBoundingBox(initialVertexIndex, vertexData);
00435:
00436: } else if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { // USE_NIO_BUFFER
00437: //System.err.println("vertexFormat & GeometryArray.USE_NIO_BUFFER");
00438: if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
00439: computeBoundingBox(initialCoordIndex,
00440: interleavedFloatBufferImpl);
00441: } else if ((vertexType & PF) != 0) {
00442: computeBoundingBox(floatBufferRefCoords);
00443: } else if ((vertexType & PD) != 0) {
00444: computeBoundingBox(doubleBufferRefCoords);
00445: }
00446:
00447: } else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
00448: //System.err.println("vertexFormat & GeometryArray.INTERLEAVED");
00449: computeBoundingBox(initialCoordIndex, interLeavedVertexData);
00450: } else if ((vertexType & PF) != 0) {
00451: //System.err.println("vertexType & PF");
00452: computeBoundingBox(floatRefCoords);
00453: } else if ((vertexType & P3F) != 0) {
00454: //System.err.println("vertexType & P3F");
00455: computeBoundingBox(p3fRefCoords);
00456: } else if ((vertexType & P3D) != 0) {
00457: //System.err.println("vertexType & P3D");
00458: computeBoundingBox(p3dRefCoords);
00459: } else if ((vertexType & PD) != 0) {
00460: //System.err.println("vertexType & PD");
00461: computeBoundingBox(doubleRefCoords);
00462: }
00463:
00464: }
00465:
00466: // NullGeometry is true only for byRef case
00467: void processCoordsChanged(boolean nullGeo) {
00468:
00469: /*
00470: System.err.println("processCoordsChanged : nullGeo " + nullGeo);
00471: System.err.println("Before :processCoordsChanged : geoBounds ");
00472: System.err.println(geoBounds);
00473: */
00474: if (nullGeo) {
00475: synchronized (geoBounds) {
00476: geoBounds.setLower(-1.0, -1.0, -1.0);
00477: geoBounds.setUpper(1.0, 1.0, 1.0);
00478: boundsDirty = false;
00479: }
00480: synchronized (centroid) {
00481: recompCentroid = false;
00482: this .centroid.set(geoBounds.getCenter());
00483: }
00484:
00485: } else {
00486: // re-compute centroid if used
00487: synchronized (centroid) {
00488: recompCentroid = true;
00489: }
00490:
00491: synchronized (geoBounds) {
00492: boundsDirty = true;
00493: computeBoundingBox();
00494: }
00495:
00496: /*
00497: System.err.println("After :processCoordsChanged : geoBounds ");
00498: System.err.println(geoBounds);
00499: */
00500: }
00501: }
00502:
00503: void computeBoundingBox(int vIndex, float[] vdata) {
00504: int i, offset;
00505: double xmin, xmax, ymin, ymax, zmin, zmax;
00506:
00507: //System.err.println("Before : computeBoundingBox : geoBounds ");
00508: // System.err.println(geoBounds);
00509:
00510: synchronized (geoBounds) {
00511:
00512: // If autobounds compute is false then return
00513: // It is possible that user call getBounds() before
00514: // this Geometry add to live scene graph.
00515: if ((computeGeoBounds == 0) && (refCount > 0)) {
00516: return;
00517: }
00518: if (!boundsDirty)
00519: return;
00520:
00521: // Initial offset
00522: offset = vIndex * stride + coordinateOffset;
00523: // Compute the bounding box
00524: xmin = xmax = vdata[offset];
00525: ymin = ymax = vdata[offset + 1];
00526: zmin = zmax = vdata[offset + 2];
00527: offset += stride;
00528: for (i = 1; i < validVertexCount; i++) {
00529: if (vdata[offset] > xmax)
00530: xmax = vdata[offset];
00531: if (vdata[offset] < xmin)
00532: xmin = vdata[offset];
00533:
00534: if (vdata[offset + 1] > ymax)
00535: ymax = vdata[offset + 1];
00536: if (vdata[offset + 1] < ymin)
00537: ymin = vdata[offset + 1];
00538:
00539: if (vdata[offset + 2] > zmax)
00540: zmax = vdata[offset + 2];
00541: if (vdata[offset + 2] < zmin)
00542: zmin = vdata[offset + 2];
00543:
00544: offset += stride;
00545: }
00546:
00547: geoBounds.setUpper(xmax, ymax, zmax);
00548: geoBounds.setLower(xmin, ymin, zmin);
00549: boundsDirty = false;
00550: }
00551: /*
00552: System.err.println("After : computeBoundingBox : geoBounds ");
00553: System.err.println(geoBounds);
00554: */
00555: }
00556:
00557: // Compute boundingbox for interleaved nio buffer
00558: void computeBoundingBox(int vIndex, FloatBufferWrapper vdata) {
00559: int i, offset;
00560: double xmin, xmax, ymin, ymax, zmin, zmax;
00561:
00562: synchronized (geoBounds) {
00563: // If autobounds compute is false then return
00564: if ((computeGeoBounds == 0) && (refCount > 0)) {
00565: return;
00566: }
00567:
00568: if (!boundsDirty)
00569: return;
00570:
00571: // Initial offset
00572: offset = vIndex * stride + coordinateOffset;
00573: // Compute the bounding box
00574: xmin = xmax = vdata.get(offset);
00575: ymin = ymax = vdata.get(offset + 1);
00576: zmin = zmax = vdata.get(offset + 2);
00577: offset += stride;
00578: for (i = 1; i < validVertexCount; i++) {
00579: if (vdata.get(offset) > xmax)
00580: xmax = vdata.get(offset);
00581: if (vdata.get(offset) < xmin)
00582: xmin = vdata.get(offset);
00583:
00584: if (vdata.get(offset + 1) > ymax)
00585: ymax = vdata.get(offset + 1);
00586: if (vdata.get(offset + 1) < ymin)
00587: ymin = vdata.get(offset + 1);
00588:
00589: if (vdata.get(offset + 2) > zmax)
00590: zmax = vdata.get(offset + 2);
00591: if (vdata.get(offset + 2) < zmin)
00592: zmin = vdata.get(offset + 2);
00593:
00594: offset += stride;
00595: }
00596:
00597: geoBounds.setUpper(xmax, ymax, zmax);
00598: geoBounds.setLower(xmin, ymin, zmin);
00599: boundsDirty = false;
00600: }
00601: }
00602:
00603: // compute bounding box for coord with noi buffer
00604: void computeBoundingBox(DoubleBufferWrapper buffer) {
00605: int i, j, k, sIndex;
00606: double xmin, xmax, ymin, ymax, zmin, zmax;
00607:
00608: synchronized (geoBounds) {
00609: // If autobounds compute is false then return
00610: if ((computeGeoBounds == 0) && (refCount > 0)) {
00611: return;
00612: }
00613:
00614: if (!boundsDirty)
00615: return;
00616:
00617: sIndex = initialCoordIndex;
00618: int maxIndex = 3 * validVertexCount;
00619:
00620: // Compute the bounding box
00621: xmin = xmax = buffer.get(sIndex++);
00622: ymin = ymax = buffer.get(sIndex++);
00623: zmin = zmax = buffer.get(sIndex++);
00624:
00625: for (i = sIndex; i < maxIndex; i += 3) {
00626: j = i + 1;
00627: k = i + 2;
00628:
00629: if (buffer.get(i) > xmax)
00630: xmax = buffer.get(i);
00631: if (buffer.get(i) < xmin)
00632: xmin = buffer.get(i);
00633:
00634: if (buffer.get(j) > ymax)
00635: ymax = buffer.get(j);
00636: if (buffer.get(j) < ymin)
00637: ymin = buffer.get(j);
00638:
00639: if (buffer.get(k) > zmax)
00640: zmax = buffer.get(k);
00641: if (buffer.get(k) < zmin)
00642: zmin = buffer.get(k);
00643:
00644: }
00645: geoBounds.setUpper(xmax, ymax, zmax);
00646: geoBounds.setLower(xmin, ymin, zmin);
00647: boundsDirty = false;
00648: }
00649: }
00650:
00651: // compute bounding box for coord with noi buffer
00652: void computeBoundingBox(FloatBufferWrapper buffer) {
00653: int i, j, k, sIndex;
00654: double xmin, xmax, ymin, ymax, zmin, zmax;
00655:
00656: synchronized (geoBounds) {
00657: // If autobounds compute is false then return
00658: if ((computeGeoBounds == 0) && (refCount > 0)) {
00659: return;
00660: }
00661:
00662: if (!boundsDirty)
00663: return;
00664:
00665: sIndex = initialCoordIndex;
00666: int maxIndex = 3 * validVertexCount;
00667:
00668: // Compute the bounding box
00669: xmin = xmax = buffer.get(sIndex++);
00670: ymin = ymax = buffer.get(sIndex++);
00671: zmin = zmax = buffer.get(sIndex++);
00672:
00673: for (i = sIndex; i < maxIndex; i += 3) {
00674: j = i + 1;
00675: k = i + 2;
00676:
00677: if (buffer.get(i) > xmax)
00678: xmax = buffer.get(i);
00679: if (buffer.get(i) < xmin)
00680: xmin = buffer.get(i);
00681:
00682: if (buffer.get(j) > ymax)
00683: ymax = buffer.get(j);
00684: if (buffer.get(j) < ymin)
00685: ymin = buffer.get(j);
00686:
00687: if (buffer.get(k) > zmax)
00688: zmax = buffer.get(k);
00689: if (buffer.get(k) < zmin)
00690: zmin = buffer.get(k);
00691:
00692: }
00693: geoBounds.setUpper(xmax, ymax, zmax);
00694: geoBounds.setLower(xmin, ymin, zmin);
00695: boundsDirty = false;
00696: }
00697: }
00698:
00699: void computeBoundingBox(float[] coords) {
00700: // System.err.println("GeometryArrayRetained : computeBoundingBox(float[] coords)");
00701: int i, j, k, sIndex;
00702: double xmin, xmax, ymin, ymax, zmin, zmax;
00703:
00704: synchronized (geoBounds) {
00705: // If autobounds compute is false then return
00706: if ((computeGeoBounds == 0) && (refCount > 0)) {
00707: return;
00708: }
00709:
00710: if (!boundsDirty)
00711: return;
00712:
00713: sIndex = initialCoordIndex;
00714: int maxIndex = 3 * validVertexCount;
00715:
00716: // Compute the bounding box
00717: xmin = xmax = coords[sIndex++];
00718: ymin = ymax = coords[sIndex++];
00719: zmin = zmax = coords[sIndex++];
00720:
00721: for (i = sIndex; i < maxIndex; i += 3) {
00722: j = i + 1;
00723: k = i + 2;
00724:
00725: if (coords[i] > xmax)
00726: xmax = coords[i];
00727: if (coords[i] < xmin)
00728: xmin = coords[i];
00729:
00730: if (coords[j] > ymax)
00731: ymax = coords[j];
00732: if (coords[j] < ymin)
00733: ymin = coords[j];
00734:
00735: if (coords[k] > zmax)
00736: zmax = coords[k];
00737: if (coords[k] < zmin)
00738: zmin = coords[k];
00739:
00740: }
00741: geoBounds.setUpper(xmax, ymax, zmax);
00742: // System.err.println("max(" + xmax + ", " + ymax + ", " + zmax + ")");
00743: geoBounds.setLower(xmin, ymin, zmin);
00744: // System.err.println("min(" + xmin + ", " + ymin + ", " + zmin + ")");
00745:
00746: boundsDirty = false;
00747: }
00748:
00749: }
00750:
00751: void computeBoundingBox(double[] coords) {
00752: int i, j, k, sIndex;
00753: double xmin, xmax, ymin, ymax, zmin, zmax;
00754:
00755: synchronized (geoBounds) {
00756: // If autobounds compute is false then return
00757: if ((computeGeoBounds == 0) && (refCount > 0)) {
00758: return;
00759: }
00760:
00761: if (!boundsDirty)
00762: return;
00763:
00764: sIndex = initialCoordIndex;
00765: int maxIndex = 3 * validVertexCount;
00766:
00767: // Compute the bounding box
00768: xmin = xmax = coords[sIndex++];
00769: ymin = ymax = coords[sIndex++];
00770: zmin = zmax = coords[sIndex++];
00771:
00772: for (i = sIndex; i < maxIndex; i += 3) {
00773: j = i + 1;
00774: k = i + 2;
00775:
00776: if (coords[i] > xmax)
00777: xmax = coords[i];
00778: if (coords[i] < xmin)
00779: xmin = coords[i];
00780:
00781: if (coords[j] > ymax)
00782: ymax = coords[j];
00783: if (coords[j] < ymin)
00784: ymin = coords[j];
00785:
00786: if (coords[k] > zmax)
00787: zmax = coords[k];
00788: if (coords[k] < zmin)
00789: zmin = coords[k];
00790:
00791: }
00792: geoBounds.setUpper(xmax, ymax, zmax);
00793: geoBounds.setLower(xmin, ymin, zmin);
00794: boundsDirty = false;
00795: }
00796:
00797: }
00798:
00799: void computeBoundingBox(Point3f[] coords) {
00800:
00801: double xmin, xmax, ymin, ymax, zmin, zmax;
00802: Point3f p;
00803:
00804: synchronized (geoBounds) {
00805: // If autobounds compute is false then return
00806: if ((computeGeoBounds == 0) && (refCount > 0)) {
00807: return;
00808: }
00809:
00810: if (!boundsDirty)
00811: return;
00812:
00813: // Compute the bounding box
00814: xmin = xmax = coords[initialCoordIndex].x;
00815: ymin = ymax = coords[initialCoordIndex].y;
00816: zmin = zmax = coords[initialCoordIndex].z;
00817:
00818: for (int i = initialCoordIndex + 1; i < validVertexCount; i++) {
00819: p = coords[i];
00820: if (p.x > xmax)
00821: xmax = p.x;
00822: if (p.x < xmin)
00823: xmin = p.x;
00824:
00825: if (p.y > ymax)
00826: ymax = p.y;
00827: if (p.y < ymin)
00828: ymin = p.y;
00829:
00830: if (p.z > zmax)
00831: zmax = p.z;
00832: if (p.z < zmin)
00833: zmin = p.z;
00834:
00835: }
00836: geoBounds.setUpper(xmax, ymax, zmax);
00837: geoBounds.setLower(xmin, ymin, zmin);
00838: boundsDirty = false;
00839: }
00840:
00841: }
00842:
00843: void computeBoundingBox(Point3d[] coords) {
00844:
00845: double xmin, xmax, ymin, ymax, zmin, zmax;
00846: Point3d p;
00847:
00848: synchronized (geoBounds) {
00849: // If autobounds compute is false then return
00850: if ((computeGeoBounds == 0) && (refCount > 0)) {
00851: return;
00852: }
00853:
00854: if (!boundsDirty)
00855: return;
00856:
00857: // Compute the bounding box
00858: xmin = xmax = coords[initialCoordIndex].x;
00859: ymin = ymax = coords[initialCoordIndex].y;
00860: zmin = zmax = coords[initialCoordIndex].z;
00861:
00862: for (int i = initialCoordIndex + 1; i < validVertexCount; i++) {
00863: p = coords[i];
00864: if (p.x > xmax)
00865: xmax = p.x;
00866: if (p.x < xmin)
00867: xmin = p.x;
00868:
00869: if (p.y > ymax)
00870: ymax = p.y;
00871: if (p.y < ymin)
00872: ymin = p.y;
00873:
00874: if (p.z > zmax)
00875: zmax = p.z;
00876: if (p.z < zmin)
00877: zmin = p.z;
00878:
00879: }
00880: geoBounds.setUpper(xmax, ymax, zmax);
00881: geoBounds.setLower(xmin, ymin, zmin);
00882: boundsDirty = false;
00883: }
00884:
00885: }
00886:
00887: synchronized void update() {
00888: }
00889:
00890: void setupMirrorVertexPointer(int vType) {
00891: int i, index;
00892:
00893: switch (vType) {
00894: case PF:
00895: if (floatRefCoords == null) {
00896: if ((vertexType & VERTEX_DEFINED) == PF) {
00897: vertexType &= ~PF;
00898: mirrorFloatRefCoords = null;
00899: mirrorVertexAllocated &= ~PF;
00900: }
00901: } else {
00902: vertexType |= PF;
00903: mirrorFloatRefCoords = floatRefCoords;
00904: mirrorVertexAllocated &= ~PF;
00905: }
00906:
00907: break;
00908: case PD:
00909: if (doubleRefCoords == null) {
00910: if ((vertexType & VERTEX_DEFINED) == PD) {
00911: mirrorDoubleRefCoords = null;
00912: mirrorVertexAllocated &= ~PD;
00913: vertexType &= ~PD;
00914: }
00915: vertexType &= ~PD;
00916: } else {
00917: vertexType |= PD;
00918: mirrorDoubleRefCoords = doubleRefCoords;
00919: mirrorVertexAllocated &= ~PD;
00920: }
00921:
00922: break;
00923: case P3F:
00924: if (p3fRefCoords == null) {
00925: vertexType &= ~P3F;
00926: // Don't set the mirrorFloatRefCoords to null,
00927: // may be able to re-use
00928: // mirrorFloatRefCoords = null;
00929: } else {
00930: vertexType |= P3F;
00931:
00932: if ((mirrorVertexAllocated & PF) == 0) {
00933: mirrorFloatRefCoords = new float[vertexCount * 3];
00934: mirrorVertexAllocated |= PF;
00935: }
00936:
00937: index = initialCoordIndex * 3;
00938: for (i = initialCoordIndex; i < validVertexCount; i++) {
00939: mirrorFloatRefCoords[index++] = p3fRefCoords[i].x;
00940: mirrorFloatRefCoords[index++] = p3fRefCoords[i].y;
00941: mirrorFloatRefCoords[index++] = p3fRefCoords[i].z;
00942: }
00943: }
00944: break;
00945: case P3D:
00946: if (p3dRefCoords == null) {
00947: vertexType &= ~P3D;
00948: // Don't set the mirrorDoubleRefCoords to null,
00949: // may be able to re-use
00950: // mirrorDoubleRefCoords = null;
00951: } else {
00952: vertexType |= P3D;
00953:
00954: if ((mirrorVertexAllocated & PD) == 0) {
00955: mirrorDoubleRefCoords = new double[vertexCount * 3];
00956: mirrorVertexAllocated |= PD;
00957: }
00958:
00959: index = initialCoordIndex * 3;
00960: for (i = initialCoordIndex; i < validVertexCount; i++) {
00961: mirrorDoubleRefCoords[index++] = p3dRefCoords[i].x;
00962: mirrorDoubleRefCoords[index++] = p3dRefCoords[i].y;
00963: mirrorDoubleRefCoords[index++] = p3dRefCoords[i].z;
00964: }
00965: }
00966: break;
00967: default:
00968: break;
00969:
00970: }
00971:
00972: }
00973:
00974: // If turned transparent the first time, then force it to allocate
00975: void setupMirrorInterleavedColorPointer(boolean force) {
00976: int index, length, offset;
00977: int i;
00978:
00979: if (force || (c4fAllocated != 0)) { // Color is present
00980:
00981: length = 4 * vertexCount;
00982:
00983: if (mirrorInterleavedColorPointer == null) {
00984: mirrorInterleavedColorPointer = new float[1][length];
00985: }
00986:
00987: index = 4 * initialVertexIndex;
00988: offset = stride * initialVertexIndex + colorOffset;
00989:
00990: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0
00991: && interLeavedVertexData != null) { // java array
00992: if ((vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
00993:
00994: for (i = initialVertexIndex; i < validVertexCount; i++) {
00995: mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset];
00996: mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 1];
00997: mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 2];
00998: mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 3];
00999: offset += stride;
01000: }
01001: } else {
01002: for (i = initialVertexIndex; i < validVertexCount; i++) {
01003: mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset];
01004: mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 1];
01005: mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 2];
01006: mirrorInterleavedColorPointer[0][index++] = 1.0f;
01007: offset += stride;
01008: }
01009: }
01010:
01011: } else { // NIO BUFFER
01012: if ((vertexFormat & GeometryArray.WITH_ALPHA) != 0
01013: && interleavedFloatBufferImpl != null) {
01014: for (i = initialVertexIndex; i < validVertexCount; i++) {
01015: interleavedFloatBufferImpl.position(offset);
01016: interleavedFloatBufferImpl.get(
01017: mirrorInterleavedColorPointer[0],
01018: index, 4);
01019: index += 4;
01020: offset += stride;
01021: }
01022: } else {
01023: for (i = initialVertexIndex; i < validVertexCount; i++) {
01024: interleavedFloatBufferImpl.position(offset);
01025: interleavedFloatBufferImpl.get(
01026: mirrorInterleavedColorPointer[0],
01027: index, 3);
01028: mirrorInterleavedColorPointer[0][index + 3] = 1.0f;
01029: index += 4;
01030: offset += stride;
01031:
01032: }
01033: }
01034: }
01035: c4fAllocated = GeometryArray.WITH_ALPHA;
01036: }
01037: }
01038:
01039: // If turned transparent the first time, then force it to allocate
01040: void setupMirrorColorPointer(int ctype, boolean force) {
01041: int i, srcIndex = 0, dstIndex = 0;
01042: int multiplier;
01043:
01044: if (c4fAllocated == 0 && !force) {
01045: multiplier = 3;
01046: } else {
01047:
01048: // If the first time, we are forced to allocate 4f, then
01049: // we need to force the allocation of the colors again
01050: // for the case when allocation has previously occurred
01051: // only for RGB
01052: if (force && (c4fAllocated == 0)
01053: && (vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01054: mirrorColorAllocated = 0;
01055: }
01056: c4fAllocated = GeometryArray.WITH_ALPHA;
01057: multiplier = 4;
01058: }
01059:
01060: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) { // java array
01061: switch (ctype) {
01062: case CF:
01063: if (floatRefColors == null) {
01064: if ((c4fAllocated == 0) && !force
01065: && (vertexType & COLOR_DEFINED) == CF) {
01066: mirrorFloatRefColors[0] = null;
01067: mirrorColorAllocated &= ~CF;
01068: }
01069: vertexType &= ~CF;
01070: return;
01071: }
01072:
01073: vertexType |= CF;
01074: if (c4fAllocated == 0 && !force) {
01075: mirrorFloatRefColors[0] = floatRefColors;
01076: mirrorColorAllocated &= ~CF;
01077: } else {
01078: if ((mirrorColorAllocated & CF) == 0) {
01079: mirrorFloatRefColors[0] = new float[4 * vertexCount];
01080: mirrorColorAllocated |= CF;
01081: }
01082:
01083: if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01084:
01085: srcIndex = initialColorIndex * 3;
01086: dstIndex = initialColorIndex * 4;
01087:
01088: for (i = initialColorIndex; i < validVertexCount; i++) {
01089: mirrorFloatRefColors[0][dstIndex++] = floatRefColors[srcIndex++];
01090: mirrorFloatRefColors[0][dstIndex++] = floatRefColors[srcIndex++];
01091: mirrorFloatRefColors[0][dstIndex++] = floatRefColors[srcIndex++];
01092: mirrorFloatRefColors[0][dstIndex++] = 1.0f;
01093: }
01094:
01095: } else {
01096: srcIndex = initialColorIndex * 4;
01097: System.arraycopy(floatRefColors, srcIndex,
01098: mirrorFloatRefColors[0], srcIndex,
01099: (4 * validVertexCount));
01100: }
01101: }
01102: break;
01103: case CUB:
01104: if (byteRefColors == null) {
01105: if (c4fAllocated == 0 && !force
01106: && ((vertexType & COLOR_DEFINED) == CUB)) {
01107: mirrorUnsignedByteRefColors[0] = null;
01108: mirrorColorAllocated &= ~CUB;
01109: }
01110: vertexType &= ~CUB;
01111: return;
01112: }
01113: vertexType |= CUB;
01114: if (c4fAllocated == 0 && !force) {
01115: mirrorUnsignedByteRefColors[0] = byteRefColors;
01116: mirrorColorAllocated &= ~CUB;
01117: ;
01118: } else {
01119: if ((mirrorColorAllocated & CUB) == 0) {
01120: mirrorUnsignedByteRefColors[0] = new byte[4 * vertexCount];
01121: mirrorColorAllocated |= CUB;
01122: }
01123: if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01124:
01125: srcIndex = initialColorIndex * 3;
01126: dstIndex = initialColorIndex * 4;
01127:
01128: for (i = initialColorIndex; i < validVertexCount; i++) {
01129: mirrorUnsignedByteRefColors[0][dstIndex++] = byteRefColors[srcIndex++];
01130: mirrorUnsignedByteRefColors[0][dstIndex++] = byteRefColors[srcIndex++];
01131: mirrorUnsignedByteRefColors[0][dstIndex++] = byteRefColors[srcIndex++];
01132: mirrorUnsignedByteRefColors[0][dstIndex++] = (byte) (255.0);
01133: }
01134: } else {
01135: srcIndex = initialColorIndex * 4;
01136: System.arraycopy(byteRefColors, srcIndex,
01137: mirrorUnsignedByteRefColors[0],
01138: srcIndex, (4 * validVertexCount));
01139: }
01140: }
01141:
01142: break;
01143: case C3F:
01144: if (c3fRefColors == null) {
01145: vertexType &= ~C3F;
01146: return;
01147: }
01148: vertexType |= C3F;
01149:
01150: if ((mirrorColorAllocated & CF) == 0) {
01151: mirrorFloatRefColors[0] = new float[vertexCount
01152: * multiplier];
01153: mirrorColorAllocated |= CF;
01154: }
01155: if ((c4fAllocated & GeometryArray.WITH_ALPHA) == 0) {
01156:
01157: dstIndex = initialColorIndex * 3;
01158: for (i = initialColorIndex; i < validVertexCount; i++) {
01159: mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].x;
01160: mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].y;
01161: mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].z;
01162: }
01163: } else {
01164:
01165: dstIndex = initialColorIndex * 4;
01166: for (i = initialColorIndex; i < validVertexCount; i++) {
01167: mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].x;
01168: mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].y;
01169: mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].z;
01170: mirrorFloatRefColors[0][dstIndex++] = 1.0f;
01171: }
01172: }
01173:
01174: break;
01175: case C4F:
01176: if (c4fRefColors == null) {
01177: vertexType &= ~C4F;
01178: return;
01179: }
01180: vertexType |= C4F;
01181:
01182: if ((mirrorColorAllocated & CF) == 0) {
01183: mirrorFloatRefColors[0] = new float[vertexCount << 2];
01184: mirrorColorAllocated |= CF;
01185: }
01186:
01187: dstIndex = initialColorIndex * 4;
01188: for (i = initialColorIndex; i < validVertexCount; i++) {
01189: mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].x;
01190: mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].y;
01191: mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].z;
01192: mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].w;
01193: }
01194: break;
01195: case C3UB:
01196: if (c3bRefColors == null) {
01197: vertexType &= ~C3UB;
01198: return;
01199: }
01200: vertexType |= C3UB;
01201:
01202: if ((mirrorColorAllocated & CUB) == 0) {
01203: mirrorUnsignedByteRefColors[0] = new byte[vertexCount
01204: * multiplier];
01205: mirrorColorAllocated |= CUB;
01206: }
01207: if ((c4fAllocated & GeometryArray.WITH_ALPHA) == 0) {
01208: dstIndex = initialColorIndex * 3;
01209: for (i = initialColorIndex; i < validVertexCount; i++) {
01210: mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].x;
01211: mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].y;
01212: mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].z;
01213: }
01214: } else {
01215: dstIndex = initialColorIndex * 4;
01216: for (i = initialColorIndex; i < validVertexCount; i++) {
01217: mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].x;
01218: mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].y;
01219: mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].z;
01220: mirrorUnsignedByteRefColors[0][dstIndex++] = (byte) 255;
01221: }
01222: }
01223: break;
01224: case C4UB:
01225: if (c4bRefColors == null) {
01226: vertexType &= ~C4UB;
01227: return;
01228: }
01229: vertexType |= C4UB;
01230: if ((mirrorColorAllocated & CUB) == 0) {
01231: mirrorUnsignedByteRefColors[0] = new byte[vertexCount << 2];
01232: mirrorColorAllocated |= CUB;
01233: }
01234:
01235: dstIndex = initialColorIndex * 4;
01236: for (i = initialColorIndex; i < validVertexCount; i++) {
01237: mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].x;
01238: mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].y;
01239: mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].z;
01240: mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].w;
01241: }
01242: break;
01243: default:
01244: break;
01245: }
01246: } else { //USE_NIO_BUFFER is set
01247: if (colorRefBuffer == null) {
01248: if (c4fAllocated == 0 && !force
01249: && (vertexType & COLOR_DEFINED) == CF) {
01250: mirrorFloatRefColors[0] = null;
01251: mirrorColorAllocated &= ~CF;
01252: }
01253: vertexType &= ~CF;
01254:
01255: if (c4fAllocated == 0 && !force
01256: && ((vertexType & COLOR_DEFINED) == CUB)) {
01257: mirrorUnsignedByteRefColors[0] = null;
01258: mirrorColorAllocated &= ~CUB;
01259: }
01260: vertexType &= ~CUB;
01261: return;
01262:
01263: } else if (floatBufferRefColors != null) {
01264: vertexType |= CF;
01265: vertexType &= ~CUB;
01266: if (c4fAllocated == 0 && !force) {
01267: // NOTE: make suren mirrorFloatRefColors[0] is set right
01268: mirrorFloatRefColors[0] = null;
01269: mirrorColorAllocated &= ~CF;
01270: } else {
01271: if ((mirrorColorAllocated & CF) == 0) {
01272: mirrorFloatRefColors[0] = new float[4 * vertexCount];
01273: mirrorColorAllocated |= CF;
01274: }
01275: floatBufferRefColors.rewind();
01276: if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01277: srcIndex = initialColorIndex * 3;
01278: dstIndex = initialColorIndex * 4;
01279: floatBufferRefColors.position(srcIndex);
01280:
01281: for (i = initialColorIndex; i < validVertexCount; i++) {
01282: floatBufferRefColors.get(
01283: mirrorFloatRefColors[0], dstIndex,
01284: 3);
01285: mirrorFloatRefColors[0][dstIndex + 3] = 1.0f;
01286: dstIndex += 4;
01287: }
01288: } else {
01289:
01290: srcIndex = initialColorIndex * 4;
01291: dstIndex = initialColorIndex * 4;
01292: floatBufferRefColors.position(srcIndex);
01293: for (i = initialColorIndex; i < validVertexCount; i++) {
01294: floatBufferRefColors.get(
01295: mirrorFloatRefColors[0], dstIndex,
01296: 4);
01297: dstIndex += 4;
01298: }
01299: }
01300: }
01301: } else if (byteBufferRefColors != null) {
01302: vertexType |= CUB;
01303: vertexType &= ~CF;
01304: if (c4fAllocated == 0 && !force) {
01305: // NOTE: make sure mirrorUnsignedByteRefColors[0] is set right
01306: mirrorUnsignedByteRefColors[0] = null;
01307: mirrorColorAllocated &= ~CUB;
01308: ;
01309: } else {
01310: if ((mirrorColorAllocated & CUB) == 0) {
01311: mirrorUnsignedByteRefColors[0] = new byte[4 * vertexCount];
01312: mirrorColorAllocated |= CUB;
01313: }
01314:
01315: byteBufferRefColors.rewind();
01316: if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01317: srcIndex = initialColorIndex * 3;
01318: dstIndex = initialColorIndex * 4;
01319: byteBufferRefColors.position(srcIndex);
01320: for (i = initialColorIndex; i < validVertexCount; i++) {
01321: byteBufferRefColors.get(
01322: mirrorUnsignedByteRefColors[0],
01323: dstIndex, 3);
01324: mirrorUnsignedByteRefColors[0][dstIndex + 3] = (byte) (255.0);
01325: dstIndex += 4;
01326: }
01327: } else {
01328: srcIndex = initialColorIndex * 4;
01329: dstIndex = initialColorIndex * 4;
01330: byteBufferRefColors.position(srcIndex);
01331: for (i = initialColorIndex; i < validVertexCount; i++) {
01332: byteBufferRefColors.get(
01333: mirrorUnsignedByteRefColors[0],
01334: dstIndex, 4);
01335: dstIndex += 4;
01336: }
01337: }
01338: } // end of else
01339: }//end of else if ( byteBufferRefColors != null)
01340: }//end of NIO BUFFER case
01341:
01342: colorChanged = 0xffff;
01343: }
01344:
01345: void setupMirrorNormalPointer(int ntype) {
01346: int i, index;
01347:
01348: switch (ntype) {
01349: case NF:
01350: if (floatRefNormals == null) {
01351: if ((vertexType & NORMAL_DEFINED) == NF) {
01352: vertexType &= ~NF;
01353: mirrorFloatRefNormals = null;
01354: mirrorNormalAllocated = false;
01355: }
01356: } else {
01357: vertexType |= NF;
01358: mirrorFloatRefNormals = floatRefNormals;
01359: mirrorNormalAllocated = false;
01360: }
01361: break;
01362: case N3F:
01363: if (v3fRefNormals == null) {
01364: if ((vertexType & NORMAL_DEFINED) == N3F) {
01365: vertexType &= ~N3F;
01366: }
01367: return;
01368: } else {
01369: vertexType |= N3F;
01370: }
01371: if (!mirrorNormalAllocated) {
01372: mirrorFloatRefNormals = new float[vertexCount * 3];
01373: mirrorNormalAllocated = true;
01374: }
01375:
01376: index = initialNormalIndex * 3;
01377: for (i = initialNormalIndex; i < validVertexCount; i++) {
01378: mirrorFloatRefNormals[index++] = v3fRefNormals[i].x;
01379: mirrorFloatRefNormals[index++] = v3fRefNormals[i].y;
01380: mirrorFloatRefNormals[index++] = v3fRefNormals[i].z;
01381: }
01382: break;
01383: default:
01384: break;
01385: }
01386: }
01387:
01388: void setupMirrorTexCoordPointer(int type) {
01389: for (int i = 0; i < texCoordSetCount; i++) {
01390: doSetupMirrorTexCoordPointer(i, type);
01391: }
01392:
01393: validateTexCoordPointerType();
01394: }
01395:
01396: void setupMirrorTexCoordPointer(int texCoordSet, int type) {
01397: doSetupMirrorTexCoordPointer(texCoordSet, type);
01398: validateTexCoordPointerType();
01399: }
01400:
01401: // If all texCoord pointers are set to a non-null value, then set the
01402: // texcoord type in the vertexType flag word, else clear the texcoord type
01403: private void validateTexCoordPointerType() {
01404: boolean allNonNull = true;
01405: boolean allNull = true;
01406: for (int i = 0; i < texCoordSetCount; i++) {
01407: if (refTexCoords[i] == null) {
01408: allNonNull = false;
01409: } else {
01410: allNull = false;
01411: }
01412: }
01413:
01414: // Reset texCoordType if all references are null
01415: if (allNull) {
01416: texCoordType = 0;
01417: }
01418:
01419: // Copy texCoordType to vertexType if all references are non-null
01420: vertexType &= ~TEXCOORD_DEFINED;
01421: if (allNonNull) {
01422: vertexType |= texCoordType;
01423: }
01424: }
01425:
01426: private void doSetupMirrorTexCoordPointer(int texCoordSet, int type) {
01427: int i, index;
01428:
01429: switch (type) {
01430: case TF:
01431: texCoordType = TF;
01432: mirrorRefTexCoords[texCoordSet] = refTexCoords[texCoordSet];
01433: break;
01434:
01435: case T2F:
01436: texCoordType = T2F;
01437: t2fRefTexCoords = (TexCoord2f[]) refTexCoords[texCoordSet];
01438:
01439: if (t2fRefTexCoords == null) {
01440: mirrorRefTexCoords[texCoordSet] = null;
01441: break;
01442: }
01443:
01444: mirrorFloatRefTexCoords = (float[]) mirrorRefTexCoords[texCoordSet];
01445: if (mirrorFloatRefTexCoords != null) {
01446: if (mirrorFloatRefTexCoords.length < (vertexCount * 2))
01447: mirrorRefTexCoords[texCoordSet] = mirrorFloatRefTexCoords = new float[vertexCount * 2];
01448: } else {
01449: mirrorRefTexCoords[texCoordSet] = mirrorFloatRefTexCoords = new float[vertexCount * 2];
01450: }
01451:
01452: index = initialTexCoordIndex[texCoordSet] * 2;
01453: for (i = initialTexCoordIndex[texCoordSet]; i < validVertexCount; i++) {
01454: mirrorFloatRefTexCoords[index++] = t2fRefTexCoords[i].x;
01455: mirrorFloatRefTexCoords[index++] = t2fRefTexCoords[i].y;
01456: }
01457: break;
01458:
01459: case T3F:
01460: texCoordType = T3F;
01461: t3fRefTexCoords = (TexCoord3f[]) refTexCoords[texCoordSet];
01462:
01463: if (t3fRefTexCoords == null) {
01464: mirrorRefTexCoords[texCoordSet] = null;
01465: break;
01466: }
01467:
01468: mirrorFloatRefTexCoords = (float[]) mirrorRefTexCoords[texCoordSet];
01469: if (mirrorFloatRefTexCoords != null) {
01470: if (mirrorFloatRefTexCoords.length < (vertexCount * 3))
01471: mirrorRefTexCoords[texCoordSet] = mirrorFloatRefTexCoords = new float[vertexCount * 3];
01472: } else {
01473: mirrorRefTexCoords[texCoordSet] = mirrorFloatRefTexCoords = new float[vertexCount * 3];
01474: }
01475:
01476: index = initialTexCoordIndex[texCoordSet] * 3;
01477: for (i = initialTexCoordIndex[texCoordSet]; i < validVertexCount; i++) {
01478: mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].x;
01479: mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].y;
01480: mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].z;
01481: }
01482: break;
01483:
01484: default:
01485: break;
01486: }
01487: }
01488:
01489: void setupMirrorVertexAttrPointer(int type) {
01490: for (int i = 0; i < vertexAttrCount; i++) {
01491: doSetupMirrorVertexAttrPointer(i, type);
01492: }
01493:
01494: validateVertexAttrPointerType();
01495: }
01496:
01497: void setupMirrorVertexAttrPointer(int vertexAttrNum, int type) {
01498: doSetupMirrorVertexAttrPointer(vertexAttrNum, type);
01499: validateVertexAttrPointerType();
01500: }
01501:
01502: // If all vertex attr pointers are set to a non-null value, then set the
01503: // vertex attr type in the vertexType flag word, else clear the
01504: // vertex attr type
01505: private void validateVertexAttrPointerType() {
01506: boolean allNonNull = true;
01507: boolean allNull = true;
01508:
01509: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
01510: for (int i = 0; i < vertexAttrCount; i++) {
01511: if (floatRefVertexAttrs[i] == null) {
01512: allNonNull = false;
01513: } else {
01514: allNull = false;
01515: }
01516: }
01517: } else {
01518: for (int i = 0; i < vertexAttrCount; i++) {
01519: if (nioFloatBufferRefVertexAttrs[i] == null) {
01520: allNonNull = false;
01521: } else {
01522: allNull = false;
01523: }
01524: }
01525: }
01526:
01527: // Reset vertexAttrType if all references are null
01528: if (allNull) {
01529: vertexAttrType = 0;
01530: }
01531:
01532: // Copy vertexAttrType to vertexType if all references are non-null
01533: vertexType &= ~VATTR_DEFINED;
01534: if (allNonNull) {
01535: vertexType |= vertexAttrType;
01536: }
01537: }
01538:
01539: private void doSetupMirrorVertexAttrPointer(int vertexAttrNum,
01540: int type) {
01541: switch (type) {
01542: case AF:
01543: vertexAttrType = AF;
01544: mirrorFloatRefVertexAttrs[vertexAttrNum] = floatRefVertexAttrs[vertexAttrNum];
01545: break;
01546: default:
01547: break;
01548: }
01549: }
01550:
01551: void createGeometryArrayData(int vertexCount, int vertexFormat) {
01552: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
01553: createGeometryArrayData(vertexCount, vertexFormat, 1,
01554: defaultTexCoordSetMap);
01555: } else {
01556: createGeometryArrayData(vertexCount, vertexFormat, 0, null);
01557: }
01558: }
01559:
01560: void createGeometryArrayData(int vertexCount, int vertexFormat,
01561: int texCoordSetCount, int[] texCoordSetMap) {
01562:
01563: createGeometryArrayData(vertexCount, vertexFormat,
01564: texCoordSetCount, texCoordSetMap, 0, null);
01565: }
01566:
01567: void createGeometryArrayData(int vertexCount, int vertexFormat,
01568: int texCoordSetCount, int[] texCoordSetMap,
01569: int vertexAttrCount, int[] vertexAttrSizes) {
01570: this .vertexFormat = vertexFormat;
01571: this .vertexCount = vertexCount;
01572: this .validVertexCount = vertexCount;
01573:
01574: this .texCoordSetCount = texCoordSetCount;
01575: if (texCoordSetMap == null) {
01576: this .texCoordSetMap = null;
01577: } else {
01578: this .texCoordSetMap = (int[]) texCoordSetMap.clone();
01579: }
01580:
01581: this .vertexAttrCount = vertexAttrCount;
01582: if (vertexAttrSizes == null) {
01583: this .vertexAttrSizes = null;
01584: } else {
01585: this .vertexAttrSizes = (int[]) vertexAttrSizes.clone();
01586: }
01587:
01588: this .vertexAttrStride = this .vertexAttrStride();
01589: this .stride = this .stride();
01590:
01591: this .vertexAttrOffsets = this .vertexAttrOffsets();
01592: this .texCoordSetMapOffset = this .texCoordSetMapOffset();
01593: this .textureOffset = this .textureOffset();
01594: this .colorOffset = this .colorOffset();
01595: this .normalOffset = this .normalOffset();
01596: this .coordinateOffset = this .coordinateOffset();
01597:
01598: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
01599: this .vertexData = new float[this .vertexCount * this .stride];
01600: } else { // By reference geometry
01601: this .vertexData = null;
01602: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
01603: this .mirrorRefTexCoords = new Object[texCoordSetCount];
01604: this .refTexCoords = new Object[texCoordSetCount]; // keep J3DBufferImp object in nio buffer case
01605: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0)
01606: this .refTexCoordsBuffer = new Object[texCoordSetCount]; // keep J3DBuffer object
01607: }
01608: if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
01609: this .floatRefVertexAttrs = new float[vertexAttrCount][];
01610: this .mirrorFloatRefVertexAttrs = new float[vertexAttrCount][];
01611: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
01612: this .vertexAttrsRefBuffer = new J3DBuffer[vertexAttrCount];
01613: this .floatBufferRefVertexAttrs = new FloatBufferWrapper[vertexAttrCount];
01614: this .nioFloatBufferRefVertexAttrs = new Object[vertexAttrCount];
01615: }
01616: }
01617: }
01618: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
01619: this .initialTexCoordIndex = new int[texCoordSetCount];
01620: }
01621: if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
01622: this .initialVertexAttrIndex = new int[vertexAttrCount];
01623: }
01624: noAlpha = ((vertexFormat & GeometryArray.WITH_ALPHA) == 0);
01625: lastAlpha[0] = 1.0f;
01626:
01627: }
01628:
01629: void setVertexFormat(boolean useAlpha, boolean ignoreVC, Context ctx) {
01630: Pipeline.getPipeline().setVertexFormat(ctx, this , vertexFormat,
01631: useAlpha, ignoreVC);
01632: }
01633:
01634: void disableGlobalAlpha(Context ctx, boolean useAlpha,
01635: boolean ignoreVC) {
01636: // If global alpha was turned on, then disable it
01637: Pipeline.getPipeline().disableGlobalAlpha(ctx, this ,
01638: vertexFormat, useAlpha, ignoreVC);
01639: }
01640:
01641: float[] updateAlphaInFloatRefColors(Canvas3D cv, int screen,
01642: float alpha) {
01643:
01644: //System.err.println("updateAlphaInFloatRefColors screen = " + screen +
01645: // " alpha " + alpha );
01646:
01647: // no need to update alpha values if canvas supports global alpha
01648: if (cv.supportGlobalAlpha()) {
01649: cv.setGlobalAlpha(cv.ctx, alpha);
01650: return mirrorFloatRefColors[0];
01651: }
01652:
01653: // update alpha only if vertex format includes alpha
01654: if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0)
01655: return mirrorFloatRefColors[0];
01656:
01657: // if alpha is smaller than EPSILON, set it to EPSILON, so that
01658: // even if alpha is equal to 0, we will not completely lose
01659: // the original alpha value
01660: if (alpha <= EPSILON) {
01661: alpha = (float) EPSILON;
01662: }
01663:
01664: assert lastAlpha != null;
01665: assert mirrorFloatRefColors != null;
01666: assert mirrorFloatRefColors.length == lastAlpha.length;
01667:
01668: // Issue 113 - reallocate lastAlpha array if needed, but no need to
01669: // update the values here
01670: if (lastAlpha.length <= screen) {
01671: float[] la = new float[screen + 1];
01672: for (int i = 0; i < lastAlpha.length; i++) {
01673: la[i] = lastAlpha[i];
01674: }
01675: lastAlpha = la;
01676: }
01677:
01678: //System.err.println("updateAlphaInFloatRefColors screen is " + screen
01679: // + " mirrorFloatRefColors.length " +
01680: // mirrorFloatRefColors.length);
01681:
01682: // allocate a copy of the color data for the screen if needed.
01683: // this piece of code is only for multi-screens case
01684: if (mirrorFloatRefColors.length <= screen) {
01685: float[][] cfData = new float[screen + 1][];
01686:
01687: for (int i = 0; i < mirrorFloatRefColors.length; i++) {
01688: cfData[i] = mirrorFloatRefColors[i];
01689: }
01690:
01691: // Issue 113 - allocate entries for [oldSize..screen];
01692: // copy cfData[0] to cfData[oldsize..screen-1] and
01693: // lastAlpha[0] to lastAlpha[oldsize..screen-1].
01694: for (int i = mirrorFloatRefColors.length; i < screen + 1; i++) {
01695: cfData[i] = new float[4 * vertexCount];
01696: System.arraycopy(cfData[0], 0, cfData[i], 0,
01697: 4 * vertexCount);
01698: lastAlpha[i] = lastAlpha[0];
01699: }
01700:
01701: mirrorFloatRefColors = cfData;
01702:
01703: // Issue 113 - since we copied the data from screen 0, we don't need
01704: // to do any further special processing.
01705: }
01706:
01707: assert lastAlpha[screen] >= 0.0;
01708: /*
01709: System.err.println("updateAlphaInFloatRefColors ** : lastAlpha[screen] " +
01710: lastAlpha[screen]);
01711:
01712: System.err.println("((colorChanged & (1<<screen)) == 0) " +
01713: ((colorChanged & (1<<screen)) == 0));
01714: */
01715:
01716: if ((colorChanged & (1 << screen)) == 0) {
01717: // color data is not modified
01718: if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
01719: // and if alpha is the same as the last one,
01720: // just return the data
01721: //System.err.println("updateAlphaInFloatRefColors 0 : alpha is the same as the last one " + alpha);
01722:
01723: return mirrorFloatRefColors[screen];
01724: } else {
01725:
01726: // if alpha is different, update the alpha values
01727: //System.err.println("updateAlphaInFloatRefColors 1 : alpha is different, update the alpha values " + alpha);
01728:
01729: float m = alpha / lastAlpha[screen];
01730:
01731: float[] cdata = mirrorFloatRefColors[screen];
01732:
01733: // We've to traverse the whole due to BugId : 4676483
01734: for (int i = 0, j = 0; i < vertexCount; i++, j += 4) {
01735: cdata[j + 3] = cdata[j + 3] * m;
01736: }
01737: }
01738: } else {
01739: // color data is modified
01740: if (screen == 0) {
01741:
01742: // just update alpha values since screen 0 data is
01743: // already updated in setupMirrorColorPointer
01744:
01745: //System.err.println("updateAlphaInFloatRefColors 2 : just update alpha = " + alpha);
01746:
01747: float[] cdata = mirrorFloatRefColors[screen];
01748:
01749: // This part is also incorrect due to BugId : 4676483
01750: // But traversing the whole array doesn't help either, as there
01751: // isn't a mechanism to indicate the the alpha component has
01752: // not changed by user.
01753: int j = initialColorIndex * 4;
01754: for (int i = initialColorIndex; i < validVertexCount; i++, j += 4) {
01755: cdata[j + 3] = cdata[j + 3] * alpha;
01756: }
01757: } else {
01758: // update color values from screen 0 data
01759: //System.err.println("updateAlphaInFloatRefColors 3 : update color values from screen 0 data " + alpha);
01760:
01761: float m;
01762:
01763: if ((colorChanged & 1) == 0) {
01764: // alpha is up to date in screen 0
01765: m = alpha / lastAlpha[0];
01766: } else {
01767: m = alpha;
01768: }
01769:
01770: float[] sdata = mirrorFloatRefColors[0];
01771: float[] cdata = mirrorFloatRefColors[screen];
01772:
01773: int j = initialColorIndex * 4;
01774: for (int i = initialColorIndex; i < validVertexCount; i++) {
01775: cdata[j] = sdata[j++];
01776: cdata[j] = sdata[j++];
01777: cdata[j] = sdata[j++];
01778: cdata[j] = sdata[j++] * m;
01779: }
01780: }
01781: }
01782:
01783: lastAlpha[screen] = alpha;
01784: colorChanged &= ~(1 << screen);
01785: dirtyFlag |= COLOR_CHANGED;
01786: return mirrorFloatRefColors[screen];
01787: }
01788:
01789: byte[] updateAlphaInByteRefColors(Canvas3D cv, int screen,
01790: float alpha) {
01791:
01792: /*
01793: System.err.println("updateAlphaInByteRefColors screen = " + screen +
01794: " alpha " + alpha );
01795: */
01796:
01797: // no need to update alpha values if canvas supports global alpha
01798: if (cv.supportGlobalAlpha()) {
01799: cv.setGlobalAlpha(cv.ctx, alpha);
01800: return mirrorUnsignedByteRefColors[0];
01801: }
01802:
01803: // update alpha only if vertex format includes alpha
01804: if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0)
01805: return mirrorUnsignedByteRefColors[0];
01806:
01807: // if alpha is smaller than EPSILON, set it to EPSILON, so that
01808: // even if alpha is equal to 0, we will not completely lose
01809: // the original alpha value
01810: if (alpha <= EPSILON) {
01811: alpha = (float) EPSILON;
01812: }
01813:
01814: assert lastAlpha != null;
01815: assert mirrorUnsignedByteRefColors != null;
01816: assert mirrorUnsignedByteRefColors.length == lastAlpha.length;
01817:
01818: // Issue 113 - reallocate lastAlpha array if needed, but no need to
01819: // update the values here
01820: if (lastAlpha.length <= screen) {
01821: float[] la = new float[screen + 1];
01822: for (int i = 0; i < lastAlpha.length; i++) {
01823: la[i] = lastAlpha[i];
01824: }
01825: lastAlpha = la;
01826: }
01827:
01828: // allocate a copy of the color data for the screen if needed.
01829: // this piece of code is only for multi-screens case
01830: if (mirrorUnsignedByteRefColors.length <= screen) {
01831: byte[][] cbData = new byte[screen + 1][];
01832: for (int i = 0; i < mirrorUnsignedByteRefColors.length; i++) {
01833: cbData[i] = mirrorUnsignedByteRefColors[i];
01834: }
01835:
01836: // Issue 113 - allocate entries for [oldSize..screen];
01837: // copy cbData[0] to cbData[oldsize..screen-1] and
01838: // lastAlpha[0] to lastAlpha[oldsize..screen-1].
01839: for (int i = mirrorUnsignedByteRefColors.length; i < screen + 1; i++) {
01840: cbData[i] = new byte[4 * vertexCount];
01841: System.arraycopy(cbData[0], 0, cbData[i], 0,
01842: 4 * vertexCount);
01843: lastAlpha[i] = lastAlpha[0];
01844: }
01845:
01846: mirrorUnsignedByteRefColors = cbData;
01847:
01848: // Issue 113 - since we copied the data from screen 0, we don't need
01849: // to do any further special processing.
01850: }
01851:
01852: assert lastAlpha[screen] >= 0.0;
01853: /*
01854: System.err.println("updateAlphaInByteRefColors ## : lastAlpha[screen] " +
01855: lastAlpha[screen]);
01856:
01857: System.err.println("((colorChanged & (1<<screen)) == 0) " +
01858: ((colorChanged & (1<<screen)) == 0));
01859: */
01860:
01861: if ((colorChanged & (1 << screen)) == 0) {
01862: // color data is not modified
01863: if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
01864: // and if alpha is the same as the last one,
01865: // just return the data
01866: //System.err.println("updateAlphaInByteRefColors 0 : alpha is the same as the last one " + alpha);
01867:
01868: return mirrorUnsignedByteRefColors[screen];
01869: } else {
01870: // if alpha is different, update the alpha values
01871:
01872: //System.err.println("updateAlphaInByteRefColors 1 : alpha is different, update the alpha values " + alpha);
01873:
01874: float m = alpha / lastAlpha[screen];
01875:
01876: byte[] cdata = mirrorUnsignedByteRefColors[screen];
01877:
01878: // We've to traverse the whole due to BugId : 4676483
01879: for (int i = 0, j = 0; i < vertexCount; i++, j += 4) {
01880: cdata[j + 3] = (byte) (((int) cdata[j + 3] & 0xff) * m);
01881: }
01882: }
01883: } else {
01884: // color data is modified
01885: if (screen == 0) {
01886: //System.err.println("updateAlphaInByteRefColors 2 : just update alpha =" + alpha);
01887:
01888: // just update alpha values since screen 0 data is
01889: // already updated in setupMirrorColorPointer
01890:
01891: byte[] cdata = mirrorUnsignedByteRefColors[screen];
01892:
01893: // This part is also incorrect due to BugId : 4676483
01894: // But traversing the whole array doesn't help either, as there
01895: // isn't a mechanism to indicate the the alpha component has
01896: // not changed by user.
01897: int j = initialColorIndex * 4;
01898: for (int i = initialColorIndex; i < validVertexCount; i++, j += 4) {
01899: cdata[j + 3] = (byte) (((int) cdata[j + 3] & 0xff) * alpha);
01900: }
01901: } else {
01902: // update color values from screen 0 data
01903: float m;
01904:
01905: //System.err.println("updateAlphaInByteRefColors 3 : update color values from screen 0 data " + alpha);
01906:
01907: if ((colorChanged & 1) == 0) {
01908: // alpha is up to date in screen 0
01909: m = alpha / lastAlpha[0];
01910: } else {
01911: m = alpha;
01912: }
01913: byte[] sdata = mirrorUnsignedByteRefColors[0];
01914: byte[] cdata = mirrorUnsignedByteRefColors[screen];
01915:
01916: int j = initialColorIndex * 4;
01917: for (int i = initialColorIndex; i < validVertexCount; i++) {
01918: cdata[j] = sdata[j++];
01919: cdata[j] = sdata[j++];
01920: cdata[j] = sdata[j++];
01921: cdata[j] = (byte) (((int) sdata[j++] & 0xff) * m);
01922: }
01923: }
01924: }
01925:
01926: lastAlpha[screen] = alpha;
01927: colorChanged &= ~(1 << screen);
01928: dirtyFlag |= COLOR_CHANGED;
01929: return mirrorUnsignedByteRefColors[screen];
01930: }
01931:
01932: Object[] updateAlphaInVertexData(Canvas3D cv, int screen,
01933: float alpha) {
01934:
01935: Object[] retVal = new Object[2];
01936: retVal[0] = Boolean.FALSE;
01937:
01938: // no need to update alpha values if canvas supports global alpha
01939: if (cv.supportGlobalAlpha()) {
01940: cv.setGlobalAlpha(cv.ctx, alpha);
01941: retVal[1] = vertexData;
01942: return retVal;
01943: }
01944:
01945: // update alpha only if vertex format includes alpha
01946: if ((vertexFormat & GeometryArray.COLOR) == 0) {
01947: retVal[1] = vertexData;
01948: return retVal;
01949: }
01950:
01951: // if alpha is smaller than EPSILON, set it to EPSILON, so that
01952: // even if alpha is equal to 0, we will not completely lose
01953: // the original alpha value
01954: if (alpha <= EPSILON) {
01955: alpha = (float) EPSILON;
01956: }
01957: retVal[0] = Boolean.TRUE;
01958:
01959: assert lastAlpha != null;
01960: assert mvertexData == null
01961: || mvertexData.length == lastAlpha.length;
01962:
01963: // Issue 113 - reallocate lastAlpha array if needed, but no need to
01964: // update the values here
01965: if (lastAlpha.length <= screen) {
01966: float[] la = new float[screen + 1];
01967: for (int i = 0; i < lastAlpha.length; i++) {
01968: la[i] = lastAlpha[i];
01969: }
01970: lastAlpha = la;
01971: }
01972:
01973: // allocate a copy of the vertex data for the screen if needed.
01974: // Note that a copy operation only happens in the multi-screens case.
01975: // We always use the existing vertexData for screen 0.
01976: if (mvertexData == null || mvertexData.length <= screen) {
01977:
01978: float[][] cfData = new float[screen + 1][];
01979: int oldSize = 1;
01980:
01981: if (mvertexData != null) {
01982: oldSize = mvertexData.length;
01983: for (int i = 0; i < mvertexData.length; i++) {
01984: cfData[i] = mvertexData[i];
01985: }
01986: }
01987:
01988: if (cfData[0] == null) {
01989: cfData[0] = vertexData;
01990: }
01991:
01992: // Issue 113 - allocate entries for [oldSize..screen];
01993: // copy cfData[0] to cfData[oldsize..screen-1] and
01994: // lastAlpha[0] to lastAlpha[oldsize..screen-1].
01995: if (screen > 0) {
01996: for (int i = oldSize; i < screen + 1; i++) {
01997: cfData[i] = new float[stride * vertexCount];
01998: System.arraycopy(cfData[0], 0, cfData[i], 0, stride
01999: * vertexCount);
02000: lastAlpha[i] = lastAlpha[0];
02001: }
02002: }
02003:
02004: mvertexData = cfData;
02005:
02006: // Issue 113 - since we copied the data from screen 0, we don't need
02007: // to do any further special processing.
02008: }
02009:
02010: assert lastAlpha[screen] >= 0.0;
02011:
02012: if ((colorChanged & (1 << screen)) == 0) {
02013: // color data is not modified
02014: if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
02015: // and if alpha is the same as the last one,
02016: // just return the data
02017: retVal[1] = mvertexData[screen];
02018: return retVal;
02019: } else {
02020: // if alpha is different, update the alpha values
02021: float m = alpha / lastAlpha[screen];
02022:
02023: float[] cdata = mvertexData[screen];
02024: for (int i = 0, j = colorOffset; i < vertexCount; i++, j += stride) {
02025: cdata[j + 3] *= m;
02026: }
02027: }
02028: } else {
02029: // color data is modified
02030: if (screen == 0) {
02031: // just update alpha values since screen 0 data is
02032: // already updated in setupMirrorColorPointer
02033:
02034: float[] cdata = mvertexData[screen];
02035: double m = alpha / lastAlpha[0];
02036:
02037: for (int i = 0, j = colorOffset; i < vertexCount; i++, j += stride) {
02038: cdata[j + 3] *= m;
02039: }
02040: } else {
02041: // update color values from screen 0 data
02042:
02043: float m = alpha / lastAlpha[0];
02044: float[] sdata = mvertexData[0];
02045: float[] cdata = mvertexData[screen];
02046:
02047: for (int i = 0, j = colorOffset; i < vertexCount; i++, j += stride) {
02048: System.arraycopy(sdata, j, cdata, j, 3);
02049: cdata[j + 3] = sdata[j + 3] * m;
02050: }
02051: }
02052: }
02053:
02054: lastAlpha[screen] = alpha;
02055: colorChanged &= ~(1 << screen);
02056: dirtyFlag |= COLOR_CHANGED;
02057: retVal[1] = mvertexData[screen];
02058: return retVal;
02059: }
02060:
02061: Object[] updateAlphaInInterLeavedData(Canvas3D cv, int screen,
02062: float alpha) {
02063:
02064: Object[] retVal = new Object[2];
02065: retVal[0] = Boolean.FALSE;
02066:
02067: // no need to update alpha values if canvas supports global alpha
02068: if (cv.supportGlobalAlpha()) {
02069: cv.setGlobalAlpha(cv.ctx, alpha);
02070: retVal[1] = null;
02071: return retVal;
02072: }
02073:
02074: // update alpha only if vertex format includes alpha
02075: if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0) {
02076: retVal[1] = mirrorInterleavedColorPointer[0];
02077: return retVal;
02078: }
02079: int coffset = initialColorIndex << 2; // Each color is 4 floats
02080:
02081: // if alpha is smaller than EPSILON, set it to EPSILON, so that
02082: // even if alpha is equal to 0, we will not completely lose
02083: // the original alpha value
02084: if (alpha <= EPSILON) {
02085: alpha = (float) EPSILON;
02086: }
02087: retVal[0] = Boolean.TRUE;
02088:
02089: assert lastAlpha != null;
02090: assert mirrorInterleavedColorPointer != null;
02091: assert mirrorInterleavedColorPointer.length == lastAlpha.length;
02092:
02093: // Issue 113 - reallocate lastAlpha array if needed, but no need to
02094: // update the values here
02095: if (lastAlpha.length <= screen) {
02096: float[] la = new float[screen + 1];
02097: for (int i = 0; i < lastAlpha.length; i++) {
02098: la[i] = lastAlpha[i];
02099: }
02100: lastAlpha = la;
02101: }
02102:
02103: // allocate a copy of the vertex data for the screen if needed.
02104: // this piece of code is only for multi-screens case
02105: if (mirrorInterleavedColorPointer.length <= screen) {
02106:
02107: float[][] cfData = new float[screen + 1][];
02108:
02109: for (int i = 0; i < mirrorInterleavedColorPointer.length; i++) {
02110: cfData[i] = mirrorInterleavedColorPointer[i];
02111: }
02112:
02113: // Issue 113 - allocate entries for [oldSize..screen];
02114: // copy cfData[0] to cfData[oldsize..screen-1] and
02115: // lastAlpha[0] to lastAlpha[oldsize..screen-1].
02116: for (int i = mirrorInterleavedColorPointer.length; i < screen + 1; i++) {
02117: cfData[i] = new float[4 * vertexCount];
02118: System.arraycopy(cfData[0], 0, cfData[i], 0,
02119: 4 * vertexCount);
02120: lastAlpha[i] = lastAlpha[0];
02121: }
02122:
02123: mirrorInterleavedColorPointer = cfData;
02124:
02125: // Issue 113 - since we copied the data from screen 0, we don't need
02126: // to do any further special processing.
02127: }
02128:
02129: assert lastAlpha[screen] >= 0.0;
02130:
02131: if ((colorChanged & (1 << screen)) == 0) {
02132: // color data is not modified
02133: if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
02134: // and if alpha is the same as the last one,
02135: // just return the data
02136: retVal[1] = mirrorInterleavedColorPointer[screen];
02137: return retVal;
02138: } else {
02139:
02140: // if alpha is different, update the alpha values
02141:
02142: float m = alpha / lastAlpha[screen];
02143:
02144: float[] cdata = mirrorInterleavedColorPointer[screen];
02145:
02146: coffset = initialColorIndex << 2;
02147: for (int i = coffset; i < coffset + (vertexCount << 2); i += 4) {
02148: cdata[i + 3] = cdata[i + 3] * m;
02149: }
02150: }
02151: } else {
02152: // color data is modified
02153: if (screen == 0) {
02154:
02155: // just update alpha values since screen 0 data is
02156: // already updated in setupMirrorInterleavedColorPointer
02157:
02158: float[] cdata = mirrorInterleavedColorPointer[screen];
02159:
02160: for (int i = coffset; i < coffset + (vertexCount << 2); i += 4) {
02161: cdata[i + 3] = cdata[i + 3] * alpha;
02162: }
02163: } else {
02164: // update color values from screen 0 data
02165:
02166: float m;
02167:
02168: if ((colorChanged & 1) == 0) {
02169: // alpha is up to date in screen 0
02170: m = alpha / lastAlpha[0];
02171: } else {
02172: m = alpha;
02173: }
02174:
02175: float[] sdata = mirrorInterleavedColorPointer[0];
02176: float[] cdata = mirrorInterleavedColorPointer[screen];
02177:
02178: for (int i = coffset; i < coffset + (vertexCount << 2);) {
02179: // System.arraycopy(sdata, i, cdata, i, 3);
02180: cdata[i] = sdata[i++];
02181: cdata[i] = sdata[i++];
02182: cdata[i] = sdata[i++];
02183: cdata[i] = sdata[i++] * m;
02184: }
02185: }
02186: }
02187:
02188: lastAlpha[screen] = alpha;
02189: colorChanged &= ~(1 << screen);
02190: dirtyFlag |= COLOR_CHANGED;
02191: retVal[1] = mirrorInterleavedColorPointer[screen];
02192: return retVal;
02193: }
02194:
02195: // pass < 0 implies underlying library supports multiTexture, so
02196: // use the multiTexture extension to send all texture units
02197: // data in one pass
02198: // pass >= 0 implies one pass for one texture unit state
02199:
02200: void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
02201: boolean updateAlpha, float alpha, int screen,
02202: boolean ignoreVertexColors) {
02203:
02204: int cdirty;
02205: boolean useAlpha = false;
02206: Object[] retVal;
02207:
02208: // Check for by-copy case
02209: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
02210: float[] vdata;
02211:
02212: synchronized (this ) {
02213: cdirty = dirtyFlag;
02214: if (updateAlpha && !ignoreVertexColors) {
02215: // update the alpha values
02216: retVal = updateAlphaInVertexData(cv, screen, alpha);
02217: useAlpha = (retVal[0] == Boolean.TRUE);
02218: vdata = (float[]) retVal[1];
02219:
02220: // D3D only
02221: if (alpha != lastScreenAlpha) {
02222: // handle multiple screen case
02223: lastScreenAlpha = alpha;
02224: cdirty |= COLOR_CHANGED;
02225: }
02226: } else {
02227: vdata = vertexData;
02228: // if transparency switch between on/off
02229: if (lastScreenAlpha != -1) {
02230: lastScreenAlpha = -1;
02231: cdirty |= COLOR_CHANGED;
02232: }
02233: }
02234: // geomLock is get in MasterControl when
02235: // RenderBin render the geometry. So it is safe
02236: // just to set the dirty flag here
02237: dirtyFlag = 0;
02238: }
02239:
02240: Pipeline
02241: .getPipeline()
02242: .execute(
02243: cv.ctx,
02244: this ,
02245: geoType,
02246: isNonUniformScale,
02247: useAlpha,
02248: ignoreVertexColors,
02249: initialVertexIndex,
02250: validVertexCount,
02251: ((vertexFormat & GeometryArray.COLOR) != 0) ? (vertexFormat | GeometryArray.COLOR_4)
02252: : vertexFormat,
02253: texCoordSetCount,
02254: texCoordSetMap,
02255: (texCoordSetMap == null) ? 0
02256: : texCoordSetMap.length,
02257: texCoordSetMapOffset, cv.numActiveTexUnit,
02258: vertexAttrCount, vertexAttrSizes, vdata,
02259: null, cdirty);
02260: }
02261:
02262: //By reference with java array
02263: else if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
02264: // interleaved data
02265: if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
02266: if (interLeavedVertexData == null)
02267: return;
02268:
02269: float[] cdata = null;
02270:
02271: synchronized (this ) {
02272: cdirty = dirtyFlag;
02273: if (updateAlpha && !ignoreVertexColors) {
02274: // update the alpha values
02275: retVal = updateAlphaInInterLeavedData(cv,
02276: screen, alpha);
02277: useAlpha = (retVal[0] == Boolean.TRUE);
02278: cdata = (float[]) retVal[1];
02279: if (alpha != lastScreenAlpha) {
02280: lastScreenAlpha = alpha;
02281: cdirty |= COLOR_CHANGED;
02282: }
02283: } else {
02284: // if transparency switch between on/off
02285: if (lastScreenAlpha != -1) {
02286: lastScreenAlpha = -1;
02287: cdirty |= COLOR_CHANGED;
02288: }
02289: }
02290: dirtyFlag = 0;
02291: }
02292:
02293: Pipeline.getPipeline().execute(
02294: cv.ctx,
02295: this ,
02296: geoType,
02297: isNonUniformScale,
02298: useAlpha,
02299: ignoreVertexColors,
02300: initialVertexIndex,
02301: validVertexCount,
02302: vertexFormat,
02303: texCoordSetCount,
02304: texCoordSetMap,
02305: (texCoordSetMap == null) ? 0
02306: : texCoordSetMap.length,
02307: texCoordSetMapOffset, cv.numActiveTexUnit,
02308: vertexAttrCount, vertexAttrSizes,
02309: interLeavedVertexData, cdata, cdirty);
02310:
02311: } // end of interleaved case
02312:
02313: // non interleaved data
02314: else {
02315:
02316: // Check if a vertexformat is set, but the array is null
02317: // if yes, don't draw anything
02318: if ((vertexType == 0)
02319: || ((vertexType & VERTEX_DEFINED) == 0)
02320: || (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0)
02321: || (((vertexFormat & GeometryArray.NORMALS) != 0) && (vertexType & NORMAL_DEFINED) == 0)
02322: || (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && (vertexType & VATTR_DEFINED) == 0)
02323: || (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) {
02324: return;
02325: } else {
02326: byte[] cbdata = null;
02327: float[] cfdata = null;
02328:
02329: if ((vertexType & (CF | C3F | C4F)) != 0) {
02330:
02331: synchronized (this ) {
02332: cdirty = dirtyFlag;
02333: if (updateAlpha && !ignoreVertexColors) {
02334: cfdata = updateAlphaInFloatRefColors(
02335: cv, screen, alpha);
02336: if (alpha != lastScreenAlpha) {
02337: lastScreenAlpha = alpha;
02338: cdirty |= COLOR_CHANGED;
02339: }
02340: } else {
02341: cfdata = mirrorFloatRefColors[0];
02342: // if transparency switch between on/off
02343: if (lastScreenAlpha != -1) {
02344: lastScreenAlpha = -1;
02345: cdirty |= COLOR_CHANGED;
02346: }
02347:
02348: }
02349: dirtyFlag = 0;
02350: }
02351: } // end of color in float format
02352: else if ((vertexType & (CUB | C3UB | C4UB)) != 0) {
02353: synchronized (this ) {
02354: cdirty = dirtyFlag;
02355: if (updateAlpha && !ignoreVertexColors) {
02356: cbdata = updateAlphaInByteRefColors(cv,
02357: screen, alpha);
02358: if (alpha != lastScreenAlpha) {
02359: lastScreenAlpha = alpha;
02360: cdirty |= COLOR_CHANGED;
02361: }
02362: } else {
02363: cbdata = mirrorUnsignedByteRefColors[0];
02364: // if transparency switch between on/off
02365: if (lastScreenAlpha != -1) {
02366: lastScreenAlpha = -1;
02367: cdirty |= COLOR_CHANGED;
02368: }
02369: }
02370: dirtyFlag = 0;
02371: }
02372: } // end of color in byte format
02373: else {
02374: cdirty = dirtyFlag;
02375: }
02376: // setup vdefined to passed to native code
02377: int vdefined = 0;
02378: if ((vertexType & (PF | P3F)) != 0)
02379: vdefined |= COORD_FLOAT;
02380: if ((vertexType & (PD | P3D)) != 0)
02381: vdefined |= COORD_DOUBLE;
02382: if ((vertexType & (CF | C3F | C4F)) != 0)
02383: vdefined |= COLOR_FLOAT;
02384: if ((vertexType & (CUB | C3UB | C4UB)) != 0)
02385: vdefined |= COLOR_BYTE;
02386: if ((vertexType & NORMAL_DEFINED) != 0)
02387: vdefined |= NORMAL_FLOAT;
02388: if ((vertexType & VATTR_DEFINED) != 0)
02389: vdefined |= VATTR_FLOAT;
02390: if ((vertexType & TEXCOORD_DEFINED) != 0)
02391: vdefined |= TEXCOORD_FLOAT;
02392:
02393: Pipeline.getPipeline().executeVA(
02394: cv.ctx,
02395: this ,
02396: geoType,
02397: isNonUniformScale,
02398: ignoreVertexColors,
02399: validVertexCount,
02400: (vertexFormat | c4fAllocated),
02401: vdefined,
02402: initialCoordIndex,
02403: mirrorFloatRefCoords,
02404: mirrorDoubleRefCoords,
02405: initialColorIndex,
02406: cfdata,
02407: cbdata,
02408: initialNormalIndex,
02409: mirrorFloatRefNormals,
02410: vertexAttrCount,
02411: vertexAttrSizes,
02412: initialVertexAttrIndex,
02413: mirrorFloatRefVertexAttrs,
02414: ((texCoordSetMap == null) ? 0
02415: : texCoordSetMap.length),
02416: texCoordSetMap, cv.numActiveTexUnit,
02417: initialTexCoordIndex, texCoordStride,
02418: mirrorRefTexCoords, cdirty);
02419: }// end of all vertex data being set
02420: }// end of non interleaved case
02421: }// end of by reference with java array
02422:
02423: //By reference with nio buffer
02424: else {
02425: // interleaved data
02426: if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
02427:
02428: if (interleavedFloatBufferImpl == null)
02429: return;
02430:
02431: float[] cdata = null;
02432: synchronized (this ) {
02433: cdirty = dirtyFlag;
02434: if (updateAlpha && !ignoreVertexColors) {
02435: // update the alpha values
02436: // XXXX: to handle alpha case
02437: retVal = updateAlphaInInterLeavedData(cv,
02438: screen, alpha);
02439: useAlpha = (retVal[0] == Boolean.TRUE);
02440: cdata = (float[]) retVal[1];
02441:
02442: if (alpha != lastScreenAlpha) {
02443: lastScreenAlpha = alpha;
02444: cdirty |= COLOR_CHANGED;
02445: }
02446: } else {
02447: // XXXX: to handle alpha case
02448: cdata = null;
02449: // if transparency switch between on/off
02450: if (lastScreenAlpha != -1) {
02451: lastScreenAlpha = -1;
02452: cdirty |= COLOR_CHANGED;
02453: }
02454: }
02455: dirtyFlag = 0;
02456: }
02457:
02458: Pipeline.getPipeline().executeInterleavedBuffer(
02459: cv.ctx,
02460: this ,
02461: geoType,
02462: isNonUniformScale,
02463: useAlpha,
02464: ignoreVertexColors,
02465: initialVertexIndex,
02466: validVertexCount,
02467: vertexFormat,
02468: texCoordSetCount,
02469: texCoordSetMap,
02470: (texCoordSetMap == null) ? 0
02471: : texCoordSetMap.length,
02472: texCoordSetMapOffset, cv.numActiveTexUnit,
02473: interleavedFloatBufferImpl.getBufferAsObject(),
02474: cdata, cdirty);
02475:
02476: } // end of interleaved case
02477:
02478: // non interleaved data
02479: else {
02480:
02481: // Check if a vertexformat is set, but the array is null
02482: // if yes, don't draw anything
02483: if ((vertexType == 0)
02484: || ((vertexType & VERTEX_DEFINED) == 0)
02485: || (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0)
02486: || (((vertexFormat & GeometryArray.NORMALS) != 0) && (vertexType & NORMAL_DEFINED) == 0)
02487: || (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && (vertexType & VATTR_DEFINED) == 0)
02488: || (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) {
02489: return;
02490: } else {
02491: byte[] cbdata = null;
02492: float[] cfdata = null;
02493:
02494: if ((vertexType & CF) != 0) {
02495: synchronized (this ) {
02496: cdirty = dirtyFlag;
02497: if (updateAlpha && !ignoreVertexColors) {
02498: cfdata = updateAlphaInFloatRefColors(
02499: cv, screen, alpha);
02500: if (alpha != lastScreenAlpha) {
02501: lastScreenAlpha = alpha;
02502: cdirty |= COLOR_CHANGED;
02503: }
02504: } else {
02505: // XXXX: handle transparency case
02506: //cfdata = null;
02507: cfdata = mirrorFloatRefColors[0];
02508: // if transparency switch between on/off
02509: if (lastScreenAlpha != -1) {
02510: lastScreenAlpha = -1;
02511: cdirty |= COLOR_CHANGED;
02512: }
02513:
02514: }
02515: dirtyFlag = 0;
02516: }
02517: } // end of color in float format
02518: else if ((vertexType & CUB) != 0) {
02519: synchronized (this ) {
02520: cdirty = dirtyFlag;
02521: if (updateAlpha && !ignoreVertexColors) {
02522: cbdata = updateAlphaInByteRefColors(cv,
02523: screen, alpha);
02524: if (alpha != lastScreenAlpha) {
02525: lastScreenAlpha = alpha;
02526: cdirty |= COLOR_CHANGED;
02527: }
02528: } else {
02529: // XXXX: handle transparency case
02530: //cbdata = null;
02531: cbdata = mirrorUnsignedByteRefColors[0];
02532: // if transparency switch between on/off
02533: if (lastScreenAlpha != -1) {
02534: lastScreenAlpha = -1;
02535: cdirty |= COLOR_CHANGED;
02536: }
02537: }
02538: dirtyFlag = 0;
02539: }
02540: } // end of color in byte format
02541: else {
02542: cdirty = dirtyFlag;
02543: }
02544:
02545: Object vcoord = null, cdataBuffer = null, normal = null;
02546:
02547: int vdefined = 0;
02548: if ((vertexType & PF) != 0) {
02549: vdefined |= COORD_FLOAT;
02550: vcoord = floatBufferRefCoords
02551: .getBufferAsObject();
02552: } else if ((vertexType & PD) != 0) {
02553: vdefined |= COORD_DOUBLE;
02554: vcoord = doubleBufferRefCoords
02555: .getBufferAsObject();
02556: }
02557:
02558: if ((vertexType & CF) != 0) {
02559: vdefined |= COLOR_FLOAT;
02560: cdataBuffer = floatBufferRefColors
02561: .getBufferAsObject();
02562: } else if ((vertexType & CUB) != 0) {
02563: vdefined |= COLOR_BYTE;
02564: cdataBuffer = byteBufferRefColors
02565: .getBufferAsObject();
02566: }
02567:
02568: if ((vertexType & NORMAL_DEFINED) != 0) {
02569: vdefined |= NORMAL_FLOAT;
02570: normal = floatBufferRefNormals
02571: .getBufferAsObject();
02572: }
02573:
02574: if ((vertexType & VATTR_DEFINED) != 0) {
02575: vdefined |= VATTR_FLOAT;
02576: }
02577:
02578: if ((vertexType & TEXCOORD_DEFINED) != 0)
02579: vdefined |= TEXCOORD_FLOAT;
02580:
02581: Pipeline.getPipeline().executeVABuffer(
02582: cv.ctx,
02583: this ,
02584: geoType,
02585: isNonUniformScale,
02586: ignoreVertexColors,
02587: validVertexCount,
02588: (vertexFormat | c4fAllocated),
02589: vdefined,
02590: initialCoordIndex,
02591: vcoord,
02592: initialColorIndex,
02593: cdataBuffer,
02594: cfdata,
02595: cbdata,
02596: initialNormalIndex,
02597: normal,
02598: vertexAttrCount,
02599: vertexAttrSizes,
02600: initialVertexAttrIndex,
02601: nioFloatBufferRefVertexAttrs,
02602: ((texCoordSetMap == null) ? 0
02603: : texCoordSetMap.length),
02604: texCoordSetMap, cv.numActiveTexUnit,
02605: initialTexCoordIndex, texCoordStride,
02606: refTexCoords, cdirty);
02607: }// end of all vertex data being set
02608: }// end of non interleaved case
02609: }// end of by reference with nio-buffer case
02610: }
02611:
02612: void buildGA(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
02613: boolean updateAlpha, float alpha,
02614: boolean ignoreVertexColors, Transform3D xform,
02615: Transform3D nxform) {
02616:
02617: float[] vdata = null;
02618:
02619: // NIO buffers are no longer supported in display lists
02620: assert (vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0;
02621:
02622: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
02623: vdata = vertexData;
02624: } else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0
02625: && ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0)) {
02626: vdata = interLeavedVertexData;
02627: }
02628: if (vdata != null) {
02629: /*
02630: System.err.println("calling native buildGA()");
02631: System.err.println("geoType = "+geoType+" initialVertexIndex = "+initialVertexIndex+" validVertexCount = "+validVertexCount+" vertexFormat = "+vertexFormat+" vertexData = "+vertexData);
02632: */
02633: Pipeline.getPipeline().buildGA(
02634: cv.ctx,
02635: this ,
02636: geoType,
02637: isNonUniformScale,
02638: updateAlpha,
02639: alpha,
02640: ignoreVertexColors,
02641: initialVertexIndex,
02642: validVertexCount,
02643: vertexFormat,
02644: texCoordSetCount,
02645: texCoordSetMap,
02646: (texCoordSetMap == null) ? 0
02647: : texCoordSetMap.length,
02648: texCoordSetMapOffset, vertexAttrCount,
02649: vertexAttrSizes,
02650: (xform == null) ? null : xform.mat,
02651: (nxform == null) ? null : nxform.mat, vdata);
02652: } else {
02653: // Check if a vertexformat is set, but the array is null
02654: // if yes, don't draw anything
02655: if ((vertexType == 0)
02656: || ((vertexType & VERTEX_DEFINED) == 0)
02657: || (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0)
02658: || (((vertexFormat & GeometryArray.NORMALS) != 0) && (vertexType & NORMAL_DEFINED) == 0)
02659: || (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && (vertexType & VATTR_DEFINED) == 0)
02660: || (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) {
02661:
02662: return;
02663: }
02664:
02665: // Either non-interleaved, by-ref or nio buffer
02666: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
02667: // Java array case
02668: // setup vdefined to passed to native code
02669: int vdefined = 0;
02670: if ((vertexType & (PF | P3F)) != 0)
02671: vdefined |= COORD_FLOAT;
02672: if ((vertexType & (PD | P3D)) != 0)
02673: vdefined |= COORD_DOUBLE;
02674: if ((vertexType & (CF | C3F | C4F)) != 0)
02675: vdefined |= COLOR_FLOAT;
02676: if ((vertexType & (CUB | C3UB | C4UB)) != 0)
02677: vdefined |= COLOR_BYTE;
02678: if ((vertexType & NORMAL_DEFINED) != 0)
02679: vdefined |= NORMAL_FLOAT;
02680: if ((vertexType & VATTR_DEFINED) != 0)
02681: vdefined |= VATTR_FLOAT;
02682: if ((vertexType & TEXCOORD_DEFINED) != 0)
02683: vdefined |= TEXCOORD_FLOAT;
02684:
02685: Pipeline.getPipeline().buildGAForByRef(
02686: cv.ctx,
02687: this ,
02688: geoType,
02689: isNonUniformScale,
02690: updateAlpha,
02691: alpha,
02692: ignoreVertexColors,
02693: validVertexCount,
02694: vertexFormat,
02695: vdefined,
02696: initialCoordIndex,
02697: mirrorFloatRefCoords,
02698: mirrorDoubleRefCoords,
02699: initialColorIndex,
02700: mirrorFloatRefColors[0],
02701: mirrorUnsignedByteRefColors[0],
02702: initialNormalIndex,
02703: mirrorFloatRefNormals,
02704: vertexAttrCount,
02705: vertexAttrSizes,
02706: initialVertexAttrIndex,
02707: mirrorFloatRefVertexAttrs,
02708: ((texCoordSetMap == null) ? 0
02709: : texCoordSetMap.length),
02710: texCoordSetMap, initialTexCoordIndex,
02711: texCoordStride, mirrorRefTexCoords,
02712: (xform == null) ? null : xform.mat,
02713: (nxform == null) ? null : nxform.mat);
02714: }
02715: /*
02716: // NOTE: NIO buffers are no longer supported in display lists.
02717: // This was never enabled by default anyway (only when the
02718: // optimizeForSpace property was set to false), so it wasn't
02719: // well-tested. If future support is desired, we will need to
02720: // add vertex attributes to buildGAForBuffer. There are no plans
02721: // to ever do this.
02722: else {
02723: // NIO Buffer case
02724: Object vcoord = null, cdataBuffer=null, normal=null;
02725:
02726: int vdefined = 0;
02727: if((vertexType & PF) != 0) {
02728: vdefined |= COORD_FLOAT;
02729: vcoord = floatBufferRefCoords.getBufferAsObject();
02730: } else if((vertexType & PD ) != 0) {
02731: vdefined |= COORD_DOUBLE;
02732: vcoord = doubleBufferRefCoords.getBufferAsObject();
02733: }
02734:
02735: if((vertexType & CF ) != 0) {
02736: vdefined |= COLOR_FLOAT;
02737: cdataBuffer = floatBufferRefColors.getBufferAsObject();
02738: } else if((vertexType & CUB) != 0) {
02739: vdefined |= COLOR_BYTE;
02740: cdataBuffer = byteBufferRefColors.getBufferAsObject();
02741: }
02742:
02743: if((vertexType & NORMAL_DEFINED) != 0) {
02744: vdefined |= NORMAL_FLOAT;
02745: normal = floatBufferRefNormals.getBufferAsObject();
02746: }
02747:
02748: if((vertexType & TEXCOORD_DEFINED) != 0)
02749: vdefined |= TEXCOORD_FLOAT;
02750: // NOTE : need to add vertex attrs
02751: Pipeline.getPipeline().buildGAForBuffer(cv.ctx,
02752: this, geoType, isNonUniformScale,
02753: updateAlpha, alpha,
02754: ignoreVertexColors,
02755: validVertexCount,
02756: vertexFormat,
02757: vdefined,
02758: initialCoordIndex,
02759: vcoord,
02760: initialColorIndex,cdataBuffer,
02761: initialNormalIndex, normal,
02762: ((texCoordSetMap == null) ? 0:texCoordSetMap.length),
02763: texCoordSetMap,
02764: initialTexCoordIndex,texCoordStride,
02765: refTexCoords,
02766: (xform == null) ? null : xform.mat,
02767: (nxform == null) ? null : nxform.mat);
02768: }
02769: */
02770:
02771: }
02772:
02773: }
02774:
02775: void unIndexify(IndexedGeometryArrayRetained src) {
02776: if ((src.vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
02777: unIndexifyJavaArray(src);
02778: } else {
02779: unIndexifyNIOBuffer(src);
02780: }
02781: }
02782:
02783: private void unIndexifyJavaArray(IndexedGeometryArrayRetained src) {
02784: // System.err.println("unIndexifyJavaArray");
02785:
02786: int vOffset = 0, srcOffset, tOffset = 0;
02787: int index, colorStride = 0;
02788: float[] vdata = null;
02789: int i;
02790: int start, end;
02791: start = src.initialIndexIndex;
02792: end = src.initialIndexIndex + src.validIndexCount;
02793: // If its either "normal" data or interleaved data then ..
02794: if (((src.vertexFormat & GeometryArray.BY_REFERENCE) == 0)
02795: || ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
02796:
02797: if ((src.vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
02798: vdata = src.vertexData;
02799: if ((src.vertexFormat & GeometryArray.COLOR) != 0)
02800: colorStride = 4;
02801: } else if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
02802: vdata = src.interLeavedVertexData;
02803: if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
02804: colorStride = 4;
02805: else if ((src.vertexFormat & GeometryArray.COLOR) != 0)
02806: colorStride = 3;
02807: }
02808:
02809: // System.err.println("===> start = "+start+" end = "+end);
02810: for (index = start; index < end; index++) {
02811: if ((vertexFormat & GeometryArray.NORMALS) != 0) {
02812: System.arraycopy(vdata, src.indexNormal[index]
02813: * src.stride + src.normalOffset,
02814: vertexData, vOffset + normalOffset, 3);
02815: }
02816: if (colorStride == 4) {
02817: // System.err.println("===> copying color3");
02818: System.arraycopy(vdata, src.indexColor[index]
02819: * src.stride + src.colorOffset, vertexData,
02820: vOffset + colorOffset, colorStride);
02821: } else if (colorStride == 3) {
02822: // System.err.println("===> copying color4");
02823: System.arraycopy(vdata, src.indexColor[index]
02824: * src.stride + src.colorOffset, vertexData,
02825: vOffset + colorOffset, colorStride);
02826: vertexData[vOffset + colorOffset + 3] = 1.0f;
02827: }
02828:
02829: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
02830: int tcOffset = vOffset + textureOffset;
02831: int interleavedOffset = 0;
02832:
02833: for (i = 0; i < texCoordSetCount; i++, tcOffset += texCoordStride) {
02834:
02835: if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
02836: interleavedOffset = i * texCoordStride;
02837: }
02838:
02839: System.arraycopy(vdata,
02840: (src.indexTexCoord[i][index])
02841: * src.stride
02842: + src.textureOffset
02843: + interleavedOffset,
02844: vertexData, tcOffset, texCoordStride);
02845: }
02846: }
02847:
02848: if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
02849: // vertex attributes can't be interleaved
02850: assert (src.vertexFormat & GeometryArray.INTERLEAVED) == 0;
02851:
02852: for (i = 0; i < vertexAttrCount; i++) {
02853: int vaOffset = vOffset + vertexAttrOffsets[i];
02854:
02855: System.arraycopy(vdata,
02856: (src.indexVertexAttr[i][index])
02857: * src.stride
02858: + src.vertexAttrOffsets[i],
02859: vertexData, vaOffset,
02860: vertexAttrSizes[i]);
02861: }
02862: }
02863:
02864: if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
02865: // System.err.println("===> copying coords");
02866: System.arraycopy(vdata, src.indexCoord[index]
02867: * src.stride + src.coordinateOffset,
02868: vertexData, vOffset + coordinateOffset, 3);
02869: }
02870: vOffset += stride;
02871: }
02872:
02873: } else {
02874: if ((vertexFormat & GeometryArray.NORMALS) != 0) {
02875: vOffset = normalOffset;
02876: switch ((src.vertexType & NORMAL_DEFINED)) {
02877: case NF:
02878: for (index = start; index < end; index++) {
02879: System.arraycopy(src.floatRefNormals,
02880: src.indexNormal[index] * 3, vertexData,
02881: vOffset, 3);
02882: vOffset += stride;
02883: }
02884: break;
02885: case N3F:
02886: for (index = start; index < end; index++) {
02887: srcOffset = src.indexNormal[index];
02888: vertexData[vOffset] = src.v3fRefNormals[srcOffset].x;
02889: vertexData[vOffset + 1] = src.v3fRefNormals[srcOffset].y;
02890: vertexData[vOffset + 2] = src.v3fRefNormals[srcOffset].z;
02891: vOffset += stride;
02892: }
02893: break;
02894: default:
02895: break;
02896: }
02897: }
02898:
02899: if ((vertexFormat & GeometryArray.COLOR) != 0) {
02900: vOffset = colorOffset;
02901: int multiplier = 3;
02902: if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
02903: multiplier = 4;
02904:
02905: switch ((src.vertexType & COLOR_DEFINED)) {
02906: case CF:
02907: for (index = start; index < end; index++) {
02908: if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
02909: System.arraycopy(src.floatRefColors,
02910: src.indexColor[index] * multiplier,
02911: vertexData, vOffset, 4);
02912: } else {
02913: System.arraycopy(src.floatRefColors,
02914: src.indexColor[index] * multiplier,
02915: vertexData, vOffset, 3);
02916: vertexData[vOffset + 3] = 1.0f;
02917: }
02918: vOffset += stride;
02919: }
02920: break;
02921: case CUB:
02922: for (index = start; index < end; index++) {
02923: srcOffset = src.indexColor[index] * multiplier;
02924: vertexData[vOffset] = (src.byteRefColors[srcOffset] & 0xff)
02925: * ByteToFloatScale;
02926: vertexData[vOffset + 1] = (src.byteRefColors[srcOffset + 1] & 0xff)
02927: * ByteToFloatScale;
02928: vertexData[vOffset + 2] = (src.byteRefColors[srcOffset + 2] & 0xff)
02929: * ByteToFloatScale;
02930: if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
02931: vertexData[vOffset + 3] = (src.byteRefColors[srcOffset + 3] & 0xff)
02932: * ByteToFloatScale;
02933: } else {
02934: vertexData[vOffset + 3] = 1.0f;
02935: }
02936: vOffset += stride;
02937: }
02938: break;
02939: case C3F:
02940: for (index = start; index < end; index++) {
02941: srcOffset = src.indexColor[index];
02942: vertexData[vOffset] = src.c3fRefColors[srcOffset].x;
02943: vertexData[vOffset + 1] = src.c3fRefColors[srcOffset].y;
02944: vertexData[vOffset + 2] = src.c3fRefColors[srcOffset].z;
02945: vertexData[vOffset + 3] = 1.0f;
02946: vOffset += stride;
02947: }
02948: break;
02949: case C4F:
02950: for (index = start; index < end; index++) {
02951: srcOffset = src.indexColor[index];
02952: vertexData[vOffset] = src.c4fRefColors[srcOffset].x;
02953: vertexData[vOffset + 1] = src.c4fRefColors[srcOffset].y;
02954: vertexData[vOffset + 2] = src.c4fRefColors[srcOffset].z;
02955: vertexData[vOffset + 3] = src.c4fRefColors[srcOffset].w;
02956: vOffset += stride;
02957: }
02958: break;
02959: case C3UB:
02960: for (index = start; index < end; index++) {
02961: srcOffset = src.indexColor[index];
02962: vertexData[vOffset] = (src.c3bRefColors[srcOffset].x & 0xff)
02963: * ByteToFloatScale;
02964: vertexData[vOffset + 1] = (src.c3bRefColors[srcOffset].y & 0xff)
02965: * ByteToFloatScale;
02966: vertexData[vOffset + 2] = (src.c3bRefColors[srcOffset].z & 0xff)
02967: * ByteToFloatScale;
02968: vertexData[vOffset + 3] = 1.0f;
02969: vOffset += stride;
02970: }
02971: break;
02972: case C4UB:
02973: for (index = start; index < end; index++) {
02974: srcOffset = src.indexColor[index];
02975: vertexData[vOffset] = (src.c4bRefColors[srcOffset].x & 0xff)
02976: * ByteToFloatScale;
02977: vertexData[vOffset + 1] = (src.c4bRefColors[srcOffset].y & 0xff)
02978: * ByteToFloatScale;
02979: vertexData[vOffset + 2] = (src.c4bRefColors[srcOffset].z & 0xff)
02980: * ByteToFloatScale;
02981: vertexData[vOffset + 3] = (src.c4bRefColors[srcOffset].w & 0xff)
02982: * ByteToFloatScale;
02983: vOffset += stride;
02984: }
02985: break;
02986: default:
02987: break;
02988: }
02989: }
02990:
02991: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
02992: vOffset = textureOffset;
02993: switch ((src.vertexType & TEXCOORD_DEFINED)) {
02994: case TF:
02995: for (index = start; index < end; index++) {
02996: for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) {
02997: System
02998: .arraycopy(src.refTexCoords[i],
02999: src.indexTexCoord[i][index]
03000: * texCoordStride,
03001: vertexData, tOffset,
03002: texCoordStride);
03003: tOffset += texCoordStride;
03004: }
03005: vOffset += stride;
03006: }
03007: break;
03008: case T2F:
03009: for (index = start; index < end; index++) {
03010: for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) {
03011: srcOffset = src.indexTexCoord[i][index];
03012: vertexData[tOffset] = ((TexCoord2f[]) src.refTexCoords[i])[srcOffset].x;
03013: vertexData[tOffset + 1] = ((TexCoord2f[]) src.refTexCoords[i])[srcOffset].y;
03014: tOffset += texCoordStride;
03015: }
03016: vOffset += stride;
03017: }
03018: break;
03019: case T3F:
03020: for (index = start; index < end; index++) {
03021: for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) {
03022: srcOffset = src.indexTexCoord[i][index];
03023: vertexData[tOffset] = ((TexCoord3f[]) src.refTexCoords[i])[srcOffset].x;
03024: vertexData[tOffset + 1] = ((TexCoord3f[]) src.refTexCoords[i])[srcOffset].y;
03025: vertexData[tOffset + 2] = ((TexCoord3f[]) src.refTexCoords[i])[srcOffset].z;
03026: tOffset += texCoordStride;
03027: }
03028: vOffset += stride;
03029: }
03030: break;
03031: default:
03032: break;
03033: }
03034: }
03035:
03036: if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
03037: vOffset = 0;
03038: switch (src.vertexType & VATTR_DEFINED) {
03039: case AF:
03040: for (index = start; index < end; index++) {
03041: for (i = 0; i < vertexAttrCount; i++) {
03042: int vaOffset = vOffset
03043: + vertexAttrOffsets[i];
03044: System.arraycopy(
03045: src.floatRefVertexAttrs[i],
03046: src.indexVertexAttr[i][index]
03047: * vertexAttrSizes[i],
03048: vertexData, vaOffset,
03049: vertexAttrSizes[i]);
03050: }
03051: vOffset += stride;
03052: }
03053: break;
03054: }
03055: }
03056:
03057: if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
03058: vOffset = coordinateOffset;
03059: switch ((src.vertexType & VERTEX_DEFINED)) {
03060: case PF:
03061: for (index = start; index < end; index++) {
03062: System.arraycopy(src.floatRefCoords,
03063: src.indexCoord[index] * 3, vertexData,
03064: vOffset, 3);
03065: vOffset += stride;
03066: }
03067: break;
03068: case PD:
03069: for (index = start; index < end; index++) {
03070: srcOffset = src.indexCoord[index] * 3;
03071: vertexData[vOffset] = (float) src.doubleRefCoords[srcOffset];
03072: vertexData[vOffset + 1] = (float) src.doubleRefCoords[srcOffset + 1];
03073: vertexData[vOffset + 2] = (float) src.doubleRefCoords[srcOffset + 2];
03074: vOffset += stride;
03075: }
03076: break;
03077: case P3F:
03078: for (index = start; index < end; index++) {
03079: srcOffset = src.indexCoord[index];
03080: vertexData[vOffset] = src.p3fRefCoords[srcOffset].x;
03081: vertexData[vOffset + 1] = src.p3fRefCoords[srcOffset].y;
03082: vertexData[vOffset + 2] = src.p3fRefCoords[srcOffset].z;
03083: vOffset += stride;
03084: }
03085: break;
03086: case P3D:
03087: for (index = start; index < end; index++) {
03088: srcOffset = src.indexCoord[index];
03089: vertexData[vOffset] = (float) src.p3dRefCoords[srcOffset].x;
03090: vertexData[vOffset + 1] = (float) src.p3dRefCoords[srcOffset].y;
03091: vertexData[vOffset + 2] = (float) src.p3dRefCoords[srcOffset].z;
03092: vOffset += stride;
03093: }
03094: break;
03095: default:
03096: break;
03097: }
03098: }
03099:
03100: }
03101: }
03102:
03103: private void unIndexifyNIOBuffer(IndexedGeometryArrayRetained src) {
03104: // System.err.println("unIndexifyNIOBuffer");
03105:
03106: int vOffset = 0, srcOffset, tOffset = 0;
03107: int index, colorStride = 0;
03108: float[] vdata = null;
03109: int i;
03110: int start, end;
03111: start = src.initialIndexIndex;
03112: end = src.initialIndexIndex + src.validIndexCount;
03113: // If its interleaved data then ..
03114: if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
03115: if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
03116: colorStride = 4;
03117: else if ((src.vertexFormat & GeometryArray.COLOR) != 0)
03118: colorStride = 3;
03119:
03120: // System.err.println("===> start = "+start+" end = "+end);
03121: for (index = start; index < end; index++) {
03122: if ((vertexFormat & GeometryArray.NORMALS) != 0) {
03123: src.interleavedFloatBufferImpl
03124: .position(src.indexNormal[index]
03125: * src.stride + src.normalOffset);
03126: src.interleavedFloatBufferImpl.get(vertexData,
03127: vOffset + normalOffset, 3);
03128: }
03129:
03130: if (colorStride == 4) {
03131: src.interleavedFloatBufferImpl
03132: .position(src.indexColor[index]
03133: * src.stride + src.colorOffset);
03134: src.interleavedFloatBufferImpl.get(vertexData,
03135: vOffset + colorOffset, colorStride);
03136: } else if (colorStride == 3) {
03137: src.interleavedFloatBufferImpl
03138: .position(src.indexColor[index]
03139: * src.stride + src.colorOffset);
03140: src.interleavedFloatBufferImpl.get(vertexData,
03141: vOffset + colorOffset, colorStride);
03142: vertexData[vOffset + colorOffset + 3] = 1.0f;
03143: }
03144:
03145: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
03146: int tcOffset = vOffset + textureOffset;
03147: for (i = 0; i < texCoordSetCount; i++, tcOffset += texCoordStride) {
03148:
03149: src.interleavedFloatBufferImpl
03150: .position((src.indexTexCoord[i][index])
03151: * src.stride
03152: + src.textureOffset);
03153: src.interleavedFloatBufferImpl.get(vertexData,
03154: tcOffset, texCoordStride);
03155: }
03156: }
03157: if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
03158: src.interleavedFloatBufferImpl
03159: .position(src.indexCoord[index]
03160: * src.stride + src.coordinateOffset);
03161: src.interleavedFloatBufferImpl.get(vertexData,
03162: vOffset + coordinateOffset, 3);
03163: }
03164: vOffset += stride;
03165: }
03166:
03167: } else {
03168: if ((vertexFormat & GeometryArray.NORMALS) != 0) {
03169: vOffset = normalOffset;
03170: if ((src.vertexType & NORMAL_DEFINED) != 0) {
03171: for (index = start; index < end; index++) {
03172: src.floatBufferRefNormals
03173: .position(src.indexNormal[index] * 3);
03174: src.floatBufferRefNormals.get(vertexData,
03175: vOffset, 3);
03176: vOffset += stride;
03177: }
03178: }
03179: }
03180:
03181: if ((vertexFormat & GeometryArray.COLOR) != 0) {
03182: vOffset = colorOffset;
03183: int multiplier = 3;
03184: if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
03185: multiplier = 4;
03186:
03187: switch ((src.vertexType & COLOR_DEFINED)) {
03188: case CF:
03189: for (index = start; index < end; index++) {
03190: if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
03191: src.floatBufferRefColors
03192: .position(src.indexColor[index]
03193: * multiplier);
03194: src.floatBufferRefColors.get(vertexData,
03195: vOffset, 4);
03196: } else {
03197: src.floatBufferRefColors
03198: .position(src.indexColor[index]
03199: * multiplier);
03200: src.floatBufferRefColors.get(vertexData,
03201: vOffset, 3);
03202: vertexData[vOffset + 3] = 1.0f;
03203: }
03204: vOffset += stride;
03205: }
03206: break;
03207: case CUB:
03208: for (index = start; index < end; index++) {
03209: srcOffset = src.indexColor[index] * multiplier;
03210: vertexData[vOffset] = (src.byteBufferRefColors
03211: .get(srcOffset) & 0xff)
03212: * ByteToFloatScale;
03213: vertexData[vOffset + 1] = (src.byteBufferRefColors
03214: .get(srcOffset + 1) & 0xff)
03215: * ByteToFloatScale;
03216: vertexData[vOffset + 2] = (src.byteBufferRefColors
03217: .get(srcOffset + 2) & 0xff)
03218: * ByteToFloatScale;
03219:
03220: if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
03221: vertexData[vOffset + 3] = (src.byteBufferRefColors
03222: .get(srcOffset + 3) & 0xff)
03223: * ByteToFloatScale;
03224: } else {
03225: vertexData[vOffset + 3] = 1.0f;
03226: }
03227: vOffset += stride;
03228: }
03229: break;
03230: default:
03231: break;
03232: }
03233: }
03234:
03235: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
03236: vOffset = textureOffset;
03237: FloatBufferWrapper texBuffer;
03238: if ((src.vertexType & TEXCOORD_DEFINED) != 0) {
03239: for (index = start; index < end; index++) {
03240: for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) {
03241: texBuffer = (FloatBufferWrapper) (((J3DBuffer) (src.refTexCoordsBuffer[i]))
03242: .getBufferImpl());
03243: texBuffer
03244: .position(src.indexTexCoord[i][index]
03245: * texCoordStride);
03246: texBuffer.get(vertexData, tOffset,
03247: texCoordStride);
03248: tOffset += texCoordStride;
03249: }
03250: vOffset += stride;
03251: }
03252: }
03253: }
03254:
03255: if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
03256: vOffset = 0;
03257: if ((src.vertexType & VATTR_DEFINED) == AF) {
03258: for (index = start; index < end; index++) {
03259: for (i = 0; i < vertexAttrCount; i++) {
03260: int vaOffset = vOffset
03261: + vertexAttrOffsets[i];
03262: FloatBufferWrapper vaBuffer = src.floatBufferRefVertexAttrs[i];
03263: vaBuffer
03264: .position(src.indexVertexAttr[i][index]
03265: * vertexAttrSizes[i]);
03266: vaBuffer.get(vertexData, vaOffset,
03267: vertexAttrSizes[i]);
03268: }
03269: vOffset += stride;
03270: }
03271: }
03272: }
03273:
03274: if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
03275: vOffset = coordinateOffset;
03276: switch ((src.vertexType & VERTEX_DEFINED)) {
03277: case PF:
03278: for (index = start; index < end; index++) {
03279: src.floatBufferRefCoords
03280: .position(src.indexCoord[index] * 3);
03281: src.floatBufferRefCoords.get(vertexData,
03282: vOffset, 3);
03283: vOffset += stride;
03284: }
03285: break;
03286: case PD:
03287: for (index = start; index < end; index++) {
03288: srcOffset = src.indexCoord[index] * 3;
03289: vertexData[vOffset] = (float) src.doubleBufferRefCoords
03290: .get(srcOffset);
03291: vertexData[vOffset + 1] = (float) src.doubleBufferRefCoords
03292: .get(srcOffset + 1);
03293: vertexData[vOffset + 2] = (float) src.doubleBufferRefCoords
03294: .get(srcOffset + 2);
03295: vOffset += stride;
03296: }
03297: break;
03298: default:
03299: break;
03300: }
03301: }
03302:
03303: }
03304: }
03305:
03306: /**
03307: * Returns the vertex stride in numbers of floats as a function
03308: * of the vertexFormat.
03309: * @return the stride in floats for this vertex array
03310: */
03311: int stride() {
03312: int stride = 0;
03313:
03314: if ((this .vertexFormat & GeometryArray.COORDINATES) != 0)
03315: stride += 3;
03316: if ((this .vertexFormat & GeometryArray.NORMALS) != 0)
03317: stride += 3;
03318:
03319: if ((this .vertexFormat & GeometryArray.COLOR) != 0) {
03320: if ((this .vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
03321: // By copy
03322: stride += 4;
03323: } else {
03324: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
03325: stride += 3;
03326: } else {
03327: stride += 4;
03328: }
03329: }
03330: }
03331:
03332: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
03333:
03334: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
03335: texCoordStride = 2;
03336: } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
03337: texCoordStride = 3;
03338: } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
03339: texCoordStride = 4;
03340: }
03341:
03342: stride += texCoordStride * texCoordSetCount;
03343: }
03344:
03345: if ((this .vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
03346: stride += vertexAttrStride;
03347: }
03348:
03349: //System.err.println("stride() = " + stride);
03350: return stride;
03351: }
03352:
03353: int[] texCoordSetMapOffset() {
03354: if (texCoordSetMap == null)
03355: return null;
03356:
03357: texCoordSetMapOffset = new int[texCoordSetMap.length];
03358: for (int i = 0; i < texCoordSetMap.length; i++) {
03359: if (texCoordSetMap[i] == -1) {
03360: texCoordSetMapOffset[i] = -1;
03361: } else {
03362: texCoordSetMapOffset[i] = texCoordSetMap[i]
03363: * texCoordStride;
03364: }
03365: }
03366: return texCoordSetMapOffset;
03367: }
03368:
03369: /**
03370: * Returns the stride of the set of vertex attributes. This is the
03371: * sum of the sizes of each vertex attribute.
03372: * @return the stride of the vertex attribute data
03373: */
03374: int vertexAttrStride() {
03375: int sum = 0;
03376: for (int i = 0; i < vertexAttrCount; i++) {
03377: sum += vertexAttrSizes[i];
03378: }
03379: return sum;
03380: }
03381:
03382: /**
03383: * Returns the offset in number of floats from the start of a vertex to
03384: * each per-vertex vertex attribute.
03385: * @return array of offsets in floats vertex start to the vertex attribute data
03386: */
03387: int[] vertexAttrOffsets() {
03388: int[] offsets;
03389:
03390: // Create array of offsets to the start of each vertex attribute.
03391: // The offset of the first attribute is always 0. If no vertex attributes exist,
03392: // then we will allocate an array of length 1 to avoid some checking elsewhere.
03393: if (vertexAttrCount > 0) {
03394: offsets = new int[vertexAttrCount];
03395: } else {
03396: offsets = new int[1];
03397: }
03398: offsets[0] = 0;
03399: for (int i = 1; i < vertexAttrCount; i++) {
03400: offsets[i] = offsets[i - 1] + vertexAttrSizes[i - 1];
03401: }
03402:
03403: return offsets;
03404: }
03405:
03406: /**
03407: * Returns the offset in number of floats from the start of a vertex to
03408: * the per-vertex texture coordinate data.
03409: * texture coordinate data always follows vertex attribute data
03410: * @return the offset in floats vertex start to the tetxure data
03411: */
03412: int textureOffset() {
03413: int offset = vertexAttrOffsets[0];
03414:
03415: if ((this .vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
03416: offset += vertexAttrStride;
03417: }
03418:
03419: return offset;
03420: }
03421:
03422: /**
03423: * Returns the offset in number of floats from the start of a vertex to
03424: * the per-vertex color data.
03425: * color data always follows texture data
03426: * @param vertexFormat the vertex format for this array
03427: * @return the offset in floats vertex start to the color data
03428: */
03429: int colorOffset() {
03430: int offset = textureOffset;
03431:
03432: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0)
03433: offset += 2 * texCoordSetCount;
03434: else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0)
03435: offset += 3 * texCoordSetCount;
03436: else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0)
03437: offset += 4 * texCoordSetCount;
03438:
03439: return offset;
03440: }
03441:
03442: /**
03443: * Returns the offset in number of floats from the start of a vertex to
03444: * the per-vertex normal data.
03445: * normal data always follows color data
03446: * @return the offset in floats from the start of a vertex to the normal
03447: */
03448: int normalOffset() {
03449: int offset = colorOffset;
03450:
03451: if ((this .vertexFormat & GeometryArray.COLOR) != 0) {
03452: if ((this .vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
03453: offset += 4;
03454: } else {
03455: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
03456: offset += 3;
03457: } else {
03458: offset += 4;
03459: }
03460: }
03461: }
03462: return offset;
03463: }
03464:
03465: /**
03466: * Returns the offset in number of floats from the start of a vertex to
03467: * the per vertex coordinate data.
03468: * @return the offset in floats vertex start to the coordinate data
03469: */
03470: int coordinateOffset() {
03471: int offset = normalOffset;
03472:
03473: if ((this .vertexFormat & GeometryArray.NORMALS) != 0)
03474: offset += 3;
03475: return offset;
03476: }
03477:
03478: /**
03479: * Returns number of vertices in the GeometryArray
03480: * @return vertexCount number of vertices in the GeometryArray
03481: */
03482: int getVertexCount() {
03483: return vertexCount;
03484: }
03485:
03486: /**
03487: * Returns vertexFormat in the GeometryArray
03488: * @return vertexFormat format of vertices in the GeometryArray
03489: */
03490: int getVertexFormat() {
03491: return vertexFormat;
03492: }
03493:
03494: /**
03495: * Retrieves the number of vertex attributes in this GeometryArray
03496: * object.
03497: *
03498: * @return the number of vertex attributes in this GeometryArray
03499: * object
03500: */
03501: int getVertexAttrCount() {
03502: return vertexAttrCount;
03503: }
03504:
03505: /**
03506: * Retrieves the vertex attribute sizes array from this
03507: * GeometryArray object.
03508: *
03509: * @param vertexAttrSizes an array that will receive a copy of
03510: * the vertex attribute sizes array. The array must hold at least
03511: * <code>vertexAttrCount</code> elements.
03512: */
03513: void getVertexAttrSizes(int[] vertexAttrSizes) {
03514: for (int i = 0; i < vertexAttrCount; i++) {
03515: vertexAttrSizes[i] = this .vertexAttrSizes[i];
03516: }
03517: }
03518:
03519: void sendDataChangedMessage(boolean coordinatesChanged) {
03520: J3dMessage[] m;
03521: int i, j, k, index, numShapeMessages, numMorphMessages;
03522: ArrayList shapeList;
03523: Shape3DRetained s;
03524: ArrayList morphList;
03525: MorphRetained morph;
03526:
03527: synchronized (liveStateLock) {
03528: if (source != null && source.isLive()) {
03529: // System.err.println("In GeometryArrayRetained - ");
03530:
03531: // Send a message to renderBin to rebuild the display list or
03532: // process the vertex array accordingly
03533: // XXXX: Should I send one per universe, isn't display list
03534: // shared by all context/universes?
03535: int threads = J3dThread.UPDATE_RENDER;
03536: // If the geometry type is Indexed then we need to clone the geometry
03537: // We also need to update the cachedChangedFrequent flag
03538: threads |= J3dThread.UPDATE_RENDERING_ATTRIBUTES;
03539:
03540: synchronized (universeList) {
03541: numShapeMessages = universeList.size();
03542: m = new J3dMessage[numShapeMessages];
03543:
03544: k = 0;
03545:
03546: for (i = 0; i < numShapeMessages; i++, k++) {
03547: gaList.clear();
03548:
03549: shapeList = (ArrayList) userLists.get(i);
03550: for (j = 0; j < shapeList.size(); j++) {
03551: s = (Shape3DRetained) shapeList.get(j);
03552: LeafRetained src = (LeafRetained) s.sourceNode;
03553: // Should only need to update distinct localBounds.
03554: if (coordinatesChanged
03555: && src.boundsAutoCompute) {
03556: src.boundsDirty = true;
03557: }
03558: }
03559:
03560: for (j = 0; j < shapeList.size(); j++) {
03561: s = (Shape3DRetained) shapeList.get(j);
03562: LeafRetained src = (LeafRetained) s.sourceNode;
03563: if (src.boundsDirty) {
03564: // update combine bounds of mirrorShape3Ds. So we need to
03565: // use its bounds and not localBounds.
03566: // bounds is actually a reference to
03567: // mirrorShape3D.source.localBounds.
03568: src.updateBounds();
03569: src.boundsDirty = false;
03570: }
03571: gaList.add(Shape3DRetained.getGeomAtom(s));
03572: }
03573:
03574: m[k] = new J3dMessage();
03575:
03576: m[k].type = J3dMessage.GEOMETRY_CHANGED;
03577: // Who to send this message to ?
03578: m[k].threads = threads;
03579: m[k].args[0] = gaList.toArray();
03580: m[k].args[1] = this ;
03581: m[k].args[2] = null;
03582: m[k].args[3] = new Integer(changedFrequent);
03583: m[k].universe = (VirtualUniverse) universeList
03584: .get(i);
03585: }
03586: VirtualUniverse.mc.processMessage(m);
03587: }
03588:
03589: if (morphUniverseList != null) {
03590: synchronized (morphUniverseList) {
03591: numMorphMessages = morphUniverseList.size();
03592:
03593: // take care of morph that is referencing this geometry
03594: if (numMorphMessages > 0) {
03595: synchronized (morphUniverseList) {
03596: for (i = 0; i < numMorphMessages; i++, k++) {
03597: morphList = (ArrayList) morphUserLists
03598: .get(i);
03599: for (j = 0; j < morphList.size(); j++) {
03600: morph = (MorphRetained) morphList
03601: .get(j);
03602: morph
03603: .updateMorphedGeometryArray(
03604: this ,
03605: coordinatesChanged);
03606: }
03607: }
03608: }
03609: }
03610: }
03611: }
03612: }
03613: }
03614:
03615: }
03616:
03617: /**
03618: * Sets the coordinate associated with the vertex at
03619: * the specified index.
03620: * @param index the vertex index
03621: * @param coordinate an array of 3 values containing the new coordinate
03622: */
03623: void setCoordinate(int index, float coordinate[]) {
03624: int offset = this .stride * index + coordinateOffset;
03625: boolean isLive = source != null && source.isLive();
03626: if (isLive) {
03627: geomLock.getLock();
03628: }
03629: dirtyFlag |= COORDINATE_CHANGED;
03630:
03631: this .vertexData[offset] = coordinate[0];
03632: this .vertexData[offset + 1] = coordinate[1];
03633: this .vertexData[offset + 2] = coordinate[2];
03634:
03635: if (isLive) {
03636: geomLock.unLock();
03637: }
03638: if (inUpdater || (source == null)) {
03639: return;
03640: }
03641: if (!isLive) {
03642: boundsDirty = true;
03643: return;
03644: }
03645:
03646: // Compute geo's bounds
03647: processCoordsChanged(false);
03648: sendDataChangedMessage(true);
03649:
03650: }
03651:
03652: /**
03653: * Sets the coordinate associated with the vertex at
03654: * the specified index.
03655: * @param index the vertex index
03656: * @param coordinate an array of 3 values containing the new coordinate
03657: */
03658: void setCoordinate(int index, double coordinate[]) {
03659: int offset = this .stride * index + coordinateOffset;
03660: boolean isLive = source != null && source.isLive();
03661: if (isLive) {
03662: geomLock.getLock();
03663: }
03664: dirtyFlag |= COORDINATE_CHANGED;
03665: this .vertexData[offset] = (float) coordinate[0];
03666: this .vertexData[offset + 1] = (float) coordinate[1];
03667: this .vertexData[offset + 2] = (float) coordinate[2];
03668:
03669: if (isLive) {
03670: geomLock.unLock();
03671: }
03672:
03673: if (inUpdater || (source == null)) {
03674: return;
03675: }
03676: if (!isLive) {
03677: boundsDirty = true;
03678: return;
03679: }
03680:
03681: // Compute geo's bounds
03682: processCoordsChanged(false);
03683: sendDataChangedMessage(true);
03684: }
03685:
03686: /**
03687: * Sets the coordinate associated with the vertex at
03688: * the specified index.
03689: * @param index the vertex index
03690: * @param coordinate a vector containing the new coordinate
03691: */
03692: void setCoordinate(int index, Point3f coordinate) {
03693: int offset = this .stride * index + coordinateOffset;
03694: boolean isLive = source != null && source.isLive();
03695: if (isLive) {
03696: geomLock.getLock();
03697: }
03698: dirtyFlag |= COORDINATE_CHANGED;
03699: this .vertexData[offset] = coordinate.x;
03700: this .vertexData[offset + 1] = coordinate.y;
03701: this .vertexData[offset + 2] = coordinate.z;
03702:
03703: if (isLive) {
03704: geomLock.unLock();
03705: }
03706: if (inUpdater || (source == null)) {
03707: return;
03708: }
03709: if (!isLive) {
03710: boundsDirty = true;
03711: return;
03712: }
03713:
03714: // Compute geo's bounds
03715: processCoordsChanged(false);
03716: sendDataChangedMessage(true);
03717: }
03718:
03719: /**
03720: * Sets the coordinate associated with the vertex at
03721: * the specified index.
03722: * @param index the vertex index
03723: * @param coordinate a vector containing the new coordinate
03724: */
03725: void setCoordinate(int index, Point3d coordinate) {
03726: int offset = this .stride * index + coordinateOffset;
03727: boolean isLive = source != null && source.isLive();
03728: if (isLive) {
03729: geomLock.getLock();
03730: }
03731: dirtyFlag |= COORDINATE_CHANGED;
03732: this .vertexData[offset] = (float) coordinate.x;
03733: this .vertexData[offset + 1] = (float) coordinate.y;
03734: this .vertexData[offset + 2] = (float) coordinate.z;
03735: if (isLive) {
03736: geomLock.unLock();
03737: }
03738: if (inUpdater || source == null) {
03739: return;
03740: }
03741: if (!isLive) {
03742: boundsDirty = true;
03743: return;
03744: }
03745: // Compute geo's bounds
03746: processCoordsChanged(false);
03747: sendDataChangedMessage(true);
03748: }
03749:
03750: /**
03751: * Sets the coordinates associated with the vertices starting at
03752: * the specified index.
03753: * @param index the vertex index
03754: * @param coordinates an array of 3*n values containing n new coordinates
03755: */
03756: void setCoordinates(int index, float coordinates[]) {
03757: int offset = this .stride * index + coordinateOffset;
03758: int i, j, num = coordinates.length;
03759: boolean isLive = source != null && source.isLive();
03760: if (isLive) {
03761: geomLock.getLock();
03762: }
03763: dirtyFlag |= COORDINATE_CHANGED;
03764:
03765: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
03766: this .vertexData[j] = coordinates[i];
03767: this .vertexData[j + 1] = coordinates[i + 1];
03768: this .vertexData[j + 2] = coordinates[i + 2];
03769: }
03770:
03771: if (isLive) {
03772: geomLock.unLock();
03773: }
03774: if (inUpdater || source == null) {
03775: return;
03776: }
03777: if (!isLive) {
03778: boundsDirty = true;
03779: return;
03780: }
03781:
03782: // Compute geo's bounds
03783: processCoordsChanged(false);
03784:
03785: sendDataChangedMessage(true);
03786:
03787: }
03788:
03789: /**
03790: * Sets the coordinates associated with the vertices starting at
03791: * the specified index.
03792: * @param index the vertex index
03793: * @param coordinates an array of 3*n values containing n new coordinates
03794: */
03795: void setCoordinates(int index, double coordinates[]) {
03796: int offset = this .stride * index + coordinateOffset;
03797: int i, j, num = coordinates.length;
03798: boolean isLive = source != null && source.isLive();
03799: if (isLive) {
03800: geomLock.getLock();
03801: }
03802: dirtyFlag |= COORDINATE_CHANGED;
03803:
03804: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
03805: this .vertexData[j] = (float) coordinates[i];
03806: this .vertexData[j + 1] = (float) coordinates[i + 1];
03807: this .vertexData[j + 2] = (float) coordinates[i + 2];
03808: }
03809:
03810: if (isLive) {
03811: geomLock.unLock();
03812: }
03813:
03814: if (inUpdater || source == null) {
03815: return;
03816: }
03817: if (!isLive) {
03818: boundsDirty = true;
03819: return;
03820: }
03821:
03822: // Compute geo's bounds
03823: processCoordsChanged(false);
03824:
03825: sendDataChangedMessage(true);
03826: }
03827:
03828: /**
03829: * Sets the coordinates associated with the vertices starting at
03830: * the specified index.
03831: * @param index the vertex index
03832: * @param coordinates an array of vectors containing new coordinates
03833: */
03834: void setCoordinates(int index, Point3f coordinates[]) {
03835: int offset = this .stride * index + coordinateOffset;
03836: int i, j, num = coordinates.length;
03837: boolean isLive = source != null && source.isLive();
03838: if (isLive) {
03839: geomLock.getLock();
03840: }
03841: dirtyFlag |= COORDINATE_CHANGED;
03842:
03843: for (i = 0, j = offset; i < num; i++, j += this .stride) {
03844: this .vertexData[j] = coordinates[i].x;
03845: this .vertexData[j + 1] = coordinates[i].y;
03846: this .vertexData[j + 2] = coordinates[i].z;
03847: }
03848: if (isLive) {
03849: geomLock.unLock();
03850: }
03851:
03852: if (inUpdater || source == null) {
03853: return;
03854: }
03855: if (!isLive) {
03856: boundsDirty = true;
03857: return;
03858: }
03859:
03860: // Compute geo's bounds
03861: processCoordsChanged(false);
03862:
03863: sendDataChangedMessage(true);
03864:
03865: }
03866:
03867: /**
03868: * Sets the coordinates associated with the vertices starting at
03869: * the specified index.
03870: * @param index the vertex index
03871: * @param coordinates an array of vectors containing new coordinates
03872: */
03873: void setCoordinates(int index, Point3d coordinates[]) {
03874: int offset = this .stride * index + coordinateOffset;
03875: int i, j, num = coordinates.length;
03876: boolean isLive = source != null && source.isLive();
03877: if (isLive) {
03878: geomLock.getLock();
03879: }
03880: dirtyFlag |= COORDINATE_CHANGED;
03881:
03882: for (i = 0, j = offset; i < num; i++, j += this .stride) {
03883: this .vertexData[j] = (float) coordinates[i].x;
03884: this .vertexData[j + 1] = (float) coordinates[i].y;
03885: this .vertexData[j + 2] = (float) coordinates[i].z;
03886: }
03887: if (isLive) {
03888: geomLock.unLock();
03889: }
03890:
03891: if (inUpdater || source == null) {
03892: return;
03893: }
03894: if (!isLive) {
03895: boundsDirty = true;
03896: return;
03897: }
03898:
03899: // Compute geo's bounds
03900: processCoordsChanged(false);
03901:
03902: sendDataChangedMessage(true);
03903: }
03904:
03905: /**
03906: * Sets the coordinates associated with the vertices starting at
03907: * the specified index for this object using coordinate data starting
03908: * from vertex index <code>start</code> for <code>length</code> vertices.
03909: * @param index the vertex index
03910: * @param coordinates an array of vectors containing new coordinates
03911: * @param start starting vertex index of data in <code>coordinates</code> .
03912: * @param length number of vertices to be copied.
03913: */
03914: void setCoordinates(int index, float coordinates[], int start,
03915: int length) {
03916: int offset = this .stride * index + coordinateOffset;
03917: int i, j;
03918: boolean isLive = source != null && source.isLive();
03919: if (isLive) {
03920: geomLock.getLock();
03921: }
03922: dirtyFlag |= COORDINATE_CHANGED;
03923: for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
03924: this .vertexData[j] = coordinates[i];
03925: this .vertexData[j + 1] = coordinates[i + 1];
03926: this .vertexData[j + 2] = coordinates[i + 2];
03927: }
03928: if (isLive) {
03929: geomLock.unLock();
03930: }
03931: if (inUpdater || source == null) {
03932: return;
03933: }
03934: if (!isLive) {
03935: boundsDirty = true;
03936: return;
03937: }
03938:
03939: // Compute geo's bounds
03940: processCoordsChanged(false);
03941:
03942: sendDataChangedMessage(true);
03943: }
03944:
03945: /**
03946: * Sets the coordinates associated with the vertices starting at
03947: * the specified index for this object using coordinate data starting
03948: * from vertex index <code>start</code> for <code>length</code> vertices.
03949: * @param index the vertex index
03950: * @param coordinates an array of 3*n values containing n new coordinates
03951: * @param start starting vertex index of data in <code>coordinates</code> .
03952: * @param length number of vertices to be copied.
03953: */
03954: void setCoordinates(int index, double coordinates[], int start,
03955: int length) {
03956: int offset = this .stride * index + coordinateOffset;
03957: int i, j;
03958: boolean isLive = source != null && source.isLive();
03959: if (isLive) {
03960: geomLock.getLock();
03961: }
03962: dirtyFlag |= COORDINATE_CHANGED;
03963:
03964: for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
03965: this .vertexData[j] = (float) coordinates[i];
03966: this .vertexData[j + 1] = (float) coordinates[i + 1];
03967: this .vertexData[j + 2] = (float) coordinates[i + 2];
03968: }
03969:
03970: if (isLive) {
03971: geomLock.unLock();
03972: }
03973: if (inUpdater || (source == null)) {
03974: return;
03975: }
03976: if (!isLive) {
03977: boundsDirty = true;
03978: return;
03979: }
03980:
03981: // Compute geo's bounds
03982: processCoordsChanged(false);
03983:
03984: sendDataChangedMessage(true);
03985: }
03986:
03987: /**
03988: * Sets the coordinates associated with the vertices starting at
03989: * the specified index for this object using coordinate data starting
03990: * from vertex index <code>start</code> for <code>length</code> vertices.
03991: * @param index the vertex index
03992: * @param coordinates an array of vectors containing new coordinates
03993: * @param start starting vertex index of data in <code>coordinates</code> .
03994: * @param length number of vertices to be copied.
03995: */
03996: void setCoordinates(int index, Point3f coordinates[], int start,
03997: int length) {
03998: int offset = this .stride * index + coordinateOffset;
03999: int i, j;
04000: boolean isLive = source != null && source.isLive();
04001: if (isLive) {
04002: geomLock.getLock();
04003: }
04004: dirtyFlag |= COORDINATE_CHANGED;
04005:
04006: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04007: this .vertexData[j] = coordinates[i].x;
04008: this .vertexData[j + 1] = coordinates[i].y;
04009: this .vertexData[j + 2] = coordinates[i].z;
04010: }
04011:
04012: if (isLive) {
04013: geomLock.unLock();
04014: }
04015:
04016: if (inUpdater || (source == null)) {
04017: return;
04018: }
04019: if (!isLive) {
04020: boundsDirty = true;
04021: return;
04022: }
04023:
04024: // Compute geo's bounds
04025: processCoordsChanged(false);
04026:
04027: sendDataChangedMessage(true);
04028: }
04029:
04030: /**
04031: * Sets the coordinates associated with the vertices starting at
04032: * the specified index for this object using coordinate data starting
04033: * from vertex index <code>start</code> for <code>length</code> vertices.
04034: * @param index the vertex index
04035: * @param coordinates an array of vectors containing new coordinates
04036: * @param start starting vertex index of data in <code>coordinates</code> .
04037: * @param length number of vertices to be copied.
04038: */
04039: void setCoordinates(int index, Point3d coordinates[], int start,
04040: int length) {
04041: int offset = this .stride * index + coordinateOffset;
04042: int i, j;
04043: boolean isLive = source != null && source.isLive();
04044: if (isLive) {
04045: geomLock.getLock();
04046: }
04047: dirtyFlag |= COORDINATE_CHANGED;
04048:
04049: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04050: this .vertexData[j] = (float) coordinates[i].x;
04051: this .vertexData[j + 1] = (float) coordinates[i].y;
04052: this .vertexData[j + 2] = (float) coordinates[i].z;
04053: }
04054:
04055: if (isLive) {
04056: geomLock.unLock();
04057: }
04058: if (inUpdater || (source == null)) {
04059: return;
04060: }
04061: if (!isLive) {
04062: boundsDirty = true;
04063: return;
04064: }
04065:
04066: // Compute geo's bounds
04067: processCoordsChanged(false);
04068:
04069: sendDataChangedMessage(true);
04070: }
04071:
04072: /**
04073: * Sets the color associated with the vertex at
04074: * the specified index.
04075: * @param index the vertex index
04076: * @param color an array of 3 or 4 values containing the new color
04077: */
04078: void setColor(int index, float color[]) {
04079: int offset = this .stride * index + colorOffset;
04080:
04081: boolean isLive = source != null && source.isLive();
04082: if (isLive) {
04083: geomLock.getLock();
04084: }
04085: dirtyFlag |= COLOR_CHANGED;
04086: colorChanged = 0xffff;
04087: this .vertexData[offset] = color[0];
04088: this .vertexData[offset + 1] = color[1];
04089: this .vertexData[offset + 2] = color[2];
04090: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0)
04091: this .vertexData[offset + 3] = color[3] * lastAlpha[0];
04092: else
04093: this .vertexData[offset + 3] = lastAlpha[0];
04094:
04095: if (isLive) {
04096: geomLock.unLock();
04097: sendDataChangedMessage(false);
04098: }
04099:
04100: }
04101:
04102: /**
04103: * Sets the color associated with the vertex at
04104: * the specified index.
04105: * @param index the vertex index
04106: * @param color an array of 3 or 4 values containing the new color
04107: */
04108: void setColor(int index, byte color[]) {
04109: int offset = this .stride * index + colorOffset;
04110:
04111: boolean isLive = source != null && source.isLive();
04112: if (isLive) {
04113: geomLock.getLock();
04114: }
04115:
04116: dirtyFlag |= COLOR_CHANGED;
04117: colorChanged = 0xffff;
04118: this .vertexData[offset] = (color[0] & 0xff) * ByteToFloatScale;
04119: this .vertexData[offset + 1] = (color[1] & 0xff)
04120: * ByteToFloatScale;
04121: this .vertexData[offset + 2] = (color[2] & 0xff)
04122: * ByteToFloatScale;
04123: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0)
04124: this .vertexData[offset + 3] = ((color[3] & 0xff) * ByteToFloatScale)
04125: * lastAlpha[0];
04126: else
04127: this .vertexData[offset + 3] = lastAlpha[0];
04128:
04129: if (isLive) {
04130: geomLock.unLock();
04131: sendDataChangedMessage(false);
04132: }
04133:
04134: }
04135:
04136: /**
04137: * Sets the color associated with the vertex at
04138: * the specified index.
04139: * @param index the vertex index
04140: * @param color a vector containing the new color
04141: */
04142: void setColor(int index, Color3f color) {
04143: int offset = this .stride * index + colorOffset;
04144:
04145: boolean isLive = source != null && source.isLive();
04146: if (isLive) {
04147: geomLock.getLock();
04148: }
04149:
04150: dirtyFlag |= COLOR_CHANGED;
04151: colorChanged = 0xffff;
04152: this .vertexData[offset] = color.x;
04153: this .vertexData[offset + 1] = color.y;
04154: this .vertexData[offset + 2] = color.z;
04155: this .vertexData[offset + 3] = lastAlpha[0];
04156:
04157: if (isLive) {
04158: geomLock.unLock();
04159: sendDataChangedMessage(false);
04160: }
04161:
04162: }
04163:
04164: /**
04165: * Sets the color associated with the vertex at
04166: * the specified index.
04167: * @param index the vertex index
04168: * @param color a vector containing the new color
04169: */
04170: void setColor(int index, Color4f color) {
04171: int offset = this .stride * index + colorOffset;
04172: boolean isLive = source != null && source.isLive();
04173: if (isLive) {
04174: geomLock.getLock();
04175: }
04176: dirtyFlag |= COLOR_CHANGED;
04177: colorChanged = 0xffff;
04178: this .vertexData[offset] = color.x;
04179: this .vertexData[offset + 1] = color.y;
04180: this .vertexData[offset + 2] = color.z;
04181: this .vertexData[offset + 3] = color.w * lastAlpha[0];
04182:
04183: if (isLive) {
04184: geomLock.unLock();
04185: sendDataChangedMessage(false);
04186: }
04187:
04188: }
04189:
04190: /**
04191: * Sets the color associated with the vertex at
04192: * the specified index.
04193: * @param index the vertex index
04194: * @param color a vector containing the new color
04195: */
04196: void setColor(int index, Color3b color) {
04197: int offset = this .stride * index + colorOffset;
04198:
04199: boolean isLive = source != null && source.isLive();
04200: if (isLive) {
04201: geomLock.getLock();
04202: }
04203:
04204: dirtyFlag |= COLOR_CHANGED;
04205: colorChanged = 0xffff;
04206: this .vertexData[offset] = (color.x & 0xff) * ByteToFloatScale;
04207: this .vertexData[offset + 1] = (color.y & 0xff)
04208: * ByteToFloatScale;
04209: this .vertexData[offset + 2] = (color.z & 0xff)
04210: * ByteToFloatScale;
04211: this .vertexData[offset + 3] = lastAlpha[0];
04212:
04213: if (isLive) {
04214: geomLock.unLock();
04215: sendDataChangedMessage(false);
04216: }
04217:
04218: }
04219:
04220: /**
04221: * Sets the color associated with the vertex at
04222: * the specified index.
04223: * @param index the vertex index
04224: * @param color a vector containing the new color
04225: */
04226: void setColor(int index, Color4b color) {
04227: int offset = this .stride * index + colorOffset;
04228:
04229: boolean isLive = source != null && source.isLive();
04230: if (isLive) {
04231: geomLock.getLock();
04232: }
04233: dirtyFlag |= COLOR_CHANGED;
04234: colorChanged = 0xffff;
04235: this .vertexData[offset] = (color.x * 0xff) * ByteToFloatScale;
04236: this .vertexData[offset + 1] = (color.y * 0xff)
04237: * ByteToFloatScale;
04238: this .vertexData[offset + 2] = (color.z * 0xff)
04239: * ByteToFloatScale;
04240: this .vertexData[offset + 3] = ((color.w & 0xff) * ByteToFloatScale)
04241: * lastAlpha[0];
04242:
04243: if (isLive) {
04244: geomLock.unLock();
04245: sendDataChangedMessage(false);
04246: }
04247:
04248: }
04249:
04250: /**
04251: * Sets the colors associated with the vertices starting at
04252: * the specified index.
04253: * @param index the vertex index
04254: * @param colors an array of 3*n or 4*n values containing n new colors
04255: */
04256: void setColors(int index, float colors[]) {
04257: int offset = this .stride * index + colorOffset;
04258: int i, j, num = colors.length;
04259:
04260: boolean isLive = source != null && source.isLive();
04261: if (isLive) {
04262: geomLock.getLock();
04263: }
04264: dirtyFlag |= COLOR_CHANGED;
04265: colorChanged = 0xffff;
04266:
04267: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
04268: for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
04269: this .vertexData[j] = colors[i];
04270: this .vertexData[j + 1] = colors[i + 1];
04271: this .vertexData[j + 2] = colors[i + 2];
04272: this .vertexData[j + 3] = colors[i + 3] * lastAlpha[0];
04273: }
04274: } else {
04275: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
04276: this .vertexData[j] = colors[i];
04277: this .vertexData[j + 1] = colors[i + 1];
04278: this .vertexData[j + 2] = colors[i + 2];
04279: this .vertexData[j + 3] = lastAlpha[0];
04280: }
04281: }
04282:
04283: if (isLive) {
04284: geomLock.unLock();
04285: sendDataChangedMessage(false);
04286: }
04287:
04288: }
04289:
04290: /**
04291: * Sets the colors associated with the vertices starting at
04292: * the specified index.
04293: * @param index the vertex index
04294: * @param colors an array of 3*n or 4*n values containing n new colors
04295: */
04296: void setColors(int index, byte colors[]) {
04297: int offset = this .stride * index + colorOffset;
04298: int i, j, num = colors.length;
04299:
04300: boolean isLive = source != null && source.isLive();
04301: if (isLive) {
04302: geomLock.getLock();
04303: }
04304: dirtyFlag |= COLOR_CHANGED;
04305: colorChanged = 0xffff;
04306:
04307: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
04308: for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
04309: this .vertexData[j] = (colors[i] & 0xff)
04310: * ByteToFloatScale;
04311: this .vertexData[j + 1] = (colors[i + 1] & 0xff)
04312: * ByteToFloatScale;
04313: this .vertexData[j + 2] = (colors[i + 2] & 0xff)
04314: * ByteToFloatScale;
04315: this .vertexData[j + 3] = ((colors[i + 3] & 0xff) * ByteToFloatScale)
04316: * lastAlpha[0];
04317: }
04318: } else {
04319: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
04320: this .vertexData[j] = (colors[i] & 0xff)
04321: * ByteToFloatScale;
04322: this .vertexData[j + 1] = (colors[i + 1] & 0xff)
04323: * ByteToFloatScale;
04324: this .vertexData[j + 2] = (colors[i + 2] & 0xff)
04325: * ByteToFloatScale;
04326: this .vertexData[j + 3] = lastAlpha[0];
04327: }
04328: }
04329:
04330: if (isLive) {
04331: geomLock.unLock();
04332: sendDataChangedMessage(false);
04333: }
04334:
04335: }
04336:
04337: /**
04338: * Sets the colors associated with the vertices starting at
04339: * the specified index.
04340: * @param index the vertex index
04341: * @param colors an array of vectors containing new colors
04342: */
04343: void setColors(int index, Color3f colors[]) {
04344: int offset = this .stride * index + colorOffset;
04345: int i, j, num = colors.length;
04346:
04347: boolean isLive = source != null && source.isLive();
04348: if (isLive) {
04349: geomLock.getLock();
04350: }
04351: dirtyFlag |= COLOR_CHANGED;
04352: colorChanged = 0xffff;
04353:
04354: for (i = 0, j = offset; i < num; i++, j += this .stride) {
04355: this .vertexData[j] = colors[i].x;
04356: this .vertexData[j + 1] = colors[i].y;
04357: this .vertexData[j + 2] = colors[i].z;
04358: this .vertexData[j + 3] = lastAlpha[0];
04359: }
04360: if (isLive) {
04361: geomLock.unLock();
04362: sendDataChangedMessage(false);
04363: }
04364:
04365: }
04366:
04367: /**
04368: * Sets the colors associated with the vertices starting at
04369: * the specified index.
04370: * @param index the vertex index
04371: * @param colors an array of vectors containing new colors
04372: */
04373: void setColors(int index, Color4f colors[]) {
04374: int offset = this .stride * index + colorOffset;
04375: int i, j, num = colors.length;
04376: boolean isLive = source != null && source.isLive();
04377: if (isLive) {
04378: geomLock.getLock();
04379: }
04380: dirtyFlag |= COLOR_CHANGED;
04381: colorChanged = 0xffff;
04382:
04383: for (i = 0, j = offset; i < num; i++, j += this .stride) {
04384: this .vertexData[j] = colors[i].x;
04385: this .vertexData[j + 1] = colors[i].y;
04386: this .vertexData[j + 2] = colors[i].z;
04387: this .vertexData[j + 3] = colors[i].w * lastAlpha[0];
04388: }
04389: if (isLive) {
04390: geomLock.unLock();
04391: sendDataChangedMessage(false);
04392: }
04393:
04394: }
04395:
04396: /**
04397: * Sets the colors associated with the vertices starting at
04398: * the specified index.
04399: * @param index the vertex index
04400: * @param colors an array of vectors containing new colors
04401: */
04402: void setColors(int index, Color3b colors[]) {
04403: int offset = this .stride * index + colorOffset;
04404: int i, j, num = colors.length;
04405: boolean isLive = source != null && source.isLive();
04406: if (isLive) {
04407: geomLock.getLock();
04408: }
04409: dirtyFlag |= COLOR_CHANGED;
04410: colorChanged = 0xffff;
04411: for (i = 0, j = offset; i < num; i++, j += this .stride) {
04412: this .vertexData[j] = (colors[i].x & 0xff)
04413: * ByteToFloatScale;
04414: this .vertexData[j + 1] = (colors[i].y & 0xff)
04415: * ByteToFloatScale;
04416: this .vertexData[j + 2] = (colors[i].z & 0xff)
04417: * ByteToFloatScale;
04418: this .vertexData[j + 3] = lastAlpha[0];
04419: }
04420:
04421: if (isLive) {
04422: geomLock.unLock();
04423: sendDataChangedMessage(false);
04424: }
04425: }
04426:
04427: /**
04428: * Sets the colors associated with the vertices starting at
04429: * the specified index.
04430: * @param index the vertex index
04431: * @param colors an array of vectors containing new colors
04432: */
04433: void setColors(int index, Color4b colors[]) {
04434: int offset = this .stride * index + colorOffset;
04435: int i, j, num = colors.length;
04436:
04437: boolean isLive = source != null && source.isLive();
04438: if (isLive) {
04439: geomLock.getLock();
04440: }
04441: dirtyFlag |= COLOR_CHANGED;
04442: colorChanged = 0xffff;
04443:
04444: for (i = 0, j = offset; i < num; i++, j += this .stride) {
04445: this .vertexData[j] = (colors[i].x & 0xff)
04446: * ByteToFloatScale;
04447: this .vertexData[j + 1] = (colors[i].y & 0xff)
04448: * ByteToFloatScale;
04449: this .vertexData[j + 2] = (colors[i].z & 0xff)
04450: * ByteToFloatScale;
04451: this .vertexData[j + 3] = ((colors[i].w & 0xff) * ByteToFloatScale)
04452: * lastAlpha[0];
04453: }
04454:
04455: if (isLive) {
04456: geomLock.unLock();
04457: sendDataChangedMessage(false);
04458: }
04459:
04460: }
04461:
04462: /**
04463: * Sets the colors associated with the vertices starting at
04464: * the specified index for this object using data in <code>color</code>s
04465: * starting at index <code>start</code> for <code>length</code> colors.
04466: * @param index the vertex index
04467: * @param colors an array of 3*n or 4*n values containing n new colors
04468: * @param start starting color index of data in <code>colors</code>.
04469: * @param length number of colors to be copied.
04470: */
04471: void setColors(int index, float colors[], int start, int length) {
04472: int offset = this .stride * index + colorOffset;
04473: int i, j;
04474: boolean isLive = source != null && source.isLive();
04475: if (isLive) {
04476: geomLock.getLock();
04477: }
04478: dirtyFlag |= COLOR_CHANGED;
04479: colorChanged = 0xffff;
04480:
04481: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
04482: for (i = start * 4, j = offset; i < (start + length) * 4; i += 4, j += this .stride) {
04483: this .vertexData[j] = colors[i];
04484: this .vertexData[j + 1] = colors[i + 1];
04485: this .vertexData[j + 2] = colors[i + 2];
04486: this .vertexData[j + 3] = colors[i + 3] * lastAlpha[0];
04487: }
04488: } else {
04489: for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
04490: this .vertexData[j] = colors[i];
04491: this .vertexData[j + 1] = colors[i + 1];
04492: this .vertexData[j + 2] = colors[i + 2];
04493: this .vertexData[j + 3] = lastAlpha[0];
04494: }
04495: }
04496:
04497: if (isLive) {
04498: geomLock.unLock();
04499: sendDataChangedMessage(false);
04500: }
04501:
04502: }
04503:
04504: /**
04505: * Sets the colors associated with the vertices starting at
04506: * the specified index for this object using data in <code>color</code>s
04507: * starting at index <code>start</code> for <code>length</code> colors.
04508: * @param index the vertex index
04509: * @param colors an array of 3*n or 4*n values containing n new colors
04510: * @param start starting color index of data in <code>colors</code>.
04511: * @param length number of colors to be copied.
04512: */
04513: void setColors(int index, byte colors[], int start, int length) {
04514: int offset = this .stride * index + colorOffset;
04515: int i, j;
04516:
04517: boolean isLive = source != null && source.isLive();
04518: if (isLive) {
04519: geomLock.getLock();
04520: }
04521: dirtyFlag |= COLOR_CHANGED;
04522: colorChanged = 0xffff;
04523:
04524: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
04525: for (i = start * 4, j = offset; i < (start + length) * 4; i += 4, j += this .stride) {
04526: this .vertexData[j] = (colors[i] & 0xff)
04527: * ByteToFloatScale;
04528: this .vertexData[j + 1] = (colors[i + 1] & 0xff)
04529: * ByteToFloatScale;
04530: this .vertexData[j + 2] = (colors[i + 2] & 0xff)
04531: * ByteToFloatScale;
04532: this .vertexData[j + 3] = ((colors[i + 3] & 0xff) * ByteToFloatScale)
04533: * lastAlpha[0];
04534: }
04535: } else {
04536: for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
04537: this .vertexData[j] = (colors[i] & 0xff)
04538: * ByteToFloatScale;
04539: this .vertexData[j + 1] = (colors[i + 1] & 0xff)
04540: * ByteToFloatScale;
04541: this .vertexData[j + 2] = (colors[i + 2] & 0xff)
04542: * ByteToFloatScale;
04543: this .vertexData[j + 3] = lastAlpha[0];
04544: }
04545: }
04546:
04547: if (isLive) {
04548: geomLock.unLock();
04549: sendDataChangedMessage(false);
04550: }
04551:
04552: }
04553:
04554: /**
04555: * Sets the colors associated with the vertices starting at
04556: * the specified index for this object using data in <code>color</code>s
04557: * starting at index <code>start</code> for <code>length</code> colors.
04558: * @param index the vertex index
04559: * @param colors an array of 3*n or 4*n values containing n new colors
04560: * @param start starting color index of data in <code>colors</code>.
04561: * @param length number of colors to be copied.
04562: */
04563: void setColors(int index, Color3f colors[], int start, int length) {
04564: int offset = this .stride * index + colorOffset;
04565: int i, j;
04566: boolean isLive = source != null && source.isLive();
04567: if (isLive) {
04568: geomLock.getLock();
04569: }
04570: dirtyFlag |= COLOR_CHANGED;
04571: colorChanged = 0xffff;
04572:
04573: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04574: this .vertexData[j] = colors[i].x;
04575: this .vertexData[j + 1] = colors[i].y;
04576: this .vertexData[j + 2] = colors[i].z;
04577: this .vertexData[j + 3] = lastAlpha[0];
04578: }
04579:
04580: if (isLive) {
04581: geomLock.unLock();
04582: sendDataChangedMessage(false);
04583: }
04584:
04585: }
04586:
04587: /**
04588: * Sets the colors associated with the vertices starting at
04589: * the specified index for this object using data in <code>color</code>s
04590: * starting at index <code>start</code> for <code>length</code> colors.
04591: * @param index the vertex index
04592: * @param colors an array of 3*n or 4*n values containing n new colors
04593: * @param start starting color index of data in <code>colors</code>.
04594: * @param length number of colors to be copied.
04595: */
04596: void setColors(int index, Color4f colors[], int start, int length) {
04597: int offset = this .stride * index + colorOffset;
04598: int i, j;
04599: boolean isLive = source != null && source.isLive();
04600: if (isLive) {
04601: geomLock.getLock();
04602: }
04603: dirtyFlag |= COLOR_CHANGED;
04604: colorChanged = 0xffff;
04605:
04606: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04607: this .vertexData[j] = colors[i].x;
04608: this .vertexData[j + 1] = colors[i].y;
04609: this .vertexData[j + 2] = colors[i].z;
04610: this .vertexData[j + 3] = colors[i].w * lastAlpha[0];
04611: }
04612:
04613: if (isLive) {
04614: geomLock.unLock();
04615: sendDataChangedMessage(false);
04616: }
04617:
04618: }
04619:
04620: /**
04621: * Sets the colors associated with the vertices starting at
04622: * the specified index for this object using data in <code>color</code>s
04623: * starting at index <code>start</code> for <code>length</code> colors.
04624: * @param index the vertex index
04625: * @param colors an array of 3*n or 4*n values containing n new colors
04626: * @param start starting color index of data in <code>colors</code>.
04627: * @param length number of colors to be copied.
04628: */
04629: void setColors(int index, Color3b colors[], int start, int length) {
04630: int offset = this .stride * index + colorOffset;
04631: int i, j;
04632: boolean isLive = source != null && source.isLive();
04633: if (isLive) {
04634: geomLock.getLock();
04635: }
04636: dirtyFlag |= COLOR_CHANGED;
04637: colorChanged = 0xffff;
04638:
04639: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04640: this .vertexData[j] = (colors[i].x & 0xff)
04641: * ByteToFloatScale;
04642: this .vertexData[j + 1] = (colors[i].y & 0xff)
04643: * ByteToFloatScale;
04644: this .vertexData[j + 2] = (colors[i].z & 0xff)
04645: * ByteToFloatScale;
04646: this .vertexData[j + 3] = lastAlpha[0];
04647: }
04648:
04649: if (isLive) {
04650: geomLock.unLock();
04651: sendDataChangedMessage(false);
04652: }
04653:
04654: }
04655:
04656: /**
04657: * Sets the colors associated with the vertices starting at
04658: * the specified index for this object using data in <code>color</code>s
04659: * starting at index <code>start</code> for <code>length</code> colors.
04660: * @param index the vertex index
04661: * @param colors an array of 3*n or 4*n values containing n new colors
04662: * @param start starting color index of data in <code>colors</code>.
04663: * @param length number of colors to be copied.
04664: */
04665: void setColors(int index, Color4b colors[], int start, int length) {
04666: int offset = this .stride * index + colorOffset;
04667: int i, j;
04668: boolean isLive = source != null && source.isLive();
04669: if (isLive) {
04670: geomLock.getLock();
04671: }
04672: dirtyFlag |= COLOR_CHANGED;
04673: colorChanged = 0xffff;
04674:
04675: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04676: this .vertexData[j] = (colors[i].x & 0xff)
04677: * ByteToFloatScale;
04678: this .vertexData[j + 1] = (colors[i].y & 0xff)
04679: * ByteToFloatScale;
04680: this .vertexData[j + 2] = (colors[i].z & 0xff)
04681: * ByteToFloatScale;
04682: this .vertexData[j + 3] = ((colors[i].w & 0xff) * ByteToFloatScale)
04683: * lastAlpha[0];
04684: }
04685:
04686: if (isLive) {
04687: geomLock.unLock();
04688: sendDataChangedMessage(false);
04689: }
04690:
04691: }
04692:
04693: /**
04694: * Sets the normal associated with the vertex at
04695: * the specified index.
04696: * @param index the vertex index
04697: * @param normal the new normal
04698: */
04699: void setNormal(int index, float normal[]) {
04700: int offset = this .stride * index + normalOffset;
04701: boolean isLive = source != null && source.isLive();
04702: if (isLive) {
04703: geomLock.getLock();
04704: }
04705: this .vertexData[offset] = normal[0];
04706: this .vertexData[offset + 1] = normal[1];
04707: this .vertexData[offset + 2] = normal[2];
04708:
04709: if (isLive) {
04710: geomLock.unLock();
04711: sendDataChangedMessage(false);
04712: }
04713:
04714: }
04715:
04716: /**
04717: * Sets the normal associated with the vertex at
04718: * the specified index.
04719: * @param index the vertex index
04720: * @param normal the vector containing the new normal
04721: */
04722: void setNormal(int index, Vector3f normal) {
04723: int offset = this .stride * index + normalOffset;
04724: boolean isLive = source != null && source.isLive();
04725: if (isLive) {
04726: geomLock.getLock();
04727: }
04728: dirtyFlag |= NORMAL_CHANGED;
04729: this .vertexData[offset] = normal.x;
04730: this .vertexData[offset + 1] = normal.y;
04731: this .vertexData[offset + 2] = normal.z;
04732:
04733: if (isLive) {
04734: geomLock.unLock();
04735: sendDataChangedMessage(false);
04736: }
04737:
04738: }
04739:
04740: /**
04741: * Sets the normals associated with the vertices starting at
04742: * the specified index.
04743: * @param index the vertex index
04744: * @param normals the new normals
04745: */
04746: void setNormals(int index, float normals[]) {
04747: int offset = this .stride * index + normalOffset;
04748: int i, j, num = normals.length;
04749: boolean isLive = source != null && source.isLive();
04750: if (isLive) {
04751: geomLock.getLock();
04752: }
04753: dirtyFlag |= NORMAL_CHANGED;
04754: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
04755: this .vertexData[j] = normals[i];
04756: this .vertexData[j + 1] = normals[i + 1];
04757: this .vertexData[j + 2] = normals[i + 2];
04758: }
04759: if (isLive) {
04760: geomLock.unLock();
04761: sendDataChangedMessage(false);
04762: }
04763:
04764: }
04765:
04766: /**
04767: * Sets the normals associated with the vertices starting at
04768: * the specified index.
04769: * @param index the vertex index
04770: * @param normals the vector containing the new normals
04771: */
04772: void setNormals(int index, Vector3f normals[]) {
04773: int offset = this .stride * index + normalOffset;
04774: int i, j, num = normals.length;
04775: boolean isLive = source != null && source.isLive();
04776: if (isLive) {
04777: geomLock.getLock();
04778: }
04779: dirtyFlag |= NORMAL_CHANGED;
04780: for (i = 0, j = offset; i < num; i++, j += this .stride) {
04781: this .vertexData[j] = normals[i].x;
04782: this .vertexData[j + 1] = normals[i].y;
04783: this .vertexData[j + 2] = normals[i].z;
04784: }
04785: if (isLive) {
04786: geomLock.unLock();
04787: sendDataChangedMessage(false);
04788: }
04789:
04790: }
04791:
04792: /**
04793: * Sets the normals associated with the vertices starting at
04794: * the specified index for this object using data in <code>normals</code>
04795: * starting at index <code>start</code> and ending at index <code>start+length</code>.
04796: * @param index the vertex index
04797: * @param normals the new normals
04798: * @param start starting normal index of data in <code>colors</code> .
04799: * @param length number of normals to be copied.
04800: */
04801: void setNormals(int index, float normals[], int start, int length) {
04802: int offset = this .stride * index + normalOffset;
04803: int i, j;
04804: boolean isLive = source != null && source.isLive();
04805: if (isLive) {
04806: geomLock.getLock();
04807: }
04808: dirtyFlag |= NORMAL_CHANGED;
04809: for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
04810: this .vertexData[j] = normals[i];
04811: this .vertexData[j + 1] = normals[i + 1];
04812: this .vertexData[j + 2] = normals[i + 2];
04813: }
04814: if (isLive) {
04815: geomLock.unLock();
04816: sendDataChangedMessage(false);
04817: }
04818:
04819: }
04820:
04821: /**
04822: * Sets the normals associated with the vertices starting at
04823: * the specified index for this object using data in <code>normals</code>
04824: * starting at index <code>start</code> and ending at index <code>start+length</code>.
04825: * @param index the vertex index
04826: * @param normals the new normals
04827: * @param start starting normal index of data in <code>colors</code> .
04828: * @param length number of normals to be copied.
04829: */
04830: void setNormals(int index, Vector3f normals[], int start, int length) {
04831: int offset = this .stride * index + normalOffset;
04832: int i, j;
04833: boolean isLive = source != null && source.isLive();
04834: if (isLive) {
04835: geomLock.getLock();
04836: }
04837: dirtyFlag |= NORMAL_CHANGED;
04838: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04839: this .vertexData[j] = normals[i].x;
04840: this .vertexData[j + 1] = normals[i].y;
04841: this .vertexData[j + 2] = normals[i].z;
04842: }
04843: if (isLive) {
04844: geomLock.unLock();
04845: sendDataChangedMessage(false);
04846: }
04847:
04848: }
04849:
04850: /**
04851: * Sets the texture coordinates associated with the vertices starting at
04852: * the specified index for this object using data in <code>texCoords</code>
04853: * starting at index <code>start</code> and ending at index <code>start+length</code>.
04854: * @param index the vertex index
04855: * @param texCoords the new texture coordinates
04856: * @param start starting texture coordinate index of data in <code>texCoords</code> .
04857: * @param length number of texture Coordinates to be copied.
04858: */
04859: void setTextureCoordinates(int texCoordSet, int index,
04860: float texCoords[], int start, int length) {
04861:
04862: if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
04863: throw new IllegalStateException(J3dI18N
04864: .getString("GeometryArray82"));
04865:
04866: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
04867: throw new ArrayIndexOutOfBoundsException(J3dI18N
04868: .getString("GeometryArray79"));
04869:
04870: int offset = this .stride * index + textureOffset + texCoordSet
04871: * texCoordStride;
04872: int i, j, k;
04873: boolean isLive = source != null && source.isLive();
04874: if (isLive) {
04875: geomLock.getLock();
04876: }
04877: dirtyFlag |= TEXTURE_CHANGED;
04878:
04879: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
04880: for (i = start * 4, j = offset, k = 0; k < length; j += this .stride, k++) {
04881: this .vertexData[j] = texCoords[i++];
04882: this .vertexData[j + 1] = texCoords[i++];
04883: this .vertexData[j + 2] = texCoords[i++];
04884: this .vertexData[j + 3] = texCoords[i++];
04885: }
04886: } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
04887: for (i = start * 3, j = offset, k = 0; k < length; j += this .stride, k++) {
04888: this .vertexData[j] = texCoords[i++];
04889: this .vertexData[j + 1] = texCoords[i++];
04890: this .vertexData[j + 2] = texCoords[i++];
04891: }
04892: } else {
04893: for (i = start * 2, j = offset, k = 0; k < length; j += this .stride, k++) {
04894: this .vertexData[j] = texCoords[i++];
04895: this .vertexData[j + 1] = texCoords[i++];
04896: }
04897: }
04898: if (isLive) {
04899: geomLock.unLock();
04900: sendDataChangedMessage(false);
04901: }
04902:
04903: }
04904:
04905: /**
04906: * Sets the texture coordinates associated with the vertices starting at
04907: * the specified index for this object using data in <code>texCoords</code>
04908: * starting at index <code>start</code> and ending at index <code>start+length</code>.
04909: * @param index the vertex index
04910: * @param texCoords the new texture coordinates
04911: * @param start starting texture coordinate index of data in <code>texCoords</code> .
04912: * @param length number of texture Coordinates to be copied.
04913: */
04914: void setTextureCoordinates(int texCoordSet, int index,
04915: Point2f texCoords[], int start, int length) {
04916:
04917: if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
04918: throw new IllegalStateException(J3dI18N
04919: .getString("GeometryArray82"));
04920:
04921: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
04922: throw new ArrayIndexOutOfBoundsException(J3dI18N
04923: .getString("GeometryArray79"));
04924:
04925: int offset = this .stride * index + textureOffset + texCoordSet
04926: * texCoordStride;
04927: int i, j;
04928:
04929: boolean isLive = source != null && source.isLive();
04930: if (isLive) {
04931: geomLock.getLock();
04932: }
04933: dirtyFlag |= TEXTURE_CHANGED;
04934:
04935: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04936: this .vertexData[j] = texCoords[i].x;
04937: this .vertexData[j + 1] = texCoords[i].y;
04938: }
04939: if (isLive) {
04940: geomLock.unLock();
04941: sendDataChangedMessage(false);
04942: }
04943:
04944: }
04945:
04946: /**
04947: * Sets the texture coordinates associated with the vertices starting at
04948: * the specified index for this object using data in <code>texCoords</code>
04949: * starting at index <code>start</code> and ending at index <code>start+length</code>.
04950: * @param index the vertex index
04951: * @param texCoords the new texture coordinates
04952: * @param start starting texture coordinate index of data in <code>texCoords</code> .
04953: * @param length number of texture Coordinates to be copied.
04954: */
04955: void setTextureCoordinates(int texCoordSet, int index,
04956: Point3f texCoords[], int start, int length) {
04957:
04958: if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
04959: throw new IllegalStateException(J3dI18N
04960: .getString("GeometryArray82"));
04961:
04962: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
04963: throw new ArrayIndexOutOfBoundsException(J3dI18N
04964: .getString("GeometryArray79"));
04965:
04966: int offset = this .stride * index + textureOffset + texCoordSet
04967: * texCoordStride;
04968: int i, j;
04969: boolean isLive = source != null && source.isLive();
04970: if (isLive) {
04971: geomLock.getLock();
04972: }
04973: dirtyFlag |= TEXTURE_CHANGED;
04974:
04975: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04976: this .vertexData[j] = texCoords[i].x;
04977: this .vertexData[j + 1] = texCoords[i].y;
04978: this .vertexData[j + 2] = texCoords[i].z;
04979: }
04980: if (isLive) {
04981: geomLock.unLock();
04982: sendDataChangedMessage(false);
04983: }
04984:
04985: }
04986:
04987: /**
04988: * Sets the texture coordinates associated with the vertices starting at
04989: * the specified index for this object using data in <code>texCoords</code>
04990: * starting at index <code>start</code> and ending at index <code>start+length</code>.
04991: * @param index the vertex index
04992: * @param texCoords the new texture coordinates
04993: * @param start starting texture coordinate index of data in <code>texCoords</code> .
04994: * @param length number of texture Coordinates to be copied.
04995: */
04996: void setTextureCoordinates(int texCoordSet, int index,
04997: TexCoord2f texCoords[], int start, int length) {
04998: boolean isLive = source != null && source.isLive();
04999: if (isLive) {
05000: geomLock.getLock();
05001: }
05002: dirtyFlag |= TEXTURE_CHANGED;
05003: if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
05004: throw new IllegalStateException(J3dI18N
05005: .getString("GeometryArray82"));
05006:
05007: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
05008: throw new ArrayIndexOutOfBoundsException(J3dI18N
05009: .getString("GeometryArray79"));
05010:
05011: int offset = this .stride * index + textureOffset + texCoordSet
05012: * texCoordStride;
05013: int i, j;
05014:
05015: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
05016: this .vertexData[j] = texCoords[i].x;
05017: this .vertexData[j + 1] = texCoords[i].y;
05018: }
05019: if (isLive) {
05020: geomLock.unLock();
05021: sendDataChangedMessage(false);
05022: }
05023:
05024: }
05025:
05026: /**
05027: * Sets the texture coordinates associated with the vertices starting at
05028: * the specified index for this object using data in <code>texCoords</code>
05029: * starting at index <code>start</code> and ending at index <code>start+length</code>.
05030: * @param index the vertex index
05031: * @param texCoords the new texture coordinates
05032: * @param start starting texture coordinate index of data in <code>texCoords</code> .
05033: * @param length number of texture Coordinates to be copied.
05034: */
05035: void setTextureCoordinates(int texCoordSet, int index,
05036: TexCoord3f texCoords[], int start, int length) {
05037: boolean isLive = source != null && source.isLive();
05038: if (isLive) {
05039: geomLock.getLock();
05040: }
05041: dirtyFlag |= TEXTURE_CHANGED;
05042:
05043: if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
05044: throw new IllegalStateException(J3dI18N
05045: .getString("GeometryArray82"));
05046:
05047: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
05048: throw new ArrayIndexOutOfBoundsException(J3dI18N
05049: .getString("GeometryArray79"));
05050:
05051: int offset = this .stride * index + textureOffset + texCoordSet
05052: * texCoordStride;
05053: int i, j;
05054:
05055: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
05056: this .vertexData[j] = texCoords[i].x;
05057: this .vertexData[j + 1] = texCoords[i].y;
05058: this .vertexData[j + 2] = texCoords[i].z;
05059: }
05060: if (isLive) {
05061: geomLock.unLock();
05062: sendDataChangedMessage(false);
05063: }
05064: }
05065:
05066: /**
05067: * Sets the texture coordinates associated with the vertices starting at
05068: * the specified index for this object using data in <code>texCoords</code>
05069: * starting at index <code>start</code> and ending at index <code>start+length</code>.
05070: * @param index the vertex index
05071: * @param texCoords the new texture coordinates
05072: * @param start starting texture coordinate index of data in <code>texCoords</code> .
05073: * @param length number of texture Coordinates to be copied.
05074: */
05075: void setTextureCoordinates(int texCoordSet, int index,
05076: TexCoord4f texCoords[], int start, int length) {
05077: boolean isLive = source != null && source.isLive();
05078: if (isLive) {
05079: geomLock.getLock();
05080: }
05081: dirtyFlag |= TEXTURE_CHANGED;
05082:
05083: if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
05084: throw new IllegalStateException(J3dI18N
05085: .getString("GeometryArray82"));
05086:
05087: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
05088: throw new ArrayIndexOutOfBoundsException(J3dI18N
05089: .getString("GeometryArray79"));
05090:
05091: int offset = this .stride * index + textureOffset + texCoordSet
05092: * texCoordStride;
05093: int i, j;
05094:
05095: for (i = start, j = offset; i < start + length; i++, j += this .stride) {
05096: this .vertexData[j] = texCoords[i].x;
05097: this .vertexData[j + 1] = texCoords[i].y;
05098: this .vertexData[j + 2] = texCoords[i].z;
05099: this .vertexData[j + 3] = texCoords[i].w;
05100: }
05101: if (isLive) {
05102: geomLock.unLock();
05103: sendDataChangedMessage(false);
05104: }
05105: }
05106:
05107: /**
05108: * Sets the vertex attribute associated with the vertex at the
05109: * specified index in the specified vertex attribute number for
05110: * this object.
05111: *
05112: * @param vertexAttrNum vertex attribute number in this geometry array
05113: * @param index destination vertex index in this geometry array
05114: * @param vertexAttr the Point2f containing the new vertex attribute
05115: */
05116: void setVertexAttr(int vertexAttrNum, int index, Point2f vertexAttr) {
05117:
05118: int offset = this .stride * index
05119: + vertexAttrOffsets[vertexAttrNum];
05120: boolean isLive = source != null && source.isLive();
05121: if (isLive) {
05122: geomLock.getLock();
05123: }
05124: dirtyFlag |= VATTR_CHANGED;
05125:
05126: this .vertexData[offset] = vertexAttr.x;
05127: this .vertexData[offset + 1] = vertexAttr.y;
05128:
05129: if (isLive) {
05130: geomLock.unLock();
05131: sendDataChangedMessage(false);
05132: }
05133: }
05134:
05135: /**
05136: * Sets the vertex attribute associated with the vertex at the
05137: * specified index in the specified vertex attribute number for
05138: * this object.
05139: *
05140: * @param vertexAttrNum vertex attribute number in this geometry array
05141: * @param index destination vertex index in this geometry array
05142: * @param vertexAttr the Point3f containing the new vertex attribute
05143: */
05144: void setVertexAttr(int vertexAttrNum, int index, Point3f vertexAttr) {
05145:
05146: int offset = this .stride * index
05147: + vertexAttrOffsets[vertexAttrNum];
05148: boolean isLive = source != null && source.isLive();
05149: if (isLive) {
05150: geomLock.getLock();
05151: }
05152: dirtyFlag |= VATTR_CHANGED;
05153:
05154: this .vertexData[offset] = vertexAttr.x;
05155: this .vertexData[offset + 1] = vertexAttr.y;
05156: this .vertexData[offset + 2] = vertexAttr.z;
05157:
05158: if (isLive) {
05159: geomLock.unLock();
05160: sendDataChangedMessage(false);
05161: }
05162: }
05163:
05164: /**
05165: * Sets the vertex attribute associated with the vertex at the
05166: * specified index in the specified vertex attribute number for
05167: * this object.
05168: *
05169: * @param vertexAttrNum vertex attribute number in this geometry array
05170: * @param index destination vertex index in this geometry array
05171: * @param vertexAttr the Point4f containing the new vertex attribute
05172: */
05173: void setVertexAttr(int vertexAttrNum, int index, Point4f vertexAttr) {
05174:
05175: int offset = this .stride * index
05176: + vertexAttrOffsets[vertexAttrNum];
05177: boolean isLive = source != null && source.isLive();
05178: if (isLive) {
05179: geomLock.getLock();
05180: }
05181: dirtyFlag |= VATTR_CHANGED;
05182:
05183: this .vertexData[offset] = vertexAttr.x;
05184: this .vertexData[offset + 1] = vertexAttr.y;
05185: this .vertexData[offset + 2] = vertexAttr.z;
05186: this .vertexData[offset + 3] = vertexAttr.w;
05187:
05188: if (isLive) {
05189: geomLock.unLock();
05190: sendDataChangedMessage(false);
05191: }
05192: }
05193:
05194: /**
05195: * Sets the vertex attributes associated with the vertices
05196: * starting at the specified index in the specified vertex
05197: * attribute number for this object using data in
05198: * <code>vertexAttrs</code> starting at index <code>start</code> and
05199: * ending at index <code>start+length</code>.
05200: *
05201: * @param index starting destination vertex index in this geometry array
05202: * @param vertexAttrs source array of 1*n, 2*n, 3*n, or 4*n values
05203: * containing n new vertex attributes
05204: * @param start starting source vertex index in <code>vertexAttrs</code>
05205: * array.
05206: * @param length number of vertex attributes to be copied.
05207: */
05208: void setVertexAttrs(int vertexAttrNum, int index,
05209: float[] vertexAttrs, int start, int length) {
05210:
05211: int offset = this .stride * index
05212: + vertexAttrOffsets[vertexAttrNum];
05213: int size = vertexAttrSizes[vertexAttrNum];
05214: int i, j, k;
05215: boolean isLive = source != null && source.isLive();
05216: if (isLive) {
05217: geomLock.getLock();
05218: }
05219: dirtyFlag |= VATTR_CHANGED;
05220:
05221: for (i = start * size, j = offset, k = 0; k < length; i += size, j += this .stride, k++) {
05222: for (int ii = 0; ii < size; ii++) {
05223: this .vertexData[j + ii] = vertexAttrs[i + ii];
05224: }
05225: }
05226:
05227: if (isLive) {
05228: geomLock.unLock();
05229: sendDataChangedMessage(false);
05230: }
05231: }
05232:
05233: /**
05234: * Sets the vertex attributes associated with the vertices
05235: * starting at the specified index in the specified vertex
05236: * attribute number for this object using data in
05237: * <code>vertexAttrs</code> starting at index <code>start</code> and
05238: * ending at index <code>start+length</code>.
05239: *
05240: * @param vertexAttrNum vertex attribute number in this geometry array
05241: * @param index starting destination vertex index in this geometry array
05242: * @param vertexAttrs source array of Point2f objects containing new
05243: * vertex attributes
05244: * @param start starting source vertex index in <code>vertexAttrs</code>
05245: * array.
05246: * @param length number of vertex attributes to be copied.
05247: */
05248: void setVertexAttrs(int vertexAttrNum, int index,
05249: Point2f[] vertexAttrs, int start, int length) {
05250:
05251: int offset = this .stride * index
05252: + vertexAttrOffsets[vertexAttrNum];
05253: int i, j, k;
05254: boolean isLive = source != null && source.isLive();
05255: if (isLive) {
05256: geomLock.getLock();
05257: }
05258: dirtyFlag |= VATTR_CHANGED;
05259:
05260: for (i = start, j = offset, k = 0; k < length; i++, j += this .stride, k++) {
05261: this .vertexData[j] = vertexAttrs[i].x;
05262: this .vertexData[j + 1] = vertexAttrs[i].y;
05263: }
05264: if (isLive) {
05265: geomLock.unLock();
05266: sendDataChangedMessage(false);
05267: }
05268: }
05269:
05270: /**
05271: * Sets the vertex attributes associated with the vertices
05272: * starting at the specified index in the specified vertex
05273: * attribute number for this object using data in
05274: * <code>vertexAttrs</code> starting at index <code>start</code> and
05275: * ending at index <code>start+length</code>.
05276: *
05277: * @param vertexAttrNum vertex attribute number in this geometry array
05278: * @param index starting destination vertex index in this geometry array
05279: * @param vertexAttrs source array of Point3f objects containing new
05280: * vertex attributes
05281: * @param start starting source vertex index in <code>vertexAttrs</code>
05282: * array.
05283: * @param length number of vertex attributes to be copied.
05284: */
05285: void setVertexAttrs(int vertexAttrNum, int index,
05286: Point3f[] vertexAttrs, int start, int length) {
05287:
05288: int offset = this .stride * index
05289: + vertexAttrOffsets[vertexAttrNum];
05290: int i, j, k;
05291: boolean isLive = source != null && source.isLive();
05292: if (isLive) {
05293: geomLock.getLock();
05294: }
05295: dirtyFlag |= VATTR_CHANGED;
05296:
05297: for (i = start, j = offset, k = 0; k < length; i++, j += this .stride, k++) {
05298: this .vertexData[j] = vertexAttrs[i].x;
05299: this .vertexData[j + 1] = vertexAttrs[i].y;
05300: this .vertexData[j + 2] = vertexAttrs[i].z;
05301: }
05302: if (isLive) {
05303: geomLock.unLock();
05304: sendDataChangedMessage(false);
05305: }
05306: }
05307:
05308: /**
05309: * Sets the vertex attributes associated with the vertices
05310: * starting at the specified index in the specified vertex
05311: * attribute number for this object using data in
05312: * <code>vertexAttrs</code> starting at index <code>start</code> and
05313: * ending at index <code>start+length</code>.
05314: *
05315: * @param vertexAttrNum vertex attribute number in this geometry array
05316: * @param index starting destination vertex index in this geometry array
05317: * @param vertexAttrs source array of Point4f objects containing new
05318: * vertex attributes
05319: * @param start starting source vertex index in <code>vertexAttrs</code>
05320: * array.
05321: * @param length number of vertex attributes to be copied.
05322: */
05323: void setVertexAttrs(int vertexAttrNum, int index,
05324: Point4f[] vertexAttrs, int start, int length) {
05325:
05326: int offset = this .stride * index
05327: + vertexAttrOffsets[vertexAttrNum];
05328: int i, j, k;
05329:
05330: boolean isLive = source != null && source.isLive();
05331: if (isLive) {
05332: geomLock.getLock();
05333: }
05334: dirtyFlag |= VATTR_CHANGED;
05335:
05336: for (i = start, j = offset, k = 0; k < length; i++, j += this .stride, k++) {
05337: this .vertexData[j] = vertexAttrs[i].x;
05338: this .vertexData[j + 1] = vertexAttrs[i].y;
05339: this .vertexData[j + 2] = vertexAttrs[i].z;
05340: this .vertexData[j + 3] = vertexAttrs[i].w;
05341: }
05342: if (isLive) {
05343: geomLock.unLock();
05344: sendDataChangedMessage(false);
05345: }
05346: }
05347:
05348: /**
05349: * Gets the coordinate associated with the vertex at
05350: * the specified index.
05351: * @param index the vertex index
05352: * @param coordinate an array of 3 values that will receive the new coordinate
05353: */
05354: void getCoordinate(int index, float coordinate[]) {
05355: int offset = this .stride * index + coordinateOffset;
05356:
05357: coordinate[0] = this .vertexData[offset];
05358: coordinate[1] = this .vertexData[offset + 1];
05359: coordinate[2] = this .vertexData[offset + 2];
05360: }
05361:
05362: /**
05363: * Gets the coordinate associated with the vertex at
05364: * the specified index.
05365: * @param index the vertex index
05366: * @param coordinate an array of 3 values that will receive the new coordinate
05367: */
05368: void getCoordinate(int index, double coordinate[]) {
05369: int offset = this .stride * index + coordinateOffset;
05370:
05371: coordinate[0] = (double) this .vertexData[offset];
05372: coordinate[1] = (double) this .vertexData[offset + 1];
05373: coordinate[2] = (double) this .vertexData[offset + 2];
05374: }
05375:
05376: /**
05377: * Gets the coordinate associated with the vertex at
05378: * the specified index.
05379: * @param index the vertex index
05380: * @param coordinate a vector that will receive the new coordinate
05381: */
05382: void getCoordinate(int index, Point3f coordinate) {
05383: int offset = this .stride * index + coordinateOffset;
05384:
05385: coordinate.x = this .vertexData[offset];
05386: coordinate.y = this .vertexData[offset + 1];
05387: coordinate.z = this .vertexData[offset + 2];
05388: }
05389:
05390: /**
05391: * Gets the coordinate associated with the vertex at
05392: * the specified index.
05393: * @param index the vertex index
05394: * @param coordinate a vector that will receive the new coordinate
05395: */
05396: void getCoordinate(int index, Point3d coordinate) {
05397: int offset = this .stride * index + coordinateOffset;
05398:
05399: coordinate.x = (double) this .vertexData[offset];
05400: coordinate.y = (double) this .vertexData[offset + 1];
05401: coordinate.z = (double) this .vertexData[offset + 2];
05402: }
05403:
05404: /**
05405: * Gets the coordinates associated with the vertices starting at
05406: * the specified index.
05407: * @param index the vertex index
05408: * @param coordinates an array of 3*n values that will receive new coordinates
05409: */
05410: void getCoordinates(int index, float coordinates[]) {
05411: int offset = this .stride * index + coordinateOffset;
05412: int i, j, num = coordinates.length;
05413:
05414: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05415: coordinates[i] = this .vertexData[j];
05416: coordinates[i + 1] = this .vertexData[j + 1];
05417: coordinates[i + 2] = this .vertexData[j + 2];
05418: }
05419: }
05420:
05421: /**
05422: * Gets the coordinates associated with the vertices starting at
05423: * the specified index.
05424: * @param index the vertex index
05425: * @param coordinates an array of 3*n values that will receive new coordinates
05426: */
05427: void getCoordinates(int index, double coordinates[]) {
05428: int offset = this .stride * index + coordinateOffset;
05429: int i, j, num = coordinates.length;
05430:
05431: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05432: coordinates[i] = (double) this .vertexData[j];
05433: coordinates[i + 1] = (double) this .vertexData[j + 1];
05434: coordinates[i + 2] = (double) this .vertexData[j + 2];
05435: }
05436: }
05437:
05438: /**
05439: * Gets the coordinates associated with the vertices starting at
05440: * the specified index.
05441: * @param index the vertex index
05442: * @param coordinates an array of vectors that will receive new coordinates
05443: */
05444: void getCoordinates(int index, Point3f coordinates[]) {
05445: int offset = this .stride * index + coordinateOffset;
05446: int i, j, num = coordinates.length;
05447:
05448: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05449: coordinates[i].x = this .vertexData[j];
05450: coordinates[i].y = this .vertexData[j + 1];
05451: coordinates[i].z = this .vertexData[j + 2];
05452: }
05453: }
05454:
05455: /**
05456: * Gets the coordinates associated with the vertices starting at
05457: * the specified index.
05458: * @param index the vertex index
05459: * @param coordinates an array of vectors that will receive new coordinates
05460: */
05461: void getCoordinates(int index, Point3d coordinates[]) {
05462: int offset = this .stride * index + coordinateOffset;
05463: int i, j, num = coordinates.length;
05464:
05465: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05466: coordinates[i].x = (double) this .vertexData[j];
05467: coordinates[i].y = (double) this .vertexData[j + 1];
05468: coordinates[i].z = (double) this .vertexData[j + 2];
05469: }
05470: }
05471:
05472: /**
05473: * Gets the color associated with the vertex at
05474: * the specified index.
05475: * @param index the vertex index
05476: * @param color an array of 3 or 4 values that will receive the new color
05477: */
05478: void getColor(int index, float color[]) {
05479: int offset = this .stride * index + colorOffset;
05480:
05481: color[0] = this .vertexData[offset];
05482: color[1] = this .vertexData[offset + 1];
05483: color[2] = this .vertexData[offset + 2];
05484: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0)
05485: color[3] = this .vertexData[offset + 3] / lastAlpha[0];
05486: }
05487:
05488: /**
05489: * Gets the color associated with the vertex at
05490: * the specified index.
05491: * @param index the vertex index
05492: * @param color an array of 3 or 4 values that will receive the new color
05493: */
05494: void getColor(int index, byte color[]) {
05495: int offset = this .stride * index + colorOffset;
05496:
05497: color[0] = (byte) (this .vertexData[offset] * FloatToByteScale);
05498: color[1] = (byte) (this .vertexData[offset + 1] * FloatToByteScale);
05499: color[2] = (byte) (this .vertexData[offset + 2] * FloatToByteScale);
05500: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0)
05501: color[3] = (byte) ((this .vertexData[offset + 3] / lastAlpha[0]) * FloatToByteScale);
05502: }
05503:
05504: /**
05505: * Gets the color associated with the vertex at
05506: * the specified index.
05507: * @param index the vertex index
05508: * @param color a vector that will receive the new color
05509: */
05510: void getColor(int index, Color3f color) {
05511: int offset = this .stride * index + colorOffset;
05512:
05513: color.x = this .vertexData[offset];
05514: color.y = this .vertexData[offset + 1];
05515: color.z = this .vertexData[offset + 2];
05516: }
05517:
05518: /**
05519: * Gets the color associated with the vertex at
05520: * the specified index.
05521: * @param index the vertex index
05522: * @param color a vector that will receive the new color
05523: */
05524: void getColor(int index, Color4f color) {
05525: int offset = this .stride * index + colorOffset;
05526:
05527: color.x = this .vertexData[offset];
05528: color.y = this .vertexData[offset + 1];
05529: color.z = this .vertexData[offset + 2];
05530: color.w = this .vertexData[offset + 3] / lastAlpha[0];
05531: }
05532:
05533: /**
05534: * Gets the color associated with the vertex at
05535: * the specified index.
05536: * @param index the vertex index
05537: * @param color a vector that will receive the new color
05538: */
05539: void getColor(int index, Color3b color) {
05540: int offset = this .stride * index + colorOffset;
05541:
05542: color.x = (byte) (this .vertexData[offset] * FloatToByteScale);
05543: color.y = (byte) (this .vertexData[offset + 1] * FloatToByteScale);
05544: color.z = (byte) (this .vertexData[offset + 2] * FloatToByteScale);
05545: }
05546:
05547: /**
05548: * Gets the color associated with the vertex at
05549: * the specified index.
05550: * @param index the vertex index
05551: * @param color a vector that will receive the new color
05552: */
05553: void getColor(int index, Color4b color) {
05554: int offset = this .stride * index + colorOffset;
05555:
05556: color.x = (byte) (this .vertexData[offset] * FloatToByteScale);
05557: color.y = (byte) (this .vertexData[offset + 1] * FloatToByteScale);
05558: color.z = (byte) (this .vertexData[offset + 2] * FloatToByteScale);
05559: color.w = (byte) ((this .vertexData[offset + 3] / lastAlpha[0]) * FloatToByteScale);
05560: }
05561:
05562: /**
05563: * Gets the colors associated with the vertices starting at
05564: * the specified index.
05565: * @param index the vertex index
05566: * @param colors an array of 3*n or 4*n values that will receive n new colors
05567: */
05568: void getColors(int index, float colors[]) {
05569: int offset = this .stride * index + colorOffset;
05570: int i, j, num = colors.length;
05571: float val = 1.0f / lastAlpha[0];
05572:
05573: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
05574: for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
05575: colors[i] = this .vertexData[j];
05576: colors[i + 1] = this .vertexData[j + 1];
05577: colors[i + 2] = this .vertexData[j + 2];
05578: colors[i + 3] = this .vertexData[j + 3] * val;
05579: }
05580: } else {
05581: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05582: colors[i] = this .vertexData[j];
05583: colors[i + 1] = this .vertexData[j + 1];
05584: colors[i + 2] = this .vertexData[j + 2];
05585: }
05586: }
05587: }
05588:
05589: /**
05590: * Gets the colors associated with the vertices starting at
05591: * the specified index.
05592: * @param index the vertex index
05593: * @param colors an array of 3*n or 4*n values that will receive new colors
05594: */
05595: void getColors(int index, byte colors[]) {
05596: int offset = this .stride * index + colorOffset;
05597: int i, j, num = colors.length;
05598: float val = 1.0f / lastAlpha[0];
05599:
05600: if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
05601: for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
05602: colors[i] = (byte) (this .vertexData[j] * FloatToByteScale);
05603: colors[i + 1] = (byte) (this .vertexData[j + 1] * FloatToByteScale);
05604: colors[i + 2] = (byte) (this .vertexData[j + 2] * FloatToByteScale);
05605: colors[i + 3] = (byte) ((this .vertexData[j + 3] * val) * FloatToByteScale);
05606: }
05607: } else {
05608: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05609: colors[i] = (byte) (this .vertexData[j] * FloatToByteScale);
05610: colors[i + 1] = (byte) (this .vertexData[j + 1] * FloatToByteScale);
05611: colors[i + 2] = (byte) (this .vertexData[j + 2] * FloatToByteScale);
05612: }
05613: }
05614: }
05615:
05616: /**
05617: * Gets the colors associated with the vertices starting at
05618: * the specified index.
05619: * @param index the vertex index
05620: * @param colors an array of vectors that will receive new colors
05621: */
05622: void getColors(int index, Color3f colors[]) {
05623: int offset = this .stride * index + colorOffset;
05624: int i, j, num = colors.length;
05625:
05626: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05627: colors[i].x = this .vertexData[j];
05628: colors[i].y = this .vertexData[j + 1];
05629: colors[i].z = this .vertexData[j + 2];
05630: }
05631: }
05632:
05633: /**
05634: * Gets the colors associated with the vertices starting at
05635: * the specified index.
05636: * @param index the vertex index
05637: * @param colors an array of vectors that will receive new colors
05638: */
05639: void getColors(int index, Color4f colors[]) {
05640: int offset = this .stride * index + colorOffset;
05641: int i, j, num = colors.length;
05642: float val = 1.0f / lastAlpha[0];
05643:
05644: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05645: colors[i].x = this .vertexData[j];
05646: colors[i].y = this .vertexData[j + 1];
05647: colors[i].z = this .vertexData[j + 2];
05648: colors[i].w = this .vertexData[j + 3] * val;
05649: }
05650: }
05651:
05652: /**
05653: * Gets the colors associated with the vertices starting at
05654: * the specified index.
05655: * @param index the vertex index
05656: * @param colors an array of vectors that will receive new colors
05657: */
05658: void getColors(int index, Color3b colors[]) {
05659: int offset = this .stride * index + colorOffset;
05660: int i, j, num = colors.length;
05661:
05662: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05663: colors[i].x = (byte) (this .vertexData[j] * FloatToByteScale);
05664: colors[i].y = (byte) (this .vertexData[j + 1] * FloatToByteScale);
05665: colors[i].z = (byte) (this .vertexData[j + 2] * FloatToByteScale);
05666: }
05667: }
05668:
05669: /**
05670: * Gets the colors associated with the vertices starting at
05671: * the specified index.
05672: * @param index the vertex index
05673: * @param colors an array of vectors that will receive new colors
05674: */
05675: void getColors(int index, Color4b colors[]) {
05676: int offset = this .stride * index + colorOffset;
05677: int i, j, num = colors.length;
05678: float val = 1.0f / lastAlpha[0];
05679:
05680: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05681: colors[i].x = (byte) (this .vertexData[j] * FloatToByteScale);
05682: colors[i].y = (byte) (this .vertexData[j + 1] * FloatToByteScale);
05683: colors[i].z = (byte) (this .vertexData[j + 2] * FloatToByteScale);
05684: colors[i].w = (byte) (this .vertexData[j + 3] * val * FloatToByteScale);
05685: }
05686: }
05687:
05688: /**
05689: * Gets the normal associated with the vertex at
05690: * the specified index.
05691: * @param index the vertex index
05692: * @param normal array that will receive the new normal
05693: */
05694: void getNormal(int index, float normal[]) {
05695: int offset = this .stride * index + normalOffset;
05696:
05697: normal[0] = this .vertexData[offset];
05698: normal[1] = this .vertexData[offset + 1];
05699: normal[2] = this .vertexData[offset + 2];
05700: }
05701:
05702: /**
05703: * Gets the normal associated with the vertex at
05704: * the specified index.
05705: * @param index the vertex index
05706: * @param normal the vector that will receive the new normal
05707: */
05708: void getNormal(int index, Vector3f normal) {
05709: int offset = this .stride * index + normalOffset;
05710:
05711: normal.x = this .vertexData[offset];
05712: normal.y = this .vertexData[offset + 1];
05713: normal.z = this .vertexData[offset + 2];
05714: }
05715:
05716: /**
05717: * Gets the normals associated with the vertices starting at
05718: * the specified index.
05719: * @param index the vertex index
05720: * @param normals array that will receive the new normals
05721: */
05722: void getNormals(int index, float normals[]) {
05723: int offset = this .stride * index + normalOffset;
05724: int i, j, num = normals.length;
05725:
05726: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05727: normals[i] = this .vertexData[j];
05728: normals[i + 1] = this .vertexData[j + 1];
05729: normals[i + 2] = this .vertexData[j + 2];
05730: }
05731: }
05732:
05733: /**
05734: * Gets the normals associated with the vertices starting at
05735: * the specified index.
05736: * @param index the vertex index
05737: * @param normals the vector that will receive the new normals
05738: */
05739: void getNormals(int index, Vector3f normals[]) {
05740: int offset = this .stride * index + normalOffset;
05741: int i, j, num = normals.length;
05742:
05743: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05744: normals[i].x = this .vertexData[j];
05745: normals[i].y = this .vertexData[j + 1];
05746: normals[i].z = this .vertexData[j + 2];
05747: }
05748: }
05749:
05750: /**
05751: * Gets the texture co-ordinate associated with the vertex at
05752: * the specified index.
05753: * @param index the vertex index
05754: * @param texCoord array that will receive the new texture co-ordinate
05755: */
05756: void getTextureCoordinate(int texCoordSet, int index,
05757: float texCoord[]) {
05758: int offset = this .stride * index + textureOffset + texCoordSet
05759: * texCoordStride;
05760:
05761: texCoord[0] = this .vertexData[offset];
05762: texCoord[1] = this .vertexData[offset + 1];
05763: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
05764: texCoord[2] = this .vertexData[offset + 2];
05765:
05766: } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
05767: texCoord[2] = this .vertexData[offset + 2];
05768: texCoord[3] = this .vertexData[offset + 3];
05769: }
05770: }
05771:
05772: /**
05773: * Gets the texture co-ordinate associated with the vertex at
05774: * the specified index.
05775: * @param index the vertex index
05776: * @param texCoord the vector that will receive the new texture co-ordinates
05777: */
05778: void getTextureCoordinate(int texCoordSet, int index,
05779: TexCoord2f texCoord) {
05780: int offset = this .stride * index + textureOffset + texCoordSet
05781: * texCoordStride;
05782:
05783: texCoord.x = this .vertexData[offset];
05784: texCoord.y = this .vertexData[offset + 1];
05785: }
05786:
05787: /**
05788: * Gets the texture co-ordinate associated with the vertex at
05789: * the specified index.
05790: * @param index the vertex index
05791: * @param texCoord the vector that will receive the new texture co-ordinates
05792: */
05793: void getTextureCoordinate(int texCoordSet, int index,
05794: TexCoord3f texCoord) {
05795: int offset = this .stride * index + textureOffset + texCoordSet
05796: * texCoordStride;
05797:
05798: texCoord.x = this .vertexData[offset];
05799: texCoord.y = this .vertexData[offset + 1];
05800: texCoord.z = this .vertexData[offset + 2];
05801: }
05802:
05803: /**
05804: * Gets the texture co-ordinate associated with the vertex at
05805: * the specified index.
05806: * @param index the vertex index
05807: * @param texCoord the vector that will receive the new texture co-ordinates
05808: */
05809: void getTextureCoordinate(int texCoordSet, int index,
05810: TexCoord4f texCoord) {
05811: int offset = this .stride * index + textureOffset + texCoordSet
05812: * texCoordStride;
05813:
05814: texCoord.x = this .vertexData[offset];
05815: texCoord.y = this .vertexData[offset + 1];
05816: texCoord.z = this .vertexData[offset + 2];
05817: texCoord.w = this .vertexData[offset + 3];
05818: }
05819:
05820: /**
05821: * Gets the texture co-ordinates associated with the vertices starting at
05822: * the specified index.
05823: * @param index the vertex index
05824: * @param texCoords array that will receive the new texture co-ordinates
05825: */
05826: void getTextureCoordinates(int texCoordSet, int index,
05827: float texCoords[]) {
05828: int offset = this .stride * index + textureOffset + texCoordSet
05829: * texCoordStride;
05830: int i, j, num = texCoords.length;
05831:
05832: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
05833: for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
05834: texCoords[i] = this .vertexData[j];
05835: texCoords[i + 1] = this .vertexData[j + 1];
05836: texCoords[i + 2] = this .vertexData[j + 2];
05837: texCoords[i + 3] = this .vertexData[j + 3];
05838: }
05839: } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
05840: for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05841: texCoords[i] = this .vertexData[j];
05842: texCoords[i + 1] = this .vertexData[j + 1];
05843: texCoords[i + 2] = this .vertexData[j + 2];
05844: }
05845: } else {
05846: for (i = 0, j = offset; i < num; i += 2, j += this .stride) {
05847: texCoords[i] = this .vertexData[j];
05848: texCoords[i + 1] = this .vertexData[j + 1];
05849: }
05850: }
05851: }
05852:
05853: /**
05854: * Gets the texture co-ordinates associated with the vertices starting at
05855: * the specified index.
05856: * @param index the vertex index
05857: * @param texCoords the vector that will receive the new texture co-ordinates
05858: */
05859: void getTextureCoordinates(int texCoordSet, int index,
05860: TexCoord2f texCoords[]) {
05861: int offset = this .stride * index + textureOffset + texCoordSet
05862: * texCoordStride;
05863: int i, j, num = texCoords.length;
05864:
05865: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05866: texCoords[i].x = this .vertexData[j];
05867: texCoords[i].y = this .vertexData[j + 1];
05868: }
05869: }
05870:
05871: /**
05872: * Gets the texture co-ordinates associated with the vertices starting at
05873: * the specified index.
05874: * @param index the vertex index
05875: * @param texCoords the vector that will receive the new texture co-ordinates
05876: */
05877: void getTextureCoordinates(int texCoordSet, int index,
05878: TexCoord3f texCoords[]) {
05879: int offset = this .stride * index + textureOffset + texCoordSet
05880: * texCoordStride;
05881: int i, j, num = texCoords.length;
05882:
05883: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05884: texCoords[i].x = this .vertexData[j];
05885: texCoords[i].y = this .vertexData[j + 1];
05886: texCoords[i].z = this .vertexData[j + 2];
05887: }
05888: }
05889:
05890: /**
05891: * Gets the texture co-ordinates associated with the vertices starting at
05892: * the specified index.
05893: * @param index the vertex index
05894: * @param texCoords the vector that will receive the new texture co-ordinates
05895: */
05896: void getTextureCoordinates(int texCoordSet, int index,
05897: TexCoord4f texCoords[]) {
05898: int offset = this .stride * index + textureOffset + texCoordSet
05899: * texCoordStride;
05900: int i, j, num = texCoords.length;
05901:
05902: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05903: texCoords[i].x = this .vertexData[j];
05904: texCoords[i].y = this .vertexData[j + 1];
05905: texCoords[i].z = this .vertexData[j + 2];
05906: texCoords[i].w = this .vertexData[j + 3];
05907: }
05908: }
05909:
05910: void getTextureCoordinates(int texCoordSet, int index,
05911: Point2f texCoords[]) {
05912: int offset = this .stride * index + textureOffset + texCoordSet
05913: * texCoordStride;
05914: int i, j, num = texCoords.length;
05915:
05916: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05917: texCoords[i].x = this .vertexData[j];
05918: texCoords[i].y = this .vertexData[j + 1];
05919: }
05920: }
05921:
05922: void getTextureCoordinates(int texCoordSet, int index,
05923: Point3f texCoords[]) {
05924: int offset = this .stride * index + textureOffset + texCoordSet
05925: * texCoordStride;
05926: int i, j, num = texCoords.length;
05927:
05928: for (i = 0, j = offset; i < num; i++, j += this .stride) {
05929: texCoords[i].x = this .vertexData[j];
05930: texCoords[i].y = this .vertexData[j + 1];
05931: texCoords[i].z = this .vertexData[j + 2];
05932: }
05933: }
05934:
05935: /**
05936: * Gets the vertex attribute associated with the vertex at
05937: * the specified index in the specified vertex attribute number
05938: * for this object.
05939: */
05940: public void getVertexAttr(int vertexAttrNum, int index,
05941: float[] vertexAttr) {
05942:
05943: int offset = this .stride * index
05944: + vertexAttrOffsets[vertexAttrNum];
05945: int size = vertexAttrSizes[vertexAttrNum];
05946:
05947: for (int i = 0; i < size; i++) {
05948: vertexAttr[i] = this .vertexData[offset + i];
05949:
05950: }
05951:
05952: }
05953:
05954: /**
05955: * Gets the vertex attribute associated with the vertex at
05956: * the specified index in the specified vertex attribute number
05957: * for this object.
05958: */
05959: public void getVertexAttr(int vertexAttrNum, int index,
05960: Point2f vertexAttr) {
05961:
05962: int offset = this .stride * index
05963: + vertexAttrOffsets[vertexAttrNum];
05964:
05965: vertexAttr.x = this .vertexData[offset];
05966: vertexAttr.y = this .vertexData[offset + 1];
05967:
05968: }
05969:
05970: /**
05971: * Gets the vertex attribute associated with the vertex at
05972: * the specified index in the specified vertex attribute number
05973: * for this object.
05974: */
05975: public void getVertexAttr(int vertexAttrNum, int index,
05976: Point3f vertexAttr) {
05977:
05978: int offset = this .stride * index
05979: + vertexAttrOffsets[vertexAttrNum];
05980:
05981: vertexAttr.x = this .vertexData[offset];
05982: vertexAttr.y = this .vertexData[offset + 1];
05983: vertexAttr.z = this .vertexData[offset + 2];
05984:
05985: }
05986:
05987: /**
05988: * Gets the vertex attribute associated with the vertex at
05989: * the specified index in the specified vertex attribute number
05990: * for this object.
05991: */
05992: public void getVertexAttr(int vertexAttrNum, int index,
05993: Point4f vertexAttr) {
05994:
05995: int offset = this .stride * index
05996: + vertexAttrOffsets[vertexAttrNum];
05997:
05998: vertexAttr.x = this .vertexData[offset];
05999: vertexAttr.y = this .vertexData[offset + 1];
06000: vertexAttr.z = this .vertexData[offset + 2];
06001: vertexAttr.w = this .vertexData[offset + 3];
06002:
06003: }
06004:
06005: /**
06006: * Gets the vertex attributes associated with the vertices starting at
06007: * the specified index in the specified vertex attribute number
06008: * for this object.
06009: */
06010: public void getVertexAttrs(int vertexAttrNum, int index,
06011: float[] vertexAttrs) {
06012:
06013: int offset = this .stride * index
06014: + vertexAttrOffsets[vertexAttrNum];
06015: int size = vertexAttrSizes[vertexAttrNum];
06016: int i, j, k;
06017:
06018: for (i = 0, j = offset; ((i < vertexAttrs.length) && (j < this .vertexData.length)); i += size, j += this .stride) {
06019: for (k = 0; k < size; k++) {
06020: vertexAttrs[i + k] = this .vertexData[j + k];
06021: }
06022: }
06023:
06024: }
06025:
06026: /**
06027: * Gets the vertex attributes associated with the vertices starting at
06028: * the specified index in the specified vertex attribute number
06029: * for this object.
06030: */
06031: public void getVertexAttrs(int vertexAttrNum, int index,
06032: Point2f[] vertexAttrs) {
06033:
06034: int offset = this .stride * index
06035: + vertexAttrOffsets[vertexAttrNum];
06036: int i, j;
06037:
06038: for (i = 0, j = offset; ((i < vertexAttrs.length) && (j < this .vertexData.length)); i++, j += this .stride) {
06039: vertexAttrs[i].x = this .vertexData[j];
06040: vertexAttrs[i].y = this .vertexData[j + 1];
06041: }
06042:
06043: }
06044:
06045: /**
06046: * Gets the vertex attributes associated with the vertices starting at
06047: * the specified index in the specified vertex attribute number
06048: * for this object.
06049: */
06050: public void getVertexAttrs(int vertexAttrNum, int index,
06051: Point3f[] vertexAttrs) {
06052:
06053: int offset = this .stride * index
06054: + vertexAttrOffsets[vertexAttrNum];
06055: int i, j;
06056:
06057: for (i = 0, j = offset; ((i < vertexAttrs.length) && (j < this .vertexData.length)); i++, j += this .stride) {
06058: vertexAttrs[i].x = this .vertexData[j];
06059: vertexAttrs[i].y = this .vertexData[j + 1];
06060: vertexAttrs[i].z = this .vertexData[j + 2];
06061: }
06062:
06063: }
06064:
06065: /**
06066: * Gets the vertex attributes associated with the vertices starting at
06067: * the specified index in the specified vertex attribute number
06068: * for this object.
06069: */
06070: public void getVertexAttrs(int vertexAttrNum, int index,
06071: Point4f[] vertexAttrs) {
06072:
06073: int offset = this .stride * index
06074: + vertexAttrOffsets[vertexAttrNum];
06075: int i, j;
06076:
06077: for (i = 0, j = offset; ((i < vertexAttrs.length) && (j < this .vertexData.length)); i++, j += this .stride) {
06078: vertexAttrs[i].x = this .vertexData[j];
06079: vertexAttrs[i].y = this .vertexData[j + 1];
06080: vertexAttrs[i].z = this .vertexData[j + 2];
06081: vertexAttrs[i].w = this .vertexData[j + 3];
06082: }
06083:
06084: }
06085:
06086: /**
06087: * Updates geometry array data.
06088: */
06089: void updateData(GeometryUpdater updater) {
06090: boolean nullGeo = false;
06091:
06092: // Add yourself to obtain the geometry lock
06093: // and Thread.currentThread().sleep until you get the lock
06094: geomLock.getLock();
06095:
06096: inUpdater = true;
06097: updater.updateData((Geometry) source);
06098: inUpdater = false;
06099: if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) {
06100: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
06101: // XXXX: handle the nio buffer
06102: if (!(this instanceof IndexedGeometryArrayRetained)
06103: || (vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
06104: if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
06105: setupMirrorInterleavedColorPointer(false);
06106: nullGeo = (interleavedFloatBufferImpl == null);
06107: } else {
06108: setupMirrorColorPointer(
06109: (vertexType & COLOR_DEFINED), false);
06110: nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
06111: }
06112: }
06113: } else {
06114: if (!(this instanceof IndexedGeometryArrayRetained)
06115: || (vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
06116: if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
06117: setupMirrorInterleavedColorPointer(false);
06118: nullGeo = (interLeavedVertexData == null);
06119: } else {
06120: setupMirrorVertexPointer(vertexType
06121: & VERTEX_DEFINED);
06122: setupMirrorColorPointer(
06123: (vertexType & COLOR_DEFINED), false);
06124: setupMirrorNormalPointer(vertexType
06125: & NORMAL_DEFINED);
06126: setupMirrorTexCoordPointer(texCoordType);
06127: setupMirrorVertexAttrPointer(vertexAttrType);
06128: nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
06129: }
06130: }
06131: }
06132:
06133: //NVaidya
06134: // User may or may not have changed indices in updater callback.
06135: // We need to presume that the user may indeed have and, thus, will
06136: // need to recompute maxCoordIndex unconditionally while
06137: // geomLock is still locked.
06138: if ((vertexFormat & GeometryArray.BY_REFERENCE_INDICES) != 0) {
06139: assert (this instanceof IndexedGeometryArrayRetained);
06140:
06141: if (((IndexedGeometryArrayRetained) this )
06142: .getCoordIndicesRef() == null) {
06143: nullGeo = true;
06144: }
06145: ((IndexedGeometryArrayRetained) this )
06146: .doPostUpdaterUpdate();
06147: }
06148: }
06149:
06150: dirtyFlag |= VERTEX_CHANGED;
06151: colorChanged = 0xffff;
06152: geomLock.unLock();
06153:
06154: if (source != null && source.isLive()) {
06155: processCoordsChanged(nullGeo);
06156: sendDataChangedMessage(true);
06157: }
06158: }
06159:
06160: boolean intersectBoundingBox(Point3d coordinates[],
06161: BoundingBox box, double dist[], Point3d iPnt) {
06162: int i, j;
06163: int out[] = new int[6];
06164:
06165: //Do trivial vertex test.
06166: for (i = 0; i < 6; i++)
06167: out[i] = 0;
06168: for (i = 0; i < coordinates.length; i++) {
06169: if ((coordinates[i].x >= box.lower.x)
06170: && (coordinates[i].x <= box.upper.x)
06171: && (coordinates[i].y >= box.lower.y)
06172: && (coordinates[i].y <= box.upper.y)
06173: && (coordinates[i].z >= box.lower.z)
06174: && (coordinates[i].z <= box.upper.z))
06175: // We're done! It's inside the boundingbox.
06176: return true;
06177: else {
06178: if (coordinates[i].x < box.lower.x)
06179: out[0]++; // left
06180: if (coordinates[i].y < box.lower.y)
06181: out[1]++; // bottom
06182: if (coordinates[i].z < box.lower.z)
06183: out[2]++; // back
06184: if (coordinates[i].x > box.upper.x)
06185: out[3]++; // right
06186: if (coordinates[i].y > box.upper.y)
06187: out[4]++; // top
06188: if (coordinates[i].z > box.upper.z)
06189: out[5]++; // front
06190: }
06191:
06192: }
06193:
06194: if ((out[0] == coordinates.length)
06195: || (out[1] == coordinates.length)
06196: || (out[2] == coordinates.length)
06197: || (out[3] == coordinates.length)
06198: || (out[4] == coordinates.length)
06199: || (out[5] == coordinates.length))
06200: // we're done. primitive is outside of boundingbox.
06201: return false;
06202:
06203: // Setup bounding planes.
06204: Point3d pCoor[] = new Point3d[4];
06205: for (i = 0; i < 4; i++)
06206: pCoor[i] = new Point3d();
06207:
06208: // left plane.
06209: pCoor[0].set(box.lower.x, box.lower.y, box.lower.z);
06210: pCoor[1].set(box.lower.x, box.lower.y, box.upper.z);
06211: pCoor[2].set(box.lower.x, box.upper.y, box.upper.z);
06212: pCoor[3].set(box.lower.x, box.upper.y, box.lower.z);
06213:
06214: if (intersectPolygon(pCoor, coordinates)) {
06215: if (dist != null) {
06216: computeMinDistance(pCoor, box.getCenter(), null, dist,
06217: iPnt);
06218: }
06219: return true;
06220: }
06221:
06222: // right plane.
06223: pCoor[0].set(box.upper.x, box.lower.y, box.lower.z);
06224: pCoor[1].set(box.upper.x, box.upper.y, box.lower.z);
06225: pCoor[2].set(box.upper.x, box.upper.y, box.upper.z);
06226: pCoor[3].set(box.upper.x, box.lower.y, box.upper.z);
06227: if (intersectPolygon(pCoor, coordinates)) {
06228: if (dist != null) {
06229: computeMinDistance(pCoor, box.getCenter(), null, dist,
06230: iPnt);
06231: }
06232: return true;
06233: }
06234:
06235: // bottom plane.
06236: pCoor[0].set(box.upper.x, box.lower.y, box.upper.z);
06237: pCoor[1].set(box.lower.x, box.lower.y, box.upper.z);
06238: pCoor[2].set(box.lower.x, box.lower.y, box.lower.z);
06239: pCoor[3].set(box.upper.x, box.lower.y, box.lower.z);
06240: if (intersectPolygon(pCoor, coordinates)) {
06241: if (dist != null) {
06242: computeMinDistance(pCoor, box.getCenter(), null, dist,
06243: iPnt);
06244: }
06245: return true;
06246: }
06247: // top plane.
06248: pCoor[0].set(box.upper.x, box.upper.y, box.upper.z);
06249: pCoor[1].set(box.upper.x, box.upper.y, box.lower.z);
06250: pCoor[2].set(box.lower.x, box.upper.y, box.lower.z);
06251: pCoor[3].set(box.lower.x, box.upper.y, box.upper.z);
06252: if (intersectPolygon(pCoor, coordinates)) {
06253: if (dist != null) {
06254: computeMinDistance(pCoor, box.getCenter(), null, dist,
06255: iPnt);
06256: }
06257: return true;
06258: }
06259:
06260: // front plane.
06261: pCoor[0].set(box.upper.x, box.upper.y, box.upper.z);
06262: pCoor[1].set(box.lower.x, box.upper.y, box.upper.z);
06263: pCoor[2].set(box.lower.x, box.lower.y, box.upper.z);
06264: pCoor[3].set(box.upper.x, box.lower.y, box.upper.z);
06265: if (intersectPolygon(pCoor, coordinates)) {
06266: if (dist != null) {
06267: computeMinDistance(pCoor, box.getCenter(), null, dist,
06268: iPnt);
06269: }
06270: return true;
06271: }
06272:
06273: // back plane.
06274: pCoor[0].set(box.upper.x, box.upper.y, box.lower.z);
06275: pCoor[1].set(box.upper.x, box.lower.y, box.lower.z);
06276: pCoor[2].set(box.lower.x, box.lower.y, box.lower.z);
06277: pCoor[3].set(box.lower.x, box.upper.y, box.lower.z);
06278: if (intersectPolygon(pCoor, coordinates)) {
06279: if (dist != null) {
06280: computeMinDistance(pCoor, box.getCenter(), null, dist,
06281: iPnt);
06282: }
06283: return true;
06284: }
06285: return false;
06286: }
06287:
06288: boolean intersectBoundingSphere(Point3d coordinates[],
06289: BoundingSphere sphere, double dist[], Point3d iPnt) {
06290: int i, j;
06291: Vector3d tempV3D = new Vector3d();
06292: boolean esFlag;
06293:
06294: //Do trivial vertex test.
06295:
06296: for (i = 0; i < coordinates.length; i++) {
06297: tempV3D.x = coordinates[i].x - sphere.center.x;
06298: tempV3D.y = coordinates[i].y - sphere.center.y;
06299: tempV3D.z = coordinates[i].z - sphere.center.z;
06300:
06301: if (tempV3D.length() <= sphere.radius) {
06302: // We're done! It's inside the boundingSphere.
06303: if (dist != null) {
06304: computeMinDistance(coordinates, sphere.getCenter(),
06305: null, dist, iPnt);
06306: }
06307:
06308: return true;
06309: }
06310: }
06311:
06312: for (i = 0; i < coordinates.length; i++) {
06313: if (i < (coordinates.length - 1))
06314: esFlag = edgeIntersectSphere(sphere, coordinates[i],
06315: coordinates[i + 1]);
06316: else
06317: esFlag = edgeIntersectSphere(sphere, coordinates[i],
06318: coordinates[0]);
06319: if (esFlag == true) {
06320: if (dist != null) {
06321: computeMinDistance(coordinates, sphere.getCenter(),
06322: null, dist, iPnt);
06323: }
06324:
06325: return true;
06326: }
06327: }
06328:
06329: if (coordinates.length < 3) {
06330: return false; // We're done with line.
06331: }
06332:
06333: // Find rho.
06334: // Compute plane normal.
06335: Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
06336: Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
06337: Vector3d pNrm = new Vector3d();
06338: Vector3d pa = new Vector3d();
06339: Point3d q = new Point3d();
06340: double nLenSq, pqLen, pNrmDotPa, tq;
06341:
06342: // compute plane normal for coordinates.
06343: for (i = 0; i < coordinates.length - 1;) {
06344: vec0.x = coordinates[i + 1].x - coordinates[i].x;
06345: vec0.y = coordinates[i + 1].y - coordinates[i].y;
06346: vec0.z = coordinates[i + 1].z - coordinates[i++].z;
06347: if (vec0.length() > 0.0)
06348: break;
06349: }
06350:
06351: for (j = i; j < coordinates.length - 1; j++) {
06352: vec1.x = coordinates[j + 1].x - coordinates[j].x;
06353: vec1.y = coordinates[j + 1].y - coordinates[j].y;
06354: vec1.z = coordinates[j + 1].z - coordinates[j].z;
06355: if (vec1.length() > 0.0)
06356: break;
06357: }
06358:
06359: if (j == (coordinates.length - 1)) {
06360: // System.err.println("(1) Degenerate polygon.");
06361: return false; // Degenerate polygon.
06362: }
06363:
06364: /*
06365: for(i=0; i<coordinates.length; i++)
06366: System.err.println("coordinates P" + i + " " + coordinates[i]);
06367: for(i=0; i<coord2.length; i++)
06368: System.err.println("coord2 P" + i + " " + coord2[i]);
06369: */
06370:
06371: pNrm.cross(vec0, vec1);
06372:
06373: nLenSq = pNrm.lengthSquared();
06374: if (nLenSq == 0.0) {
06375: // System.err.println("(2) Degenerate polygon.");
06376: return false; // Degenerate polygon.
06377: }
06378:
06379: pa.x = coordinates[0].x - sphere.center.x;
06380: pa.y = coordinates[0].y - sphere.center.y;
06381: pa.z = coordinates[0].z - sphere.center.z;
06382:
06383: pNrmDotPa = pNrm.dot(pa);
06384:
06385: pqLen = Math.sqrt(pNrmDotPa * pNrmDotPa / nLenSq);
06386:
06387: if (pqLen > sphere.radius) {
06388: return false;
06389: }
06390:
06391: tq = pNrmDotPa / nLenSq;
06392:
06393: q.x = sphere.center.x + tq * pNrm.x;
06394: q.y = sphere.center.y + tq * pNrm.y;
06395: q.z = sphere.center.z + tq * pNrm.z;
06396:
06397: // PolyPnt2D Test.
06398: if (pointIntersectPolygon2D(pNrm, coordinates, q)) {
06399: if (dist != null) {
06400: computeMinDistance(coordinates, sphere.getCenter(),
06401: pNrm, dist, iPnt);
06402: }
06403: return true;
06404: }
06405: return false;
06406:
06407: }
06408:
06409: boolean intersectBoundingPolytope(Point3d coordinates[],
06410: BoundingPolytope polytope, double dist[], Point3d iPnt) {
06411: boolean debug = false;
06412:
06413: Point4d tP4d = new Point4d();
06414:
06415: // this is a multiplier to the halfplane distance coefficients
06416: double distanceSign = -1.0;
06417:
06418: if (coordinates.length == 2) {
06419: // we'll handle line separately.
06420: if (polytope
06421: .intersect(coordinates[0], coordinates[1], tP4d)) {
06422: if (dist != null) {
06423: iPnt.x = tP4d.x;
06424: iPnt.y = tP4d.y;
06425: iPnt.z = tP4d.z;
06426: Point3d pc = polytope.getCenter();
06427: double x = iPnt.x - pc.x;
06428: double y = iPnt.y - pc.y;
06429: double z = iPnt.z - pc.z;
06430: dist[0] = Math.sqrt(x * x + y * y + z * z);
06431: }
06432: return true;
06433: }
06434: return false;
06435: }
06436:
06437: // It is a triangle or a quad.
06438:
06439: // first test to see if any of the coordinates are all inside of the
06440: // intersection polytope's half planes
06441: // essentially do a matrix multiply of the constraintMatrix K*3 with
06442: // the input coordinates 3*1 = K*1 vector
06443:
06444: if (debug) {
06445: System.err.println("The value of the input vertices are: ");
06446: for (int i = 0; i < coordinates.length; i++) {
06447: System.err.println("The " + i + " th vertex is: "
06448: + coordinates[i]);
06449: }
06450:
06451: System.err
06452: .println("The value of the input bounding Polytope's planes =");
06453: for (int i = 0; i < polytope.planes.length; i++) {
06454: System.err.println("The " + i + " th plane is: "
06455: + polytope.planes[i]);
06456: }
06457:
06458: }
06459:
06460: // the direction for the intersection cost function
06461: double centers[] = new double[4];
06462: centers[0] = 0.8;
06463: centers[1] = 0.9;
06464: centers[2] = 1.1;
06465: centers[3] = 1.2;
06466:
06467: boolean intersection = true;
06468: boolean PreTest = false;
06469:
06470: if (PreTest) {
06471: // for each coordinate, test it with each half plane
06472: for (int i = 0; i < coordinates.length; i++) {
06473: for (int j = 0; j < polytope.planes.length; j++) {
06474: if ((polytope.planes[j].x * coordinates[i].x
06475: + polytope.planes[j].y * coordinates[i].y + polytope.planes[j].z
06476: * coordinates[i].z) <= (distanceSign)
06477: * polytope.planes[j].w) {
06478: // the point satisfies this particular hyperplane
06479: intersection = true;
06480: } else {
06481: // the point fails this hyper plane try with a new hyper plane
06482: intersection = false;
06483: break;
06484: }
06485: }
06486: if (intersection) {
06487: // a point was found to be completely inside the bounding hull
06488: if (dist != null) {
06489: computeMinDistance(coordinates, polytope
06490: .getCenter(), null, dist, iPnt);
06491: }
06492: return true;
06493: }
06494: }
06495: } // end of pretest
06496:
06497: // at this point all points are outside of the bounding hull
06498: // build the problem tableau for the linear program
06499:
06500: int numberCols = polytope.planes.length + 2
06501: + coordinates.length + 1;
06502: int numberRows = 1 + coordinates.length;
06503:
06504: double problemTableau[][] = new double[numberRows][numberCols];
06505:
06506: // compute -Mtrans = -A*P
06507:
06508: for (int i = 0; i < polytope.planes.length; i++) {
06509: for (int j = 0; j < coordinates.length; j++) {
06510: problemTableau[j][i] = (-1.0)
06511: * (polytope.planes[i].x * coordinates[j].x
06512: + polytope.planes[i].y
06513: * coordinates[j].y + polytope.planes[i].z
06514: * coordinates[j].z);
06515: }
06516: }
06517:
06518: // add the other rows
06519: for (int i = 0; i < coordinates.length; i++) {
06520: problemTableau[i][polytope.planes.length] = -1.0;
06521: problemTableau[i][polytope.planes.length + 1] = 1.0;
06522:
06523: for (int j = 0; j < coordinates.length; j++) {
06524: if (i == j) {
06525: problemTableau[i][j + polytope.planes.length + 2] = 1.0;
06526: } else {
06527: problemTableau[i][j + polytope.planes.length + 2] = 0.0;
06528: }
06529:
06530: // place the last column elements the Ci's
06531: problemTableau[i][numberCols - 1] = centers[i];
06532: }
06533: }
06534:
06535: // place the final rows value
06536: for (int j = 0; j < polytope.planes.length; j++) {
06537: problemTableau[numberRows - 1][j] = (distanceSign)
06538: * polytope.planes[j].w;
06539: }
06540: problemTableau[numberRows - 1][polytope.planes.length] = 1.0;
06541: problemTableau[numberRows - 1][polytope.planes.length + 1] = -1.0;
06542: for (int j = 0; j < coordinates.length; j++) {
06543: problemTableau[numberRows - 1][polytope.planes.length + 2
06544: + j] = 0.0;
06545: }
06546:
06547: if (debug) {
06548: System.err.println("The value of the problem tableau is: ");
06549: for (int i = 0; i < problemTableau.length; i++) {
06550: for (int j = 0; j < problemTableau[0].length; j++) {
06551: System.err.print(problemTableau[i][j] + " ");
06552: }
06553: System.err.println();
06554: }
06555: }
06556:
06557: double distance = generalStandardSimplexSolver(problemTableau,
06558: Float.NEGATIVE_INFINITY);
06559: if (debug) {
06560: System.err
06561: .println("The value returned by the general standard simplex = "
06562: + distance);
06563: }
06564: if (distance == Float.POSITIVE_INFINITY) {
06565: return false;
06566: }
06567: if (dist != null) {
06568: computeMinDistance(coordinates, polytope.getCenter(), null,
06569: dist, iPnt);
06570: }
06571: return true;
06572:
06573: }
06574:
06575: // optimized version using arrays of doubles, but using the standard simplex
06576: // method to solve the LP tableau. This version has not been optimized to
06577: // work with a particular size input tableau and is much slower than some
06578: // of the other variants...supposedly
06579: double generalStandardSimplexSolver(double problemTableau[][],
06580: double stopingValue) {
06581: boolean debug = false;
06582: int numRow = problemTableau.length;
06583: int numCol = problemTableau[0].length;
06584: boolean optimal = false;
06585: int i, pivotRowIndex, pivotColIndex;
06586: double maxElement, element, endElement, ratio, prevRatio;
06587: int count = 0;
06588: double multiplier;
06589:
06590: if (debug) {
06591: System.err.println("The number of rows is : " + numRow);
06592: System.err.println("The number of columns is : " + numCol);
06593: }
06594:
06595: // until the optimal solution is found continue to do
06596: // iterations of the simplex method
06597: while (!optimal) {
06598:
06599: if (debug) {
06600: System.err.println("input problem tableau is:");
06601: for (int k = 0; k < numRow; k++) {
06602: for (int j = 0; j < numCol; j++) {
06603: System.err.println("kth, jth value is:" + k
06604: + " " + j + " : "
06605: + problemTableau[k][j]);
06606: }
06607: }
06608: }
06609:
06610: // test to see if the current solution is optimal
06611: // check all bottom row elements except the right most one and
06612: // if all positive or zero its optimal
06613: for (i = 0, maxElement = 0, pivotColIndex = -1; i < numCol - 1; i++) {
06614: // a bottom row element
06615: element = problemTableau[numRow - 1][i];
06616: if (element < maxElement) {
06617: maxElement = element;
06618: pivotColIndex = i;
06619: }
06620: }
06621:
06622: // if there is no negative non-zero element then we
06623: // have found an optimal solution (the last row of the tableau)
06624: if (pivotColIndex == -1) {
06625: // found an optimal solution
06626: //System.err.println("Found an optimal solution");
06627: optimal = true;
06628: }
06629:
06630: //System.err.println("The value of maxElement is:" + maxElement);
06631:
06632: if (!optimal) {
06633: // Case when the solution is not optimal but not known to be
06634: // either unbounded or infeasable
06635:
06636: // from the above we have found the maximum negative element in
06637: // bottom row, we have also found the column for this value
06638: // the pivotColIndex represents this
06639:
06640: // initialize the values for the algorithm, -1 for pivotRowIndex
06641: // indicates no solution
06642:
06643: prevRatio = Float.POSITIVE_INFINITY;
06644: ratio = 0.0;
06645: pivotRowIndex = -1;
06646:
06647: // note if all of the elements in the pivot column are zero or
06648: // negative the problem is unbounded.
06649: for (i = 0; i < numRow - 1; i++) {
06650: element = problemTableau[i][pivotColIndex]; // r value
06651: endElement = problemTableau[i][numCol - 1]; // s value
06652:
06653: // pivot according to the rule that we want to choose the row
06654: // with smallest s/r ratio see third case
06655: // currently we ignore valuse of r==0 (case 1) and cases where the
06656: // ratio is negative, i.e. either r or s are negative (case 2)
06657: if (element == 0) {
06658: if (debug) {
06659: System.err
06660: .println("Division by zero has occurred");
06661: System.err
06662: .println("Within the linear program solver");
06663: System.err
06664: .println("Ignoring the zero as a potential pivot");
06665: }
06666: } else if ((element < 0.0) || (endElement < 0.0)) {
06667: if (debug) {
06668: System.err
06669: .println("Ignoring cases where element is negative");
06670: System.err
06671: .println("The value of element is: "
06672: + element);
06673: System.err
06674: .println("The value of end Element is: "
06675: + endElement);
06676: }
06677: } else {
06678: ratio = endElement / element; // should be s/r
06679: if (debug) {
06680: System.err
06681: .println("The value of element is: "
06682: + element);
06683: System.err
06684: .println("The value of endElement is: "
06685: + endElement);
06686: System.err
06687: .println("The value of ratio is: "
06688: + ratio);
06689: System.err
06690: .println("The value of prevRatio is: "
06691: + prevRatio);
06692: System.err
06693: .println("Value of ratio <= prevRatio is :"
06694: + (ratio <= prevRatio));
06695: }
06696: if (ratio <= prevRatio) {
06697: if (debug) {
06698: System.err
06699: .println("updating prevRatio with ratio");
06700: }
06701: prevRatio = ratio;
06702: pivotRowIndex = i;
06703: }
06704: }
06705: }
06706:
06707: // if the pivotRowIndex is still -1 then we know the pivotColumn
06708: // has no viable pivot points and the solution is unbounded or
06709: // infeasable (all pivot elements were either zero or negative or
06710: // the right most value was negative (the later shouldn't happen?)
06711: if (pivotRowIndex == -1) {
06712: if (debug) {
06713: System.err.println("UNABLE TO FIND SOLUTION");
06714: System.err
06715: .println("The system is infeasable or unbounded");
06716: }
06717: return (Float.POSITIVE_INFINITY);
06718: }
06719:
06720: // we now have the pivot row and col all that remains is
06721: // to divide through by this value and subtract the appropriate
06722: // multiple of the pivot row from all other rows to obtain
06723: // a tableau which has a column of all zeros and one 1 in the
06724: // intersection of pivot row and col
06725:
06726: // divide through by the pivot value
06727: double pivotValue = problemTableau[pivotRowIndex][pivotColIndex];
06728:
06729: if (debug) {
06730: System.err.println("The value of row index is: "
06731: + pivotRowIndex);
06732: System.err.println("The value of col index is: "
06733: + pivotColIndex);
06734: System.err.println("The value of pivotValue is: "
06735: + pivotValue);
06736: }
06737: // divide through by s on the pivot row to obtain a 1 in pivot col
06738: for (i = 0; i < numCol; i++) {
06739: problemTableau[pivotRowIndex][i] = problemTableau[pivotRowIndex][i]
06740: / pivotValue;
06741: }
06742:
06743: // subtract appropriate multiple of pivot row from all other rows
06744: // to zero out all rows except the final row and the pivot row
06745: for (i = 0; i < numRow; i++) {
06746: if (i != pivotRowIndex) {
06747: multiplier = problemTableau[i][pivotColIndex];
06748: for (int j = 0; j < numCol; j++) {
06749: problemTableau[i][j] = problemTableau[i][j]
06750: - multiplier
06751: * problemTableau[pivotRowIndex][j];
06752: }
06753: }
06754: }
06755: }
06756: // case when the element is optimal
06757: }
06758: return (problemTableau[numRow - 1][numCol - 1]);
06759: }
06760:
06761: boolean edgeIntersectSphere(BoundingSphere sphere, Point3d start,
06762: Point3d end) {
06763: double abLenSq, acLenSq, apLenSq, abDotAp, radiusSq;
06764: Vector3d ab = new Vector3d();
06765: Vector3d ap = new Vector3d();
06766:
06767: ab.x = end.x - start.x;
06768: ab.y = end.y - start.y;
06769: ab.z = end.z - start.z;
06770:
06771: ap.x = sphere.center.x - start.x;
06772: ap.y = sphere.center.y - start.y;
06773: ap.z = sphere.center.z - start.z;
06774:
06775: abDotAp = ab.dot(ap);
06776:
06777: if (abDotAp < 0.0) {
06778: return false; // line segment points away from sphere.
06779: }
06780:
06781: abLenSq = ab.lengthSquared();
06782: acLenSq = abDotAp * abDotAp / abLenSq;
06783:
06784: if (acLenSq < abLenSq) {
06785: return false; // C doesn't lies between end points of edge.
06786: }
06787:
06788: radiusSq = sphere.radius * sphere.radius;
06789: apLenSq = ap.lengthSquared();
06790:
06791: if ((apLenSq - acLenSq) <= radiusSq) {
06792: return true;
06793: }
06794:
06795: return false;
06796:
06797: }
06798:
06799: double det2D(Point2d a, Point2d b, Point2d p) {
06800: return (((p).x - (a).x) * ((a).y - (b).y) + ((a).y - (p).y)
06801: * ((a).x - (b).x));
06802: }
06803:
06804: // Assume coord is CCW.
06805: boolean pointIntersectPolygon2D(Vector3d normal, Point3d[] coord,
06806: Point3d point) {
06807:
06808: double absNrmX, absNrmY, absNrmZ;
06809: Point2d coord2D[] = new Point2d[coord.length];
06810: Point2d pnt = new Point2d();
06811:
06812: int i, j, axis;
06813:
06814: // Project 3d points onto 2d plane.
06815: // Note : Area of polygon is not preserve in this projection, but
06816: // it doesn't matter here.
06817:
06818: // Find the axis of projection.
06819: absNrmX = Math.abs(normal.x);
06820: absNrmY = Math.abs(normal.y);
06821: absNrmZ = Math.abs(normal.z);
06822:
06823: if (absNrmX > absNrmY)
06824: axis = 0;
06825: else
06826: axis = 1;
06827:
06828: if (axis == 0) {
06829: if (absNrmX < absNrmZ)
06830: axis = 2;
06831: } else if (axis == 1) {
06832: if (absNrmY < absNrmZ)
06833: axis = 2;
06834: }
06835:
06836: // System.err.println("Normal " + normal + " axis " + axis );
06837:
06838: for (i = 0; i < coord.length; i++) {
06839: coord2D[i] = new Point2d();
06840:
06841: switch (axis) {
06842: case 0:
06843: coord2D[i].x = coord[i].y;
06844: coord2D[i].y = coord[i].z;
06845: break;
06846:
06847: case 1:
06848: coord2D[i].x = coord[i].x;
06849: coord2D[i].y = coord[i].z;
06850: break;
06851:
06852: case 2:
06853: coord2D[i].x = coord[i].x;
06854: coord2D[i].y = coord[i].y;
06855: break;
06856: }
06857:
06858: // System.err.println("i " + i + " u " + uCoor[i] + " v " + vCoor[i]);
06859: }
06860:
06861: switch (axis) {
06862: case 0:
06863: pnt.x = point.y;
06864: pnt.y = point.z;
06865: break;
06866:
06867: case 1:
06868: pnt.x = point.x;
06869: pnt.y = point.z;
06870: break;
06871:
06872: case 2:
06873: pnt.x = point.x;
06874: pnt.y = point.y;
06875: break;
06876: }
06877:
06878: // Do determinant test.
06879: for (j = 0; j < coord.length; j++) {
06880: if (j < (coord.length - 1))
06881: if (det2D(coord2D[j], coord2D[j + 1], pnt) > 0.0)
06882: ;
06883: else
06884: return false;
06885: else if (det2D(coord2D[j], coord2D[0], pnt) > 0.0)
06886: ;
06887: else
06888: return false;
06889: }
06890:
06891: return true;
06892:
06893: }
06894:
06895: boolean edgeIntersectPlane(Vector3d normal, Point3d pnt,
06896: Point3d start, Point3d end, Point3d iPnt) {
06897:
06898: Vector3d tempV3d = new Vector3d();
06899: Vector3d direction = new Vector3d();
06900: double pD, pNrmDotrDir, tr;
06901:
06902: // Compute plane D.
06903: tempV3d.set((Tuple3d) pnt);
06904: pD = normal.dot(tempV3d);
06905:
06906: direction.x = end.x - start.x;
06907: direction.y = end.y - start.y;
06908: direction.z = end.z - start.z;
06909:
06910: pNrmDotrDir = normal.dot(direction);
06911:
06912: // edge is parallel to plane.
06913: if (pNrmDotrDir == 0.0) {
06914: // System.err.println("Edge is parallel to plane.");
06915: return false;
06916: }
06917:
06918: tempV3d.set((Tuple3d) start);
06919:
06920: tr = (pD - normal.dot(tempV3d)) / pNrmDotrDir;
06921:
06922: // Edge intersects the plane behind the edge's start.
06923: // or exceed the edge's length.
06924: if ((tr < 0.0) || (tr > 1.0)) {
06925: // System.err.println("Edge intersects the plane behind the start or exceed end.");
06926: return false;
06927: }
06928:
06929: iPnt.x = start.x + tr * direction.x;
06930: iPnt.y = start.y + tr * direction.y;
06931: iPnt.z = start.z + tr * direction.z;
06932:
06933: return true;
06934:
06935: }
06936:
06937: // Assume coord is CCW.
06938: boolean edgeIntersectPolygon2D(Vector3d normal, Point3d[] coord,
06939: Point3d[] seg) {
06940:
06941: double absNrmX, absNrmY, absNrmZ;
06942: Point2d coord2D[] = new Point2d[coord.length];
06943: Point2d seg2D[] = new Point2d[2];
06944:
06945: int i, j, axis;
06946:
06947: // Project 3d points onto 2d plane.
06948: // Note : Area of polygon is not preserve in this projection, but
06949: // it doesn't matter here.
06950:
06951: // Find the axis of projection.
06952: absNrmX = Math.abs(normal.x);
06953: absNrmY = Math.abs(normal.y);
06954: absNrmZ = Math.abs(normal.z);
06955:
06956: if (absNrmX > absNrmY)
06957: axis = 0;
06958: else
06959: axis = 1;
06960:
06961: if (axis == 0) {
06962: if (absNrmX < absNrmZ)
06963: axis = 2;
06964: } else if (axis == 1) {
06965: if (absNrmY < absNrmZ)
06966: axis = 2;
06967: }
06968:
06969: // System.err.println("Normal " + normal + " axis " + axis );
06970:
06971: for (i = 0; i < coord.length; i++) {
06972: coord2D[i] = new Point2d();
06973:
06974: switch (axis) {
06975: case 0:
06976: coord2D[i].x = coord[i].y;
06977: coord2D[i].y = coord[i].z;
06978: break;
06979:
06980: case 1:
06981: coord2D[i].x = coord[i].x;
06982: coord2D[i].y = coord[i].z;
06983: break;
06984:
06985: case 2:
06986: coord2D[i].x = coord[i].x;
06987: coord2D[i].y = coord[i].y;
06988: break;
06989: }
06990:
06991: // System.err.println("i " + i + " u " + uCoor[i] + " v " + vCoor[i]);
06992: }
06993:
06994: for (i = 0; i < 2; i++) {
06995: seg2D[i] = new Point2d();
06996: switch (axis) {
06997: case 0:
06998: seg2D[i].x = seg[i].y;
06999: seg2D[i].y = seg[i].z;
07000: break;
07001:
07002: case 1:
07003: seg2D[i].x = seg[i].x;
07004: seg2D[i].y = seg[i].z;
07005: break;
07006:
07007: case 2:
07008: seg2D[i].x = seg[i].x;
07009: seg2D[i].y = seg[i].y;
07010: break;
07011: }
07012:
07013: // System.err.println("i " + i + " u " + uSeg[i] + " v " + vSeg[i]);
07014: }
07015:
07016: // Do determinant test.
07017: boolean pntTest[][] = new boolean[2][coord.length];
07018: boolean testFlag;
07019:
07020: for (j = 0; j < coord.length; j++) {
07021: for (i = 0; i < 2; i++) {
07022: if (j < (coord.length - 1))
07023: pntTest[i][j] = (det2D(coord2D[j], coord2D[j + 1],
07024: seg2D[i]) < 0.0);
07025: else
07026: pntTest[i][j] = (det2D(coord2D[j], coord2D[0],
07027: seg2D[i]) < 0.0);
07028: }
07029:
07030: if ((pntTest[0][j] == false) && (pntTest[1][j] == false))
07031: return false;
07032: }
07033:
07034: testFlag = true;
07035: for (i = 0; i < coord.length; i++) {
07036: if (pntTest[0][i] == false) {
07037: testFlag = false;
07038: break;
07039: }
07040: }
07041:
07042: if (testFlag == true)
07043: return true; // start point is inside polygon.
07044:
07045: testFlag = true;
07046: for (i = 0; i < coord.length; i++) {
07047: if (pntTest[1][i] == false) {
07048: testFlag = false;
07049: break;
07050: }
07051: }
07052:
07053: if (testFlag == true)
07054: return true; // end point is inside polygon.
07055:
07056: int cnt = 0;
07057: for (i = 0; i < coord.length; i++) {
07058: if (det2D(seg2D[0], seg2D[1], coord2D[i]) < 0.0)
07059: cnt++;
07060: }
07061:
07062: if ((cnt == 0) || (cnt == coord.length))
07063: return false;
07064:
07065: return true;
07066:
07067: }
07068:
07069: // New stuffs .....
07070: double getCompValue(Point3d v, int i) {
07071: switch (i) {
07072: case 0:
07073: return v.x;
07074: case 1:
07075: return v.y;
07076: }
07077: // Has to return something, so set the default to z component.
07078: return v.z;
07079: }
07080:
07081: double getCompValue(Point3d v0, Point3d v1, int i) {
07082: switch (i) {
07083: case 0:
07084: return (v0.x - v1.x);
07085: case 1:
07086: return (v0.y - v1.y);
07087: }
07088: // Has to return some, so set the default to z component.
07089: return (v0.z - v1.z);
07090: }
07091:
07092: boolean pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2,
07093: Vector3d normal) {
07094:
07095: double nAbsX, nAbsY, nAbsZ;
07096: int i0, i1;
07097:
07098: // first project onto an axis-aligned plane, that maximizes the area
07099: // of the triangles, compute indices i0, i1.
07100: nAbsX = Math.abs(normal.x);
07101: nAbsY = Math.abs(normal.y);
07102: nAbsZ = Math.abs(normal.z);
07103:
07104: if (nAbsX > nAbsY) {
07105: if (nAbsX > nAbsZ) {
07106: i0 = 1; // nAbsX is greatest.
07107: i1 = 2;
07108: } else {
07109: i0 = 0; // nAbsZ is greatest.
07110: i1 = 1;
07111: }
07112: } else { // nAbsX <= nAbsY
07113: if (nAbsZ > nAbsY) {
07114: i0 = 0; // nAbsZ is greatest.
07115: i1 = 1;
07116: } else {
07117: i0 = 0; // nAbsY is greatest.
07118: i1 = 2;
07119: }
07120: }
07121: return pointInTri(v0, u0, u1, u2, i0, i1);
07122: }
07123:
07124: boolean pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2,
07125: int i0, int i1) {
07126:
07127: double a, b, c, d0, d1, d2;
07128: // is T1 completely inside T2 ?
07129: // check if v0 is inside tri(u0,u1,u2)
07130:
07131: a = getCompValue(u1, u0, i1);
07132: b = -(getCompValue(u1, u0, i0));
07133: c = -a * getCompValue(u0, i0) - b * getCompValue(u0, i1);
07134: d0 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
07135:
07136: a = getCompValue(u2, u1, i1);
07137: b = -(getCompValue(u2, u1, i0));
07138: c = -a * getCompValue(u1, i0) - b * getCompValue(u1, i1);
07139: d1 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
07140:
07141: a = getCompValue(u0, u2, i1);
07142: b = -(getCompValue(u0, u2, i0));
07143: c = -a * getCompValue(u2, i0) - b * getCompValue(u2, i1);
07144: d2 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
07145:
07146: if (d0 * d1 > 0.0) {
07147: if (d0 * d2 > 0.0) {
07148: return true;
07149: }
07150: }
07151: return false;
07152: }
07153:
07154: // this edge to edge test is based on Franlin Antonio's gem:
07155: // "Faster line segment intersection", in Graphics Gems III, pp 199-202
07156: boolean edgeAgainstEdge(Point3d v0, Point3d u0, Point3d u1,
07157: double aX, double aY, int i0, int i1) {
07158: double bX, bY, cX, cY, e, d, f;
07159:
07160: bX = getCompValue(u0, u1, i0);
07161: bY = getCompValue(u0, u1, i1);
07162: cX = getCompValue(v0, u0, i0);
07163: cY = getCompValue(v0, u0, i1);
07164:
07165: f = aY * bX - aX * bY;
07166: d = bY * cX - bX * cY;
07167: if ((f > 0 && d >= 0 && d <= f) || (f < 0 && d <= 0 && d >= f)) {
07168: e = aX * cY - aY * cX;
07169: if (f > 0) {
07170: if (e >= 0 && e <= f)
07171: return true;
07172: } else {
07173: if (e <= 0 && e >= f)
07174: return true;
07175: }
07176: }
07177:
07178: return false;
07179: }
07180:
07181: boolean edgeAgainstTriEdges(Point3d v0, Point3d v1, Point3d u0,
07182: Point3d u1, Point3d u2, int i0, int i1) {
07183: double aX, aY;
07184:
07185: // aX = v1[i0] - v0[i0];
07186: // aY = v1[i1] - v0[i1];
07187: aX = getCompValue(v1, v0, i0);
07188: aY = getCompValue(v1, v0, i1);
07189:
07190: // test edge u0, u1 against v0, v1
07191: if (edgeAgainstEdge(v0, u0, u1, aX, aY, i0, i1))
07192: return true;
07193: // test edge u1, u2 against v0, v1
07194: if (edgeAgainstEdge(v0, u1, u2, aX, aY, i0, i1))
07195: return true;
07196: // test edge u2, u0 against v0, v1
07197: if (edgeAgainstEdge(v0, u2, u0, aX, aY, i0, i1))
07198: return true;
07199:
07200: return false;
07201:
07202: }
07203:
07204: boolean coplanarTriTri(Vector3d normal, Point3d v0, Point3d v1,
07205: Point3d v2, Point3d u0, Point3d u1, Point3d u2) {
07206:
07207: double nAbsX, nAbsY, nAbsZ;
07208: int i0, i1;
07209:
07210: // first project onto an axis-aligned plane, that maximizes the area
07211: // of the triangles, compute indices i0, i1.
07212: nAbsX = Math.abs(normal.x);
07213: nAbsY = Math.abs(normal.y);
07214: nAbsZ = Math.abs(normal.z);
07215:
07216: if (nAbsX > nAbsY) {
07217: if (nAbsX > nAbsZ) {
07218: i0 = 1; // nAbsX is greatest.
07219: i1 = 2;
07220: } else {
07221: i0 = 0; // nAbsZ is greatest.
07222: i1 = 1;
07223: }
07224: } else { // nAbsX <= nAbsY
07225: if (nAbsZ > nAbsY) {
07226: i0 = 0; // nAbsZ is greatest.
07227: i1 = 1;
07228: } else {
07229: i0 = 0; // nAbsY is greatest.
07230: i1 = 2;
07231: }
07232: }
07233:
07234: // test all edges of triangle 1 against the edges of triangle 2
07235: if (edgeAgainstTriEdges(v0, v1, u0, u1, u2, i0, i1))
07236: return true;
07237:
07238: if (edgeAgainstTriEdges(v1, v2, u0, u1, u2, i0, i1))
07239: return true;
07240:
07241: if (edgeAgainstTriEdges(v2, v0, u0, u1, u2, i0, i1))
07242: return true;
07243:
07244: // finally, test if tri1 is totally contained in tri2 or vice versa.
07245: if (pointInTri(v0, u0, u1, u2, i0, i1))
07246: return true;
07247:
07248: if (pointInTri(u0, v0, v1, v2, i0, i1))
07249: return true;
07250:
07251: return false;
07252: }
07253:
07254: boolean intersectTriPnt(Point3d v0, Point3d v1, Point3d v2,
07255: Point3d u) {
07256:
07257: Vector3d e1 = new Vector3d();
07258: Vector3d e2 = new Vector3d();
07259: Vector3d n1 = new Vector3d();
07260: Vector3d tempV3d = new Vector3d();
07261:
07262: double d1, du;
07263:
07264: // compute plane equation of triange(coord1)
07265: e1.x = v1.x - v0.x;
07266: e1.y = v1.y - v0.y;
07267: e1.z = v1.z - v0.z;
07268:
07269: e2.x = v2.x - v0.x;
07270: e2.y = v2.y - v0.y;
07271: e2.z = v2.z - v0.z;
07272:
07273: n1.cross(e1, e2);
07274:
07275: if (n1.length() == 0.0) {
07276: // System.err.println("(1) Degenerate triangle.");
07277: return false; // Degenerate triangle.
07278: }
07279:
07280: tempV3d.set((Tuple3d) v0);
07281: d1 = -n1.dot(tempV3d); // plane equation 1: n1.x + d1 = 0
07282:
07283: // put u to compute signed distance to the plane.
07284: tempV3d.set((Tuple3d) u);
07285: du = n1.dot(tempV3d) + d1;
07286:
07287: // coplanarity robustness check
07288: if (Math.abs(du) < EPS)
07289: du = 0.0;
07290:
07291: // no intersection occurs
07292: if (du != 0.0) {
07293: return false;
07294: }
07295:
07296: double nAbsX, nAbsY, nAbsZ;
07297: int i0, i1;
07298:
07299: // first project onto an axis-aligned plane, that maximizes the area
07300: // of the triangles, compute indices i0, i1.
07301: nAbsX = Math.abs(n1.x);
07302: nAbsY = Math.abs(n1.y);
07303: nAbsZ = Math.abs(n1.z);
07304:
07305: if (nAbsX > nAbsY) {
07306: if (nAbsX > nAbsZ) {
07307: i0 = 1; // nAbsX is greatest.
07308: i1 = 2;
07309: } else {
07310: i0 = 0; // nAbsZ is greatest.
07311: i1 = 1;
07312: }
07313: } else { // nAbsX <= nAbsY
07314: if (nAbsZ > nAbsY) {
07315: i0 = 0; // nAbsZ is greatest.
07316: i1 = 1;
07317: } else {
07318: i0 = 0; // nAbsY is greatest.
07319: i1 = 2;
07320: }
07321: }
07322:
07323: // finally, test if u is totally contained in tri.
07324: if (pointInTri(u, v0, v1, v2, i0, i1)) {
07325: return true;
07326: }
07327:
07328: return false;
07329: }
07330:
07331: /**
07332: * Return flag indicating whether two triangles intersect. This
07333: * uses Tomas Moller's code for fast triangle-triangle
07334: * intersection from his "Real-Time Rendering" book.
07335: *
07336: * The code is now divisionless. It tests for separating by planes
07337: * parallel to either triangle. If neither separate the
07338: * triangles, then two cases are considered. First case is if the
07339: * normals to the triangles are parallel. In that case, the
07340: * triangles are coplanar and a sequence of tests are made to see
07341: * if edges of each triangle intersect the other triangle. If the
07342: * normals are not parallel, then the two triangles can intersect
07343: * only on the line of intersection of the two planes. The
07344: * intervals of intersection of the triangles with the line of
07345: * intersection of the two planes are computed and tested for
07346: * overlap.
07347: */
07348: boolean intersectTriTri(Point3d v0, Point3d v1, Point3d v2,
07349: Point3d u0, Point3d u1, Point3d u2) {
07350:
07351: // System.err.println("In intersectTriTri ...");
07352: Vector3d e1 = new Vector3d();
07353: Vector3d e2 = new Vector3d();
07354: Vector3d n1 = new Vector3d();
07355: Vector3d n2 = new Vector3d();
07356: Vector3d tempV3d = new Vector3d();
07357:
07358: double d1, d2;
07359: double du0, du1, du2, dv0, dv1, dv2;
07360: double du0du1, du0du2, dv0dv1, dv0dv2;
07361: int index;
07362: double vp0 = 0.0, vp1 = 0.0, vp2 = 0.0;
07363: double up0 = 0.0, up1 = 0.0, up2 = 0.0;
07364: double bb, cc, max;
07365:
07366: // compute plane equation of triange(coord1)
07367: e1.x = v1.x - v0.x;
07368: e1.y = v1.y - v0.y;
07369: e1.z = v1.z - v0.z;
07370:
07371: e2.x = v2.x - v0.x;
07372: e2.y = v2.y - v0.y;
07373: e2.z = v2.z - v0.z;
07374:
07375: n1.cross(e1, e2);
07376:
07377: if (n1.length() == 0.0) {
07378: // System.err.println("(1) Degenerate triangle.");
07379: return false; // Degenerate triangle.
07380: }
07381:
07382: tempV3d.set((Tuple3d) v0);
07383: d1 = -n1.dot(tempV3d); // plane equation 1: n1.x + d1 = 0
07384:
07385: // put u0, u1, and u2 into plane equation 1
07386: // to compute signed distance to the plane.
07387: tempV3d.set((Tuple3d) u0);
07388: du0 = n1.dot(tempV3d) + d1;
07389: tempV3d.set((Tuple3d) u1);
07390: du1 = n1.dot(tempV3d) + d1;
07391: tempV3d.set((Tuple3d) u2);
07392: du2 = n1.dot(tempV3d) + d1;
07393:
07394: // coplanarity robustness check
07395: if (Math.abs(du0) < EPS)
07396: du0 = 0.0;
07397: if (Math.abs(du1) < EPS)
07398: du1 = 0.0;
07399: if (Math.abs(du2) < EPS)
07400: du2 = 0.0;
07401:
07402: du0du1 = du0 * du1;
07403: du0du2 = du0 * du2;
07404:
07405: // same sign on all of them + not equal 0 ?
07406: // no intersection occurs
07407: if (du0du1 > 0.0 && du0du2 > 0.0) {
07408: // System.err.println("In intersectTriTri : du0du1>0.0 && du0du2>0.0");
07409: return false;
07410: }
07411:
07412: // compute plane of triangle(coord2)
07413: e1.x = u1.x - u0.x;
07414: e1.y = u1.y - u0.y;
07415: e1.z = u1.z - u0.z;
07416:
07417: e2.x = u2.x - u0.x;
07418: e2.y = u2.y - u0.y;
07419: e2.z = u2.z - u0.z;
07420:
07421: n2.cross(e1, e2);
07422:
07423: if (n2.length() == 0.0) {
07424: // System.err.println("(2) Degenerate triangle.");
07425: return false; // Degenerate triangle.
07426: }
07427:
07428: tempV3d.set((Tuple3d) u0);
07429: d2 = -n2.dot(tempV3d); // plane equation 2: n2.x + d2 = 0
07430:
07431: // put v0, v1, and v2 into plane equation 2
07432: // to compute signed distance to the plane.
07433: tempV3d.set((Tuple3d) v0);
07434: dv0 = n2.dot(tempV3d) + d2;
07435: tempV3d.set((Tuple3d) v1);
07436: dv1 = n2.dot(tempV3d) + d2;
07437: tempV3d.set((Tuple3d) v2);
07438: dv2 = n2.dot(tempV3d) + d2;
07439:
07440: // coplanarity robustness check
07441: if (Math.abs(dv0) < EPS)
07442: dv0 = 0.0;
07443: if (Math.abs(dv1) < EPS)
07444: dv1 = 0.0;
07445: if (Math.abs(dv2) < EPS)
07446: dv2 = 0.0;
07447:
07448: dv0dv1 = dv0 * dv1;
07449: dv0dv2 = dv0 * dv2;
07450:
07451: // same sign on all of them + not equal 0 ?
07452: // no intersection occurs
07453: if (dv0dv1 > 0.0 && dv0dv2 > 0.0) {
07454: // System.err.println("In intersectTriTri : dv0dv1>0.0 && dv0dv2>0.0");
07455: return false;
07456: }
07457: // compute direction of intersection line.
07458: tempV3d.cross(n1, n2);
07459:
07460: // compute and index to the largest component of tempV3d.
07461: max = Math.abs(tempV3d.x);
07462: index = 0;
07463: bb = Math.abs(tempV3d.y);
07464: cc = Math.abs(tempV3d.z);
07465: if (bb > max) {
07466: max = bb;
07467: index = 1;
07468: }
07469: if (cc > max) {
07470: max = cc;
07471: index = 2;
07472: }
07473:
07474: // this is the simplified projection onto L.
07475:
07476: switch (index) {
07477: case 0:
07478: vp0 = v0.x;
07479: vp1 = v1.x;
07480: vp2 = v2.x;
07481:
07482: up0 = u0.x;
07483: up1 = u1.x;
07484: up2 = u2.x;
07485: break;
07486: case 1:
07487: vp0 = v0.y;
07488: vp1 = v1.y;
07489: vp2 = v2.y;
07490:
07491: up0 = u0.y;
07492: up1 = u1.y;
07493: up2 = u2.y;
07494: break;
07495: case 2:
07496: vp0 = v0.z;
07497: vp1 = v1.z;
07498: vp2 = v2.z;
07499:
07500: up0 = u0.z;
07501: up1 = u1.z;
07502: up2 = u2.z;
07503: break;
07504: }
07505:
07506: // compute intereval for triangle 1.
07507: double a = 0.0, b = 0.0, c = 0.0, x0 = 0.0, x1 = 0.0;
07508: if (dv0dv1 > 0.0) {
07509: // here we know that dv0dv2 <= 0.0 that is dv0 and dv1 are on the same side,
07510: // dv2 on the other side or on the plane.
07511: a = vp2;
07512: b = (vp0 - vp2) * dv2;
07513: c = (vp1 - vp2) * dv2;
07514: x0 = dv2 - dv0;
07515: x1 = dv2 - dv1;
07516: } else if (dv0dv2 > 0.0) {
07517: // here we know that dv0dv1<=0.0
07518: a = vp1;
07519: b = (vp0 - vp1) * dv1;
07520: c = (vp2 - vp1) * dv1;
07521: x0 = dv1 - dv0;
07522: x1 = dv1 - dv2;
07523: } else if ((dv1 * dv2 > 0.0) || (dv0 != 0.0)) {
07524: // here we know that dv0vd1<=0.0 or that dv0!=0.0
07525: a = vp0;
07526: b = (vp1 - vp0) * dv0;
07527: c = (vp2 - vp0) * dv0;
07528: x0 = dv0 - dv1;
07529: x1 = dv0 - dv2;
07530: } else if (dv1 != 0.0) {
07531: a = vp1;
07532: b = (vp0 - vp1) * dv1;
07533: c = (vp2 - vp1) * dv1;
07534: x0 = dv1 - dv0;
07535: x1 = dv1 - dv2;
07536: } else if (dv2 != 0.0) {
07537: a = vp2;
07538: b = (vp0 - vp2) * dv2;
07539: c = (vp1 - vp2) * dv2;
07540: x0 = dv2 - dv0;
07541: x1 = dv2 - dv1;
07542: } else {
07543: // triangles are coplanar
07544: boolean toreturn = coplanarTriTri(n1, v0, v1, v2, u0, u1,
07545: u2);
07546: return toreturn;
07547: }
07548:
07549: // compute intereval for triangle 2.
07550: double d = 0.0, e = 0.0, f = 0.0, y0 = 0.0, y1 = 0.0;
07551: if (du0du1 > 0.0) {
07552: // here we know that du0du2 <= 0.0 that is du0 and du1 are on the same side,
07553: // du2 on the other side or on the plane.
07554: d = up2;
07555: e = (up0 - up2) * du2;
07556: f = (up1 - up2) * du2;
07557: y0 = du2 - du0;
07558: y1 = du2 - du1;
07559: } else if (du0du2 > 0.0) {
07560: // here we know that du0du1<=0.0
07561: d = up1;
07562: e = (up0 - up1) * du1;
07563: f = (up2 - up1) * du1;
07564: y0 = du1 - du0;
07565: y1 = du1 - du2;
07566: } else if ((du1 * du2 > 0.0) || (du0 != 0.0)) {
07567: // here we know that du0du1<=0.0 or that D0!=0.0
07568: d = up0;
07569: e = (up1 - up0) * du0;
07570: f = (up2 - up0) * du0;
07571: y0 = du0 - du1;
07572: y1 = du0 - du2;
07573: } else if (du1 != 0.0) {
07574: d = up1;
07575: e = (up0 - up1) * du1;
07576: f = (up2 - up1) * du1;
07577: y0 = du1 - du0;
07578: y1 = du1 - du2;
07579: } else if (du2 != 0.0) {
07580: d = up2;
07581: e = (up0 - up2) * du2;
07582: f = (up1 - up2) * du2;
07583: y0 = du2 - du0;
07584: y1 = du2 - du1;
07585: } else {
07586: // triangles are coplanar
07587: // System.err.println("In intersectTriTri : coplanarTriTri test 2");
07588: boolean toreturn = coplanarTriTri(n2, v0, v1, v2, u0, u1,
07589: u2);
07590: return toreturn;
07591: }
07592:
07593: double xx, yy, xxyy, tmp, isect1S, isect1E, isect2S, isect2E;
07594: xx = x0 * x1;
07595: yy = y0 * y1;
07596: xxyy = xx * yy;
07597:
07598: tmp = a * xxyy;
07599: isect1S = tmp + b * x1 * yy;
07600: isect1E = tmp + c * x0 * yy;
07601:
07602: tmp = d * xxyy;
07603: isect2S = tmp + e * y1 * xx;
07604: isect2E = tmp + f * y0 * xx;
07605:
07606: // sort so that isect1S <= isect1E
07607: if (isect1S > isect1E) {
07608: tmp = isect1S;
07609: isect1S = isect1E;
07610: isect1E = tmp;
07611: }
07612:
07613: // sort so that isect2S <= isect2E
07614: if (isect2S > isect2E) {
07615: tmp = isect2S;
07616: isect2S = isect2E;
07617: isect2E = tmp;
07618: }
07619:
07620: if (isect1E < isect2S || isect2E < isect1S) {
07621: // System.err.println("In intersectTriTri :isect1E<isect2S || isect2E<isect1S");
07622: // System.err.println("In intersectTriTri : return false");
07623: return false;
07624: }
07625:
07626: // System.err.println("In intersectTriTri : return true");
07627: return true;
07628:
07629: }
07630:
07631: boolean intersectPolygon(Point3d coord1[], Point3d coord2[]) {
07632: int i, j;
07633: Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
07634: Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
07635: Vector3d pNrm = new Vector3d();
07636: boolean epFlag;
07637:
07638: // compute plane normal for coord1.
07639: for (i = 0; i < coord1.length - 1;) {
07640: vec0.x = coord1[i + 1].x - coord1[i].x;
07641: vec0.y = coord1[i + 1].y - coord1[i].y;
07642: vec0.z = coord1[i + 1].z - coord1[i++].z;
07643: if (vec0.length() > 0.0)
07644: break;
07645: }
07646:
07647: for (j = i; j < coord1.length - 1; j++) {
07648: vec1.x = coord1[j + 1].x - coord1[j].x;
07649: vec1.y = coord1[j + 1].y - coord1[j].y;
07650: vec1.z = coord1[j + 1].z - coord1[j].z;
07651: if (vec1.length() > 0.0)
07652: break;
07653: }
07654:
07655: if (j == (coord1.length - 1)) {
07656: // System.err.println("(1) Degenerate polygon.");
07657: return false; // Degenerate polygon.
07658: }
07659:
07660: /*
07661: for(i=0; i<coord1.length; i++)
07662: System.err.println("coord1 P" + i + " " + coord1[i]);
07663: for(i=0; i<coord2.length; i++)
07664: System.err.println("coord2 P" + i + " " + coord2[i]);
07665: */
07666:
07667: pNrm.cross(vec0, vec1);
07668:
07669: if (pNrm.length() == 0.0) {
07670: // System.err.println("(2) Degenerate polygon.");
07671: return false; // Degenerate polygon.
07672: }
07673:
07674: j = 0;
07675: Point3d seg[] = new Point3d[2];
07676: seg[0] = new Point3d();
07677: seg[1] = new Point3d();
07678:
07679: for (i = 0; i < coord2.length; i++) {
07680: if (i < (coord2.length - 1))
07681: epFlag = edgeIntersectPlane(pNrm, coord1[0], coord2[i],
07682: coord2[i + 1], seg[j]);
07683: else
07684: epFlag = edgeIntersectPlane(pNrm, coord1[0], coord2[i],
07685: coord2[0], seg[j]);
07686: if (epFlag) {
07687: if (++j > 1) {
07688: break;
07689: }
07690: }
07691: }
07692:
07693: if (j == 0) {
07694: return false;
07695: }
07696:
07697: if (coord2.length < 3) {
07698: boolean toreturn = pointIntersectPolygon2D(pNrm, coord1,
07699: seg[0]);
07700: return toreturn;
07701: } else {
07702: boolean toreturn = edgeIntersectPolygon2D(pNrm, coord1, seg);
07703: return toreturn;
07704: }
07705: }
07706:
07707: /**
07708: * Return true if triangle or quad intersects with ray and the
07709: * distance is stored in dist[0] and the intersect point in iPnt
07710: * (if iPnt is not null).
07711: */
07712: boolean intersectRay(Point3d coordinates[], PickRay ray,
07713: double dist[], Point3d iPnt) {
07714:
07715: return intersectRayOrSegment(coordinates, ray.direction,
07716: ray.origin, dist, iPnt, false);
07717:
07718: }
07719:
07720: /**
07721: * Return true if triangle or quad intersects with segment and
07722: * the distance is stored in dist[0].
07723: */
07724: boolean intersectSegment(Point3d coordinates[], Point3d start,
07725: Point3d end, double dist[], Point3d iPnt) {
07726: boolean result;
07727: Vector3d direction = new Vector3d();
07728: direction.x = end.x - start.x;
07729: direction.y = end.y - start.y;
07730: direction.z = end.z - start.z;
07731: result = intersectRayOrSegment(coordinates, direction, start,
07732: dist, iPnt, true);
07733: return result;
07734: }
07735:
07736: /**
07737: * Return true if triangle or quad intersects with ray and the distance is
07738: * stored in pr.
07739: */
07740: boolean intersectRayOrSegment(Point3d coordinates[],
07741: Vector3d direction, Point3d origin, double dist[],
07742: Point3d iPnt, boolean isSegment) {
07743: Vector3d vec0, vec1, pNrm, tempV3d;
07744: vec0 = new Vector3d();
07745: vec1 = new Vector3d();
07746: pNrm = new Vector3d();
07747:
07748: double absNrmX, absNrmY, absNrmZ, pD = 0.0;
07749: double pNrmDotrDir = 0.0;
07750:
07751: boolean isIntersect = false;
07752: int i, j, k = 0, l = 0;
07753:
07754: // Compute plane normal.
07755: for (i = 0; i < coordinates.length; i++) {
07756: if (i != coordinates.length - 1) {
07757: l = i + 1;
07758: } else {
07759: l = 0;
07760: }
07761: vec0.x = coordinates[l].x - coordinates[i].x;
07762: vec0.y = coordinates[l].y - coordinates[i].y;
07763: vec0.z = coordinates[l].z - coordinates[i].z;
07764: if (vec0.length() > 0.0) {
07765: break;
07766: }
07767: }
07768:
07769: for (j = l; j < coordinates.length; j++) {
07770: if (j != coordinates.length - 1) {
07771: k = j + 1;
07772: } else {
07773: k = 0;
07774: }
07775: vec1.x = coordinates[k].x - coordinates[j].x;
07776: vec1.y = coordinates[k].y - coordinates[j].y;
07777: vec1.z = coordinates[k].z - coordinates[j].z;
07778: if (vec1.length() > 0.0) {
07779: break;
07780: }
07781: }
07782:
07783: pNrm.cross(vec0, vec1);
07784:
07785: if ((vec1.length() == 0) || (pNrm.length() == 0)) {
07786: // degenerate to line if vec0.length() == 0
07787: // or vec0.length > 0 and vec0 parallel to vec1
07788: k = (l == 0 ? coordinates.length - 1 : l - 1);
07789: isIntersect = intersectLineAndRay(coordinates[l],
07790: coordinates[k], origin, direction, dist, iPnt);
07791:
07792: // put the Vectors on the freelist
07793: return isIntersect;
07794: }
07795:
07796: // It is possible that Quad is degenerate to Triangle
07797: // at this point
07798:
07799: pNrmDotrDir = pNrm.dot(direction);
07800:
07801: // Ray is parallel to plane.
07802: if (pNrmDotrDir == 0.0) {
07803: // Ray is parallel to plane
07804: // Check line/triangle intersection on plane.
07805: for (i = 0; i < coordinates.length; i++) {
07806: if (i != coordinates.length - 1) {
07807: k = i + 1;
07808: } else {
07809: k = 0;
07810: }
07811: if (intersectLineAndRay(coordinates[i], coordinates[k],
07812: origin, direction, dist, iPnt)) {
07813: isIntersect = true;
07814: break;
07815: }
07816: }
07817: return isIntersect;
07818: }
07819:
07820: // Plane equation: (p - p0)*pNrm = 0 or p*pNrm = pD;
07821: tempV3d = new Vector3d();
07822: tempV3d.set((Tuple3d) coordinates[0]);
07823: pD = pNrm.dot(tempV3d);
07824: tempV3d.set((Tuple3d) origin);
07825:
07826: // Substitute Ray equation:
07827: // p = origin + pi.distance*direction
07828: // into the above Plane equation
07829:
07830: dist[0] = (pD - pNrm.dot(tempV3d)) / pNrmDotrDir;
07831:
07832: // Ray intersects the plane behind the ray's origin.
07833: if ((dist[0] < -EPS) || (isSegment && (dist[0] > 1.0 + EPS))) {
07834: // Ray intersects the plane behind the ray's origin
07835: // or intersect point not fall in Segment
07836: return false;
07837: }
07838:
07839: // Now, one thing for sure the ray intersect the plane.
07840: // Find the intersection point.
07841: if (iPnt == null) {
07842: iPnt = new Point3d();
07843: }
07844: iPnt.x = origin.x + direction.x * dist[0];
07845: iPnt.y = origin.y + direction.y * dist[0];
07846: iPnt.z = origin.z + direction.z * dist[0];
07847:
07848: // Project 3d points onto 2d plane
07849: // Find the axis so that area of projection is maximize.
07850: absNrmX = Math.abs(pNrm.x);
07851: absNrmY = Math.abs(pNrm.y);
07852: absNrmZ = Math.abs(pNrm.z);
07853:
07854: // All sign of (y - y0) (x1 - x0) - (x - x0) (y1 - y0)
07855: // must agree.
07856: double sign, t, lastSign = 0;
07857: Point3d p0 = coordinates[coordinates.length - 1];
07858: Point3d p1 = coordinates[0];
07859:
07860: isIntersect = true;
07861:
07862: if (absNrmX > absNrmY) {
07863: if (absNrmX < absNrmZ) {
07864: for (i = 0; i < coordinates.length; i++) {
07865: p0 = coordinates[i];
07866: p1 = (i != coordinates.length - 1 ? coordinates[i + 1]
07867: : coordinates[0]);
07868: sign = (iPnt.y - p0.y) * (p1.x - p0.x)
07869: - (iPnt.x - p0.x) * (p1.y - p0.y);
07870: if (isNonZero(sign)) {
07871: if (sign * lastSign < 0) {
07872: isIntersect = false;
07873: break;
07874: }
07875: lastSign = sign;
07876: } else { // point on line, check inside interval
07877: t = p1.y - p0.y;
07878: if (isNonZero(t)) {
07879: t = (iPnt.y - p0.y) / t;
07880: isIntersect = ((t > -EPS) && (t < 1 + EPS));
07881: break;
07882: } else {
07883: t = p1.x - p0.x;
07884: if (isNonZero(t)) {
07885: t = (iPnt.x - p0.x) / t;
07886: isIntersect = ((t > -EPS) && (t < 1 + EPS));
07887: break;
07888: } else {
07889: // Ignore degenerate line=>point happen when Quad => Triangle.
07890: // Note that by next round sign*lastSign = 0 so it will
07891: // not pass the interest test. This should only happen once in the
07892: // loop because we already check for degenerate geometry before.
07893: }
07894: }
07895: }
07896: }
07897: } else {
07898: for (i = 0; i < coordinates.length; i++) {
07899: p0 = coordinates[i];
07900: p1 = (i != coordinates.length - 1 ? coordinates[i + 1]
07901: : coordinates[0]);
07902: sign = (iPnt.y - p0.y) * (p1.z - p0.z)
07903: - (iPnt.z - p0.z) * (p1.y - p0.y);
07904: if (isNonZero(sign)) {
07905: if (sign * lastSign < 0) {
07906: isIntersect = false;
07907: break;
07908: }
07909: lastSign = sign;
07910: } else { // point on line, check inside interval
07911: t = p1.y - p0.y;
07912:
07913: if (isNonZero(t)) {
07914: t = (iPnt.y - p0.y) / t;
07915: isIntersect = ((t > -EPS) && (t < 1 + EPS));
07916: break;
07917:
07918: } else {
07919: t = p1.z - p0.z;
07920: if (isNonZero(t)) {
07921: t = (iPnt.z - p0.z) / t;
07922: isIntersect = ((t > -EPS) && (t < 1 + EPS));
07923: break;
07924: } else {
07925: //degenerate line=>point
07926: }
07927: }
07928: }
07929: }
07930: }
07931: } else {
07932: if (absNrmY < absNrmZ) {
07933: for (i = 0; i < coordinates.length; i++) {
07934: p0 = coordinates[i];
07935: p1 = (i != coordinates.length - 1 ? coordinates[i + 1]
07936: : coordinates[0]);
07937: sign = (iPnt.y - p0.y) * (p1.x - p0.x)
07938: - (iPnt.x - p0.x) * (p1.y - p0.y);
07939: if (isNonZero(sign)) {
07940: if (sign * lastSign < 0) {
07941: isIntersect = false;
07942: break;
07943: }
07944: lastSign = sign;
07945: } else { // point on line, check inside interval
07946: t = p1.y - p0.y;
07947: if (isNonZero(t)) {
07948: t = (iPnt.y - p0.y) / t;
07949: isIntersect = ((t > -EPS) && (t < 1 + EPS));
07950: break;
07951: } else {
07952: t = p1.x - p0.x;
07953: if (isNonZero(t)) {
07954: t = (iPnt.x - p0.x) / t;
07955: isIntersect = ((t > -EPS) && (t < 1 + EPS));
07956: break;
07957: } else {
07958: //degenerate line=>point
07959: }
07960: }
07961: }
07962: }
07963: } else {
07964: for (i = 0; i < coordinates.length; i++) {
07965: p0 = coordinates[i];
07966: p1 = (i != coordinates.length - 1 ? coordinates[i + 1]
07967: : coordinates[0]);
07968: sign = (iPnt.x - p0.x) * (p1.z - p0.z)
07969: - (iPnt.z - p0.z) * (p1.x - p0.x);
07970: if (isNonZero(sign)) {
07971: if (sign * lastSign < 0) {
07972: isIntersect = false;
07973: break;
07974: }
07975: lastSign = sign;
07976: } else { // point on line, check inside interval
07977: t = p1.x - p0.x;
07978: if (isNonZero(t)) {
07979: t = (iPnt.x - p0.x) / t;
07980: isIntersect = ((t > -EPS) && (t < 1 + EPS));
07981: break;
07982: } else {
07983: t = p1.z - p0.z;
07984: if (isNonZero(t)) {
07985: t = (iPnt.z - p0.z) / t;
07986: isIntersect = ((t > -EPS) && (t < 1 + EPS));
07987: break;
07988: } else {
07989: //degenerate line=>point
07990: }
07991: }
07992: }
07993: }
07994: }
07995: }
07996:
07997: if (isIntersect) {
07998: dist[0] *= direction.length();
07999: }
08000: return isIntersect;
08001: }
08002:
08003: static final boolean isNonZero(double v) {
08004: return ((v > EPS) || (v < -EPS));
08005:
08006: }
08007:
08008: /**
08009: * Return true if point is on the inside of halfspace test. The
08010: * halfspace is partition by the plane of triangle or quad.
08011: */
08012: boolean inside(Point3d coordinates[], PickPoint point, int ccw) {
08013:
08014: Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
08015: Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
08016: Vector3d pNrm = new Vector3d();
08017: double absNrmX, absNrmY, absNrmZ, pD = 0.0;
08018: Vector3d tempV3d = new Vector3d();
08019: double pNrmDotrDir = 0.0;
08020:
08021: double tempD;
08022:
08023: int i, j;
08024:
08025: // Compute plane normal.
08026: for (i = 0; i < coordinates.length - 1;) {
08027: vec0.x = coordinates[i + 1].x - coordinates[i].x;
08028: vec0.y = coordinates[i + 1].y - coordinates[i].y;
08029: vec0.z = coordinates[i + 1].z - coordinates[i++].z;
08030: if (vec0.length() > 0.0)
08031: break;
08032: }
08033:
08034: for (j = i; j < coordinates.length - 1; j++) {
08035: vec1.x = coordinates[j + 1].x - coordinates[j].x;
08036: vec1.y = coordinates[j + 1].y - coordinates[j].y;
08037: vec1.z = coordinates[j + 1].z - coordinates[j].z;
08038: if (vec1.length() > 0.0)
08039: break;
08040: }
08041:
08042: if (j == (coordinates.length - 1)) {
08043: // System.err.println("(1) Degenerate polygon.");
08044: return false; // Degenerate polygon.
08045: }
08046:
08047: /*
08048: System.err.println("Ray orgin : " + ray.origin + " dir " + ray.direction);
08049: System.err.println("Triangle/Quad :");
08050: for(i=0; i<coordinates.length; i++)
08051: System.err.println("P" + i + " " + coordinates[i]);
08052: */
08053:
08054: if (ccw == 0x1)
08055: pNrm.cross(vec0, vec1);
08056: else
08057: pNrm.cross(vec1, vec0);
08058:
08059: if (pNrm.length() == 0.0) {
08060: // System.err.println("(2) Degenerate polygon.");
08061: return false; // Degenerate polygon.
08062: }
08063: // Compute plane D.
08064: tempV3d.set((Tuple3d) coordinates[0]);
08065: pD = pNrm.dot(tempV3d);
08066: tempV3d.set((Tuple3d) point.location);
08067:
08068: return ((pD - pNrm.dot(tempV3d)) <= 0);
08069: }
08070:
08071: boolean intersectPntAndPnt(Point3d pnt1, Point3d pnt2) {
08072: return ((pnt1.x == pnt2.x) && (pnt1.y == pnt2.y) && (pnt1.z == pnt2.z));
08073: }
08074:
08075: boolean intersectPntAndRay(Point3d pnt, Point3d ori, Vector3d dir,
08076: double dist[]) {
08077: int flag = 0;
08078: double temp;
08079:
08080: if (dir.x != 0.0) {
08081: flag = 0;
08082: dist[0] = (pnt.x - ori.x) / dir.x;
08083: } else if (dir.y != 0.0) {
08084: if (pnt.x != ori.x)
08085: return false;
08086: flag = 1;
08087: dist[0] = (pnt.y - ori.y) / dir.y;
08088: } else if (dir.z != 0.0) {
08089: if ((pnt.x != ori.x) || (pnt.y != ori.y))
08090: return false;
08091: flag = 2;
08092: dist[0] = (pnt.z - ori.z) / dir.z;
08093:
08094: } else
08095: return false;
08096:
08097: if (dist[0] < 0.0)
08098: return false;
08099:
08100: if (flag == 0) {
08101: temp = ori.y + dist[0] * dir.y;
08102: if ((pnt.y < (temp - EPS)) || (pnt.y > (temp + EPS)))
08103: return false;
08104: }
08105:
08106: if (flag < 2) {
08107: temp = ori.z + dist[0] * dir.z;
08108: if ((pnt.z < (temp - EPS)) || (pnt.z > (temp + EPS)))
08109: return false;
08110: }
08111:
08112: return true;
08113:
08114: }
08115:
08116: boolean intersectLineAndRay(Point3d start, Point3d end,
08117: Point3d ori, Vector3d dir, double dist[], Point3d iPnt) {
08118:
08119: double m00, m01, m10, m11;
08120: double mInv00, mInv01, mInv10, mInv11;
08121: double dmt, t, s, tmp1, tmp2;
08122: Vector3d lDir;
08123:
08124: // System.err.println("GeometryArrayRetained : intersectLineAndRay");
08125: // System.err.println("start " + start + " end " + end );
08126: // System.err.println("ori " + ori + " dir " + dir);
08127:
08128: lDir = new Vector3d();
08129: lDir.x = (end.x - start.x);
08130: lDir.y = (end.y - start.y);
08131: lDir.z = (end.z - start.z);
08132:
08133: m00 = lDir.x;
08134: m01 = -dir.x;
08135: m10 = lDir.y;
08136: m11 = -dir.y;
08137:
08138: // Get the determinant.
08139: dmt = (m00 * m11) - (m10 * m01);
08140:
08141: if (dmt == 0.0) { // No solution, check degenerate line
08142: boolean isIntersect = false;
08143: if ((lDir.x == 0) && (lDir.y == 0) && (lDir.z == 0)) {
08144: isIntersect = intersectPntAndRay(start, ori, dir, dist);
08145: if (isIntersect && (iPnt != null)) {
08146: iPnt.set(start);
08147: }
08148: }
08149: return isIntersect;
08150: }
08151: // Find the inverse.
08152: tmp1 = 1 / dmt;
08153:
08154: mInv00 = tmp1 * m11;
08155: mInv01 = tmp1 * (-m01);
08156: mInv10 = tmp1 * (-m10);
08157: mInv11 = tmp1 * m00;
08158:
08159: tmp1 = ori.x - start.x;
08160: tmp2 = ori.y - start.y;
08161:
08162: t = mInv00 * tmp1 + mInv01 * tmp2;
08163: s = mInv10 * tmp1 + mInv11 * tmp2;
08164:
08165: if (s < 0.0) { // Before the origin of ray.
08166: // System.err.println("Before the origin of ray " + s);
08167: return false;
08168: }
08169: if ((t < 0) || (t > 1.0)) {// Before or after the end points of line.
08170: // System.err.println("Before or after the end points of line. " + t);
08171: return false;
08172: }
08173:
08174: tmp1 = ori.z + s * dir.z;
08175: tmp2 = start.z + t * lDir.z;
08176:
08177: if ((tmp1 < (tmp2 - EPS)) || (tmp1 > (tmp2 + EPS))) {
08178: // System.err.println("No intersection : tmp1 " + tmp1 + " tmp2 " + tmp2);
08179: return false;
08180: }
08181:
08182: dist[0] = s;
08183:
08184: if (iPnt != null) {
08185: // compute point of intersection.
08186: iPnt.x = ori.x + dir.x * dist[0];
08187: iPnt.y = ori.y + dir.y * dist[0];
08188: iPnt.z = ori.z + dir.z * dist[0];
08189: }
08190:
08191: // System.err.println("Intersected : tmp1 " + tmp1 + " tmp2 " + tmp2);
08192: return true;
08193: }
08194:
08195: /**
08196: Return true if triangle or quad intersects with cylinder. The
08197: distance is stored in dist.
08198: */
08199: boolean intersectCylinder(Point3d coordinates[], PickCylinder cyl,
08200: double dist[], Point3d iPnt) {
08201:
08202: Point3d origin = new Point3d();
08203: Point3d end = new Point3d();
08204: Vector3d direction = new Vector3d();
08205: Point3d iPnt1 = new Point3d();
08206: Vector3d originToIpnt = new Vector3d();
08207:
08208: if (iPnt == null) {
08209: iPnt = new Point3d();
08210: }
08211:
08212: // Get cylinder information
08213: cyl.getOrigin(origin);
08214: cyl.getDirection(direction);
08215: double radius = cyl.getRadius();
08216:
08217: if (cyl instanceof PickCylinderSegment) {
08218: ((PickCylinderSegment) cyl).getEnd(end);
08219: }
08220:
08221: // If the ray intersects, we're good (do not do this if we only have
08222: // a segment
08223: if (coordinates.length > 2) {
08224: if (cyl instanceof PickCylinderRay) {
08225: if (intersectRay(coordinates, new PickRay(origin,
08226: direction), dist, iPnt)) {
08227: return true;
08228: }
08229: } else {
08230: if (intersectSegment(coordinates, origin, end, dist,
08231: iPnt)) {
08232: return true;
08233: }
08234: }
08235: }
08236:
08237: // Ray doesn't intersect, check distance to edges
08238: double sqDistToEdge;
08239: int j;
08240: for (int i = 0; i < coordinates.length; i++) {
08241: j = (i < coordinates.length - 1 ? i + 1 : 0);
08242: if (cyl instanceof PickCylinderSegment) {
08243: sqDistToEdge = Distance.segmentToSegment(origin, end,
08244: coordinates[i], coordinates[j], iPnt1, iPnt,
08245: null);
08246: } else {
08247: sqDistToEdge = Distance.rayToSegment(origin, direction,
08248: coordinates[i], coordinates[j], iPnt1, iPnt,
08249: null);
08250: }
08251: if (sqDistToEdge <= radius * radius) {
08252: originToIpnt.sub(iPnt1, origin);
08253: dist[0] = originToIpnt.length();
08254: return true;
08255: }
08256: }
08257: return false;
08258: }
08259:
08260: /**
08261: Return true if triangle or quad intersects with cone. The
08262: distance is stored in dist.
08263: */
08264: boolean intersectCone(Point3d coordinates[], PickCone cone,
08265: double[] dist, Point3d iPnt) {
08266:
08267: Point3d origin = new Point3d();
08268: Point3d end = new Point3d();
08269: Vector3d direction = new Vector3d();
08270: Vector3d originToIpnt = new Vector3d();
08271: double distance;
08272:
08273: Point3d iPnt1 = new Point3d();
08274: Vector3d vector = new Vector3d();
08275:
08276: if (iPnt == null) {
08277: iPnt = new Point3d();
08278: }
08279: // Get cone information
08280: cone.getOrigin(origin);
08281: cone.getDirection(direction);
08282: double radius;
08283:
08284: if (cone instanceof PickConeSegment) {
08285: ((PickConeSegment) cone).getEnd(end);
08286: }
08287:
08288: // If the ray intersects, we're good (do not do this if we only have
08289: // a segment
08290: if (coordinates.length > 2) {
08291: if (cone instanceof PickConeRay) {
08292: if (intersectRay(coordinates, new PickRay(origin,
08293: direction), dist, iPnt)) {
08294: return true;
08295: }
08296: } else {
08297: if (intersectSegment(coordinates, origin, end, dist,
08298: iPnt)) {
08299: return true;
08300: }
08301: }
08302: }
08303:
08304: // Ray doesn't intersect, check distance to edges
08305: double sqDistToEdge;
08306: int j = 0;
08307: for (int i = 0; i < coordinates.length; i++) {
08308: j = (i < coordinates.length - 1 ? i + 1 : 0);
08309: if (cone instanceof PickConeSegment) {
08310: sqDistToEdge = Distance.segmentToSegment(origin, end,
08311: coordinates[i], coordinates[j], iPnt1, iPnt,
08312: null);
08313: } else {
08314: sqDistToEdge = Distance.rayToSegment(origin, direction,
08315: coordinates[i], coordinates[j], iPnt1, iPnt,
08316: null);
08317: }
08318: originToIpnt.sub(iPnt1, origin);
08319: distance = originToIpnt.length();
08320: radius = Math.tan(cone.getSpreadAngle()) * distance;
08321: if (sqDistToEdge <= radius * radius) {
08322: // System.err.println ("intersectCone: edge "+i+" intersected");
08323: dist[0] = distance;
08324: return true;
08325: }
08326: }
08327: return false;
08328: }
08329:
08330: /**
08331: Return true if point intersects with cylinder and the distance is
08332: stored in dist.
08333: */
08334: boolean intersectCylinder(Point3d pt, PickCylinder cyl,
08335: double[] dist) {
08336:
08337: Point3d origin = new Point3d();
08338: Point3d end = new Point3d();
08339: Vector3d direction = new Vector3d();
08340: Point3d iPnt = new Point3d();
08341: Vector3d originToIpnt = new Vector3d();
08342:
08343: // Get cylinder information
08344: cyl.getOrigin(origin);
08345: cyl.getDirection(direction);
08346: double radius = cyl.getRadius();
08347: double sqDist;
08348:
08349: if (cyl instanceof PickCylinderSegment) {
08350: ((PickCylinderSegment) cyl).getEnd(end);
08351: sqDist = Distance.pointToSegment(pt, origin, end, iPnt,
08352: null);
08353: } else {
08354: sqDist = Distance.pointToRay(pt, origin, direction, iPnt,
08355: null);
08356: }
08357: if (sqDist <= radius * radius) {
08358: originToIpnt.sub(iPnt, origin);
08359: dist[0] = originToIpnt.length();
08360: return true;
08361: }
08362: return false;
08363: }
08364:
08365: /**
08366: Return true if point intersects with cone and the
08367: distance is stored in pi.
08368: */
08369: boolean intersectCone(Point3d pt, PickCone cone, double[] dist) {
08370: Point3d origin = new Point3d();
08371: Point3d end = new Point3d();
08372: Vector3d direction = new Vector3d();
08373: Point3d iPnt = new Point3d();
08374: Vector3d originToIpnt = new Vector3d();
08375:
08376: // Get cone information
08377: cone.getOrigin(origin);
08378: cone.getDirection(direction);
08379: double radius;
08380: double distance;
08381: double sqDist;
08382:
08383: if (iPnt == null) {
08384: iPnt = new Point3d();
08385: }
08386:
08387: if (cone instanceof PickConeSegment) {
08388: ((PickConeSegment) cone).getEnd(end);
08389: sqDist = Distance.pointToSegment(pt, origin, end, iPnt,
08390: null);
08391: } else {
08392: sqDist = Distance.pointToRay(pt, origin, direction, iPnt,
08393: null);
08394: }
08395: originToIpnt.sub(iPnt, origin);
08396: distance = originToIpnt.length();
08397: radius = Math.tan(cone.getSpreadAngle()) * distance;
08398: if (sqDist <= radius * radius) {
08399: dist[0] = distance;
08400: return true;
08401: }
08402: return false;
08403: }
08404:
08405: void setCoordRefBuffer(J3DBuffer coords) {
08406: if (coords != null) {
08407: switch (coords.getBufferType()) {
08408: case J3DBuffer.TYPE_FLOAT:
08409: assert ((FloatBufferWrapper) coords.getBufferImpl())
08410: .isDirect();
08411: break;
08412: case J3DBuffer.TYPE_DOUBLE:
08413: assert ((DoubleBufferWrapper) coords.getBufferImpl())
08414: .isDirect();
08415: break;
08416: case J3DBuffer.TYPE_NULL:
08417: throw new IllegalArgumentException(J3dI18N
08418: .getString("GeometryArray115"));
08419:
08420: default:
08421: throw new IllegalArgumentException(J3dI18N
08422: .getString("GeometryArray116"));
08423: }
08424:
08425: if (this instanceof IndexedGeometryArrayRetained) {
08426: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08427: if (3 * idx.maxCoordIndex >= coords.getBufferImpl()
08428: .limit()) {
08429: throw new ArrayIndexOutOfBoundsException(J3dI18N
08430: .getString("IndexedGeometryArray23"));
08431: }
08432: } else if (coords.getBufferImpl().limit() < (3 * (initialCoordIndex + validVertexCount))) {
08433: throw new ArrayIndexOutOfBoundsException(J3dI18N
08434: .getString("GeometryArray99"));
08435: }
08436: }
08437:
08438: // lock the geometry and start to do real work
08439: boolean isLive = source != null && source.isLive();
08440: if (isLive) {
08441: geomLock.getLock();
08442: }
08443: dirtyFlag |= COORDINATE_CHANGED;
08444: coordRefBuffer = coords;
08445: if (coords == null) {
08446: floatBufferRefCoords = null;
08447: doubleBufferRefCoords = null;
08448: // XXXX: if not mix java array with nio buffer
08449: // vertexType can be used as vertexTypeBuffer
08450: vertexType &= ~PD;
08451: vertexType &= ~PF;
08452: } else {
08453: switch (coords.getBufferType()) {
08454: case J3DBuffer.TYPE_FLOAT:
08455: floatBufferRefCoords = (FloatBufferWrapper) coords
08456: .getBufferImpl();
08457: doubleBufferRefCoords = null;
08458: vertexType |= PF;
08459: vertexType &= ~PD;
08460: break;
08461: case J3DBuffer.TYPE_DOUBLE:
08462: floatBufferRefCoords = null;
08463: doubleBufferRefCoords = (DoubleBufferWrapper) coords
08464: .getBufferImpl();
08465: vertexType |= PD;
08466: vertexType &= ~PF;
08467: break;
08468: default:
08469: break;
08470: }
08471: }
08472:
08473: // need not call setupMirrorVertexPointer() since
08474: // we are not going to set mirror in NIO buffer case
08475: // XXXX: if we need to mix java array with buffer,
08476: // we may need to consider setupMirrorVertexPointer()
08477:
08478: if (isLive) {
08479: geomLock.unLock();
08480: }
08481: if (!inUpdater && source != null) {
08482: if (isLive) {
08483: processCoordsChanged((coords == null));
08484: sendDataChangedMessage(true);
08485: } else {
08486: boundsDirty = true;
08487: }
08488: }
08489:
08490: }
08491:
08492: J3DBuffer getCoordRefBuffer() {
08493: return coordRefBuffer;
08494: }
08495:
08496: void setCoordRefFloat(float[] coords) {
08497:
08498: // If non-null coordinate and vertType is either defined
08499: // to be something other than PF, then issue an error
08500: if (coords != null) {
08501: if ((vertexType & VERTEX_DEFINED) != 0
08502: && (vertexType & VERTEX_DEFINED) != PF) {
08503: throw new IllegalArgumentException(J3dI18N
08504: .getString("GeometryArray98"));
08505: }
08506:
08507: if (this instanceof IndexedGeometryArrayRetained) {
08508: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08509:
08510: if (3 * idx.maxCoordIndex >= coords.length) {
08511: throw new ArrayIndexOutOfBoundsException(J3dI18N
08512: .getString("IndexedGeometryArray23"));
08513: }
08514: } else if (coords.length < 3 * (initialCoordIndex + validVertexCount)) {
08515: throw new ArrayIndexOutOfBoundsException(J3dI18N
08516: .getString("GeometryArray99"));
08517: }
08518: }
08519: boolean isLive = source != null && source.isLive();
08520: if (isLive) {
08521: geomLock.getLock();
08522: }
08523: dirtyFlag |= COORDINATE_CHANGED;
08524:
08525: floatRefCoords = coords;
08526: if (inUpdater
08527: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08528: if (coords == null)
08529: vertexType &= ~PF;
08530: else
08531: vertexType |= PF;
08532: } else {
08533: setupMirrorVertexPointer(PF);
08534: }
08535:
08536: if (isLive) {
08537: geomLock.unLock();
08538: }
08539: if (!inUpdater && source != null) {
08540: if (isLive) {
08541: processCoordsChanged(coords == null);
08542: sendDataChangedMessage(true);
08543: } else {
08544: boundsDirty = true;
08545: }
08546: }
08547: }
08548:
08549: float[] getCoordRefFloat() {
08550: return floatRefCoords;
08551: }
08552:
08553: void setCoordRefDouble(double[] coords) {
08554:
08555: if (coords != null) {
08556: if ((vertexType & VERTEX_DEFINED) != 0
08557: && (vertexType & VERTEX_DEFINED) != PD) {
08558: throw new IllegalArgumentException(J3dI18N
08559: .getString("GeometryArray98"));
08560: }
08561:
08562: if (this instanceof IndexedGeometryArrayRetained) {
08563: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08564: if (3 * idx.maxCoordIndex >= coords.length) {
08565: throw new ArrayIndexOutOfBoundsException(J3dI18N
08566: .getString("IndexedGeometryArray23"));
08567: }
08568: } else if (coords.length < 3 * (initialCoordIndex + validVertexCount)) {
08569: throw new ArrayIndexOutOfBoundsException(J3dI18N
08570: .getString("GeometryArray99"));
08571: }
08572: }
08573: boolean isLive = source != null && source.isLive();
08574: if (isLive) {
08575: geomLock.getLock();
08576: }
08577: dirtyFlag |= COORDINATE_CHANGED;
08578: doubleRefCoords = coords;
08579: if (inUpdater
08580: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08581: if (coords == null)
08582: vertexType &= ~PD;
08583: else
08584: vertexType |= PD;
08585: } else {
08586: setupMirrorVertexPointer(PD);
08587: }
08588: if (isLive) {
08589: geomLock.unLock();
08590: }
08591: if (!inUpdater && source != null) {
08592: if (isLive) {
08593: processCoordsChanged(coords == null);
08594: sendDataChangedMessage(true);
08595: } else {
08596: boundsDirty = true;
08597: }
08598: }
08599: }
08600:
08601: double[] getCoordRefDouble() {
08602: return doubleRefCoords;
08603: }
08604:
08605: void setCoordRef3f(Point3f[] coords) {
08606:
08607: if (coords != null) {
08608: if ((vertexType & VERTEX_DEFINED) != 0
08609: && (vertexType & VERTEX_DEFINED) != P3F) {
08610: throw new IllegalArgumentException(J3dI18N
08611: .getString("GeometryArray98"));
08612: }
08613:
08614: if (this instanceof IndexedGeometryArrayRetained) {
08615: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08616:
08617: if (idx.maxCoordIndex >= coords.length) {
08618: throw new ArrayIndexOutOfBoundsException(J3dI18N
08619: .getString("IndexedGeometryArray23"));
08620: }
08621: } else if (coords.length < (initialCoordIndex + validVertexCount)) {
08622: throw new ArrayIndexOutOfBoundsException(J3dI18N
08623: .getString("GeometryArray99"));
08624: }
08625: }
08626: boolean isLive = source != null && source.isLive();
08627: if (isLive) {
08628: geomLock.getLock();
08629: }
08630: dirtyFlag |= COORDINATE_CHANGED;
08631: p3fRefCoords = coords;
08632: if (inUpdater
08633: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08634: if (coords == null)
08635: vertexType &= ~P3F;
08636: else
08637: vertexType |= P3F;
08638: } else {
08639: setupMirrorVertexPointer(P3F);
08640: }
08641: if (isLive) {
08642: geomLock.unLock();
08643: }
08644: if (!inUpdater && source != null) {
08645: if (isLive) {
08646: processCoordsChanged(coords == null);
08647: sendDataChangedMessage(true);
08648: } else {
08649: boundsDirty = true;
08650: }
08651: }
08652: }
08653:
08654: Point3f[] getCoordRef3f() {
08655: return p3fRefCoords;
08656:
08657: }
08658:
08659: void setCoordRef3d(Point3d[] coords) {
08660:
08661: if (coords != null) {
08662: if ((vertexType & VERTEX_DEFINED) != 0
08663: && (vertexType & VERTEX_DEFINED) != P3D) {
08664: throw new IllegalArgumentException(J3dI18N
08665: .getString("GeometryArray98"));
08666: }
08667:
08668: if (this instanceof IndexedGeometryArrayRetained) {
08669: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08670:
08671: if (idx.maxCoordIndex >= coords.length) {
08672: throw new ArrayIndexOutOfBoundsException(J3dI18N
08673: .getString("IndexedGeometryArray23"));
08674: }
08675: } else if (coords.length < (initialCoordIndex + validVertexCount)) {
08676: throw new ArrayIndexOutOfBoundsException(J3dI18N
08677: .getString("GeometryArray99"));
08678: }
08679: }
08680: boolean isLive = source != null && source.isLive();
08681: if (isLive) {
08682: geomLock.getLock();
08683: }
08684: dirtyFlag |= COORDINATE_CHANGED;
08685: p3dRefCoords = coords;
08686: if (inUpdater
08687: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08688: if (coords == null)
08689: vertexType &= ~P3D;
08690: else
08691: vertexType |= P3D;
08692: } else {
08693: setupMirrorVertexPointer(P3D);
08694: }
08695: if (isLive) {
08696: geomLock.unLock();
08697: }
08698: if (!inUpdater && source != null) {
08699: if (isLive) {
08700: processCoordsChanged(coords == null);
08701: sendDataChangedMessage(true);
08702: } else {
08703: boundsDirty = true;
08704: }
08705: }
08706: }
08707:
08708: Point3d[] getCoordRef3d() {
08709: return p3dRefCoords;
08710: }
08711:
08712: void setColorRefFloat(float[] colors) {
08713:
08714: if (colors != null) {
08715: if ((vertexType & COLOR_DEFINED) != 0
08716: && (vertexType & COLOR_DEFINED) != CF) {
08717: throw new IllegalArgumentException(J3dI18N
08718: .getString("GeometryArray98"));
08719: }
08720:
08721: if ((vertexFormat & GeometryArray.COLOR) == 0) {
08722: throw new IllegalStateException(J3dI18N
08723: .getString("GeometryArray123"));
08724: }
08725:
08726: if (this instanceof IndexedGeometryArrayRetained) {
08727: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08728:
08729: if (getColorStride() * idx.maxColorIndex >= colors.length) {
08730: throw new ArrayIndexOutOfBoundsException(J3dI18N
08731: .getString("IndexedGeometryArray24"));
08732: }
08733: } else if (colors.length < getColorStride()
08734: * (initialColorIndex + validVertexCount)) {
08735: throw new ArrayIndexOutOfBoundsException(J3dI18N
08736: .getString("GeometryArray112"));
08737: }
08738: }
08739:
08740: boolean isLive = source != null && source.isLive();
08741: if (isLive) {
08742: geomLock.getLock();
08743: }
08744: dirtyFlag |= COLOR_CHANGED;
08745: colorChanged = 0xffff;
08746: floatRefColors = colors;
08747: if (inUpdater
08748: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08749: if (colors == null)
08750: vertexType &= ~CF;
08751: else
08752: vertexType |= CF;
08753: } else {
08754: setupMirrorColorPointer(CF, false);
08755: }
08756:
08757: if (isLive) {
08758: geomLock.unLock();
08759: }
08760: if (!inUpdater && isLive) {
08761: sendDataChangedMessage(false);
08762: }
08763:
08764: }
08765:
08766: float[] getColorRefFloat() {
08767: return floatRefColors;
08768: }
08769:
08770: // set the color with nio buffer
08771: void setColorRefBuffer(J3DBuffer colors) {
08772: if (colors != null) {
08773: switch (colors.getBufferType()) {
08774: case J3DBuffer.TYPE_FLOAT:
08775: assert ((FloatBufferWrapper) colors.getBufferImpl())
08776: .isDirect();
08777: break;
08778: case J3DBuffer.TYPE_BYTE:
08779: assert ((ByteBufferWrapper) colors.getBufferImpl())
08780: .isDirect();
08781: break;
08782: case J3DBuffer.TYPE_NULL:
08783: throw new IllegalArgumentException(J3dI18N
08784: .getString("GeometryArray115"));
08785:
08786: default:
08787: throw new IllegalArgumentException(J3dI18N
08788: .getString("GeometryArray116"));
08789: }
08790:
08791: if ((vertexFormat & GeometryArray.COLOR) == 0) {
08792: throw new IllegalStateException(J3dI18N
08793: .getString("GeometryArray123"));
08794: }
08795:
08796: if (this instanceof IndexedGeometryArrayRetained) {
08797: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08798:
08799: if (getColorStride() * idx.maxColorIndex >= colors
08800: .getBufferImpl().limit()) {
08801: throw new ArrayIndexOutOfBoundsException(J3dI18N
08802: .getString("IndexedGeometryArray24"));
08803: }
08804: } else if (colors.getBufferImpl().limit() < getColorStride()
08805: * (initialColorIndex + validVertexCount)) {
08806: throw new ArrayIndexOutOfBoundsException(J3dI18N
08807: .getString("GeometryArray112"));
08808: }
08809: }
08810:
08811: boolean isLive = source != null && source.isLive();
08812: if (isLive) {
08813: geomLock.getLock();
08814: }
08815: dirtyFlag |= COLOR_CHANGED;
08816: colorChanged = 0xffff;
08817: colorRefBuffer = colors;
08818: if (colors == null) {
08819: floatBufferRefColors = null;
08820: byteBufferRefColors = null;
08821: } else {
08822: switch (colors.getBufferType()) {
08823: case J3DBuffer.TYPE_FLOAT:
08824: floatBufferRefColors = (FloatBufferWrapper) colors
08825: .getBufferImpl();
08826: byteBufferRefColors = null;
08827: break;
08828:
08829: case J3DBuffer.TYPE_BYTE:
08830: byteBufferRefColors = (ByteBufferWrapper) colors
08831: .getBufferImpl();
08832: floatBufferRefColors = null;
08833: break;
08834: default:
08835: break;
08836: }
08837: }
08838: if (inUpdater
08839: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08840: if (colors == null) {
08841: vertexType &= ~CF;
08842: vertexType &= ~CUB;
08843: } else {
08844: switch (colors.getBufferType()) {
08845: case J3DBuffer.TYPE_FLOAT:
08846: vertexType |= CF;
08847: vertexType &= ~CUB;
08848: break;
08849:
08850: case J3DBuffer.TYPE_BYTE:
08851: vertexType |= CUB;
08852: vertexType &= ~CF;
08853: break;
08854: default:
08855: break;
08856: }
08857: }
08858: } else {
08859: setupMirrorColorPointer(CF | CUB, false);
08860: }
08861:
08862: if (isLive) {
08863: geomLock.unLock();
08864: }
08865:
08866: if (!inUpdater && isLive) {
08867: sendDataChangedMessage(false);
08868: }
08869: }
08870:
08871: // return the color data in nio buffer format
08872: J3DBuffer getColorRefBuffer() {
08873: return colorRefBuffer;
08874: }
08875:
08876: void setColorRefByte(byte[] colors) {
08877:
08878: if (colors != null) {
08879: if ((vertexType & COLOR_DEFINED) != 0
08880: && (vertexType & COLOR_DEFINED) != CUB) {
08881: throw new IllegalArgumentException(J3dI18N
08882: .getString("GeometryArray98"));
08883: }
08884:
08885: if ((vertexFormat & GeometryArray.COLOR) == 0) {
08886: throw new IllegalStateException(J3dI18N
08887: .getString("GeometryArray123"));
08888: }
08889:
08890: if (this instanceof IndexedGeometryArrayRetained) {
08891: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08892:
08893: if (getColorStride() * idx.maxColorIndex >= colors.length) {
08894: throw new ArrayIndexOutOfBoundsException(J3dI18N
08895: .getString("IndexedGeometryArray24"));
08896: }
08897: } else if (colors.length < getColorStride()
08898: * (initialColorIndex + validVertexCount)) {
08899: throw new ArrayIndexOutOfBoundsException(J3dI18N
08900: .getString("GeometryArray112"));
08901: }
08902: }
08903: boolean isLive = source != null && source.isLive();
08904: if (isLive) {
08905: geomLock.getLock();
08906: }
08907: dirtyFlag |= COLOR_CHANGED;
08908: colorChanged = 0xffff;
08909: byteRefColors = colors;
08910: if (inUpdater
08911: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08912: if (colors == null)
08913: vertexType &= ~CUB;
08914: else
08915: vertexType |= CUB;
08916: } else {
08917: setupMirrorColorPointer(CUB, false);
08918: }
08919: if (isLive) {
08920: geomLock.unLock();
08921: }
08922:
08923: if (!inUpdater && isLive) {
08924: sendDataChangedMessage(false);
08925: }
08926:
08927: }
08928:
08929: byte[] getColorRefByte() {
08930: return byteRefColors;
08931: }
08932:
08933: void setColorRef3f(Color3f[] colors) {
08934:
08935: if (colors != null) {
08936: if ((vertexType & COLOR_DEFINED) != 0
08937: && (vertexType & COLOR_DEFINED) != C3F) {
08938: throw new IllegalArgumentException(J3dI18N
08939: .getString("GeometryArray98"));
08940: }
08941:
08942: if ((vertexFormat & GeometryArray.COLOR_3) == 0) {
08943: throw new IllegalStateException(J3dI18N
08944: .getString("GeometryArray92"));
08945: }
08946:
08947: if (this instanceof IndexedGeometryArrayRetained) {
08948: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08949: if (idx.maxColorIndex >= colors.length) {
08950: throw new ArrayIndexOutOfBoundsException(J3dI18N
08951: .getString("IndexedGeometryArray24"));
08952: }
08953: } else if (colors.length < (initialColorIndex + validVertexCount)) {
08954: throw new ArrayIndexOutOfBoundsException(J3dI18N
08955: .getString("GeometryArray112"));
08956: }
08957: }
08958:
08959: boolean isLive = source != null && source.isLive();
08960: if (isLive) {
08961: geomLock.getLock();
08962: }
08963: dirtyFlag |= COLOR_CHANGED;
08964: colorChanged = 0xffff;
08965: c3fRefColors = colors;
08966: if (inUpdater
08967: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08968: if (colors == null)
08969: vertexType &= ~C3F;
08970: else
08971: vertexType |= C3F;
08972: } else {
08973: setupMirrorColorPointer(C3F, false);
08974: }
08975:
08976: if (isLive) {
08977: geomLock.unLock();
08978: }
08979:
08980: if (!inUpdater && isLive) {
08981: sendDataChangedMessage(false);
08982: }
08983:
08984: }
08985:
08986: Color3f[] getColorRef3f() {
08987: return c3fRefColors;
08988: }
08989:
08990: void setColorRef4f(Color4f[] colors) {
08991:
08992: if (colors != null) {
08993: if ((vertexType & COLOR_DEFINED) != 0
08994: && (vertexType & COLOR_DEFINED) != C4F) {
08995: throw new IllegalArgumentException(J3dI18N
08996: .getString("GeometryArray98"));
08997: }
08998: if ((vertexFormat & GeometryArray.COLOR_4) == 0) {
08999: throw new IllegalStateException(J3dI18N
09000: .getString("GeometryArray93"));
09001: }
09002:
09003: if (this instanceof IndexedGeometryArrayRetained) {
09004: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09005: if (idx.maxColorIndex >= colors.length) {
09006: throw new ArrayIndexOutOfBoundsException(J3dI18N
09007: .getString("IndexedGeometryArray24"));
09008: }
09009: } else if (colors.length < (initialColorIndex + validVertexCount)) {
09010: throw new ArrayIndexOutOfBoundsException(J3dI18N
09011: .getString("GeometryArray112"));
09012: }
09013: }
09014: boolean isLive = source != null && source.isLive();
09015: if (isLive) {
09016: geomLock.getLock();
09017: }
09018: dirtyFlag |= COLOR_CHANGED;
09019: colorChanged = 0xffff;
09020: c4fRefColors = colors;
09021: if (inUpdater
09022: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09023: if (colors == null)
09024: vertexType &= ~C4F;
09025: else
09026: vertexType |= C4F;
09027: } else {
09028: setupMirrorColorPointer(C4F, false);
09029: }
09030: if (isLive) {
09031: geomLock.unLock();
09032: }
09033:
09034: if (!inUpdater && isLive) {
09035: sendDataChangedMessage(false);
09036: }
09037: }
09038:
09039: Color4f[] getColorRef4f() {
09040: return c4fRefColors;
09041: }
09042:
09043: void setColorRef3b(Color3b[] colors) {
09044:
09045: if (colors != null) {
09046:
09047: if ((vertexType & COLOR_DEFINED) != 0
09048: && (vertexType & COLOR_DEFINED) != C3UB) {
09049: throw new IllegalArgumentException(J3dI18N
09050: .getString("GeometryArray98"));
09051: }
09052:
09053: if ((vertexFormat & GeometryArray.COLOR_3) == 0) {
09054: throw new IllegalStateException(J3dI18N
09055: .getString("GeometryArray92"));
09056: }
09057:
09058: if (this instanceof IndexedGeometryArrayRetained) {
09059: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09060:
09061: if (idx.maxColorIndex >= colors.length) {
09062: throw new ArrayIndexOutOfBoundsException(J3dI18N
09063: .getString("IndexedGeometryArray24"));
09064: }
09065: } else if (colors.length < (initialColorIndex + validVertexCount)) {
09066: throw new ArrayIndexOutOfBoundsException(J3dI18N
09067: .getString("GeometryArray112"));
09068: }
09069: }
09070:
09071: boolean isLive = source != null && source.isLive();
09072: if (isLive) {
09073: geomLock.getLock();
09074: }
09075: dirtyFlag |= COLOR_CHANGED;
09076: colorChanged = 0xffff;
09077: c3bRefColors = colors;
09078: if (inUpdater
09079: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09080: if (colors == null)
09081: vertexType &= ~C3UB;
09082: else
09083: vertexType |= C3UB;
09084: } else {
09085: setupMirrorColorPointer(C3UB, false);
09086: }
09087:
09088: if (isLive) {
09089: geomLock.unLock();
09090: }
09091:
09092: if (!inUpdater && isLive) {
09093: sendDataChangedMessage(false);
09094: }
09095: }
09096:
09097: Color3b[] getColorRef3b() {
09098: return c3bRefColors;
09099: }
09100:
09101: void setColorRef4b(Color4b[] colors) {
09102:
09103: if (colors != null) {
09104: if ((vertexType & COLOR_DEFINED) != 0
09105: && (vertexType & COLOR_DEFINED) != C4UB) {
09106: throw new IllegalArgumentException(J3dI18N
09107: .getString("GeometryArray98"));
09108: }
09109:
09110: if ((vertexFormat & GeometryArray.COLOR_4) == 0) {
09111: throw new IllegalStateException(J3dI18N
09112: .getString("GeometryArray93"));
09113: }
09114:
09115: if (this instanceof IndexedGeometryArrayRetained) {
09116: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09117:
09118: if (idx.maxColorIndex >= colors.length) {
09119: throw new ArrayIndexOutOfBoundsException(J3dI18N
09120: .getString("IndexedGeometryArray24"));
09121: }
09122: } else if (colors.length < (initialColorIndex + validVertexCount)) {
09123: throw new ArrayIndexOutOfBoundsException(J3dI18N
09124: .getString("GeometryArray112"));
09125: }
09126: }
09127: boolean isLive = source != null && source.isLive();
09128: if (isLive) {
09129: geomLock.getLock();
09130: }
09131: dirtyFlag |= COLOR_CHANGED;
09132: colorChanged = 0xffff;
09133: c4bRefColors = colors;
09134: if (inUpdater
09135: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09136: if (colors == null)
09137: vertexType &= ~C4UB;
09138: else
09139: vertexType |= C4UB;
09140: } else {
09141: setupMirrorColorPointer(C4UB, false);
09142: }
09143:
09144: if (isLive) {
09145: geomLock.unLock();
09146: }
09147: if (!inUpdater && isLive) {
09148: sendDataChangedMessage(false);
09149: }
09150: }
09151:
09152: Color4b[] getColorRef4b() {
09153: return c4bRefColors;
09154: }
09155:
09156: void setNormalRefFloat(float[] normals) {
09157:
09158: if (normals != null) {
09159: if ((vertexType & NORMAL_DEFINED) != 0
09160: && (vertexType & NORMAL_DEFINED) != NF) {
09161: throw new IllegalArgumentException(J3dI18N
09162: .getString("GeometryArray98"));
09163: }
09164:
09165: if ((vertexFormat & GeometryArray.NORMALS) == 0) {
09166: throw new IllegalStateException(J3dI18N
09167: .getString("GeometryArray122"));
09168: }
09169:
09170: if (this instanceof IndexedGeometryArrayRetained) {
09171: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09172:
09173: if (idx.maxNormalIndex * 3 >= normals.length) {
09174: throw new ArrayIndexOutOfBoundsException(J3dI18N
09175: .getString("IndexedGeometryArray26"));
09176: }
09177: } else if (normals.length < 3 * (initialNormalIndex + validVertexCount)) {
09178: throw new ArrayIndexOutOfBoundsException(J3dI18N
09179: .getString("GeometryArray111"));
09180: }
09181: }
09182: boolean isLive = source != null && source.isLive();
09183: if (isLive) {
09184: geomLock.getLock();
09185: }
09186: dirtyFlag |= NORMAL_CHANGED;
09187: floatRefNormals = normals;
09188: if (inUpdater
09189: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09190: if (normals == null)
09191: vertexType &= ~NF;
09192: else
09193: vertexType |= NF;
09194: } else {
09195: setupMirrorNormalPointer(NF);
09196: }
09197: if (isLive) {
09198: geomLock.unLock();
09199: }
09200: if (!inUpdater && isLive) {
09201: sendDataChangedMessage(false);
09202: }
09203:
09204: }
09205:
09206: float[] getNormalRefFloat() {
09207: return floatRefNormals;
09208: }
09209:
09210: // setup the normal with nio buffer
09211: void setNormalRefBuffer(J3DBuffer normals) {
09212:
09213: FloatBufferWrapper bufferImpl = null;
09214:
09215: if (normals != null) {
09216: if (normals.getBufferType() != J3DBuffer.TYPE_FLOAT)
09217: throw new IllegalArgumentException(J3dI18N
09218: .getString("GeometryArray116"));
09219:
09220: bufferImpl = (FloatBufferWrapper) normals.getBufferImpl();
09221:
09222: assert bufferImpl.isDirect();
09223:
09224: if ((vertexFormat & GeometryArray.NORMALS) == 0) {
09225: throw new IllegalStateException(J3dI18N
09226: .getString("GeometryArray122"));
09227: }
09228:
09229: if (this instanceof IndexedGeometryArrayRetained) {
09230: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09231: if (idx.maxNormalIndex * 3 >= ((FloatBufferWrapper) normals
09232: .getBufferImpl()).limit()) {
09233: throw new ArrayIndexOutOfBoundsException(J3dI18N
09234: .getString("IndexedGeometryArray26"));
09235: }
09236: } else if (bufferImpl.limit() < 3 * (initialNormalIndex + validVertexCount)) {
09237: throw new ArrayIndexOutOfBoundsException(J3dI18N
09238: .getString("GeometryArray111"));
09239: }
09240: }
09241: boolean isLive = source != null && source.isLive();
09242: if (isLive) {
09243: geomLock.getLock();
09244: }
09245: dirtyFlag |= NORMAL_CHANGED;
09246: normalRefBuffer = normals;
09247:
09248: if (normals == null) {
09249: vertexType &= ~NF;
09250: floatBufferRefNormals = null;
09251: } else {
09252: vertexType |= NF;
09253: floatBufferRefNormals = bufferImpl;
09254: }
09255: if (isLive) {
09256: geomLock.unLock();
09257: }
09258: if (!inUpdater && isLive) {
09259: sendDataChangedMessage(false);
09260: }
09261: }
09262:
09263: J3DBuffer getNormalRefBuffer() {
09264: return normalRefBuffer;
09265: }
09266:
09267: void setNormalRef3f(Vector3f[] normals) {
09268:
09269: if (normals != null) {
09270: if ((vertexType & NORMAL_DEFINED) != 0
09271: && (vertexType & NORMAL_DEFINED) != N3F) {
09272: throw new IllegalArgumentException(J3dI18N
09273: .getString("GeometryArray98"));
09274: }
09275:
09276: if ((vertexFormat & GeometryArray.NORMALS) == 0) {
09277: throw new IllegalStateException(J3dI18N
09278: .getString("GeometryArray122"));
09279: }
09280:
09281: if (this instanceof IndexedGeometryArrayRetained) {
09282: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09283: if (idx.maxNormalIndex >= normals.length) {
09284: throw new ArrayIndexOutOfBoundsException(J3dI18N
09285: .getString("IndexedGeometryArray26"));
09286: }
09287: } else if (normals.length < (initialNormalIndex + validVertexCount)) {
09288: throw new ArrayIndexOutOfBoundsException(J3dI18N
09289: .getString("GeometryArray111"));
09290: }
09291: }
09292: boolean isLive = source != null && source.isLive();
09293: if (isLive) {
09294: geomLock.getLock();
09295: }
09296: dirtyFlag |= NORMAL_CHANGED;
09297: v3fRefNormals = normals;
09298: if (inUpdater
09299: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09300: if (normals == null)
09301: vertexType &= ~N3F;
09302: else
09303: vertexType |= N3F;
09304: } else {
09305: setupMirrorNormalPointer(N3F);
09306: }
09307: if (isLive) {
09308: geomLock.unLock();
09309: }
09310: if (!inUpdater && isLive) {
09311: sendDataChangedMessage(false);
09312: }
09313: }
09314:
09315: Vector3f[] getNormalRef3f() {
09316: return v3fRefNormals;
09317: }
09318:
09319: final int getColorStride() {
09320: return ((vertexFormat & GeometryArray.WITH_ALPHA) != 0 ? 4 : 3);
09321: }
09322:
09323: final int getTexStride() {
09324: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
09325: return 2;
09326: }
09327: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
09328: return 3;
09329: }
09330: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
09331: return 4;
09332: }
09333:
09334: throw new ArrayIndexOutOfBoundsException(J3dI18N
09335: .getString("GeometryArray121"));
09336: }
09337:
09338: void setTexCoordRefFloat(int texCoordSet, float[] texCoords) {
09339:
09340: if (texCoordType != 0 && texCoordType != TF) {
09341: if (texCoords != null) {
09342: throw new IllegalArgumentException(J3dI18N
09343: .getString("GeometryArray98"));
09344: }
09345: return;
09346: }
09347:
09348: if (texCoords != null) {
09349:
09350: int ts = getTexStride();
09351:
09352: if (this instanceof IndexedGeometryArrayRetained) {
09353: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09354:
09355: if (idx.maxTexCoordIndices[texCoordSet] * ts >= texCoords.length) {
09356: throw new ArrayIndexOutOfBoundsException(J3dI18N
09357: .getString("IndexedGeometryArray25"));
09358: }
09359: } else if (texCoords.length < ts
09360: * (initialTexCoordIndex[texCoordSet] + validVertexCount)) {
09361: throw new ArrayIndexOutOfBoundsException(J3dI18N
09362: .getString("GeometryArray113"));
09363: }
09364: }
09365: boolean isLive = source != null && source.isLive();
09366: if (isLive) {
09367: geomLock.getLock();
09368: }
09369: dirtyFlag |= TEXTURE_CHANGED;
09370: refTexCoords[texCoordSet] = texCoords;
09371: if (inUpdater
09372: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09373: texCoordType = TF;
09374: validateTexCoordPointerType();
09375: } else {
09376: setupMirrorTexCoordPointer(texCoordSet, TF);
09377: }
09378: if (isLive) {
09379: geomLock.unLock();
09380: }
09381: if (!inUpdater && isLive) {
09382: sendDataChangedMessage(false);
09383: }
09384: }
09385:
09386: float[] getTexCoordRefFloat(int texCoordSet) {
09387: return ((float[]) refTexCoords[texCoordSet]);
09388: }
09389:
09390: // set the tex coord with nio buffer
09391: void setTexCoordRefBuffer(int texCoordSet, J3DBuffer texCoords) {
09392:
09393: FloatBufferWrapper bufferImpl = null;
09394:
09395: if (texCoords != null) {
09396: if (texCoords.getBufferType() != J3DBuffer.TYPE_FLOAT)
09397: throw new IllegalArgumentException(J3dI18N
09398: .getString("GeometryArray116"));
09399:
09400: bufferImpl = (FloatBufferWrapper) texCoords.getBufferImpl();
09401: int bufferSize = bufferImpl.limit();
09402:
09403: assert bufferImpl.isDirect();
09404:
09405: int ts = getTexStride();
09406:
09407: if (this instanceof IndexedGeometryArrayRetained) {
09408: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09409: if (idx.maxTexCoordIndices[texCoordSet] * ts >= bufferSize) {
09410: throw new ArrayIndexOutOfBoundsException(J3dI18N
09411: .getString("IndexedGeometryArray25"));
09412: }
09413: } else if (bufferSize < ts
09414: * (initialTexCoordIndex[texCoordSet] + validVertexCount)) {
09415: throw new ArrayIndexOutOfBoundsException(J3dI18N
09416: .getString("GeometryArray113"));
09417: }
09418: }
09419: boolean isLive = source != null && source.isLive();
09420: if (isLive) {
09421: geomLock.getLock();
09422: }
09423: dirtyFlag |= TEXTURE_CHANGED;
09424: // refTexCoordsBuffer contains J3DBuffer object for tex coord
09425: refTexCoordsBuffer[texCoordSet] = texCoords;
09426: if (texCoords == null) {
09427: refTexCoords[texCoordSet] = null;
09428: } else {
09429: // refTexCoords contains NIOBuffer object for tex coord
09430: refTexCoords[texCoordSet] = bufferImpl.getBufferAsObject();
09431: }
09432: texCoordType = TF;
09433: validateTexCoordPointerType();
09434: if (isLive) {
09435: geomLock.unLock();
09436: }
09437: if (!inUpdater && isLive) {
09438: sendDataChangedMessage(false);
09439: }
09440: }
09441:
09442: J3DBuffer getTexCoordRefBuffer(int texCoordSet) {
09443: return (J3DBuffer) (refTexCoordsBuffer[texCoordSet]);
09444: }
09445:
09446: void setTexCoordRef2f(int texCoordSet, TexCoord2f[] texCoords) {
09447:
09448: if (texCoordType != 0 && texCoordType != T2F) {
09449: if (texCoords != null) {
09450: throw new IllegalArgumentException(J3dI18N
09451: .getString("GeometryArray98"));
09452: }
09453: return;
09454: }
09455:
09456: if (texCoords != null) {
09457: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) == 0) {
09458: throw new IllegalStateException(J3dI18N
09459: .getString("GeometryArray94"));
09460: }
09461:
09462: if (this instanceof IndexedGeometryArrayRetained) {
09463: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09464:
09465: if (idx.maxTexCoordIndices[texCoordSet] >= texCoords.length) {
09466: throw new ArrayIndexOutOfBoundsException(J3dI18N
09467: .getString("IndexedGeometryArray25"));
09468: }
09469: } else if (texCoords.length < (initialTexCoordIndex[texCoordSet] + validVertexCount)) {
09470: throw new ArrayIndexOutOfBoundsException(J3dI18N
09471: .getString("GeometryArray113"));
09472: }
09473:
09474: }
09475: boolean isLive = source != null && source.isLive();
09476: if (isLive) {
09477: geomLock.getLock();
09478: }
09479: dirtyFlag |= TEXTURE_CHANGED;
09480: refTexCoords[texCoordSet] = texCoords;
09481: if (inUpdater
09482: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09483: texCoordType = T2F;
09484: validateTexCoordPointerType();
09485: } else {
09486: setupMirrorTexCoordPointer(texCoordSet, T2F);
09487: }
09488: if (isLive) {
09489: geomLock.unLock();
09490: }
09491: if (!inUpdater && isLive) {
09492: sendDataChangedMessage(false);
09493: }
09494: }
09495:
09496: TexCoord2f[] getTexCoordRef2f(int texCoordSet) {
09497: if (refTexCoords != null && refTexCoords[texCoordSet] != null
09498: && refTexCoords[texCoordSet] instanceof TexCoord2f[]) {
09499: return ((TexCoord2f[]) refTexCoords[texCoordSet]);
09500: } else {
09501: return null;
09502: }
09503: }
09504:
09505: void setTexCoordRef3f(int texCoordSet, TexCoord3f[] texCoords) {
09506:
09507: if (texCoordType != 0 && texCoordType != T3F) {
09508: if (texCoords != null) {
09509: throw new IllegalArgumentException(J3dI18N
09510: .getString("GeometryArray98"));
09511: }
09512: return;
09513: }
09514:
09515: if (texCoords != null) {
09516:
09517: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) == 0) {
09518: throw new IllegalStateException(J3dI18N
09519: .getString("GeometryArray95"));
09520: }
09521:
09522: if (this instanceof IndexedGeometryArrayRetained) {
09523: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09524:
09525: if (idx.maxTexCoordIndices[texCoordSet] >= texCoords.length) {
09526: throw new ArrayIndexOutOfBoundsException(J3dI18N
09527: .getString("IndexedGeometryArray25"));
09528: }
09529:
09530: } else if (texCoords.length < (initialTexCoordIndex[texCoordSet] + validVertexCount)) {
09531: throw new ArrayIndexOutOfBoundsException(J3dI18N
09532: .getString("GeometryArray113"));
09533: }
09534:
09535: }
09536: boolean isLive = source != null && source.isLive();
09537: if (isLive) {
09538: geomLock.getLock();
09539: }
09540: dirtyFlag |= TEXTURE_CHANGED;
09541: refTexCoords[texCoordSet] = texCoords;
09542: if (inUpdater
09543: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09544: texCoordType = T3F;
09545: validateTexCoordPointerType();
09546: } else {
09547: setupMirrorTexCoordPointer(texCoordSet, T3F);
09548: }
09549: if (isLive) {
09550: geomLock.unLock();
09551: }
09552: if (!inUpdater && isLive) {
09553: sendDataChangedMessage(false);
09554: }
09555: }
09556:
09557: TexCoord3f[] getTexCoordRef3f(int texCoordSet) {
09558: if (refTexCoords != null && refTexCoords[texCoordSet] != null
09559: && refTexCoords[texCoordSet] instanceof TexCoord3f[]) {
09560: return ((TexCoord3f[]) refTexCoords[texCoordSet]);
09561: } else {
09562: return null;
09563: }
09564: }
09565:
09566: /**
09567: * Sets the float vertex attribute array reference for the
09568: * specified vertex attribute number to the specified array.
09569: */
09570: void setVertexAttrRefFloat(int vertexAttrNum, float[] vertexAttrs) {
09571:
09572: // XXXX: Add the following test if we ever add double-precision types
09573: /*
09574: if (vertexAttrType != 0 && vertexAttrType != AF) {
09575: if (vertexAttrs != null) {
09576: // XXXX: new exception string
09577: throw new IllegalArgumentException(
09578: J3dI18N.getString("GeometryArray98-XXX"));
09579: }
09580: return;
09581: }
09582: */
09583:
09584: if (vertexAttrs != null) {
09585: int sz = vertexAttrSizes[vertexAttrNum];
09586:
09587: if (this instanceof IndexedGeometryArrayRetained) {
09588: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09589:
09590: if (sz * idx.maxVertexAttrIndices[vertexAttrNum] >= vertexAttrs.length) {
09591: throw new ArrayIndexOutOfBoundsException(J3dI18N
09592: .getString("IndexedGeometryArray30"));
09593: }
09594:
09595: } else if (vertexAttrs.length < sz
09596: * (initialVertexAttrIndex[vertexAttrNum] + validVertexCount)) {
09597: throw new ArrayIndexOutOfBoundsException(J3dI18N
09598: .getString("GeometryArray129"));
09599: }
09600: }
09601: boolean isLive = source != null && source.isLive();
09602: if (isLive) {
09603: geomLock.getLock();
09604: }
09605: dirtyFlag |= VATTR_CHANGED;
09606: floatRefVertexAttrs[vertexAttrNum] = vertexAttrs;
09607: if (inUpdater
09608: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09609: vertexAttrType = AF;
09610: validateVertexAttrPointerType();
09611: } else {
09612: setupMirrorVertexAttrPointer(vertexAttrNum, AF);
09613: }
09614: if (isLive) {
09615: geomLock.unLock();
09616: }
09617: if (!inUpdater && isLive) {
09618: sendDataChangedMessage(false);
09619: }
09620: }
09621:
09622: /**
09623: * Gets the float vertex attribute array reference for the specified
09624: * vertex attribute number.
09625: */
09626: float[] getVertexAttrRefFloat(int vertexAttrNum) {
09627: return floatRefVertexAttrs[vertexAttrNum];
09628: }
09629:
09630: /**
09631: * Sets the vertex attribute buffer reference for the specified
09632: * vertex attribute number to the specified buffer object.
09633: */
09634: void setVertexAttrRefBuffer(int vertexAttrNum, J3DBuffer vertexAttrs) {
09635:
09636: FloatBufferWrapper bufferImpl = null;
09637:
09638: if (vertexAttrs != null) {
09639: if (vertexAttrs.getBufferType() != J3DBuffer.TYPE_FLOAT)
09640: throw new IllegalArgumentException(J3dI18N
09641: .getString("GeometryArray116"));
09642:
09643: bufferImpl = (FloatBufferWrapper) vertexAttrs
09644: .getBufferImpl();
09645: int bufferSize = bufferImpl.limit();
09646:
09647: assert bufferImpl.isDirect();
09648:
09649: int sz = vertexAttrSizes[vertexAttrNum];
09650:
09651: if (this instanceof IndexedGeometryArrayRetained) {
09652: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09653:
09654: if (idx.maxVertexAttrIndices[vertexAttrNum] * sz >= bufferSize) {
09655: throw new ArrayIndexOutOfBoundsException(J3dI18N
09656: .getString("IndexedGeometryArray30"));
09657: }
09658: } else if (bufferSize < sz
09659: * (initialVertexAttrIndex[vertexAttrNum] + validVertexCount)) {
09660: throw new ArrayIndexOutOfBoundsException(J3dI18N
09661: .getString("GeometryArray129"));
09662: }
09663: }
09664: boolean isLive = source != null && source.isLive();
09665: if (isLive) {
09666: geomLock.getLock();
09667: }
09668: dirtyFlag |= VATTR_CHANGED;
09669: vertexAttrsRefBuffer[vertexAttrNum] = vertexAttrs;
09670: if (vertexAttrs == null) {
09671: floatBufferRefVertexAttrs[vertexAttrNum] = null;
09672: nioFloatBufferRefVertexAttrs[vertexAttrNum] = null;
09673: } else {
09674: floatBufferRefVertexAttrs[vertexAttrNum] = bufferImpl;
09675: nioFloatBufferRefVertexAttrs[vertexAttrNum] = bufferImpl
09676: .getBufferAsObject();
09677: }
09678: vertexAttrType = AF;
09679: validateVertexAttrPointerType();
09680: if (isLive) {
09681: geomLock.unLock();
09682: }
09683: if (!inUpdater && isLive) {
09684: sendDataChangedMessage(false);
09685: }
09686:
09687: }
09688:
09689: /**
09690: * Gets the vertex attribute array buffer reference for the specified
09691: * vertex attribute number.
09692: */
09693: J3DBuffer getVertexAttrRefBuffer(int vertexAttrNum) {
09694: return vertexAttrsRefBuffer[vertexAttrNum];
09695: }
09696:
09697: void setInterleavedVertices(float[] vertexData) {
09698: if (vertexData != null) {
09699:
09700: if (this instanceof IndexedGeometryArrayRetained) {
09701: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09702:
09703: if (stride * idx.maxCoordIndex >= vertexData.length) {
09704: throw new ArrayIndexOutOfBoundsException(J3dI18N
09705: .getString("IndexedGeometryArray23"));
09706: }
09707:
09708: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
09709: for (int i = 0; i < texCoordSetCount; i++) {
09710: if (stride * idx.maxTexCoordIndices[i] >= vertexData.length) {
09711: throw new ArrayIndexOutOfBoundsException(
09712: J3dI18N
09713: .getString("IndexedGeometryArray25"));
09714: }
09715: }
09716: }
09717:
09718: if (((this .vertexFormat & GeometryArray.COLOR) != 0)
09719: && (stride * idx.maxColorIndex >= vertexData.length)) {
09720: throw new ArrayIndexOutOfBoundsException(J3dI18N
09721: .getString("IndexedGeometryArray24"));
09722: }
09723:
09724: if (((this .vertexFormat & GeometryArray.NORMALS) != 0)
09725: && (stride * idx.maxNormalIndex >= vertexData.length)) {
09726: throw new ArrayIndexOutOfBoundsException(J3dI18N
09727: .getString("IndexedGeometryArray26"));
09728: }
09729: } else {
09730: if (vertexData.length < (stride * (initialVertexIndex + validVertexCount)))
09731: throw new ArrayIndexOutOfBoundsException(J3dI18N
09732: .getString("GeometryArray114"));
09733: }
09734: }
09735:
09736: // If the geometry has been rendered transparent, then make a copy
09737: // of the color pointer with 4f
09738: boolean isLive = source != null && source.isLive();
09739: if (isLive) {
09740: geomLock.getLock();
09741: }
09742: dirtyFlag |= VERTEX_CHANGED;
09743: colorChanged = 0xffff;
09744: interLeavedVertexData = vertexData;
09745: if (inUpdater
09746: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09747: setupMirrorInterleavedColorPointer(false);
09748: }
09749: if (isLive) {
09750: geomLock.unLock();
09751: }
09752: if (!inUpdater && isLive) {
09753: processCoordsChanged(vertexData == null);
09754: sendDataChangedMessage(true);
09755: }
09756: }
09757:
09758: // set the interleaved vertex with NIO buffer
09759: void setInterleavedVertexBuffer(J3DBuffer vertexData) {
09760:
09761: FloatBufferWrapper bufferImpl = null;
09762:
09763: if (vertexData != null) {
09764:
09765: if (vertexData.getBufferType() != J3DBuffer.TYPE_FLOAT)
09766: throw new IllegalArgumentException(J3dI18N
09767: .getString("GeometryArray116"));
09768:
09769: bufferImpl = (FloatBufferWrapper) vertexData
09770: .getBufferImpl();
09771:
09772: assert bufferImpl.isDirect();
09773:
09774: int bufferSize = bufferImpl.limit();
09775:
09776: if (this instanceof IndexedGeometryArrayRetained) {
09777: IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09778:
09779: if (stride * idx.maxCoordIndex >= bufferSize) {
09780: throw new ArrayIndexOutOfBoundsException(J3dI18N
09781: .getString("IndexedGeometryArray23"));
09782: }
09783:
09784: if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
09785: for (int i = 0; i < texCoordSetCount; i++) {
09786: if (stride * idx.maxTexCoordIndices[i] >= bufferSize) {
09787: throw new ArrayIndexOutOfBoundsException(
09788: J3dI18N
09789: .getString("IndexedGeometryArray25"));
09790: }
09791: }
09792: }
09793:
09794: if (((this .vertexFormat & GeometryArray.COLOR) != 0)
09795: && (stride * idx.maxColorIndex >= bufferSize)) {
09796: throw new ArrayIndexOutOfBoundsException(J3dI18N
09797: .getString("IndexedGeometryArray24"));
09798: }
09799:
09800: if (((this .vertexFormat & GeometryArray.NORMALS) != 0)
09801: && (stride * idx.maxNormalIndex >= bufferSize)) {
09802: throw new ArrayIndexOutOfBoundsException(J3dI18N
09803: .getString("IndexedGeometryArray23"));
09804: }
09805: } else {
09806: if (bufferSize < (stride * (initialVertexIndex + validVertexCount)))
09807: throw new ArrayIndexOutOfBoundsException(J3dI18N
09808: .getString("GeometryArray114"));
09809: }
09810: }
09811: // If the geometry has been rendered transparent, then make a copy
09812: // of the color pointer with 4f
09813: boolean isLive = source != null && source.isLive();
09814: if (isLive) {
09815: geomLock.getLock();
09816: }
09817: dirtyFlag |= VERTEX_CHANGED;
09818: colorChanged = 0xffff;
09819: interleavedVertexBuffer = vertexData;
09820:
09821: if (vertexData == null)
09822: interleavedFloatBufferImpl = null;
09823: else
09824: interleavedFloatBufferImpl = bufferImpl;
09825:
09826: if (inUpdater
09827: || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09828: setupMirrorInterleavedColorPointer(false);
09829: }
09830: if (isLive) {
09831: geomLock.unLock();
09832: }
09833: if (!inUpdater && isLive) {
09834: processCoordsChanged(vertexData == null);
09835: sendDataChangedMessage(true);
09836: }
09837: }
09838:
09839: float[] getInterleavedVertices() {
09840: return interLeavedVertexData;
09841: }
09842:
09843: J3DBuffer getInterleavedVertexBuffer() {
09844: return interleavedVertexBuffer;
09845: }
09846:
09847: void setValidVertexCount(int validVertexCount) {
09848:
09849: boolean nullGeo = false;
09850: if (validVertexCount < 0) {
09851: throw new IllegalArgumentException(J3dI18N
09852: .getString("GeometryArray110"));
09853: }
09854:
09855: if ((initialVertexIndex + validVertexCount) > vertexCount) {
09856: throw new IllegalArgumentException(J3dI18N
09857: .getString("GeometryArray100"));
09858: }
09859:
09860: if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
09861: // Interleaved, by-ref
09862:
09863: // use nio buffer for interleaved data
09864: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0
09865: && interleavedFloatBufferImpl != null) {
09866: if (interleavedFloatBufferImpl.limit() < stride
09867: * (initialVertexIndex + validVertexCount)) {
09868: throw new ArrayIndexOutOfBoundsException(J3dI18N
09869: .getString("GeometryArray114"));
09870: }
09871: }
09872: //use java array for interleaved data
09873: else if (interLeavedVertexData != null) {
09874: if (interLeavedVertexData.length < stride
09875: * (initialVertexIndex + validVertexCount)) {
09876: throw new ArrayIndexOutOfBoundsException(J3dI18N
09877: .getString("GeometryArray114"));
09878: }
09879: } else {
09880: nullGeo = true;
09881: }
09882: } else if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) {
09883: // Non-interleaved, by-ref
09884:
09885: if ((initialCoordIndex + validVertexCount) > vertexCount) {
09886: throw new IllegalArgumentException(J3dI18N
09887: .getString("GeometryArray104"));
09888: }
09889: if ((initialColorIndex + validVertexCount) > vertexCount) {
09890: throw new IllegalArgumentException(J3dI18N
09891: .getString("GeometryArray101"));
09892: }
09893: if ((initialNormalIndex + validVertexCount) > vertexCount) {
09894: throw new IllegalArgumentException(J3dI18N
09895: .getString("GeometryArray102"));
09896: }
09897:
09898: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
09899: for (int i = 0; i < texCoordSetCount; i++) {
09900: if ((initialTexCoordIndex[i] + validVertexCount) > vertexCount) {
09901: throw new IllegalArgumentException(J3dI18N
09902: .getString("GeometryArray103"));
09903: }
09904: }
09905: }
09906:
09907: if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
09908: for (int i = 0; i < vertexAttrCount; i++) {
09909: if ((initialVertexAttrIndex[i] + validVertexCount) > vertexCount) {
09910: throw new IllegalArgumentException(J3dI18N
09911: .getString("GeometryArray130"));
09912: }
09913: }
09914: }
09915:
09916: if ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0) {
09917: nullGeo = true;
09918: }
09919:
09920: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
09921: // by reference with nio buffer
09922: switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
09923: case PF:
09924: if (floatBufferRefCoords.limit() < 3 * (initialCoordIndex + validVertexCount)) {
09925: throw new ArrayIndexOutOfBoundsException(
09926: J3dI18N.getString("GeometryArray99"));
09927: }
09928: break;
09929: case PD:
09930: if (doubleBufferRefCoords.limit() < 3 * (initialCoordIndex + validVertexCount)) {
09931: throw new ArrayIndexOutOfBoundsException(
09932: J3dI18N.getString("GeometryArray99"));
09933: }
09934: break;
09935: }
09936:
09937: switch ((vertexType & COLOR_DEFINED)) {
09938: case CF:
09939: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
09940: if (floatBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
09941: throw new ArrayIndexOutOfBoundsException(
09942: J3dI18N
09943: .getString("GeometryArray112"));
09944: }
09945: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
09946: if (floatBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount)) {
09947: throw new ArrayIndexOutOfBoundsException(
09948: J3dI18N
09949: .getString("GeometryArray112"));
09950: }
09951: }
09952: break;
09953: case CUB:
09954: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
09955: if (byteBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
09956: throw new ArrayIndexOutOfBoundsException(
09957: J3dI18N
09958: .getString("GeometryArray112"));
09959: }
09960: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
09961: if (byteBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount)) {
09962: throw new ArrayIndexOutOfBoundsException(
09963: J3dI18N
09964: .getString("GeometryArray112"));
09965: }
09966: }
09967: break;
09968: }
09969: switch ((vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
09970: case TF:
09971: FloatBufferWrapper texBuffer;
09972: for (int i = 0; i < texCoordSetCount; i++) {
09973: texBuffer = (FloatBufferWrapper) (((J3DBuffer) refTexCoordsBuffer[i])
09974: .getBufferImpl());
09975: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
09976: if (texBuffer.limit() < 2 * (initialTexCoordIndex[i] + validVertexCount)) {
09977: throw new ArrayIndexOutOfBoundsException(
09978: J3dI18N
09979: .getString("GeometryArray113"));
09980: }
09981: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
09982: if (texBuffer.limit() < 3 * (initialTexCoordIndex[i] + validVertexCount)) {
09983: throw new ArrayIndexOutOfBoundsException(
09984: J3dI18N
09985: .getString("GeometryArray113"));
09986: }
09987: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
09988: if (texBuffer.limit() < 4 * (initialTexCoordIndex[i] + validVertexCount)) {
09989: throw new ArrayIndexOutOfBoundsException(
09990: J3dI18N
09991: .getString("GeometryArray113"));
09992: }
09993: }
09994: }
09995: break;
09996: }
09997: switch ((vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
09998: case NF:
09999: if (floatBufferRefNormals.limit() < 3 * (initialNormalIndex + validVertexCount)) {
10000: throw new ArrayIndexOutOfBoundsException(
10001: J3dI18N.getString("GeometryArray111"));
10002: }
10003: break;
10004: }
10005: switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) {
10006: case AF:
10007: for (int i = 0; i < vertexAttrCount; i++) {
10008: int sz = vertexAttrSizes[i];
10009: if (floatBufferRefVertexAttrs[i].limit() < (sz * (initialVertexAttrIndex[i] + validVertexCount))) {
10010: throw new ArrayIndexOutOfBoundsException(
10011: J3dI18N
10012: .getString("GeometryArray129"));
10013: }
10014: }
10015: break;
10016: }
10017: }
10018: // By reference with java array
10019: else {
10020: switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10021: case PF:
10022: if (floatRefCoords.length < 3 * (initialCoordIndex + validVertexCount)) {
10023: throw new ArrayIndexOutOfBoundsException(
10024: J3dI18N.getString("GeometryArray99"));
10025: }
10026: break;
10027: case PD:
10028: if (doubleRefCoords.length < 3 * (initialCoordIndex + validVertexCount)) {
10029: throw new ArrayIndexOutOfBoundsException(
10030: J3dI18N.getString("GeometryArray99"));
10031: }
10032: break;
10033: case P3F:
10034: if (p3fRefCoords.length < (initialCoordIndex + validVertexCount)) {
10035: throw new ArrayIndexOutOfBoundsException(
10036: J3dI18N.getString("GeometryArray99"));
10037: }
10038: break;
10039: case P3D:
10040: if (p3dRefCoords.length < (initialCoordIndex + validVertexCount)) {
10041: throw new ArrayIndexOutOfBoundsException(
10042: J3dI18N.getString("GeometryArray99"));
10043: }
10044: break;
10045: }
10046: switch ((vertexType & COLOR_DEFINED)) {
10047: case CF:
10048: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10049: if (floatRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10050: throw new ArrayIndexOutOfBoundsException(
10051: J3dI18N
10052: .getString("GeometryArray112"));
10053: }
10054: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10055: if (floatRefColors.length < 4 * (initialColorIndex + validVertexCount)) {
10056: throw new ArrayIndexOutOfBoundsException(
10057: J3dI18N
10058: .getString("GeometryArray112"));
10059: }
10060: }
10061: break;
10062: case CUB:
10063: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10064: if (byteRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10065: throw new ArrayIndexOutOfBoundsException(
10066: J3dI18N
10067: .getString("GeometryArray112"));
10068: }
10069: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10070: if (byteRefColors.length < 4 * (initialColorIndex + validVertexCount)) {
10071: throw new ArrayIndexOutOfBoundsException(
10072: J3dI18N
10073: .getString("GeometryArray112"));
10074: }
10075: }
10076: break;
10077: case C3F:
10078: if (c3fRefColors.length < (initialColorIndex + validVertexCount)) {
10079: throw new ArrayIndexOutOfBoundsException(
10080: J3dI18N.getString("GeometryArray112"));
10081: }
10082: break;
10083: case C4F:
10084: if (c4fRefColors.length < (initialColorIndex + validVertexCount)) {
10085: throw new ArrayIndexOutOfBoundsException(
10086: J3dI18N.getString("GeometryArray112"));
10087: }
10088: break;
10089: case C3UB:
10090: if (c3bRefColors.length < (initialColorIndex + validVertexCount)) {
10091: throw new ArrayIndexOutOfBoundsException(
10092: J3dI18N.getString("GeometryArray112"));
10093: }
10094: break;
10095: case C4UB:
10096: if (c4bRefColors.length < (initialColorIndex + validVertexCount)) {
10097: throw new ArrayIndexOutOfBoundsException(
10098: J3dI18N.getString("GeometryArray112"));
10099: }
10100: break;
10101: }
10102: switch ((vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
10103: case TF:
10104: for (int i = 0; i < texCoordSetCount; i++) {
10105: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
10106: if (((float[]) refTexCoords[i]).length < 2 * (initialTexCoordIndex[i] + validVertexCount)) {
10107: throw new ArrayIndexOutOfBoundsException(
10108: J3dI18N
10109: .getString("GeometryArray113"));
10110: }
10111: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10112: if (((float[]) refTexCoords[i]).length < 3 * (initialTexCoordIndex[i] + validVertexCount)) {
10113: throw new ArrayIndexOutOfBoundsException(
10114: J3dI18N
10115: .getString("GeometryArray113"));
10116: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10117: if (((float[]) refTexCoords[i]).length < 4 * (initialTexCoordIndex[i] + validVertexCount)) {
10118: throw new ArrayIndexOutOfBoundsException(
10119: J3dI18N
10120: .getString("GeometryArray113"));
10121: }
10122: }
10123: }
10124: }
10125: break;
10126: case T2F:
10127: for (int i = 0; i < texCoordSetCount; i++) {
10128: if (((TexCoord2f[]) refTexCoords[i]).length < (initialTexCoordIndex[i] + validVertexCount)) {
10129: throw new ArrayIndexOutOfBoundsException(
10130: J3dI18N
10131: .getString("GeometryArray113"));
10132: }
10133: }
10134: break;
10135: case T3F:
10136: for (int i = 0; i < texCoordSetCount; i++) {
10137: if (((TexCoord3f[]) refTexCoords[i]).length < (initialTexCoordIndex[i] + validVertexCount)) {
10138: throw new ArrayIndexOutOfBoundsException(
10139: J3dI18N
10140: .getString("GeometryArray113"));
10141: }
10142: }
10143: break;
10144: }
10145: switch ((vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
10146: case NF:
10147: if (floatRefNormals.length < 3 * (initialNormalIndex + validVertexCount)) {
10148: throw new ArrayIndexOutOfBoundsException(
10149: J3dI18N.getString("GeometryArray111"));
10150: }
10151: break;
10152: case N3F:
10153: if (v3fRefNormals.length < (initialNormalIndex + validVertexCount)) {
10154: throw new ArrayIndexOutOfBoundsException(
10155: J3dI18N.getString("GeometryArray111"));
10156: }
10157: }
10158: switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) {
10159: case AF:
10160: for (int i = 0; i < vertexAttrCount; i++) {
10161: int sz = vertexAttrSizes[i];
10162: if (floatRefVertexAttrs[i].length < (sz * (initialVertexAttrIndex[i] + validVertexCount))) {
10163: throw new ArrayIndexOutOfBoundsException(
10164: J3dI18N
10165: .getString("GeometryArray129"));
10166: }
10167: }
10168: break;
10169: }
10170: }
10171: }
10172: boolean isLive = source != null && source.isLive();
10173: if (isLive) {
10174: geomLock.getLock();
10175: }
10176: dirtyFlag |= VERTEX_CHANGED;
10177: this .validVertexCount = validVertexCount;
10178:
10179: if (isLive) {
10180: geomLock.unLock();
10181: }
10182:
10183: if (!inUpdater && isLive) {
10184: processCoordsChanged(nullGeo);
10185: sendDataChangedMessage(true);
10186: }
10187: }
10188:
10189: int getValidVertexCount() {
10190: return validVertexCount;
10191: }
10192:
10193: //Used for interleaved data (array or nio buffer)
10194: void setInitialVertexIndex(int initialVertexIndex) {
10195: boolean nullGeo = false;
10196:
10197: if ((initialVertexIndex + validVertexCount) > vertexCount) {
10198: throw new IllegalArgumentException(J3dI18N
10199: .getString("GeometryArray100"));
10200: }
10201:
10202: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0
10203: && interleavedFloatBufferImpl != null) {
10204: if (interleavedFloatBufferImpl.limit() < stride
10205: * (initialVertexIndex + validVertexCount)) {
10206: throw new ArrayIndexOutOfBoundsException(J3dI18N
10207: .getString("GeometryArray114"));
10208: }
10209: }
10210: // interleaved data using java array
10211: else if (interLeavedVertexData != null) {
10212: if (interLeavedVertexData.length < stride
10213: * (initialVertexIndex + validVertexCount)) {
10214: throw new ArrayIndexOutOfBoundsException(J3dI18N
10215: .getString("GeometryArray114"));
10216: }
10217: } else {
10218: nullGeo = (vertexFormat & GeometryArray.INTERLEAVED) != 0; // Only for byRef
10219: }
10220: boolean isLive = source != null && source.isLive();
10221: if (isLive) {
10222: geomLock.getLock();
10223: }
10224: dirtyFlag |= VERTEX_CHANGED;
10225: this .initialVertexIndex = initialVertexIndex;
10226: if (isLive) {
10227: geomLock.unLock();
10228: }
10229: if (!inUpdater && isLive) {
10230: processCoordsChanged(nullGeo);
10231: sendDataChangedMessage(true);
10232: }
10233: }
10234:
10235: int getInitialVertexIndex() {
10236: return initialVertexIndex;
10237: }
10238:
10239: void setInitialCoordIndex(int initialCoordIndex) {
10240: if ((initialCoordIndex + validVertexCount) > vertexCount) {
10241: throw new IllegalArgumentException(J3dI18N
10242: .getString("GeometryArray104"));
10243: }
10244: // use NIO buffer
10245: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10246: switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10247: case PF:
10248: if (floatBufferRefCoords.limit() < (initialCoordIndex + validVertexCount)) {
10249: throw new ArrayIndexOutOfBoundsException(J3dI18N
10250: .getString("GeometryArray99"));
10251: }
10252: break;
10253: case PD:
10254: if (doubleBufferRefCoords.limit() < (initialCoordIndex + validVertexCount)) {
10255: throw new ArrayIndexOutOfBoundsException(J3dI18N
10256: .getString("GeometryArray99"));
10257: }
10258: break;
10259: }
10260: } else {
10261: switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10262: case PF:
10263: if (floatRefCoords.length < 3 * (initialCoordIndex + validVertexCount)) {
10264: throw new ArrayIndexOutOfBoundsException(J3dI18N
10265: .getString("GeometryArray99"));
10266: }
10267: break;
10268: case PD:
10269: if (doubleRefCoords.length < 3 * (initialCoordIndex + validVertexCount)) {
10270: throw new ArrayIndexOutOfBoundsException(J3dI18N
10271: .getString("GeometryArray99"));
10272: }
10273: break;
10274: case P3F:
10275: if (p3fRefCoords.length < (initialCoordIndex + validVertexCount)) {
10276: throw new ArrayIndexOutOfBoundsException(J3dI18N
10277: .getString("GeometryArray99"));
10278: }
10279: break;
10280: case P3D:
10281: if (p3dRefCoords.length < (initialCoordIndex + validVertexCount)) {
10282: throw new ArrayIndexOutOfBoundsException(J3dI18N
10283: .getString("GeometryArray99"));
10284: }
10285: break;
10286: }
10287: }
10288: boolean isLive = source != null && source.isLive();
10289: if (isLive) {
10290: geomLock.getLock();
10291: }
10292: dirtyFlag |= COORDINATE_CHANGED;
10293: this .initialCoordIndex = initialCoordIndex;
10294: dirtyFlag |= COORDINATE_CHANGED;
10295: if (isLive) {
10296: geomLock.unLock();
10297: }
10298: // Send a message, since bounds changed
10299: if (!inUpdater && isLive) {
10300: processCoordsChanged((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
10301: sendDataChangedMessage(true);
10302: }
10303: }
10304:
10305: int getInitialCoordIndex() {
10306: return initialCoordIndex;
10307: }
10308:
10309: void setInitialColorIndex(int initialColorIndex) {
10310: if ((initialColorIndex + validVertexCount) > vertexCount) {
10311: throw new IllegalArgumentException(J3dI18N
10312: .getString("GeometryArray101"));
10313: }
10314: // NIO BUFFER CASE
10315: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10316: switch ((vertexType & COLOR_DEFINED)) {
10317: case CF:
10318: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10319: if (floatBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
10320: throw new ArrayIndexOutOfBoundsException(
10321: J3dI18N.getString("GeometryArray112"));
10322: }
10323: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10324: if (floatBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount)) {
10325: throw new ArrayIndexOutOfBoundsException(
10326: J3dI18N.getString("GeometryArray112"));
10327: }
10328: }
10329: break;
10330:
10331: case CUB:
10332: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10333: if (byteBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
10334: throw new ArrayIndexOutOfBoundsException(
10335: J3dI18N.getString("GeometryArray112"));
10336: }
10337: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10338: if (byteBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount)) {
10339: throw new ArrayIndexOutOfBoundsException(
10340: J3dI18N.getString("GeometryArray112"));
10341: }
10342: }
10343: break;
10344: }
10345: }
10346: // Java ARRAY CASE
10347: else {
10348: switch ((vertexType & COLOR_DEFINED)) {
10349: case CF:
10350: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10351: if (floatRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10352: throw new ArrayIndexOutOfBoundsException(
10353: J3dI18N.getString("GeometryArray112"));
10354: }
10355: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10356: if (floatRefColors.length < 4 * (initialColorIndex + validVertexCount)) {
10357: throw new ArrayIndexOutOfBoundsException(
10358: J3dI18N.getString("GeometryArray112"));
10359: }
10360: }
10361: break;
10362: case CUB:
10363: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10364: if (byteRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10365: throw new ArrayIndexOutOfBoundsException(
10366: J3dI18N.getString("GeometryArray112"));
10367: }
10368: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10369: if (byteRefColors.length < 4 * (initialColorIndex + validVertexCount)) {
10370: throw new ArrayIndexOutOfBoundsException(
10371: J3dI18N.getString("GeometryArray112"));
10372: }
10373: }
10374: break;
10375: case C3F:
10376: if (c3fRefColors.length < (initialColorIndex + validVertexCount)) {
10377: throw new ArrayIndexOutOfBoundsException(J3dI18N
10378: .getString("GeometryArray112"));
10379: }
10380: break;
10381: case C4F:
10382: if (c4fRefColors.length < (initialColorIndex + validVertexCount)) {
10383: throw new ArrayIndexOutOfBoundsException(J3dI18N
10384: .getString("GeometryArray112"));
10385: }
10386: break;
10387: case C3UB:
10388: if (c3bRefColors.length < (initialColorIndex + validVertexCount)) {
10389: throw new ArrayIndexOutOfBoundsException(J3dI18N
10390: .getString("GeometryArray112"));
10391: }
10392: break;
10393: case C4UB:
10394: if (c4bRefColors.length < (initialColorIndex + validVertexCount)) {
10395: throw new ArrayIndexOutOfBoundsException(J3dI18N
10396: .getString("GeometryArray112"));
10397: }
10398: break;
10399: }
10400: }
10401: boolean isLive = source != null && source.isLive();
10402: if (isLive) {
10403: geomLock.getLock();
10404: }
10405: dirtyFlag |= COLOR_CHANGED;
10406: colorChanged = 0xffff;
10407: this .initialColorIndex = initialColorIndex;
10408: if (isLive) {
10409: geomLock.unLock();
10410: }
10411: // There is no need to send message for by reference, since we
10412: // use VA
10413:
10414: }
10415:
10416: int getInitialColorIndex() {
10417: return initialColorIndex;
10418: }
10419:
10420: void setInitialNormalIndex(int initialNormalIndex) {
10421: if ((initialNormalIndex + validVertexCount) > vertexCount) {
10422: throw new IllegalArgumentException(J3dI18N
10423: .getString("GeometryArray102"));
10424: }
10425: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10426: if ((vertexType & NORMAL_DEFINED) == NF) {
10427: if (floatBufferRefNormals.limit() < 3 * (initialNormalIndex + validVertexCount)) {
10428: throw new ArrayIndexOutOfBoundsException(J3dI18N
10429: .getString("GeometryArray111"));
10430: }
10431: }
10432: } else {
10433: switch ((vertexType & NORMAL_DEFINED)) {
10434: case NF:
10435: if (floatRefNormals.length < 3 * (initialNormalIndex + validVertexCount)) {
10436: throw new ArrayIndexOutOfBoundsException(J3dI18N
10437: .getString("GeometryArray111"));
10438: }
10439: break;
10440: case N3F:
10441: if (v3fRefNormals.length < (initialNormalIndex + validVertexCount)) {
10442: throw new ArrayIndexOutOfBoundsException(J3dI18N
10443: .getString("GeometryArray111"));
10444: }
10445: }
10446: }
10447: boolean isLive = source != null && source.isLive();
10448: if (isLive) {
10449: geomLock.getLock();
10450: }
10451: dirtyFlag |= NORMAL_CHANGED;
10452: this .initialNormalIndex = initialNormalIndex;
10453: if (isLive) {
10454: geomLock.unLock();
10455: }
10456: // There is no need to send message for by reference, since we
10457: // use VA
10458: }
10459:
10460: int getInitialNormalIndex() {
10461: return initialNormalIndex;
10462: }
10463:
10464: /**
10465: * Sets the initial vertex attribute index for the specified
10466: * vertex attribute number for this GeometryArray object.
10467: */
10468: void setInitialVertexAttrIndex(int vertexAttrNum,
10469: int initialVertexAttrIndex) {
10470:
10471: if ((initialVertexAttrIndex + validVertexCount) > vertexCount) {
10472: throw new IllegalArgumentException(J3dI18N
10473: .getString("GeometryArray130"));
10474: }
10475:
10476: int sz = vertexAttrSizes[vertexAttrNum];
10477: int minLength = sz
10478: * (initialVertexAttrIndex + validVertexCount);
10479: if ((vertexType & VATTR_DEFINED) == AF) {
10480: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10481: if (floatBufferRefVertexAttrs[vertexAttrNum].limit() < minLength) {
10482: throw new ArrayIndexOutOfBoundsException(J3dI18N
10483: .getString("GeometryArray129"));
10484: }
10485: } else {
10486: if (floatRefVertexAttrs[vertexAttrNum].length < minLength) {
10487: throw new ArrayIndexOutOfBoundsException(J3dI18N
10488: .getString("GeometryArray129"));
10489: }
10490: }
10491: }
10492: boolean isLive = source != null && source.isLive();
10493: if (isLive) {
10494: geomLock.getLock();
10495: }
10496: dirtyFlag |= VATTR_CHANGED;
10497: this .initialVertexAttrIndex[vertexAttrNum] = initialVertexAttrIndex;
10498: if (isLive) {
10499: geomLock.unLock();
10500: }
10501: // There is no need to send message for by reference, since we
10502: // use VA
10503: }
10504:
10505: /**
10506: * Gets the initial vertex attribute index for the specified
10507: * vertex attribute number for this GeometryArray object.
10508: */
10509: int getInitialVertexAttrIndex(int vertexAttrNum) {
10510: return initialVertexAttrIndex[vertexAttrNum];
10511: }
10512:
10513: void setInitialTexCoordIndex(int texCoordSet,
10514: int initialTexCoordIndex) {
10515: if ((initialTexCoordIndex + validVertexCount) > vertexCount) {
10516: throw new IllegalArgumentException(J3dI18N
10517: .getString("GeometryArray103"));
10518: }
10519:
10520: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10521: if ((vertexType & TEXCOORD_DEFINED) == TF) {
10522: FloatBufferWrapper texBuffer = (FloatBufferWrapper) (((J3DBuffer) refTexCoordsBuffer[texCoordSet])
10523: .getBufferImpl());
10524: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
10525: if (texBuffer.limit() < 2 * (initialTexCoordIndex + validVertexCount)) {
10526: throw new ArrayIndexOutOfBoundsException(
10527: J3dI18N.getString("GeometryArray113"));
10528: }
10529: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10530: if (texBuffer.limit() < 3 * (initialTexCoordIndex + validVertexCount)) {
10531: throw new ArrayIndexOutOfBoundsException(
10532: J3dI18N.getString("GeometryArray113"));
10533: }
10534: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10535: if (texBuffer.limit() < 4 * (initialTexCoordIndex + validVertexCount)) {
10536: throw new ArrayIndexOutOfBoundsException(
10537: J3dI18N.getString("GeometryArray113"));
10538: }
10539: }
10540: }
10541: } else {
10542: switch ((vertexType & TEXCOORD_DEFINED)) {
10543: case TF:
10544: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
10545: if (((float[]) refTexCoords[texCoordSet]).length < 2 * (initialTexCoordIndex + validVertexCount)) {
10546: throw new ArrayIndexOutOfBoundsException(
10547: J3dI18N.getString("GeometryArray113"));
10548: }
10549: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10550: if (((float[]) refTexCoords[texCoordSet]).length < 3 * (initialTexCoordIndex + validVertexCount)) {
10551: throw new ArrayIndexOutOfBoundsException(
10552: J3dI18N.getString("GeometryArray113"));
10553: }
10554: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10555: if (((float[]) refTexCoords[texCoordSet]).length < 4 * (initialTexCoordIndex + validVertexCount)) {
10556: throw new ArrayIndexOutOfBoundsException(
10557: J3dI18N.getString("GeometryArray113"));
10558: }
10559: }
10560: break;
10561: case T2F:
10562: if (((TexCoord2f[]) refTexCoords[texCoordSet]).length < (initialTexCoordIndex + validVertexCount)) {
10563: throw new ArrayIndexOutOfBoundsException(J3dI18N
10564: .getString("GeometryArray113"));
10565: }
10566: break;
10567: case T3F:
10568: if (((TexCoord3f[]) refTexCoords[texCoordSet]).length < (initialTexCoordIndex + validVertexCount)) {
10569: throw new ArrayIndexOutOfBoundsException(J3dI18N
10570: .getString("GeometryArray113"));
10571: }
10572: break;
10573: }
10574: }
10575: boolean isLive = source != null && source.isLive();
10576: if (isLive) {
10577: geomLock.getLock();
10578: }
10579: dirtyFlag |= TEXTURE_CHANGED;
10580: this .initialTexCoordIndex[texCoordSet] = initialTexCoordIndex;
10581: if (isLive) {
10582: geomLock.unLock();
10583: }
10584: // There is no need to send message for by reference, since we
10585: // use VA
10586: }
10587:
10588: int getInitialTexCoordIndex(int texCoordSet) {
10589: return initialTexCoordIndex[texCoordSet];
10590: }
10591:
10592: int getTexCoordSetCount() {
10593: return this .texCoordSetCount;
10594: }
10595:
10596: int getTexCoordSetMapLength() {
10597: if (this .texCoordSetMap != null)
10598: return this .texCoordSetMap.length;
10599: else
10600: return 0;
10601: }
10602:
10603: void getTexCoordSetMap(int[] texCoordSetMap) {
10604:
10605: if (this .texCoordSetMap != null) {
10606: for (int i = 0; i < this .texCoordSetMap.length; i++) {
10607: texCoordSetMap[i] = this .texCoordSetMap[i];
10608: }
10609: }
10610: }
10611:
10612: void freeDlistId() {
10613: if (dlistId != -1) {
10614: VirtualUniverse.mc.freeDisplayListId(dlistObj);
10615: dlistId = -1;
10616: }
10617: }
10618:
10619: void assignDlistId() {
10620: if (dlistId == -1) {
10621: dlistObj = VirtualUniverse.mc.getDisplayListId();
10622: dlistId = dlistObj.intValue();
10623: }
10624: }
10625:
10626: // Add the specified render atom as a user of this geometry array
10627: // (for the specified render bin)
10628: void addDlistUser(RenderBin renderBin, RenderAtomListInfo ra) {
10629: if (dlistUsers == null) {
10630: dlistUsers = new HashMap(2, 1.0f);
10631: }
10632:
10633: Set raSet = (Set) dlistUsers.get(renderBin);
10634: if (raSet == null) {
10635: raSet = new HashSet();
10636: dlistUsers.put(renderBin, raSet);
10637: }
10638: raSet.add(ra);
10639: }
10640:
10641: // Remove the specified render atom from the set of users of this
10642: // geometry array (for the specified render bin)
10643: void removeDlistUser(RenderBin renderBin, RenderAtomListInfo ra) {
10644: if (dlistUsers == null) {
10645: // Nothing to do
10646: return;
10647: }
10648:
10649: Set raSet = (Set) dlistUsers.get(renderBin);
10650: if (raSet == null) {
10651: // Nothing to do
10652: return;
10653: }
10654: raSet.remove(ra);
10655: }
10656:
10657: // Returns true if the set of render atoms using this geometry
10658: // array in the specified render bin is empty.
10659: boolean isDlistUserSetEmpty(RenderBin renderBin) {
10660: if (dlistUsers == null) {
10661: return true;
10662: }
10663:
10664: Set raSet = (Set) dlistUsers.get(renderBin);
10665: if (raSet == null) {
10666: return true;
10667: }
10668: return raSet.isEmpty();
10669: }
10670:
10671: // This method is used for debugging only
10672: int numDlistUsers(RenderBin renderBin) {
10673: if (isDlistUserSetEmpty(renderBin)) {
10674: return 0;
10675: }
10676: Set raSet = (Set) dlistUsers.get(renderBin);
10677: return raSet.size();
10678: }
10679:
10680: void setDlistTimeStamp(int rdrBit, long timeStamp) {
10681: int index = getIndex(rdrBit);
10682: if (index >= timeStampPerDlist.length) {
10683: long[] newList = new long[index * 2];
10684: for (int i = 0; i < timeStampPerDlist.length; i++) {
10685: newList[i] = timeStampPerDlist[i];
10686: }
10687: timeStampPerDlist = newList;
10688: }
10689: timeStampPerDlist[index] = timeStamp;
10690: }
10691:
10692: long getDlistTimeStamp(int rdrBit) {
10693: int index = getIndex(rdrBit);
10694: // If index is greater than what currently exists, increase
10695: // the array and return zero
10696: if (index >= timeStampPerDlist.length) {
10697: setDlistTimeStamp(rdrBit, 0);
10698: }
10699: return timeStampPerDlist[index];
10700: }
10701:
10702: int getIndex(int bit) {
10703: int num = 0;
10704:
10705: while (bit > 0) {
10706: num++;
10707: bit >>= 1;
10708: }
10709: return num;
10710: }
10711:
10712: boolean isWriteStatic() {
10713:
10714: if (source.getCapability(GeometryArray.ALLOW_COORDINATE_WRITE)
10715: || source
10716: .getCapability(GeometryArray.ALLOW_COLOR_WRITE)
10717: || source
10718: .getCapability(GeometryArray.ALLOW_NORMAL_WRITE)
10719: || source
10720: .getCapability(GeometryArray.ALLOW_TEXCOORD_WRITE)
10721: || source
10722: .getCapability(GeometryArray.ALLOW_VERTEX_ATTR_WRITE)
10723: || source
10724: .getCapability(GeometryArray.ALLOW_COUNT_WRITE)
10725: || source
10726: .getCapability(GeometryArray.ALLOW_REF_DATA_WRITE))
10727: return false;
10728:
10729: return true;
10730: }
10731:
10732: /**
10733: * The functions below are only used in compile mode
10734: */
10735: void setCompiled(ArrayList curList) {
10736: int i;
10737: int num = curList.size();
10738: int offset = 0;
10739: geoOffset = new int[num];
10740: compileVcount = new int[num];
10741: int vcount = 0, vformat = 0;
10742: vcount = 0;
10743: isCompiled = true;
10744:
10745: if (num > 0)
10746: source = ((SceneGraphObjectRetained) curList.get(0)).source;
10747: for (i = 0; i < num; i++) {
10748: // Build the back mapping
10749: GeometryArrayRetained geo = (GeometryArrayRetained) curList
10750: .get(i);
10751: ((GeometryArray) geo.source).retained = this ;
10752: compileVcount[i] = geo.getValidVertexCount();
10753: vcount += geo.getValidVertexCount();
10754: geoOffset[i] = offset;
10755: offset += geo.stride() * compileVcount[i];
10756: vformat = geo.getVertexFormat();
10757: }
10758: createGeometryArrayData(vcount, vformat);
10759:
10760: // Assign the initial and valid fields
10761: validVertexCount = vcount;
10762: initialVertexIndex = 0;
10763:
10764: mergeGeometryArrays(curList);
10765:
10766: }
10767:
10768: /*
10769: // Ununsed
10770: int getVertexCount(int index) {
10771: return compileVcount[index];
10772: }
10773:
10774:
10775: int getValidVertexCount(int index) {
10776: return compileVcount[index];
10777: }
10778:
10779:
10780: int getInitialVertexIndex(int index) {
10781: return 0;
10782: }
10783: */
10784:
10785: void mergeGeometryArrays(ArrayList list) {
10786: float[] curVertexData;
10787: int length, srcOffset;
10788: int curOffset = 0;
10789: // We only merge if the texCoordSetCount is 1 and there are no
10790: // vertex attrs
10791: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
10792: texCoordSetCount = 1;
10793: texCoordSetMap = new int[1];
10794: texCoordSetMap[0] = 1;
10795: }
10796: for (int i = 0; i < list.size(); i++) {
10797: GeometryArrayRetained geo = (GeometryArrayRetained) list
10798: .get(i);
10799: // Take into account the validVertexCount and initialVertexIndex
10800: curVertexData = geo.vertexData;
10801: length = geo.validVertexCount * stride;
10802: srcOffset = geo.initialVertexIndex * stride;
10803: System.arraycopy(curVertexData, srcOffset, this .vertexData,
10804: curOffset, length);
10805: curOffset += length;
10806:
10807: // assign geoBounds
10808: geoBounds.combine(geo.geoBounds);
10809:
10810: }
10811: this .centroid.set(geoBounds.getCenter());
10812: }
10813:
10814: boolean isMergeable() {
10815:
10816: // For now, turn off by ref geometry
10817: if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0)
10818: return false;
10819:
10820: if (!isStatic())
10821: return false;
10822:
10823: // If there is more than one set of texture coordinate set defined
10824: // then don't merge geometry (we avoid dealing with texCoordSetMap
10825: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0
10826: && (texCoordSetCount > 1 || texCoordSetMap != null
10827: && texCoordSetMap.length > 1)) {
10828: return false;
10829: }
10830:
10831: // We will avoid merging geometry if there are any vertex attributes.
10832: if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
10833: return false;
10834: }
10835:
10836: // If intersect is allowed turn off merging
10837: if (source.getCapability(Geometry.ALLOW_INTERSECT))
10838: return false;
10839:
10840: return true;
10841: }
10842:
10843: void compile(CompileState compState) {
10844: super .compile(compState);
10845:
10846: if ((vertexFormat & GeometryArray.NORMALS) != 0) {
10847: compState.needNormalsTransform = true;
10848: }
10849: }
10850:
10851: void mergeTransform(TransformGroupRetained xform) {
10852: if (geoBounds != null) {
10853: geoBounds.transform(xform.transform);
10854: }
10855: }
10856:
10857: // This adds a MorphRetained to the list of users of this geometry
10858: void addMorphUser(MorphRetained m) {
10859: int index;
10860: ArrayList morphList;
10861:
10862: if (morphUniverseList == null) {
10863: morphUniverseList = new ArrayList(1);
10864: morphUserLists = new ArrayList(1);
10865: }
10866: synchronized (morphUniverseList) {
10867: if (morphUniverseList.contains(m.universe)) {
10868: index = morphUniverseList.indexOf(m.universe);
10869: morphList = (ArrayList) morphUserLists.get(index);
10870: morphList.add(m);
10871: } else {
10872: morphUniverseList.add(m.universe);
10873: morphList = new ArrayList(5);
10874: morphList.add(m);
10875: morphUserLists.add(morphList);
10876: }
10877: }
10878: }
10879:
10880: // This adds a MorphRetained to the list of users of this geometry
10881: void removeMorphUser(MorphRetained m) {
10882: int index;
10883: ArrayList morphList;
10884:
10885: if (morphUniverseList == null)
10886: return;
10887:
10888: synchronized (morphUniverseList) {
10889: index = morphUniverseList.indexOf(m.universe);
10890: morphList = (ArrayList) morphUserLists.get(index);
10891: morphList.remove(morphList.indexOf(m));
10892: if (morphList.size() == 0) {
10893: morphUserLists.remove(index);
10894: morphUniverseList.remove(index);
10895: }
10896: }
10897: }
10898:
10899: // Initialize mirror object when geometry is first setLived
10900: void initMirrorGeometry() {
10901: geomLock.getLock();
10902: if (this instanceof IndexedGeometryArrayRetained) {
10903: if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) {
10904: mirrorGeometry = ((IndexedGeometryArrayRetained) this )
10905: .cloneNonIndexedGeometry();
10906: } else {
10907: mirrorGeometry = null;
10908: }
10909: }
10910: geomLock.unLock();
10911:
10912: }
10913:
10914: // Update Mirror Object in response to change in geometry
10915: void updateMirrorGeometry() {
10916: geomLock.getLock();
10917: if (this instanceof IndexedGeometryArrayRetained) {
10918: if (mirrorGeometry != null) {
10919: mirrorGeometry = ((IndexedGeometryArrayRetained) this )
10920: .cloneNonIndexedGeometry();
10921: }
10922: }
10923: geomLock.unLock();
10924:
10925: }
10926:
10927: // Used by the picking intersect routines
10928: void getVertexData(int i, Point3d pnts) {
10929: int offset;
10930: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
10931: offset = stride * i + coordinateOffset;
10932: pnts.x = this .vertexData[offset];
10933: pnts.y = this .vertexData[offset + 1];
10934: pnts.z = this .vertexData[offset + 2];
10935: return;
10936: }
10937:
10938: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
10939: if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
10940: offset = stride * i + coordinateOffset;
10941: pnts.x = this .interLeavedVertexData[offset];
10942: pnts.y = this .interLeavedVertexData[offset + 1];
10943: pnts.z = this .interLeavedVertexData[offset + 2];
10944: } else {
10945: switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10946: case GeometryArrayRetained.PF:
10947: offset = i * 3;
10948: pnts.x = this .floatRefCoords[offset];
10949: pnts.y = this .floatRefCoords[offset + 1];
10950: pnts.z = this .floatRefCoords[offset + 2];
10951: break;
10952: case GeometryArrayRetained.PD:
10953: offset = i * 3;
10954: pnts.x = this .doubleRefCoords[offset];
10955: pnts.y = this .doubleRefCoords[offset + 1];
10956: pnts.z = this .doubleRefCoords[offset + 2];
10957: break;
10958: case GeometryArrayRetained.P3F:
10959: pnts.x = this .p3fRefCoords[i].x;
10960: pnts.y = this .p3fRefCoords[i].y;
10961: pnts.z = this .p3fRefCoords[i].z;
10962: break;
10963: case GeometryArrayRetained.P3D:
10964: pnts.x = this .p3dRefCoords[i].x;
10965: pnts.y = this .p3dRefCoords[i].y;
10966: pnts.z = this .p3dRefCoords[i].z;
10967: break;
10968: }
10969: }
10970: }// end of non nio buffer
10971: else { // NIO BUFFER
10972: if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
10973: offset = stride * i + coordinateOffset;
10974: pnts.x = this .interleavedFloatBufferImpl.get(offset);
10975: pnts.y = this .interleavedFloatBufferImpl
10976: .get(offset + 1);
10977: pnts.z = this .interleavedFloatBufferImpl
10978: .get(offset + 2);
10979: } else {
10980: switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10981: case GeometryArrayRetained.PF:
10982: offset = i * 3;
10983: pnts.x = this .floatBufferRefCoords.get(offset);
10984: pnts.y = this .floatBufferRefCoords.get(offset + 1);
10985: pnts.z = this .floatBufferRefCoords.get(offset + 2);
10986: break;
10987: case GeometryArrayRetained.PD:
10988: offset = i * 3;
10989: pnts.x = this .doubleBufferRefCoords.get(offset);
10990: pnts.y = this .doubleBufferRefCoords.get(offset + 1);
10991: pnts.z = this .doubleBufferRefCoords.get(offset + 2);
10992: break;
10993: }
10994: }
10995: } // end of nio buffer
10996: }
10997:
10998: void getCrossValue(Point3d p1, Point3d p2, Vector3d value) {
10999: value.x += p1.y * p2.z - p1.z * p2.y;
11000: value.y += p2.x * p1.z - p2.z * p1.x;
11001: value.z += p1.x * p2.y - p1.y * p2.x;
11002: }
11003:
11004: boolean intersect(Transform3D this LocalToVworld,
11005: Transform3D otherLocalToVworld, GeometryRetained geom) {
11006:
11007: Transform3D t3d = new Transform3D();
11008: boolean isIntersect = false;
11009:
11010: if (geom instanceof GeometryArrayRetained) {
11011: GeometryArrayRetained geomArray = (GeometryArrayRetained) geom;
11012:
11013: if (geomArray.validVertexCount >= validVertexCount) {
11014: t3d.invert(otherLocalToVworld);
11015: t3d.mul(this LocalToVworld);
11016: isIntersect = intersect(t3d, geom);
11017: } else {
11018: t3d.invert(this LocalToVworld);
11019: t3d.mul(otherLocalToVworld);
11020: isIntersect = geomArray.intersect(t3d, this );
11021: }
11022: } else {
11023: t3d.invert(this LocalToVworld);
11024: t3d.mul(otherLocalToVworld);
11025: isIntersect = geom.intersect(t3d, this );
11026: }
11027: return isIntersect;
11028: }
11029:
11030: int getNumCoordCount() {
11031: int count = 0;
11032: if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
11033: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11034: count = vertexCount;
11035: return count;
11036: }
11037:
11038: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11039: if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11040: switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
11041: case PF:
11042: count = floatRefCoords.length / 3;
11043: break;
11044: case PD:
11045: count = doubleRefCoords.length / 3;
11046: break;
11047: case P3F:
11048: count = p3fRefCoords.length;
11049: break;
11050: case P3D:
11051: count = p3dRefCoords.length;
11052: break;
11053: }
11054: } else {
11055: count = interLeavedVertexData.length / stride;
11056: }
11057: } else { // nio buffer
11058: if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11059: switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
11060: case PF:
11061: count = floatBufferRefCoords.limit() / 3; // XXXX: limit or capacity?
11062: break;
11063: case PD:
11064: count = doubleBufferRefCoords.limit() / 3;
11065: break;
11066: }
11067: } else {
11068: count = interleavedFloatBufferImpl.limit() / stride;
11069: }
11070: }
11071: }
11072: return count;
11073: }
11074:
11075: int getNumColorCount() {
11076: int count = 0;
11077: if ((vertexFormat & GeometryArray.COLOR) != 0) {
11078: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11079: count = vertexCount;
11080: return count;
11081: }
11082: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11083: if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11084: switch ((vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
11085: case CF:
11086: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
11087: count = floatRefColors.length / 3;
11088: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
11089: count = floatRefColors.length / 4;
11090: }
11091: break;
11092: case CUB:
11093: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
11094: count = byteRefColors.length / 3;
11095: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
11096: count = byteRefColors.length / 4;
11097: }
11098: break;
11099: case C3F:
11100: count = c3fRefColors.length;
11101: break;
11102: case C4F:
11103: count = c4fRefColors.length;
11104: break;
11105: case C3UB:
11106: count = c3bRefColors.length;
11107: break;
11108: case C4UB:
11109: count = c4bRefColors.length;
11110: break;
11111: }
11112: } else {
11113: count = interLeavedVertexData.length / stride;
11114: }
11115: } // end of non nio buffer
11116: else {
11117: if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11118: switch ((vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
11119: case CF:
11120: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
11121: count = floatBufferRefColors.limit() / 3;
11122: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
11123: count = floatBufferRefColors.limit() / 4;
11124: }
11125: break;
11126: case CUB:
11127: if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
11128: count = byteBufferRefColors.limit() / 3;
11129: } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
11130: count = byteBufferRefColors.limit() / 4;
11131: }
11132: break;
11133: }
11134: } else {
11135: count = interleavedFloatBufferImpl.limit() / stride;
11136: }
11137: } // end of nio buffer
11138: }
11139: return count;
11140: }
11141:
11142: int getNumNormalCount() {
11143: int count = 0;
11144: if ((vertexFormat & GeometryArray.NORMALS) != 0) {
11145: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11146: count = vertexCount;
11147: return count;
11148: }
11149:
11150: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11151: if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11152: switch ((vertexType & NORMAL_DEFINED)) {
11153: case NF:
11154: count = floatRefNormals.length / 3;
11155: break;
11156: case N3F:
11157: count = v3fRefNormals.length;
11158: break;
11159: }
11160: } else {
11161: count = interLeavedVertexData.length / stride;
11162: }
11163: } // end of non nio buffer
11164: else {
11165: if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11166: if ((vertexType & NORMAL_DEFINED) == NF) {
11167: count = floatBufferRefNormals.limit() / 3;
11168: }
11169: } else {
11170: count = interleavedFloatBufferImpl.limit() / stride;
11171: }
11172: }
11173: }
11174: return count;
11175: }
11176:
11177: int getNumTexCoordCount(int i) {
11178: int count = 0;
11179: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
11180: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11181: count = vertexCount;
11182: return count;
11183: }
11184:
11185: if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11186: if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11187: switch ((vertexType & TEXCOORD_DEFINED)) {
11188: case TF:
11189: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
11190: count = ((float[]) refTexCoords[i]).length / 2;
11191: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
11192: count = ((float[]) refTexCoords[i]).length / 3;
11193: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
11194: count = ((float[]) refTexCoords[i]).length / 4;
11195: }
11196:
11197: break;
11198: case T2F:
11199: count = ((TexCoord2f[]) refTexCoords[i]).length;
11200: break;
11201: case T3F:
11202: count = ((TexCoord3f[]) refTexCoords[i]).length;
11203: }
11204: } else {
11205: count = interLeavedVertexData.length / stride;
11206: }
11207: } else { // nio buffer
11208: if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11209: if ((vertexType & TEXCOORD_DEFINED) == TF) {
11210: FloatBufferWrapper texBuffer = (FloatBufferWrapper) (((J3DBuffer) refTexCoordsBuffer[i])
11211: .getBufferImpl());
11212: if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
11213: count = texBuffer.limit() / 2;
11214: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
11215: count = texBuffer.limit() / 3;
11216: } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
11217: count = texBuffer.limit() / 4;
11218: }
11219: }
11220: } else {
11221: count = interleavedFloatBufferImpl.limit() / stride;
11222: }
11223: }
11224: }
11225: return count;
11226: }
11227:
11228: // NOTE: we don't need a getNumVertexAttrCount method, since getNum*Count
11229: // is only called by Morph, which doesn't support vertex attrs
11230:
11231: // Found the min distance from center to the point/line/tri/quad
11232: // form by dist[]
11233: void computeMinDistance(Point3d coordinates[], Point3d center,
11234: Vector3d normal, double dist[], Point3d iPnt) {
11235: double x, y, z;
11236: int i, j;
11237:
11238: if (coordinates.length == 1) {
11239: // a point
11240: iPnt.x = coordinates[0].x;
11241: iPnt.y = coordinates[0].y;
11242: iPnt.z = coordinates[0].z;
11243: x = iPnt.x - center.x;
11244: y = iPnt.y - center.y;
11245: z = iPnt.z - center.z;
11246: dist[0] = Math.sqrt(x * x + y * y + z * z);
11247: return;
11248: }
11249:
11250: if (coordinates.length == 2) {
11251: // a line
11252: dist[0] = Math.sqrt(Distance.pointToSegment(center,
11253: coordinates[0], coordinates[1], iPnt, null));
11254: return;
11255: }
11256:
11257: double normalLen = 0;
11258:
11259: if (normal == null) {
11260: Vector3d vec0 = new Vector3d();
11261: Vector3d vec1 = new Vector3d();
11262: normal = new Vector3d();
11263: // compute plane normal for coordinates.
11264: for (i = 0; i < coordinates.length - 1;) {
11265: vec0.x = coordinates[i + 1].x - coordinates[i].x;
11266: vec0.y = coordinates[i + 1].y - coordinates[i].y;
11267: vec0.z = coordinates[i + 1].z - coordinates[i++].z;
11268: if (vec0.length() > 0.0)
11269: break;
11270: }
11271:
11272: for (j = i; j < coordinates.length - 1; j++) {
11273: vec1.x = coordinates[j + 1].x - coordinates[j].x;
11274: vec1.y = coordinates[j + 1].y - coordinates[j].y;
11275: vec1.z = coordinates[j + 1].z - coordinates[j].z;
11276: if (vec1.length() > 0.0)
11277: break;
11278: }
11279:
11280: if (j == (coordinates.length - 1)) {
11281: // Degenerate polygon, check with edge only
11282: normal = null;
11283: } else {
11284: normal.cross(vec0, vec1);
11285: }
11286: }
11287:
11288: if (normal != null) {
11289: normalLen = normal.length();
11290: if (normalLen == 0.0) {
11291: // Degenerate polygon, check with edge only
11292: normal = null;
11293: }
11294: }
11295:
11296: if (coordinates.length == 3) {
11297: // a triangle
11298: if (normal != null) {
11299: double d = -(normal.x * coordinates[0].x + normal.y
11300: * coordinates[0].y + normal.z
11301: * coordinates[0].z);
11302: dist[0] = (normal.x * center.x + normal.y * center.y
11303: + normal.z * center.z + d)
11304: / normalLen;
11305: iPnt.x = center.x - dist[0] * normal.x / normalLen;
11306: iPnt.y = center.y - dist[0] * normal.y / normalLen;
11307: iPnt.z = center.z - dist[0] * normal.z / normalLen;
11308:
11309: if (pointInTri(iPnt, coordinates[0], coordinates[1],
11310: coordinates[2], normal)) {
11311: return;
11312: }
11313: }
11314:
11315: // checking point to line distance
11316: double minDist;
11317: Point3d minPnt = new Point3d();
11318:
11319: dist[0] = Distance.pointToSegment(center, coordinates[0],
11320: coordinates[1], iPnt, null);
11321: minDist = Distance.pointToSegment(center, coordinates[1],
11322: coordinates[2], minPnt, null);
11323: if (minDist < dist[0]) {
11324: dist[0] = minDist;
11325: iPnt.x = minPnt.x;
11326: iPnt.y = minPnt.y;
11327: iPnt.z = minPnt.z;
11328: }
11329: minDist = Distance.pointToSegment(center, coordinates[2],
11330: coordinates[0], minPnt, null);
11331: if (minDist < dist[0]) {
11332: dist[0] = minDist;
11333: iPnt.x = minPnt.x;
11334: iPnt.y = minPnt.y;
11335: iPnt.z = minPnt.z;
11336: }
11337: dist[0] = Math.sqrt(dist[0]);
11338: return;
11339: }
11340:
11341: // a quad
11342: if (normal != null) {
11343: double d = -(normal.x * coordinates[0].x + normal.y
11344: * coordinates[0].y + normal.z * coordinates[0].z);
11345: dist[0] = (normal.x * center.x + normal.y * center.y
11346: + normal.z * center.z + d)
11347: / normalLen;
11348: iPnt.x = center.x - dist[0] * normal.x / normalLen;
11349: iPnt.y = center.y - dist[0] * normal.y / normalLen;
11350: iPnt.z = center.z - dist[0] * normal.z / normalLen;
11351:
11352: if (pointInTri(iPnt, coordinates[0], coordinates[1],
11353: coordinates[2], normal)
11354: || pointInTri(iPnt, coordinates[1], coordinates[2],
11355: coordinates[3], normal)) {
11356: return;
11357: }
11358: }
11359:
11360: // checking point to line distance
11361: double minDist;
11362: Point3d minPnt = new Point3d();
11363:
11364: dist[0] = Distance.pointToSegment(center, coordinates[0],
11365: coordinates[1], iPnt, null);
11366: minDist = Distance.pointToSegment(center, coordinates[1],
11367: coordinates[2], minPnt, null);
11368: if (minDist < dist[0]) {
11369: dist[0] = minDist;
11370: iPnt.x = minPnt.x;
11371: iPnt.y = minPnt.y;
11372: iPnt.z = minPnt.z;
11373: }
11374: minDist = Distance.pointToSegment(center, coordinates[2],
11375: coordinates[3], minPnt, null);
11376: if (minDist < dist[0]) {
11377: dist[0] = minDist;
11378: iPnt.x = minPnt.x;
11379: iPnt.y = minPnt.y;
11380: iPnt.z = minPnt.z;
11381: }
11382:
11383: minDist = Distance.pointToSegment(center, coordinates[3],
11384: coordinates[0], minPnt, null);
11385: if (minDist < dist[0]) {
11386: dist[0] = minDist;
11387: iPnt.x = minPnt.x;
11388: iPnt.y = minPnt.y;
11389: iPnt.z = minPnt.z;
11390: }
11391:
11392: dist[0] = Math.sqrt(dist[0]);
11393: }
11394:
11395: void handleFrequencyChange(int bit) {
11396: int mask = 0;
11397: if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11398: if ((bit == GeometryArray.ALLOW_COORDINATE_WRITE)
11399: || (((vertexFormat & GeometryArray.COLOR) != 0) && bit == GeometryArray.ALLOW_COLOR_WRITE)
11400: || (((vertexFormat & GeometryArray.NORMALS) != 0) && bit == GeometryArray.ALLOW_NORMAL_WRITE)
11401: || (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && bit == GeometryArray.ALLOW_TEXCOORD_WRITE)
11402: || (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && bit == GeometryArray.ALLOW_VERTEX_ATTR_WRITE)
11403: || (bit == GeometryArray.ALLOW_COUNT_WRITE)) {
11404: mask = 1;
11405: }
11406: } else {
11407: if (bit == GeometryArray.ALLOW_REF_DATA_WRITE)
11408: mask = 1;
11409: }
11410: if (mask != 0) {
11411: setFrequencyChangeMask(bit, mask);
11412: }
11413: }
11414:
11415: int getTexCoordType() {
11416: return texCoordType;
11417: }
11418:
11419: int getVertexAttrType() {
11420: return vertexAttrType;
11421: }
11422:
11423: }
|