1 /*
2  * $RCSfile: GeometryArrayRetained.java,v $
3  *
4  * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6  *
7  * This code is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 only, as
9  * published by the Free Software Foundation.  Sun designates this
10  * particular file as subject to the "Classpath" exception as provided
11  * by Sun in the LICENSE file that accompanied this code.
12  *
13  * This code is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16  * version 2 for more details (a copy is included in the LICENSE file that
17  * accompanied this code).
18  *
19  * You should have received a copy of the GNU General Public License version
20  * 2 along with this work; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
24  * CA 95054 USA or visit www.sun.com if you need additional information or
25  * have any questions.
26  *
27  * $Revision: 1.12 $
28  * $Date: 2008/02/28 20:17:22 $
29  * $State: Exp $
30  */
31 
32 package javax.media.j3d;
33 
34 import com.sun.j3d.internal.Distance;
35 import javax.vecmath.*;
36 import java.lang.Math;
37 import java.util.ArrayList;
38 import java.util.Set;
39 import java.util.HashSet;
40 import java.util.HashMap;
41 import java.util.Vector;
42 import java.util.Enumeration;
43 import com.sun.j3d.internal.ByteBufferWrapper;
44 import com.sun.j3d.internal.BufferWrapper;
45 import com.sun.j3d.internal.FloatBufferWrapper;
46 import com.sun.j3d.internal.DoubleBufferWrapper;
47 
48 
49 /**
50  * The GeometryArray object contains arrays of positional coordinates,
51  * colors, normals and/or texture coordinates that describe
52  * point, line, or surface geometry.  It is extended to create
53  * the various primitive types (e.g., lines, triangle_strips, etc.)
54  */
55 
56 abstract class GeometryArrayRetained extends GeometryRetained{
57 
58     // XXXX: Memory footprint reduction. Should have separate object to
59     //       to contain specific data such as a ByRef object for
60     //       all ByRef related data. So that incases where no
61     //       ByRef is needed, the ByRef object reference is
62     //       set to null. Hence saving memory!
63     //       Need object such as Texture, D3d and ByRef ...
64     //
65 
66 
67     // Contains a bitset indicating which components are present
68     int vertexFormat;
69 
70     // Whether this geometry was ever rendered as transparent
71     int c4fAllocated =  0;
72 
73     // Total Number of vertices
74     int vertexCount;
75 
76     // number of vertices used in rendering
77     int validVertexCount;
78 
79     // The vertex data in packed format
80     float vertexData[];
81 
82     // vertex data in packed format for each screen in multi-screen situation
83     // if alpha values of each vertex are to be updated
84     private float mvertexData[][];
85 
86     //
87     // The following offset/stride values are internally computed
88     // from the format
89     //
90 
91     // Stride (in words) from one vertex to the next
92     int stride;
93 
94     // Stride (in words) from one texture coordinate to the next
95     int texCoordStride;
96 
97     // Offset (in words) within each vertex of the coordinate position
98     int coordinateOffset;
99 
100     // Offset (in words) within each vertex of the normal
101     int normalOffset;
102 
103     // Offset (in words) within each vertex of the color
104     int colorOffset;
105 
106     // Offset (in words) within each vertex of the texture coordinate
107     int textureOffset;
108 
109     // Offset (in words) within each vertex of each vertex attribute
110     int[] vertexAttrOffsets;
111 
112     // Stride (size) of all vertex attributes
113     int vertexAttrStride;
114 
115     // alpha value for transparency and texture blending
116     private float[] lastAlpha = new float[1];
117     float lastScreenAlpha = -1;
118 
119     int colorChanged = 0;
120 
121     // byte to float scale factor
122     static final float ByteToFloatScale = 1.0f/255.0f;
123 
124     // float to byte scale factor
125     static final float FloatToByteScale = 255.0f;
126 
127     // Set flag indicating that we are in the updater.  This flag
128     // can be used by the various setRef methods to inhibit any
129     // update messages
130     boolean inUpdater = false;
131 
132     // Array List used for messages
133     ArrayList gaList = new ArrayList(1);
134 
135 
136     // Target threads to be notified when morph changes
137     static final int targetThreads = (J3dThread.UPDATE_RENDER |
138 				      J3dThread.UPDATE_GEOMETRY);
139 
140     // used for byReference geometry
141     float[] floatRefCoords = null;
142     double[] doubleRefCoords = null;
143     Point3d[] p3dRefCoords = null;
144     Point3f[] p3fRefCoords = null;
145 
146     // Used for NIO buffer geometry
147     J3DBuffer coordRefBuffer = null;
148     FloatBufferWrapper floatBufferRefCoords = null;
149     DoubleBufferWrapper doubleBufferRefCoords = null;
150 
151     // Initial index to use for rendering
152     int initialCoordIndex = 0;
153     int initialColorIndex = 0;
154     int initialNormalIndex = 0;
155     int[] initialTexCoordIndex = null;
156     int[] initialVertexAttrIndex = null;
157     int initialVertexIndex = 0;
158 
159 
160     // used for byReference colors
161     float[] floatRefColors = null;
162     byte[] byteRefColors = null;
163     Color3f[] c3fRefColors = null;
164     Color4f[] c4fRefColors = null;
165     Color3b[] c3bRefColors = null;
166     Color4b[] c4bRefColors = null;
167 
168     // Used for NIO buffer colors
169     J3DBuffer colorRefBuffer = null;
170     FloatBufferWrapper floatBufferRefColors = null;
171     ByteBufferWrapper byteBufferRefColors = null;
172 
173     // flag to indicate if the "by reference" component is already set
174     int vertexType = 0;
175     static  final int PF    = 0x1;
176     static  final int PD    = 0x2;
177     static  final int P3F   = 0x4;
178     static  final int P3D   = 0x8;
179     static final int VERTEX_DEFINED = PF | PD | P3F | P3D;
180 
181     static final int CF  = 0x10;
182     static final int CUB = 0x20;
183     static final int C3F = 0x40;
184     static final int C4F = 0x80;
185     static final int C3UB  = 0x100;
186     static final int C4UB = 0x200;
187     static final int COLOR_DEFINED = CF | CUB | C3F | C4F| C3UB | C4UB;
188 
189     static final int NF = 0x400;
190     static final int N3F = 0x800;
191     static final int NORMAL_DEFINED = NF | N3F;
192 
193     static final int TF = 0x1000;
194     static final int T2F = 0x2000;
195     static final int T3F = 0x4000;
196     static final int TEXCOORD_DEFINED = TF | T2F | T3F;
197 
198     static final int AF = 0x8000;
199     static final int VATTR_DEFINED = AF;
200 
201     // Flag word indicating the type of by-ref texCoord. We will copy this to
202     // the vertexType field only when the references for all texture coordinate
203     // sets are set to non-null values.
204     private int texCoordType = 0;
205 
206     // Flag word indicating the type of by-ref vertex attr. We will copy this to
207     // the vertexType field only when the references for all vertex attrs
208     // are set to non-null values.
209     private int vertexAttrType = 0;
210 
211     // flag for execute geometry array when by reference
212     static final int COORD_FLOAT  = 0x01;
213     static final int COORD_DOUBLE = 0x02;
214     static final int COLOR_FLOAT  = 0x04;
215     static final int COLOR_BYTE   = 0x08;
216     static final int NORMAL_FLOAT = 0x10;
217     static final int TEXCOORD_FLOAT = 0x20;
218     static final int VATTR_FLOAT = 0x40;
219 
220 
221     // used by "by reference" normals
222     float[] floatRefNormals = null;
223     Vector3f[] v3fRefNormals = null;
224 
225     // Used for NIO buffer normals
226     J3DBuffer normalRefBuffer = null;
227     FloatBufferWrapper floatBufferRefNormals = null;
228 
229     // used for "by reference" vertex attrs
230     float[][] floatRefVertexAttrs = null;
231 
232     // Used for NIO buffer vertex attrs
233     J3DBuffer[] vertexAttrsRefBuffer = null;
234     FloatBufferWrapper[] floatBufferRefVertexAttrs = null;
235     Object[] nioFloatBufferRefVertexAttrs = null;
236 
237     // used by "by reference" tex coords
238     Object[] refTexCoords = null;
239     TexCoord2f[] t2fRefTexCoords = null;
240     TexCoord3f[] t3fRefTexCoords = null;
241 
242     // Used for NIO buffer tex coords
243     Object[] refTexCoordsBuffer = null;
244     //FloatBufferWrapper[] floatBufferRefTexCoords = null;
245 
246 
247     // used by interleaved array
248     float[] interLeavedVertexData = null;
249 
250     // used by interleaved NIO buffer
251     J3DBuffer interleavedVertexBuffer = null;
252     FloatBufferWrapper interleavedFloatBufferImpl = null;
253 
254     // pointers used, when transparency is turned on
255     // or when its an object such as C3F, P3F etc ..
256     float[] mirrorFloatRefCoords = null;
257     double[] mirrorDoubleRefCoords = null;
258     float[] mirrorFloatRefNormals = null;
259     float[][] mirrorFloatRefVertexAttrs = null;
260     float[] mirrorFloatRefTexCoords = null;
261     Object[] mirrorRefTexCoords = null;
262 
263     float[][] mirrorFloatRefColors = new float[1][];
264     byte[][] mirrorUnsignedByteRefColors= new byte[1][];
265     float[][] mirrorInterleavedColorPointer = null;
266 
267     // boolean to determine if a mirror was allocated
268     int mirrorVertexAllocated = 0;
269     int mirrorColorAllocated = 0;
270     boolean mirrorNormalAllocated = false;
271 
272     // Some dirty bits for GeometryArrays
273     static final int COORDINATE_CHANGED 	= 0x01;
274     static final int NORMAL_CHANGED 		= 0x02;
275     static final int COLOR_CHANGED 		= 0x04;
276     static final int TEXTURE_CHANGED 		= 0x08;
277     static final int BOUNDS_CHANGED 		= 0x10;
278     static final int INDEX_CHANGED 		= 0x20;
279     static final int STRIPCOUNT_CHANGED 	= 0x40;
280     static final int VATTR_CHANGED 		= 0x80;
281     static final int VERTEX_CHANGED             = COORDINATE_CHANGED |
282                                                   NORMAL_CHANGED |
283                                                   COLOR_CHANGED |
284                                                   TEXTURE_CHANGED |
285                                                   VATTR_CHANGED;
286 
287     static final int defaultTexCoordSetMap[] = {0};
288     int texCoordSetCount = 0;
289     int [] texCoordSetMap = null;
290 
291     // this array contains offset to the texCoord data for each
292     // texture unit.  -1 means no corresponding texCoord data offset
293     int [] texCoordSetMapOffset = null;
294 
295     // Vertex attribute information
296     int vertexAttrCount = 0;
297     int[] vertexAttrSizes = null;
298 
299 
300     // This point to a list of VertexBuffers in a Vector structure
301     // Each element correspond to a D3D context that create this VB.
302     // Note that this GeometryArray can be used by multiple ctx.
303     long pVertexBuffers = 0;
304     int dirtyFlag;
305 
306     // each bit corresponds to a unique renderer if shared context
307     // or a unique canvas otherwise
308     int resourceCreationMask = 0x0;
309 
310     // Fix for Issue 5
311     //
312     // Replace the per-canvas reference count with a per-RenderBin set
313     // of users.  The per-RenderBin set of users of this display list
314     // is defined as a HashMap where:
315     //
316     //   key   = the RenderBin
317     //   value = a set of RenderAtomListInfo objects using this
318     //           geometry array for display list purposes
319     private HashMap dlistUsers = null;
320 
321     // timestamp used to create display list. This is either
322     // one per renderer for useSharedCtx, or one per Canvas for non-shared
323     // ctx
324     private long[] timeStampPerDlist = new long[2];
325 
326     // Unique display list Id, if this geometry is shared
327     int dlistId = -1;
328     Integer dlistObj = null;
329 
330     // A list of pre-defined bits to indicate which component
331     // in this Texture object changed.
332     //    static final int DLIST_CREATE_CHANGED      = 0x01;
333     static final int INIT_MIRROR_GEOMETRY      = 0x02;
334 
335 
336     // A list of Universes that this Geometry is referenced in Morph from
337     ArrayList morphUniverseList = null;
338 
339     // A list of ArrayLists which contain all the MorphRetained objects
340     // refering to this geometry.  Each list corresponds to the universe
341     // above.
342     ArrayList morphUserLists = null;
343 
344     // The following variables are only used in compile mode
345 
346     // Offset of a geometry array into the merged array
347     int[] geoOffset;
348 
349     // vertexcount of a geometry array in a merge array
350     int[] compileVcount;
351 
352     boolean isCompiled = false;
353 
354     boolean isShared = false;
355 
356     IndexedGeometryArrayRetained cloneSourceArray = null;
357 
358     static final double EPS = 1.0e-13;
359 
freeD3DArray(boolean deleteVB)360     void freeD3DArray(boolean deleteVB) {
361         assert VirtualUniverse.mc.isD3D();
362         Pipeline.getPipeline().freeD3DArray(this, deleteVB);
363     }
364 
GeometryArrayRetained()365     GeometryArrayRetained() {
366 	dirtyFlag = INDEX_CHANGED|VERTEX_CHANGED;
367         lastAlpha[0] = 1.0f;
368     }
369 
370 
setLive(boolean inBackgroundGroup, int refCount)371     void setLive(boolean inBackgroundGroup, int refCount) {
372 	dirtyFlag = VERTEX_CHANGED|INDEX_CHANGED;
373         isEditable = !isWriteStatic();
374         super.doSetLive(inBackgroundGroup, refCount);
375 	super.markAsLive();
376 	// Send message to RenderingAttribute structure to obtain a dlistId
377 	//	System.err.println("Geometry - "+this+"refCount = "+this.refCount);
378 	if (this.refCount > 1) {
379 	    // Send to rendering attribute structure,
380 	    /*
381 	    J3dMessage createMessage = new J3dMessage();
382 	    createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
383 	    createMessage.type = J3dMessage.GEOMETRYARRAY_CHANGED;
384 	    createMessage.universe = null;
385 	    createMessage.args[0] = this;
386 	    createMessage.args[1]= new Integer(DLIST_CREATE_CHANGED);
387 	    VirtualUniverse.mc.processMessage(createMessage);
388 	    */
389 	    isShared = true;
390 	} // Clone geometry only for the first setLive
391 	else {
392 	    // If geometry is indexed and use_index_coord is false, unindexify
393 	    // otherwise, set mirrorGeometry to null (from previous clearLive)
394 	    if (this instanceof IndexedGeometryArrayRetained) {
395 		// Send to rendering attribute structure,
396 		J3dMessage createMessage = new J3dMessage();
397 		createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
398 		createMessage.type = J3dMessage.GEOMETRY_CHANGED;
399 		createMessage.universe = null;
400 		createMessage.args[0] = null;
401 		createMessage.args[1]= this;
402 		createMessage.args[2]= new Integer(INIT_MIRROR_GEOMETRY);
403 		VirtualUniverse.mc.processMessage(createMessage);
404 	    }
405 	}
406 
407     }
408 
clearLive(int refCount)409     void clearLive(int refCount) {
410 	super.clearLive(refCount);
411 
412 	if (this.refCount <= 0) {
413 	    if (pVertexBuffers != 0) {
414 		J3dMessage renderMessage = new J3dMessage();
415 		renderMessage.threads = J3dThread.RENDER_THREAD;
416 		renderMessage.type = J3dMessage.RENDER_IMMEDIATE;
417 		renderMessage.universe = null;
418 		renderMessage.view = null;
419 		renderMessage.args[0] = null;
420 		renderMessage.args[1] = this;
421 		// Any one renderer is fine since VB store the ctx
422 		// where it is created.
423 		Enumeration e = Screen3D.deviceRendererMap.elements();
424 		Renderer rdr = (Renderer) e.nextElement();
425 		rdr.rendererStructure.addMessage(renderMessage);
426 		VirtualUniverse.mc.setWorkForRequestRenderer();
427 	    }
428 	    isShared = false;
429 	}
430     }
431 
computeBoundingBox()432     void computeBoundingBox() {
433 
434 	//	System.err.println("computeBoundingBox ....");
435 
436         if (boundsDirty && VirtualUniverse.mc.cacheAutoComputedBounds) {
437             for(ArrayList<Shape3DRetained> users : userLists) {
438                 for(Shape3DRetained shape : users)
439                     shape.dirtyBoundsCache();
440             }
441         }
442 
443 	if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
444 	    // by copy
445 	    computeBoundingBox(initialVertexIndex, vertexData);
446 
447 	} else if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { // USE_NIO_BUFFER
448 	    //System.err.println("vertexFormat & GeometryArray.USE_NIO_BUFFER");
449 	    if((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
450 		computeBoundingBox(initialCoordIndex, interleavedFloatBufferImpl);
451 	    } else if((vertexType & PF) != 0) {
452 		computeBoundingBox(floatBufferRefCoords);
453 	    } else if((vertexType & PD) != 0) {
454 		computeBoundingBox(doubleBufferRefCoords);
455 	    }
456 
457 	} else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
458 	    //System.err.println("vertexFormat & GeometryArray.INTERLEAVED");
459 	    computeBoundingBox(initialCoordIndex, interLeavedVertexData);
460 	} else if ((vertexType & PF) != 0) {
461 	    //System.err.println("vertexType & PF");
462 	    computeBoundingBox(floatRefCoords);
463 	} else if ((vertexType & P3F) != 0) {
464 	    //System.err.println("vertexType & P3F");
465 	    computeBoundingBox(p3fRefCoords);
466 	} else if ((vertexType & P3D) != 0) {
467 	    //System.err.println("vertexType & P3D");
468 	    computeBoundingBox(p3dRefCoords);
469 	} else if ((vertexType & PD) != 0) {
470 	    //System.err.println("vertexType & PD");
471 	    computeBoundingBox(doubleRefCoords);
472 	}
473 
474     }
475 
476 
477     // NullGeometry is true only for byRef case
processCoordsChanged(boolean nullGeo)478     void processCoordsChanged(boolean nullGeo) {
479 
480 	/*
481 	  System.err.println("processCoordsChanged : nullGeo " + nullGeo);
482 	  System.err.println("Before :processCoordsChanged : geoBounds ");
483 	  System.err.println(geoBounds);
484 	*/
485 	if (nullGeo) {
486 	    synchronized(geoBounds) {
487 		geoBounds.setLower(-1.0, -1.0, -1.0);
488 		geoBounds.setUpper(1.0, 1.0, 1.0);
489 		boundsDirty = false;
490 	    }
491 	    synchronized(centroid) {
492 		recompCentroid = false;
493 		this.centroid.set(geoBounds.getCenter());
494 	    }
495 
496 	}
497 	else {
498 	    // re-compute centroid if used
499 	    synchronized(centroid) {
500 		recompCentroid = true;
501 	    }
502 
503 	    synchronized(geoBounds) {
504 		boundsDirty = true;
505 		computeBoundingBox();
506 	    }
507 
508 	    /*
509 	      System.err.println("After :processCoordsChanged : geoBounds ");
510 	      System.err.println(geoBounds);
511 	    */
512 	}
513     }
514 
515 
computeBoundingBox(int vIndex, float[] vdata)516     void computeBoundingBox(int vIndex, float[] vdata) {
517 	int i, offset;
518 	double xmin, xmax, ymin, ymax, zmin, zmax;
519 
520 
521 	//System.err.println("Before : computeBoundingBox : geoBounds ");
522 	//  System.err.println(geoBounds);
523 
524 	synchronized(geoBounds) {
525 
526 	    // If autobounds compute is false  then return
527 	    // It is possible that user call getBounds() before
528 	    // this Geometry add to live scene graph.
529 	    if ((computeGeoBounds == 0) && (refCount > 0)) {
530 	    	return;
531 	    }
532 	    if (!boundsDirty)
533 		return;
534 
535 	    // Initial offset
536 	    offset = vIndex * stride+coordinateOffset;
537 	    // Compute the bounding box
538 	    xmin = xmax = vdata[offset];
539 	    ymin = ymax = vdata[offset+1];
540 	    zmin = zmax = vdata[offset+2];
541 	    offset += stride;
542 	    for (i=1; i<validVertexCount; i++) {
543 		if (vdata[offset] > xmax)
544 		    xmax = vdata[offset];
545 		if (vdata[offset] < xmin)
546 		    xmin = vdata[offset];
547 
548 		if (vdata[offset+1] > ymax)
549 		    ymax = vdata[offset+1];
550 		if (vdata[offset+1] < ymin)
551 		    ymin = vdata[offset+1];
552 
553 		if (vdata[offset+2] > zmax)
554 		    zmax = vdata[offset+2];
555 		if (vdata[offset+2] < zmin)
556 		    zmin = vdata[offset+2];
557 
558 		offset += stride;
559 	    }
560 
561 	    geoBounds.setUpper(xmax, ymax, zmax);
562 	    geoBounds.setLower(xmin, ymin, zmin);
563 	    boundsDirty = false;
564 	}
565 	/*
566 	  System.err.println("After : computeBoundingBox : geoBounds ");
567 	  System.err.println(geoBounds);
568 	*/
569     }
570 
571     // Compute boundingbox for interleaved nio buffer
computeBoundingBox(int vIndex, FloatBufferWrapper vdata)572     void computeBoundingBox(int vIndex,   FloatBufferWrapper vdata) {
573 	int i, offset;
574 	double xmin, xmax, ymin, ymax, zmin, zmax;
575 
576 
577 	synchronized(geoBounds) {
578 	    // If autobounds compute is false  then return
579 	    if ((computeGeoBounds == 0) && (refCount > 0)) {
580 		return;
581 	    }
582 
583 	    if (!boundsDirty)
584 		return;
585 
586 	    // Initial offset
587 	    offset = vIndex * stride+coordinateOffset;
588 	    // Compute the bounding box
589 	    xmin = xmax = vdata.get(offset);
590 	    ymin = ymax = vdata.get(offset+1);
591 	    zmin = zmax = vdata.get(offset+2);
592 	    offset += stride;
593 	    for (i=1; i<validVertexCount; i++) {
594 		if (vdata.get(offset) > xmax)
595 		    xmax = vdata.get(offset);
596 		if (vdata.get(offset) < xmin)
597 		    xmin = vdata.get(offset);
598 
599 		if (vdata.get(offset+1) > ymax)
600 		    ymax = vdata.get(offset+1);
601 		if (vdata.get(offset+1) < ymin)
602 		    ymin = vdata.get(offset+1);
603 
604 		if (vdata.get(offset+2) > zmax)
605 		    zmax = vdata.get(offset+2);
606 		if (vdata.get(offset+2) < zmin)
607 		    zmin = vdata.get(offset+2);
608 
609 		offset += stride;
610 	    }
611 
612 	    geoBounds.setUpper(xmax, ymax, zmax);
613 	    geoBounds.setLower(xmin, ymin, zmin);
614 	    boundsDirty = false;
615 	}
616     }
617 
618 
619     // compute bounding box for coord with noi buffer
computeBoundingBox( DoubleBufferWrapper buffer)620     void computeBoundingBox( DoubleBufferWrapper buffer) {
621 	int i, j, k, sIndex;
622 	double xmin, xmax, ymin, ymax, zmin, zmax;
623 
624 	synchronized(geoBounds) {
625 	    // If autobounds compute is false  then return
626 	    if ((computeGeoBounds == 0) && (refCount > 0)) {
627 		return;
628 	    }
629 
630 	    if (!boundsDirty)
631 		return;
632 
633 	    sIndex = initialCoordIndex;
634 	    int maxIndex = 3*validVertexCount;
635 
636 	    // Compute the bounding box
637 	    xmin = xmax = buffer.get(sIndex++);
638 	    ymin = ymax = buffer.get(sIndex++);
639 	    zmin = zmax = buffer.get(sIndex++);
640 
641 	    for (i=sIndex; i<maxIndex; i+=3) {
642 		j = i + 1;
643 		k = i + 2;
644 
645 		if (buffer.get(i) > xmax)
646 		    xmax = buffer.get(i);
647 		if (buffer.get(i) < xmin)
648 		    xmin = buffer.get(i);
649 
650 		if (buffer.get(j) > ymax)
651 		    ymax = buffer.get(j);
652 		if (buffer.get(j) < ymin)
653 		    ymin = buffer.get(j);
654 
655 		if (buffer.get(k) > zmax)
656 		    zmax = buffer.get(k);
657 		if (buffer.get(k) < zmin)
658 		    zmin = buffer.get(k);
659 
660 	    }
661 	    geoBounds.setUpper(xmax, ymax, zmax);
662 	    geoBounds.setLower(xmin, ymin, zmin);
663 	    boundsDirty = false;
664 	}
665     }
666 
667     // compute bounding box for coord with noi buffer
computeBoundingBox( FloatBufferWrapper buffer)668     void computeBoundingBox( FloatBufferWrapper buffer) {
669 	int i, j, k, sIndex;
670 	double xmin, xmax, ymin, ymax, zmin, zmax;
671 
672 
673 	synchronized(geoBounds) {
674 	    // If autobounds compute is false  then return
675 	    if ((computeGeoBounds == 0) && (refCount > 0)) {
676 		return;
677 	    }
678 
679 	    if (!boundsDirty)
680 		return;
681 
682 
683 	    sIndex = initialCoordIndex;
684 	    int maxIndex = 3*validVertexCount;
685 
686 	    // Compute the bounding box
687 	    xmin = xmax = buffer.get(sIndex++);
688 	    ymin = ymax = buffer.get(sIndex++);
689 	    zmin = zmax = buffer.get(sIndex++);
690 
691 	    for (i=sIndex; i<maxIndex; i+=3) {
692 		j = i + 1;
693 		k = i + 2;
694 
695 		if (buffer.get(i) > xmax)
696 		    xmax = buffer.get(i);
697 		if (buffer.get(i) < xmin)
698 		    xmin = buffer.get(i);
699 
700 		if (buffer.get(j) > ymax)
701 		    ymax = buffer.get(j);
702 		if (buffer.get(j) < ymin)
703 		    ymin = buffer.get(j);
704 
705 		if (buffer.get(k) > zmax)
706 		    zmax = buffer.get(k);
707 		if (buffer.get(k) < zmin)
708 		    zmin = buffer.get(k);
709 
710 	    }
711 	    geoBounds.setUpper(xmax, ymax, zmax);
712 	    geoBounds.setLower(xmin, ymin, zmin);
713 	    boundsDirty = false;
714 	}
715     }
716 
computeBoundingBox(float[] coords)717     void computeBoundingBox(float[] coords) {
718 	// System.err.println("GeometryArrayRetained : computeBoundingBox(float[] coords)");
719 	int i, j, k, sIndex;
720 	double xmin, xmax, ymin, ymax, zmin, zmax;
721 
722 	synchronized(geoBounds) {
723 	    // If autobounds compute is false  then return
724 	    if ((computeGeoBounds == 0) && (refCount > 0)) {
725 		return;
726 	    }
727 
728 	    if (!boundsDirty)
729 		return;
730 
731 	    sIndex = initialCoordIndex;
732 	    int maxIndex = 3*validVertexCount;
733 
734 	// Compute the bounding box
735 	    xmin = xmax = coords[sIndex++];
736 	    ymin = ymax = coords[sIndex++];
737 	    zmin = zmax = coords[sIndex++];
738 
739 	    for (i=sIndex; i<maxIndex; i+=3) {
740 		j = i + 1;
741 		k = i + 2;
742 
743 		if (coords[i] > xmax)
744 		    xmax = coords[i];
745 		if (coords[i] < xmin)
746 		    xmin = coords[i];
747 
748 		if (coords[j] > ymax)
749 		    ymax = coords[j];
750 		if (coords[j] < ymin)
751 		    ymin = coords[j];
752 
753 		if (coords[k] > zmax)
754 		    zmax = coords[k];
755 		if (coords[k] < zmin)
756 		    zmin = coords[k];
757 
758 	    }
759 	    geoBounds.setUpper(xmax, ymax, zmax);
760 	    // System.err.println("max(" + xmax + ", " + ymax + ", " + zmax + ")");
761 	    geoBounds.setLower(xmin, ymin, zmin);
762 	    // System.err.println("min(" + xmin + ", " + ymin + ", " + zmin + ")");
763 
764 	    boundsDirty = false;
765 	}
766 
767     }
768 
computeBoundingBox(double[] coords)769     void computeBoundingBox(double[] coords) {
770 	int i, j, k, sIndex;
771 	double xmin, xmax, ymin, ymax, zmin, zmax;
772 
773 	synchronized(geoBounds) {
774 	    // If autobounds compute is false  then return
775 	    if ((computeGeoBounds == 0) && (refCount > 0)) {
776 		return;
777 	    }
778 
779 	    if (!boundsDirty)
780 		return;
781 
782 
783 	    sIndex = initialCoordIndex;
784 	    int maxIndex = 3*validVertexCount;
785 
786 	    // Compute the bounding box
787 	    xmin = xmax = coords[sIndex++];
788 	    ymin = ymax = coords[sIndex++];
789 	    zmin = zmax = coords[sIndex++];
790 
791 	    for (i=sIndex; i<maxIndex; i+=3) {
792 		j = i + 1;
793 		k = i + 2;
794 
795 		if (coords[i] > xmax)
796 		    xmax = coords[i];
797 		if (coords[i] < xmin)
798 		    xmin = coords[i];
799 
800 		if (coords[j] > ymax)
801 		    ymax = coords[j];
802 		if (coords[j] < ymin)
803 		    ymin = coords[j];
804 
805 		if (coords[k] > zmax)
806 		    zmax = coords[k];
807 		if (coords[k] < zmin)
808 		    zmin = coords[k];
809 
810 	    }
811 	    geoBounds.setUpper(xmax, ymax, zmax);
812 	    geoBounds.setLower(xmin, ymin, zmin);
813 	    boundsDirty = false;
814 	}
815 
816     }
817 
computeBoundingBox(Point3f[] coords)818     void computeBoundingBox(Point3f[] coords) {
819 
820 	double xmin, xmax, ymin, ymax, zmin, zmax;
821 	Point3f p;
822 
823 	synchronized(geoBounds) {
824 	    // If autobounds compute is false  then return
825 	    if ((computeGeoBounds == 0) && (refCount > 0)) {
826 		return;
827 	    }
828 
829 	    if (!boundsDirty)
830 		return;
831 
832 
833 
834 	// Compute the bounding box
835 	    xmin = xmax = coords[initialCoordIndex].x;
836 	    ymin = ymax = coords[initialCoordIndex].y;
837 	    zmin = zmax = coords[initialCoordIndex].z;
838 
839 	    for (int i=initialCoordIndex+1; i<validVertexCount; i++) {
840 		p = coords[i];
841 		if (p.x > xmax) xmax = p.x;
842 		if (p.x < xmin) xmin = p.x;
843 
844 		if (p.y > ymax) ymax = p.y;
845 		if (p.y < ymin) ymin = p.y;
846 
847 		if (p.z > zmax) zmax = p.z;
848 		if (p.z < zmin) zmin = p.z;
849 
850 	    }
851 	    geoBounds.setUpper(xmax, ymax, zmax);
852 	    geoBounds.setLower(xmin, ymin, zmin);
853 	    boundsDirty = false;
854 	}
855 
856     }
857 
computeBoundingBox(Point3d[] coords)858     void computeBoundingBox(Point3d[] coords) {
859 
860 	double xmin, xmax, ymin, ymax, zmin, zmax;
861 	Point3d p;
862 
863 	synchronized(geoBounds) {
864 	    // If autobounds compute is false  then return
865 	    if ((computeGeoBounds == 0) && (refCount > 0)) {
866 		return;
867 	    }
868 
869 	    if (!boundsDirty)
870 		return;
871 
872 
873 	// Compute the bounding box
874 	    xmin = xmax = coords[initialCoordIndex].x;
875 	    ymin = ymax = coords[initialCoordIndex].y;
876 	    zmin = zmax = coords[initialCoordIndex].z;
877 
878 	    for (int i=initialCoordIndex+1; i<validVertexCount; i++) {
879 		p = coords[i];
880 		if (p.x > xmax) xmax = p.x;
881 		if (p.x < xmin) xmin = p.x;
882 
883 		if (p.y > ymax) ymax = p.y;
884 		if (p.y < ymin) ymin = p.y;
885 
886 		if (p.z > zmax) zmax = p.z;
887 		if (p.z < zmin) zmin = p.z;
888 
889 	    }
890 	    geoBounds.setUpper(xmax, ymax, zmax);
891 	    geoBounds.setLower(xmin, ymin, zmin);
892 	    boundsDirty = false;
893 	}
894 
895     }
896 
897 
update()898     synchronized void update() {
899     }
900 
setupMirrorVertexPointer(int vType)901     void setupMirrorVertexPointer(int vType) {
902 	int i, index;
903 
904 	switch (vType) {
905 	case PF:
906 	    if (floatRefCoords == null) {
907 		if ((vertexType & VERTEX_DEFINED) == PF) {
908 		    vertexType &= ~PF;
909 		    mirrorFloatRefCoords = null;
910 		    mirrorVertexAllocated &= ~PF;
911 		}
912 	    }
913 	    else {
914 		vertexType |= PF;
915 		mirrorFloatRefCoords = floatRefCoords;
916 		mirrorVertexAllocated &= ~PF;
917 	    }
918 
919 	    break;
920 	case PD:
921 	    if (doubleRefCoords == null) {
922 		if ((vertexType & VERTEX_DEFINED) == PD) {
923 		    mirrorDoubleRefCoords = null;
924 		    mirrorVertexAllocated &= ~PD;
925 		    vertexType &= ~PD;
926 		}
927 		vertexType &= ~PD;
928 	    }
929 	    else {
930 		vertexType |= PD;
931 		mirrorDoubleRefCoords = doubleRefCoords;
932 		mirrorVertexAllocated &= ~PD;
933 	    }
934 
935 	    break;
936 	case P3F:
937 	    if (p3fRefCoords == null) {
938 		vertexType &= ~P3F;
939 		// Don't set the mirrorFloatRefCoords to null,
940 		// may be able to re-use
941 		//	    mirrorFloatRefCoords = null;
942 	    }
943 	    else {
944 		vertexType |= P3F;
945 
946 		if ((mirrorVertexAllocated & PF) == 0) {
947 		    mirrorFloatRefCoords = new float[vertexCount * 3];
948 		    mirrorVertexAllocated |= PF;
949 		}
950 
951 		index = initialCoordIndex * 3;
952 		for ( i=initialCoordIndex; i<validVertexCount; i++) {
953 		    mirrorFloatRefCoords[index++] = p3fRefCoords[i].x;
954 		    mirrorFloatRefCoords[index++] = p3fRefCoords[i].y;
955 		    mirrorFloatRefCoords[index++] = p3fRefCoords[i].z;
956 		}
957 	    }
958 	    break;
959 	case P3D:
960 	    if (p3dRefCoords == null) {
961 		vertexType &= ~P3D;
962 		// Don't set the mirrorDoubleRefCoords to null,
963 		// may be able to re-use
964 		//	    mirrorDoubleRefCoords = null;
965 	    }
966 	    else {
967 		vertexType |= P3D;
968 
969 		if ((mirrorVertexAllocated & PD) == 0) {
970 		    mirrorDoubleRefCoords = new double[vertexCount * 3];
971 		    mirrorVertexAllocated |= PD;
972 		}
973 
974 		index = initialCoordIndex * 3;
975 		for ( i=initialCoordIndex; i<validVertexCount; i++) {
976 		    mirrorDoubleRefCoords[index++] = p3dRefCoords[i].x;
977 		    mirrorDoubleRefCoords[index++] = p3dRefCoords[i].y;
978 		    mirrorDoubleRefCoords[index++] = p3dRefCoords[i].z;
979 		}
980 	    }
981 	    break;
982 	default:
983 	    break;
984 
985 	}
986 
987     }
988 
989     // If turned transparent the first time, then force it to allocate
setupMirrorInterleavedColorPointer(boolean force)990     void setupMirrorInterleavedColorPointer(boolean force) {
991 	int index, length, offset;
992 	int i;
993 
994 	if (force || (c4fAllocated != 0)) { // Color is present
995 
996 	    length = 4 * vertexCount;
997 
998 	    if (mirrorInterleavedColorPointer == null) {
999 		mirrorInterleavedColorPointer = new float[1][length];
1000 	    }
1001 
1002 	    index = 4 * initialVertexIndex;
1003 	    offset = stride * initialVertexIndex + colorOffset;
1004 
1005 	    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0 &&
1006 		interLeavedVertexData != null ) { // java array
1007 		if ((vertexFormat  & GeometryArray.WITH_ALPHA) != 0) {
1008 
1009 		    for (i = initialVertexIndex; i < validVertexCount; i++) {
1010 			mirrorInterleavedColorPointer[0][index++] =
1011 			    interLeavedVertexData[offset];
1012 			mirrorInterleavedColorPointer[0][index++] =
1013 			    interLeavedVertexData[offset+1];
1014 			mirrorInterleavedColorPointer[0][index++] =
1015 			    interLeavedVertexData[offset+2];
1016 			mirrorInterleavedColorPointer[0][index++] =
1017 			    interLeavedVertexData[offset+3];
1018 			offset += stride;
1019 		    }
1020 		}
1021 		else {
1022 		    for (i = initialVertexIndex; i < validVertexCount; i++) {
1023 			mirrorInterleavedColorPointer[0][index++] =
1024 			    interLeavedVertexData[offset];
1025 			mirrorInterleavedColorPointer[0][index++] =
1026 			    interLeavedVertexData[offset+1];
1027 			mirrorInterleavedColorPointer[0][index++] =
1028 			    interLeavedVertexData[offset+2];
1029 			mirrorInterleavedColorPointer[0][index++] = 1.0f;
1030 			offset += stride;
1031 		    }
1032 		}
1033 
1034 	    } else { // NIO BUFFER
1035 		if ((vertexFormat  & GeometryArray.WITH_ALPHA) != 0 &&
1036 		    interleavedFloatBufferImpl != null) {
1037 		    for (i = initialVertexIndex; i < validVertexCount; i++) {
1038 			interleavedFloatBufferImpl.position(offset);
1039 			interleavedFloatBufferImpl.get(mirrorInterleavedColorPointer[0],
1040 						       index , 4);
1041 			index += 4;
1042 			offset += stride;
1043 		    }
1044 		}
1045 		else {
1046 		    for (i = initialVertexIndex; i < validVertexCount; i++) {
1047 			interleavedFloatBufferImpl.position(offset);
1048 			interleavedFloatBufferImpl.get(mirrorInterleavedColorPointer[0],
1049 						       index, 3);
1050 			mirrorInterleavedColorPointer[0][index+3] = 1.0f;
1051 			index += 4;
1052 			offset += stride;
1053 
1054 		    }
1055 		}
1056 	    }
1057 	    c4fAllocated = GeometryArray.WITH_ALPHA;
1058 	}
1059     }
1060 
1061     // If turned transparent the first time, then force it to allocate
setupMirrorColorPointer(int ctype, boolean force)1062     void setupMirrorColorPointer(int ctype, boolean force) {
1063 	int i, srcIndex = 0, dstIndex = 0;
1064 	int multiplier;
1065 
1066  	if (c4fAllocated == 0 && !force) {
1067 	    multiplier = 3;
1068 	} else {
1069 
1070 	    // If the first time, we are forced to allocate 4f, then
1071 	    // we need to force the allocation of the colors again
1072 	    // for the case when allocation has previously occurred
1073 	    // only for RGB
1074 	    if (force && (c4fAllocated == 0) &&
1075 		(vertexFormat & GeometryArray.WITH_ALPHA) == 0)  {
1076 		mirrorColorAllocated = 0;
1077 	    }
1078 	    c4fAllocated = GeometryArray.WITH_ALPHA;
1079 	    multiplier = 4;
1080 	}
1081 
1082 	if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) { // java array
1083 	    switch (ctype) {
1084 	    case CF:
1085 		if (floatRefColors == null) {
1086 		    if ((c4fAllocated == 0) && !force &&
1087 			(vertexType & COLOR_DEFINED) == CF) {
1088 			mirrorFloatRefColors[0] = null;
1089 			mirrorColorAllocated &= ~CF;
1090 		    }
1091 		    vertexType &= ~CF;
1092 		    return;
1093 		}
1094 
1095 		vertexType |= CF;
1096 		if (c4fAllocated == 0 && !force) {
1097 		    mirrorFloatRefColors[0] = floatRefColors;
1098 		    mirrorColorAllocated &= ~CF;
1099 		}
1100 		else {
1101  		    if ((mirrorColorAllocated & CF) == 0) {
1102 			mirrorFloatRefColors[0] = new float[4 * vertexCount];
1103 			mirrorColorAllocated |= CF;
1104 		    }
1105 
1106 		    if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
1107 
1108 			srcIndex = initialColorIndex * 3;
1109 			dstIndex = initialColorIndex * 4;
1110 
1111 			for (i = initialColorIndex; i < validVertexCount; i++) {
1112 			    mirrorFloatRefColors[0][dstIndex++] =
1113 				floatRefColors[srcIndex++];
1114 			    mirrorFloatRefColors[0][dstIndex++] =
1115 				floatRefColors[srcIndex++];
1116 			    mirrorFloatRefColors[0][dstIndex++] =
1117 				floatRefColors[srcIndex++];
1118 			    mirrorFloatRefColors[0][dstIndex++] = 1.0f;
1119 			}
1120 
1121 		    }
1122 		    else {
1123 			srcIndex = initialColorIndex * 4;
1124 			System.arraycopy(floatRefColors, srcIndex,
1125 					 mirrorFloatRefColors[0], srcIndex,
1126 					 (4*validVertexCount));
1127 		    }
1128 		}
1129 		break;
1130 	    case CUB:
1131 		if (byteRefColors == null) {
1132 		    if (c4fAllocated == 0 && !force &&
1133 			((vertexType & COLOR_DEFINED) == CUB) ) {
1134 			mirrorUnsignedByteRefColors[0] = null;
1135 			mirrorColorAllocated &= ~CUB;
1136 		    }
1137 		    vertexType &= ~CUB;
1138 		    return;
1139 		}
1140 		vertexType |= CUB;
1141 		if (c4fAllocated == 0 && !force) {
1142 		    mirrorUnsignedByteRefColors[0] = byteRefColors;
1143 		    mirrorColorAllocated &= ~CUB;;
1144 		}
1145 		else {
1146 		    if ((mirrorColorAllocated & CUB) == 0) {
1147 			mirrorUnsignedByteRefColors[0] = new byte[4 * vertexCount];
1148 			mirrorColorAllocated |= CUB;
1149 		    }
1150 		    if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
1151 
1152 			srcIndex = initialColorIndex * 3;
1153 			dstIndex = initialColorIndex * 4;
1154 
1155 			for (i = initialColorIndex; i < validVertexCount; i++) {
1156 			    mirrorUnsignedByteRefColors[0][dstIndex++] =
1157 				byteRefColors[srcIndex++];
1158 			    mirrorUnsignedByteRefColors[0][dstIndex++] =
1159 				byteRefColors[srcIndex++];
1160 			    mirrorUnsignedByteRefColors[0][dstIndex++] =
1161 				byteRefColors[srcIndex++];
1162 			    mirrorUnsignedByteRefColors[0][dstIndex++] =
1163 				(byte)(255.0);
1164 			}
1165 		    }
1166 		    else {
1167 			srcIndex = initialColorIndex * 4;
1168 			System.arraycopy(byteRefColors, srcIndex,
1169 					 mirrorUnsignedByteRefColors[0], srcIndex,
1170 					 (4*validVertexCount));
1171 		    }
1172 		}
1173 
1174 		break;
1175 	    case C3F:
1176 		if (c3fRefColors == null) {
1177 		    vertexType &= ~C3F;
1178 		    return;
1179 		}
1180 		vertexType |=C3F ;
1181 
1182 		if ((mirrorColorAllocated & CF) == 0) {
1183 		    mirrorFloatRefColors[0] = new float[vertexCount * multiplier];
1184 		    mirrorColorAllocated |= CF;
1185 		}
1186 		if ((c4fAllocated & GeometryArray.WITH_ALPHA) == 0) {
1187 
1188 		    dstIndex = initialColorIndex * 3;
1189 		    for (i = initialColorIndex; i < validVertexCount; i++) {
1190 			mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].x;
1191 			mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].y;
1192 			mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].z;
1193 		    }
1194 		} else {
1195 
1196 		    dstIndex = initialColorIndex * 4;
1197 		    for (i = initialColorIndex; i < validVertexCount; i++) {
1198 			mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].x;
1199 			mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].y;
1200 			mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].z;
1201 			mirrorFloatRefColors[0][dstIndex++] = 1.0f;
1202 		    }
1203 		}
1204 
1205 		break;
1206 	    case C4F:
1207 		if (c4fRefColors == null) {
1208 		    vertexType &= ~C4F;
1209 		    return;
1210 		}
1211 		vertexType |=C4F ;
1212 
1213 		if ((mirrorColorAllocated & CF) == 0) {
1214 		    mirrorFloatRefColors[0] = new float[vertexCount << 2];
1215 		    mirrorColorAllocated |= CF;
1216 		}
1217 
1218 		dstIndex = initialColorIndex * 4;
1219 		for (i = initialColorIndex; i < validVertexCount; i++) {
1220 		    mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].x;
1221 		    mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].y;
1222 		    mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].z;
1223 		    mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].w;
1224 		}
1225 		break;
1226 	    case C3UB:
1227 		if (c3bRefColors == null) {
1228 		    vertexType &= ~C3UB;
1229 		    return;
1230 		}
1231 		vertexType |=C3UB ;
1232 
1233 		if ((mirrorColorAllocated & CUB) == 0) {
1234 		    mirrorUnsignedByteRefColors[0] =
1235 			new byte[vertexCount * multiplier];
1236 		    mirrorColorAllocated |= CUB;
1237 		}
1238 		if ((c4fAllocated & GeometryArray.WITH_ALPHA) == 0) {
1239 		    dstIndex = initialColorIndex * 3;
1240 		    for (i = initialColorIndex; i < validVertexCount; i++) {
1241 			mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].x;
1242 			mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].y;
1243 			mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].z;
1244 		    }
1245 		} else {
1246 		    dstIndex = initialColorIndex * 4;
1247 		    for (i = initialColorIndex; i < validVertexCount; i++) {
1248 			mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].x;
1249 			mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].y;
1250 			mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].z;
1251 			mirrorUnsignedByteRefColors[0][dstIndex++] = (byte)255;
1252 		    }
1253 		}
1254 		break;
1255 	    case C4UB:
1256 		if (c4bRefColors == null) {
1257 		    vertexType &= ~C4UB;
1258 		    return;
1259 		}
1260 		vertexType |=C4UB ;
1261 		if ((mirrorColorAllocated & CUB) == 0) {
1262 		    mirrorUnsignedByteRefColors[0] = new byte[vertexCount << 2];
1263 		    mirrorColorAllocated |= CUB;
1264 		}
1265 
1266 		dstIndex = initialColorIndex * 4;
1267 		for (i = initialColorIndex; i < validVertexCount; i++) {
1268 		    mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].x;
1269 		    mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].y;
1270 		    mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].z;
1271 		    mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].w;
1272 		}
1273 		break;
1274 	    default:
1275 		break;
1276 	    }
1277 	}
1278 	else {  //USE_NIO_BUFFER is set
1279 	    if(	colorRefBuffer == null) {
1280 		if (c4fAllocated == 0 && !force &&
1281 		    (vertexType & COLOR_DEFINED) == CF) {
1282 		    mirrorFloatRefColors[0] = null;
1283 		    mirrorColorAllocated &= ~CF;
1284 		}
1285 		vertexType &= ~CF;
1286 
1287 		if (c4fAllocated == 0 && !force &&
1288 		    ((vertexType & COLOR_DEFINED) == CUB) ) {
1289 		    mirrorUnsignedByteRefColors[0] = null;
1290 		    mirrorColorAllocated &= ~CUB;
1291 		}
1292 		vertexType &= ~CUB;
1293 		return;
1294 
1295 	    } else if( floatBufferRefColors != null) {
1296 		vertexType |= CF;
1297 		vertexType &= ~CUB;
1298 		if (c4fAllocated == 0 && !force) {
1299 		    // NOTE: make suren mirrorFloatRefColors[0] is set right
1300 		    mirrorFloatRefColors[0] = null;
1301 		    mirrorColorAllocated &= ~CF;
1302 		}
1303 		else {
1304 		    if ((mirrorColorAllocated & CF) == 0) {
1305 			mirrorFloatRefColors[0] = new float[4 * vertexCount];
1306 			mirrorColorAllocated |= CF;
1307 		    }
1308 		    floatBufferRefColors.rewind();
1309 		    if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
1310 			srcIndex = initialColorIndex * 3;
1311 			dstIndex = initialColorIndex * 4;
1312 			floatBufferRefColors.position(srcIndex);
1313 
1314 			for (i = initialColorIndex; i < validVertexCount; i++) {
1315 			    floatBufferRefColors.get(mirrorFloatRefColors[0], dstIndex, 3);
1316 			    mirrorFloatRefColors[0][dstIndex+3] = 1.0f;
1317 			    dstIndex += 4;
1318 			}
1319 		    }
1320 		    else {
1321 
1322 			srcIndex = initialColorIndex * 4;
1323 			dstIndex = initialColorIndex * 4;
1324 			floatBufferRefColors.position(srcIndex);
1325 			for (i = initialColorIndex; i < validVertexCount; i++) {
1326 			    floatBufferRefColors.get(mirrorFloatRefColors[0], dstIndex, 4);
1327 			    dstIndex+= 4;
1328 			}
1329 		    }
1330 		}
1331 	    } else if ( byteBufferRefColors != null) {
1332 		vertexType |= CUB;
1333 		vertexType &= ~CF;
1334 		if (c4fAllocated == 0 && !force) {
1335 		    // NOTE: make sure mirrorUnsignedByteRefColors[0] is set right
1336 		    mirrorUnsignedByteRefColors[0] = null;
1337 		    mirrorColorAllocated &= ~CUB;;
1338 		}
1339 		else {
1340 		    if ((mirrorColorAllocated & CUB) == 0) {
1341 			mirrorUnsignedByteRefColors[0] = new byte[4 * vertexCount];
1342 			mirrorColorAllocated |= CUB;
1343 		    }
1344 
1345 		    byteBufferRefColors.rewind();
1346 		    if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
1347 			srcIndex = initialColorIndex * 3;
1348 			dstIndex = initialColorIndex * 4;
1349 			byteBufferRefColors.position(srcIndex);
1350 			for (i = initialColorIndex; i < validVertexCount; i++) {
1351 			    byteBufferRefColors.get(mirrorUnsignedByteRefColors[0],
1352 						    dstIndex, 3);
1353 			    mirrorUnsignedByteRefColors[0][dstIndex+3] = (byte)(255.0);
1354 			    dstIndex += 4;
1355 			}
1356 		    }
1357 		    else {
1358 			srcIndex = initialColorIndex * 4;
1359 			dstIndex = initialColorIndex * 4;
1360 			byteBufferRefColors.position(srcIndex);
1361 			for (i = initialColorIndex; i < validVertexCount; i++) {
1362 			    byteBufferRefColors.get(mirrorUnsignedByteRefColors[0], dstIndex, 4);
1363 			    dstIndex+= 4;
1364 			}
1365 		    }
1366 		} // end of else
1367 	    }//end of else if ( byteBufferRefColors != null)
1368 	}//end of NIO BUFFER case
1369 
1370 	colorChanged = 0xffff;
1371     }
1372 
1373 
setupMirrorNormalPointer(int ntype)1374     void setupMirrorNormalPointer(int ntype) {
1375 	int i, index;
1376 
1377 	switch (ntype) {
1378 	case NF:
1379 	    if (floatRefNormals == null) {
1380 		if ((vertexType & NORMAL_DEFINED) == NF) {
1381 		    vertexType &= ~NF;
1382 		    mirrorFloatRefNormals = null;
1383 		    mirrorNormalAllocated = false;
1384 		}
1385 	    }
1386 	    else {
1387 		vertexType |= NF;
1388 		mirrorFloatRefNormals = floatRefNormals;
1389 		mirrorNormalAllocated = false;
1390 	    }
1391 	    break;
1392 	case N3F:
1393 	    if (v3fRefNormals == null) {
1394 		if ((vertexType & NORMAL_DEFINED) == N3F) {
1395 		    vertexType &= ~N3F;
1396 		}
1397 		return;
1398 	    }
1399 	    else {
1400 		vertexType |= N3F;
1401 	    }
1402 	    if (!mirrorNormalAllocated) {
1403 		mirrorFloatRefNormals = new float[vertexCount * 3];
1404 		mirrorNormalAllocated = true;
1405 	    }
1406 
1407 	    index = initialNormalIndex * 3;
1408 	    for (i = initialNormalIndex; i < validVertexCount; i++) {
1409 		mirrorFloatRefNormals[index++] = v3fRefNormals[i].x;
1410 		mirrorFloatRefNormals[index++] = v3fRefNormals[i].y;
1411 		mirrorFloatRefNormals[index++] = v3fRefNormals[i].z;
1412 	    }
1413 	    break;
1414 	default:
1415 	    break;	}
1416     }
1417 
setupMirrorTexCoordPointer(int type)1418     void setupMirrorTexCoordPointer(int type) {
1419 	for (int i = 0; i < texCoordSetCount; i++) {
1420 	     doSetupMirrorTexCoordPointer(i, type);
1421 	}
1422 
1423         validateTexCoordPointerType();
1424     }
1425 
setupMirrorTexCoordPointer(int texCoordSet, int type)1426     void setupMirrorTexCoordPointer(int texCoordSet, int type) {
1427         doSetupMirrorTexCoordPointer(texCoordSet, type);
1428         validateTexCoordPointerType();
1429     }
1430 
1431     // If all texCoord pointers are set to a non-null value, then set the
1432     // texcoord type in the vertexType flag word, else clear the texcoord type
validateTexCoordPointerType()1433     private void validateTexCoordPointerType() {
1434         boolean allNonNull = true;
1435         boolean allNull = true;
1436         for (int i = 0; i < texCoordSetCount; i++) {
1437             if (refTexCoords[i] == null) {
1438                 allNonNull = false;
1439             } else {
1440                 allNull = false;
1441             }
1442         }
1443 
1444         // Reset texCoordType if all references are null
1445         if (allNull) {
1446             texCoordType = 0;
1447         }
1448 
1449         // Copy texCoordType to vertexType if all references are non-null
1450         vertexType &= ~TEXCOORD_DEFINED;
1451         if (allNonNull) {
1452             vertexType |= texCoordType;
1453         }
1454     }
1455 
doSetupMirrorTexCoordPointer(int texCoordSet, int type)1456     private void doSetupMirrorTexCoordPointer(int texCoordSet, int type) {
1457 	int i, index;
1458 
1459         switch (type) {
1460 	case TF:
1461             texCoordType = TF;
1462             mirrorRefTexCoords[texCoordSet] = refTexCoords[texCoordSet];
1463 	    break;
1464 
1465         case T2F:
1466             texCoordType = T2F;
1467 	    t2fRefTexCoords = (TexCoord2f[])refTexCoords[texCoordSet];
1468 
1469 	    if (t2fRefTexCoords == null) {
1470                 mirrorRefTexCoords[texCoordSet] = null;
1471 		break;
1472 	    }
1473 
1474             mirrorFloatRefTexCoords = (float[])mirrorRefTexCoords[texCoordSet];
1475             if (mirrorFloatRefTexCoords != null) {
1476                 if (mirrorFloatRefTexCoords.length < (vertexCount * 2))
1477                     mirrorRefTexCoords[texCoordSet] =
1478                         mirrorFloatRefTexCoords = new float[vertexCount * 2];
1479             }
1480             else {
1481                 mirrorRefTexCoords[texCoordSet] =
1482                         mirrorFloatRefTexCoords = new float[vertexCount * 2];
1483             }
1484 
1485 	    index = initialTexCoordIndex[texCoordSet] * 2;
1486 	    for (i = initialTexCoordIndex[texCoordSet]; i < validVertexCount; i++) {
1487 		mirrorFloatRefTexCoords[index++] = t2fRefTexCoords[i].x;
1488 		mirrorFloatRefTexCoords[index++] = t2fRefTexCoords[i].y;
1489 	    }
1490 	    break;
1491 
1492 	case T3F:
1493             texCoordType = T3F;
1494 	    t3fRefTexCoords = (TexCoord3f[])refTexCoords[texCoordSet];
1495 
1496             if (t3fRefTexCoords == null) {
1497                 mirrorRefTexCoords[texCoordSet] = null;
1498 		break;
1499 	    }
1500 
1501             mirrorFloatRefTexCoords = (float[])mirrorRefTexCoords[texCoordSet];
1502             if (mirrorFloatRefTexCoords != null) {
1503                 if (mirrorFloatRefTexCoords.length < (vertexCount * 3))
1504                     mirrorRefTexCoords[texCoordSet] =
1505                         mirrorFloatRefTexCoords = new float[vertexCount * 3];
1506             }
1507             else {
1508                 mirrorRefTexCoords[texCoordSet] =
1509                     mirrorFloatRefTexCoords = new float[vertexCount * 3];
1510             }
1511 
1512 	    index =  initialTexCoordIndex[texCoordSet] * 3;
1513 	    for (i = initialTexCoordIndex[texCoordSet]; i < validVertexCount; i++) {
1514 		mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].x;
1515 		mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].y;
1516 		mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].z;
1517 	    }
1518 	    break;
1519 
1520 	default:
1521 	    break;
1522 	}
1523     }
1524 
setupMirrorVertexAttrPointer(int type)1525     void setupMirrorVertexAttrPointer(int type) {
1526         for (int i = 0; i < vertexAttrCount; i++) {
1527             doSetupMirrorVertexAttrPointer(i, type);
1528         }
1529 
1530         validateVertexAttrPointerType();
1531     }
1532 
setupMirrorVertexAttrPointer(int vertexAttrNum, int type)1533     void setupMirrorVertexAttrPointer(int vertexAttrNum, int type) {
1534         doSetupMirrorVertexAttrPointer(vertexAttrNum, type);
1535         validateVertexAttrPointerType();
1536     }
1537 
1538     // If all vertex attr pointers are set to a non-null value, then set the
1539     // vertex attr type in the vertexType flag word, else clear the
1540     // vertex attr type
validateVertexAttrPointerType()1541     private void validateVertexAttrPointerType() {
1542         boolean allNonNull = true;
1543         boolean allNull = true;
1544 
1545         if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
1546             for (int i = 0; i < vertexAttrCount; i++) {
1547                 if (floatRefVertexAttrs[i] == null) {
1548                     allNonNull = false;
1549                 } else {
1550                     allNull = false;
1551                 }
1552             }
1553         } else {
1554             for (int i = 0; i < vertexAttrCount; i++) {
1555                 if (nioFloatBufferRefVertexAttrs[i] == null) {
1556                     allNonNull = false;
1557                 } else {
1558                     allNull = false;
1559                 }
1560             }
1561         }
1562 
1563         // Reset vertexAttrType if all references are null
1564         if (allNull) {
1565             vertexAttrType = 0;
1566         }
1567 
1568         // Copy vertexAttrType to vertexType if all references are non-null
1569         vertexType &= ~VATTR_DEFINED;
1570         if (allNonNull) {
1571             vertexType |= vertexAttrType;
1572         }
1573     }
1574 
doSetupMirrorVertexAttrPointer(int vertexAttrNum, int type)1575     private void doSetupMirrorVertexAttrPointer(int vertexAttrNum, int type) {
1576         switch (type) {
1577         case AF:
1578             vertexAttrType = AF;
1579             mirrorFloatRefVertexAttrs[vertexAttrNum] =
1580                 floatRefVertexAttrs[vertexAttrNum];
1581             break;
1582         default:
1583             break;
1584         }
1585     }
1586 
1587 
createGeometryArrayData(int vertexCount, int vertexFormat)1588     void createGeometryArrayData(int vertexCount, int vertexFormat) {
1589 	if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
1590 	    createGeometryArrayData(vertexCount, vertexFormat, 1,
1591 				    defaultTexCoordSetMap);
1592 	} else {
1593 	    createGeometryArrayData(vertexCount, vertexFormat, 0, null);
1594 	}
1595     }
1596 
createGeometryArrayData(int vertexCount, int vertexFormat, int texCoordSetCount, int[] texCoordSetMap)1597     void createGeometryArrayData(int vertexCount, int vertexFormat,
1598 				 int texCoordSetCount, int[] texCoordSetMap) {
1599 
1600 	createGeometryArrayData(vertexCount, vertexFormat,
1601 				texCoordSetCount, texCoordSetMap,
1602 				0, null);
1603     }
1604 
createGeometryArrayData(int vertexCount, int vertexFormat, int texCoordSetCount, int[] texCoordSetMap, int vertexAttrCount, int[] vertexAttrSizes)1605     void createGeometryArrayData(int vertexCount, int vertexFormat,
1606 				 int texCoordSetCount, int[] texCoordSetMap,
1607 				 int vertexAttrCount, int[] vertexAttrSizes) {
1608 	this.vertexFormat = vertexFormat;
1609 	this.vertexCount = vertexCount;
1610 	this.validVertexCount = vertexCount;
1611 
1612 	this.texCoordSetCount = texCoordSetCount;
1613 	if (texCoordSetMap == null) {
1614 	    this.texCoordSetMap = null;
1615 	}
1616 	else {
1617 	    this.texCoordSetMap = (int[])texCoordSetMap.clone();
1618 	}
1619 
1620         this.vertexAttrCount = vertexAttrCount;
1621 	if (vertexAttrSizes == null) {
1622 	    this.vertexAttrSizes = null;
1623 	}
1624 	else {
1625 	    this.vertexAttrSizes = (int[])vertexAttrSizes.clone();
1626 	}
1627 
1628         this.vertexAttrStride = this.vertexAttrStride();
1629 	this.stride = this.stride();
1630 
1631 	this.vertexAttrOffsets = this.vertexAttrOffsets();
1632 	this.texCoordSetMapOffset = this.texCoordSetMapOffset();
1633 	this.textureOffset = this.textureOffset();
1634 	this.colorOffset = this.colorOffset();
1635 	this.normalOffset = this.normalOffset();
1636 	this.coordinateOffset = this.coordinateOffset();
1637 
1638 	if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
1639 	    this.vertexData = new float[this.vertexCount * this.stride];
1640 	}
1641 	else { // By reference geometry
1642 	    this.vertexData = null;
1643             if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
1644                 this.mirrorRefTexCoords = new Object[texCoordSetCount];
1645                 this.refTexCoords = new Object[texCoordSetCount]; // keep J3DBufferImp object in nio buffer case
1646 		if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0 )
1647 		    this.refTexCoordsBuffer = new Object[texCoordSetCount]; // keep J3DBuffer object
1648 	    }
1649             if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
1650                 this.floatRefVertexAttrs = new float[vertexAttrCount][];
1651                 this.mirrorFloatRefVertexAttrs = new float[vertexAttrCount][];
1652 		if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
1653 		    this.vertexAttrsRefBuffer = new J3DBuffer[vertexAttrCount];
1654                     this.floatBufferRefVertexAttrs = new FloatBufferWrapper[vertexAttrCount];
1655                     this.nioFloatBufferRefVertexAttrs = new Object[vertexAttrCount];
1656                 }
1657 	    }
1658 	}
1659         if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
1660             this.initialTexCoordIndex = new int[texCoordSetCount];
1661         }
1662         if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
1663             this.initialVertexAttrIndex = new int[vertexAttrCount];
1664         }
1665 	noAlpha = ((vertexFormat & GeometryArray.WITH_ALPHA) == 0);
1666 	lastAlpha[0] = 1.0f;
1667 
1668     }
1669 
setVertexFormat(boolean useAlpha, boolean ignoreVC, Context ctx)1670     void setVertexFormat(boolean useAlpha, boolean ignoreVC, Context ctx) {
1671 	Pipeline.getPipeline().setVertexFormat(ctx,
1672                 this, vertexFormat, useAlpha, ignoreVC);
1673     }
1674 
disableGlobalAlpha(Context ctx, boolean useAlpha, boolean ignoreVC)1675     void disableGlobalAlpha(Context ctx, boolean useAlpha, boolean ignoreVC) {
1676 	// If global alpha was turned on, then disable it
1677 	Pipeline.getPipeline().disableGlobalAlpha(ctx,
1678                 this, vertexFormat, useAlpha, ignoreVC);
1679     }
1680 
1681 
updateAlphaInFloatRefColors(Canvas3D cv, int screen, float alpha)1682     float[] updateAlphaInFloatRefColors(Canvas3D cv, int screen, float alpha) {
1683 
1684 	//System.err.println("updateAlphaInFloatRefColors  screen = " + screen +
1685 	//		   " alpha " + alpha );
1686 
1687 	// no need to update alpha values if canvas supports global alpha
1688 	if (cv.supportGlobalAlpha()) {
1689 	    cv.setGlobalAlpha(cv.ctx, alpha);
1690 	    return mirrorFloatRefColors[0];
1691 	}
1692 
1693 	// update alpha only if vertex format includes alpha
1694 	if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0)
1695 	    return mirrorFloatRefColors[0];
1696 
1697 	// if alpha is smaller than EPSILON, set it to EPSILON, so that
1698 	// even if alpha is equal to 0, we will not completely lose
1699 	// the original alpha value
1700 	if (alpha <= EPSILON) {
1701 	    alpha = (float)EPSILON;
1702 	}
1703 
1704         assert lastAlpha != null;
1705         assert mirrorFloatRefColors != null;
1706         assert mirrorFloatRefColors.length == lastAlpha.length;
1707 
1708 	// Issue 113 - reallocate lastAlpha array if needed, but no need to
1709         // update the values here
1710 	if (lastAlpha.length <= screen) {
1711 	    float[] la = new float[screen + 1];
1712 	    for (int i = 0; i < lastAlpha.length; i++) {
1713 		la[i] = lastAlpha[i];
1714 	    }
1715 	    lastAlpha = la;
1716 	}
1717 
1718 	//System.err.println("updateAlphaInFloatRefColors screen is " + screen
1719 	//		     + " mirrorFloatRefColors.length " +
1720 	//		     mirrorFloatRefColors.length);
1721 
1722 	// allocate a copy of the color data for the screen if needed.
1723 	// this piece of code is only for multi-screens case
1724 	if (mirrorFloatRefColors.length <= screen) {
1725 	    float[][] cfData = new float[screen + 1][];
1726 
1727 	    for (int i = 0; i < mirrorFloatRefColors.length; i++) {
1728 		cfData[i] = mirrorFloatRefColors[i];
1729 	    }
1730 
1731             // Issue 113 - allocate entries for [oldSize..screen];
1732             // copy cfData[0] to cfData[oldsize..screen-1] and
1733             // lastAlpha[0] to lastAlpha[oldsize..screen-1].
1734             for (int i = mirrorFloatRefColors.length; i < screen+1; i++) {
1735                 cfData[i] = new float[4 * vertexCount];
1736                 System.arraycopy(cfData[0], 0, cfData[i], 0, 4 * vertexCount);
1737                 lastAlpha[i] = lastAlpha[0];
1738             }
1739 
1740             mirrorFloatRefColors = cfData;
1741 
1742             // Issue 113 - since we copied the data from screen 0, we don't need
1743             // to do any further special processing.
1744 	}
1745 
1746         assert lastAlpha[screen] >= 0.0;
1747 	/*
1748 	  System.err.println("updateAlphaInFloatRefColors ** : lastAlpha[screen] " +
1749 			     lastAlpha[screen]);
1750 
1751 	  System.err.println("((colorChanged & (1<<screen)) == 0) " +
1752 			     ((colorChanged & (1<<screen)) == 0));
1753 	*/
1754 
1755 	if ((colorChanged & (1<<screen)) == 0) {
1756 	    // color data is not modified
1757 	    if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
1758 		// and if alpha is the same as the last one,
1759 		// just return the data
1760 		//System.err.println("updateAlphaInFloatRefColors 0 : alpha is the same as the last one " + alpha);
1761 
1762 	        return mirrorFloatRefColors[screen];
1763 	    } else {
1764 
1765 		// if alpha is different, update the alpha values
1766 		//System.err.println("updateAlphaInFloatRefColors 1 : alpha is different, update the alpha values " + alpha);
1767 
1768 		float m = alpha / lastAlpha[screen];
1769 
1770 		float[] cdata = mirrorFloatRefColors[screen];
1771 
1772 		// We've to traverse the whole due to BugId : 4676483
1773 		for (int i = 0, j = 0; i < vertexCount; i++, j+=4) {
1774 	    	    cdata[j+3] = cdata[j+3] * m;
1775 		}
1776 	    }
1777 	} else {
1778 	    // color data is modified
1779 	    if (screen == 0) {
1780 
1781 		// just update alpha values since screen 0 data is
1782 		// already updated in setupMirrorColorPointer
1783 
1784 		//System.err.println("updateAlphaInFloatRefColors 2 : just update alpha = " + alpha);
1785 
1786 		float[] cdata = mirrorFloatRefColors[screen];
1787 
1788 
1789 		// This part is also incorrect due to BugId : 4676483
1790 		// But traversing the whole array doesn't help either, as there
1791 		// isn't a mechanism to indicate the the alpha component has
1792 		// not changed by user.
1793 		int j = initialColorIndex * 4;
1794 		for (int i = initialColorIndex; i < validVertexCount; i++, j+=4) {
1795 	    	    cdata[j+3] = cdata[j+3] * alpha;
1796 		}
1797 	    } else {
1798 		// update color values from screen 0 data
1799 		//System.err.println("updateAlphaInFloatRefColors 3 : update color values from screen 0 data " + alpha);
1800 
1801 		float m;
1802 
1803 		if ((colorChanged & 1) == 0) {
1804 		    // alpha is up to date in screen 0
1805 		    m = alpha / lastAlpha[0];
1806 		} else {
1807 		    m = alpha;
1808 		}
1809 
1810 		float[] sdata = mirrorFloatRefColors[0];
1811 		float[] cdata = mirrorFloatRefColors[screen];
1812 
1813 		int j = initialColorIndex * 4;
1814 		for (int i = initialColorIndex; i < validVertexCount; i++) {
1815 		    cdata[j] = sdata[j++];
1816 		    cdata[j] = sdata[j++];
1817 		    cdata[j] = sdata[j++];
1818 		    cdata[j] = sdata[j++] * m;
1819 		}
1820 	    }
1821 	}
1822 
1823 	lastAlpha[screen] = alpha;
1824 	colorChanged &= ~(1 << screen);
1825 	dirtyFlag |= COLOR_CHANGED;
1826 	return mirrorFloatRefColors[screen];
1827     }
1828 
1829 
updateAlphaInByteRefColors(Canvas3D cv, int screen, float alpha)1830     byte[] updateAlphaInByteRefColors(Canvas3D cv, int screen, float alpha) {
1831 
1832 	/*
1833 	  System.err.println("updateAlphaInByteRefColors  screen = " + screen +
1834 	  " alpha " + alpha );
1835 	*/
1836 
1837 	// no need to update alpha values if canvas supports global alpha
1838 
1839 	if (cv.supportGlobalAlpha()) {
1840 	    cv.setGlobalAlpha(cv.ctx, alpha);
1841 	    return mirrorUnsignedByteRefColors[0];
1842 	}
1843 
1844 	// update alpha only if vertex format includes alpha
1845 	if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0)
1846 	    return mirrorUnsignedByteRefColors[0];
1847 
1848 	// if alpha is smaller than EPSILON, set it to EPSILON, so that
1849 	// even if alpha is equal to 0, we will not completely lose
1850 	// the original alpha value
1851 	if (alpha <= EPSILON) {
1852 	    alpha = (float)EPSILON;
1853 	}
1854 
1855         assert lastAlpha != null;
1856         assert mirrorUnsignedByteRefColors != null;
1857         assert mirrorUnsignedByteRefColors.length == lastAlpha.length;
1858 
1859 	// Issue 113 - reallocate lastAlpha array if needed, but no need to
1860         // update the values here
1861 	if (lastAlpha.length <= screen) {
1862 	    float[] la = new float[screen + 1];
1863 	    for (int i = 0; i < lastAlpha.length; i++) {
1864 		la[i] = lastAlpha[i];
1865 	    }
1866 	    lastAlpha = la;
1867 	}
1868 
1869 	// allocate a copy of the color data for the screen if needed.
1870 	// this piece of code is only for multi-screens case
1871 	if (mirrorUnsignedByteRefColors.length <= screen) {
1872 	    byte[][] cbData = new byte[screen + 1][];
1873 	    for (int i = 0; i < mirrorUnsignedByteRefColors.length; i++) {
1874 		cbData[i] = mirrorUnsignedByteRefColors[i];
1875 	    }
1876 
1877             // Issue 113 - allocate entries for [oldSize..screen];
1878             // copy cbData[0] to cbData[oldsize..screen-1] and
1879             // lastAlpha[0] to lastAlpha[oldsize..screen-1].
1880             for (int i = mirrorUnsignedByteRefColors.length; i < screen+1; i++) {
1881                 cbData[i] = new byte[4 * vertexCount];
1882                 System.arraycopy(cbData[0], 0, cbData[i], 0, 4 * vertexCount);
1883                 lastAlpha[i] = lastAlpha[0];
1884             }
1885 
1886             mirrorUnsignedByteRefColors = cbData;
1887 
1888             // Issue 113 - since we copied the data from screen 0, we don't need
1889             // to do any further special processing.
1890 	}
1891 
1892         assert lastAlpha[screen] >= 0.0;
1893         /*
1894 	System.err.println("updateAlphaInByteRefColors ## : lastAlpha[screen] " +
1895 			   lastAlpha[screen]);
1896 
1897 	System.err.println("((colorChanged & (1<<screen)) == 0) " +
1898 			   ((colorChanged & (1<<screen)) == 0));
1899 	*/
1900 
1901         if ((colorChanged & (1<<screen)) == 0) {
1902             // color data is not modified
1903             if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
1904                 // and if alpha is the same as the last one,
1905                 // just return the data
1906 		//System.err.println("updateAlphaInByteRefColors 0 : alpha is the same as the last one " + alpha);
1907 
1908                 return mirrorUnsignedByteRefColors[screen];
1909             } else {
1910                 // if alpha is different, update the alpha values
1911 
1912 		//System.err.println("updateAlphaInByteRefColors 1 : alpha is different, update the alpha values " + alpha);
1913 
1914                 float m = alpha / lastAlpha[screen];
1915 
1916                 byte[] cdata = mirrorUnsignedByteRefColors[screen];
1917 
1918 		// We've to traverse the whole due to BugId : 4676483
1919 		for (int i = 0, j = 0; i < vertexCount; i++, j+=4) {
1920                     cdata[j+3] = (byte)( ((int)cdata[j+3] & 0xff) * m);
1921                 }
1922             }
1923         } else {
1924             // color data is modified
1925             if (screen == 0) {
1926 		//System.err.println("updateAlphaInByteRefColors 2 : just update alpha =" + alpha);
1927 
1928                 // just update alpha values since screen 0 data is
1929                 // already updated in setupMirrorColorPointer
1930 
1931                 byte[] cdata = mirrorUnsignedByteRefColors[screen];
1932 
1933 		// This part is also incorrect due to BugId : 4676483
1934 		// But traversing the whole array doesn't help either, as there
1935 		// isn't a mechanism to indicate the the alpha component has
1936 		// not changed by user.
1937 		int j = initialColorIndex * 4;
1938 		for (int i = initialColorIndex; i < validVertexCount; i++, j+=4) {
1939                     cdata[j+3] = (byte)(((int)cdata[j+3] & 0xff) * alpha);
1940                 }
1941             } else {
1942                 // update color values from screen 0 data
1943                 float m;
1944 
1945 		//System.err.println("updateAlphaInByteRefColors 3 : update color values from screen 0 data " + alpha);
1946 
1947                 if ((colorChanged & 1) == 0) {
1948                     // alpha is up to date in screen 0
1949                     m = alpha / lastAlpha[0];
1950                 } else {
1951                     m = alpha;
1952                 }
1953                 byte[] sdata = mirrorUnsignedByteRefColors[0];
1954                 byte[] cdata = mirrorUnsignedByteRefColors[screen];
1955 
1956 		int j = initialColorIndex * 4;
1957 		for (int i = initialColorIndex; i < validVertexCount; i++) {
1958 		    cdata[j] = sdata[j++];
1959 		    cdata[j] = sdata[j++];
1960 		    cdata[j] = sdata[j++];
1961 		    cdata[j] = (byte)(((int)sdata[j++]& 0xff) * m);
1962                 }
1963             }
1964         }
1965 
1966         lastAlpha[screen] = alpha;
1967         colorChanged &= ~(1 << screen);
1968 	dirtyFlag |= COLOR_CHANGED;
1969         return mirrorUnsignedByteRefColors[screen];
1970     }
1971 
1972 
updateAlphaInVertexData(Canvas3D cv, int screen, float alpha)1973     Object[] updateAlphaInVertexData(Canvas3D cv, int screen, float alpha) {
1974 
1975 	Object[] retVal = new Object[2];
1976 	retVal[0] = Boolean.FALSE;
1977 
1978 	// no need to update alpha values if canvas supports global alpha
1979 	if (cv.supportGlobalAlpha()) {
1980 	    cv.setGlobalAlpha(cv.ctx, alpha);
1981 	    retVal[1] = vertexData;
1982 	    return retVal;
1983 	}
1984 
1985 	// update alpha only if vertex format includes alpha
1986 	if ((vertexFormat & GeometryArray.COLOR) == 0) {
1987 	    retVal[1] = vertexData;
1988 	    return retVal;
1989 	}
1990 
1991 	// if alpha is smaller than EPSILON, set it to EPSILON, so that
1992 	// even if alpha is equal to 0, we will not completely lose
1993 	// the original alpha value
1994 	if (alpha <= EPSILON) {
1995 	    alpha = (float)EPSILON;
1996 	}
1997 	retVal[0] = Boolean.TRUE;
1998 
1999         assert lastAlpha != null;
2000         assert mvertexData == null || mvertexData.length == lastAlpha.length;
2001 
2002 	// Issue 113 - reallocate lastAlpha array if needed, but no need to
2003         // update the values here
2004 	if (lastAlpha.length <= screen) {
2005 	    float[] la = new float[screen + 1];
2006 	    for (int i = 0; i < lastAlpha.length; i++) {
2007 		la[i] = lastAlpha[i];
2008 	    }
2009 	    lastAlpha = la;
2010 	}
2011 
2012 	// allocate a copy of the vertex data for the screen if needed.
2013 	// Note that a copy operation only happens in the multi-screens case.
2014         // We always use the existing vertexData for screen 0.
2015 	if (mvertexData == null || mvertexData.length <= screen) {
2016 
2017 	    float[][] cfData = new float[screen + 1][];
2018             int oldSize = 1;
2019 
2020 	    if (mvertexData != null) {
2021                 oldSize = mvertexData.length;
2022 	        for (int i = 0; i < mvertexData.length; i++) {
2023 		    cfData[i] = mvertexData[i];
2024 		}
2025 	    }
2026 
2027 	    if (cfData[0] == null)  {
2028 		cfData[0] = vertexData;
2029 	    }
2030 
2031             // Issue 113 - allocate entries for [oldSize..screen];
2032             // copy cfData[0] to cfData[oldsize..screen-1] and
2033             // lastAlpha[0] to lastAlpha[oldsize..screen-1].
2034             if (screen > 0) {
2035                 for (int i = oldSize; i < screen+1; i++) {
2036                     cfData[i] = new float[stride * vertexCount];
2037                     System.arraycopy(cfData[0], 0, cfData[i], 0,
2038                             stride * vertexCount);
2039                     lastAlpha[i] = lastAlpha[0];
2040                 }
2041             }
2042 
2043             mvertexData = cfData;
2044 
2045             // Issue 113 - since we copied the data from screen 0, we don't need
2046             // to do any further special processing.
2047 	}
2048 
2049         assert lastAlpha[screen] >= 0.0;
2050 
2051 	if ((colorChanged & (1<<screen)) == 0) {
2052 	    // color data is not modified
2053 	    if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
2054 		// and if alpha is the same as the last one,
2055 		// just return the data
2056 		retVal[1] = mvertexData[screen];
2057 	        return retVal;
2058 	    } else {
2059 		// if alpha is different, update the alpha values
2060 		float m = alpha / lastAlpha[screen];
2061 
2062 		float[] cdata = mvertexData[screen];
2063 		for (int i = 0, j = colorOffset; i < vertexCount;
2064 					i++, j+=stride) {
2065 	    	    cdata[j+3] *= m;
2066 		}
2067 	    }
2068 	} else {
2069 	    // color data is modified
2070 	    if (screen == 0) {
2071 		// just update alpha values since screen 0 data is
2072 		// already updated in setupMirrorColorPointer
2073 
2074 		float[] cdata = mvertexData[screen];
2075 		double m = alpha / lastAlpha[0];
2076 
2077 		for (int i = 0, j = colorOffset; i < vertexCount;
2078 					i++, j+=stride) {
2079 	    	    cdata[j+3] *= m;
2080 		}
2081 	    } else {
2082 		// update color values from screen 0 data
2083 
2084 		float m = alpha / lastAlpha[0];
2085 		float[] sdata = mvertexData[0];
2086 		float[] cdata = mvertexData[screen];
2087 
2088 		for (int i = 0, j = colorOffset; i < vertexCount;
2089 					i++, j+=stride) {
2090 		    System.arraycopy(sdata, j, cdata, j, 3);
2091 		    cdata[j+3] = sdata[j+3] * m;
2092 		}
2093 	    }
2094 	}
2095 
2096 	lastAlpha[screen] = alpha;
2097 	colorChanged &= ~(1 << screen);
2098 	dirtyFlag |= COLOR_CHANGED;
2099 	retVal[1] = mvertexData[screen];
2100 	return retVal;
2101     }
2102 
updateAlphaInInterLeavedData(Canvas3D cv, int screen, float alpha)2103     Object[] updateAlphaInInterLeavedData(Canvas3D cv, int screen, float alpha) {
2104 
2105 	Object[] retVal = new Object[2];
2106 	retVal[0] = Boolean.FALSE;
2107 
2108 	// no need to update alpha values if canvas supports global alpha
2109 	if (cv.supportGlobalAlpha()) {
2110 	    cv.setGlobalAlpha(cv.ctx, alpha);
2111 	    retVal[1] = null;
2112 	    return retVal;
2113 	}
2114 
2115 	// update alpha only if vertex format includes alpha
2116 	if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0) {
2117 	    retVal[1] = mirrorInterleavedColorPointer[0];
2118 	    return retVal;
2119 	}
2120         int coffset = initialColorIndex << 2; // Each color is 4 floats
2121 
2122 	// if alpha is smaller than EPSILON, set it to EPSILON, so that
2123 	// even if alpha is equal to 0, we will not completely lose
2124 	// the original alpha value
2125 	if (alpha <= EPSILON) {
2126 	    alpha = (float)EPSILON;
2127 	}
2128 	retVal[0] = Boolean.TRUE;
2129 
2130         assert lastAlpha != null;
2131         assert mirrorInterleavedColorPointer != null;
2132         assert mirrorInterleavedColorPointer.length == lastAlpha.length;
2133 
2134 	// Issue 113 - reallocate lastAlpha array if needed, but no need to
2135         // update the values here
2136 	if (lastAlpha.length <= screen) {
2137 	    float[] la = new float[screen + 1];
2138 	    for (int i = 0; i < lastAlpha.length; i++) {
2139 		la[i] = lastAlpha[i];
2140 	    }
2141 	    lastAlpha = la;
2142 	}
2143 
2144 	// allocate a copy of the vertex data for the screen if needed.
2145 	// this piece of code is only for multi-screens case
2146 	if (mirrorInterleavedColorPointer.length <= screen) {
2147 
2148 	    float[][] cfData = new float[screen + 1][];
2149 
2150 	    for (int i = 0; i < mirrorInterleavedColorPointer.length; i++) {
2151 		cfData[i] = mirrorInterleavedColorPointer[i];
2152 	    }
2153 
2154             // Issue 113 - allocate entries for [oldSize..screen];
2155             // copy cfData[0] to cfData[oldsize..screen-1] and
2156             // lastAlpha[0] to lastAlpha[oldsize..screen-1].
2157             for (int i = mirrorInterleavedColorPointer.length; i < screen+1; i++) {
2158                 cfData[i] = new float[4 * vertexCount];
2159                 System.arraycopy(cfData[0], 0, cfData[i], 0, 4 * vertexCount);
2160                 lastAlpha[i] = lastAlpha[0];
2161             }
2162 
2163 	    mirrorInterleavedColorPointer = cfData;
2164 
2165             // Issue 113 - since we copied the data from screen 0, we don't need
2166             // to do any further special processing.
2167 	}
2168 
2169         assert lastAlpha[screen] >= 0.0;
2170 
2171         if ((colorChanged & (1<<screen)) == 0) {
2172 	    // color data is not modified
2173 	    if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
2174 		// and if alpha is the same as the last one,
2175 		// just return the data
2176 		retVal[1] = mirrorInterleavedColorPointer[screen];
2177 	        return retVal;
2178 	    } else {
2179 
2180 		// if alpha is different, update the alpha values
2181 
2182 		float m = alpha / lastAlpha[screen];
2183 
2184 		float[] cdata = mirrorInterleavedColorPointer[screen];
2185 
2186 		coffset = initialColorIndex << 2;
2187 		for (int i = coffset; i < coffset + (vertexCount << 2); i+=4) {
2188 	    	    cdata[i+3] = cdata[i+3] * m;
2189 		}
2190 	    }
2191 	} else {
2192 	    // color data is modified
2193 	    if (screen == 0) {
2194 
2195 		// just update alpha values since screen 0 data is
2196 		// already updated in setupMirrorInterleavedColorPointer
2197 
2198 		float[] cdata = mirrorInterleavedColorPointer[screen];
2199 
2200 		for (int i = coffset; i < coffset + (vertexCount << 2); i+=4) {
2201 	    	    cdata[i+3] = cdata[i+3] * alpha;
2202 		}
2203 	    } else {
2204 		// update color values from screen 0 data
2205 
2206 		float m;
2207 
2208 		if ((colorChanged & 1) == 0) {
2209 		    // alpha is up to date in screen 0
2210 		    m = alpha / lastAlpha[0];
2211 		} else {
2212 		    m = alpha;
2213 		}
2214 
2215 		float[] sdata = mirrorInterleavedColorPointer[0];
2216 		float[] cdata = mirrorInterleavedColorPointer[screen];
2217 
2218 		for (int i = coffset; i < coffset + (vertexCount << 2);) {
2219 		    // System.arraycopy(sdata, i, cdata, i, 3);
2220 		    cdata[i] = sdata[i++];
2221 		    cdata[i] = sdata[i++];
2222 		    cdata[i] = sdata[i++];
2223 		    cdata[i] = sdata[i++] * m;
2224 		}
2225 	    }
2226 	}
2227 
2228 	lastAlpha[screen] = alpha;
2229 	colorChanged &= ~(1 << screen);
2230 	dirtyFlag |= COLOR_CHANGED;
2231 	retVal[1] = mirrorInterleavedColorPointer[screen];
2232 	return retVal;
2233     }
2234 
2235 
2236     // pass < 0  implies underlying library supports multiTexture, so
2237     // 		 use the multiTexture extension to send all texture units
2238     //		 data in one pass
2239     // pass >= 0 implies one pass for one texture unit state
2240 
execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, int screen, boolean ignoreVertexColors)2241     void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
2242 		 boolean updateAlpha, float alpha,
2243 		 int screen,
2244                  boolean ignoreVertexColors) {
2245 
2246 	int cdirty;
2247 	boolean useAlpha = false;
2248 	Object[] retVal;
2249 
2250         // Check for by-copy case
2251 	if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
2252             float[] vdata;
2253 
2254 	    synchronized (this) {
2255 		cdirty = dirtyFlag;
2256 		if (updateAlpha && !ignoreVertexColors) {
2257 		    // update the alpha values
2258 		    retVal = updateAlphaInVertexData(cv, screen, alpha);
2259 		    useAlpha = (retVal[0] == Boolean.TRUE);
2260 		    vdata = (float[])retVal[1];
2261 
2262 		    // D3D only
2263 		    if (alpha != lastScreenAlpha) {
2264 			// handle multiple screen case
2265 			lastScreenAlpha = alpha;
2266 			cdirty |= COLOR_CHANGED;
2267 		    }
2268 		} else {
2269 		    vdata = vertexData;
2270 		    // if transparency switch between on/off
2271 		    if (lastScreenAlpha != -1) {
2272 			lastScreenAlpha = -1;
2273 			cdirty |= COLOR_CHANGED;
2274 		    }
2275 		}
2276 		// geomLock is get in MasterControl when
2277 		// RenderBin render the geometry. So it is safe
2278 		// just to set the dirty flag here
2279 		dirtyFlag = 0;
2280 	    }
2281 
2282 	    Pipeline.getPipeline().execute(cv.ctx,
2283                     this, geoType, isNonUniformScale,
2284 		    useAlpha,
2285 		    ignoreVertexColors,
2286 		    initialVertexIndex,
2287 		     validVertexCount,
2288 		    ((vertexFormat & GeometryArray.COLOR) != 0)?(vertexFormat|GeometryArray.COLOR_4):vertexFormat,
2289                     texCoordSetCount, texCoordSetMap,
2290                     (texCoordSetMap == null) ? 0 : texCoordSetMap.length,
2291                     texCoordSetMapOffset,
2292 		    cv.numActiveTexUnit,
2293                     vertexAttrCount, vertexAttrSizes,
2294                     vdata, null,
2295                     cdirty);
2296 	}
2297 
2298 	//By reference with java array
2299 	else if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
2300 	    // interleaved data
2301 	    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
2302 		if(interLeavedVertexData == null)
2303 		    return;
2304 
2305 		float[] cdata = null;
2306 
2307 		synchronized (this) {
2308 		    cdirty = dirtyFlag;
2309 		    if (updateAlpha && !ignoreVertexColors) {
2310 			// update the alpha values
2311 			retVal = updateAlphaInInterLeavedData(cv, screen, alpha);
2312 			useAlpha = (retVal[0] == Boolean.TRUE);
2313 			cdata = (float[])retVal[1];
2314 			if (alpha != lastScreenAlpha) {
2315 			    lastScreenAlpha = alpha;
2316 			    cdirty |= COLOR_CHANGED;
2317 			}
2318 		    } else {
2319 			// if transparency switch between on/off
2320 			if (lastScreenAlpha != -1) {
2321 			    lastScreenAlpha = -1;
2322 			    cdirty |= COLOR_CHANGED;
2323 			}
2324 		    }
2325 		    dirtyFlag = 0;
2326 		}
2327 
2328 		Pipeline.getPipeline().execute(cv.ctx,
2329                         this, geoType, isNonUniformScale,
2330 			useAlpha,
2331 			ignoreVertexColors,
2332 			initialVertexIndex,
2333 			validVertexCount,
2334 			vertexFormat,
2335 			texCoordSetCount, texCoordSetMap,
2336 			(texCoordSetMap == null) ? 0 : texCoordSetMap.length,
2337 			texCoordSetMapOffset,
2338 			cv.numActiveTexUnit,
2339                         vertexAttrCount, vertexAttrSizes,
2340                         interLeavedVertexData, cdata,
2341 			cdirty);
2342 
2343 	    } // end of interleaved case
2344 
2345 	    // non interleaved data
2346 	    else {
2347 
2348 		// Check if a vertexformat is set, but the array is null
2349 		// if yes, don't draw anything
2350 		if ((vertexType == 0) ||
2351 		    ((vertexType & VERTEX_DEFINED) == 0) ||
2352 		    (((vertexFormat & GeometryArray.COLOR) != 0) &&
2353 		     (vertexType & COLOR_DEFINED) == 0) ||
2354 		    (((vertexFormat & GeometryArray.NORMALS) != 0) &&
2355 		     (vertexType & NORMAL_DEFINED) == 0) ||
2356 		    (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) &&
2357 		     (vertexType & VATTR_DEFINED) == 0) ||
2358 		    (((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) &&
2359 		     (vertexType & TEXCOORD_DEFINED) == 0)) {
2360 		    return;
2361 		} else {
2362 		    byte[] cbdata = null;
2363 		    float[] cfdata = null;
2364 
2365 		    if ((vertexType & (CF | C3F | C4F )) != 0) {
2366 
2367 			synchronized (this) {
2368 			    cdirty = dirtyFlag;
2369 			    if (updateAlpha && !ignoreVertexColors) {
2370 				cfdata = updateAlphaInFloatRefColors(cv, screen, alpha);
2371 				if (alpha != lastScreenAlpha) {
2372 				    lastScreenAlpha = alpha;
2373 				    cdirty |= COLOR_CHANGED;
2374 				}
2375 			    } else {
2376 				cfdata = mirrorFloatRefColors[0];
2377 				// if transparency switch between on/off
2378 				if (lastScreenAlpha != -1) {
2379 				    lastScreenAlpha = -1;
2380 				    cdirty |= COLOR_CHANGED;
2381 				}
2382 
2383 			    }
2384 			    dirtyFlag = 0;
2385 			}
2386 		    } // end of color in float format
2387 		    else if ((vertexType & (CUB| C3UB | C4UB)) != 0) {
2388 			synchronized (this) {
2389 			    cdirty = dirtyFlag;
2390 			    if (updateAlpha && !ignoreVertexColors) {
2391 				cbdata = updateAlphaInByteRefColors(cv, screen, alpha);
2392 				if (alpha != lastScreenAlpha) {
2393 				    lastScreenAlpha = alpha;
2394 				    cdirty |= COLOR_CHANGED;
2395 				}
2396 			    } else {
2397 				cbdata = mirrorUnsignedByteRefColors[0];
2398 				// if transparency switch between on/off
2399 				if (lastScreenAlpha != -1) {
2400 				    lastScreenAlpha = -1;
2401 				    cdirty |= COLOR_CHANGED;
2402 				}
2403 			    }
2404 			    dirtyFlag = 0;
2405 			}
2406 		    } // end of color in byte format
2407 		    else {
2408 			cdirty = dirtyFlag;
2409 		    }
2410 		    // setup vdefined to passed to native code
2411 		    int vdefined = 0;
2412 		    if((vertexType & (PF | P3F)) != 0)
2413 			vdefined |= COORD_FLOAT;
2414 		    if((vertexType & (PD | P3D)) != 0)
2415 			vdefined |= COORD_DOUBLE;
2416 		    if((vertexType & (CF | C3F | C4F)) != 0)
2417 			vdefined |= COLOR_FLOAT;
2418 		    if((vertexType & (CUB| C3UB | C4UB)) != 0)
2419 			vdefined |= COLOR_BYTE;
2420 		    if((vertexType & NORMAL_DEFINED) != 0)
2421 			vdefined |= NORMAL_FLOAT;
2422 		    if((vertexType & VATTR_DEFINED) != 0)
2423 			vdefined |= VATTR_FLOAT;
2424 		    if((vertexType & TEXCOORD_DEFINED) != 0)
2425 			vdefined |= TEXCOORD_FLOAT;
2426 
2427                     Pipeline.getPipeline().executeVA(cv.ctx,
2428                             this, geoType, isNonUniformScale,
2429                             ignoreVertexColors,
2430                             validVertexCount,
2431                             (vertexFormat | c4fAllocated),
2432                             vdefined,
2433                             initialCoordIndex,
2434                             mirrorFloatRefCoords, mirrorDoubleRefCoords,
2435                             initialColorIndex, cfdata, cbdata,
2436                             initialNormalIndex, mirrorFloatRefNormals,
2437                             vertexAttrCount, vertexAttrSizes,
2438                             initialVertexAttrIndex, mirrorFloatRefVertexAttrs,
2439                             ((texCoordSetMap == null) ? 0:texCoordSetMap.length),
2440                             texCoordSetMap,
2441                             cv.numActiveTexUnit,
2442                             initialTexCoordIndex,texCoordStride,
2443                             mirrorRefTexCoords, cdirty);
2444 		}// end of all vertex data being set
2445 	    }// end of non interleaved case
2446 	}// end of by reference with java array
2447 
2448 	//By reference with nio buffer
2449 	else  {
2450 	    // interleaved data
2451 	    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
2452 
2453 		if ( interleavedFloatBufferImpl == null)
2454 		    return;
2455 
2456 		float[] cdata = null;
2457 		synchronized (this) {
2458 		    cdirty = dirtyFlag;
2459 		    if (updateAlpha && !ignoreVertexColors) {
2460 			// update the alpha values
2461 			// XXXX: to handle alpha case
2462 			retVal = updateAlphaInInterLeavedData(cv, screen, alpha);
2463 			useAlpha = (retVal[0] == Boolean.TRUE);
2464 			cdata = (float[])retVal[1];
2465 
2466 			if (alpha != lastScreenAlpha) {
2467 			    lastScreenAlpha = alpha;
2468 			    cdirty |= COLOR_CHANGED;
2469 			}
2470 		    } else {
2471 			// XXXX: to handle alpha case
2472 			cdata = null;
2473 			// if transparency switch between on/off
2474 			if (lastScreenAlpha != -1) {
2475 			    lastScreenAlpha = -1;
2476 			    cdirty |= COLOR_CHANGED;
2477 			}
2478 		    }
2479 		    dirtyFlag = 0;
2480 		}
2481 
2482                 Pipeline.getPipeline().executeInterleavedBuffer(cv.ctx,
2483                         this, geoType, isNonUniformScale,
2484                         useAlpha,
2485                         ignoreVertexColors,
2486                         initialVertexIndex,
2487                         validVertexCount,
2488                         vertexFormat,
2489                         texCoordSetCount, texCoordSetMap,
2490                         (texCoordSetMap == null) ? 0 : texCoordSetMap.length,
2491                         texCoordSetMapOffset,
2492                         cv.numActiveTexUnit,
2493                         interleavedFloatBufferImpl.getBufferAsObject(), cdata,
2494                         cdirty);
2495 
2496 	    } // end of interleaved case
2497 
2498 	    // non interleaved data
2499 	    else {
2500 
2501 		// Check if a vertexformat is set, but the array is null
2502 		// if yes, don't draw anything
2503 		if ((vertexType == 0) ||
2504 		    ((vertexType & VERTEX_DEFINED) == 0) ||
2505 		    (((vertexFormat & GeometryArray.COLOR) != 0) &&
2506 		     (vertexType & COLOR_DEFINED) == 0) ||
2507 		    (((vertexFormat & GeometryArray.NORMALS) != 0) &&
2508 		     (vertexType & NORMAL_DEFINED) == 0) ||
2509 		    (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) &&
2510 		     (vertexType & VATTR_DEFINED) == 0) ||
2511 		    (((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) &&
2512 		     (vertexType & TEXCOORD_DEFINED) == 0)) {
2513 		    return;
2514 		} else {
2515 		    byte[] cbdata = null;
2516 		    float[] cfdata = null;
2517 
2518 		    if ((vertexType & CF ) != 0) {
2519 			synchronized (this) {
2520 			    cdirty = dirtyFlag;
2521 			    if (updateAlpha && !ignoreVertexColors) {
2522 				cfdata = updateAlphaInFloatRefColors(cv,
2523 								     screen, alpha);
2524 				if (alpha != lastScreenAlpha) {
2525 				    lastScreenAlpha = alpha;
2526 				    cdirty |= COLOR_CHANGED;
2527 				}
2528 			    } else {
2529 				// XXXX: handle transparency case
2530 				//cfdata = null;
2531 				cfdata = mirrorFloatRefColors[0];
2532 				// if transparency switch between on/off
2533 				if (lastScreenAlpha != -1) {
2534 				    lastScreenAlpha = -1;
2535 				    cdirty |= COLOR_CHANGED;
2536 				}
2537 
2538 			    }
2539 			    dirtyFlag = 0;
2540 			}
2541 		    } // end of color in float format
2542 		    else if ((vertexType & CUB) != 0) {
2543 			synchronized (this) {
2544 			    cdirty = dirtyFlag;
2545 			    if (updateAlpha && !ignoreVertexColors) {
2546 				cbdata = updateAlphaInByteRefColors(
2547 								    cv, screen, alpha);
2548 				if (alpha != lastScreenAlpha) {
2549 				    lastScreenAlpha = alpha;
2550 				    cdirty |= COLOR_CHANGED;
2551 				}
2552 			    } else {
2553 				// XXXX: handle transparency case
2554 				//cbdata = null;
2555 				cbdata = mirrorUnsignedByteRefColors[0];
2556 				// if transparency switch between on/off
2557 				if (lastScreenAlpha != -1) {
2558 				    lastScreenAlpha = -1;
2559 				    cdirty |= COLOR_CHANGED;
2560 				}
2561 			    }
2562 			    dirtyFlag = 0;
2563 			}
2564 		    } // end of color in byte format
2565 		    else {
2566 			cdirty = dirtyFlag;
2567 		    }
2568 
2569 		    Object vcoord = null, cdataBuffer=null, normal=null;
2570 
2571 		    int vdefined = 0;
2572 		    if((vertexType & PF)  != 0) {
2573 			vdefined |= COORD_FLOAT;
2574 			vcoord = floatBufferRefCoords.getBufferAsObject();
2575 		    } else if((vertexType & PD ) != 0) {
2576 			vdefined |= COORD_DOUBLE;
2577 			vcoord = doubleBufferRefCoords.getBufferAsObject();
2578 		    }
2579 
2580 		    if((vertexType & CF ) != 0) {
2581 			vdefined |= COLOR_FLOAT;
2582 			cdataBuffer = floatBufferRefColors.getBufferAsObject();
2583 		    } else if((vertexType & CUB) != 0) {
2584 			vdefined |= COLOR_BYTE;
2585 			cdataBuffer = byteBufferRefColors.getBufferAsObject();
2586 		    }
2587 
2588 		    if((vertexType & NORMAL_DEFINED) != 0) {
2589 			vdefined |= NORMAL_FLOAT;
2590 			normal = floatBufferRefNormals.getBufferAsObject();
2591                     }
2592 
2593                     if ((vertexType & VATTR_DEFINED) != 0) {
2594                         vdefined |= VATTR_FLOAT;
2595                     }
2596 
2597                     if((vertexType & TEXCOORD_DEFINED) != 0)
2598 		       vdefined |= TEXCOORD_FLOAT;
2599 
2600                     Pipeline.getPipeline().executeVABuffer(cv.ctx,
2601                             this, geoType, isNonUniformScale,
2602                             ignoreVertexColors,
2603                             validVertexCount,
2604                             (vertexFormat | c4fAllocated),
2605                             vdefined,
2606                             initialCoordIndex,
2607                             vcoord,
2608                             initialColorIndex,
2609                             cdataBuffer,
2610                             cfdata, cbdata,
2611                             initialNormalIndex,
2612                             normal,
2613                             vertexAttrCount, vertexAttrSizes,
2614                             initialVertexAttrIndex,
2615                             nioFloatBufferRefVertexAttrs,
2616                             ((texCoordSetMap == null) ? 0:texCoordSetMap.length),
2617                             texCoordSetMap,
2618                             cv.numActiveTexUnit,
2619                             initialTexCoordIndex,texCoordStride,
2620                             refTexCoords, cdirty);
2621 		}// end of all vertex data being set
2622 	    }// end of non interleaved case
2623 	}// end of by reference with nio-buffer case
2624     }
2625 
buildGA(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, boolean ignoreVertexColors, Transform3D xform, Transform3D nxform)2626     void buildGA(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
2627 		 boolean updateAlpha, float alpha, boolean ignoreVertexColors,
2628 		 Transform3D xform, Transform3D nxform) {
2629 
2630         float[] vdata = null;
2631 
2632         // NIO buffers are no longer supported in display lists
2633         assert (vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0;
2634 
2635 	if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
2636 	    vdata = vertexData;
2637 	}
2638 	else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0 &&
2639 		 ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0)) {
2640 	    vdata = interLeavedVertexData;
2641 	}
2642 	if (vdata != null) {
2643 	    /*
2644 	     System.err.println("calling native buildGA()");
2645 	     System.err.println("geoType = "+geoType+" initialVertexIndex = "+initialVertexIndex+" validVertexCount = "+validVertexCount+" vertexFormat = "+vertexFormat+"  vertexData = "+vertexData);
2646 	     */
2647 	    Pipeline.getPipeline().buildGA(cv.ctx,
2648                     this, geoType, isNonUniformScale,
2649 		    updateAlpha, alpha, ignoreVertexColors,
2650 		    initialVertexIndex,
2651 		    validVertexCount, vertexFormat,
2652 		    texCoordSetCount, texCoordSetMap,
2653 		    (texCoordSetMap == null) ? 0 : texCoordSetMap.length,
2654 		    texCoordSetMapOffset,
2655                     vertexAttrCount, vertexAttrSizes,
2656                     (xform == null) ? null : xform.mat,
2657 		    (nxform == null) ? null : nxform.mat,
2658 		    vdata);
2659 	}
2660 	else {
2661             // Check if a vertexformat is set, but the array is null
2662             // if yes, don't draw anything
2663             if ((vertexType == 0) ||
2664 		((vertexType & VERTEX_DEFINED) == 0) ||
2665 		(((vertexFormat & GeometryArray.COLOR) != 0) &&
2666 		 (vertexType & COLOR_DEFINED) == 0) ||
2667 		(((vertexFormat & GeometryArray.NORMALS) != 0) &&
2668 		 (vertexType & NORMAL_DEFINED) == 0) ||
2669 		(((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) &&
2670 		 (vertexType & VATTR_DEFINED) == 0) ||
2671 		(((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) &&
2672 		 (vertexType & TEXCOORD_DEFINED) == 0)) {
2673 
2674                 return;
2675             }
2676 
2677             // Either non-interleaved, by-ref or nio buffer
2678 	    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
2679                 // Java array case
2680 		    // setup vdefined to passed to native code
2681 		    int vdefined = 0;
2682 		    if((vertexType & (PF | P3F)) != 0)
2683 			vdefined |= COORD_FLOAT;
2684 		    if((vertexType & (PD | P3D)) != 0)
2685 			vdefined |= COORD_DOUBLE;
2686 		    if((vertexType & (CF | C3F | C4F)) != 0)
2687 			vdefined |= COLOR_FLOAT;
2688 		    if((vertexType & (CUB| C3UB | C4UB)) != 0)
2689 			vdefined |= COLOR_BYTE;
2690 		    if((vertexType & NORMAL_DEFINED) != 0)
2691 			vdefined |= NORMAL_FLOAT;
2692 		    if((vertexType & VATTR_DEFINED) != 0)
2693 			vdefined |= VATTR_FLOAT;
2694 		    if((vertexType & TEXCOORD_DEFINED) != 0)
2695 			vdefined |= TEXCOORD_FLOAT;
2696 
2697 		    Pipeline.getPipeline().buildGAForByRef(cv.ctx,
2698                             this, geoType, isNonUniformScale,
2699 			    updateAlpha, alpha,
2700 			    ignoreVertexColors,
2701 			    validVertexCount,
2702 			    vertexFormat,
2703 			    vdefined,
2704 			    initialCoordIndex,
2705 			    mirrorFloatRefCoords, mirrorDoubleRefCoords,
2706 			    initialColorIndex, mirrorFloatRefColors[0], mirrorUnsignedByteRefColors[0],
2707 			    initialNormalIndex, mirrorFloatRefNormals,
2708 			    vertexAttrCount, vertexAttrSizes,
2709                             initialVertexAttrIndex, mirrorFloatRefVertexAttrs,
2710 			    ((texCoordSetMap == null) ? 0:texCoordSetMap.length),
2711 			    texCoordSetMap,
2712 			    initialTexCoordIndex,texCoordStride,
2713 			    mirrorRefTexCoords,
2714 			    (xform == null) ? null : xform.mat,
2715 			    (nxform == null) ? null : nxform.mat);
2716 	    }
2717             /*
2718             // NOTE: NIO buffers are no longer supported in display lists.
2719             // This was never enabled by default anyway (only when the
2720             // optimizeForSpace property was set to false), so it wasn't
2721             // well-tested. If future support is desired, we will need to
2722             // add vertex attributes to buildGAForBuffer. There are no plans
2723             // to ever do this.
2724 	    else {
2725                 // NIO Buffer case
2726                 Object vcoord = null, cdataBuffer=null, normal=null;
2727 
2728                 int vdefined = 0;
2729                 if((vertexType & PF)  != 0) {
2730                     vdefined |= COORD_FLOAT;
2731                     vcoord = floatBufferRefCoords.getBufferAsObject();
2732                 } else if((vertexType & PD ) != 0) {
2733                     vdefined |= COORD_DOUBLE;
2734                     vcoord = doubleBufferRefCoords.getBufferAsObject();
2735                 }
2736 
2737                 if((vertexType & CF ) != 0) {
2738                     vdefined |= COLOR_FLOAT;
2739                     cdataBuffer = floatBufferRefColors.getBufferAsObject();
2740                 } else if((vertexType & CUB) != 0) {
2741                     vdefined |= COLOR_BYTE;
2742                     cdataBuffer = byteBufferRefColors.getBufferAsObject();
2743                 }
2744 
2745                 if((vertexType & NORMAL_DEFINED) != 0) {
2746                     vdefined |= NORMAL_FLOAT;
2747                     normal = floatBufferRefNormals.getBufferAsObject();
2748                 }
2749 
2750                 if((vertexType & TEXCOORD_DEFINED) != 0)
2751                     vdefined |= TEXCOORD_FLOAT;
2752                 // NOTE : need to add vertex attrs
2753                 Pipeline.getPipeline().buildGAForBuffer(cv.ctx,
2754                         this, geoType, isNonUniformScale,
2755                         updateAlpha, alpha,
2756                         ignoreVertexColors,
2757                         validVertexCount,
2758                         vertexFormat,
2759                         vdefined,
2760                         initialCoordIndex,
2761                         vcoord,
2762                         initialColorIndex,cdataBuffer,
2763                         initialNormalIndex, normal,
2764                         ((texCoordSetMap == null) ? 0:texCoordSetMap.length),
2765                         texCoordSetMap,
2766                         initialTexCoordIndex,texCoordStride,
2767                         refTexCoords,
2768                         (xform == null) ? null : xform.mat,
2769                         (nxform == null) ? null : nxform.mat);
2770 	    }
2771             */
2772 
2773 	}
2774 
2775     }
2776 
unIndexify(IndexedGeometryArrayRetained src)2777     void unIndexify(IndexedGeometryArrayRetained src) {
2778 	if ((src.vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
2779 	    unIndexifyJavaArray(src);
2780 	}
2781 	else {
2782 	    unIndexifyNIOBuffer(src);
2783 	}
2784     }
2785 
unIndexifyJavaArray(IndexedGeometryArrayRetained src)2786     private void unIndexifyJavaArray(IndexedGeometryArrayRetained src) {
2787 //        System.err.println("unIndexifyJavaArray");
2788 
2789         int vOffset = 0, srcOffset, tOffset = 0;
2790         int index, colorStride = 0;
2791 	float[] vdata = null;
2792         int i;
2793 	int start, end;
2794 	start = src.initialIndexIndex;
2795 	end = src.initialIndexIndex + src.validIndexCount;
2796 	// If its either "normal" data or interleaved data then ..
2797 	if (((src.vertexFormat & GeometryArray.BY_REFERENCE) == 0) ||
2798 	    ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
2799 
2800 	    if ((src.vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
2801 		vdata = src.vertexData;
2802 		if ((src.vertexFormat & GeometryArray.COLOR) != 0)
2803 		    colorStride = 4;
2804 	    }
2805 	    else if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
2806 		vdata = src.interLeavedVertexData;
2807 		if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
2808 		    colorStride = 4;
2809 		else if ((src.vertexFormat & GeometryArray.COLOR) != 0)
2810 		    colorStride = 3;
2811 	    }
2812 
2813 	    //	    System.err.println("===> start = "+start+" end = "+end);
2814 	    for (index= start; index < end; index++) {
2815 		if ((vertexFormat & GeometryArray.NORMALS) != 0){
2816 		    System.arraycopy(vdata,
2817 			src.indexNormal[index]*src.stride + src.normalOffset,
2818 			vertexData, vOffset + normalOffset, 3);
2819 		}
2820 		if (colorStride == 4){
2821 		    //		    System.err.println("===> copying color3");
2822 		    System.arraycopy(vdata,
2823 			src.indexColor[index]*src.stride + src.colorOffset,
2824 			vertexData, vOffset + colorOffset, colorStride);
2825 		} else if (colorStride == 3) {
2826 		    //		    System.err.println("===> copying color4");
2827 		    System.arraycopy(vdata,
2828 			src.indexColor[index]*src.stride + src.colorOffset,
2829 			vertexData, vOffset + colorOffset, colorStride);
2830 		    vertexData[vOffset + colorOffset + 3] = 1.0f;
2831 		}
2832 
2833 		if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
2834 		    int tcOffset = vOffset + textureOffset;
2835                     int interleavedOffset = 0;
2836 
2837 		    for (i = 0; i < texCoordSetCount;
2838 				i++, tcOffset += texCoordStride) {
2839 
2840                         if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
2841                             interleavedOffset = i * texCoordStride;
2842                         }
2843 
2844 			 System.arraycopy(vdata,
2845 			    (src.indexTexCoord[i][index])*src.stride + src.textureOffset + interleavedOffset,
2846 			    vertexData, tcOffset, texCoordStride);
2847 		    }
2848 		}
2849 
2850                 if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
2851                     // vertex attributes can't be interleaved
2852                     assert (src.vertexFormat & GeometryArray.INTERLEAVED) == 0;
2853 
2854 		    for (i = 0; i < vertexAttrCount; i++) {
2855                         int vaOffset = vOffset + vertexAttrOffsets[i];
2856 
2857 			 System.arraycopy(vdata,
2858 			    (src.indexVertexAttr[i][index])*src.stride + src.vertexAttrOffsets[i],
2859 			    vertexData, vaOffset, vertexAttrSizes[i]);
2860 		    }
2861                 }
2862 
2863 		if ((vertexFormat & GeometryArray.COORDINATES) != 0){
2864 		    //		    System.err.println("===> copying coords");
2865 		    System.arraycopy(vdata,
2866 			src.indexCoord[index]*src.stride
2867 				+ src.coordinateOffset,
2868 			vertexData,
2869 			vOffset + coordinateOffset, 3);
2870 		}
2871 		vOffset += stride;
2872 	    }
2873 
2874 	} else {
2875 	    if ((vertexFormat & GeometryArray.NORMALS) != 0) {
2876 		vOffset = normalOffset;
2877 		switch ((src.vertexType & NORMAL_DEFINED)) {
2878 		case NF:
2879 		    for (index=start; index < end; index++) {
2880 			System.arraycopy(src.floatRefNormals,
2881 					 src.indexNormal[index]*3,
2882 					 vertexData,
2883 					 vOffset, 3);
2884 			vOffset += stride;
2885 		    }
2886 		    break;
2887 		case N3F:
2888 		    for (index=start; index < end; index++) {
2889 			srcOffset = src.indexNormal[index];
2890 			vertexData[vOffset] = src.v3fRefNormals[srcOffset].x;
2891 			vertexData[vOffset+1] = src.v3fRefNormals[srcOffset].y;
2892 			vertexData[vOffset+2] = src.v3fRefNormals[srcOffset].z;
2893 			vOffset += stride;
2894 		    }
2895 		    break;
2896 		default:
2897 		    break;
2898 		}
2899 	    }
2900 
2901 	    if ((vertexFormat & GeometryArray.COLOR) != 0) {
2902 		vOffset = colorOffset;
2903 		int multiplier = 3;
2904 		if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
2905 		    multiplier = 4;
2906 
2907 		switch ((src.vertexType & COLOR_DEFINED)) {
2908 		case CF:
2909 		    for (index=start; index < end; index++) {
2910 			if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
2911 			    System.arraycopy(src.floatRefColors,
2912 					     src.indexColor[index]*multiplier,
2913 					     vertexData,
2914 					     vOffset, 4);
2915 			}
2916 			else {
2917 			    System.arraycopy(src.floatRefColors,
2918 					     src.indexColor[index]*multiplier,
2919 					     vertexData,
2920 					     vOffset, 3);
2921 			    vertexData[vOffset+3] = 1.0f;
2922 			}
2923 			vOffset += stride;
2924 		    }
2925 		    break;
2926 		case CUB:
2927 		    for (index=start; index < end; index++) {
2928 			srcOffset = src.indexColor[index] * multiplier;
2929 			vertexData[vOffset] = (src.byteRefColors[srcOffset] & 0xff) * ByteToFloatScale;
2930 			vertexData[vOffset+1] = (src.byteRefColors[srcOffset+1] & 0xff) * ByteToFloatScale;
2931 			vertexData[vOffset+2] = (src.byteRefColors[srcOffset+2] & 0xff) * ByteToFloatScale;
2932 			if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
2933 			    vertexData[vOffset+3] = (src.byteRefColors[srcOffset+3] & 0xff) * ByteToFloatScale;
2934 			}
2935 			else {
2936 			    vertexData[vOffset+3] = 1.0f;
2937 			}
2938 			vOffset += stride;
2939 		    }
2940 		    break;
2941 		case C3F:
2942 		    for (index=start; index < end; index++) {
2943 			srcOffset = src.indexColor[index];
2944 			vertexData[vOffset] = src.c3fRefColors[srcOffset].x;
2945 			vertexData[vOffset+1] = src.c3fRefColors[srcOffset].y;
2946 			vertexData[vOffset+2] = src.c3fRefColors[srcOffset].z;
2947 			vertexData[vOffset+3] = 1.0f;
2948 			vOffset += stride;
2949 		    }
2950 		    break;
2951 		case C4F:
2952 		    for (index=start; index < end; index++) {
2953 			srcOffset = src.indexColor[index];
2954 			vertexData[vOffset] = src.c4fRefColors[srcOffset].x;
2955 			vertexData[vOffset+1] = src.c4fRefColors[srcOffset].y;
2956 			vertexData[vOffset+2] = src.c4fRefColors[srcOffset].z;
2957 			vertexData[vOffset+3] = src.c4fRefColors[srcOffset].w;
2958 			vOffset += stride;
2959 		    }
2960 		    break;
2961 		case C3UB:
2962 		    for (index=start; index < end; index++) {
2963 			srcOffset = src.indexColor[index];
2964 			vertexData[vOffset] = (src.c3bRefColors[srcOffset].x & 0xff) * ByteToFloatScale;
2965 			vertexData[vOffset+1] = (src.c3bRefColors[srcOffset].y & 0xff) * ByteToFloatScale;
2966 			vertexData[vOffset+2] = (src.c3bRefColors[srcOffset].z & 0xff) * ByteToFloatScale;
2967 			vertexData[vOffset+3] = 1.0f;
2968 			vOffset += stride;
2969 		    }
2970 		    break;
2971 		case C4UB:
2972 		    for (index=start; index < end; index++) {
2973 			srcOffset = src.indexColor[index];
2974 			vertexData[vOffset] = (src.c4bRefColors[srcOffset].x & 0xff) * ByteToFloatScale;
2975 			vertexData[vOffset+1] = (src.c4bRefColors[srcOffset].y & 0xff) * ByteToFloatScale;
2976 			vertexData[vOffset+2] = (src.c4bRefColors[srcOffset].z & 0xff) * ByteToFloatScale;
2977 			vertexData[vOffset+3] = (src.c4bRefColors[srcOffset].w & 0xff) * ByteToFloatScale;
2978 			vOffset += stride;
2979 		    }
2980 		    break;
2981 		default:
2982 		    break;
2983 		}
2984 	    }
2985 
2986 	    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
2987 		vOffset = textureOffset;
2988 		switch ((src.vertexType & TEXCOORD_DEFINED)) {
2989 		case TF:
2990 		    for (index=start; index < end; index++) {
2991 			for (i = 0, tOffset = vOffset;
2992 				i < texCoordSetCount; i++) {
2993 			    System.arraycopy(src.refTexCoords[i],
2994 				src.indexTexCoord[i][index]*texCoordStride,
2995 				vertexData, tOffset, texCoordStride);
2996 			    tOffset += texCoordStride;
2997 			}
2998 			vOffset += stride;
2999 		    }
3000 		    break;
3001 		case T2F:
3002 		    for (index=start; index < end; index++) {
3003 			for (i = 0, tOffset = vOffset;
3004 			        i < texCoordSetCount; i++) {
3005 			     srcOffset = src.indexTexCoord[i][index];
3006 			     vertexData[tOffset] =
3007 			      ((TexCoord2f[])src.refTexCoords[i])[srcOffset].x;
3008 			     vertexData[tOffset+1] =
3009 			      ((TexCoord2f[])src.refTexCoords[i])[srcOffset].y;
3010 			     tOffset += texCoordStride;
3011 			}
3012 			vOffset += stride;
3013 		    }
3014 		    break;
3015 		case T3F:
3016 		    for (index=start; index < end; index++) {
3017 			for (i = 0, tOffset = vOffset;
3018 			        i < texCoordSetCount; i++) {
3019 			     srcOffset = src.indexTexCoord[i][index];
3020 			     vertexData[tOffset] =
3021 			      ((TexCoord3f[])src.refTexCoords[i])[srcOffset].x;
3022 			     vertexData[tOffset+1] =
3023 			      ((TexCoord3f[])src.refTexCoords[i])[srcOffset].y;
3024 			     vertexData[tOffset+2] =
3025 			      ((TexCoord3f[])src.refTexCoords[i])[srcOffset].z;
3026 			     tOffset += texCoordStride;
3027 			}
3028 			vOffset += stride;
3029 		    }
3030 		    break;
3031 		default:
3032 		    break;
3033 		}
3034 	    }
3035 
3036             if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
3037 		vOffset = 0;
3038 		switch (src.vertexType & VATTR_DEFINED) {
3039 		case AF:
3040 		    for (index=start; index < end; index++) {
3041 			for (i = 0; i < vertexAttrCount; i++) {
3042                             int vaOffset = vOffset + vertexAttrOffsets[i];
3043 			    System.arraycopy(src.floatRefVertexAttrs[i],
3044 				src.indexVertexAttr[i][index]*vertexAttrSizes[i],
3045 				vertexData, vaOffset, vertexAttrSizes[i]);
3046 			}
3047 			vOffset += stride;
3048 		    }
3049 		    break;
3050 		}
3051             }
3052 
3053 	    if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
3054 		vOffset = coordinateOffset;
3055 		switch ((src.vertexType & VERTEX_DEFINED)) {
3056 		case PF:
3057 		    for (index=start; index < end; index++) {
3058 			System.arraycopy(src.floatRefCoords,
3059 					 src.indexCoord[index]*3,
3060 					 vertexData,
3061 					 vOffset, 3);
3062 			vOffset += stride;
3063 		    }
3064 		    break;
3065 		case PD:
3066 		    for (index=start; index < end; index++) {
3067 			srcOffset = src.indexCoord[index] * 3;
3068 			vertexData[vOffset] = (float)src.doubleRefCoords[srcOffset];
3069 			vertexData[vOffset+1] = (float)src.doubleRefCoords[srcOffset+1];
3070 			vertexData[vOffset+2] = (float)src.doubleRefCoords[srcOffset+2];
3071 			vOffset += stride;
3072 		    }
3073 		    break;
3074 		case P3F:
3075 		    for (index=start; index < end; index++) {
3076 			srcOffset = src.indexCoord[index];
3077 			vertexData[vOffset] = src.p3fRefCoords[srcOffset].x;
3078 			vertexData[vOffset+1] = src.p3fRefCoords[srcOffset].y;
3079 			vertexData[vOffset+2] = src.p3fRefCoords[srcOffset].z;
3080 			vOffset += stride;
3081 		    }
3082 		    break;
3083 		case P3D:
3084 		    for (index=start; index < end; index++) {
3085 			srcOffset = src.indexCoord[index];
3086 			vertexData[vOffset] = (float)src.p3dRefCoords[srcOffset].x;
3087 			vertexData[vOffset+1] = (float)src.p3dRefCoords[srcOffset].y;
3088 			vertexData[vOffset+2] = (float)src.p3dRefCoords[srcOffset].z;
3089 			vOffset += stride;
3090 		    }
3091 		    break;
3092 		default:
3093 		    break;
3094 		}
3095 	    }
3096 
3097 	}
3098     }
3099 
3100 
unIndexifyNIOBuffer(IndexedGeometryArrayRetained src)3101     private void unIndexifyNIOBuffer(IndexedGeometryArrayRetained src) {
3102 //        System.err.println("unIndexifyNIOBuffer");
3103 
3104         int vOffset = 0, srcOffset, tOffset = 0;
3105         int index, colorStride = 0;
3106 	float[] vdata = null;
3107         int i;
3108 	int start, end;
3109 	start = src.initialIndexIndex;
3110 	end = src.initialIndexIndex + src.validIndexCount;
3111 	// If its interleaved data then ..
3112 	if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
3113 	    if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
3114 		colorStride = 4;
3115 	    else if ((src.vertexFormat & GeometryArray.COLOR) != 0)
3116 		colorStride = 3;
3117 
3118 	    //	    System.err.println("===> start = "+start+" end = "+end);
3119 	    for (index= start; index < end; index++) {
3120 		if ((vertexFormat & GeometryArray.NORMALS) != 0){
3121 		    src.interleavedFloatBufferImpl.position(src.indexNormal[index]*src.stride + src.normalOffset);
3122 		    src.interleavedFloatBufferImpl.get(vertexData, vOffset + normalOffset, 3);
3123 		}
3124 
3125 		if (colorStride == 4){
3126 		    src.interleavedFloatBufferImpl.position(src.indexColor[index]*src.stride + src.colorOffset);
3127 		    src.interleavedFloatBufferImpl.get(vertexData, vOffset + colorOffset, colorStride);
3128 		} else if (colorStride == 3) {
3129 		    src.interleavedFloatBufferImpl.position(src.indexColor[index]*src.stride + src.colorOffset);
3130 		    src.interleavedFloatBufferImpl.get(vertexData, vOffset + colorOffset, colorStride);
3131 		    vertexData[vOffset + colorOffset + 3] = 1.0f;
3132 		}
3133 
3134 		if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
3135 		    int tcOffset = vOffset + textureOffset;
3136 		    for (i = 0; i < texCoordSetCount;
3137 				i++, tcOffset += texCoordStride) {
3138 
3139 			src.interleavedFloatBufferImpl.position((src.indexTexCoord[i][index])*src.stride +
3140 							    src.textureOffset);
3141 			src.interleavedFloatBufferImpl.get(vertexData, tcOffset, texCoordStride);
3142 		    }
3143 		}
3144 		if ((vertexFormat & GeometryArray.COORDINATES) != 0){
3145 		    src.interleavedFloatBufferImpl.position(src.indexCoord[index]*src.stride + src.coordinateOffset );
3146 		    src.interleavedFloatBufferImpl.get(vertexData, vOffset + coordinateOffset, 3);
3147 		}
3148 		vOffset += stride;
3149 	    }
3150 
3151 	} else {
3152 	    if ((vertexFormat & GeometryArray.NORMALS) != 0){
3153 		vOffset = normalOffset;
3154 		if ((src.vertexType & NORMAL_DEFINED) != 0) {
3155 		    for (index=start; index < end; index++) {
3156 			src.floatBufferRefNormals.position(src.indexNormal[index]*3);
3157 			src.floatBufferRefNormals.get(vertexData, vOffset, 3);
3158 			vOffset += stride;
3159 		    }
3160 		}
3161 	    }
3162 
3163             if ((vertexFormat & GeometryArray.COLOR) != 0){
3164 		vOffset = colorOffset;
3165 		int multiplier = 3;
3166 		if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
3167 		    multiplier = 4;
3168 
3169 		switch ((src.vertexType & COLOR_DEFINED)) {
3170 		case CF:
3171 		    for (index=start; index < end; index++) {
3172 			if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
3173 			    src.floatBufferRefColors.position(src.indexColor[index]*multiplier);
3174 			    src.floatBufferRefColors.get(vertexData, vOffset, 4);
3175 			}
3176 			else {
3177 			    src.floatBufferRefColors.position(src.indexColor[index]*multiplier);
3178 			    src.floatBufferRefColors.get(vertexData, vOffset, 3);
3179 			    vertexData[vOffset+3] = 1.0f;
3180 			}
3181 			vOffset += stride;
3182 		    }
3183 		    break;
3184 		case CUB:
3185 		    for (index=start; index < end; index++) {
3186 			srcOffset = src.indexColor[index] * multiplier;
3187 			vertexData[vOffset] = (src.byteBufferRefColors.get(srcOffset) & 0xff) * ByteToFloatScale;
3188 			vertexData[vOffset+1] = (src.byteBufferRefColors.get(srcOffset+1) & 0xff) * ByteToFloatScale;
3189 			vertexData[vOffset+2] = (src.byteBufferRefColors.get(srcOffset+2) & 0xff) * ByteToFloatScale;
3190 
3191 			if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
3192 			    vertexData[vOffset+3] = (src.byteBufferRefColors.get(srcOffset+3) & 0xff) * ByteToFloatScale;
3193 			}
3194 			else {
3195 			    vertexData[vOffset+3] = 1.0f;
3196 			}
3197 			vOffset += stride;
3198 		    }
3199 		    break;
3200 		default:
3201 		    break;
3202 		}
3203 	    }
3204 
3205             if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
3206 		vOffset = textureOffset;
3207 		 FloatBufferWrapper texBuffer;
3208 		if ((src.vertexType & TEXCOORD_DEFINED) != 0) {
3209 		    for (index=start; index < end; index++) {
3210 			for (i = 0, tOffset = vOffset;
3211 				i < texCoordSetCount; i++) {
3212 			    texBuffer = (FloatBufferWrapper)(((J3DBuffer) (src.refTexCoordsBuffer[i])).getBufferImpl());
3213 			    texBuffer.position(src.indexTexCoord[i][index]*texCoordStride);
3214 			    texBuffer.get(vertexData, tOffset, texCoordStride);
3215 			    tOffset += texCoordStride;
3216 			}
3217 			vOffset += stride;
3218 		    }
3219 		}
3220 	    }
3221 
3222             if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
3223 		vOffset = 0;
3224 		if ((src.vertexType & VATTR_DEFINED) == AF) {
3225 		    for (index=start; index < end; index++) {
3226 			for (i = 0; i < vertexAttrCount; i++) {
3227                             int vaOffset = vOffset + vertexAttrOffsets[i];
3228 			    FloatBufferWrapper vaBuffer = src.floatBufferRefVertexAttrs[i];
3229 			    vaBuffer.position(src.indexVertexAttr[i][index]*vertexAttrSizes[i]);
3230 			    vaBuffer.get(vertexData, vaOffset, vertexAttrSizes[i]);
3231 			}
3232 			vOffset += stride;
3233 		    }
3234 		}
3235 	    }
3236 
3237             if ((vertexFormat & GeometryArray.COORDINATES) != 0){
3238 		vOffset = coordinateOffset;
3239 		switch ((src.vertexType & VERTEX_DEFINED)) {
3240 		case PF:
3241 		    for (index=start; index < end; index++) {
3242 			src.floatBufferRefCoords.position(src.indexCoord[index]*3);
3243 			src.floatBufferRefCoords.get(vertexData, vOffset, 3);
3244 			vOffset += stride;
3245 		    }
3246 		    break;
3247 		case PD:
3248 		    for (index=start; index < end; index++) {
3249 			srcOffset = src.indexCoord[index] * 3;
3250 			vertexData[vOffset] = (float)src.doubleBufferRefCoords.get(srcOffset);
3251 			vertexData[vOffset+1] = (float)src.doubleBufferRefCoords.get(srcOffset+1);
3252 			vertexData[vOffset+2] = (float)src.doubleBufferRefCoords.get(srcOffset+2);
3253 			vOffset += stride;
3254 		    }
3255 		    break;
3256 		default:
3257 		    break;
3258 		}
3259 	    }
3260 
3261 	}
3262     }
3263 
3264 
3265     /**
3266      * Returns the vertex stride in numbers of floats as a function
3267      * of the vertexFormat.
3268      * @return the stride in floats for this vertex array
3269      */
stride()3270     int stride()
3271     {
3272 	int stride = 0;
3273 
3274 	if((this.vertexFormat & GeometryArray.COORDINATES) != 0) stride += 3;
3275 	if((this.vertexFormat & GeometryArray.NORMALS) != 0) stride += 3;
3276 
3277 	if ((this.vertexFormat & GeometryArray.COLOR) != 0) {
3278 	    if ((this.vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
3279 		// By copy
3280 		stride += 4;
3281 	    } else {
3282 		if ((this.vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
3283 		    stride += 3;
3284 		}
3285 		else {
3286 		    stride += 4;
3287 		}
3288 	    }
3289 	}
3290 
3291 	if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
3292 
3293 	    if ((this.vertexFormat &
3294 			GeometryArray.TEXTURE_COORDINATE_2) != 0) {
3295 	        texCoordStride = 2;
3296 	    } else if ((this.vertexFormat &
3297 			GeometryArray.TEXTURE_COORDINATE_3) != 0) {
3298 		texCoordStride = 3;
3299 	    } else if ((this.vertexFormat &
3300 			GeometryArray.TEXTURE_COORDINATE_4) != 0) {
3301 		texCoordStride = 4;
3302 	    }
3303 
3304 	    stride += texCoordStride * texCoordSetCount;
3305 	}
3306 
3307 	if ((this.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
3308 	    stride += vertexAttrStride;
3309 	}
3310 
3311 	//System.err.println("stride() = " + stride);
3312 	return stride;
3313     }
3314 
texCoordSetMapOffset()3315     int[] texCoordSetMapOffset()
3316     {
3317 	if (texCoordSetMap == null)
3318 	    return null;
3319 
3320         texCoordSetMapOffset = new int[texCoordSetMap.length];
3321 	for (int i = 0; i < texCoordSetMap.length; i++) {
3322 	     if (texCoordSetMap[i] == -1) {
3323 		 texCoordSetMapOffset[i] = -1;
3324 	     } else {
3325 	         texCoordSetMapOffset[i] = texCoordSetMap[i] * texCoordStride;
3326 	     }
3327 	}
3328 	return texCoordSetMapOffset;
3329     }
3330 
3331     /**
3332      * Returns the stride of the set of vertex attributes. This is the
3333      * sum of the sizes of each vertex attribute.
3334      * @return the stride of the vertex attribute data
3335      */
vertexAttrStride()3336     int vertexAttrStride() {
3337         int sum = 0;
3338         for (int i = 0; i < vertexAttrCount; i++) {
3339             sum += vertexAttrSizes[i];
3340         }
3341         return sum;
3342     }
3343 
3344     /**
3345      * Returns the offset in number of floats from the start of a vertex to
3346      * each per-vertex vertex attribute.
3347      * @return array of offsets in floats vertex start to the vertex attribute data
3348      */
vertexAttrOffsets()3349     int[] vertexAttrOffsets() {
3350 	int[] offsets;
3351 
3352         // Create array of offsets to the start of each vertex attribute.
3353         // The offset of the first attribute is always 0. If no vertex attributes exist,
3354         // then we will allocate an array of length 1 to avoid some checking elsewhere.
3355         if (vertexAttrCount > 0) {
3356             offsets = new int[vertexAttrCount];
3357         }
3358         else {
3359             offsets = new int[1];
3360         }
3361         offsets[0] = 0;
3362         for (int i = 1; i < vertexAttrCount; i++) {
3363             offsets[i] = offsets[i-1] + vertexAttrSizes[i-1];
3364         }
3365 
3366         return offsets;
3367     }
3368 
3369     /**
3370      * Returns the offset in number of floats from the start of a vertex to
3371      * the per-vertex texture coordinate data.
3372      * texture coordinate data always follows vertex attribute data
3373      * @return the offset in floats vertex start to the tetxure data
3374      */
textureOffset()3375     int textureOffset()
3376     {
3377 	int offset = vertexAttrOffsets[0];
3378 
3379 	if ((this.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
3380 	    offset += vertexAttrStride;
3381 	}
3382 
3383 	return offset;
3384     }
3385 
3386     /**
3387      * Returns the offset in number of floats from the start of a vertex to
3388      * the per-vertex color data.
3389      * color data always follows texture data
3390      * @param vertexFormat the vertex format for this array
3391      * @return the offset in floats vertex start to the color data
3392      */
colorOffset()3393     int colorOffset()
3394     {
3395 	int offset = textureOffset;
3396 
3397 	if((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0)
3398 	    offset += 2 * texCoordSetCount;
3399 	else if((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0)
3400 	    offset += 3 * texCoordSetCount;
3401 	else if((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0)
3402 	    offset += 4 * texCoordSetCount;
3403 
3404 	return offset;
3405     }
3406 
3407     /**
3408      * Returns the offset in number of floats from the start of a vertex to
3409      * the per-vertex normal data.
3410      * normal data always follows color data
3411      * @return the offset in floats from the start of a vertex to the normal
3412      */
normalOffset()3413     int normalOffset()
3414     {
3415 	int offset = colorOffset;
3416 
3417 	if ((this.vertexFormat & GeometryArray.COLOR) != 0) {
3418 	    if ((this.vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
3419 		offset += 4;
3420 	    } else {
3421 		if ((this.vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
3422 		    offset += 3;
3423 		}
3424 		else {
3425 		    offset += 4;
3426 		}
3427 	    }
3428 	}
3429 	return offset;
3430     }
3431 
3432     /**
3433      * Returns the offset in number of floats from the start of a vertex to
3434      * the per vertex coordinate data.
3435      * @return the offset in floats vertex start to the coordinate data
3436      */
coordinateOffset()3437     int coordinateOffset()
3438     {
3439 	int offset = normalOffset;
3440 
3441 	if ((this.vertexFormat & GeometryArray.NORMALS) != 0) offset += 3;
3442 	return offset;
3443     }
3444 
3445     /**
3446      * Returns number of vertices in the GeometryArray
3447      * @return vertexCount number of vertices in the GeometryArray
3448      */
getVertexCount()3449     int getVertexCount(){
3450 	return vertexCount;
3451     }
3452 
3453     /**
3454      * Returns vertexFormat in the GeometryArray
3455      * @return vertexFormat format of vertices in the GeometryArray
3456      */
getVertexFormat()3457     int getVertexFormat(){
3458 	return vertexFormat;
3459     }
3460 
3461     /**
3462      * Retrieves the number of vertex attributes in this GeometryArray
3463      * object.
3464      *
3465      * @return the number of vertex attributes in this GeometryArray
3466      * object
3467      */
getVertexAttrCount()3468     int getVertexAttrCount() {
3469         return vertexAttrCount;
3470     }
3471 
3472 
3473     /**
3474      * Retrieves the vertex attribute sizes array from this
3475      * GeometryArray object.
3476      *
3477      * @param vertexAttrSizes an array that will receive a copy of
3478      * the vertex attribute sizes array.  The array must hold at least
3479      * <code>vertexAttrCount</code> elements.
3480      */
getVertexAttrSizes(int[] vertexAttrSizes)3481     void getVertexAttrSizes(int[] vertexAttrSizes) {
3482         for (int i = 0; i < vertexAttrCount; i++) {
3483             vertexAttrSizes[i] = this.vertexAttrSizes[i];
3484         }
3485     }
3486 
3487 
3488 
sendDataChangedMessage(boolean coordinatesChanged)3489     void sendDataChangedMessage(boolean coordinatesChanged) {
3490 	J3dMessage[] m;
3491 	int i, j, k, index, numShapeMessages, numMorphMessages;
3492 	ArrayList shapeList;
3493 	Shape3DRetained s;
3494 	ArrayList morphList;
3495 	MorphRetained morph;
3496 
3497 	synchronized(liveStateLock) {
3498 	    if (source != null && source.isLive()) {
3499 		// System.err.println("In GeometryArrayRetained - ");
3500 
3501 		// Send a message to renderBin to rebuild the display list or
3502 		// process the vertex array accordingly
3503 		// XXXX: Should I send one per universe, isn't display list
3504 		// shared by all context/universes?
3505 		int threads = J3dThread.UPDATE_RENDER;
3506 		// If the geometry type is Indexed then we need to clone the geometry
3507 		// We also need to update the cachedChangedFrequent flag
3508 		threads |= J3dThread.UPDATE_RENDERING_ATTRIBUTES;
3509 
3510 		synchronized (universeList) {
3511 		    numShapeMessages = universeList.size();
3512 		    m = new J3dMessage[numShapeMessages];
3513 
3514 		    k = 0;
3515 
3516 		    for (i = 0; i < numShapeMessages; i++, k++) {
3517 			gaList.clear();
3518 
3519 			shapeList = (ArrayList)userLists.get(i);
3520 			for (j=0; j<shapeList.size(); j++) {
3521 			    s = (Shape3DRetained)shapeList.get(j);
3522 			    LeafRetained src = (LeafRetained)s.sourceNode;
3523 			    // Should only need to update distinct localBounds.
3524 			    if (coordinatesChanged && src.boundsAutoCompute) {
3525 				src.boundsDirty = true;
3526 			    }
3527 			}
3528 
3529 			for (j=0; j<shapeList.size(); j++) {
3530 			    s = (Shape3DRetained)shapeList.get(j);
3531 			    LeafRetained src = (LeafRetained)s.sourceNode;
3532 			    if (src.boundsDirty) {
3533 				// update combine bounds of mirrorShape3Ds. So we need to
3534 				// use its bounds and not localBounds.
3535 				// bounds is actually a reference to
3536 				// mirrorShape3D.source.localBounds.
3537 				src.updateBounds();
3538 				src.boundsDirty = false;
3539 			    }
3540 			    gaList.add(Shape3DRetained.getGeomAtom(s));
3541 			}
3542 
3543 			m[k] = new J3dMessage();
3544 
3545 			m[k].type = J3dMessage.GEOMETRY_CHANGED;
3546 			// Who to send this message to ?
3547 			m[k].threads = threads;
3548 			m[k].args[0] = gaList.toArray();
3549 			m[k].args[1] = this;
3550 			m[k].args[2]= null;
3551 			m[k].args[3] = new Integer(changedFrequent);
3552 			m[k].universe=(VirtualUniverse)universeList.get(i);
3553 		    }
3554 		    VirtualUniverse.mc.processMessage(m);
3555 		}
3556 
3557 		if (morphUniverseList != null) {
3558 		    synchronized (morphUniverseList) {
3559 			numMorphMessages = morphUniverseList.size();
3560 
3561 			// take care of morph that is referencing this geometry
3562 			if (numMorphMessages > 0) {
3563 			    synchronized (morphUniverseList) {
3564 				for (i = 0; i < numMorphMessages; i++, k++) {
3565 				    morphList = (ArrayList)morphUserLists.get(i);
3566 				    for (j=0; j<morphList.size(); j++) {
3567 					morph = (MorphRetained)morphList.get(j);
3568 					morph.updateMorphedGeometryArray(this, coordinatesChanged);
3569 				    }
3570 				}
3571 			    }
3572 			}
3573 		    }
3574 		}
3575 	    }
3576 	}
3577 
3578     }
3579     /**
3580      * Sets the coordinate associated with the vertex at
3581      * the specified index.
3582      * @param index the vertex index
3583      * @param coordinate an array of 3 values containing the new coordinate
3584      */
setCoordinate(int index, float coordinate[])3585     void setCoordinate(int index, float coordinate[]) {
3586 	int offset = this.stride * index + coordinateOffset;
3587 	boolean isLive = source!=null && source.isLive();
3588 	if(isLive){
3589             geomLock.getLock();
3590 	}
3591 	dirtyFlag |= COORDINATE_CHANGED;
3592 
3593 	this.vertexData[offset]  = coordinate[0];
3594 	this.vertexData[offset+1]= coordinate[1];
3595 	this.vertexData[offset+2]= coordinate[2];
3596 
3597         if (isLive) {
3598             geomLock.unLock();
3599         }
3600         if (inUpdater || (source == null)) {
3601             return;
3602         }
3603 	if (!isLive) {
3604 		boundsDirty = true;
3605 	    return;
3606 	}
3607 
3608 	// Compute geo's bounds
3609 	processCoordsChanged(false);
3610 	sendDataChangedMessage(true);
3611 
3612     }
3613 
3614     /**
3615      * Sets the coordinate associated with the vertex at
3616      * the specified index.
3617      * @param index the vertex index
3618      * @param coordinate an array of 3 values containing the new coordinate
3619      */
setCoordinate(int index, double coordinate[])3620     void setCoordinate(int index, double coordinate[]) {
3621 	int offset = this.stride * index + coordinateOffset;
3622 	boolean isLive = source!=null && source.isLive();
3623 	if(isLive){
3624             geomLock.getLock();
3625 	}
3626 	dirtyFlag |= COORDINATE_CHANGED;
3627 	this.vertexData[offset]  = (float)coordinate[0];
3628 	this.vertexData[offset+1]= (float)coordinate[1];
3629 	this.vertexData[offset+2]= (float)coordinate[2];
3630 
3631 	if(isLive) {
3632             geomLock.unLock();
3633 	}
3634 
3635         if (inUpdater || (source == null)) {
3636 	    return;
3637 	}
3638 	if (!isLive) {
3639             boundsDirty = true;
3640 	    return;
3641 	}
3642 
3643 	// Compute geo's bounds
3644 	processCoordsChanged(false);
3645 	sendDataChangedMessage(true);
3646     }
3647 
3648     /**
3649      * Sets the coordinate associated with the vertex at
3650      * the specified index.
3651      * @param index the vertex index
3652      * @param coordinate a vector containing the new coordinate
3653      */
setCoordinate(int index, Point3f coordinate)3654     void setCoordinate(int index, Point3f coordinate) {
3655 	int offset = this.stride * index + coordinateOffset;
3656 	boolean isLive = source!=null && source.isLive();
3657 	if(isLive){
3658             geomLock.getLock();
3659 	}
3660 	dirtyFlag |= COORDINATE_CHANGED;
3661 	this.vertexData[offset]  = coordinate.x;
3662 	this.vertexData[offset+1]= coordinate.y;
3663 	this.vertexData[offset+2]= coordinate.z;
3664 
3665 	if(isLive) {
3666             geomLock.unLock();
3667 	}
3668         if (inUpdater || (source == null)) {
3669 	    return;
3670 	}
3671 	if (!isLive) {
3672 	    boundsDirty = true;
3673 	    return;
3674 	}
3675 
3676 	// Compute geo's bounds
3677 	processCoordsChanged(false);
3678 	sendDataChangedMessage(true);
3679     }
3680 
3681     /**
3682      * Sets the coordinate associated with the vertex at
3683      * the specified index.
3684      * @param index the vertex index
3685      * @param coordinate a vector containing the new coordinate
3686      */
setCoordinate(int index, Point3d coordinate)3687     void setCoordinate(int index, Point3d coordinate) {
3688 	int offset = this.stride * index + coordinateOffset;
3689 	boolean isLive = source!=null && source.isLive();
3690 	if(isLive){
3691             geomLock.getLock();
3692 	}
3693 	dirtyFlag |= COORDINATE_CHANGED;
3694 	this.vertexData[offset]  = (float)coordinate.x;
3695 	this.vertexData[offset+1]= (float)coordinate.y;
3696 	this.vertexData[offset+2]= (float)coordinate.z;
3697 	if(isLive) {
3698             geomLock.unLock();
3699 	}
3700 	if (inUpdater || source == null ) {
3701 	    return;
3702 	}
3703 	if (!isLive) {
3704 	    boundsDirty = true;
3705 	    return;
3706 	}
3707 	// Compute geo's bounds
3708 	processCoordsChanged(false);
3709 	sendDataChangedMessage(true);
3710     }
3711 
3712     /**
3713      * Sets the coordinates associated with the vertices starting at
3714      * the specified index.
3715      * @param index the vertex index
3716      * @param coordinates an array of 3*n values containing n new coordinates
3717      */
setCoordinates(int index, float coordinates[])3718     void setCoordinates(int index, float coordinates[]) {
3719 	int offset = this.stride * index + coordinateOffset;
3720 	int i, j, num = coordinates.length;
3721 	boolean isLive = source!=null && source.isLive();
3722 	if(isLive){
3723             geomLock.getLock();
3724 	}
3725 	dirtyFlag |= COORDINATE_CHANGED;
3726 
3727 	for (i=0, j= offset;i < num; i+=3, j+= this.stride)
3728 	    {
3729 		this.vertexData[j]  = coordinates[i];
3730 		this.vertexData[j+1]= coordinates[i+1];
3731 		this.vertexData[j+2]= coordinates[i+2];
3732 	    }
3733 
3734 	if(isLive) {
3735             geomLock.unLock();
3736 	}
3737 	if (inUpdater ||source == null ) {
3738 	    return;
3739 	}
3740 	if (!isLive) {
3741 	    boundsDirty = true;
3742 	    return;
3743 	}
3744 
3745 	// Compute geo's bounds
3746 	processCoordsChanged(false);
3747 
3748 	sendDataChangedMessage(true);
3749 
3750     }
3751 
3752     /**
3753      * Sets the coordinates associated with the vertices starting at
3754      * the specified index.
3755      * @param index the vertex index
3756      * @param coordinates an array of 3*n values containing n new coordinates
3757      */
setCoordinates(int index, double coordinates[])3758     void setCoordinates(int index, double coordinates[]) {
3759 	int offset = this.stride * index + coordinateOffset;
3760 	int i, j, num = coordinates.length;
3761 	boolean isLive = source!=null && source.isLive();
3762 	if(isLive){
3763             geomLock.getLock();
3764 	}
3765 	dirtyFlag |= COORDINATE_CHANGED;
3766 
3767 	for (i=0, j= offset;i < num; i+=3, j+= this.stride)
3768 	    {
3769 		this.vertexData[j]  = (float)coordinates[i];
3770 		this.vertexData[j+1]= (float)coordinates[i+1];
3771 		this.vertexData[j+2]= (float)coordinates[i+2];
3772 	    }
3773 
3774 	if(isLive) {
3775             geomLock.unLock();
3776 	}
3777 
3778 	if (inUpdater ||source == null ) {
3779 	    return;
3780 	}
3781 	if (!isLive) {
3782 	    boundsDirty = true;
3783 	    return;
3784 	}
3785 
3786 	// Compute geo's bounds
3787 	processCoordsChanged(false);
3788 
3789 	sendDataChangedMessage(true);
3790     }
3791 
3792     /**
3793      * Sets the coordinates associated with the vertices starting at
3794      * the specified index.
3795      * @param index the vertex index
3796      * @param coordinates an array of vectors containing new coordinates
3797      */
setCoordinates(int index, Point3f coordinates[])3798     void setCoordinates(int index, Point3f coordinates[]) {
3799 	int offset = this.stride * index + coordinateOffset;
3800 	int i, j, num = coordinates.length;
3801 	boolean isLive = source!=null && source.isLive();
3802 	if(isLive){
3803             geomLock.getLock();
3804 	}
3805 	dirtyFlag |= COORDINATE_CHANGED;
3806 
3807 	for (i=0, j= offset;i < num; i++, j+= this.stride)
3808 	    {
3809 		this.vertexData[j]  = coordinates[i].x;
3810 		this.vertexData[j+1]= coordinates[i].y;
3811 		this.vertexData[j+2]= coordinates[i].z;
3812 	    }
3813 	if(isLive) {
3814             geomLock.unLock();
3815 	}
3816 
3817 	if (inUpdater ||source == null ) {
3818 	    return;
3819 	}
3820 	if (!isLive) {
3821 	    boundsDirty = true;
3822 	    return;
3823 	}
3824 
3825 	// Compute geo's bounds
3826 	processCoordsChanged(false);
3827 
3828 	sendDataChangedMessage(true);
3829 
3830     }
3831 
3832     /**
3833      * Sets the coordinates associated with the vertices starting at
3834      * the specified index.
3835      * @param index the vertex index
3836      * @param coordinates an array of vectors containing new coordinates
3837      */
setCoordinates(int index, Point3d coordinates[])3838     void setCoordinates(int index, Point3d coordinates[]) {
3839 	int offset = this.stride * index + coordinateOffset;
3840 	int i, j, num = coordinates.length;
3841 	boolean isLive = source!=null && source.isLive();
3842 	if(isLive){
3843             geomLock.getLock();
3844 	}
3845 	dirtyFlag |= COORDINATE_CHANGED;
3846 
3847 	for (i=0, j= offset;i < num; i++, j+= this.stride)
3848 	    {
3849 		this.vertexData[j]  = (float)coordinates[i].x;
3850 		this.vertexData[j+1]= (float)coordinates[i].y;
3851 		this.vertexData[j+2]= (float)coordinates[i].z;
3852 	    }
3853         if(isLive) {
3854             geomLock.unLock();
3855         }
3856 
3857         if (inUpdater ||source == null ) {
3858 	    return;
3859 	}
3860 	if (!isLive) {
3861 	    boundsDirty = true;
3862 	    return;
3863 	}
3864 
3865 	// Compute geo's bounds
3866 	processCoordsChanged(false);
3867 
3868 	sendDataChangedMessage(true);
3869     }
3870 
3871 
3872     /**
3873      * Sets the coordinates associated with the vertices starting at
3874      * the specified index for this object using coordinate data starting
3875      * from vertex index <code>start</code> for <code>length</code> vertices.
3876      * @param index the vertex index
3877      * @param coordinates an array of vectors containing new coordinates
3878      * @param start starting vertex index of data in <code>coordinates</code>  .
3879      * @param length number of vertices to be copied.
3880      */
setCoordinates(int index, float coordinates[], int start, int length)3881     void setCoordinates(int index, float coordinates[], int start, int length) {
3882 	int offset = this.stride * index + coordinateOffset;
3883 	int i, j;
3884 	boolean isLive = source!=null && source.isLive();
3885 	if(isLive){
3886             geomLock.getLock();
3887 	}
3888 	dirtyFlag |= COORDINATE_CHANGED;
3889 	for (i= start * 3, j= offset; i < (start+length) * 3;
3890 	     i+=3, j+= this.stride) {
3891 	    this.vertexData[j]  = coordinates[i];
3892 	    this.vertexData[j+1]= coordinates[i+1];
3893 	    this.vertexData[j+2]= coordinates[i+2];
3894 	}
3895 	if(isLive) {
3896             geomLock.unLock();
3897 	}
3898 	if (inUpdater ||source == null ) {
3899 	    return;
3900 	}
3901 	if (!isLive) {
3902 	    boundsDirty = true;
3903 	    return;
3904 	}
3905 
3906 	// Compute geo's bounds
3907 	processCoordsChanged(false);
3908 
3909 	sendDataChangedMessage(true);
3910     }
3911 
3912     /**
3913      * Sets the coordinates associated with the vertices starting at
3914      * the specified index for this object  using coordinate data starting
3915      * from vertex index <code>start</code> for <code>length</code> vertices.
3916      * @param index the vertex index
3917      * @param coordinates an array of 3*n values containing n new coordinates
3918      * @param start starting vertex index of data in <code>coordinates</code>  .
3919      * @param length number of vertices to be copied.
3920      */
setCoordinates(int index, double coordinates[], int start, int length)3921     void setCoordinates(int index, double coordinates[], int start, int length) {
3922 	int offset = this.stride * index + coordinateOffset;
3923 	int i, j;
3924 	boolean isLive = source!=null && source.isLive();
3925 	if(isLive){
3926             geomLock.getLock();
3927 	}
3928 	dirtyFlag |= COORDINATE_CHANGED;
3929 
3930 	for (i= start*3, j= offset; i < (start+length)*3;
3931 	     i+=3, j+= this.stride) {
3932 	    this.vertexData[j]  = (float)coordinates[i];
3933 	    this.vertexData[j+1]= (float)coordinates[i+1];
3934 	    this.vertexData[j+2]= (float)coordinates[i+2];
3935 	}
3936 
3937 	if(isLive) {
3938             geomLock.unLock();
3939 	}
3940         if (inUpdater || (source == null)) {
3941 	    return;
3942 	}
3943 	if (!isLive) {
3944 	    boundsDirty = true;
3945 	    return;
3946 	}
3947 
3948 
3949 	// Compute geo's bounds
3950 	processCoordsChanged(false);
3951 
3952 	sendDataChangedMessage(true);
3953     }
3954 
3955     /**
3956      * Sets the coordinates associated with the vertices starting at
3957      * the specified index for this object using coordinate data starting
3958      * from vertex index <code>start</code> for <code>length</code> vertices.
3959      * @param index the vertex index
3960      * @param coordinates an array of vectors containing new coordinates
3961      * @param start starting vertex index of data in <code>coordinates</code>  .
3962      * @param length number of vertices to be copied.
3963      */
setCoordinates(int index, Point3f coordinates[], int start, int length)3964     void setCoordinates(int index, Point3f coordinates[], int start,
3965 			int length) {
3966 	int offset = this.stride * index + coordinateOffset;
3967 	int i, j;
3968 	boolean isLive = source!=null && source.isLive();
3969 	if(isLive){
3970             geomLock.getLock();
3971 	}
3972 	dirtyFlag |= COORDINATE_CHANGED;
3973 
3974 	for (i=start, j= offset;i < start + length; i++, j+= this.stride) {
3975 	    this.vertexData[j]  = coordinates[i].x;
3976 	    this.vertexData[j+1]= coordinates[i].y;
3977 	    this.vertexData[j+2]= coordinates[i].z;
3978 	}
3979 
3980 	if(isLive) {
3981             geomLock.unLock();
3982         }
3983 
3984         if (inUpdater || (source == null)) {
3985 	    return;
3986 	}
3987 	if (!isLive) {
3988 	    boundsDirty = true;
3989 	    return;
3990 	}
3991 
3992 
3993 	// Compute geo's bounds
3994 	processCoordsChanged(false);
3995 
3996 	sendDataChangedMessage(true);
3997     }
3998 
3999     /**
4000      * Sets the coordinates associated with the vertices starting at
4001      * the specified index for this object using coordinate data starting
4002      * from vertex index <code>start</code> for <code>length</code> vertices.
4003      * @param index the vertex index
4004      * @param coordinates an array of vectors containing new coordinates
4005      * @param start starting vertex index of data in <code>coordinates</code>  .
4006      * @param length number of vertices to be copied.
4007      */
setCoordinates(int index, Point3d coordinates[], int start, int length)4008     void setCoordinates(int index, Point3d coordinates[], int start,
4009 			int length) {
4010 	int offset = this.stride * index + coordinateOffset;
4011 	int i, j;
4012 	boolean isLive = source!=null && source.isLive();
4013 	if(isLive){
4014             geomLock.getLock();
4015 	}
4016 	dirtyFlag |= COORDINATE_CHANGED;
4017 
4018 	for (i=start, j= offset;i < start + length; i++, j+= this.stride) {
4019 	    this.vertexData[j]  = (float)coordinates[i].x;
4020 	    this.vertexData[j+1]= (float)coordinates[i].y;
4021 	    this.vertexData[j+2]= (float)coordinates[i].z;
4022 	}
4023 
4024 	if(isLive) {
4025             geomLock.unLock();
4026         }
4027         if (inUpdater || (source == null)) {
4028 	    return;
4029 	}
4030 	if (!isLive) {
4031 	    boundsDirty = true;
4032 	    return;
4033 	}
4034 
4035 	// Compute geo's bounds
4036 	processCoordsChanged(false);
4037 
4038 	sendDataChangedMessage(true);
4039     }
4040 
4041     /**
4042      * Sets the color associated with the vertex at
4043      * the specified index.
4044      * @param index the vertex index
4045      * @param color an array of 3 or 4 values containing the new color
4046      */
setColor(int index, float color[])4047     void setColor(int index, float color[]) {
4048 	int offset = this.stride*index + colorOffset;
4049 
4050 	boolean isLive = source!=null && source.isLive();
4051 	if(isLive){
4052             geomLock.getLock();
4053 	}
4054 	dirtyFlag |= COLOR_CHANGED;
4055 	colorChanged = 0xffff;
4056 	this.vertexData[offset]   = color[0];
4057 	this.vertexData[offset+1] = color[1];
4058 	this.vertexData[offset+2] = color[2];
4059 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
4060 	    this.vertexData[offset+3] = color[3]*lastAlpha[0];
4061 	else
4062 	    this.vertexData[offset+3] = lastAlpha[0];
4063 
4064 	if(isLive) {
4065             geomLock.unLock();
4066             sendDataChangedMessage(false);
4067 	}
4068 
4069     }
4070 
4071     /**
4072      * Sets the color associated with the vertex at
4073      * the specified index.
4074      * @param index the vertex index
4075      * @param color an array of 3 or 4 values containing the new color
4076      */
setColor(int index, byte color[])4077     void setColor(int index, byte color[]) {
4078 	int offset = this.stride*index + colorOffset;
4079 
4080 	boolean isLive = source!=null && source.isLive();
4081 	if(isLive) {
4082             geomLock.getLock();
4083 	}
4084 
4085 	dirtyFlag |= COLOR_CHANGED;
4086 	colorChanged = 0xffff;
4087 	this.vertexData[offset]   = (color[0] & 0xff) * ByteToFloatScale;
4088 	this.vertexData[offset+1] = (color[1] & 0xff) * ByteToFloatScale;
4089 	this.vertexData[offset+2] = (color[2] & 0xff) * ByteToFloatScale;
4090 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
4091 	    this.vertexData[offset+3] = ((color[3] & 0xff)* ByteToFloatScale)*lastAlpha[0];
4092         else
4093 	    this.vertexData[offset+3] = lastAlpha[0];
4094 
4095 	if(isLive) {
4096             geomLock.unLock();
4097             sendDataChangedMessage(false);
4098 	}
4099 
4100     }
4101 
4102     /**
4103      * Sets the color associated with the vertex at
4104      * the specified index.
4105      * @param index the vertex index
4106      * @param color a vector containing the new color
4107      */
setColor(int index, Color3f color)4108     void setColor(int index, Color3f color) {
4109 	int offset = this.stride*index + colorOffset;
4110 
4111 	boolean isLive = source!=null && source.isLive();
4112 	if(isLive){
4113             geomLock.getLock();
4114         }
4115 
4116 	dirtyFlag |= COLOR_CHANGED;
4117 	colorChanged = 0xffff;
4118 	this.vertexData[offset]   = color.x;
4119 	this.vertexData[offset+1] = color.y;
4120 	this.vertexData[offset+2] = color.z;
4121         this.vertexData[offset+3] = lastAlpha[0];
4122 
4123 	if(isLive) {
4124             geomLock.unLock();
4125             sendDataChangedMessage(false);
4126 	}
4127 
4128 
4129     }
4130 
4131     /**
4132      * Sets the color associated with the vertex at
4133      * the specified index.
4134      * @param index the vertex index
4135      * @param color a vector containing the new color
4136      */
setColor(int index, Color4f color)4137     void setColor(int index, Color4f color) {
4138 	int offset = this.stride*index + colorOffset;
4139 	boolean isLive = source!=null && source.isLive();
4140 	if(isLive){
4141             geomLock.getLock();
4142 	}
4143 	dirtyFlag |= COLOR_CHANGED;
4144 	colorChanged = 0xffff;
4145 	this.vertexData[offset]   = color.x;
4146 	this.vertexData[offset+1] = color.y;
4147 	this.vertexData[offset+2] = color.z;
4148 	this.vertexData[offset+3] = color.w*lastAlpha[0];
4149 
4150 	if(isLive) {
4151             geomLock.unLock();
4152             sendDataChangedMessage(false);
4153 	}
4154 
4155     }
4156 
4157     /**
4158      * Sets the color associated with the vertex at
4159      * the specified index.
4160      * @param index the vertex index
4161      * @param color a vector containing the new color
4162      */
setColor(int index, Color3b color)4163     void setColor(int index, Color3b color) {
4164 	int offset = this.stride*index + colorOffset;
4165 
4166 	boolean isLive = source!=null && source.isLive();
4167 	if(isLive){
4168             geomLock.getLock();
4169 	}
4170 
4171 	dirtyFlag |= COLOR_CHANGED;
4172 	colorChanged = 0xffff;
4173 	this.vertexData[offset]   = (color.x & 0xff) * ByteToFloatScale;
4174 	this.vertexData[offset+1] = (color.y & 0xff) * ByteToFloatScale;
4175 	this.vertexData[offset+2] = (color.z & 0xff) * ByteToFloatScale;
4176         this.vertexData[offset+3] = lastAlpha[0];
4177 
4178 	if(isLive) {
4179             geomLock.unLock();
4180             sendDataChangedMessage(false);
4181 	}
4182 
4183     }
4184 
4185     /**
4186      * Sets the color associated with the vertex at
4187      * the specified index.
4188      * @param index the vertex index
4189      * @param color a vector containing the new color
4190      */
setColor(int index, Color4b color)4191     void setColor(int index, Color4b color) {
4192 	int offset = this.stride*index + colorOffset;
4193 
4194 	boolean isLive = source!=null && source.isLive();
4195 	if(isLive){
4196             geomLock.getLock();
4197 	}
4198 	dirtyFlag |= COLOR_CHANGED;
4199 	colorChanged = 0xffff;
4200 	this.vertexData[offset]   = (color.x * 0xff) * ByteToFloatScale;
4201 	this.vertexData[offset+1] = (color.y * 0xff) * ByteToFloatScale;
4202 	this.vertexData[offset+2] = (color.z * 0xff) * ByteToFloatScale;
4203 	this.vertexData[offset+3] = ((color.w & 0xff) * ByteToFloatScale)*lastAlpha[0];
4204 
4205 	if(isLive){
4206             geomLock.unLock();
4207             sendDataChangedMessage(false);
4208 	}
4209 
4210     }
4211 
4212     /**
4213      * Sets the colors associated with the vertices starting at
4214      * the specified index.
4215      * @param index the vertex index
4216      * @param colors an array of 3*n or 4*n values containing n new colors
4217      */
setColors(int index, float colors[])4218     void setColors(int index, float colors[]) {
4219 	int offset = this.stride*index + colorOffset;
4220 	int i, j, num = colors.length;
4221 
4222 	boolean isLive = source!=null && source.isLive();
4223 	if(isLive){
4224             geomLock.getLock();
4225 	}
4226 	dirtyFlag |= COLOR_CHANGED;
4227 	colorChanged = 0xffff;
4228 
4229 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
4230 	    {
4231 		for (i=0, j= offset;i < num; i+= 4, j+= this.stride)
4232 		    {
4233 			this.vertexData[j]   = colors[i];
4234 			this.vertexData[j+1] = colors[i+1];
4235 			this.vertexData[j+2] = colors[i+2];
4236 			this.vertexData[j+3] = colors[i+3]*lastAlpha[0];
4237 		    }
4238 	    }
4239 	else
4240 	    {
4241 		for (i=0, j= offset;i < num; i+= 3, j+= this.stride)
4242 		    {
4243 			this.vertexData[j]   = colors[i];
4244 			this.vertexData[j+1] = colors[i+1];
4245 			this.vertexData[j+2] = colors[i+2];
4246 			this.vertexData[j+3] = lastAlpha[0];
4247 		    }
4248 	    }
4249 
4250 	if(isLive) {
4251             geomLock.unLock();
4252             sendDataChangedMessage(false);
4253 	}
4254 
4255     }
4256 
4257     /**
4258      * Sets the colors associated with the vertices starting at
4259      * the specified index.
4260      * @param index the vertex index
4261      * @param colors an array of 3*n or 4*n values containing n new colors
4262      */
setColors(int index, byte colors[])4263     void setColors(int index, byte colors[]) {
4264 	int offset = this.stride*index + colorOffset;
4265 	int i, j, num = colors.length;
4266 
4267 	boolean isLive = source!=null && source.isLive();
4268 	if(isLive){
4269             geomLock.getLock();
4270 	}
4271 	dirtyFlag |= COLOR_CHANGED;
4272 	colorChanged = 0xffff;
4273 
4274 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
4275 	    {
4276 		for (i=0, j= offset;i < num; i+= 4, j+= this.stride)
4277 		    {
4278 			this.vertexData[j]   = (colors[i] & 0xff) * ByteToFloatScale;
4279 			this.vertexData[j+1] = (colors[i+1] & 0xff) * ByteToFloatScale;
4280 			this.vertexData[j+2] = (colors[i+2] & 0xff) * ByteToFloatScale;
4281 			this.vertexData[j+3] = ((colors[i+3] & 0xff) * ByteToFloatScale)*lastAlpha[0];
4282 		    }
4283 	    }
4284 	else
4285 	    {
4286 		for (i=0, j= offset;i < num; i+= 3, j+= this.stride)
4287 		    {
4288 			this.vertexData[j]   = (colors[i] & 0xff) * ByteToFloatScale;
4289 			this.vertexData[j+1] = (colors[i+1] & 0xff) * ByteToFloatScale;
4290 			this.vertexData[j+2] = (colors[i+2] & 0xff) * ByteToFloatScale;
4291 			this.vertexData[j+3] = lastAlpha[0];
4292 		    }
4293 	    }
4294 
4295 
4296 	if(isLive) {
4297             geomLock.unLock();
4298             sendDataChangedMessage(false);
4299 	}
4300 
4301     }
4302 
4303     /**
4304      * Sets the colors associated with the vertices starting at
4305      * the specified index.
4306      * @param index the vertex index
4307      * @param colors an array of vectors containing new colors
4308      */
setColors(int index, Color3f colors[])4309     void setColors(int index, Color3f colors[]) {
4310 	int offset = this.stride*index + colorOffset;
4311 	int i, j, num = colors.length;
4312 
4313 	boolean isLive = source!=null && source.isLive();
4314 	if(isLive){
4315             geomLock.getLock();
4316 	}
4317 	dirtyFlag |= COLOR_CHANGED;
4318 	colorChanged = 0xffff;
4319 
4320 	for (i=0, j= offset;i < num; i++, j+= this.stride)
4321 	    {
4322 		this.vertexData[j]   = colors[i].x;
4323 		this.vertexData[j+1] = colors[i].y;
4324 		this.vertexData[j+2] = colors[i].z;
4325 		this.vertexData[j+3] = lastAlpha[0];
4326 	    }
4327         if(isLive) {
4328             geomLock.unLock();
4329             sendDataChangedMessage(false);
4330         }
4331 
4332     }
4333 
4334     /**
4335      * Sets the colors associated with the vertices starting at
4336      * the specified index.
4337      * @param index the vertex index
4338      * @param colors an array of vectors containing new colors
4339      */
setColors(int index, Color4f colors[])4340     void setColors(int index, Color4f colors[]) {
4341 	int offset = this.stride*index + colorOffset;
4342 	int i, j, num = colors.length;
4343 	boolean isLive = source!=null && source.isLive();
4344 	if(isLive){
4345             geomLock.getLock();
4346 	}
4347 	dirtyFlag |= COLOR_CHANGED;
4348 	colorChanged = 0xffff;
4349 
4350 	for (i=0, j= offset;i < num; i++, j+= this.stride)
4351 	    {
4352 		this.vertexData[j]   = colors[i].x;
4353 		this.vertexData[j+1] = colors[i].y;
4354 		this.vertexData[j+2] = colors[i].z;
4355 		this.vertexData[j+3] = colors[i].w*lastAlpha[0];
4356 	    }
4357         if(isLive) {
4358             geomLock.unLock();
4359             sendDataChangedMessage(false);
4360         }
4361 
4362     }
4363 
4364     /**
4365      * Sets the colors associated with the vertices starting at
4366      * the specified index.
4367      * @param index the vertex index
4368      * @param colors an array of vectors containing new colors
4369      */
setColors(int index, Color3b colors[])4370     void setColors(int index, Color3b colors[]) {
4371 	int offset = this.stride*index + colorOffset;
4372 	int i, j, num = colors.length;
4373 	boolean isLive = source!=null && source.isLive();
4374 	if(isLive){
4375             geomLock.getLock();
4376 	}
4377 	dirtyFlag |= COLOR_CHANGED;
4378 	colorChanged = 0xffff;
4379 	for (i=0, j= offset;i < num; i++, j+= this.stride)
4380 	    {
4381 		this.vertexData[j]   = (colors[i].x & 0xff) * ByteToFloatScale;
4382 		this.vertexData[j+1] = (colors[i].y & 0xff) * ByteToFloatScale;
4383 		this.vertexData[j+2] = (colors[i].z & 0xff) * ByteToFloatScale;
4384 		this.vertexData[j+3] = lastAlpha[0];
4385 	    }
4386 
4387 	if(isLive) {
4388             geomLock.unLock();
4389             sendDataChangedMessage(false);
4390         }
4391     }
4392 
4393 
4394     /**
4395      * Sets the colors associated with the vertices starting at
4396      * the specified index.
4397      * @param index the vertex index
4398      * @param colors an array of vectors containing new colors
4399      */
setColors(int index, Color4b colors[])4400     void setColors(int index, Color4b colors[]) {
4401 	int offset = this.stride*index + colorOffset;
4402 	int i, j, num = colors.length;
4403 
4404 	boolean isLive = source!=null && source.isLive();
4405 	if(isLive){
4406             geomLock.getLock();
4407 	}
4408 	dirtyFlag |= COLOR_CHANGED;
4409 	colorChanged = 0xffff;
4410 
4411 	for (i=0, j= offset;i < num; i++, j+= this.stride)
4412 	    {
4413 		this.vertexData[j]   = (colors[i].x & 0xff) * ByteToFloatScale;
4414 		this.vertexData[j+1] = (colors[i].y & 0xff) * ByteToFloatScale;
4415 		this.vertexData[j+2] = (colors[i].z & 0xff) * ByteToFloatScale;
4416 		this.vertexData[j+3] = ((colors[i].w & 0xff) * ByteToFloatScale)*lastAlpha[0];
4417 	    }
4418 
4419 	if(isLive) {
4420             geomLock.unLock();
4421             sendDataChangedMessage(false);
4422 	}
4423 
4424     }
4425 
4426     /**
4427      * Sets the colors associated with the vertices starting at
4428      * the specified index for this object using data in <code>color</code>s
4429      * starting at index <code>start</code> for <code>length</code> colors.
4430      * @param index the vertex index
4431      * @param colors an array of 3*n or 4*n values containing n new colors
4432      * @param start starting color index of data in <code>colors</code>.
4433      * @param length number of colors to be copied.
4434      */
setColors(int index, float colors[], int start, int length)4435     void setColors(int index, float colors[], int start, int length) {
4436         int offset = this.stride*index + colorOffset;
4437         int i, j;
4438         boolean isLive = source!=null && source.isLive();
4439         if(isLive){
4440             geomLock.getLock();
4441         }
4442 	dirtyFlag |= COLOR_CHANGED;
4443 	colorChanged = 0xffff;
4444 
4445 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
4446             for (i = start * 4, j = offset; i < (start + length) * 4;
4447 		 i += 4, j += this.stride) {
4448                 this.vertexData[j]   = colors[i];
4449                 this.vertexData[j+1] = colors[i+1];
4450                 this.vertexData[j+2] = colors[i+2];
4451                 this.vertexData[j+3] = colors[i+3]*lastAlpha[0];
4452             }
4453         } else {
4454             for (i = start * 3, j = offset; i < (start + length) * 3;
4455 		 i += 3, j += this.stride) {
4456                 this.vertexData[j]   = colors[i];
4457                 this.vertexData[j+1] = colors[i+1];
4458                 this.vertexData[j+2] = colors[i+2];
4459                 this.vertexData[j+3] = lastAlpha[0];
4460             }
4461         }
4462 
4463 	if(isLive) {
4464             geomLock.unLock();
4465             sendDataChangedMessage(false);
4466         }
4467 
4468     }
4469 
4470     /**
4471      * Sets the colors associated with the vertices starting at
4472      * the specified index for this object using data in <code>color</code>s
4473      * starting at index <code>start</code> for <code>length</code> colors.
4474      * @param index the vertex index
4475      * @param colors an array of 3*n or 4*n values containing n new colors
4476      * @param start starting color index of data in <code>colors</code>.
4477      * @param length number of colors to be copied.
4478      */
setColors(int index, byte colors[], int start, int length)4479     void setColors(int index, byte colors[], int start, int length) {
4480         int offset = this.stride*index + colorOffset;
4481         int i, j;
4482 
4483         boolean isLive = source!=null && source.isLive();
4484         if(isLive){
4485             geomLock.getLock();
4486         }
4487 	dirtyFlag |= COLOR_CHANGED;
4488 	colorChanged = 0xffff;
4489 
4490 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
4491             for (i = start * 4, j = offset; i < (start + length) * 4;
4492 		 i += 4, j += this.stride) {
4493                 this.vertexData[j]   = (colors[i] & 0xff) * ByteToFloatScale;
4494                 this.vertexData[j+1] = (colors[i+1] & 0xff) * ByteToFloatScale;
4495                 this.vertexData[j+2] = (colors[i+2] & 0xff) * ByteToFloatScale;
4496                 this.vertexData[j+3] = ((colors[i+3] & 0xff) * ByteToFloatScale)*lastAlpha[0];
4497             }
4498         } else {
4499             for (i = start * 3, j = offset; i < (start + length) * 3;
4500 		 i += 3, j += this.stride) {
4501                 this.vertexData[j]   = (colors[i] & 0xff) * ByteToFloatScale;
4502                 this.vertexData[j+1] = (colors[i+1] & 0xff) * ByteToFloatScale;
4503                 this.vertexData[j+2] = (colors[i+2] & 0xff) * ByteToFloatScale;
4504                 this.vertexData[j+3] = lastAlpha[0];
4505             }
4506         }
4507 
4508         if(isLive) {
4509             geomLock.unLock();
4510 	    sendDataChangedMessage(false);
4511         }
4512 
4513     }
4514 
4515     /**
4516      * Sets the colors associated with the vertices starting at
4517      * the specified index for this object using data in <code>color</code>s
4518      * starting at index <code>start</code> for <code>length</code> colors.
4519      * @param index the vertex index
4520      * @param colors an array of 3*n or 4*n values containing n new colors
4521      * @param start starting color index of data in <code>colors</code>.
4522      * @param length number of colors to be copied.
4523      */
setColors(int index, Color3f colors[], int start, int length)4524     void setColors(int index, Color3f colors[], int start, int length) {
4525         int offset = this.stride*index + colorOffset;
4526         int i, j;
4527         boolean isLive = source!=null && source.isLive();
4528         if(isLive){
4529             geomLock.getLock();
4530         }
4531 	dirtyFlag |= COLOR_CHANGED;
4532 	colorChanged = 0xffff;
4533 
4534 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
4535             this.vertexData[j]   = colors[i].x;
4536             this.vertexData[j+1] = colors[i].y;
4537             this.vertexData[j+2] = colors[i].z;
4538             this.vertexData[j+3] = lastAlpha[0];
4539         }
4540 
4541 	if(isLive) {
4542             geomLock.unLock();
4543             sendDataChangedMessage(false);
4544 	}
4545 
4546     }
4547 
4548     /**
4549      * Sets the colors associated with the vertices starting at
4550      * the specified index for this object using data in <code>color</code>s
4551      * starting at index <code>start</code> for <code>length</code> colors.
4552      * @param index the vertex index
4553      * @param colors an array of 3*n or 4*n values containing n new colors
4554      * @param start starting color index of data in <code>colors</code>.
4555      * @param length number of colors to be copied.
4556      */
setColors(int index, Color4f colors[], int start, int length)4557     void setColors(int index, Color4f colors[], int start, int length) {
4558         int offset = this.stride*index + colorOffset;
4559         int i, j;
4560         boolean isLive = source!=null && source.isLive();
4561         if(isLive){
4562             geomLock.getLock();
4563         }
4564 	dirtyFlag |= COLOR_CHANGED;
4565 	colorChanged = 0xffff;
4566 
4567 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
4568             this.vertexData[j]   = colors[i].x;
4569             this.vertexData[j+1] = colors[i].y;
4570             this.vertexData[j+2] = colors[i].z;
4571             this.vertexData[j+3] = colors[i].w*lastAlpha[0];
4572         }
4573 
4574         if(isLive) {
4575             geomLock.unLock();
4576             sendDataChangedMessage(false);
4577         }
4578 
4579     }
4580 
4581     /**
4582      * Sets the colors associated with the vertices starting at
4583      * the specified index for this object using data in <code>color</code>s
4584      * starting at index <code>start</code> for <code>length</code> colors.
4585      * @param index the vertex index
4586      * @param colors an array of 3*n or 4*n values containing n new colors
4587      * @param start starting color index of data in <code>colors</code>.
4588      * @param length number of colors to be copied.
4589      */
setColors(int index, Color3b colors[], int start, int length)4590     void setColors(int index, Color3b colors[], int start, int length) {
4591         int offset = this.stride*index + colorOffset;
4592         int i, j;
4593         boolean isLive = source!=null && source.isLive();
4594         if(isLive){
4595             geomLock.getLock();
4596         }
4597 	dirtyFlag |= COLOR_CHANGED;
4598 	colorChanged = 0xffff;
4599 
4600 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
4601             this.vertexData[j]   = (colors[i].x & 0xff) * ByteToFloatScale;
4602             this.vertexData[j+1] = (colors[i].y & 0xff) * ByteToFloatScale;
4603             this.vertexData[j+2] = (colors[i].z & 0xff) * ByteToFloatScale;
4604             this.vertexData[j+3] = lastAlpha[0];
4605         }
4606 
4607         if(isLive) {
4608             geomLock.unLock();
4609             sendDataChangedMessage(false);
4610         }
4611 
4612     }
4613 
4614     /**
4615      * Sets the colors associated with the vertices starting at
4616      * the specified index for this object using data in <code>color</code>s
4617      * starting at index <code>start</code> for <code>length</code> colors.
4618      * @param index the vertex index
4619      * @param colors an array of 3*n or 4*n values containing n new colors
4620      * @param start starting color index of data in <code>colors</code>.
4621      * @param length number of colors to be copied.
4622      */
setColors(int index, Color4b colors[], int start, int length)4623     void setColors(int index, Color4b colors[], int start, int length) {
4624         int offset = this.stride*index + colorOffset;
4625         int i, j;
4626         boolean isLive = source!=null && source.isLive();
4627     	if(isLive){
4628             geomLock.getLock();
4629     	}
4630 	dirtyFlag |= COLOR_CHANGED;
4631 	colorChanged = 0xffff;
4632 
4633 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
4634 	    this.vertexData[j]   = (colors[i].x & 0xff) * ByteToFloatScale;
4635 	    this.vertexData[j+1] = (colors[i].y & 0xff) * ByteToFloatScale;
4636 	    this.vertexData[j+2] = (colors[i].z & 0xff) * ByteToFloatScale;
4637 	    this.vertexData[j+3] = ((colors[i].w & 0xff) * ByteToFloatScale)*lastAlpha[0];
4638         }
4639 
4640 	if(isLive) {
4641             geomLock.unLock();
4642             sendDataChangedMessage(false);
4643 	}
4644 
4645     }
4646 
4647     /**
4648      * Sets the normal associated with the vertex at
4649      * the specified index.
4650      * @param index the vertex index
4651      * @param normal the new normal
4652      */
setNormal(int index, float normal[])4653     void setNormal(int index, float normal[]) {
4654 	int offset = this.stride*index + normalOffset;
4655 	boolean isLive = source!=null && source.isLive();
4656 	if(isLive){
4657             geomLock.getLock();
4658 	}
4659 	this.vertexData[offset]   = normal[0];
4660 	this.vertexData[offset+1] = normal[1];
4661 	this.vertexData[offset+2] = normal[2];
4662 
4663         if(isLive) {
4664             geomLock.unLock();
4665             sendDataChangedMessage(false);
4666         }
4667 
4668     }
4669 
4670     /**
4671      * Sets the normal associated with the vertex at
4672      * the specified index.
4673      * @param index the vertex index
4674      * @param normal the vector containing the new normal
4675      */
setNormal(int index, Vector3f normal)4676     void setNormal(int index, Vector3f normal) {
4677 	int offset = this.stride*index + normalOffset;
4678 	boolean isLive = source!=null && source.isLive();
4679 	if(isLive){
4680             geomLock.getLock();
4681 	}
4682 	dirtyFlag |= NORMAL_CHANGED;
4683 	this.vertexData[offset]   = normal.x;
4684 	this.vertexData[offset+1] = normal.y;
4685 	this.vertexData[offset+2] = normal.z;
4686 
4687 	if(isLive){
4688             geomLock.unLock();
4689             sendDataChangedMessage(false);
4690 	}
4691 
4692     }
4693 
4694     /**
4695      * Sets the normals associated with the vertices starting at
4696      * the specified index.
4697      * @param index the vertex index
4698      * @param normals the new normals
4699      */
setNormals(int index, float normals[])4700     void setNormals(int index, float normals[]) {
4701 	int offset = this.stride*index + normalOffset;
4702 	int i, j, num = normals.length;
4703 	boolean isLive = source!=null && source.isLive();
4704 	if(isLive){
4705             geomLock.getLock();
4706 	}
4707 	dirtyFlag |= NORMAL_CHANGED;
4708 	for (i=0, j= offset;i < num;i += 3, j+= this.stride)
4709 	    {
4710 		this.vertexData[j]   = normals[i];
4711 		this.vertexData[j+1] = normals[i+1];
4712 		this.vertexData[j+2] = normals[i+2];
4713 	    }
4714 	if(isLive) {
4715 		geomLock.unLock();
4716 		sendDataChangedMessage(false);
4717 	}
4718 
4719     }
4720 
4721     /**
4722      * Sets the normals associated with the vertices starting at
4723      * the specified index.
4724      * @param index the vertex index
4725      * @param normals the vector containing the new normals
4726      */
setNormals(int index, Vector3f normals[])4727     void setNormals(int index, Vector3f normals[]) {
4728 	int offset = this.stride*index + normalOffset;
4729 	int i, j, num = normals.length;
4730 	boolean isLive = source!=null && source.isLive();
4731 	if(isLive){
4732 	   geomLock.getLock();
4733 	}
4734 	dirtyFlag |= NORMAL_CHANGED;
4735 	for (i=0, j= offset;i < num;i++, j+= this.stride)
4736 	    {
4737 		this.vertexData[j]   = normals[i].x;
4738 		this.vertexData[j+1] = normals[i].y;
4739 		this.vertexData[j+2] = normals[i].z;
4740 	    }
4741 	if(isLive) {
4742             geomLock.unLock();
4743             sendDataChangedMessage(false);
4744 	}
4745 
4746     }
4747 
4748     /**
4749      * Sets the normals associated with the vertices starting at
4750      * the specified index for this object using data in <code>normals</code>
4751      * starting at index <code>start</code> and  ending at index <code>start+length</code>.
4752      * @param index the vertex index
4753      * @param normals the new normals
4754      * @param start starting normal index of data in <code>colors</code>  .
4755      * @param length number of normals to be copied.
4756      */
setNormals(int index, float normals[], int start, int length)4757     void setNormals(int index, float normals[], int start, int length) {
4758         int offset = this.stride*index + normalOffset;
4759         int i, j;
4760         boolean isLive = source!=null && source.isLive();
4761         if(isLive){
4762             geomLock.getLock();
4763         }
4764         dirtyFlag |= NORMAL_CHANGED;
4765 	for (i = start * 3, j = offset; i < (start + length) * 3;
4766 	     i+=3, j += this.stride) {
4767 	    this.vertexData[j]   = normals[i];
4768 	    this.vertexData[j+1] = normals[i+1];
4769 	    this.vertexData[j+2] = normals[i+2];
4770         }
4771 	if(isLive) {
4772             geomLock.unLock();
4773             sendDataChangedMessage(false);
4774         }
4775 
4776     }
4777 
4778     /**
4779      * Sets the normals associated with the vertices starting at
4780      * the specified index for this object using data in <code>normals</code>
4781      * starting at index <code>start</code> and  ending at index <code>start+length</code>.
4782      * @param index the vertex index
4783      * @param normals the new normals
4784      * @param start starting normal index of data in <code>colors</code>  .
4785      * @param length number of normals to be copied.
4786      */
setNormals(int index, Vector3f normals[], int start, int length)4787     void setNormals(int index, Vector3f normals[], int start, int length) {
4788         int offset = this.stride*index + normalOffset;
4789         int i, j;
4790         boolean isLive = source!=null && source.isLive();
4791         if(isLive){
4792             geomLock.getLock();
4793         }
4794         dirtyFlag |= NORMAL_CHANGED;
4795 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
4796 	    this.vertexData[j]   = normals[i].x;
4797 	    this.vertexData[j+1] = normals[i].y;
4798 	    this.vertexData[j+2] = normals[i].z;
4799         }
4800 	if(isLive) {
4801             geomLock.unLock();
4802             sendDataChangedMessage(false);
4803 	}
4804 
4805     }
4806 
4807 
4808     /**
4809      * Sets the texture coordinates associated with the vertices starting at
4810      * the specified index for this object using data in <code>texCoords</code>
4811      * starting at index <code>start</code> and ending at index <code>start+length</code>.
4812      * @param index the vertex index
4813      * @param texCoords the new texture coordinates
4814      * @param start starting texture coordinate index of data in <code>texCoords</code>  .
4815      * @param length number of texture Coordinates to be copied.
4816      */
setTextureCoordinates(int texCoordSet, int index, float texCoords[], int start, int length)4817     void setTextureCoordinates(int texCoordSet, int index, float texCoords[],
4818 				int start, int length) {
4819 
4820 	if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
4821             throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
4822 
4823         if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
4824             throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
4825 
4826 	int offset = this.stride*index + textureOffset +
4827 			texCoordSet * texCoordStride;
4828         int i, j, k;
4829         boolean isLive = source!=null && source.isLive();
4830         if(isLive){
4831             geomLock.getLock();
4832         }
4833 	dirtyFlag |= TEXTURE_CHANGED;
4834 
4835 	if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
4836             for (i = start * 4, j = offset, k = 0; k < length;
4837 		 	j += this.stride, k++) {
4838                 this.vertexData[j]   = texCoords[i++];
4839                 this.vertexData[j+1] = texCoords[i++];
4840                 this.vertexData[j+2] = texCoords[i++];
4841                 this.vertexData[j+3] = texCoords[i++];
4842             }
4843 	} else if ((this.vertexFormat &
4844 			GeometryArray.TEXTURE_COORDINATE_3) != 0) {
4845             for (i = start * 3, j = offset, k = 0; k < length;
4846 		 	j += this.stride, k++) {
4847                 this.vertexData[j]   = texCoords[i++];
4848                 this.vertexData[j+1] = texCoords[i++];
4849                 this.vertexData[j+2] = texCoords[i++];
4850             }
4851         } else {
4852             for (i = start * 2, j = offset, k = 0; k < length;
4853 		 	j += this.stride, k++) {
4854                 this.vertexData[j]   = texCoords[i++];
4855                 this.vertexData[j+1] = texCoords[i++];
4856             }
4857         }
4858 	if(isLive) {
4859             geomLock.unLock();
4860             sendDataChangedMessage(false);
4861 	}
4862 
4863     }
4864 
4865     /**
4866      * Sets the texture coordinates associated with the vertices starting at
4867      * the specified index for this object using data in <code>texCoords</code>
4868      * starting at index <code>start</code> and ending at index <code>start+length</code>.
4869      * @param index the vertex index
4870      * @param texCoords the new texture coordinates
4871      * @param start starting texture coordinate index of data in <code>texCoords</code>  .
4872      * @param length number of texture Coordinates to be copied.
4873      */
setTextureCoordinates(int texCoordSet, int index, Point2f texCoords[], int start, int length)4874     void setTextureCoordinates(int texCoordSet, int index, Point2f texCoords[],
4875 				int start, int length) {
4876 
4877 	if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
4878             throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
4879 
4880         if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
4881             throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
4882 
4883 	int offset = this.stride*index + textureOffset +
4884 			texCoordSet * texCoordStride;
4885         int i, j;
4886 
4887         boolean isLive = source!=null && source.isLive();
4888         if(isLive){
4889             geomLock.getLock();
4890 	}
4891 	dirtyFlag |= TEXTURE_CHANGED;
4892 
4893 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
4894             this.vertexData[j]   = texCoords[i].x;
4895             this.vertexData[j+1] = texCoords[i].y;
4896         }
4897 	if(isLive) {
4898             geomLock.unLock();
4899             sendDataChangedMessage(false);
4900 	}
4901 
4902     }
4903 
4904     /**
4905      * Sets the texture coordinates associated with the vertices starting at
4906      * the specified index for this object using data in <code>texCoords</code>
4907      * starting at index <code>start</code> and ending at index <code>start+length</code>.
4908      * @param index the vertex index
4909      * @param texCoords the new texture coordinates
4910      * @param start starting texture coordinate index of data in <code>texCoords</code>  .
4911      * @param length number of texture Coordinates to be copied.
4912      */
setTextureCoordinates(int texCoordSet, int index, Point3f texCoords[], int start, int length)4913     void setTextureCoordinates(int texCoordSet, int index, Point3f texCoords[],
4914 				int start, int length) {
4915 
4916 	if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
4917             throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
4918 
4919         if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
4920             throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
4921 
4922 	int offset = this.stride*index + textureOffset +
4923 			texCoordSet * texCoordStride;
4924         int i, j;
4925         boolean isLive = source!=null && source.isLive();
4926         if(isLive){
4927             geomLock.getLock();
4928         }
4929 	dirtyFlag |= TEXTURE_CHANGED;
4930 
4931 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
4932             this.vertexData[j]   = texCoords[i].x;
4933             this.vertexData[j+1] = texCoords[i].y;
4934             this.vertexData[j+2] = texCoords[i].z;
4935         }
4936 	if(isLive) {
4937             geomLock.unLock();
4938             sendDataChangedMessage(false);
4939 	}
4940 
4941     }
4942 
4943     /**
4944      * Sets the texture coordinates associated with the vertices starting at
4945      * the specified index for this object using data in <code>texCoords</code>
4946      * starting at index <code>start</code> and ending at index <code>start+length</code>.
4947      * @param index the vertex index
4948      * @param texCoords the new texture coordinates
4949      * @param start starting texture coordinate index of data in <code>texCoords</code>  .
4950      * @param length number of texture Coordinates to be copied.
4951      */
setTextureCoordinates(int texCoordSet, int index, TexCoord2f texCoords[], int start, int length)4952     void setTextureCoordinates(int texCoordSet, int index, TexCoord2f texCoords[],
4953 				int start, int length) {
4954         boolean isLive = source!=null && source.isLive();
4955         if(isLive){
4956             geomLock.getLock();
4957         }
4958         dirtyFlag |= TEXTURE_CHANGED;
4959 	if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
4960             throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
4961 
4962         if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
4963             throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
4964 
4965 	int offset = this.stride*index + textureOffset +
4966 			texCoordSet * texCoordStride;
4967         int i, j;
4968 
4969 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
4970             this.vertexData[j]   = texCoords[i].x;
4971             this.vertexData[j+1] = texCoords[i].y;
4972         }
4973 	if(isLive) {
4974             geomLock.unLock();
4975             sendDataChangedMessage(false);
4976 	}
4977 
4978     }
4979 
4980     /**
4981      * Sets the texture coordinates associated with the vertices starting at
4982      * the specified index for this object using data in <code>texCoords</code>
4983      * starting at index <code>start</code> and ending at index <code>start+length</code>.
4984      * @param index the vertex index
4985      * @param texCoords the new texture coordinates
4986      * @param start starting texture coordinate index of data in <code>texCoords</code>  .
4987      * @param length number of texture Coordinates to be copied.
4988      */
setTextureCoordinates(int texCoordSet, int index, TexCoord3f texCoords[], int start, int length)4989     void setTextureCoordinates(int texCoordSet, int index,
4990 				TexCoord3f texCoords[],
4991 				int start, int length) {
4992         boolean isLive = source!=null && source.isLive();
4993         if(isLive){
4994             geomLock.getLock();
4995         }
4996 	dirtyFlag |= TEXTURE_CHANGED;
4997 
4998 	if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
4999             throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
5000 
5001         if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
5002             throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
5003 
5004 	int offset = this.stride*index + textureOffset +
5005 			texCoordSet * texCoordStride;
5006         int i, j;
5007 
5008 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
5009             this.vertexData[j]   = texCoords[i].x;
5010             this.vertexData[j+1] = texCoords[i].y;
5011             this.vertexData[j+2] = texCoords[i].z;
5012         }
5013 	if(isLive) {
5014             geomLock.unLock();
5015             sendDataChangedMessage(false);
5016 	}
5017     }
5018 
5019     /**
5020      * Sets the texture coordinates associated with the vertices starting at
5021      * the specified index for this object using data in <code>texCoords</code>
5022      * starting at index <code>start</code> and ending at index <code>start+length</code>.
5023      * @param index the vertex index
5024      * @param texCoords the new texture coordinates
5025      * @param start starting texture coordinate index of data in <code>texCoords</code>  .
5026      * @param length number of texture Coordinates to be copied.
5027      */
setTextureCoordinates(int texCoordSet, int index, TexCoord4f texCoords[], int start, int length)5028     void setTextureCoordinates(int texCoordSet, int index,
5029 				TexCoord4f texCoords[],
5030 				int start, int length) {
5031         boolean isLive = source!=null && source.isLive();
5032         if(isLive){
5033             geomLock.getLock();
5034         }
5035 	dirtyFlag |= TEXTURE_CHANGED;
5036 
5037 	if ((this.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
5038             throw new IllegalStateException(J3dI18N.getString("GeometryArray82"));
5039 
5040         if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE ) == 0)
5041             throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray79"));
5042 
5043 	int offset = this.stride*index + textureOffset +
5044 			texCoordSet * texCoordStride;
5045         int i, j;
5046 
5047 	for (i = start, j = offset; i < start+length; i++, j += this.stride) {
5048             this.vertexData[j]   = texCoords[i].x;
5049             this.vertexData[j+1] = texCoords[i].y;
5050             this.vertexData[j+2] = texCoords[i].z;
5051             this.vertexData[j+3] = texCoords[i].w;
5052         }
5053 	if(isLive) {
5054             geomLock.unLock();
5055             sendDataChangedMessage(false);
5056 	}
5057     }
5058 
5059 
5060     /**
5061      * Sets the vertex attribute associated with the vertex at the
5062      * specified index in the specified vertex attribute number for
5063      * this object.
5064      *
5065      * @param vertexAttrNum vertex attribute number in this geometry array
5066      * @param index destination vertex index in this geometry array
5067      * @param vertexAttr the Point2f containing the new vertex attribute
5068      */
setVertexAttr(int vertexAttrNum, int index, Point2f vertexAttr)5069     void setVertexAttr(int vertexAttrNum, int index,
5070 		       Point2f vertexAttr) {
5071 
5072 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5073 	boolean isLive = source!=null && source.isLive();
5074         if(isLive){
5075             geomLock.getLock();
5076         }
5077 	dirtyFlag |= VATTR_CHANGED;
5078 
5079 	this.vertexData[offset] = vertexAttr.x;
5080 	this.vertexData[offset+1] = vertexAttr.y;
5081 
5082         if(isLive) {
5083             geomLock.unLock();
5084             sendDataChangedMessage(false);
5085         }
5086     }
5087 
5088     /**
5089      * Sets the vertex attribute associated with the vertex at the
5090      * specified index in the specified vertex attribute number for
5091      * this object.
5092      *
5093      * @param vertexAttrNum vertex attribute number in this geometry array
5094      * @param index destination vertex index in this geometry array
5095      * @param vertexAttr the Point3f containing the new vertex attribute
5096      */
setVertexAttr(int vertexAttrNum, int index, Point3f vertexAttr)5097     void setVertexAttr(int vertexAttrNum, int index,
5098 		       Point3f vertexAttr) {
5099 
5100 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5101 	boolean isLive = source!=null && source.isLive();
5102         if(isLive){
5103             geomLock.getLock();
5104         }
5105 	dirtyFlag |= VATTR_CHANGED;
5106 
5107 	this.vertexData[offset] = vertexAttr.x;
5108 	this.vertexData[offset+1] = vertexAttr.y;
5109 	this.vertexData[offset+2] = vertexAttr.z;
5110 
5111 	if (isLive) {
5112             geomLock.unLock();
5113             sendDataChangedMessage(false);
5114 	}
5115     }
5116 
5117     /**
5118      * Sets the vertex attribute associated with the vertex at the
5119      * specified index in the specified vertex attribute number for
5120      * this object.
5121      *
5122      * @param vertexAttrNum vertex attribute number in this geometry array
5123      * @param index destination vertex index in this geometry array
5124      * @param vertexAttr the Point4f containing the new vertex attribute
5125      */
setVertexAttr(int vertexAttrNum, int index, Point4f vertexAttr)5126     void setVertexAttr(int vertexAttrNum, int index,
5127 		       Point4f vertexAttr) {
5128 
5129 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5130 	boolean isLive = source!=null && source.isLive();
5131         if(isLive){
5132             geomLock.getLock();
5133         }
5134 	dirtyFlag |= VATTR_CHANGED;
5135 
5136 	this.vertexData[offset] = vertexAttr.x;
5137 	this.vertexData[offset+1] = vertexAttr.y;
5138 	this.vertexData[offset+2] = vertexAttr.z;
5139 	this.vertexData[offset+3] = vertexAttr.w;
5140 
5141         if(isLive) {
5142             geomLock.unLock();
5143             sendDataChangedMessage(false);
5144         }
5145     }
5146 
5147     /**
5148      * Sets the vertex attributes associated with the vertices
5149      * starting at the specified index in the specified vertex
5150      * attribute number for this object using data in
5151      * <code>vertexAttrs</code> starting at index <code>start</code> and
5152      * ending at index <code>start+length</code>.
5153      *
5154      * @param index starting destination vertex index in this geometry array
5155      * @param vertexAttrs source array of 1*n, 2*n, 3*n, or 4*n values
5156      * containing n new vertex attributes
5157      * @param start starting source vertex index in <code>vertexAttrs</code>
5158      * array.
5159      * @param length number of vertex attributes to be copied.
5160      */
setVertexAttrs(int vertexAttrNum, int index, float[] vertexAttrs, int start, int length)5161     void setVertexAttrs(int vertexAttrNum, int index,
5162 			float[] vertexAttrs,
5163 			int start, int length) {
5164 
5165 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5166         int size = vertexAttrSizes[vertexAttrNum];
5167         int i, j, k;
5168         boolean isLive = source!=null && source.isLive();
5169         if(isLive){
5170             geomLock.getLock();
5171         }
5172         dirtyFlag |= VATTR_CHANGED;
5173 
5174         for (i = start * size, j = offset, k = 0; k < length; i += size, j += this.stride, k++) {
5175             for (int ii = 0; ii < size; ii++) {
5176                 this.vertexData[j+ii] = vertexAttrs[i+ii];
5177             }
5178         }
5179 
5180         if(isLive) {
5181             geomLock.unLock();
5182             sendDataChangedMessage(false);
5183         }
5184     }
5185 
5186     /**
5187      * Sets the vertex attributes associated with the vertices
5188      * starting at the specified index in the specified vertex
5189      * attribute number for this object using data in
5190      * <code>vertexAttrs</code> starting at index <code>start</code> and
5191      * ending at index <code>start+length</code>.
5192      *
5193      * @param vertexAttrNum vertex attribute number in this geometry array
5194      * @param index starting destination vertex index in this geometry array
5195      * @param vertexAttrs source array of Point2f objects containing new
5196      * vertex attributes
5197      * @param start starting source vertex index in <code>vertexAttrs</code>
5198      * array.
5199      * @param length number of vertex attributes to be copied.
5200      */
setVertexAttrs(int vertexAttrNum, int index, Point2f[] vertexAttrs, int start, int length)5201     void setVertexAttrs(int vertexAttrNum, int index,
5202 			Point2f[] vertexAttrs,
5203 			int start, int length) {
5204 
5205 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5206         int i, j, k;
5207         boolean isLive = source!=null && source.isLive();
5208         if(isLive){
5209             geomLock.getLock();
5210         }
5211         dirtyFlag |= VATTR_CHANGED;
5212 
5213         for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) {
5214 	    this.vertexData[j] = vertexAttrs[i].x;
5215 	    this.vertexData[j+1] = vertexAttrs[i].y;
5216         }
5217         if(isLive) {
5218             geomLock.unLock();
5219             sendDataChangedMessage(false);
5220         }
5221     }
5222 
5223     /**
5224      * Sets the vertex attributes associated with the vertices
5225      * starting at the specified index in the specified vertex
5226      * attribute number for this object using data in
5227      * <code>vertexAttrs</code> starting at index <code>start</code> and
5228      * ending at index <code>start+length</code>.
5229      *
5230      * @param vertexAttrNum vertex attribute number in this geometry array
5231      * @param index starting destination vertex index in this geometry array
5232      * @param vertexAttrs source array of Point3f objects containing new
5233      * vertex attributes
5234      * @param start starting source vertex index in <code>vertexAttrs</code>
5235      * array.
5236      * @param length number of vertex attributes to be copied.
5237      */
setVertexAttrs(int vertexAttrNum, int index, Point3f[] vertexAttrs, int start, int length)5238     void setVertexAttrs(int vertexAttrNum, int index,
5239 			Point3f[] vertexAttrs,
5240 			int start, int length) {
5241 
5242 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5243         int i, j, k;
5244         boolean isLive = source!=null && source.isLive();
5245         if(isLive){
5246             geomLock.getLock();
5247         }
5248         dirtyFlag |= VATTR_CHANGED;
5249 
5250         for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) {
5251 	    this.vertexData[j] = vertexAttrs[i].x;
5252 	    this.vertexData[j+1] = vertexAttrs[i].y;
5253 	    this.vertexData[j+2] = vertexAttrs[i].z;
5254         }
5255         if(isLive) {
5256             geomLock.unLock();
5257             sendDataChangedMessage(false);
5258         }
5259     }
5260 
5261     /**
5262      * Sets the vertex attributes associated with the vertices
5263      * starting at the specified index in the specified vertex
5264      * attribute number for this object using data in
5265      * <code>vertexAttrs</code> starting at index <code>start</code> and
5266      * ending at index <code>start+length</code>.
5267      *
5268      * @param vertexAttrNum vertex attribute number in this geometry array
5269      * @param index starting destination vertex index in this geometry array
5270      * @param vertexAttrs source array of Point4f objects containing new
5271      * vertex attributes
5272      * @param start starting source vertex index in <code>vertexAttrs</code>
5273      * array.
5274      * @param length number of vertex attributes to be copied.
5275      */
setVertexAttrs(int vertexAttrNum, int index, Point4f[] vertexAttrs, int start, int length)5276     void setVertexAttrs(int vertexAttrNum, int index,
5277 			Point4f[] vertexAttrs,
5278 			int start, int length) {
5279 
5280 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5281         int i, j, k;
5282 
5283         boolean isLive = source!=null && source.isLive();
5284         if(isLive){
5285             geomLock.getLock();
5286         }
5287         dirtyFlag |= VATTR_CHANGED;
5288 
5289         for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) {
5290 	    this.vertexData[j] = vertexAttrs[i].x;
5291 	    this.vertexData[j+1] = vertexAttrs[i].y;
5292 	    this.vertexData[j+2] = vertexAttrs[i].z;
5293 	    this.vertexData[j+3] = vertexAttrs[i].w;
5294         }
5295         if(isLive) {
5296             geomLock.unLock();
5297             sendDataChangedMessage(false);
5298         }
5299     }
5300 
5301 
5302     /**
5303      * Gets the coordinate associated with the vertex at
5304      * the specified index.
5305      * @param index the vertex index
5306      * @param coordinate an array of 3 values that will receive the new coordinate
5307      */
getCoordinate(int index, float coordinate[])5308     void getCoordinate(int index, float coordinate[]) {
5309 	int offset = this.stride*index + coordinateOffset;
5310 
5311 	coordinate[0]= this.vertexData[offset];
5312 	coordinate[1]= this.vertexData[offset+1];
5313 	coordinate[2]= this.vertexData[offset+2];
5314     }
5315 
5316     /**
5317      * Gets the coordinate associated with the vertex at
5318      * the specified index.
5319      * @param index the vertex index
5320      * @param coordinate an array of 3 values that will receive the new coordinate
5321      */
getCoordinate(int index, double coordinate[])5322     void getCoordinate(int index, double coordinate[]) {
5323 	int offset = this.stride*index + coordinateOffset;
5324 
5325 	coordinate[0]= (double)this.vertexData[offset];
5326 	coordinate[1]= (double)this.vertexData[offset+1];
5327 	coordinate[2]= (double)this.vertexData[offset+2];
5328     }
5329 
5330     /**
5331      * Gets the coordinate associated with the vertex at
5332      * the specified index.
5333      * @param index the vertex index
5334      * @param coordinate a vector that will receive the new coordinate
5335      */
getCoordinate(int index, Point3f coordinate)5336     void getCoordinate(int index, Point3f coordinate) {
5337 	int offset = this.stride*index + coordinateOffset;
5338 
5339 	coordinate.x = this.vertexData[offset];
5340 	coordinate.y = this.vertexData[offset+1];
5341 	coordinate.z = this.vertexData[offset+2];
5342     }
5343 
5344     /**
5345      * Gets the coordinate associated with the vertex at
5346      * the specified index.
5347      * @param index the vertex index
5348      * @param coordinate a vector that will receive the new coordinate
5349      */
getCoordinate(int index, Point3d coordinate)5350     void getCoordinate(int index, Point3d coordinate) {
5351 	int offset = this.stride*index + coordinateOffset;
5352 
5353 	coordinate.x = (double)this.vertexData[offset];
5354 	coordinate.y = (double)this.vertexData[offset+1];
5355 	coordinate.z = (double)this.vertexData[offset+2];
5356     }
5357 
5358     /**
5359      * Gets the coordinates associated with the vertices starting at
5360      * the specified index.
5361      * @param index the vertex index
5362      * @param coordinates an array of 3*n values that will receive new coordinates
5363      */
getCoordinates(int index, float coordinates[])5364     void getCoordinates(int index, float coordinates[]) {
5365 	int offset = this.stride*index + coordinateOffset;
5366 	int i, j, num = coordinates.length;
5367 
5368 	for (i=0,j= offset;i < num;i +=3, j += this.stride)
5369 	    {
5370 		coordinates[i]  = this.vertexData[j];
5371 		coordinates[i+1]= this.vertexData[j+1];
5372 		coordinates[i+2]= this.vertexData[j+2];
5373 	    }
5374     }
5375 
5376 
5377     /**
5378      * Gets the coordinates associated with the vertices starting at
5379      * the specified index.
5380      * @param index the vertex index
5381      * @param coordinates an array of 3*n values that will receive new coordinates
5382      */
getCoordinates(int index, double coordinates[])5383     void getCoordinates(int index, double coordinates[]) {
5384 	int offset = this.stride*index + coordinateOffset;
5385 	int i, j, num = coordinates.length;
5386 
5387 	for (i=0,j= offset;i < num;i +=3, j += this.stride)
5388 	    {
5389 		coordinates[i]  = (double)this.vertexData[j];
5390 		coordinates[i+1]= (double)this.vertexData[j+1];
5391 		coordinates[i+2]= (double)this.vertexData[j+2];
5392 	    }
5393     }
5394 
5395     /**
5396      * Gets the coordinates associated with the vertices starting at
5397      * the specified index.
5398      * @param index the vertex index
5399      * @param coordinates an array of vectors that will receive new coordinates
5400      */
getCoordinates(int index, Point3f coordinates[])5401     void getCoordinates(int index, Point3f coordinates[]) {
5402 	int offset = this.stride*index + coordinateOffset;
5403 	int i, j, num = coordinates.length;
5404 
5405 	for (i=0,j= offset;i < num;i++, j += this.stride)
5406 	    {
5407 		coordinates[i].x  = this.vertexData[j];
5408 		coordinates[i].y  = this.vertexData[j+1];
5409 		coordinates[i].z  = this.vertexData[j+2];
5410 	    }
5411     }
5412 
5413     /**
5414      * Gets the coordinates associated with the vertices starting at
5415      * the specified index.
5416      * @param index the vertex index
5417      * @param coordinates an array of vectors that will receive new coordinates
5418      */
getCoordinates(int index, Point3d coordinates[])5419     void getCoordinates(int index, Point3d coordinates[]) {
5420 	int offset = this.stride*index + coordinateOffset;
5421 	int i, j, num = coordinates.length;
5422 
5423 	for (i=0,j= offset;i < num;i++, j += this.stride)
5424 	    {
5425 		coordinates[i].x  = (double)this.vertexData[j];
5426 		coordinates[i].y  = (double)this.vertexData[j+1];
5427 		coordinates[i].z  = (double)this.vertexData[j+2];
5428 	    }
5429     }
5430 
5431     /**
5432      * Gets the color associated with the vertex at
5433      * the specified index.
5434      * @param index the vertex index
5435      * @param color an array of 3 or 4 values that will receive the new color
5436      */
getColor(int index, float color[])5437     void getColor(int index, float color[]) {
5438 	int offset = this.stride*index + colorOffset;
5439 
5440 	color[0]= this.vertexData[offset];
5441 	color[1]= this.vertexData[offset+1];
5442 	color[2]= this.vertexData[offset+2];
5443 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
5444 	    color[3]= this.vertexData[offset+3]/lastAlpha[0];
5445     }
5446 
5447     /**
5448      * Gets the color associated with the vertex at
5449      * the specified index.
5450      * @param index the vertex index
5451      * @param color an array of 3 or 4 values that will receive the new color
5452      */
getColor(int index, byte color[])5453     void getColor(int index, byte color[]) {
5454 	int offset = this.stride*index + colorOffset;
5455 
5456 	color[0]= (byte)(this.vertexData[offset] * FloatToByteScale);
5457 	color[1]= (byte)(this.vertexData[offset+1] * FloatToByteScale);
5458 	color[2]= (byte)(this.vertexData[offset+2] * FloatToByteScale);
5459 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
5460 	    color[3]= (byte)((this.vertexData[offset+3]/lastAlpha[0]) * FloatToByteScale);
5461     }
5462 
5463     /**
5464      * Gets the color associated with the vertex at
5465      * the specified index.
5466      * @param index the vertex index
5467      * @param color a vector that will receive the new color
5468      */
getColor(int index, Color3f color)5469     void getColor(int index, Color3f color) {
5470 	int offset = this.stride*index + colorOffset;
5471 
5472 	color.x = this.vertexData[offset];
5473 	color.y = this.vertexData[offset+1];
5474 	color.z = this.vertexData[offset+2];
5475     }
5476 
5477     /**
5478      * Gets the color associated with the vertex at
5479      * the specified index.
5480      * @param index the vertex index
5481      * @param color a vector that will receive the new color
5482      */
getColor(int index, Color4f color)5483     void getColor(int index, Color4f color) {
5484 	int offset = this.stride*index + colorOffset;
5485 
5486 	color.x = this.vertexData[offset];
5487 	color.y = this.vertexData[offset+1];
5488 	color.z = this.vertexData[offset+2];
5489 	color.w= this.vertexData[offset+3]/lastAlpha[0];
5490     }
5491 
5492     /**
5493      * Gets the color associated with the vertex at
5494      * the specified index.
5495      * @param index the vertex index
5496      * @param color a vector that will receive the new color
5497      */
getColor(int index, Color3b color)5498     void getColor(int index, Color3b color) {
5499 	int offset = this.stride*index + colorOffset;
5500 
5501 	color.x = (byte)(this.vertexData[offset] * FloatToByteScale);
5502 	color.y = (byte)(this.vertexData[offset+1] * FloatToByteScale);
5503 	color.z = (byte)(this.vertexData[offset+2] * FloatToByteScale);
5504     }
5505 
5506     /**
5507      * Gets the color associated with the vertex at
5508      * the specified index.
5509      * @param index the vertex index
5510      * @param color a vector that will receive the new color
5511      */
getColor(int index, Color4b color)5512     void getColor(int index, Color4b color) {
5513 	int offset = this.stride*index + colorOffset;
5514 
5515 	color.x = (byte)(this.vertexData[offset] * FloatToByteScale);
5516 	color.y = (byte)(this.vertexData[offset+1] * FloatToByteScale);
5517 	color.z = (byte)(this.vertexData[offset+2] * FloatToByteScale);
5518 	color.w = (byte)((this.vertexData[offset+3]/lastAlpha[0]) * FloatToByteScale);
5519     }
5520 
5521     /**
5522      * Gets the colors associated with the vertices starting at
5523      * the specified index.
5524      * @param index the vertex index
5525      * @param colors an array of 3*n or 4*n values that will receive n new colors
5526      */
getColors(int index, float colors[])5527     void getColors(int index, float colors[]) {
5528 	int offset = this.stride*index + colorOffset;
5529 	int i, j, num = colors.length;
5530 	float val = 1.0f/lastAlpha[0];
5531 
5532 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
5533 	    {
5534 		for (i=0, j= offset;i < num; i+= 4, j+= this.stride)
5535 		    {
5536 			colors[i]  = this.vertexData[j];
5537 			colors[i+1]= this.vertexData[j+1];
5538 			colors[i+2]= this.vertexData[j+2];
5539 			colors[i+3]= this.vertexData[j+3] * val;
5540 		    }
5541 	    }
5542 	else
5543 	    {
5544 		for (i=0, j= offset;i < num; i+= 3, j+= this.stride)
5545 		    {
5546 			colors[i]  = this.vertexData[j];
5547 			colors[i+1]= this.vertexData[j+1];
5548 			colors[i+2]= this.vertexData[j+2];
5549 		    }
5550 	    }
5551     }
5552 
5553     /**
5554      * Gets the colors associated with the vertices starting at
5555      * the specified index.
5556      * @param index the vertex index
5557      * @param colors an array of 3*n or 4*n values that will receive new colors
5558      */
getColors(int index, byte colors[])5559     void getColors(int index, byte colors[]) {
5560 	int offset = this.stride*index + colorOffset;
5561 	int i, j, num = colors.length;
5562 	float val = 1.0f/lastAlpha[0];
5563 
5564 
5565 	if ((this.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
5566 	    {
5567 		for (i=0, j= offset;i < num; i+= 4, j+= this.stride)
5568 		    {
5569 			colors[i]  = (byte)(this.vertexData[j] * FloatToByteScale);
5570 			colors[i+1]= (byte)(this.vertexData[j+1] * FloatToByteScale);
5571 			colors[i+2]= (byte)(this.vertexData[j+2] * FloatToByteScale);
5572 			colors[i+3]= (byte)((this.vertexData[j+3] * val) * FloatToByteScale);
5573 		    }
5574 	    }
5575 	else
5576 	    {
5577 		for (i=0, j= offset;i < num; i+= 3, j+= this.stride)
5578 		    {
5579 			colors[i]  = (byte)(this.vertexData[j] * FloatToByteScale);
5580 			colors[i+1]= (byte)(this.vertexData[j+1] * FloatToByteScale);
5581 			colors[i+2]= (byte)(this.vertexData[j+2] * FloatToByteScale);
5582 		    }
5583 	    }
5584     }
5585 
5586     /**
5587      * Gets the colors associated with the vertices starting at
5588      * the specified index.
5589      * @param index the vertex index
5590      * @param colors an array of vectors that will receive new colors
5591      */
getColors(int index, Color3f colors[])5592     void getColors(int index, Color3f colors[]) {
5593 	int offset = this.stride*index + colorOffset;
5594 	int i, j, num = colors.length;
5595 
5596 	for (i=0, j= offset;i < num; i++, j+= this.stride)
5597 	    {
5598 		colors[i].x  = this.vertexData[j];
5599 		colors[i].y  = this.vertexData[j+1];
5600 		colors[i].z  = this.vertexData[j+2];
5601 	    }
5602     }
5603 
5604     /**
5605      * Gets the colors associated with the vertices starting at
5606      * the specified index.
5607      * @param index the vertex index
5608      * @param colors an array of vectors that will receive new colors
5609      */
getColors(int index, Color4f colors[])5610     void getColors(int index, Color4f colors[]) {
5611 	int offset = this.stride*index + colorOffset;
5612 	int i, j, num = colors.length;
5613 	float val = 1.0f/lastAlpha[0];
5614 
5615 	for (i=0, j= offset;i < num; i++, j+= this.stride)
5616 	    {
5617 		colors[i].x  = this.vertexData[j];
5618 		colors[i].y  = this.vertexData[j+1];
5619 		colors[i].z  = this.vertexData[j+2];
5620 		colors[i].w  = this.vertexData[j+3] * val;
5621 	    }
5622     }
5623 
5624     /**
5625      * Gets the colors associated with the vertices starting at
5626      * the specified index.
5627      * @param index the vertex index
5628      * @param colors an array of vectors that will receive new colors
5629      */
getColors(int index, Color3b colors[])5630     void getColors(int index, Color3b colors[]) {
5631 	int offset = this.stride*index + colorOffset;
5632 	int i, j, num = colors.length;
5633 
5634 	for (i=0, j= offset;i < num; i++, j+= this.stride)
5635 	    {
5636 		colors[i].x  = (byte)(this.vertexData[j] * FloatToByteScale);
5637 		colors[i].y  = (byte)(this.vertexData[j+1] * FloatToByteScale);
5638 		colors[i].z  = (byte)(this.vertexData[j+2] * FloatToByteScale);
5639 	    }
5640     }
5641 
5642     /**
5643      * Gets the colors associated with the vertices starting at
5644      * the specified index.
5645      * @param index the vertex index
5646      * @param colors an array of vectors that will receive new colors
5647      */
getColors(int index, Color4b colors[])5648     void getColors(int index, Color4b colors[]) {
5649 	int offset = this.stride*index + colorOffset;
5650 	int i, j, num = colors.length;
5651 	float val = 1.0f/lastAlpha[0];
5652 
5653 	for (i=0, j= offset;i < num; i++, j+= this.stride)
5654 	    {
5655 		colors[i].x  = (byte)(this.vertexData[j] * FloatToByteScale);
5656 		colors[i].y  = (byte)(this.vertexData[j+1] * FloatToByteScale);
5657 		colors[i].z  = (byte)(this.vertexData[j+2] * FloatToByteScale);
5658 		colors[i].w  = (byte)(this.vertexData[j+3] * val * FloatToByteScale);
5659 	    }
5660     }
5661 
5662     /**
5663      * Gets the normal associated with the vertex at
5664      * the specified index.
5665      * @param index the vertex index
5666      * @param normal array that will receive the new normal
5667      */
getNormal(int index, float normal[])5668     void getNormal(int index, float normal[]) {
5669 	int offset = this.stride*index + normalOffset;
5670 
5671 	normal[0]= this.vertexData[offset];
5672 	normal[1]= this.vertexData[offset+1];
5673 	normal[2]= this.vertexData[offset+2];
5674     }
5675 
5676     /**
5677      * Gets the normal associated with the vertex at
5678      * the specified index.
5679      * @param index the vertex index
5680      * @param normal the vector that will receive the new normal
5681      */
getNormal(int index, Vector3f normal)5682     void getNormal(int index, Vector3f normal) {
5683 	int offset = this.stride*index + normalOffset;
5684 
5685 	normal.x= this.vertexData[offset];
5686 	normal.y= this.vertexData[offset+1];
5687 	normal.z= this.vertexData[offset+2];
5688     }
5689 
5690     /**
5691      * Gets the normals associated with the vertices starting at
5692      * the specified index.
5693      * @param index the vertex index
5694      * @param normals array that will receive the new normals
5695      */
getNormals(int index, float normals[])5696     void getNormals(int index, float normals[]) {
5697 	int offset = this.stride*index + normalOffset;
5698 	int i, j, num = normals.length;
5699 
5700 	for (i=0, j= offset;i < num;i+=3, j+= this.stride)
5701 	    {
5702 		normals[i]  = this.vertexData[j];
5703 		normals[i+1]= this.vertexData[j+1];
5704 		normals[i+2]= this.vertexData[j+2];
5705 	    }
5706     }
5707 
5708     /**
5709      * Gets the normals associated with the vertices starting at
5710      * the specified index.
5711      * @param index the vertex index
5712      * @param normals the vector that will receive the new normals
5713      */
getNormals(int index, Vector3f normals[])5714     void getNormals(int index, Vector3f normals[]) {
5715 	int offset = this.stride*index + normalOffset;
5716 	int i, j, num = normals.length;
5717 
5718 	for (i=0, j= offset;i < num;i++, j+= this.stride)
5719 	    {
5720 		normals[i].x= this.vertexData[j];
5721 		normals[i].y= this.vertexData[j+1];
5722 		normals[i].z= this.vertexData[j+2];
5723 	    }
5724     }
5725 
5726     /**
5727      * Gets the texture co-ordinate associated with the vertex at
5728      * the specified index.
5729      * @param index the vertex index
5730      * @param texCoord array that will receive the new texture co-ordinate
5731      */
getTextureCoordinate(int texCoordSet, int index, float texCoord[])5732     void getTextureCoordinate(int texCoordSet, int index, float texCoord[]) {
5733 	int offset = this.stride*index + textureOffset +
5734 			texCoordSet * texCoordStride;
5735 
5736 	texCoord[0]= this.vertexData[offset];
5737 	texCoord[1]= this.vertexData[offset+1];
5738 	if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
5739 	    texCoord[2]= this.vertexData[offset+2];
5740 
5741 	} else if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_4)
5742 				!= 0) {
5743 	    texCoord[2]= this.vertexData[offset+2];
5744 	    texCoord[3]= this.vertexData[offset+3];
5745 	}
5746     }
5747 
5748     /**
5749      * Gets the texture co-ordinate associated with the vertex at
5750      * the specified index.
5751      * @param index the vertex index
5752      * @param texCoord the vector that will receive the new texture co-ordinates
5753      */
getTextureCoordinate(int texCoordSet, int index, TexCoord2f texCoord)5754     void getTextureCoordinate(int texCoordSet, int index, TexCoord2f texCoord) {
5755 	int offset = this.stride*index + textureOffset +
5756 			texCoordSet * texCoordStride;
5757 
5758 	texCoord.x= this.vertexData[offset];
5759 	texCoord.y= this.vertexData[offset+1];
5760     }
5761 
5762     /**
5763      * Gets the texture co-ordinate associated with the vertex at
5764      * the specified index.
5765      * @param index the vertex index
5766      * @param texCoord the vector that will receive the new texture co-ordinates
5767      */
getTextureCoordinate(int texCoordSet, int index, TexCoord3f texCoord)5768     void getTextureCoordinate(int texCoordSet, int index, TexCoord3f texCoord) {
5769 	int offset = this.stride*index + textureOffset +
5770 			texCoordSet * texCoordStride;
5771 
5772 	texCoord.x= this.vertexData[offset];
5773 	texCoord.y= this.vertexData[offset+1];
5774 	texCoord.z= this.vertexData[offset+2];
5775     }
5776 
5777     /**
5778      * Gets the texture co-ordinate associated with the vertex at
5779      * the specified index.
5780      * @param index the vertex index
5781      * @param texCoord the vector that will receive the new texture co-ordinates
5782      */
getTextureCoordinate(int texCoordSet, int index, TexCoord4f texCoord)5783     void getTextureCoordinate(int texCoordSet, int index, TexCoord4f texCoord) {
5784 	int offset = this.stride*index + textureOffset +
5785 			texCoordSet * texCoordStride;
5786 
5787 	texCoord.x= this.vertexData[offset];
5788 	texCoord.y= this.vertexData[offset+1];
5789 	texCoord.z= this.vertexData[offset+2];
5790 	texCoord.w= this.vertexData[offset+3];
5791     }
5792 
5793     /**
5794      * Gets the texture co-ordinates associated with the vertices starting at
5795      * the specified index.
5796      * @param index the vertex index
5797      * @param texCoords array that will receive the new texture co-ordinates
5798      */
getTextureCoordinates(int texCoordSet, int index, float texCoords[])5799     void getTextureCoordinates(int texCoordSet, int index, float texCoords[]) {
5800 	int offset = this.stride*index + textureOffset +
5801 			texCoordSet * texCoordStride;
5802 	int i, j, num = texCoords.length;
5803 
5804 	if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
5805 		for (i=0, j= offset;i < num;i+=4, j+= this.stride)
5806 		    {
5807 			texCoords[i]= this.vertexData[j];
5808 			texCoords[i+1]= this.vertexData[j+1];
5809 			texCoords[i+2]= this.vertexData[j+2];
5810 			texCoords[i+3]= this.vertexData[j+3];
5811 		    }
5812 	} else if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE_3)
5813 				!= 0) {
5814 		for (i=0, j= offset;i < num;i+=3, j+= this.stride)
5815 		    {
5816 			texCoords[i]= this.vertexData[j];
5817 			texCoords[i+1]= this.vertexData[j+1];
5818 			texCoords[i+2]= this.vertexData[j+2];
5819 		    }
5820 	} else {
5821 		for (i=0, j= offset;i < num;i+=2, j+= this.stride)
5822 		    {
5823 			texCoords[i]= this.vertexData[j];
5824 			texCoords[i+1]= this.vertexData[j+1];
5825 		    }
5826 	}
5827     }
5828 
5829     /**
5830      * Gets the texture co-ordinates associated with the vertices starting at
5831      * the specified index.
5832      * @param index the vertex index
5833      * @param texCoords the vector that will receive the new texture co-ordinates
5834      */
getTextureCoordinates(int texCoordSet, int index, TexCoord2f texCoords[])5835     void getTextureCoordinates(int texCoordSet, int index,
5836 					TexCoord2f texCoords[]) {
5837 	int offset = this.stride*index + textureOffset +
5838 			texCoordSet * texCoordStride;
5839 	int i, j, num = texCoords.length;
5840 
5841 	for (i=0, j= offset;i < num;i++, j+= this.stride)
5842 	    {
5843 		texCoords[i].x= this.vertexData[j];
5844 		texCoords[i].y= this.vertexData[j+1];
5845 	    }
5846     }
5847 
5848     /**
5849      * Gets the texture co-ordinates associated with the vertices starting at
5850      * the specified index.
5851      * @param index the vertex index
5852      * @param texCoords the vector that will receive the new texture co-ordinates
5853      */
getTextureCoordinates(int texCoordSet, int index, TexCoord3f texCoords[])5854     void getTextureCoordinates(int texCoordSet, int index, TexCoord3f texCoords[]) {
5855 	int offset = this.stride*index + textureOffset +
5856 			texCoordSet * texCoordStride;
5857 	int i, j, num = texCoords.length;
5858 
5859 	for (i=0, j= offset;i < num;i++, j+= this.stride)
5860 	    {
5861 		texCoords[i].x= this.vertexData[j];
5862 		texCoords[i].y= this.vertexData[j+1];
5863 		texCoords[i].z= this.vertexData[j+2];
5864 	    }
5865     }
5866 
5867     /**
5868      * Gets the texture co-ordinates associated with the vertices starting at
5869      * the specified index.
5870      * @param index the vertex index
5871      * @param texCoords the vector that will receive the new texture co-ordinates
5872      */
getTextureCoordinates(int texCoordSet, int index, TexCoord4f texCoords[])5873     void getTextureCoordinates(int texCoordSet, int index, TexCoord4f texCoords[]) {
5874 	int offset = this.stride*index + textureOffset +
5875 			texCoordSet * texCoordStride;
5876 	int i, j, num = texCoords.length;
5877 
5878 	for (i=0, j= offset;i < num;i++, j+= this.stride)
5879 	    {
5880 		texCoords[i].x= this.vertexData[j];
5881 		texCoords[i].y= this.vertexData[j+1];
5882 		texCoords[i].z= this.vertexData[j+2];
5883 		texCoords[i].w= this.vertexData[j+3];
5884 	    }
5885     }
5886 
getTextureCoordinates(int texCoordSet, int index, Point2f texCoords[])5887     void getTextureCoordinates(int texCoordSet, int index,
5888                                         Point2f texCoords[]) {
5889         int offset = this.stride*index + textureOffset +
5890                         texCoordSet * texCoordStride;
5891         int i, j, num = texCoords.length;
5892 
5893         for (i=0, j= offset;i < num;i++, j+= this.stride)
5894             {
5895                 texCoords[i].x= this.vertexData[j];
5896                 texCoords[i].y= this.vertexData[j+1];
5897             }
5898     }
5899 
getTextureCoordinates(int texCoordSet, int index, Point3f texCoords[])5900     void getTextureCoordinates(int texCoordSet, int index, Point3f texCoords[]) {
5901         int offset = this.stride*index + textureOffset +
5902                         texCoordSet * texCoordStride;
5903         int i, j, num = texCoords.length;
5904 
5905         for (i=0, j= offset;i < num;i++, j+= this.stride)
5906             {
5907                 texCoords[i].x= this.vertexData[j];
5908                 texCoords[i].y= this.vertexData[j+1];
5909                 texCoords[i].z= this.vertexData[j+2];
5910             }
5911     }
5912 
5913 
5914     /**
5915      * Gets the vertex attribute associated with the vertex at
5916      * the specified index in the specified vertex attribute number
5917      * for this object.
5918      */
getVertexAttr(int vertexAttrNum, int index, float[] vertexAttr)5919     public void getVertexAttr(int vertexAttrNum, int index,
5920 			      float[] vertexAttr) {
5921 
5922 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5923         int size = vertexAttrSizes[vertexAttrNum];
5924 
5925 	for (int i = 0; i < size; i++) {
5926 	    vertexAttr[i] = this.vertexData[offset+i];
5927 
5928         }
5929 
5930     }
5931 
5932     /**
5933      * Gets the vertex attribute associated with the vertex at
5934      * the specified index in the specified vertex attribute number
5935      * for this object.
5936      */
getVertexAttr(int vertexAttrNum, int index, Point2f vertexAttr)5937     public void getVertexAttr(int vertexAttrNum, int index,
5938 			      Point2f vertexAttr) {
5939 
5940 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5941 
5942 	vertexAttr.x = this.vertexData[offset];
5943 	vertexAttr.y = this.vertexData[offset+1];
5944 
5945     }
5946 
5947     /**
5948      * Gets the vertex attribute associated with the vertex at
5949      * the specified index in the specified vertex attribute number
5950      * for this object.
5951      */
getVertexAttr(int vertexAttrNum, int index, Point3f vertexAttr)5952     public void getVertexAttr(int vertexAttrNum, int index,
5953 			      Point3f vertexAttr) {
5954 
5955 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5956 
5957 	vertexAttr.x = this.vertexData[offset];
5958 	vertexAttr.y = this.vertexData[offset+1];
5959 	vertexAttr.z = this.vertexData[offset+2];
5960 
5961     }
5962 
5963     /**
5964      * Gets the vertex attribute associated with the vertex at
5965      * the specified index in the specified vertex attribute number
5966      * for this object.
5967      */
getVertexAttr(int vertexAttrNum, int index, Point4f vertexAttr)5968     public void getVertexAttr(int vertexAttrNum, int index,
5969 			      Point4f vertexAttr) {
5970 
5971 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5972 
5973 	vertexAttr.x = this.vertexData[offset];
5974 	vertexAttr.y = this.vertexData[offset+1];
5975 	vertexAttr.z = this.vertexData[offset+2];
5976 	vertexAttr.w = this.vertexData[offset+3];
5977 
5978     }
5979 
5980     /**
5981      * Gets the vertex attributes associated with the vertices starting at
5982      * the specified index in the specified vertex attribute number
5983      * for this object.
5984      */
getVertexAttrs(int vertexAttrNum, int index, float[] vertexAttrs)5985     public void getVertexAttrs(int vertexAttrNum, int index,
5986 			       float[] vertexAttrs) {
5987 
5988 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
5989         int size = vertexAttrSizes[vertexAttrNum];
5990         int i, j, k;
5991 
5992         for (i = 0, j = offset;
5993 	     ((i < vertexAttrs.length) && (j < this.vertexData.length)) ;
5994 	     i += size, j += this.stride) {
5995             for (k = 0; k < size; k++) {
5996                 vertexAttrs[i+k] = this.vertexData[j+k];
5997             }
5998         }
5999 
6000     }
6001 
6002     /**
6003      * Gets the vertex attributes associated with the vertices starting at
6004      * the specified index in the specified vertex attribute number
6005      * for this object.
6006      */
getVertexAttrs(int vertexAttrNum, int index, Point2f[] vertexAttrs)6007     public void getVertexAttrs(int vertexAttrNum, int index,
6008 			       Point2f[] vertexAttrs) {
6009 
6010 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
6011         int i, j;
6012 
6013         for (i = 0, j = offset;
6014 	     ((i < vertexAttrs.length) && (j < this.vertexData.length)) ;
6015 	     i++, j += this.stride) {
6016 	    vertexAttrs[i].x = this.vertexData[j];
6017 	    vertexAttrs[i].y = this.vertexData[j+1];
6018         }
6019 
6020     }
6021 
6022     /**
6023      * Gets the vertex attributes associated with the vertices starting at
6024      * the specified index in the specified vertex attribute number
6025      * for this object.
6026      */
getVertexAttrs(int vertexAttrNum, int index, Point3f[] vertexAttrs)6027     public void getVertexAttrs(int vertexAttrNum, int index,
6028 			       Point3f[] vertexAttrs) {
6029 
6030 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
6031         int i, j;
6032 
6033         for (i = 0, j = offset;
6034 	     ((i < vertexAttrs.length) && (j < this.vertexData.length)) ;
6035 	     i++, j += this.stride) {
6036 	    vertexAttrs[i].x = this.vertexData[j];
6037 	    vertexAttrs[i].y = this.vertexData[j+1];
6038 	    vertexAttrs[i].z = this.vertexData[j+2];
6039         }
6040 
6041     }
6042 
6043     /**
6044      * Gets the vertex attributes associated with the vertices starting at
6045      * the specified index in the specified vertex attribute number
6046      * for this object.
6047      */
getVertexAttrs(int vertexAttrNum, int index, Point4f[] vertexAttrs)6048     public void getVertexAttrs(int vertexAttrNum, int index,
6049 			       Point4f[] vertexAttrs) {
6050 
6051 	int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum];
6052         int i, j;
6053 
6054         for (i = 0, j = offset;
6055 	     ((i < vertexAttrs.length) && (j < this.vertexData.length)) ;
6056 	     i++, j += this.stride) {
6057 	    vertexAttrs[i].x = this.vertexData[j];
6058 	    vertexAttrs[i].y = this.vertexData[j+1];
6059 	    vertexAttrs[i].z = this.vertexData[j+2];
6060 	    vertexAttrs[i].w = this.vertexData[j+3];
6061         }
6062 
6063     }
6064 
6065 
6066     /**
6067      * Updates geometry array data.
6068      */
updateData(GeometryUpdater updater)6069     void updateData(GeometryUpdater updater) {
6070 	boolean nullGeo = false;
6071 
6072  	// Add yourself to obtain the geometry lock
6073  	// and Thread.currentThread().sleep until you get the lock
6074  	geomLock.getLock();
6075 
6076 	inUpdater = true;
6077 	updater.updateData((Geometry)source);
6078 	inUpdater = false;
6079 	if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) {
6080 	    if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
6081 		// XXXX: handle the nio buffer
6082 		if (!(this instanceof IndexedGeometryArrayRetained) ||
6083 		    (vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
6084 		    if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
6085 			setupMirrorInterleavedColorPointer(false);
6086 			nullGeo = (interleavedFloatBufferImpl == null);
6087 		    }
6088 		    else {
6089 			setupMirrorColorPointer((vertexType & COLOR_DEFINED), false);
6090 			nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
6091 		    }
6092 		}
6093 	    }
6094 	    else {
6095 		if (!(this instanceof IndexedGeometryArrayRetained) ||
6096 		    (vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
6097 		    if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
6098 			setupMirrorInterleavedColorPointer(false);
6099 			nullGeo = (interLeavedVertexData == null);
6100 		    }
6101 		    else {
6102 			setupMirrorVertexPointer(vertexType & VERTEX_DEFINED);
6103 			setupMirrorColorPointer((vertexType & COLOR_DEFINED), false);
6104 			setupMirrorNormalPointer(vertexType & NORMAL_DEFINED);
6105 			setupMirrorTexCoordPointer(texCoordType);
6106                         setupMirrorVertexAttrPointer(vertexAttrType);
6107 			nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
6108 		    }
6109 		}
6110 	    }
6111 
6112             //NVaidya
6113             // User may or may not have changed indices in updater callback.
6114             // We need to presume that the user may indeed have and, thus, will
6115             // need to recompute maxCoordIndex unconditionally while
6116             // geomLock is still locked.
6117             if ((vertexFormat & GeometryArray.BY_REFERENCE_INDICES) != 0) {
6118                 assert (this instanceof IndexedGeometryArrayRetained);
6119 
6120                 if (((IndexedGeometryArrayRetained)this).getCoordIndicesRef() == null) {
6121                     nullGeo = true;
6122                 }
6123                 ((IndexedGeometryArrayRetained)this).doPostUpdaterUpdate();
6124             }
6125 	}
6126 
6127         dirtyFlag |= VERTEX_CHANGED;
6128 	colorChanged = 0xffff;
6129 	geomLock.unLock();
6130 
6131 	if (source != null && source.isLive()) {
6132 	    processCoordsChanged(nullGeo);
6133 	    sendDataChangedMessage(true);
6134 	}
6135     }
6136 
intersectBoundingBox( Point3d coordinates[], BoundingBox box, double dist[], Point3d iPnt)6137     boolean intersectBoundingBox( Point3d coordinates[],
6138 				  BoundingBox box,
6139 				  double dist[],
6140 				  Point3d iPnt) {
6141 	int i, j;
6142 	int out[] = new int[6];
6143 
6144 	//Do trivial vertex test.
6145 	for(i=0; i<6; i++)
6146 	    out[i] = 0;
6147 	for(i=0; i<coordinates.length; i++) {
6148 	    if((coordinates[i].x >= box.lower.x) && (coordinates[i].x <= box.upper.x) &&
6149 	       (coordinates[i].y >= box.lower.y) && (coordinates[i].y <= box.upper.y) &&
6150 	       (coordinates[i].z >= box.lower.z) && (coordinates[i].z <= box.upper.z))
6151 		// We're done! It's inside the boundingbox.
6152 		return true;
6153 	    else {
6154 		if(coordinates[i].x < box.lower.x)
6155 		    out[0]++; // left
6156 		if(coordinates[i].y < box.lower.y)
6157 		    out[1]++; // bottom
6158 		if(coordinates[i].z < box.lower.z)
6159 		    out[2]++; // back
6160 		if(coordinates[i].x > box.upper.x)
6161 		    out[3]++; // right
6162 		if(coordinates[i].y > box.upper.y)
6163 		    out[4]++; // top
6164 		if(coordinates[i].z > box.upper.z)
6165 		    out[5]++; // front
6166 	    }
6167 
6168 	}
6169 
6170 	if((out[0] == coordinates.length) || (out[1] == coordinates.length) ||
6171 	   (out[2] == coordinates.length) || (out[3] == coordinates.length) ||
6172 	   (out[4] == coordinates.length) || (out[5] == coordinates.length))
6173 	    // we're done. primitive is outside of boundingbox.
6174 	    return false;
6175 
6176 	// Setup bounding planes.
6177 	Point3d pCoor[] = new Point3d[4];
6178 	for(i=0; i<4; i++)
6179 	    pCoor[i] = new Point3d();
6180 
6181 	// left plane.
6182 	pCoor[0].set(box.lower.x, box.lower.y, box.lower.z);
6183 	pCoor[1].set(box.lower.x, box.lower.y, box.upper.z);
6184 	pCoor[2].set(box.lower.x, box.upper.y, box.upper.z);
6185 	pCoor[3].set(box.lower.x, box.upper.y, box.lower.z);
6186 
6187 
6188 	if (intersectPolygon(pCoor, coordinates)) {
6189 	    if (dist != null) {
6190 		computeMinDistance(pCoor, box.getCenter(),
6191 				   null,
6192 				   dist, iPnt);
6193 	    }
6194 	    return true;
6195 	}
6196 
6197 	// right plane.
6198 	pCoor[0].set(box.upper.x, box.lower.y, box.lower.z);
6199 	pCoor[1].set(box.upper.x, box.upper.y, box.lower.z);
6200 	pCoor[2].set(box.upper.x, box.upper.y, box.upper.z);
6201 	pCoor[3].set(box.upper.x, box.lower.y, box.upper.z);
6202 	if (intersectPolygon(pCoor, coordinates)) {
6203 	    if (dist != null) {
6204 		computeMinDistance(pCoor, box.getCenter(),
6205 				   null,
6206 				   dist, iPnt);
6207 	    }
6208 	    return true;
6209 	}
6210 
6211 	// bottom plane.
6212 	pCoor[0].set(box.upper.x, box.lower.y, box.upper.z);
6213 	pCoor[1].set(box.lower.x, box.lower.y, box.upper.z);
6214 	pCoor[2].set(box.lower.x, box.lower.y, box.lower.z);
6215 	pCoor[3].set(box.upper.x, box.lower.y, box.lower.z);
6216 	if (intersectPolygon(pCoor, coordinates)) {
6217 	    if (dist != null) {
6218 		computeMinDistance(pCoor, box.getCenter(),
6219 				   null,
6220 				   dist, iPnt);
6221 	    }
6222 	    return true;
6223 	}
6224 	// top plane.
6225 	pCoor[0].set(box.upper.x, box.upper.y, box.upper.z);
6226 	pCoor[1].set(box.upper.x, box.upper.y, box.lower.z);
6227 	pCoor[2].set(box.lower.x, box.upper.y, box.lower.z);
6228 	pCoor[3].set(box.lower.x, box.upper.y, box.upper.z);
6229 	if (intersectPolygon(pCoor, coordinates)) {
6230 	    if (dist != null) {
6231 		computeMinDistance(pCoor, box.getCenter(),
6232 				   null,
6233 				   dist, iPnt);
6234 	    }
6235 	    return true;
6236 	}
6237 
6238 	// front plane.
6239 	pCoor[0].set(box.upper.x, box.upper.y, box.upper.z);
6240 	pCoor[1].set(box.lower.x, box.upper.y, box.upper.z);
6241 	pCoor[2].set(box.lower.x, box.lower.y, box.upper.z);
6242 	pCoor[3].set(box.upper.x, box.lower.y, box.upper.z);
6243 	if (intersectPolygon(pCoor, coordinates)) {
6244 	    if (dist != null) {
6245 		computeMinDistance(pCoor, box.getCenter(),
6246 				   null,
6247 				   dist, iPnt);
6248 	    }
6249 	    return true;
6250 	}
6251 
6252 	// back plane.
6253 	pCoor[0].set(box.upper.x, box.upper.y, box.lower.z);
6254 	pCoor[1].set(box.upper.x, box.lower.y, box.lower.z);
6255 	pCoor[2].set(box.lower.x, box.lower.y, box.lower.z);
6256 	pCoor[3].set(box.lower.x, box.upper.y, box.lower.z);
6257 	if (intersectPolygon(pCoor, coordinates)) {
6258 	    if (dist != null) {
6259 		computeMinDistance(pCoor, box.getCenter(),
6260 				   null,
6261 				   dist, iPnt);
6262 	    }
6263 	    return true;
6264 	}
6265 	return false;
6266     }
6267 
6268 
intersectBoundingSphere(Point3d coordinates[], BoundingSphere sphere, double dist[], Point3d iPnt)6269     boolean intersectBoundingSphere(Point3d coordinates[],
6270 				    BoundingSphere sphere,
6271 				    double dist[],
6272 				    Point3d iPnt)
6273     {
6274 	int i, j;
6275 	Vector3d tempV3D = new Vector3d();
6276 	boolean esFlag;
6277 
6278 	//Do trivial vertex test.
6279 
6280 	for (i=0; i<coordinates.length; i++) {
6281 	    tempV3D.x = coordinates[i].x - sphere.center.x;
6282 	    tempV3D.y = coordinates[i].y - sphere.center.y;
6283 	    tempV3D.z = coordinates[i].z - sphere.center.z;
6284 
6285 	    if (tempV3D.length() <= sphere.radius) {
6286 		// We're done! It's inside the boundingSphere.
6287 		if (dist != null) {
6288 		    computeMinDistance(coordinates,
6289 				       sphere.getCenter(),
6290 				       null, dist, iPnt);
6291 		}
6292 
6293 		return true;
6294 	    }
6295 	}
6296 
6297 	for (i=0; i<coordinates.length; i++) {
6298 	    if (i < (coordinates.length-1))
6299 		esFlag = edgeIntersectSphere(sphere, coordinates[i],
6300 					     coordinates[i+1]);
6301 	    else
6302 		esFlag = edgeIntersectSphere(sphere, coordinates[i],
6303 					     coordinates[0]);
6304 	    if (esFlag == true) {
6305 		if (dist != null) {
6306 		    computeMinDistance(coordinates,
6307 				       sphere.getCenter(),
6308 				       null,
6309 				       dist, iPnt);
6310 		}
6311 
6312 		return true;
6313 	    }
6314 	}
6315 
6316 
6317 	if (coordinates.length < 3) {
6318 	    return false; // We're done with line.
6319 	}
6320 
6321 	    // Find rho.
6322 	    // Compute plane normal.
6323 	    Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
6324 	    Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
6325 	    Vector3d pNrm = new Vector3d();
6326 	    Vector3d pa = new Vector3d();
6327 	    Point3d q = new Point3d();
6328 	    double nLenSq, pqLen, pNrmDotPa, tq;
6329 
6330 	    // compute plane normal for coordinates.
6331 	    for(i=0; i<coordinates.length-1;) {
6332 		vec0.x = coordinates[i+1].x - coordinates[i].x;
6333 		vec0.y = coordinates[i+1].y - coordinates[i].y;
6334 		vec0.z = coordinates[i+1].z - coordinates[i++].z;
6335 		if(vec0.length() > 0.0)
6336 		    break;
6337 	    }
6338 
6339 	    for(j=i; j<coordinates.length-1; j++) {
6340 		vec1.x = coordinates[j+1].x - coordinates[j].x;
6341 		vec1.y = coordinates[j+1].y - coordinates[j].y;
6342 		vec1.z = coordinates[j+1].z - coordinates[j].z;
6343 		if(vec1.length() > 0.0)
6344 		    break;
6345 	    }
6346 
6347 	    if(j == (coordinates.length-1)) {
6348 		// System.err.println("(1) Degenerate polygon.");
6349 		return false;  // Degenerate polygon.
6350 	    }
6351 
6352 	    /*
6353 	      for(i=0; i<coordinates.length; i++)
6354 	      System.err.println("coordinates P" + i + " " + coordinates[i]);
6355 	      for(i=0; i<coord2.length; i++)
6356 	      System.err.println("coord2 P" + i + " " + coord2[i]);
6357 	      */
6358 
6359 	    pNrm.cross(vec0,vec1);
6360 
6361 	    nLenSq = pNrm.lengthSquared();
6362 	    if( nLenSq == 0.0) {
6363 		// System.err.println("(2) Degenerate polygon.");
6364 		return false;  // Degenerate polygon.
6365 	    }
6366 
6367 	    pa.x = coordinates[0].x - sphere.center.x;
6368 	    pa.y = coordinates[0].y - sphere.center.y;
6369 	    pa.z = coordinates[0].z - sphere.center.z;
6370 
6371 	    pNrmDotPa = pNrm.dot(pa);
6372 
6373 	    pqLen = Math.sqrt(pNrmDotPa * pNrmDotPa/ nLenSq);
6374 
6375 	    if(pqLen > sphere.radius) {
6376 		return false;
6377 	    }
6378 
6379 	    tq = pNrmDotPa / nLenSq;
6380 
6381 	    q.x = sphere.center.x + tq * pNrm.x;
6382 	    q.y = sphere.center.y + tq * pNrm.y;
6383 	    q.z = sphere.center.z + tq * pNrm.z;
6384 
6385 	    // PolyPnt2D Test.
6386 	    if (pointIntersectPolygon2D( pNrm, coordinates, q)) {
6387 		if (dist != null) {
6388 		    computeMinDistance(coordinates,
6389 				       sphere.getCenter(),
6390 				       pNrm,
6391 				       dist, iPnt);
6392 		}
6393 		return true;
6394 	    }
6395 	    return false;
6396 
6397     }
6398 
6399 
intersectBoundingPolytope(Point3d coordinates[], BoundingPolytope polytope, double dist[], Point3d iPnt)6400     boolean intersectBoundingPolytope(Point3d coordinates[],
6401 				      BoundingPolytope polytope,
6402 				      double dist[],
6403 				      Point3d iPnt)
6404     {
6405 	boolean debug = false;
6406 
6407 	Point4d tP4d = new Point4d();
6408 
6409 	// this is a multiplier to the halfplane distance coefficients
6410 	double distanceSign = -1.0;
6411 
6412 	    if(coordinates.length == 2) {
6413 		// we'll handle line separately.
6414 		if (polytope.intersect( coordinates[0],
6415 					coordinates[1], tP4d)) {
6416 		    if (dist != null) {
6417 			iPnt.x = tP4d.x;
6418 			iPnt.y = tP4d.y;
6419 			iPnt.z = tP4d.z;
6420 			Point3d pc = polytope.getCenter();
6421 			double x = iPnt.x - pc.x;
6422 			double y = iPnt.y - pc.y;
6423 			double z = iPnt.z - pc.z;
6424 			dist[0] = Math.sqrt(x*x + y*y + z*z);
6425 		    }
6426 		    return true;
6427 		}
6428 		return false;
6429 	    }
6430 
6431 	    // It is a triangle or a quad.
6432 
6433 	    // first test to see if any of the coordinates are all inside of the
6434 	    // intersection polytope's half planes
6435 	    // essentially do a matrix multiply of the constraintMatrix K*3 with
6436 	    // the input coordinates 3*1 = K*1 vector
6437 
6438 	    if (debug) {
6439 		System.err.println("The value of the input vertices are: ");
6440 		for(int i=0; i < coordinates.length; i++) {
6441 		    System.err.println("The " +i+ " th vertex is: " + coordinates[i]);
6442 		}
6443 
6444 		System.err.println("The value of the input bounding Polytope's planes =");
6445 		for(int i=0; i < polytope.planes.length; i++) {
6446 		    System.err.println("The " +i+ " th plane is: " + polytope.planes[i]);
6447 		}
6448 
6449 	    }
6450 
6451 	    // the direction for the intersection cost function
6452 	    double centers[] = new double[4];
6453 	    centers[0] = 0.8; centers[1] = 0.9; centers[2] = 1.1; centers[3] = 1.2;
6454 
6455 	    boolean intersection = true;
6456 	    boolean PreTest = false;
6457 
6458 	    if(PreTest) {
6459 		// for each coordinate, test it with each half plane
6460 		for( int i=0; i < coordinates.length; i++) {
6461 		    for (int j=0; j < polytope.planes.length; j++) {
6462 			if ( ( polytope.planes[j].x * coordinates[i].x +
6463 			       polytope.planes[j].y * coordinates[i].y +
6464 			       polytope.planes[j].z*coordinates[i].z) <=
6465 			     (distanceSign)*polytope.planes[j].w){
6466 			    // the point satisfies this particular hyperplane
6467 			    intersection = true;
6468 			} else {
6469 			    // the point fails this hyper plane try with a new hyper plane
6470 			    intersection = false;
6471 			    break;
6472 			}
6473 		    }
6474 		    if(intersection) {
6475 			// a point was found to be completely inside the bounding hull
6476 			if (dist != null) {
6477 			    computeMinDistance(coordinates,
6478 					       polytope.getCenter(),
6479 					       null,
6480 					       dist, iPnt);
6481 			}
6482 			return true;
6483 		    }
6484 		}
6485 	    }  // end of pretest
6486 
6487 	    // at this point all points are outside of the bounding hull
6488 	    // build the problem tableau for the linear program
6489 
6490 	    int numberCols = polytope.planes.length + 2 + coordinates.length + 1;
6491 	    int numberRows = 1 + coordinates.length;
6492 
6493 	    double problemTableau[][] = new double[numberRows][numberCols];
6494 
6495 	    // compute -Mtrans = -A*P
6496 
6497 	    for( int i = 0; i < polytope.planes.length; i++) {
6498 		for( int j=0; j < coordinates.length;  j++) {
6499 		    problemTableau[j][i] = (-1.0)* (polytope.planes[i].x*coordinates[j].x+
6500 						    polytope.planes[i].y*coordinates[j].y+
6501 						    polytope.planes[i].z*coordinates[j].z);
6502 		}
6503 	    }
6504 
6505 	    // add the other rows
6506 	    for(int i = 0; i < coordinates.length; i++) {
6507 		problemTableau[i][polytope.planes.length] = -1.0;
6508 		problemTableau[i][polytope.planes.length + 1] =  1.0;
6509 
6510 		for(int j=0; j < coordinates.length; j++) {
6511 		    if ( i==j ) {
6512 			problemTableau[i][j + polytope.planes.length + 2] = 1.0;
6513 		    } else {
6514 			problemTableau[i][j + polytope.planes.length + 2] = 0.0;
6515 		    }
6516 
6517 		    // place the last column elements the Ci's
6518 		    problemTableau[i][numberCols - 1] = centers[i];
6519 		}
6520 	    }
6521 
6522 	    // place the final rows value
6523 	    for(int j = 0; j < polytope.planes.length; j++) {
6524 		problemTableau[numberRows - 1][j] =
6525 		    (distanceSign)*polytope.planes[j].w;
6526 	    }
6527 	    problemTableau[numberRows - 1][polytope.planes.length] =  1.0;
6528 	    problemTableau[numberRows - 1][polytope.planes.length+1] = -1.0;
6529 	    for(int j = 0; j < coordinates.length; j++) {
6530 		problemTableau[numberRows - 1][polytope.planes.length+2+j] = 0.0;
6531 	    }
6532 
6533 	    if(debug) {
6534 		System.err.println("The value of the problem tableau is: " );
6535 		for(int i=0; i < problemTableau.length; i++) {
6536 		    for(int j=0; j < problemTableau[0].length; j++) {
6537 			System.err.print(problemTableau[i][j] + "  ");
6538 		    }
6539 		    System.err.println();
6540 		}
6541 	    }
6542 
6543 	    double distance = generalStandardSimplexSolver(problemTableau,
6544 							   Float.NEGATIVE_INFINITY);
6545 	    if(debug) {
6546 		System.err.println("The value returned by the general standard simplex = " +
6547 				   distance);
6548 	    }
6549 	    if (distance == Float.POSITIVE_INFINITY) {
6550 		return false;
6551 	    }
6552 	    if (dist != null) {
6553 		computeMinDistance(coordinates,
6554 				   polytope.getCenter(),
6555 				   null,
6556 				   dist, iPnt);
6557 	    }
6558 	    return true;
6559 
6560 	}
6561 
6562 
6563     // optimized version using arrays of doubles, but using the standard simplex
6564     // method to solve the LP tableau.  This version has not been optimized to
6565     // work with a particular size input tableau and is much slower than some
6566     // of the other variants...supposedly
generalStandardSimplexSolver(double problemTableau[][], double stopingValue)6567     double generalStandardSimplexSolver(double problemTableau[][],
6568 					double stopingValue) {
6569 	boolean debug = false;
6570 	int numRow = problemTableau.length;
6571 	int numCol = problemTableau[0].length;
6572 	boolean optimal = false;
6573 	int i, pivotRowIndex, pivotColIndex;
6574 	double maxElement, element, endElement, ratio, prevRatio;
6575 	int count = 0;
6576 	double multiplier;
6577 
6578 	if(debug) {
6579 	    System.err.println("The number of rows is : " + numRow);
6580 	    System.err.println("The number of columns is : " + numCol);
6581 	}
6582 
6583 	// until the optimal solution is found continue to do
6584 	// iterations of the simplex method
6585 	while(!optimal) {
6586 
6587 	    if(debug) {
6588 		System.err.println("input problem tableau is:");
6589 		for(int k=0; k < numRow; k++) {
6590 		    for(int j=0; j < numCol; j++) {
6591 			System.err.println("kth, jth value is:" +k+" "+j+" : " +
6592 					   problemTableau[k][j]);
6593 		    }
6594 		}
6595 	    }
6596 
6597 	    // test to see if the current solution is optimal
6598 	    // check all bottom row elements except the right most one and
6599 	    // if all positive or zero its optimal
6600 	    for(i = 0, maxElement = 0, pivotColIndex = -1; i < numCol - 1; i++) {
6601 		// a bottom row element
6602 		element = problemTableau[numRow - 1][i];
6603 		if( element < maxElement) {
6604 		    maxElement = element;
6605 		    pivotColIndex = i;
6606 		}
6607 	    }
6608 
6609 	    // if there is no negative non-zero element then we
6610 	    // have found an optimal solution (the last row of the tableau)
6611 	    if(pivotColIndex == -1) {
6612 		// found an optimal solution
6613 		//System.err.println("Found an optimal solution");
6614 		optimal = true;
6615 	    }
6616 
6617 	    //System.err.println("The value of maxElement is:" + maxElement);
6618 
6619 	    if(!optimal) {
6620 		// Case when the solution is not optimal but not known to be
6621 		// either unbounded or infeasable
6622 
6623 		// from the above we have found the maximum negative element in
6624 		// bottom row, we have also found the column for this value
6625 		// the pivotColIndex represents this
6626 
6627 		// initialize the values for the algorithm, -1 for pivotRowIndex
6628 		// indicates no solution
6629 
6630 		prevRatio = Float.POSITIVE_INFINITY;
6631 		ratio = 0.0;
6632 		pivotRowIndex = -1;
6633 
6634 		// note if all of the elements in the pivot column are zero or
6635 		// negative the problem is unbounded.
6636 		for(i = 0; i < numRow - 1; i++) {
6637 		    element = problemTableau[i][pivotColIndex]; // r value
6638 		    endElement = problemTableau[i][numCol-1]; // s value
6639 
6640 		    // pivot according to the rule that we want to choose the row
6641 		    // with smallest s/r ratio see third case
6642 		    // currently we ignore valuse of r==0 (case 1) and cases where the
6643 		    // ratio is negative, i.e. either r or s are negative (case 2)
6644 		    if(element == 0) {
6645 			if(debug) {
6646 			    System.err.println("Division by zero has occurred");
6647 			    System.err.println("Within the linear program solver");
6648 			    System.err.println("Ignoring the zero as a potential pivot");
6649 			}
6650 		    } else if ( (element < 0.0) || (endElement < 0.0) ){
6651 			if(debug) {
6652 			    System.err.println("Ignoring cases where element is negative");
6653 			    System.err.println("The value of element is: " + element);
6654 			    System.err.println("The value of end Element is: " + endElement);
6655 			}
6656 		    } else {
6657 			ratio = endElement/element;  // should be s/r
6658 			if(debug) {
6659 			    System.err.println("The value of element is: " + element);
6660 			    System.err.println("The value of endElement is: " + endElement);
6661 			    System.err.println("The value of ratio is: " + ratio);
6662 			    System.err.println("The value of prevRatio is: " + prevRatio);
6663 			    System.err.println("Value of ratio <= prevRatio is :" +
6664 					       (ratio <= prevRatio));
6665 			}
6666 			if(ratio <= prevRatio) {
6667 			    if(debug) {
6668 				System.err.println("updating prevRatio with ratio");
6669 			    }
6670 			    prevRatio = ratio;
6671 			    pivotRowIndex = i;
6672 			}
6673 		    }
6674 		}
6675 
6676 		// if the pivotRowIndex is still -1 then we know the pivotColumn
6677 		// has no viable pivot points and the solution is unbounded or
6678 		// infeasable (all pivot elements were either zero or negative or
6679 		// the right most value was negative (the later shouldn't happen?)
6680 		if(pivotRowIndex == -1) {
6681 		    if(debug) {
6682 			System.err.println("UNABLE TO FIND SOLUTION");
6683 			System.err.println("The system is infeasable or unbounded");
6684 		    }
6685 		    return(Float.POSITIVE_INFINITY);
6686 		}
6687 
6688 		// we now have the pivot row and col all that remains is
6689 		// to divide through by this value and subtract the appropriate
6690 		// multiple of the pivot row from all other rows to obtain
6691 		// a tableau which has a column of all zeros and one 1 in the
6692 		// intersection of pivot row and col
6693 
6694 		// divide through by the pivot value
6695 		double pivotValue = problemTableau[pivotRowIndex][pivotColIndex];
6696 
6697 		if(debug) {
6698 		    System.err.println("The value of row index is: " + pivotRowIndex);
6699 		    System.err.println("The value of col index is: " + pivotColIndex);
6700 		    System.err.println("The value of pivotValue is: " + pivotValue);
6701 		}
6702 		// divide through by s on the pivot row to obtain a 1 in pivot col
6703 		for(i = 0; i < numCol; i++) {
6704 		    problemTableau[pivotRowIndex][i] =
6705 			problemTableau[pivotRowIndex][i] / pivotValue;
6706 		}
6707 
6708 		// subtract appropriate multiple of pivot row from all other rows
6709 		// to zero out all rows except the final row and the pivot row
6710 		for(i = 0; i < numRow; i++) {
6711 		    if(i != pivotRowIndex) {
6712 			multiplier = problemTableau[i][pivotColIndex];
6713 			for(int j=0; j < numCol; j++) {
6714 			    problemTableau[i][j] = problemTableau[i][j] -
6715 				multiplier * problemTableau[pivotRowIndex][j];
6716 			}
6717 		    }
6718 		}
6719 	    }
6720 	    // case when the element is optimal
6721 	}
6722 	return(problemTableau[numRow - 1][numCol - 1]);
6723     }
6724 
6725 
6726 
edgeIntersectSphere(BoundingSphere sphere, Point3d start, Point3d end)6727     boolean edgeIntersectSphere(BoundingSphere sphere, Point3d start,
6728 				Point3d end)
6729 	{
6730 	    double abLenSq, acLenSq, apLenSq, abDotAp, radiusSq;
6731 	    Vector3d ab = new Vector3d();
6732 	    Vector3d ap = new Vector3d();
6733 
6734 	    ab.x = end.x - start.x;
6735 	    ab.y = end.y - start.y;
6736 	    ab.z = end.z - start.z;
6737 
6738 	    ap.x = sphere.center.x - start.x;
6739 	    ap.y = sphere.center.y - start.y;
6740 	    ap.z = sphere.center.z - start.z;
6741 
6742 	    abDotAp = ab.dot(ap);
6743 
6744 	    if(abDotAp < 0.0) {
6745 		return false; // line segment points away from sphere.
6746 	    }
6747 
6748 	    abLenSq = ab.lengthSquared();
6749 	    acLenSq = abDotAp * abDotAp / abLenSq;
6750 
6751 	    if(acLenSq < abLenSq) {
6752 		return false; // C doesn't lies between end points of edge.
6753 	    }
6754 
6755 	    radiusSq = sphere.radius * sphere.radius;
6756 	    apLenSq = ap.lengthSquared();
6757 
6758 	    if((apLenSq - acLenSq) <= radiusSq) {
6759 		return true;
6760 	    }
6761 
6762 	    return false;
6763 
6764 	}
6765 
6766 
det2D(Point2d a, Point2d b, Point2d p)6767     double det2D(Point2d a, Point2d b, Point2d p)
6768 	{
6769 	    return (((p).x - (a).x) * ((a).y - (b).y) +
6770 		    ((a).y - (p).y) * ((a).x - (b).x));
6771 	}
6772 
6773     // Assume coord is CCW.
pointIntersectPolygon2D(Vector3d normal, Point3d[] coord, Point3d point)6774     boolean pointIntersectPolygon2D(Vector3d normal, Point3d[] coord,
6775 				    Point3d point)
6776 	{
6777 
6778 	    double  absNrmX, absNrmY, absNrmZ;
6779 	    Point2d coord2D[] = new Point2d[coord.length];
6780 	    Point2d pnt = new Point2d();
6781 
6782 	    int i, j, axis;
6783 
6784 	    // Project 3d points onto 2d plane.
6785 	    // Note : Area of polygon is not preserve in this projection, but
6786 	    // it doesn't matter here.
6787 
6788 	    // Find the axis of projection.
6789 	    absNrmX = Math.abs(normal.x);
6790 	    absNrmY = Math.abs(normal.y);
6791 	    absNrmZ = Math.abs(normal.z);
6792 
6793 	    if(absNrmX > absNrmY)
6794 		axis = 0;
6795 	    else
6796 		axis = 1;
6797 
6798 	    if(axis == 0) {
6799 		if(absNrmX < absNrmZ)
6800 		    axis = 2;
6801 	    }
6802 	    else if(axis == 1) {
6803 		if(absNrmY < absNrmZ)
6804 		    axis = 2;
6805 	    }
6806 
6807 	    // System.err.println("Normal " + normal + " axis " + axis );
6808 
6809 	    for(i=0; i<coord.length; i++) {
6810 		coord2D[i] = new Point2d();
6811 
6812 		switch (axis) {
6813 		case 0:
6814 		    coord2D[i].x = coord[i].y;
6815 		    coord2D[i].y = coord[i].z;
6816 		    break;
6817 
6818 		case 1:
6819 		    coord2D[i].x = coord[i].x;
6820 		    coord2D[i].y = coord[i].z;
6821 		    break;
6822 
6823 		case 2:
6824 		    coord2D[i].x = coord[i].x;
6825 		    coord2D[i].y = coord[i].y;
6826 		    break;
6827 		}
6828 
6829 		// System.err.println("i " + i + " u " + uCoor[i] + " v " + vCoor[i]);
6830 	    }
6831 
6832 
6833 	    switch (axis) {
6834 	    case 0:
6835 		pnt.x = point.y;
6836 		pnt.y = point.z;
6837 		break;
6838 
6839 	    case 1:
6840 		pnt.x = point.x;
6841 		pnt.y = point.z;
6842 		break;
6843 
6844 	    case 2:
6845 		pnt.x = point.x;
6846 		pnt.y = point.y;
6847 		break;
6848 	    }
6849 
6850 	    // Do determinant test.
6851 	    for(j=0; j<coord.length; j++) {
6852 		if(j<(coord.length-1))
6853 		    if(det2D(coord2D[j], coord2D[j+1], pnt)>0.0)
6854 			;
6855 		    else
6856 			return false;
6857 		else
6858 		    if(det2D(coord2D[j], coord2D[0], pnt)>0.0)
6859 			;
6860 		    else
6861 			return false;
6862 	    }
6863 
6864 	    return true;
6865 
6866 	}
6867 
6868 
edgeIntersectPlane(Vector3d normal, Point3d pnt, Point3d start, Point3d end, Point3d iPnt)6869     boolean edgeIntersectPlane(Vector3d normal, Point3d pnt, Point3d start,
6870 			       Point3d end, Point3d iPnt)
6871 	{
6872 
6873 	    Vector3d tempV3d = new Vector3d();
6874 	    Vector3d direction = new Vector3d();
6875 	    double pD, pNrmDotrDir, tr;
6876 
6877 	    // Compute plane D.
6878 	    tempV3d.set((Tuple3d) pnt);
6879 	    pD = normal.dot(tempV3d);
6880 
6881 	    direction.x = end.x - start.x;
6882 	    direction.y = end.y - start.y;
6883 	    direction.z = end.z - start.z;
6884 
6885 	    pNrmDotrDir = normal.dot(direction);
6886 
6887 	    // edge is parallel to plane.
6888 	    if(pNrmDotrDir== 0.0) {
6889 		// System.err.println("Edge is parallel to plane.");
6890 		return false;
6891 	    }
6892 
6893 	    tempV3d.set((Tuple3d) start);
6894 
6895 	    tr = (pD - normal.dot(tempV3d))/ pNrmDotrDir;
6896 
6897 	    // Edge intersects the plane behind the edge's start.
6898 	    // or exceed the edge's length.
6899 	    if((tr < 0.0 ) || (tr > 1.0 )) {
6900 		// System.err.println("Edge intersects the plane behind the start or exceed end.");
6901 		return false;
6902 	    }
6903 
6904 	    iPnt.x = start.x + tr * direction.x;
6905 	    iPnt.y = start.y + tr * direction.y;
6906 	    iPnt.z = start.z + tr * direction.z;
6907 
6908 	    return true;
6909 
6910 	}
6911 
6912     // Assume coord is CCW.
edgeIntersectPolygon2D(Vector3d normal, Point3d[] coord, Point3d[] seg)6913     boolean edgeIntersectPolygon2D(Vector3d normal, Point3d[] coord,
6914 				   Point3d[] seg)
6915 	{
6916 
6917 	    double  absNrmX, absNrmY, absNrmZ;
6918 	    Point2d coord2D[] = new Point2d[coord.length];
6919 	    Point2d seg2D[] = new Point2d[2];
6920 
6921 	    int i, j, axis;
6922 
6923 	    // Project 3d points onto 2d plane.
6924 	    // Note : Area of polygon is not preserve in this projection, but
6925 	    // it doesn't matter here.
6926 
6927 	    // Find the axis of projection.
6928 	    absNrmX = Math.abs(normal.x);
6929 	    absNrmY = Math.abs(normal.y);
6930 	    absNrmZ = Math.abs(normal.z);
6931 
6932 	    if(absNrmX > absNrmY)
6933 		axis = 0;
6934 	    else
6935 		axis = 1;
6936 
6937 	    if(axis == 0) {
6938 		if(absNrmX < absNrmZ)
6939 		    axis = 2;
6940 	    }
6941 	    else if(axis == 1) {
6942 		if(absNrmY < absNrmZ)
6943 		    axis = 2;
6944 	    }
6945 
6946 	    // System.err.println("Normal " + normal + " axis " + axis );
6947 
6948 	    for(i=0; i<coord.length; i++) {
6949 		coord2D[i] = new Point2d();
6950 
6951 		switch (axis) {
6952 		case 0:
6953 		    coord2D[i].x = coord[i].y;
6954 		    coord2D[i].y = coord[i].z;
6955 		    break;
6956 
6957 		case 1:
6958 		    coord2D[i].x = coord[i].x;
6959 		    coord2D[i].y = coord[i].z;
6960 		    break;
6961 
6962 		case 2:
6963 		    coord2D[i].x = coord[i].x;
6964 		    coord2D[i].y = coord[i].y;
6965 		    break;
6966 		}
6967 
6968 		// System.err.println("i " + i + " u " + uCoor[i] + " v " + vCoor[i]);
6969 	    }
6970 
6971 	    for(i=0; i<2; i++) {
6972 		seg2D[i] = new Point2d();
6973 		switch (axis) {
6974 		case 0:
6975 		    seg2D[i].x = seg[i].y;
6976 		    seg2D[i].y = seg[i].z;
6977 		    break;
6978 
6979 		case 1:
6980 		    seg2D[i].x = seg[i].x;
6981 		    seg2D[i].y = seg[i].z;
6982 		    break;
6983 
6984 		case 2:
6985 		    seg2D[i].x = seg[i].x;
6986 		    seg2D[i].y = seg[i].y;
6987 		    break;
6988 		}
6989 
6990 		// System.err.println("i " + i + " u " + uSeg[i] + " v " + vSeg[i]);
6991 	    }
6992 
6993 	    // Do determinant test.
6994 	    boolean pntTest[][] = new boolean[2][coord.length];
6995 	    boolean testFlag;
6996 
6997 	    for(j=0; j<coord.length; j++) {
6998 		for(i=0; i<2; i++) {
6999 		    if(j<(coord.length-1))
7000 			pntTest[i][j] = (det2D(coord2D[j], coord2D[j+1], seg2D[i])<0.0);
7001 		    else
7002 			pntTest[i][j] = (det2D(coord2D[j], coord2D[0], seg2D[i])<0.0);
7003 		}
7004 
7005 		if((pntTest[0][j]==false) && (pntTest[1][j]==false))
7006 		    return false;
7007 	    }
7008 
7009 	    testFlag = true;
7010 	    for(i=0; i<coord.length; i++) {
7011 		if(pntTest[0][i]==false) {
7012 		    testFlag = false;
7013 		    break;
7014 		}
7015 	    }
7016 
7017 	    if(testFlag == true)
7018 		return true; // start point is inside polygon.
7019 
7020 	    testFlag = true;
7021 	    for(i=0; i<coord.length; i++) {
7022 		if(pntTest[1][i]==false) {
7023 		    testFlag = false;
7024 		    break;
7025 		}
7026 	    }
7027 
7028 	    if(testFlag == true)
7029 		return true; // end point is inside polygon.
7030 
7031 
7032 	    int cnt = 0;
7033 	    for(i=0; i<coord.length; i++) {
7034 		if(det2D(seg2D[0], seg2D[1], coord2D[i])<0.0)
7035 		    cnt++;
7036 	    }
7037 
7038 	    if((cnt==0)||(cnt==coord.length))
7039 		return false;
7040 
7041 	    return true;
7042 
7043 	}
7044 
7045 
7046     // New stuffs .....
getCompValue(Point3d v, int i)7047     double getCompValue(Point3d v, int i) {
7048 	switch (i) {
7049 	case 0: return v.x;
7050 	case 1: return v.y;
7051 	}
7052 	// Has to return something, so set the default to z component.
7053 	return v.z;
7054     }
7055 
getCompValue(Point3d v0, Point3d v1, int i)7056     double getCompValue(Point3d v0, Point3d v1, int i) {
7057 	switch (i) {
7058 	case 0: return (v0.x - v1.x);
7059 	case 1: return (v0.y - v1.y);
7060 	}
7061 	// Has to return some, so set the default to z component.
7062 	return (v0.z - v1.z);
7063     }
7064 
7065 
pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2, Vector3d normal)7066     boolean pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2,
7067 		       Vector3d normal) {
7068 
7069 	double nAbsX, nAbsY, nAbsZ;
7070 	int i0, i1;
7071 
7072 	// first project onto an axis-aligned plane, that maximizes the area
7073 	// of the triangles, compute indices i0, i1.
7074 	nAbsX = Math.abs(normal.x);
7075 	nAbsY = Math.abs(normal.y);
7076 	nAbsZ = Math.abs(normal.z);
7077 
7078 	if (nAbsX > nAbsY) {
7079 	    if(nAbsX > nAbsZ) {
7080 		i0 = 1; //  nAbsX is greatest.
7081 		i1 = 2;
7082 	    }
7083 	    else {
7084 		i0 = 0; //  nAbsZ is greatest.
7085 		i1 = 1;
7086 	    }
7087 	} else { // nAbsX <= nAbsY
7088 	    if(nAbsZ > nAbsY) {
7089 		i0 = 0;  //  nAbsZ is greatest.
7090 		i1 = 1;
7091 	    }
7092 	    else {
7093 		i0 = 0; //  nAbsY is greatest.
7094 		i1 = 2;
7095 	    }
7096 	}
7097 	return pointInTri(v0, u0,  u1, u2, i0,  i1);
7098     }
7099 
pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2, int i0, int i1)7100     boolean pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2,
7101 		       int i0, int i1) {
7102 
7103 	double a, b, c, d0, d1, d2;
7104 	// is T1 completely inside T2 ?
7105 	// check if v0 is inside tri(u0,u1,u2)
7106 
7107 	a = getCompValue(u1, u0, i1);
7108 	b = -(getCompValue(u1, u0, i0));
7109 	c = -a * getCompValue(u0, i0) - b * getCompValue(u0, i1);
7110 	d0 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
7111 
7112 	a = getCompValue(u2, u1, i1);
7113 	b = -(getCompValue(u2, u1, i0));
7114 	c = -a * getCompValue(u1, i0) - b * getCompValue(u1, i1);
7115 	d1 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
7116 
7117 	a = getCompValue(u0, u2, i1);
7118 	b = -(getCompValue(u0, u2, i0));
7119 	c = -a * getCompValue(u2, i0) - b * getCompValue(u2, i1);
7120 	d2 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
7121 
7122 	if(d0*d1>0.0) {
7123 	    if(d0*d2>0.0) {
7124 		return true;
7125 	    }
7126 	}
7127 	return false;
7128     }
7129 
7130 
7131     // this edge to edge test is based on Franlin Antonio's gem:
7132     // "Faster line segment intersection", in Graphics Gems III, pp 199-202
edgeAgainstEdge(Point3d v0, Point3d u0, Point3d u1, double aX, double aY, int i0, int i1)7133     boolean edgeAgainstEdge(Point3d v0, Point3d u0, Point3d u1, double aX, double aY,
7134 			    int i0, int i1) {
7135 	double bX, bY, cX, cY, e, d, f;
7136 
7137 	bX = getCompValue(u0, u1,i0);
7138 	bY = getCompValue(u0, u1, i1);
7139 	cX = getCompValue(v0, u0, i0);
7140 	cY = getCompValue(v0, u0, i1);
7141 
7142 	f = aY * bX - aX * bY;
7143 	d = bY * cX - bX * cY;
7144 	if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f)) {
7145 	    e = aX * cY - aY * cX;
7146 	    if(f>0) {
7147 		if(e>=0 && e<=f)
7148 		    return true;
7149 	    }
7150 	    else {
7151 		if(e<=0 && e>=f)
7152 		    return true;
7153 	    }
7154 	}
7155 
7156 	return false;
7157     }
7158 
7159 
edgeAgainstTriEdges(Point3d v0, Point3d v1, Point3d u0, Point3d u1, Point3d u2, int i0, int i1)7160     boolean edgeAgainstTriEdges(Point3d v0, Point3d v1, Point3d u0,
7161 				Point3d u1, Point3d u2, int i0, int i1) {
7162 	double aX, aY;
7163 
7164 	// aX = v1[i0] - v0[i0];
7165 	// aY = v1[i1] - v0[i1];
7166 	aX = getCompValue(v1, v0, i0);
7167 	aY = getCompValue(v1, v0, i1);
7168 
7169 	// test edge u0, u1 against v0, v1
7170 	if(edgeAgainstEdge(v0, u0, u1, aX, aY, i0, i1))
7171 	    return true;
7172 	// test edge u1, u2 against v0, v1
7173 	if(edgeAgainstEdge(v0, u1, u2, aX, aY, i0, i1))
7174 	    return true;
7175 	// test edge u2, u0 against v0, v1
7176 	if(edgeAgainstEdge(v0, u2, u0, aX, aY, i0, i1))
7177 	    return true;
7178 
7179 	return false;
7180 
7181     }
7182 
coplanarTriTri(Vector3d normal, Point3d v0, Point3d v1, Point3d v2, Point3d u0, Point3d u1, Point3d u2)7183     boolean coplanarTriTri(Vector3d normal, Point3d v0, Point3d v1, Point3d v2,
7184 			   Point3d u0, Point3d u1, Point3d u2) {
7185 
7186 	double nAbsX, nAbsY, nAbsZ;
7187 	int i0, i1;
7188 
7189 	// first project onto an axis-aligned plane, that maximizes the area
7190 	// of the triangles, compute indices i0, i1.
7191 	nAbsX = Math.abs(normal.x);
7192 	nAbsY = Math.abs(normal.y);
7193 	nAbsZ = Math.abs(normal.z);
7194 
7195 	if(nAbsX > nAbsY) {
7196 	    if(nAbsX > nAbsZ) {
7197 		i0 = 1; //  nAbsX is greatest.
7198 		i1 = 2;
7199 	    }
7200 	    else {
7201 		i0 = 0; //  nAbsZ is greatest.
7202 		i1 = 1;
7203 	    }
7204 	}
7205 	else { // nAbsX <= nAbsY
7206 	    if(nAbsZ > nAbsY) {
7207 		i0 = 0;  //  nAbsZ is greatest.
7208 		i1 = 1;
7209 	    }
7210 	    else {
7211 		i0 = 0; //  nAbsY is greatest.
7212 		i1 = 2;
7213 	    }
7214 	}
7215 
7216 	// test all edges of triangle 1 against the edges of triangle 2
7217 	if(edgeAgainstTriEdges(v0, v1, u0, u1, u2, i0, i1))
7218 	    return true;
7219 
7220 	if(edgeAgainstTriEdges(v1, v2, u0, u1, u2, i0, i1))
7221 	    return true;
7222 
7223 	if(edgeAgainstTriEdges(v2, v0, u0, u1, u2, i0, i1))
7224 	    return true;
7225 
7226 	// finally, test if tri1 is totally contained in tri2 or vice versa.
7227 	if(pointInTri(v0, u0, u1, u2, i0, i1))
7228 	    return true;
7229 
7230 	if(pointInTri(u0, v0, v1, v2, i0, i1))
7231 	    return true;
7232 
7233 	return false;
7234     }
7235 
7236 
7237 
7238 
7239 
intersectTriPnt(Point3d v0, Point3d v1, Point3d v2, Point3d u)7240     boolean intersectTriPnt(Point3d v0, Point3d v1, Point3d v2, Point3d u) {
7241 
7242 	Vector3d e1 = new Vector3d();
7243 	Vector3d e2 = new Vector3d();
7244 	Vector3d n1 = new Vector3d();
7245 	Vector3d tempV3d = new Vector3d();
7246 
7247 	double d1, du;
7248 
7249 	// compute plane equation of triange(coord1)
7250 	e1.x = v1.x - v0.x;
7251 	e1.y = v1.y - v0.y;
7252 	e1.z = v1.z - v0.z;
7253 
7254 	e2.x = v2.x - v0.x;
7255 	e2.y = v2.y - v0.y;
7256 	e2.z = v2.z - v0.z;
7257 
7258 	n1.cross(e1,e2);
7259 
7260 	if(n1.length() == 0.0) {
7261 	    // System.err.println("(1) Degenerate triangle.");
7262 	    return false;  // Degenerate triangle.
7263 	}
7264 
7265 	tempV3d.set((Tuple3d) v0);
7266 	d1 = - n1.dot(tempV3d); // plane equation 1: n1.x + d1 = 0
7267 
7268 	// put u to compute signed distance to the plane.
7269 	tempV3d.set((Tuple3d) u);
7270 	du = n1.dot(tempV3d) + d1;
7271 
7272 	// coplanarity robustness check
7273 	if(Math.abs(du)<EPS) du = 0.0;
7274 
7275 	// no intersection occurs
7276 	if(du != 0.0) {
7277 	    return false;
7278 	}
7279 
7280 	double nAbsX, nAbsY, nAbsZ;
7281 	int i0, i1;
7282 
7283 	// first project onto an axis-aligned plane, that maximizes the area
7284 	// of the triangles, compute indices i0, i1.
7285 	nAbsX = Math.abs(n1.x);
7286 	nAbsY = Math.abs(n1.y);
7287 	nAbsZ = Math.abs(n1.z);
7288 
7289 	if(nAbsX > nAbsY) {
7290 	    if(nAbsX > nAbsZ) {
7291 		i0 = 1; //  nAbsX is greatest.
7292 		i1 = 2;
7293 	    }
7294 	    else {
7295 		i0 = 0; //  nAbsZ is greatest.
7296 		i1 = 1;
7297 	    }
7298 	}
7299 	else { // nAbsX <= nAbsY
7300 	    if(nAbsZ > nAbsY) {
7301 		i0 = 0;  //  nAbsZ is greatest.
7302 		i1 = 1;
7303 	    }
7304 	    else {
7305 		i0 = 0; //  nAbsY is greatest.
7306 		i1 = 2;
7307 	    }
7308 	}
7309 
7310 
7311 	// finally, test if u is totally contained in tri.
7312 	if(pointInTri(u, v0, v1, v2, i0, i1)) {
7313 	    return true;
7314 	}
7315 
7316 	return false;
7317     }
7318 
7319 
7320     /**
7321      * Return flag indicating whether two triangles intersect.  This
7322      * uses Tomas Moller's code for fast triangle-triangle
7323      * intersection from his "Real-Time Rendering" book.
7324      *
7325      * The code is now divisionless. It tests for separating by planes
7326      * parallel to either triangle.  If neither separate the
7327      * triangles, then two cases are considered. First case is if the
7328      * normals to the triangles are parallel. In that case, the
7329      * triangles are coplanar and a sequence of tests are made to see
7330      * if edges of each triangle intersect the other triangle. If the
7331      * normals are not parallel, then the two triangles can intersect
7332      * only on the line of intersection of the two planes. The
7333      * intervals of intersection of the triangles with the line of
7334      * intersection of the two planes are computed and tested for
7335      * overlap.
7336      */
intersectTriTri(Point3d v0, Point3d v1, Point3d v2, Point3d u0, Point3d u1, Point3d u2)7337     boolean intersectTriTri(Point3d v0, Point3d v1, Point3d v2,
7338 			    Point3d u0, Point3d u1, Point3d u2) {
7339 
7340 	// System.err.println("In intersectTriTri ...");
7341 	Vector3d e1 = new Vector3d();
7342 	Vector3d e2 = new Vector3d();
7343 	Vector3d n1 = new Vector3d();
7344 	Vector3d n2 = new Vector3d();
7345 	Vector3d tempV3d = new Vector3d();
7346 
7347 	double d1, d2;
7348 	double du0, du1, du2, dv0, dv1, dv2;
7349 	double du0du1, du0du2, dv0dv1, dv0dv2;
7350 	int index;
7351 	double vp0=0.0, vp1=0.0, vp2=0.0;
7352 	double up0=0.0, up1=0.0, up2=0.0;
7353 	double bb, cc, max;
7354 
7355 	// compute plane equation of triange(coord1)
7356 	e1.x = v1.x - v0.x;
7357 	e1.y = v1.y - v0.y;
7358 	e1.z = v1.z - v0.z;
7359 
7360 	e2.x = v2.x - v0.x;
7361 	e2.y = v2.y - v0.y;
7362 	e2.z = v2.z - v0.z;
7363 
7364 	n1.cross(e1,e2);
7365 
7366 	if(n1.length() == 0.0) {
7367 	    // System.err.println("(1) Degenerate triangle.");
7368 	    return false;  // Degenerate triangle.
7369 	}
7370 
7371 	tempV3d.set((Tuple3d) v0);
7372 	d1 = - n1.dot(tempV3d); // plane equation 1: n1.x + d1 = 0
7373 
7374 	// put u0, u1, and u2 into plane equation 1
7375 	// to compute signed distance to the plane.
7376 	tempV3d.set((Tuple3d) u0);
7377 	du0 = n1.dot(tempV3d) + d1;
7378 	tempV3d.set((Tuple3d) u1);
7379 	du1 = n1.dot(tempV3d) + d1;
7380 	tempV3d.set((Tuple3d) u2);
7381 	du2 = n1.dot(tempV3d) + d1;
7382 
7383 	// coplanarity robustness check
7384 	if(Math.abs(du0)<EPS) du0 = 0.0;
7385 	if(Math.abs(du1)<EPS) du1 = 0.0;
7386 	if(Math.abs(du2)<EPS) du2 = 0.0;
7387 
7388 	du0du1 = du0 * du1;
7389 	du0du2 = du0 * du2;
7390 
7391 	// same sign on all of them + not equal 0 ?
7392 	// no intersection occurs
7393 	if(du0du1>0.0 && du0du2>0.0) {
7394 	    // System.err.println("In intersectTriTri : du0du1>0.0 && du0du2>0.0");
7395 	    return false;
7396 	}
7397 
7398 	// compute plane of triangle(coord2)
7399 	e1.x = u1.x - u0.x;
7400 	e1.y = u1.y - u0.y;
7401 	e1.z = u1.z - u0.z;
7402 
7403 	e2.x = u2.x - u0.x;
7404 	e2.y = u2.y - u0.y;
7405 	e2.z = u2.z - u0.z;
7406 
7407 	n2.cross(e1,e2);
7408 
7409 	if(n2.length() == 0.0) {
7410 	    // System.err.println("(2) Degenerate triangle.");
7411 	    return false;  // Degenerate triangle.
7412 	}
7413 
7414 	tempV3d.set((Tuple3d) u0);
7415 	d2 = - n2.dot(tempV3d); // plane equation 2: n2.x + d2 = 0
7416 
7417 	// put v0, v1, and v2 into plane equation 2
7418 	// to compute signed distance to the plane.
7419 	tempV3d.set((Tuple3d) v0);
7420 	dv0 = n2.dot(tempV3d) + d2;
7421 	tempV3d.set((Tuple3d) v1);
7422 	dv1 = n2.dot(tempV3d) + d2;
7423 	tempV3d.set((Tuple3d) v2);
7424 	dv2 = n2.dot(tempV3d) + d2;
7425 
7426 	// coplanarity robustness check
7427 	if(Math.abs(dv0)<EPS) dv0 = 0.0;
7428 	if(Math.abs(dv1)<EPS) dv1 = 0.0;
7429 	if(Math.abs(dv2)<EPS) dv2 = 0.0;
7430 
7431 	dv0dv1 = dv0 * dv1;
7432 	dv0dv2 = dv0 * dv2;
7433 
7434 	// same sign on all of them + not equal 0 ?
7435 	// no intersection occurs
7436 	if(dv0dv1>0.0 && dv0dv2>0.0) {
7437 	    // System.err.println("In intersectTriTri : dv0dv1>0.0 && dv0dv2>0.0");
7438 	    return false;
7439 	}
7440 	// compute direction of intersection line.
7441 	tempV3d.cross(n1, n2);
7442 
7443 	// compute and index to the largest component of tempV3d.
7444 	max = Math.abs(tempV3d.x);
7445 	index = 0;
7446 	bb = Math.abs(tempV3d.y);
7447 	cc = Math.abs(tempV3d.z);
7448 	if(bb>max) {
7449 	    max=bb;
7450 	    index=1;
7451 	}
7452 	if(cc>max) {
7453 	    max=cc;
7454 	    index=2;
7455 	}
7456 
7457 	// this is the simplified projection onto L.
7458 
7459 	switch (index) {
7460 	case 0:
7461 	    vp0 = v0.x;
7462 	    vp1 = v1.x;
7463 	    vp2 = v2.x;
7464 
7465 	    up0 = u0.x;
7466 	    up1 = u1.x;
7467 	    up2 = u2.x;
7468 	    break;
7469 	case 1:
7470 	    vp0 = v0.y;
7471 	    vp1 = v1.y;
7472 	    vp2 = v2.y;
7473 
7474 	    up0 = u0.y;
7475 	    up1 = u1.y;
7476 	    up2 = u2.y;
7477 	    break;
7478 	case 2:
7479 	    vp0 = v0.z;
7480 	    vp1 = v1.z;
7481 	    vp2 = v2.z;
7482 
7483 	    up0 = u0.z;
7484 	    up1 = u1.z;
7485 	    up2 = u2.z;
7486 	    break;
7487 	}
7488 
7489 	// compute intereval for triangle 1.
7490 	double a=0.0, b=0.0, c=0.0, x0=0.0, x1=0.0;
7491 	if(dv0dv1>0.0) {
7492 	    // here we know that dv0dv2 <= 0.0 that is dv0 and dv1 are on the same side,
7493 	    // dv2 on the other side or on the plane.
7494 	    a = vp2; b = (vp0 - vp2) * dv2; c = (vp1 - vp2) * dv2;
7495 	    x0 = dv2 - dv0; x1 = dv2 - dv1;
7496 	}
7497 	else if(dv0dv2>0.0) {
7498 	    // here we know that dv0dv1<=0.0
7499 	    a = vp1; b = (vp0 - vp1) * dv1; c = (vp2 - vp1) * dv1;
7500 	    x0 = dv1 - dv0; x1 = dv1 - dv2;
7501 	}
7502 	else if((dv1*dv2>0.0) || (dv0 != 0.0)) {
7503 	    // here we know that dv0vd1<=0.0 or that dv0!=0.0
7504 	    a = vp0; b = (vp1 - vp0) * dv0; c = (vp2 - vp0) * dv0;
7505 	    x0 = dv0 - dv1; x1 = dv0 - dv2;
7506 	}
7507 	else if(dv1 != 0.0) {
7508 	    a = vp1; b = (vp0 - vp1) * dv1; c = (vp2 - vp1) * dv1;
7509 	    x0 = dv1 - dv0; x1 = dv1 - dv2;
7510 	}
7511 	else if(dv2 != 0.0) {
7512 	    a = vp2; b = (vp0 - vp2) * dv2; c = (vp1 - vp2) * dv2;
7513 	    x0 = dv2 - dv0; x1 = dv2 - dv1;
7514 	}
7515 	else {
7516 	    // triangles are coplanar
7517 	    boolean toreturn = coplanarTriTri(n1, v0, v1, v2, u0, u1, u2);
7518 	    return toreturn;
7519 	}
7520 
7521 
7522 	// compute intereval for triangle 2.
7523 	double d=0.0, e=0.0, f=0.0, y0=0.0, y1=0.0;
7524 	if(du0du1>0.0) {
7525 	    // here we know that du0du2 <= 0.0 that is du0 and du1 are on the same side,
7526 	    // du2 on the other side or on the plane.
7527 	    d = up2; e = (up0 - up2) * du2; f = (up1 - up2) * du2;
7528 	    y0 = du2 - du0; y1 = du2 - du1;
7529 	}
7530 	else if(du0du2>0.0) {
7531 	    // here we know that du0du1<=0.0
7532 	    d = up1; e = (up0 - up1) * du1; f = (up2 - up1) * du1;
7533 	    y0 = du1 - du0; y1 = du1 - du2;
7534 	}
7535 	else if((du1*du2>0.0) || (du0 != 0.0)) {
7536 	    // here we know that du0du1<=0.0 or that D0!=0.0
7537 	    d = up0; e = (up1 - up0) * du0; f = (up2 - up0) * du0;
7538 	    y0 = du0 - du1; y1 = du0 - du2;
7539 	}
7540 	else if(du1 != 0.0) {
7541 	    d = up1; e = (up0 - up1) * du1; f = (up2 - up1) * du1;
7542 	    y0 = du1 - du0; y1 = du1 - du2;
7543 	}
7544 	else if(du2 != 0.0) {
7545 	    d = up2; e = (up0 - up2) * du2; f = (up1 - up2) * du2;
7546 	    y0 = du2 - du0; y1 = du2 - du1;
7547 	}
7548 	else {
7549 	    // triangles are coplanar
7550 	    //	    System.err.println("In intersectTriTri : coplanarTriTri test 2");
7551 	    boolean toreturn =  coplanarTriTri(n2, v0, v1, v2, u0, u1, u2);
7552 	    return toreturn;
7553 	}
7554 
7555 	double xx, yy, xxyy, tmp, isect1S, isect1E, isect2S, isect2E;
7556 	xx = x0 * x1;
7557 	yy = y0 * y1;
7558 	xxyy = xx * yy;
7559 
7560 	tmp = a * xxyy;
7561 	isect1S = tmp + b * x1 * yy;
7562 	isect1E = tmp + c * x0 * yy;
7563 
7564 	tmp = d * xxyy;
7565 	isect2S = tmp + e * y1 * xx;
7566 	isect2E = tmp + f * y0 * xx;
7567 
7568 	// sort so that isect1S <= isect1E
7569 	if(isect1S > isect1E) {
7570 	    tmp = isect1S;
7571 	    isect1S = isect1E;
7572 	    isect1E = tmp;
7573 	}
7574 
7575 	// sort so that isect2S <= isect2E
7576 	if(isect2S > isect2E) {
7577 	    tmp = isect2S;
7578 	    isect2S = isect2E;
7579 	    isect2E = tmp;
7580 	}
7581 
7582 	if(isect1E<isect2S || isect2E<isect1S) {
7583 	    // System.err.println("In intersectTriTri :isect1E<isect2S || isect2E<isect1S");
7584 	    // System.err.println("In intersectTriTri : return false");
7585 	    return false;
7586 	}
7587 
7588 	//	 System.err.println("In intersectTriTri : return true");
7589 	return true;
7590 
7591     }
7592 
7593 
7594 
intersectPolygon(Point3d coord1[], Point3d coord2[])7595     boolean intersectPolygon(Point3d coord1[], Point3d coord2[]) {
7596 	int i, j;
7597 	Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
7598 	Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
7599 	Vector3d pNrm = new Vector3d();
7600 	boolean epFlag;
7601 
7602 
7603 	// compute plane normal for coord1.
7604 	for(i=0; i<coord1.length-1;) {
7605 	    vec0.x = coord1[i+1].x - coord1[i].x;
7606 	    vec0.y = coord1[i+1].y - coord1[i].y;
7607 	    vec0.z = coord1[i+1].z - coord1[i++].z;
7608 	    if(vec0.length() > 0.0)
7609 		break;
7610 	}
7611 
7612 	for(j=i; j<coord1.length-1; j++) {
7613 	    vec1.x = coord1[j+1].x - coord1[j].x;
7614 	    vec1.y = coord1[j+1].y - coord1[j].y;
7615 	    vec1.z = coord1[j+1].z - coord1[j].z;
7616 	    if(vec1.length() > 0.0)
7617 		break;
7618 	}
7619 
7620 	if(j == (coord1.length-1)) {
7621 	    // System.err.println("(1) Degenerate polygon.");
7622 	    return false;  // Degenerate polygon.
7623 	}
7624 
7625 	/*
7626 	  for(i=0; i<coord1.length; i++)
7627 	  System.err.println("coord1 P" + i + " " + coord1[i]);
7628 	  for(i=0; i<coord2.length; i++)
7629 	  System.err.println("coord2 P" + i + " " + coord2[i]);
7630 	  */
7631 
7632 	pNrm.cross(vec0,vec1);
7633 
7634 	if(pNrm.length() == 0.0) {
7635 	    // System.err.println("(2) Degenerate polygon.");
7636 	    return false;  // Degenerate polygon.
7637 	}
7638 
7639 	j = 0;
7640 	Point3d seg[] = new Point3d[2];
7641 	seg[0] = new Point3d();
7642 	seg[1] = new Point3d();
7643 
7644 	for(i=0; i<coord2.length; i++) {
7645 	    if(i < (coord2.length-1))
7646 		epFlag = edgeIntersectPlane(pNrm, coord1[0], coord2[i],
7647 					    coord2[i+1], seg[j]);
7648 	    else
7649 		epFlag = edgeIntersectPlane(pNrm, coord1[0], coord2[i],
7650 					    coord2[0], seg[j]);
7651 	    if (epFlag) {
7652 		if(++j>1) {
7653 		    break;
7654 		}
7655 	    }
7656 	}
7657 
7658 	if (j==0) {
7659 	    return false;
7660 	}
7661 
7662 	if (coord2.length < 3) {
7663 	    boolean toreturn = pointIntersectPolygon2D(pNrm, coord1, seg[0]);
7664 	    return toreturn;
7665 	} else {
7666 	    boolean toreturn = edgeIntersectPolygon2D(pNrm, coord1, seg);
7667 	    return toreturn;
7668 	}
7669     }
7670 
7671 
7672     /**
7673      * Return true if triangle or quad intersects with ray and the
7674      * distance is stored in dist[0] and the intersect point in iPnt
7675      * (if iPnt is not null).
7676      */
intersectRay(Point3d coordinates[], PickRay ray, double dist[], Point3d iPnt)7677     boolean intersectRay(Point3d coordinates[], PickRay ray, double dist[],
7678 			 Point3d iPnt) {
7679 
7680 	return intersectRayOrSegment(coordinates, ray.direction, ray.origin,
7681 				     dist, iPnt, false);
7682 
7683     }
7684 
7685     /**
7686      * Return true if triangle or quad intersects with segment and
7687      * the distance is stored in dist[0].
7688      */
intersectSegment( Point3d coordinates[], Point3d start, Point3d end, double dist[], Point3d iPnt )7689     boolean intersectSegment( Point3d coordinates[], Point3d start, Point3d end,
7690 			      double dist[], Point3d iPnt ) {
7691 	boolean result;
7692 	Vector3d direction = new Vector3d();
7693 	direction.x = end.x - start.x;
7694 	direction.y = end.y - start.y;
7695 	direction.z = end.z - start.z;
7696 	result = intersectRayOrSegment(coordinates, direction, start, dist, iPnt, true);
7697 	return result;
7698     }
7699 
7700 
7701 
7702     /**
7703      *  Return true if triangle or quad intersects with ray and the distance is
7704      *  stored in pr.
7705      */
intersectRayOrSegment(Point3d coordinates[], Vector3d direction, Point3d origin, double dist[], Point3d iPnt, boolean isSegment)7706     boolean intersectRayOrSegment(Point3d coordinates[],
7707 				  Vector3d direction, Point3d origin,
7708 				  double dist[], Point3d iPnt, boolean isSegment) {
7709 	Vector3d vec0, vec1, pNrm, tempV3d;
7710 	vec0 = new Vector3d();
7711 	vec1 = new Vector3d();
7712 	pNrm = new Vector3d();
7713 
7714 	double  absNrmX, absNrmY, absNrmZ, pD = 0.0;
7715 	double pNrmDotrDir = 0.0;
7716 
7717 	boolean isIntersect = false;
7718 	int i, j, k=0, l = 0;
7719 
7720 	// Compute plane normal.
7721 	for (i=0; i<coordinates.length; i++) {
7722 	    if (i != coordinates.length-1) {
7723 		l = i+1;
7724 	    } else {
7725 		l = 0;
7726 	    }
7727 	    vec0.x = coordinates[l].x - coordinates[i].x;
7728 	    vec0.y = coordinates[l].y - coordinates[i].y;
7729 	    vec0.z = coordinates[l].z - coordinates[i].z;
7730 	    if (vec0.length() > 0.0) {
7731 		break;
7732 	    }
7733 	}
7734 
7735 
7736 	for (j=l; j<coordinates.length; j++) {
7737 	    if (j != coordinates.length-1) {
7738 		k = j+1;
7739 	    } else {
7740 		k = 0;
7741 	    }
7742 	    vec1.x = coordinates[k].x - coordinates[j].x;
7743 	    vec1.y = coordinates[k].y - coordinates[j].y;
7744 	    vec1.z = coordinates[k].z - coordinates[j].z;
7745 	    if (vec1.length() > 0.0) {
7746 		break;
7747 	    }
7748 	}
7749 
7750 	pNrm.cross(vec0,vec1);
7751 
7752 	if ((vec1.length() == 0) || (pNrm.length() == 0)) {
7753 	    // degenerate to line if vec0.length() == 0
7754 	    // or vec0.length > 0 and vec0 parallel to vec1
7755 	    k = (l == 0 ? coordinates.length-1: l-1);
7756 	    isIntersect = intersectLineAndRay(coordinates[l],
7757 					      coordinates[k],
7758 					      origin,
7759 					      direction,
7760 					      dist,
7761 					      iPnt);
7762 
7763 	    // put the Vectors on the freelist
7764 	    return isIntersect;
7765 	}
7766 
7767 	// It is possible that Quad is degenerate to Triangle
7768 	// at this point
7769 
7770 	pNrmDotrDir = pNrm.dot(direction);
7771 
7772     	// Ray is parallel to plane.
7773 	if (pNrmDotrDir == 0.0) {
7774 	    // Ray is parallel to plane
7775 	    // Check line/triangle intersection on plane.
7776 	    for (i=0; i < coordinates.length ;i++) {
7777 		if (i != coordinates.length-1) {
7778 		    k = i+1;
7779 		} else {
7780 		    k = 0;
7781 		}
7782 		if (intersectLineAndRay(coordinates[i],
7783 					coordinates[k],
7784 					origin,
7785 					direction,
7786 					dist,
7787 					iPnt)) {
7788 		    isIntersect = true;
7789 		    break;
7790 		}
7791 	    }
7792 	    return isIntersect;
7793 	}
7794 
7795 	// Plane equation: (p - p0)*pNrm = 0 or p*pNrm = pD;
7796 	tempV3d = new Vector3d();
7797 	tempV3d.set((Tuple3d) coordinates[0]);
7798 	pD = pNrm.dot(tempV3d);
7799 	tempV3d.set((Tuple3d) origin);
7800 
7801 	// Substitute Ray equation:
7802 	// p = origin + pi.distance*direction
7803 	// into the above Plane equation
7804 
7805 	dist[0] = (pD - pNrm.dot(tempV3d))/ pNrmDotrDir;
7806 
7807 	// Ray intersects the plane behind the ray's origin.
7808 	if ((dist[0] < -EPS ) ||
7809 	    (isSegment && (dist[0] > 1.0+EPS))) {
7810 	    // Ray intersects the plane behind the ray's origin
7811 	    // or intersect point not fall in Segment
7812 	    return false;
7813 	}
7814 
7815 	// Now, one thing for sure the ray intersect the plane.
7816 	// Find the intersection point.
7817 	if (iPnt == null) {
7818 	    iPnt = new Point3d();
7819 	}
7820 	iPnt.x = origin.x + direction.x * dist[0];
7821 	iPnt.y = origin.y + direction.y * dist[0];
7822 	iPnt.z = origin.z + direction.z * dist[0];
7823 
7824 	// Project 3d points onto 2d plane
7825 	// Find the axis so that area of projection is maximize.
7826 	absNrmX = Math.abs(pNrm.x);
7827 	absNrmY = Math.abs(pNrm.y);
7828 	absNrmZ = Math.abs(pNrm.z);
7829 
7830 	// All sign of (y - y0) (x1 - x0) - (x - x0) (y1 - y0)
7831 	// must agree.
7832 	double sign, t, lastSign = 0;
7833 	Point3d p0 = coordinates[coordinates.length-1];
7834 	Point3d p1 = coordinates[0];
7835 
7836 	isIntersect = true;
7837 
7838 	if (absNrmX > absNrmY) {
7839 	    if (absNrmX < absNrmZ) {
7840 		for (i=0; i < coordinates.length; i++) {
7841 		    p0 = coordinates[i];
7842 		    p1 = (i != coordinates.length-1 ? coordinates[i+1]: coordinates[0]);
7843  		    sign = (iPnt.y - p0.y)*(p1.x - p0.x) -
7844 			   (iPnt.x - p0.x)*(p1.y - p0.y);
7845 		    if (isNonZero(sign)) {
7846 			if (sign*lastSign < 0) {
7847 			    isIntersect = false;
7848 			    break;
7849 			}
7850 			lastSign = sign;
7851 		    } else { // point on line, check inside interval
7852 			t = p1.y - p0.y;
7853 			if (isNonZero(t)) {
7854 			    t = (iPnt.y - p0.y)/t;
7855 			    isIntersect = ((t > -EPS) && (t < 1+EPS));
7856 			    break;
7857 			} else {
7858 			    t = p1.x - p0.x;
7859 			    if (isNonZero(t)) {
7860 				t = (iPnt.x - p0.x)/t;
7861 				isIntersect = ((t > -EPS) && (t < 1+EPS));
7862 				break;
7863 			    } else {
7864     // Ignore degenerate line=>point happen when Quad => Triangle.
7865     // Note that by next round sign*lastSign = 0 so it will
7866     // not pass the interest test. This should only happen once in the
7867     // loop because we already check for degenerate geometry before.
7868 			    }
7869 			}
7870 		    }
7871 		}
7872 	    } else {
7873 		for (i=0; i<coordinates.length; i++) {
7874 		    p0 = coordinates[i];
7875 		    p1 = (i != coordinates.length-1 ? coordinates[i+1]: coordinates[0]);
7876 		    sign = (iPnt.y - p0.y)*(p1.z - p0.z) -
7877 			   (iPnt.z - p0.z)*(p1.y - p0.y);
7878 		    if (isNonZero(sign)) {
7879 			if (sign*lastSign < 0) {
7880 			    isIntersect = false;
7881 			    break;
7882 			}
7883 			lastSign = sign;
7884 		    } else { // point on line, check inside interval
7885 			t = p1.y - p0.y;
7886 
7887 			if (isNonZero(t)) {
7888 			    t = (iPnt.y - p0.y)/t;
7889 			    isIntersect = ((t > -EPS) && (t < 1+EPS));
7890 			    break;
7891 
7892 			} else {
7893 			    t = p1.z - p0.z;
7894 			    if (isNonZero(t)) {
7895 				t = (iPnt.z - p0.z)/t;
7896 				isIntersect = ((t > -EPS) && (t < 1+EPS));
7897 				break;
7898 			    } else {
7899 				//degenerate line=>point
7900 			    }
7901 			}
7902 		    }
7903 		}
7904 	    }
7905 	} else {
7906 	    if (absNrmY < absNrmZ) {
7907 		for (i=0; i<coordinates.length; i++) {
7908 		    p0 = coordinates[i];
7909 		    p1 = (i != coordinates.length-1 ? coordinates[i+1]: coordinates[0]);
7910 		    sign = (iPnt.y - p0.y)*(p1.x - p0.x) -
7911 			   (iPnt.x - p0.x)*(p1.y - p0.y);
7912 		    if (isNonZero(sign)) {
7913 			if (sign*lastSign < 0) {
7914 			    isIntersect = false;
7915 			    break;
7916 			}
7917 			lastSign = sign;
7918 		    } else { // point on line, check inside interval
7919 			t = p1.y - p0.y;
7920 			if (isNonZero(t)) {
7921 			    t = (iPnt.y - p0.y)/t;
7922 			    isIntersect = ((t > -EPS) && (t < 1+EPS));
7923 			    break;
7924 			} else {
7925 			    t = p1.x - p0.x;
7926 			    if (isNonZero(t)) {
7927 				t = (iPnt.x - p0.x)/t;
7928 				isIntersect = ((t > -EPS) && (t < 1+EPS));
7929 				break;
7930 			    } else {
7931 				//degenerate line=>point
7932 			    }
7933 			}
7934 		    }
7935 		}
7936 	    } else {
7937 		for (i=0; i<coordinates.length; i++) {
7938 		    p0 = coordinates[i];
7939 		    p1 = (i != coordinates.length-1 ? coordinates[i+1]: coordinates[0]);
7940 		    sign = (iPnt.x - p0.x)*(p1.z - p0.z) -
7941 			   (iPnt.z - p0.z)*(p1.x - p0.x);
7942 		    if (isNonZero(sign)) {
7943 			if (sign*lastSign < 0) {
7944 			    isIntersect = false;
7945 			    break;
7946 			}
7947 			lastSign = sign;
7948 		    } else { // point on line, check inside interval
7949 			t = p1.x - p0.x;
7950 			if (isNonZero(t)) {
7951 			    t = (iPnt.x - p0.x)/t;
7952 			    isIntersect = ((t > -EPS) && (t < 1+EPS));
7953 			    break;
7954 			} else {
7955 			    t = p1.z - p0.z;
7956 			    if (isNonZero(t)) {
7957 				t = (iPnt.z - p0.z)/t;
7958 				isIntersect = ((t > -EPS) && (t < 1+EPS));
7959 				break;
7960 			    } else {
7961 				//degenerate line=>point
7962 			    }
7963 			}
7964 		    }
7965 		}
7966 	    }
7967 	}
7968 
7969 	if (isIntersect) {
7970 	    dist[0] *= direction.length();
7971 	}
7972 	return isIntersect;
7973     }
7974 
7975 
7976 
isNonZero(double v)7977     static final boolean isNonZero(double v) {
7978 	return ((v > EPS) || (v < -EPS));
7979 
7980     }
7981 
7982     /**
7983      * Return true if point is on the inside of halfspace test. The
7984      * halfspace is partition by the plane of triangle or quad.
7985      */
inside( Point3d coordinates[], PickPoint point, int ccw )7986     boolean inside( Point3d coordinates[], PickPoint point, int ccw ) {
7987 
7988 	Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
7989 	Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
7990 	Vector3d pNrm = new Vector3d();
7991 	double  absNrmX, absNrmY, absNrmZ, pD = 0.0;
7992 	Vector3d tempV3d = new Vector3d();
7993 	double pNrmDotrDir = 0.0;
7994 
7995 	double tempD;
7996 
7997 	int i, j;
7998 
7999 	// Compute plane normal.
8000 	for(i=0; i<coordinates.length-1;) {
8001 	    vec0.x = coordinates[i+1].x - coordinates[i].x;
8002 	    vec0.y = coordinates[i+1].y - coordinates[i].y;
8003 	    vec0.z = coordinates[i+1].z - coordinates[i++].z;
8004 	    if(vec0.length() > 0.0)
8005 		break;
8006 	}
8007 
8008 	for(j=i; j<coordinates.length-1; j++) {
8009 	    vec1.x = coordinates[j+1].x - coordinates[j].x;
8010 	    vec1.y = coordinates[j+1].y - coordinates[j].y;
8011 	    vec1.z = coordinates[j+1].z - coordinates[j].z;
8012 	    if(vec1.length() > 0.0)
8013 		break;
8014 	}
8015 
8016 	if(j == (coordinates.length-1)) {
8017 	    // System.err.println("(1) Degenerate polygon.");
8018 	    return false;  // Degenerate polygon.
8019 	}
8020 
8021 	/*
8022 	   System.err.println("Ray orgin : " + ray.origin + " dir " + ray.direction);
8023 	   System.err.println("Triangle/Quad :");
8024 	   for(i=0; i<coordinates.length; i++)
8025 	   System.err.println("P" + i + " " + coordinates[i]);
8026 	   */
8027 
8028 	if( ccw == 0x1)
8029 	    pNrm.cross(vec0,vec1);
8030 	else
8031 	    pNrm.cross(vec1,vec0);
8032 
8033 	if(pNrm.length() == 0.0) {
8034 	    // System.err.println("(2) Degenerate polygon.");
8035 	    return false;  // Degenerate polygon.
8036 	}
8037 	// Compute plane D.
8038 	tempV3d.set((Tuple3d) coordinates[0]);
8039 	pD = pNrm.dot(tempV3d);
8040 	tempV3d.set((Tuple3d) point.location);
8041 
8042 	return ((pD - pNrm.dot(tempV3d)) <= 0);
8043     }
8044 
intersectPntAndPnt( Point3d pnt1, Point3d pnt2 )8045     boolean intersectPntAndPnt( Point3d pnt1, Point3d pnt2 ) {
8046 	return ((pnt1.x == pnt2.x) &&
8047 		(pnt1.y == pnt2.y) &&
8048 		(pnt1.z == pnt2.z));
8049     }
8050 
intersectPntAndRay(Point3d pnt, Point3d ori, Vector3d dir, double dist[])8051     boolean intersectPntAndRay(Point3d pnt, Point3d ori, Vector3d dir,
8052 			       double dist[]) {
8053 	int flag = 0;
8054 	double temp;
8055 
8056 	if(dir.x != 0.0) {
8057 	    flag = 0;
8058 	    dist[0] = (pnt.x - ori.x)/dir.x;
8059 	}
8060 	else if(dir.y != 0.0) {
8061 	    if(pnt.x != ori.x)
8062 		return false;
8063 	    flag = 1;
8064 	    dist[0] = (pnt.y - ori.y)/dir.y;
8065 	}
8066 	else if(dir.z != 0.0) {
8067 	    if((pnt.x != ori.x)||(pnt.y != ori.y))
8068 		return false;
8069 	    flag = 2;
8070 	    dist[0] = (pnt.z - ori.z)/dir.z;
8071 
8072 	}
8073 	else
8074 	    return false;
8075 
8076 	if(dist[0] < 0.0)
8077 	    return false;
8078 
8079 	if(flag == 0) {
8080 	    temp = ori.y + dist[0] * dir.y;
8081 	    if((pnt.y < (temp - EPS)) || (pnt.y > (temp + EPS)))
8082 		return false;
8083 	}
8084 
8085 	if(flag < 2) {
8086 	    temp = ori.z + dist[0] * dir.z;
8087 	    if((pnt.z < (temp - EPS)) || (pnt.z > (temp + EPS)))
8088 		return false;
8089 	}
8090 
8091 	return true;
8092 
8093     }
8094 
intersectLineAndRay(Point3d start, Point3d end, Point3d ori, Vector3d dir, double dist[], Point3d iPnt)8095     boolean intersectLineAndRay(Point3d start, Point3d end,
8096 				Point3d ori, Vector3d dir, double dist[],
8097 				Point3d iPnt) {
8098 
8099 	double m00, m01, m10, m11;
8100 	double mInv00, mInv01, mInv10, mInv11;
8101 	double dmt, t, s, tmp1, tmp2;
8102 	Vector3d lDir;
8103 
8104 	//     System.err.println("GeometryArrayRetained : intersectLineAndRay");
8105 	//     System.err.println("start " + start + " end " + end );
8106 	//     System.err.println("ori " + ori + " dir " + dir);
8107 
8108 	lDir = new Vector3d();
8109 	lDir.x = (end.x - start.x);
8110 	lDir.y = (end.y - start.y);
8111 	lDir.z = (end.z - start.z);
8112 
8113 	m00 = lDir.x;
8114 	m01 = -dir.x;
8115 	m10 = lDir.y;
8116 	m11 = -dir.y;
8117 
8118 	// Get the determinant.
8119 	dmt = (m00 * m11) - (m10 * m01);
8120 
8121 	if (dmt==0.0) { // No solution, check degenerate line
8122 	    boolean isIntersect = false;
8123 	    if ((lDir.x == 0) && (lDir.y == 0) && (lDir.z == 0)) {
8124 		isIntersect = intersectPntAndRay(start, ori, dir, dist);
8125 		if (isIntersect && (iPnt != null)) {
8126 		    iPnt.set(start);
8127 		}
8128 	    }
8129 	    return isIntersect;
8130 	}
8131 	// Find the inverse.
8132 	tmp1 = 1/dmt;
8133 
8134 	mInv00 = tmp1 * m11;
8135 	mInv01 = tmp1 * (-m01);
8136 	mInv10 = tmp1 * (-m10);
8137 	mInv11 = tmp1 * m00;
8138 
8139 	tmp1 = ori.x - start.x;
8140 	tmp2 = ori.y - start.y;
8141 
8142 	t = mInv00 * tmp1 + mInv01 * tmp2;
8143 	s = mInv10 * tmp1 + mInv11 * tmp2;
8144 
8145 	if(s<0.0) { // Before the origin of ray.
8146 	    // System.err.println("Before the origin of ray " + s);
8147 	    return false;
8148 	}
8149 	if((t<0)||(t>1.0)) {// Before or after the end points of line.
8150 	    // System.err.println("Before or after the end points of line. " + t);
8151 	    return false;
8152 	}
8153 
8154 	tmp1 = ori.z + s * dir.z;
8155 	tmp2 = start.z + t * lDir.z;
8156 
8157 	if((tmp1 < (tmp2 - EPS)) || (tmp1 > (tmp2 + EPS))) {
8158 	    // System.err.println("No intersection : tmp1 " + tmp1 + " tmp2 " + tmp2);
8159 	    return false;
8160 	}
8161 
8162 	dist[0] = s;
8163 
8164 	if (iPnt != null) {
8165 	    // compute point of intersection.
8166 	    iPnt.x = ori.x + dir.x * dist[0];
8167 	    iPnt.y = ori.y + dir.y * dist[0];
8168 	    iPnt.z = ori.z + dir.z * dist[0];
8169 	}
8170 
8171 	// System.err.println("Intersected : tmp1 " + tmp1 + " tmp2 " + tmp2);
8172 	return true;
8173     }
8174 
8175     /**
8176       Return true if triangle or quad intersects with cylinder. The
8177       distance is stored in dist.
8178       */
intersectCylinder(Point3d coordinates[], PickCylinder cyl, double dist[], Point3d iPnt)8179     boolean intersectCylinder(Point3d coordinates[], PickCylinder cyl,
8180 			      double dist[], Point3d iPnt) {
8181 
8182 	Point3d origin = new Point3d();
8183 	Point3d end = new Point3d();
8184 	Vector3d direction = new Vector3d();
8185 	Point3d iPnt1 = new Point3d();
8186 	Vector3d originToIpnt = new Vector3d();
8187 
8188 	if (iPnt == null) {
8189 	    iPnt = new Point3d();
8190 	}
8191 
8192 	// Get cylinder information
8193 	cyl.getOrigin (origin);
8194 	cyl.getDirection (direction);
8195 	double radius = cyl.getRadius ();
8196 
8197 	if (cyl instanceof PickCylinderSegment) {
8198 	    ((PickCylinderSegment)cyl).getEnd (end);
8199 	}
8200 
8201 	// If the ray intersects, we're good (do not do this if we only have
8202 	// a segment
8203 	if (coordinates.length > 2) {
8204 	    if (cyl instanceof PickCylinderRay) {
8205 		if (intersectRay(coordinates,
8206 				 new PickRay(origin, direction),
8207 				 dist, iPnt)) {
8208 		    return true;
8209 		}
8210 	    }
8211 	    else {
8212 		if (intersectSegment(coordinates, origin, end, dist, iPnt)) {
8213 		    return true;
8214 		}
8215 	    }
8216 	}
8217 
8218 	// Ray doesn't intersect, check distance to edges
8219 	double sqDistToEdge;
8220 	int j;
8221 	for (int i=0; i<coordinates.length;i++) {
8222 	    j = (i < coordinates.length-1 ? i+1: 0);
8223 	    if (cyl instanceof PickCylinderSegment) {
8224 		sqDistToEdge =
8225 		    Distance.segmentToSegment(origin, end,
8226 					      coordinates[i], coordinates[j],
8227 					      iPnt1, iPnt, null);
8228 	    }
8229 	    else {
8230 		sqDistToEdge =
8231 		    Distance.rayToSegment(origin, direction,
8232 					  coordinates[i], coordinates[j],
8233 					  iPnt1, iPnt, null);
8234 	    }
8235 	    if (sqDistToEdge <= radius*radius) {
8236 		originToIpnt.sub (iPnt1, origin);
8237 		dist[0] = originToIpnt.length();
8238 		return true;
8239 	    }
8240 	}
8241 	return false;
8242     }
8243 
8244     /**
8245       Return true if triangle or quad intersects with cone. The
8246       distance is stored in dist.
8247       */
intersectCone(Point3d coordinates[], PickCone cone, double[] dist, Point3d iPnt)8248     boolean intersectCone(Point3d coordinates[], PickCone cone,
8249 			  double[] dist, Point3d iPnt) {
8250 
8251 	Point3d origin = new Point3d();
8252 	Point3d end = new Point3d();
8253 	Vector3d direction = new Vector3d();
8254 	Vector3d originToIpnt = new Vector3d();
8255 	double distance;
8256 
8257 	Point3d iPnt1 = new Point3d();
8258 	Vector3d vector = new Vector3d();
8259 
8260 	if (iPnt == null) {
8261 	    iPnt = new Point3d();
8262 	}
8263 	// Get cone information
8264 	cone.getOrigin (origin);
8265 	cone.getDirection (direction);
8266 	double radius;
8267 
8268 	if (cone instanceof PickConeSegment) {
8269 	    ((PickConeSegment)cone).getEnd (end);
8270 	}
8271 
8272 	// If the ray intersects, we're good (do not do this if we only have
8273 	// a segment
8274 	if (coordinates.length > 2) {
8275 	    if (cone instanceof PickConeRay) {
8276 		if (intersectRay(coordinates,
8277 				 new PickRay (origin, direction),
8278 				 dist, iPnt)) {
8279 		    return true;
8280 		}
8281 	    }
8282 	    else {
8283 		if (intersectSegment(coordinates, origin, end, dist, iPnt)) {
8284 		    return true;
8285 		}
8286 	    }
8287 	}
8288 
8289 	// Ray doesn't intersect, check distance to edges
8290 	double sqDistToEdge;
8291 	int j = 0;
8292 	for (int i=0; i<coordinates.length;i++) {
8293 	    j = (i < coordinates.length-1 ? i+1: 0);
8294 	    if (cone instanceof PickConeSegment) {
8295 		sqDistToEdge =
8296 		    Distance.segmentToSegment (origin, end,
8297 					       coordinates[i], coordinates[j],
8298 					       iPnt1, iPnt, null);
8299 	    }
8300 	    else {
8301 		sqDistToEdge =
8302 		    Distance.rayToSegment (origin, direction,
8303 					   coordinates[i], coordinates[j],
8304 					   iPnt1, iPnt, null);
8305 	    }
8306 	    originToIpnt.sub(iPnt1, origin);
8307 	    distance = originToIpnt.length();
8308 	    radius = Math.tan (cone.getSpreadAngle()) * distance;
8309 	    if (sqDistToEdge <= radius*radius) {
8310 		//	System.err.println ("intersectCone: edge "+i+" intersected");
8311 		dist[0] = distance;
8312 		return true;
8313 	    }
8314 	}
8315 	return false;
8316     }
8317 
8318 
8319     /**
8320       Return true if point intersects with cylinder and the distance is
8321       stored in dist.
8322       */
intersectCylinder(Point3d pt, PickCylinder cyl, double[] dist)8323     boolean intersectCylinder(Point3d pt, PickCylinder cyl,
8324 			      double[] dist) {
8325 
8326 	Point3d origin = new Point3d();
8327 	Point3d end = new Point3d();
8328 	Vector3d direction = new Vector3d();
8329 	Point3d iPnt = new Point3d();
8330 	Vector3d originToIpnt = new Vector3d();
8331 
8332 	// Get cylinder information
8333 	cyl.getOrigin (origin);
8334 	cyl.getDirection (direction);
8335 	double radius = cyl.getRadius ();
8336 	double sqDist;
8337 
8338 	if (cyl instanceof PickCylinderSegment) {
8339 	    ((PickCylinderSegment)cyl).getEnd (end);
8340 	    sqDist = Distance.pointToSegment(pt, origin, end, iPnt, null);
8341 	}
8342 	else {
8343 	    sqDist = Distance.pointToRay(pt, origin, direction, iPnt, null);
8344 	}
8345 	if (sqDist <= radius*radius) {
8346 	    originToIpnt.sub (iPnt, origin);
8347 	    dist[0] = originToIpnt.length();
8348 	    return true;
8349 	}
8350 	return false;
8351     }
8352 
8353     /**
8354       Return true if point intersects with cone and the
8355       distance is stored in pi.
8356       */
intersectCone(Point3d pt, PickCone cone, double[] dist)8357     boolean intersectCone(Point3d pt, PickCone cone, double[] dist)
8358     {
8359 	Point3d origin = new Point3d();
8360 	Point3d end = new Point3d();
8361 	Vector3d direction = new Vector3d();
8362         Point3d iPnt = new Point3d();
8363 	Vector3d originToIpnt = new Vector3d();
8364 
8365 	// Get cone information
8366 	cone.getOrigin (origin);
8367 	cone.getDirection (direction);
8368 	double radius;
8369 	double distance;
8370 	double sqDist;
8371 
8372 	if (iPnt == null) {
8373 	    iPnt = new Point3d();
8374 	}
8375 
8376 	if (cone instanceof PickConeSegment) {
8377 	    ((PickConeSegment)cone).getEnd (end);
8378 	    sqDist = Distance.pointToSegment (pt, origin, end, iPnt, null);
8379 	}
8380 	else {
8381 	    sqDist = Distance.pointToRay (pt, origin, direction, iPnt, null);
8382 	}
8383 	originToIpnt.sub(iPnt, origin);
8384 	distance = originToIpnt.length();
8385 	radius = Math.tan (cone.getSpreadAngle()) * distance;
8386 	if (sqDist <= radius*radius) {
8387 	    dist[0] = distance;
8388 	    return true;
8389 	}
8390 	return false;
8391     }
8392 
8393 
setCoordRefBuffer(J3DBuffer coords)8394     void setCoordRefBuffer(J3DBuffer coords) {
8395 	if (coords != null) {
8396 	    switch (coords.getBufferType()) {
8397 	    case J3DBuffer.TYPE_FLOAT:
8398 		assert ((FloatBufferWrapper)coords.getBufferImpl()).isDirect();
8399 		break;
8400 	    case J3DBuffer.TYPE_DOUBLE:
8401 		assert ((DoubleBufferWrapper)coords.getBufferImpl()).isDirect();
8402 		break;
8403 	    case J3DBuffer.TYPE_NULL:
8404 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray115"));
8405 
8406 	    default:
8407 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
8408 	    }
8409 
8410 	    if (this instanceof IndexedGeometryArrayRetained) {
8411 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8412 		if (3 * idx.maxCoordIndex >= coords.getBufferImpl().limit()) {
8413 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
8414 		}
8415 	    } else if (coords.getBufferImpl().limit() < (3*(initialCoordIndex+validVertexCount))) {
8416 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
8417 	    }
8418 	}
8419 
8420 	// lock the geometry and start to do real work
8421 	boolean isLive = source!=null && source.isLive();
8422 	if(isLive){
8423             geomLock.getLock();
8424 	}
8425 	dirtyFlag |= COORDINATE_CHANGED;
8426 	coordRefBuffer = coords;
8427 	if(coords == null) {
8428 	    floatBufferRefCoords = null;
8429 	    doubleBufferRefCoords = null;
8430 	    // XXXX: if not mix java array with nio buffer
8431 	    // vertexType can be used as vertexTypeBuffer
8432 	    vertexType &= ~PD;
8433 	    vertexType &= ~PF;
8434 	}else {
8435 	    switch (coords.getBufferType()) {
8436 	    case J3DBuffer.TYPE_FLOAT:
8437 		floatBufferRefCoords =
8438 		    (FloatBufferWrapper)coords.getBufferImpl();
8439 		doubleBufferRefCoords = null;
8440 		vertexType |= PF;
8441 		vertexType &= ~PD;
8442 		break;
8443 	    case J3DBuffer.TYPE_DOUBLE:
8444 		floatBufferRefCoords = null;
8445 		doubleBufferRefCoords =
8446 		    (DoubleBufferWrapper)coords.getBufferImpl();
8447 		vertexType |= PD;
8448 		vertexType &= ~PF;
8449 		break;
8450 	    default:
8451 		break;
8452 	    }
8453 	}
8454 
8455 	// need not call setupMirrorVertexPointer() since
8456 	// we are not going to set mirror in NIO buffer case
8457 	// XXXX: if we need to mix java array with buffer,
8458 	//        we may need to consider setupMirrorVertexPointer()
8459 
8460 	if(isLive) {
8461             geomLock.unLock();
8462         }
8463 	if (!inUpdater && source != null) {
8464 	    if (isLive) {
8465 		processCoordsChanged((coords == null));
8466 		sendDataChangedMessage(true);
8467 	    } else {
8468 		boundsDirty = true;
8469 	    }
8470 	}
8471 
8472     }
8473 
8474 
getCoordRefBuffer()8475     J3DBuffer getCoordRefBuffer() {
8476 	return coordRefBuffer;
8477     }
8478 
8479 
setCoordRefFloat(float[] coords)8480     void setCoordRefFloat(float[] coords) {
8481 
8482 	// If non-null coordinate and vertType is either  defined
8483 	// to be something other than PF, then issue an error
8484 	if (coords != null) {
8485 	    if ((vertexType & VERTEX_DEFINED) != 0 &&
8486 		(vertexType & VERTEX_DEFINED) != PF) {
8487 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
8488 	    }
8489 
8490 
8491 	    if (this instanceof IndexedGeometryArrayRetained) {
8492 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8493 
8494 		if (3 * idx.maxCoordIndex >= coords.length) {
8495 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
8496 		}
8497 	    } else if (coords.length < 3 * (initialCoordIndex+validVertexCount)) {
8498 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
8499 	    }
8500 	}
8501 	boolean isLive = source!=null && source.isLive();
8502 	if(isLive){
8503             geomLock.getLock();
8504 	}
8505 	dirtyFlag |= COORDINATE_CHANGED;
8506 
8507 	floatRefCoords = coords;
8508 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8509 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8510 	    if (coords == null)
8511 		vertexType &= ~PF;
8512 	    else
8513 		vertexType |= PF;
8514 	}
8515 	else {
8516 	    setupMirrorVertexPointer(PF);
8517 	}
8518 
8519 	if(isLive) {
8520             geomLock.unLock();
8521         }
8522 	if (!inUpdater && source != null) {
8523             if (isLive) {
8524                 processCoordsChanged(coords == null);
8525 		sendDataChangedMessage(true);
8526             } else {
8527 		boundsDirty = true;
8528 	    }
8529 	}
8530     }
8531 
8532 
getCoordRefFloat()8533     float[] getCoordRefFloat() {
8534 	return floatRefCoords;
8535     }
8536 
8537 
setCoordRefDouble(double[] coords)8538     void setCoordRefDouble(double[] coords) {
8539 
8540 	if (coords != null) {
8541 	    if ((vertexType & VERTEX_DEFINED) != 0 &&
8542 		(vertexType & VERTEX_DEFINED) != PD) {
8543 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
8544 	    }
8545 
8546 	    if (this instanceof IndexedGeometryArrayRetained) {
8547 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8548 		if (3 * idx.maxCoordIndex >= coords.length) {
8549 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
8550 		}
8551 	    } else if (coords.length < 3 * (initialCoordIndex+validVertexCount)) {
8552 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
8553 	    }
8554 	}
8555 	boolean isLive = source!=null && source.isLive();
8556 	if(isLive){
8557             geomLock.getLock();
8558 	}
8559 	dirtyFlag |= COORDINATE_CHANGED;
8560 	doubleRefCoords = coords;
8561 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8562 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8563 	    if (coords == null)
8564 		vertexType &= ~PD;
8565 	    else
8566 		vertexType |= PD;
8567 	}
8568 	else {
8569 	    setupMirrorVertexPointer(PD);
8570 	}
8571 	if(isLive) {
8572             geomLock.unLock();
8573         }
8574 	if (!inUpdater && source != null) {
8575 	    if (isLive) {
8576 		processCoordsChanged(coords == null);
8577 		sendDataChangedMessage(true);
8578 	    } else {
8579 		boundsDirty = true;
8580 	    }
8581 	}
8582     }
8583 
getCoordRefDouble()8584     double[] getCoordRefDouble() {
8585 	return doubleRefCoords;
8586     }
8587 
setCoordRef3f(Point3f[] coords)8588     void setCoordRef3f(Point3f[] coords) {
8589 
8590 	if (coords != null) {
8591 	    if ((vertexType & VERTEX_DEFINED) != 0 &&
8592 		(vertexType & VERTEX_DEFINED) != P3F) {
8593 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
8594 	    }
8595 
8596 	    if (this instanceof IndexedGeometryArrayRetained) {
8597 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8598 
8599 		if (idx.maxCoordIndex >= coords.length) {
8600 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
8601 		}
8602 	    } else if (coords.length < (initialCoordIndex+validVertexCount) ) {
8603 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
8604 	    }
8605 	}
8606 	boolean isLive = source!=null && source.isLive();
8607 	if(isLive){
8608             geomLock.getLock();
8609 	}
8610 	dirtyFlag |= COORDINATE_CHANGED;
8611 	p3fRefCoords = coords;
8612 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8613 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8614 	    if (coords == null)
8615 		vertexType &= ~P3F;
8616 	    else
8617 		vertexType |= P3F;
8618 	}
8619 	else {
8620 	    setupMirrorVertexPointer(P3F);
8621 	}
8622 	if(isLive) {
8623             geomLock.unLock();
8624         }
8625 	if (!inUpdater && source != null) {
8626 	    if (isLive) {
8627 		processCoordsChanged(coords == null);
8628 		sendDataChangedMessage(true);
8629 	    } else {
8630 		boundsDirty = true;
8631 	    }
8632 	}
8633     }
8634 
getCoordRef3f()8635     Point3f[] getCoordRef3f() {
8636 	return p3fRefCoords;
8637 
8638     }
8639 
setCoordRef3d(Point3d[] coords)8640     void setCoordRef3d(Point3d[] coords) {
8641 
8642 	if (coords != null) {
8643 	    if ((vertexType & VERTEX_DEFINED) != 0 &&
8644 		(vertexType & VERTEX_DEFINED) != P3D) {
8645 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
8646 	    }
8647 
8648 	    if (this instanceof IndexedGeometryArrayRetained) {
8649 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8650 
8651 		if (idx.maxCoordIndex >= coords.length) {
8652 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
8653 		}
8654 	    } else if (coords.length <  (initialCoordIndex+validVertexCount) ) {
8655 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
8656 	    }
8657 	}
8658 	boolean isLive = source!=null && source.isLive();
8659 	if(isLive){
8660             geomLock.getLock();
8661 	}
8662 	dirtyFlag |= COORDINATE_CHANGED;
8663 	p3dRefCoords = coords;
8664 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8665 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8666 	    if (coords == null)
8667 		vertexType &= ~P3D;
8668 	    else
8669 		vertexType |= P3D;
8670 	} else {
8671 	    setupMirrorVertexPointer(P3D);
8672 	}
8673 	if(isLive) {
8674             geomLock.unLock();
8675         }
8676 	if (!inUpdater && source != null) {
8677 	    if (isLive) {
8678 		processCoordsChanged(coords == null);
8679 		sendDataChangedMessage(true);
8680 	    } else {
8681 		boundsDirty = true;
8682 	    }
8683 	}
8684     }
8685 
getCoordRef3d()8686     Point3d[] getCoordRef3d() {
8687 	return p3dRefCoords;
8688     }
8689 
setColorRefFloat(float[] colors)8690     void setColorRefFloat(float[] colors) {
8691 
8692 	if (colors != null) {
8693 	    if ((vertexType & COLOR_DEFINED) != 0 &&
8694 		(vertexType & COLOR_DEFINED) != CF) {
8695 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
8696 	    }
8697 
8698 	    if ((vertexFormat & GeometryArray.COLOR) == 0) {
8699 		throw new IllegalStateException(J3dI18N.getString("GeometryArray123"));
8700 	    }
8701 
8702 	    if (this instanceof IndexedGeometryArrayRetained) {
8703 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8704 
8705 		if (getColorStride() * idx.maxColorIndex >= colors.length) {
8706 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
8707 		}
8708 	    } else  if (colors.length < getColorStride() * (initialColorIndex+ validVertexCount) ) {
8709 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
8710 	    }
8711 	}
8712 
8713 	boolean isLive = source!=null && source.isLive();
8714 	if(isLive){
8715             geomLock.getLock();
8716 	}
8717 	dirtyFlag |= COLOR_CHANGED;
8718 	colorChanged = 0xffff;
8719 	floatRefColors = colors;
8720 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8721 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8722 	    if (colors == null)
8723 		vertexType &= ~CF;
8724 	    else
8725 		vertexType |= CF;
8726 	}
8727 	else {
8728 	    setupMirrorColorPointer(CF, false);
8729 	}
8730 
8731 	if(isLive) {
8732             geomLock.unLock();
8733 	}
8734 	if (!inUpdater && isLive) {
8735 	    sendDataChangedMessage(false);
8736 	}
8737 
8738     }
8739 
getColorRefFloat()8740     float[] getColorRefFloat() {
8741 	return floatRefColors;
8742     }
8743 
8744 
8745     // set the color with nio buffer
setColorRefBuffer(J3DBuffer colors)8746     void setColorRefBuffer(J3DBuffer colors) {
8747 	if (colors != null) {
8748 	    switch(colors.getBufferType()) {
8749 	    case J3DBuffer.TYPE_FLOAT:
8750 		assert ((FloatBufferWrapper)colors.getBufferImpl()).isDirect();
8751 		break;
8752 	    case J3DBuffer.TYPE_BYTE:
8753 		assert ((ByteBufferWrapper)colors.getBufferImpl()).isDirect();
8754 		break;
8755 	    case J3DBuffer.TYPE_NULL:
8756 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray115"));
8757 
8758 	    default:
8759 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
8760 	    }
8761 
8762 	    if ((vertexFormat & GeometryArray.COLOR) == 0) {
8763 		throw new IllegalStateException(J3dI18N.getString("GeometryArray123"));
8764 	    }
8765 
8766 	    if (this instanceof IndexedGeometryArrayRetained) {
8767 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8768 
8769 		if (getColorStride() * idx.maxColorIndex >= colors.getBufferImpl().limit()) {
8770 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
8771 		}
8772 	    } else if (colors.getBufferImpl().limit() <
8773 		       getColorStride() * (initialColorIndex+validVertexCount)) {
8774 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
8775 	    }
8776 	}
8777 
8778 	boolean isLive = source!=null && source.isLive();
8779 	if(isLive){
8780             geomLock.getLock();
8781 	}
8782 	dirtyFlag |= COLOR_CHANGED;
8783 	colorChanged = 0xffff;
8784 	colorRefBuffer = colors;
8785 	if(colors == null) {
8786 	    floatBufferRefColors = null;
8787 	    byteBufferRefColors = null;
8788 	} else {
8789 	    switch (colors.getBufferType()) {
8790 	    case J3DBuffer.TYPE_FLOAT:
8791 		floatBufferRefColors = (FloatBufferWrapper)colors.getBufferImpl();
8792 		byteBufferRefColors = null;
8793 		break;
8794 
8795 	    case J3DBuffer.TYPE_BYTE:
8796 		byteBufferRefColors = (ByteBufferWrapper)colors.getBufferImpl();
8797 		floatBufferRefColors = null;
8798 		break;
8799 	    default:
8800 		break;
8801 	    }
8802 	}
8803 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8804 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8805 	    if(colors == null) {
8806 		vertexType &= ~CF;
8807 		vertexType &= ~CUB;
8808 	    } else {
8809 		switch (colors.getBufferType()) {
8810 		case J3DBuffer.TYPE_FLOAT:
8811 		    vertexType |= CF;
8812 		    vertexType &= ~CUB;
8813 		    break;
8814 
8815 		case J3DBuffer.TYPE_BYTE:
8816 		    vertexType |= CUB;
8817 		    vertexType &= ~CF;
8818 		    break;
8819 		default:
8820 		    break;
8821 		}
8822 	    }
8823 	}
8824 	else {
8825 	    setupMirrorColorPointer(CF|CUB, false);
8826 	}
8827 
8828 	if(isLive) {
8829             geomLock.unLock();
8830 	}
8831 
8832 	if (!inUpdater && isLive) {
8833 	    sendDataChangedMessage(false);
8834 	}
8835     }
8836 
8837     // return the color data in nio buffer format
getColorRefBuffer()8838     J3DBuffer getColorRefBuffer() {
8839 	return colorRefBuffer;
8840     }
8841 
setColorRefByte(byte[] colors)8842     void setColorRefByte(byte[] colors) {
8843 
8844 	if (colors != null) {
8845 	    if ((vertexType & COLOR_DEFINED) != 0 &&
8846 		(vertexType & COLOR_DEFINED) != CUB) {
8847 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
8848 	    }
8849 
8850 	    if ((vertexFormat & GeometryArray.COLOR) == 0) {
8851 		throw new IllegalStateException(J3dI18N.getString("GeometryArray123"));
8852 	    }
8853 
8854 	    if (this instanceof IndexedGeometryArrayRetained) {
8855 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8856 
8857 		if (getColorStride() * idx.maxColorIndex >= colors.length) {
8858 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
8859 		}
8860 	    } else if (colors.length < getColorStride() * (initialColorIndex + validVertexCount)) {
8861 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
8862 	    }
8863 	}
8864 	boolean isLive = source!=null && source.isLive();
8865 	if(isLive){
8866             geomLock.getLock();
8867 	}
8868 	dirtyFlag |= COLOR_CHANGED;
8869 	colorChanged = 0xffff;
8870 	byteRefColors = colors;
8871 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8872 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8873 	    if (colors == null)
8874 		vertexType &= ~CUB;
8875 	    else
8876 		vertexType |= CUB;
8877 	}
8878 	else {
8879 	    setupMirrorColorPointer(CUB, false);
8880 	}
8881 	if(isLive){
8882             geomLock.unLock();
8883 	}
8884 
8885 	if (!inUpdater && isLive) {
8886 	    sendDataChangedMessage(false);
8887 	}
8888 
8889     }
8890 
getColorRefByte()8891     byte[] getColorRefByte() {
8892 	return byteRefColors;
8893     }
8894 
setColorRef3f(Color3f[] colors)8895     void setColorRef3f(Color3f[] colors) {
8896 
8897 	if (colors != null) {
8898 	    if ((vertexType & COLOR_DEFINED) != 0 &&
8899 		(vertexType & COLOR_DEFINED) != C3F) {
8900 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
8901 	    }
8902 
8903 	    if ((vertexFormat & GeometryArray.COLOR_3) == 0) {
8904 		throw new IllegalStateException(J3dI18N.getString("GeometryArray92"));
8905 	    }
8906 
8907 	    if (this instanceof IndexedGeometryArrayRetained) {
8908 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8909 		if (idx.maxColorIndex >= colors.length) {
8910 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
8911 		}
8912 	    } else if (colors.length < (initialColorIndex + validVertexCount) ) {
8913 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
8914 	    }
8915 	}
8916 
8917 	boolean isLive = source!=null && source.isLive();
8918 	if(isLive){
8919             geomLock.getLock();
8920 	}
8921 	dirtyFlag |= COLOR_CHANGED;
8922 	colorChanged = 0xffff;
8923 	c3fRefColors = colors;
8924 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8925 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8926 	    if (colors == null)
8927 		vertexType &= ~C3F;
8928 	    else
8929 		vertexType |= C3F;
8930 	}
8931 	else {
8932 	    setupMirrorColorPointer(C3F, false);
8933 	}
8934 
8935 	if(isLive) {
8936             geomLock.unLock();
8937 	}
8938 
8939 	if (!inUpdater && isLive) {
8940 	    sendDataChangedMessage(false);
8941 	}
8942 
8943     }
8944 
getColorRef3f()8945     Color3f[] getColorRef3f() {
8946 	return c3fRefColors;
8947     }
8948 
8949 
setColorRef4f(Color4f[] colors)8950     void setColorRef4f(Color4f[] colors) {
8951 
8952 	if (colors != null) {
8953 	    if ((vertexType & COLOR_DEFINED) != 0 &&
8954 		(vertexType & COLOR_DEFINED) != C4F) {
8955 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
8956 	    }
8957 	    if ((vertexFormat & GeometryArray.COLOR_4) == 0) {
8958 		throw new IllegalStateException(J3dI18N.getString("GeometryArray93"));
8959 	    }
8960 
8961 	    if (this instanceof IndexedGeometryArrayRetained) {
8962 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
8963 		if (idx.maxColorIndex >= colors.length) {
8964 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
8965 		}
8966 	    } else if (colors.length < (initialColorIndex + validVertexCount) ) {
8967 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
8968 	    }
8969 	}
8970 	boolean isLive = source!=null && source.isLive();
8971 	if(isLive){
8972             geomLock.getLock();
8973 	}
8974 	dirtyFlag |= COLOR_CHANGED;
8975 	colorChanged = 0xffff;
8976 	c4fRefColors = colors;
8977 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
8978 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
8979 	    if (colors == null)
8980 		vertexType &= ~C4F;
8981 	    else
8982 		vertexType |= C4F;
8983 	}
8984 	else {
8985 	    setupMirrorColorPointer(C4F, false);
8986 	}
8987 	if(isLive) {
8988             geomLock.unLock();
8989 	}
8990 
8991 	if (!inUpdater && isLive) {
8992 	    sendDataChangedMessage(false);
8993 	}
8994     }
8995 
getColorRef4f()8996     Color4f[] getColorRef4f() {
8997 	return c4fRefColors;
8998     }
8999 
9000 
setColorRef3b(Color3b[] colors)9001     void setColorRef3b(Color3b[] colors) {
9002 
9003 	if (colors != null) {
9004 
9005 	    if ((vertexType & COLOR_DEFINED) != 0 &&
9006 		(vertexType & COLOR_DEFINED) != C3UB) {
9007 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
9008 	    }
9009 
9010 	    if ((vertexFormat & GeometryArray.COLOR_3) == 0) {
9011 		throw new IllegalStateException(J3dI18N.getString("GeometryArray92"));
9012 	    }
9013 
9014 	    if (this instanceof IndexedGeometryArrayRetained) {
9015 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9016 
9017 		if (idx.maxColorIndex >= colors.length) {
9018 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
9019 		}
9020 	    } else if (colors.length < (initialColorIndex + validVertexCount)) {
9021 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9022 	    }
9023 	}
9024 
9025 	boolean isLive = source!=null && source.isLive();
9026 	if(isLive){
9027             geomLock.getLock();
9028 	}
9029 	dirtyFlag |= COLOR_CHANGED;
9030 	colorChanged = 0xffff;
9031 	c3bRefColors = colors;
9032 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9033 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9034 	    if (colors == null)
9035 		vertexType &= ~C3UB;
9036 	    else
9037 		vertexType |= C3UB;
9038 	}
9039 	else {
9040 	    setupMirrorColorPointer(C3UB, false);
9041 	}
9042 
9043 	if(isLive) {
9044             geomLock.unLock();
9045 	}
9046 
9047 	if (!inUpdater && isLive) {
9048 	    sendDataChangedMessage(false);
9049         }
9050     }
9051 
9052 
getColorRef3b()9053     Color3b[] getColorRef3b() {
9054 	return c3bRefColors;
9055     }
9056 
setColorRef4b(Color4b[] colors)9057     void setColorRef4b(Color4b[] colors) {
9058 
9059 	if (colors != null) {
9060 	    if ((vertexType & COLOR_DEFINED) != 0 &&
9061 		(vertexType & COLOR_DEFINED) != C4UB) {
9062 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
9063 	    }
9064 
9065 	    if ((vertexFormat & GeometryArray.COLOR_4) == 0) {
9066 		throw new IllegalStateException(J3dI18N.getString("GeometryArray93"));
9067 	    }
9068 
9069 	    if (this instanceof IndexedGeometryArrayRetained) {
9070 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this;
9071 
9072 		if (idx.maxColorIndex >= colors.length) {
9073 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
9074 		}
9075 	    } else if (colors.length < (initialColorIndex + validVertexCount) ) {
9076 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9077 	    }
9078 	}
9079 	boolean isLive = source!=null && source.isLive();
9080 	if(isLive){
9081             geomLock.getLock();
9082 	}
9083 	dirtyFlag |= COLOR_CHANGED;
9084 	colorChanged = 0xffff;
9085 	c4bRefColors = colors;
9086 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9087 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9088 	    if (colors == null)
9089 		vertexType &= ~C4UB;
9090 	    else
9091 		vertexType |= C4UB;
9092 	}
9093 	else {
9094 	    setupMirrorColorPointer(C4UB, false);
9095 	}
9096 
9097 	if(isLive) {
9098             geomLock.unLock();
9099 	}
9100 	if (!inUpdater && isLive) {
9101 	    sendDataChangedMessage(false);
9102         }
9103     }
9104 
9105 
getColorRef4b()9106     Color4b[] getColorRef4b() {
9107 	return c4bRefColors;
9108     }
9109 
setNormalRefFloat(float[] normals)9110     void setNormalRefFloat(float[] normals) {
9111 
9112 	if (normals != null) {
9113 	    if ((vertexType & NORMAL_DEFINED) != 0 &&
9114 		(vertexType & NORMAL_DEFINED) != NF) {
9115 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
9116 	    }
9117 
9118 	    if ((vertexFormat & GeometryArray.NORMALS) == 0) {
9119 		throw new IllegalStateException(J3dI18N.getString("GeometryArray122"));
9120 	    }
9121 
9122 	    if (this instanceof IndexedGeometryArrayRetained) {
9123 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9124 
9125 		if (idx.maxNormalIndex*3 >= normals.length) {
9126 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray26"));
9127 		}
9128 	    } else if (normals.length < 3 * (initialNormalIndex + validVertexCount )) {
9129 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
9130 	    }
9131 	}
9132 	boolean isLive = source!=null && source.isLive();
9133 	if(isLive){
9134             geomLock.getLock();
9135 	}
9136 	dirtyFlag |= NORMAL_CHANGED;
9137 	floatRefNormals = normals;
9138 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9139 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9140 	    if (normals == null)
9141 		vertexType &= ~NF;
9142 	    else
9143 		vertexType |= NF;
9144 	}
9145 	else {
9146 	    setupMirrorNormalPointer(NF);
9147 	}
9148 	if(isLive) {
9149             geomLock.unLock();
9150 	}
9151 	if (!inUpdater && isLive) {
9152 		sendDataChangedMessage(false);
9153 	}
9154 
9155     }
9156 
getNormalRefFloat()9157     float[] getNormalRefFloat() {
9158 	return floatRefNormals;
9159     }
9160 
9161     // setup the normal with nio buffer
setNormalRefBuffer(J3DBuffer normals)9162     void setNormalRefBuffer(J3DBuffer normals) {
9163 
9164 	FloatBufferWrapper bufferImpl = null;
9165 
9166 	if (normals != null) {
9167 	    if(normals.getBufferType() != J3DBuffer.TYPE_FLOAT)
9168 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
9169 
9170 	    bufferImpl = (FloatBufferWrapper)normals.getBufferImpl();
9171 
9172 	    assert bufferImpl.isDirect();
9173 
9174 	    if ((vertexFormat & GeometryArray.NORMALS) == 0) {
9175 		throw new IllegalStateException(J3dI18N.getString("GeometryArray122"));
9176 	    }
9177 
9178 	    if (this instanceof IndexedGeometryArrayRetained) {
9179 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9180 		if (idx.maxNormalIndex * 3 >=
9181 		    ((FloatBufferWrapper)normals.getBufferImpl()).limit()) {
9182 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray26"));
9183 		}
9184 	    } else if (bufferImpl.limit() < 3 * (initialNormalIndex + validVertexCount )) {
9185 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
9186 	    }
9187 	}
9188 	boolean isLive = source!=null && source.isLive();
9189 	if(isLive){
9190             geomLock.getLock();
9191 	}
9192 	dirtyFlag |= NORMAL_CHANGED;
9193 	normalRefBuffer = normals;
9194 
9195 	if (normals == null) {
9196 	    vertexType &= ~NF;
9197 	    floatBufferRefNormals = null;
9198 	}
9199 	else {
9200 	    vertexType |= NF;
9201 	    floatBufferRefNormals = bufferImpl;
9202 	}
9203 	if(isLive) {
9204             geomLock.unLock();
9205 	}
9206 	if (!inUpdater && isLive) {
9207 		sendDataChangedMessage(false);
9208 	}
9209     }
9210 
getNormalRefBuffer()9211     J3DBuffer getNormalRefBuffer() {
9212 	return normalRefBuffer;
9213     }
9214 
setNormalRef3f(Vector3f[] normals)9215     void setNormalRef3f(Vector3f[] normals) {
9216 
9217 	if (normals != null) {
9218 	    if ((vertexType & NORMAL_DEFINED) != 0 &&
9219 		(vertexType & NORMAL_DEFINED) != N3F) {
9220 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray98"));
9221 	    }
9222 
9223 	    if ((vertexFormat & GeometryArray.NORMALS) == 0) {
9224 		throw new IllegalStateException(J3dI18N.getString("GeometryArray122"));
9225 	    }
9226 
9227 	    if (this instanceof IndexedGeometryArrayRetained) {
9228 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9229 		if (idx.maxNormalIndex >= normals.length) {
9230 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray26"));
9231 		}
9232 	    } else if (normals.length < (initialNormalIndex + validVertexCount) ) {
9233 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
9234 	    }
9235 	}
9236 	boolean isLive = source!=null && source.isLive();
9237 	if(isLive){
9238             geomLock.getLock();
9239 	}
9240 	dirtyFlag |= NORMAL_CHANGED;
9241 	v3fRefNormals = normals;
9242 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9243 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9244 	    if (normals == null)
9245 		vertexType &= ~N3F;
9246 	    else
9247 		vertexType |= N3F;
9248 	}
9249 	else {
9250 	    setupMirrorNormalPointer(N3F);
9251 	}
9252 	if(isLive) {
9253             geomLock.unLock();
9254 	}
9255 	if (!inUpdater && isLive) {
9256 	    sendDataChangedMessage(false);
9257 	}
9258     }
9259 
getNormalRef3f()9260     Vector3f[] getNormalRef3f() {
9261 	return v3fRefNormals;
9262     }
9263 
getColorStride()9264     final int getColorStride() {
9265 	return ((vertexFormat & GeometryArray.WITH_ALPHA) != 0 ? 4 : 3);
9266     }
9267 
getTexStride()9268     final int getTexStride() {
9269 	if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
9270 	    return 2;
9271 	}
9272 	if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
9273 	    return 3;
9274 	}
9275 	if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
9276 	    return 4;
9277 	}
9278 
9279 	throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray121"));
9280     }
9281 
setTexCoordRefFloat(int texCoordSet, float[] texCoords)9282     void setTexCoordRefFloat(int texCoordSet, float[] texCoords) {
9283 
9284         if (texCoordType != 0 && texCoordType != TF) {
9285             if (texCoords != null) {
9286                 throw new IllegalArgumentException(
9287                         J3dI18N.getString("GeometryArray98"));
9288             }
9289             return;
9290         }
9291 
9292         if (texCoords != null) {
9293 
9294             int ts = getTexStride();
9295 
9296 	    if (this instanceof IndexedGeometryArrayRetained) {
9297 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9298 
9299 		if (idx.maxTexCoordIndices[texCoordSet]*ts >= texCoords.length) {
9300 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray25"));
9301 		}
9302 	    } else if (texCoords.length < ts*(initialTexCoordIndex[texCoordSet]+validVertexCount)) {
9303 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray113"));
9304 	    }
9305 	}
9306         boolean isLive = source!=null && source.isLive();
9307         if(isLive){
9308             geomLock.getLock();
9309         }
9310 	dirtyFlag |= TEXTURE_CHANGED;
9311 	refTexCoords[texCoordSet] = texCoords;
9312 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9313 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9314 	    texCoordType = TF;
9315             validateTexCoordPointerType();
9316 	}
9317 	else {
9318 	    setupMirrorTexCoordPointer(texCoordSet, TF);
9319 	}
9320 	if(isLive) {
9321             geomLock.unLock();
9322 	}
9323 	if (!inUpdater && isLive) {
9324 	    sendDataChangedMessage(false);
9325 	}
9326     }
9327 
9328 
getTexCoordRefFloat(int texCoordSet)9329     float[] getTexCoordRefFloat(int texCoordSet) {
9330 	return ((float[])refTexCoords[texCoordSet]);
9331     }
9332 
9333     // set the tex coord with nio buffer
setTexCoordRefBuffer(int texCoordSet, J3DBuffer texCoords)9334     void setTexCoordRefBuffer(int texCoordSet, J3DBuffer texCoords) {
9335 
9336 	FloatBufferWrapper bufferImpl = null;
9337 
9338 	if (texCoords != null) {
9339 	    if(texCoords.getBufferType() != J3DBuffer.TYPE_FLOAT)
9340 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
9341 
9342 	    bufferImpl = (FloatBufferWrapper)texCoords.getBufferImpl();
9343 	    int bufferSize = bufferImpl.limit();
9344 
9345 	    assert bufferImpl.isDirect();
9346 
9347 	    int ts = getTexStride();
9348 
9349 	    if (this instanceof IndexedGeometryArrayRetained) {
9350 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9351 		if (idx.maxTexCoordIndices[texCoordSet] * ts >= bufferSize) {
9352 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray25"));
9353 		}
9354 	    } else if (bufferSize < ts*(initialTexCoordIndex[texCoordSet] + validVertexCount)) {
9355 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray113"));
9356 	    }
9357 	}
9358 	boolean isLive = source!=null && source.isLive();
9359 	if(isLive){
9360             geomLock.getLock();
9361 	}
9362 	dirtyFlag |= TEXTURE_CHANGED;
9363 	// refTexCoordsBuffer contains J3DBuffer object for tex coord
9364 	refTexCoordsBuffer[texCoordSet] = texCoords;
9365 	if (texCoords == null) {
9366 	    refTexCoords[texCoordSet] = null;
9367 	}
9368 	else {
9369 	    // refTexCoords contains NIOBuffer object for tex coord
9370 	    refTexCoords[texCoordSet] = bufferImpl.getBufferAsObject();
9371 	}
9372         texCoordType = TF;
9373         validateTexCoordPointerType();
9374         if(isLive) {
9375             geomLock.unLock();
9376         }
9377 	if (!inUpdater && isLive) {
9378 	    sendDataChangedMessage(false);
9379 	}
9380     }
9381 
getTexCoordRefBuffer(int texCoordSet)9382     J3DBuffer getTexCoordRefBuffer(int texCoordSet) {
9383 	return (J3DBuffer)(refTexCoordsBuffer[texCoordSet]);
9384     }
9385 
setTexCoordRef2f(int texCoordSet, TexCoord2f[] texCoords)9386     void setTexCoordRef2f(int texCoordSet, TexCoord2f[] texCoords) {
9387 
9388         if (texCoordType != 0 && texCoordType != T2F) {
9389             if (texCoords != null) {
9390                 throw new IllegalArgumentException(
9391                         J3dI18N.getString("GeometryArray98"));
9392             }
9393             return;
9394         }
9395 
9396         if (texCoords != null) {
9397 	    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) == 0) {
9398 		throw new IllegalStateException(
9399 				J3dI18N.getString("GeometryArray94"));
9400 	    }
9401 
9402 	    if (this instanceof IndexedGeometryArrayRetained) {
9403 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9404 
9405 		if (idx.maxTexCoordIndices[texCoordSet] >= texCoords.length) {
9406 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray25"));
9407 		}
9408 	    } else if (texCoords.length < (initialTexCoordIndex[texCoordSet] + validVertexCount) ) {
9409 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray113"));
9410 	    }
9411 
9412 	}
9413         boolean isLive = source!=null && source.isLive();
9414         if(isLive){
9415             geomLock.getLock();
9416         }
9417 	dirtyFlag |= TEXTURE_CHANGED;
9418 	refTexCoords[texCoordSet] = texCoords;
9419 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9420 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9421 	    texCoordType = T2F;
9422             validateTexCoordPointerType();
9423 	}
9424 	else {
9425 	    setupMirrorTexCoordPointer(texCoordSet, T2F);
9426 	}
9427 	if(isLive) {
9428             geomLock.unLock();
9429         }
9430 	if (!inUpdater && isLive) {
9431 		sendDataChangedMessage(false);
9432 	}
9433     }
9434 
9435 
getTexCoordRef2f(int texCoordSet)9436     TexCoord2f[] getTexCoordRef2f(int texCoordSet) {
9437 	if (refTexCoords != null && refTexCoords[texCoordSet] != null &&
9438 		refTexCoords[texCoordSet] instanceof TexCoord2f[]) {
9439 	    return ((TexCoord2f[])refTexCoords[texCoordSet]);
9440 	} else {
9441 	    return null;
9442 	}
9443     }
9444 
9445 
setTexCoordRef3f(int texCoordSet, TexCoord3f[] texCoords)9446     void setTexCoordRef3f(int texCoordSet, TexCoord3f[] texCoords) {
9447 
9448         if (texCoordType != 0 && texCoordType != T3F) {
9449             if (texCoords != null) {
9450                 throw new IllegalArgumentException(
9451                         J3dI18N.getString("GeometryArray98"));
9452             }
9453             return;
9454         }
9455 
9456 	if (texCoords != null) {
9457 
9458 	    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) == 0) {
9459 		throw new IllegalStateException(
9460 				J3dI18N.getString("GeometryArray95"));
9461 	    }
9462 
9463 	    if (this instanceof IndexedGeometryArrayRetained) {
9464 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9465 
9466 		if (idx.maxTexCoordIndices[texCoordSet] >= texCoords.length) {
9467 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray25"));
9468 		}
9469 
9470 	    } else if (texCoords.length < (initialTexCoordIndex[texCoordSet] + validVertexCount) ) {
9471 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray113"));
9472 	    }
9473 
9474 	}
9475 	boolean isLive = source!=null && source.isLive();
9476 	if(isLive){
9477             geomLock.getLock();
9478 	}
9479 	dirtyFlag |= TEXTURE_CHANGED;
9480 	refTexCoords[texCoordSet] = texCoords;
9481 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9482 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9483 	    texCoordType = T3F;
9484             validateTexCoordPointerType();
9485 	}
9486 	else {
9487 	    setupMirrorTexCoordPointer(texCoordSet, T3F);
9488 	}
9489 	if(isLive) {
9490             geomLock.unLock();
9491 	}
9492 	if (!inUpdater && isLive) {
9493 	    sendDataChangedMessage(false);
9494 	}
9495     }
9496 
9497 
getTexCoordRef3f(int texCoordSet)9498     TexCoord3f[] getTexCoordRef3f(int texCoordSet) {
9499 	if (refTexCoords != null && refTexCoords[texCoordSet] != null &&
9500 		refTexCoords[texCoordSet] instanceof TexCoord3f[]) {
9501 	    return ((TexCoord3f[])refTexCoords[texCoordSet]);
9502 	} else {
9503 	    return null;
9504 	}
9505     }
9506 
9507 
9508     /**
9509      * Sets the float vertex attribute array reference for the
9510      * specified vertex attribute number to the specified array.
9511      */
setVertexAttrRefFloat(int vertexAttrNum, float[] vertexAttrs)9512     void setVertexAttrRefFloat(int vertexAttrNum, float[] vertexAttrs) {
9513 
9514         // XXXX: Add the following test if we ever add double-precision types
9515         /*
9516         if (vertexAttrType != 0 && vertexAttrType != AF) {
9517             if (vertexAttrs != null) {
9518                 // XXXX: new exception string
9519                 throw new IllegalArgumentException(
9520                         J3dI18N.getString("GeometryArray98-XXX"));
9521             }
9522             return;
9523         }
9524         */
9525 
9526         if (vertexAttrs != null) {
9527             int sz = vertexAttrSizes[vertexAttrNum];
9528 
9529             if (this instanceof IndexedGeometryArrayRetained) {
9530                 IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9531 
9532 		if (sz*idx.maxVertexAttrIndices[vertexAttrNum] >= vertexAttrs.length) {
9533 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30"));
9534 		}
9535 
9536 	    } else if (vertexAttrs.length < sz*(initialVertexAttrIndex[vertexAttrNum] + validVertexCount) ) {
9537 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray129"));
9538 	    }
9539 	}
9540         boolean isLive = source!=null && source.isLive();
9541         if(isLive){
9542             geomLock.getLock();
9543         }
9544 	dirtyFlag |= VATTR_CHANGED;
9545 	floatRefVertexAttrs[vertexAttrNum] = vertexAttrs;
9546 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9547 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9548 	    vertexAttrType = AF;
9549             validateVertexAttrPointerType();
9550 	}
9551 	else {
9552 	    setupMirrorVertexAttrPointer(vertexAttrNum, AF);
9553 	}
9554 	if(isLive) {
9555             geomLock.unLock();
9556         }
9557 	if (!inUpdater && isLive) {
9558 	    sendDataChangedMessage(false);
9559 	}
9560     }
9561 
9562     /**
9563      * Gets the float vertex attribute array reference for the specified
9564      * vertex attribute number.
9565      */
getVertexAttrRefFloat(int vertexAttrNum)9566     float[] getVertexAttrRefFloat(int vertexAttrNum) {
9567         return floatRefVertexAttrs[vertexAttrNum];
9568     }
9569 
9570 
9571     /**
9572      * Sets the vertex attribute buffer reference for the specified
9573      * vertex attribute number to the specified buffer object.
9574      */
setVertexAttrRefBuffer(int vertexAttrNum, J3DBuffer vertexAttrs)9575     void setVertexAttrRefBuffer(int vertexAttrNum, J3DBuffer vertexAttrs) {
9576 
9577 	FloatBufferWrapper bufferImpl = null;
9578 
9579 	if (vertexAttrs != null) {
9580 	    if(vertexAttrs.getBufferType() != J3DBuffer.TYPE_FLOAT)
9581 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
9582 
9583 	    bufferImpl = (FloatBufferWrapper)vertexAttrs.getBufferImpl();
9584 	    int bufferSize = bufferImpl.limit();
9585 
9586 	    assert bufferImpl.isDirect();
9587 
9588 	    int sz = vertexAttrSizes[vertexAttrNum];
9589 
9590             if (this instanceof IndexedGeometryArrayRetained) {
9591 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9592 
9593 		if (idx.maxVertexAttrIndices[vertexAttrNum] * sz >= bufferSize) {
9594 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30"));
9595 		}
9596 	    } else if (bufferSize < sz*(initialVertexAttrIndex[vertexAttrNum] + validVertexCount)) {
9597 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray129"));
9598             }
9599         }
9600         boolean isLive = source!=null && source.isLive();
9601         if(isLive){
9602             geomLock.getLock();
9603         }
9604         dirtyFlag |= VATTR_CHANGED;
9605         vertexAttrsRefBuffer[vertexAttrNum] = vertexAttrs;
9606         if (vertexAttrs == null) {
9607             floatBufferRefVertexAttrs[vertexAttrNum] = null;
9608             nioFloatBufferRefVertexAttrs[vertexAttrNum] = null;
9609         }
9610         else {
9611             floatBufferRefVertexAttrs[vertexAttrNum] = bufferImpl;
9612             nioFloatBufferRefVertexAttrs[vertexAttrNum] =
9613                 bufferImpl.getBufferAsObject();
9614         }
9615         vertexAttrType = AF;
9616         validateVertexAttrPointerType();
9617         if(isLive) {
9618             geomLock.unLock();
9619         }
9620         if (!inUpdater && isLive) {
9621             sendDataChangedMessage(false);
9622         }
9623 
9624     }
9625 
9626     /**
9627      * Gets the vertex attribute array buffer reference for the specified
9628      * vertex attribute number.
9629      */
getVertexAttrRefBuffer(int vertexAttrNum)9630     J3DBuffer getVertexAttrRefBuffer(int vertexAttrNum) {
9631 	return vertexAttrsRefBuffer[vertexAttrNum];
9632     }
9633 
9634 
setInterleavedVertices(float[] vertexData)9635     void setInterleavedVertices(float[] vertexData) {
9636 	if (vertexData != null) {
9637 
9638 	    if (this instanceof IndexedGeometryArrayRetained) {
9639 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9640 
9641 		if (stride * idx.maxCoordIndex >= vertexData.length) {
9642 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
9643 		}
9644 
9645 		if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
9646 		    for (int i = 0; i < texCoordSetCount; i++) {
9647 			if (stride * idx.maxTexCoordIndices[i] >= vertexData.length) {
9648 			    throw new ArrayIndexOutOfBoundsException(
9649                                       J3dI18N.getString("IndexedGeometryArray25"));
9650 			}
9651 		    }
9652 		}
9653 
9654 		if (((this.vertexFormat & GeometryArray.COLOR) != 0) &&
9655 		    (stride * idx.maxColorIndex >= vertexData.length)) {
9656 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
9657 		}
9658 
9659 		if (((this.vertexFormat & GeometryArray.NORMALS) != 0) &&
9660 		    (stride * idx.maxNormalIndex >= vertexData.length)) {
9661 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray26"));
9662 		}
9663 	    } else {
9664 		if (vertexData.length < (stride * (initialVertexIndex+validVertexCount)))
9665 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
9666 	    }
9667 	}
9668 
9669 	// If the geometry has been rendered transparent, then make a copy
9670 	// of the color pointer with 4f
9671         boolean isLive = source!=null && source.isLive();
9672 	if(isLive){
9673             geomLock.getLock();
9674 	}
9675 	dirtyFlag |= VERTEX_CHANGED;
9676 	colorChanged = 0xffff;
9677 	interLeavedVertexData = vertexData;
9678 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9679 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9680 	    setupMirrorInterleavedColorPointer(false);
9681 	}
9682 	if(isLive) {
9683             geomLock.unLock();
9684 	}
9685 	if (!inUpdater && isLive) {
9686 	    processCoordsChanged(vertexData == null);
9687 	    sendDataChangedMessage(true);
9688 	}
9689     }
9690 
9691     // set the interleaved vertex with NIO buffer
setInterleavedVertexBuffer(J3DBuffer vertexData)9692     void setInterleavedVertexBuffer(J3DBuffer vertexData) {
9693 
9694 	FloatBufferWrapper bufferImpl = null;
9695 
9696 	if (vertexData != null ){
9697 
9698 	    if (vertexData.getBufferType() != J3DBuffer.TYPE_FLOAT)
9699 		throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116"));
9700 
9701 	    bufferImpl = (FloatBufferWrapper)vertexData.getBufferImpl();
9702 
9703             assert bufferImpl.isDirect();
9704 
9705 	    int bufferSize = bufferImpl.limit();
9706 
9707 	    if (this instanceof IndexedGeometryArrayRetained) {
9708 		IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this;
9709 
9710 		if (stride * idx.maxCoordIndex >= bufferSize) {
9711 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
9712 		}
9713 
9714 		if ((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
9715 		    for (int i = 0; i < texCoordSetCount; i++) {
9716 			if (stride * idx.maxTexCoordIndices[i] >= bufferSize) {
9717 			    throw new ArrayIndexOutOfBoundsException(
9718                                   J3dI18N.getString("IndexedGeometryArray25"));
9719 			}
9720 		    }
9721 		}
9722 
9723 		if (((this.vertexFormat & GeometryArray.COLOR) != 0) &&
9724 		    (stride * idx.maxColorIndex >= bufferSize)) {
9725 		    	throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray24"));
9726 		}
9727 
9728 		if (((this.vertexFormat & GeometryArray.NORMALS) != 0) &&
9729 		    (stride * idx.maxNormalIndex >= bufferSize)) {
9730 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23"));
9731 		}
9732 	    } else {
9733 		if (bufferSize < (stride * (initialVertexIndex+validVertexCount)))
9734 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
9735 	    }
9736 	}
9737 	// If the geometry has been rendered transparent, then make a copy
9738 	// of the color pointer with 4f
9739 	boolean isLive = source!=null && source.isLive();
9740 	if(isLive){
9741             geomLock.getLock();
9742 	}
9743 	dirtyFlag |= VERTEX_CHANGED;
9744 	colorChanged = 0xffff;
9745 	interleavedVertexBuffer = vertexData;
9746 
9747 	if(vertexData == null)
9748 	    interleavedFloatBufferImpl = null;
9749 	else
9750 	    interleavedFloatBufferImpl = bufferImpl;
9751 
9752 	if (inUpdater || (this instanceof IndexedGeometryArrayRetained &&
9753 			  ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
9754 	    setupMirrorInterleavedColorPointer(false);
9755 	}
9756 	if(isLive) {
9757             geomLock.unLock();
9758 	}
9759 	if (!inUpdater && isLive) {
9760 	    processCoordsChanged(vertexData == null);
9761 	    sendDataChangedMessage(true);
9762 	}
9763     }
9764 
getInterleavedVertices()9765     float[] getInterleavedVertices() {
9766 	return interLeavedVertexData;
9767     }
9768 
getInterleavedVertexBuffer()9769     J3DBuffer getInterleavedVertexBuffer() {
9770 	return interleavedVertexBuffer;
9771     }
9772 
setValidVertexCount(int validVertexCount)9773     void setValidVertexCount(int validVertexCount) {
9774 
9775 	boolean nullGeo = false;
9776 	if (validVertexCount < 0) {
9777 	    throw new IllegalArgumentException(J3dI18N.getString("GeometryArray110"));
9778 	}
9779 
9780         if ((initialVertexIndex + validVertexCount) > vertexCount) {
9781             throw new IllegalArgumentException(J3dI18N.getString("GeometryArray100"));
9782         }
9783 
9784         if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
9785             // Interleaved, by-ref
9786 
9787             // use nio buffer for interleaved data
9788 	    if(( vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0 && interleavedFloatBufferImpl != null){
9789 		if(interleavedFloatBufferImpl.limit() <  stride * (initialVertexIndex + validVertexCount)) {
9790 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
9791 		}
9792 	    }
9793 	    //use java array for interleaved data
9794 	    else if( interLeavedVertexData != null) {
9795 		if(interLeavedVertexData.length < stride * (initialVertexIndex + validVertexCount)) {
9796 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
9797 		}
9798 	    }
9799 	    else {
9800 		nullGeo = true;
9801 	    }
9802 	} else if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) {
9803             // Non-interleaved, by-ref
9804 
9805             if ((initialCoordIndex + validVertexCount) > vertexCount) {
9806                 throw new IllegalArgumentException(J3dI18N.getString("GeometryArray104"));
9807             }
9808             if ((initialColorIndex + validVertexCount) > vertexCount) {
9809                 throw new IllegalArgumentException(J3dI18N.getString("GeometryArray101"));
9810             }
9811             if ((initialNormalIndex + validVertexCount) > vertexCount) {
9812                 throw new IllegalArgumentException(J3dI18N.getString("GeometryArray102"));
9813             }
9814 
9815             if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
9816                 for (int i = 0; i < texCoordSetCount; i++) {
9817                     if ((initialTexCoordIndex[i] + validVertexCount) > vertexCount) {
9818                         throw new IllegalArgumentException(J3dI18N.getString(
9819                                 "GeometryArray103"));
9820                     }
9821                 }
9822             }
9823 
9824             if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
9825                 for (int i = 0; i < vertexAttrCount; i++) {
9826                     if ((initialVertexAttrIndex[i] + validVertexCount) > vertexCount) {
9827                         throw new IllegalArgumentException(J3dI18N.getString(
9828                                 "GeometryArray130"));
9829                     }
9830                 }
9831             }
9832 
9833             if ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0) {
9834 		nullGeo = true;
9835             }
9836 
9837 	    if (( vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
9838 		// by reference with nio buffer
9839 		switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
9840 		case PF:
9841 		    if(floatBufferRefCoords.limit() < 3 * (initialCoordIndex+validVertexCount) ) {
9842 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
9843 		    }
9844 		    break;
9845 		case PD:
9846 		    if(doubleBufferRefCoords.limit() < 3 * (initialCoordIndex+validVertexCount) ) {
9847 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
9848 		    }
9849 		    break;
9850 		}
9851 
9852 		switch ((vertexType & COLOR_DEFINED)) {
9853 		case CF:
9854 		    if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
9855 			if (floatBufferRefColors.limit() < 3 * (initialColorIndex+validVertexCount)) {
9856 			    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9857 			}
9858 		    }
9859 		    else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
9860 			if (floatBufferRefColors.limit() < 4 * (initialColorIndex+validVertexCount)) {
9861 			    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9862 			}
9863 		    }
9864 		    break;
9865 		case CUB:
9866 		    if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
9867 			if (byteBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
9868 			    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9869 			}
9870 		    }
9871 		    else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
9872 			if (byteBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount) ) {
9873 			    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9874 			}
9875 		    }
9876 		    break;
9877 		}
9878 		switch ((vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
9879 		case TF:
9880 		    FloatBufferWrapper texBuffer;
9881 		    for (int i = 0; i < texCoordSetCount; i++) {
9882 			texBuffer = (FloatBufferWrapper)(((J3DBuffer)refTexCoordsBuffer[i]).getBufferImpl());
9883 			if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
9884 			    if (texBuffer.limit() <  2 * (initialTexCoordIndex[i] + validVertexCount) ) {
9885 				throw new ArrayIndexOutOfBoundsException(
9886 									 J3dI18N.getString("GeometryArray113"));
9887 			    }
9888 			} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
9889 			    if (texBuffer.limit() < 3 * (initialTexCoordIndex[i] + validVertexCount) ) {
9890 				throw new ArrayIndexOutOfBoundsException(
9891 									 J3dI18N.getString("GeometryArray113"));
9892 			    }
9893 			} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
9894 			    if (texBuffer.limit() < 4 * (initialTexCoordIndex[i] + validVertexCount)) {
9895 				throw new ArrayIndexOutOfBoundsException(
9896 									 J3dI18N.getString("GeometryArray113"));
9897 			    }
9898 			}
9899 		    }
9900 		    break;
9901 		}
9902 		switch ((vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
9903 		case NF:
9904 		    if (floatBufferRefNormals.limit() < 3 * (initialNormalIndex + validVertexCount )) {
9905 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
9906 		    }
9907 		    break;
9908 		}
9909 		switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) {
9910 		case AF:
9911                     for (int i = 0; i < vertexAttrCount; i++) {
9912                         int sz = vertexAttrSizes[i];
9913                         if (floatBufferRefVertexAttrs[i].limit() <
9914                                 (sz * (initialVertexAttrIndex[i] + validVertexCount)) ) {
9915                             throw new ArrayIndexOutOfBoundsException(
9916                                     J3dI18N.getString("GeometryArray129"));
9917                         }
9918                     }
9919 		    break;
9920 		}
9921 	    }
9922 	    // By reference with java array
9923 	    else {
9924 		switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
9925 		case PF:
9926 		    if (floatRefCoords.length < 3 * (initialCoordIndex+validVertexCount)) {
9927 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
9928 		    }
9929 		    break;
9930 		case PD:
9931 		    if (doubleRefCoords.length < 3 * (initialCoordIndex+validVertexCount)) {
9932 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
9933 		    }
9934 		    break;
9935 		case P3F:
9936 		    if (p3fRefCoords.length < (initialCoordIndex+validVertexCount) ) {
9937 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
9938 		    }
9939 		    break;
9940 		case P3D:
9941 		    if (p3dRefCoords.length <  (initialCoordIndex+validVertexCount) ) {
9942 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
9943 		    }
9944 		    break;
9945 		}
9946 		switch ((vertexType & COLOR_DEFINED)) {
9947 		case CF:
9948 		    if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
9949 			if (floatRefColors.length < 3 * (initialColorIndex+validVertexCount)) {
9950 			    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9951 			}
9952 		    }
9953 		    else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
9954 			if (floatRefColors.length < 4 * (initialColorIndex+ validVertexCount) ) {
9955 			    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9956 			}
9957 		    }
9958 		    break;
9959 		case CUB:
9960 		    if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
9961 			if (byteRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
9962 			    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9963 			}
9964 		    }
9965 		    else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
9966 			if (byteRefColors.length < 4 * (initialColorIndex + validVertexCount) ) {
9967 			    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9968 			}
9969 		    }
9970 		    break;
9971 		case C3F:
9972 		    if (c3fRefColors.length < (initialColorIndex + validVertexCount) ) {
9973 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9974 		    }
9975 		    break;
9976 		case C4F:
9977 		    if (c4fRefColors.length < (initialColorIndex + validVertexCount) ) {
9978 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9979 		    }
9980 		    break;
9981 		case C3UB:
9982 		    if (c3bRefColors.length < (initialColorIndex + validVertexCount)) {
9983 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9984 		    }
9985 		    break;
9986 		case C4UB:
9987 		    if (c4bRefColors.length < (initialColorIndex + validVertexCount) ) {
9988 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
9989 		    }
9990 		    break;
9991 		}
9992 		switch ((vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
9993 		case TF:
9994 		    for (int i = 0; i < texCoordSetCount; i++) {
9995 			if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
9996 			    if (((float[])refTexCoords[i]).length < 2 * (initialTexCoordIndex[i] + validVertexCount) ) {
9997 				throw new ArrayIndexOutOfBoundsException(
9998 									 J3dI18N.getString("GeometryArray113"));
9999 			    }
10000 			} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10001 			    if (((float[])refTexCoords[i]).length < 3 * (initialTexCoordIndex[i] + validVertexCount) ) {
10002 				throw new ArrayIndexOutOfBoundsException(
10003 									 J3dI18N.getString("GeometryArray113"));
10004 			    } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10005 				if (((float[])refTexCoords[i]).length < 4 * (initialTexCoordIndex[i] + validVertexCount)) {
10006 				    throw new ArrayIndexOutOfBoundsException(
10007 									     J3dI18N.getString("GeometryArray113"));
10008 				}
10009 			    }
10010 			}
10011 		    }
10012 		    break;
10013 		case T2F:
10014 		    for (int i = 0; i < texCoordSetCount; i++) {
10015 			if (((TexCoord2f[])refTexCoords[i]).length < (initialTexCoordIndex[i] + validVertexCount) ) {
10016 			    throw new ArrayIndexOutOfBoundsException(
10017 								     J3dI18N.getString("GeometryArray113"));
10018 			}
10019 		    }
10020 		    break;
10021 		case T3F:
10022 		    for (int i = 0; i < texCoordSetCount; i++) {
10023 			if (((TexCoord3f[])refTexCoords[i]).length < (initialTexCoordIndex[i] + validVertexCount) ) {
10024 			    throw new ArrayIndexOutOfBoundsException(
10025 								     J3dI18N.getString("GeometryArray113"));
10026 			}
10027 		    }
10028 		    break;
10029 		}
10030 		switch ((vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
10031 		case NF:
10032 		    if (floatRefNormals.length < 3 * (initialNormalIndex + validVertexCount )) {
10033 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
10034 		    }
10035 		    break;
10036 		case N3F:
10037 		    if (v3fRefNormals.length < (initialNormalIndex + validVertexCount) ) {
10038 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
10039 		    }
10040 		}
10041 		switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) {
10042 		case AF:
10043                     for (int i = 0; i < vertexAttrCount; i++) {
10044                         int sz = vertexAttrSizes[i];
10045                         if (floatRefVertexAttrs[i].length <
10046                                 (sz * (initialVertexAttrIndex[i] + validVertexCount)) ) {
10047                             throw new ArrayIndexOutOfBoundsException(
10048                                     J3dI18N.getString("GeometryArray129"));
10049                         }
10050                     }
10051 		    break;
10052 		}
10053 	    }
10054 	}
10055         boolean isLive = source!=null && source.isLive();
10056         if(isLive){
10057             geomLock.getLock();
10058         }
10059 	dirtyFlag |= VERTEX_CHANGED;
10060 	this.validVertexCount = validVertexCount;
10061 
10062 	if(isLive){
10063             geomLock.unLock();
10064 	}
10065 
10066 	if (!inUpdater && isLive) {
10067 	    processCoordsChanged(nullGeo);
10068 	    sendDataChangedMessage(true);
10069 	}
10070     }
10071 
10072 
getValidVertexCount()10073     int getValidVertexCount() {
10074 	return validVertexCount;
10075     }
10076 
10077     //Used for interleaved data (array or nio buffer)
setInitialVertexIndex(int initialVertexIndex)10078     void setInitialVertexIndex(int initialVertexIndex) {
10079 	boolean nullGeo = false;
10080 
10081 	if ((initialVertexIndex + validVertexCount) > vertexCount) {
10082 	    throw new IllegalArgumentException(J3dI18N.getString("GeometryArray100"));
10083 	}
10084 
10085 	if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0 && interleavedFloatBufferImpl != null) {
10086 	    if(interleavedFloatBufferImpl.limit() <  stride * (initialVertexIndex + validVertexCount)) {
10087 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
10088 	    }
10089 	}
10090 	// interleaved data using java array
10091 	else if(interLeavedVertexData != null) {
10092 		if (interLeavedVertexData.length < stride * (initialVertexIndex + validVertexCount)) {
10093 		throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114"));
10094 	    }
10095 	}
10096 	else {
10097 	    nullGeo = (vertexFormat & GeometryArray.INTERLEAVED) != 0; // Only for byRef
10098 	}
10099 	boolean isLive = source!=null && source.isLive();
10100 	if(isLive){
10101             geomLock.getLock();
10102         }
10103 	dirtyFlag |= VERTEX_CHANGED;
10104 	this.initialVertexIndex = initialVertexIndex;
10105 	if(isLive) {
10106             geomLock.unLock();
10107 	}
10108 	if (!inUpdater && isLive) {
10109 	    processCoordsChanged(nullGeo);
10110 	    sendDataChangedMessage(true);
10111 	}
10112     }
10113 
getInitialVertexIndex()10114     int getInitialVertexIndex() {
10115 	return initialVertexIndex;
10116     }
10117 
setInitialCoordIndex(int initialCoordIndex)10118     void setInitialCoordIndex(int initialCoordIndex) {
10119 	if ((initialCoordIndex + validVertexCount) > vertexCount) {
10120 	    throw new IllegalArgumentException(J3dI18N.getString("GeometryArray104"));
10121 	}
10122 	// use NIO buffer
10123 	if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0){
10124 	    switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10125 	    case PF:
10126 		if(floatBufferRefCoords.limit() < (initialCoordIndex+validVertexCount) ) {
10127 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
10128 		}
10129 		break;
10130 	    case PD:
10131 		if(doubleBufferRefCoords.limit() < (initialCoordIndex+validVertexCount) ) {
10132 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
10133 		}
10134 		break;
10135 	    }
10136 	} else {
10137 	    switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10138 	    case PF:
10139 		if (floatRefCoords.length < 3 * (initialCoordIndex+validVertexCount)) {
10140 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
10141 		}
10142 		break;
10143 	    case PD:
10144 		if (doubleRefCoords.length < 3 * (initialCoordIndex+validVertexCount)) {
10145 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
10146 		}
10147 		break;
10148 	    case P3F:
10149 		if (p3fRefCoords.length < (initialCoordIndex+validVertexCount) ) {
10150 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
10151 		}
10152 		break;
10153 	    case P3D:
10154 		if (p3dRefCoords.length <  (initialCoordIndex+validVertexCount) ) {
10155 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray99"));
10156 		}
10157 		break;
10158 	    }
10159 	}
10160 	boolean isLive = source!=null && source.isLive();
10161 	if(isLive){
10162             geomLock.getLock();
10163 	}
10164 	dirtyFlag |= COORDINATE_CHANGED;
10165 	this.initialCoordIndex = initialCoordIndex;
10166 	dirtyFlag |= COORDINATE_CHANGED;
10167 	if(isLive) {
10168             geomLock.unLock();
10169 	}
10170 	// Send a message, since bounds changed
10171 	if (!inUpdater && isLive) {
10172 	    processCoordsChanged((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
10173 	    sendDataChangedMessage(true);
10174 	}
10175     }
10176 
getInitialCoordIndex()10177     int getInitialCoordIndex() {
10178 	return initialCoordIndex;
10179     }
10180 
setInitialColorIndex(int initialColorIndex)10181     void setInitialColorIndex(int initialColorIndex) {
10182 	if ((initialColorIndex + validVertexCount) > vertexCount) {
10183 	    throw new IllegalArgumentException(J3dI18N.getString("GeometryArray101"));
10184 	}
10185 	// NIO BUFFER CASE
10186 	if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0){
10187 	    switch ((vertexType & COLOR_DEFINED)) {
10188 	    case CF:
10189 		if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10190 		    if (floatBufferRefColors.limit() < 3 * (initialColorIndex+validVertexCount)) {
10191 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10192 		    }
10193 		}
10194 		else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10195 		    if (floatBufferRefColors.limit() < 4 * (initialColorIndex+validVertexCount)) {
10196 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10197 		    }
10198 		}
10199 		break;
10200 
10201 	    case CUB:
10202 		if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10203 		    if (byteBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
10204 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10205 		    }
10206 		}
10207 		else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10208 		    if (byteBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount) ) {
10209 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10210 		    }
10211 		}
10212 		break;
10213 	    }
10214 	}
10215 	// Java ARRAY CASE
10216 	else {
10217 	    switch ((vertexType & COLOR_DEFINED)) {
10218 	    case CF:
10219 		if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10220 		    if (floatRefColors.length < 3 * (initialColorIndex+validVertexCount)) {
10221 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10222 		    }
10223 		}
10224 		else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10225 		    if (floatRefColors.length < 4 * (initialColorIndex+ validVertexCount) ) {
10226 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10227 		    }
10228 		}
10229 		break;
10230 	    case CUB:
10231 		if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10232 		    if (byteRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10233 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10234 		    }
10235 		}
10236 		else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10237 		    if (byteRefColors.length < 4 * (initialColorIndex + validVertexCount) ) {
10238 			throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10239 		    }
10240 		}
10241 		break;
10242 	    case C3F:
10243 		if (c3fRefColors.length < (initialColorIndex + validVertexCount) ) {
10244 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10245 		}
10246 		break;
10247 	    case C4F:
10248 		if (c4fRefColors.length < (initialColorIndex + validVertexCount) ) {
10249 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10250 		}
10251 		break;
10252 	    case C3UB:
10253 		if (c3bRefColors.length < (initialColorIndex + validVertexCount)) {
10254 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10255 		}
10256 		break;
10257 	    case C4UB:
10258 		if (c4bRefColors.length < (initialColorIndex + validVertexCount) ) {
10259 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray112"));
10260 		}
10261 		break;
10262 	    }
10263 	}
10264 	boolean isLive = source!=null && source.isLive();
10265 	if(isLive){
10266             geomLock.getLock();
10267 	}
10268 	dirtyFlag |= COLOR_CHANGED;
10269 	colorChanged = 0xffff;
10270 	this.initialColorIndex = initialColorIndex;
10271 	if(isLive) {
10272             geomLock.unLock();
10273 	}
10274 	// There is no need to send message for by reference, since we
10275 	// use VA
10276 
10277     }
10278 
getInitialColorIndex()10279     int getInitialColorIndex() {
10280 	return initialColorIndex;
10281     }
10282 
setInitialNormalIndex(int initialNormalIndex)10283     void setInitialNormalIndex(int initialNormalIndex) {
10284 	if ((initialNormalIndex + validVertexCount) > vertexCount) {
10285 	    throw new IllegalArgumentException(J3dI18N.getString("GeometryArray102"));
10286 	}
10287 	if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0){
10288 	    if((vertexType & NORMAL_DEFINED) == NF){
10289 		if (floatBufferRefNormals.limit() < 3 * (initialNormalIndex + validVertexCount )) {
10290 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
10291 		}
10292 	    }
10293 	} else {
10294 	    switch((vertexType & NORMAL_DEFINED)){
10295 	    case NF:
10296 		if (floatRefNormals.length < 3 * (initialNormalIndex + validVertexCount )) {
10297 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
10298 		}
10299 		break;
10300 	    case N3F:
10301 		if (v3fRefNormals.length < (initialNormalIndex + validVertexCount) ) {
10302 		    throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111"));
10303 		}
10304 	    }
10305 	}
10306 	boolean isLive = source!=null && source.isLive();
10307 	if(isLive){
10308             geomLock.getLock();
10309 	}
10310 	dirtyFlag |= NORMAL_CHANGED;
10311 	this.initialNormalIndex = initialNormalIndex;
10312 	if(isLive) {
10313             geomLock.unLock();
10314 	}
10315 	// There is no need to send message for by reference, since we
10316 	// use VA
10317     }
10318 
getInitialNormalIndex()10319     int getInitialNormalIndex() {
10320 	return initialNormalIndex;
10321     }
10322 
10323     /**
10324      * Sets the initial vertex attribute index for the specified
10325      * vertex attribute number for this GeometryArray object.
10326      */
setInitialVertexAttrIndex(int vertexAttrNum, int initialVertexAttrIndex)10327     void setInitialVertexAttrIndex(int vertexAttrNum,
10328             int initialVertexAttrIndex) {
10329 
10330         if ((initialVertexAttrIndex + validVertexCount) > vertexCount) {
10331             throw new IllegalArgumentException(J3dI18N.getString("GeometryArray130"));
10332         }
10333 
10334         int sz = vertexAttrSizes[vertexAttrNum];
10335         int minLength = sz * (initialVertexAttrIndex + validVertexCount);
10336         if ((vertexType & VATTR_DEFINED) == AF) {
10337             if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10338                 if (floatBufferRefVertexAttrs[vertexAttrNum].limit() < minLength) {
10339                     throw new ArrayIndexOutOfBoundsException(
10340                             J3dI18N.getString("GeometryArray129"));
10341                 }
10342             } else {
10343                 if (floatRefVertexAttrs[vertexAttrNum].length < minLength ) {
10344                     throw new ArrayIndexOutOfBoundsException(
10345                             J3dI18N.getString("GeometryArray129"));
10346                 }
10347             }
10348         }
10349         boolean isLive = source!=null && source.isLive();
10350     	if(isLive){
10351             geomLock.getLock();
10352     	}
10353         dirtyFlag |= VATTR_CHANGED;
10354         this.initialVertexAttrIndex[vertexAttrNum] = initialVertexAttrIndex;
10355         if(isLive) {
10356             geomLock.unLock();
10357     	}
10358         // There is no need to send message for by reference, since we
10359         // use VA
10360     }
10361 
10362 
10363     /**
10364      * Gets the initial vertex attribute index for the specified
10365      * vertex attribute number for this GeometryArray object.
10366      */
getInitialVertexAttrIndex(int vertexAttrNum)10367     int getInitialVertexAttrIndex(int vertexAttrNum) {
10368         return initialVertexAttrIndex[vertexAttrNum];
10369     }
10370 
setInitialTexCoordIndex(int texCoordSet, int initialTexCoordIndex)10371     void setInitialTexCoordIndex(int texCoordSet, int initialTexCoordIndex) {
10372 	if ((initialTexCoordIndex + validVertexCount) > vertexCount) {
10373 	    throw new IllegalArgumentException(J3dI18N.getString("GeometryArray103"));
10374 	}
10375 
10376 	if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0){
10377 	    if((vertexType & TEXCOORD_DEFINED) == TF) {
10378 		FloatBufferWrapper texBuffer = (FloatBufferWrapper)(((J3DBuffer) refTexCoordsBuffer[texCoordSet]).getBufferImpl());
10379 		if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
10380 		    if (texBuffer.limit() < 2 * (initialTexCoordIndex+ validVertexCount) ) {
10381 			throw new ArrayIndexOutOfBoundsException(
10382 								 J3dI18N.getString("GeometryArray113"));
10383 		    }
10384 		} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10385 		    if (texBuffer.limit() < 3 * (initialTexCoordIndex + validVertexCount) ) {
10386 			throw new ArrayIndexOutOfBoundsException(
10387 								 J3dI18N.getString("GeometryArray113"));
10388 		    }
10389 		} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10390 		    if (texBuffer.limit() < 4 * (initialTexCoordIndex + validVertexCount)) {
10391 			throw new ArrayIndexOutOfBoundsException(
10392 								 J3dI18N.getString("GeometryArray113"));
10393 		    }
10394 		}
10395 	    }
10396 	} else {
10397 	    switch ((vertexType & TEXCOORD_DEFINED)) {
10398 	    case TF:
10399 		if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
10400 		    if (((float[])refTexCoords[texCoordSet]).length < 2 * (initialTexCoordIndex+ validVertexCount) ) {
10401 			throw new ArrayIndexOutOfBoundsException(
10402 								 J3dI18N.getString("GeometryArray113"));
10403 		    }
10404 		} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10405 		    if (((float[])refTexCoords[texCoordSet]).length < 3 * (initialTexCoordIndex + validVertexCount) ) {
10406 			throw new ArrayIndexOutOfBoundsException(
10407 								 J3dI18N.getString("GeometryArray113"));
10408 		    }
10409 		} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10410 		    if (((float[])refTexCoords[texCoordSet]).length < 4 * (initialTexCoordIndex + validVertexCount)) {
10411 			throw new ArrayIndexOutOfBoundsException(
10412 								 J3dI18N.getString("GeometryArray113"));
10413 		    }
10414 		}
10415 		break;
10416 	    case T2F:
10417 		if (((TexCoord2f[])refTexCoords[texCoordSet]).length < (initialTexCoordIndex+ validVertexCount) ) {
10418 		    throw new ArrayIndexOutOfBoundsException(
10419 							     J3dI18N.getString("GeometryArray113"));
10420 		}
10421 		break;
10422 	    case T3F:
10423 		if (((TexCoord3f[])refTexCoords[texCoordSet]).length < (initialTexCoordIndex+ validVertexCount) ) {
10424 		    throw new ArrayIndexOutOfBoundsException(
10425 							     J3dI18N.getString("GeometryArray113"));
10426 		}
10427 		break;
10428 	    }
10429 	}
10430 	boolean isLive = source!=null && source.isLive();
10431 	if(isLive){
10432             geomLock.getLock();
10433 	}
10434 	dirtyFlag |= TEXTURE_CHANGED;
10435 	this.initialTexCoordIndex[texCoordSet] = initialTexCoordIndex;
10436 	if(isLive) {
10437             geomLock.unLock();
10438 	}
10439 	// There is no need to send message for by reference, since we
10440 	// use VA
10441     }
10442 
getInitialTexCoordIndex(int texCoordSet)10443     int getInitialTexCoordIndex(int texCoordSet) {
10444 	return initialTexCoordIndex[texCoordSet];
10445     }
10446 
10447 
getTexCoordSetCount()10448     int getTexCoordSetCount() {
10449 	return this.texCoordSetCount;
10450     }
10451 
getTexCoordSetMapLength()10452     int getTexCoordSetMapLength() {
10453 	if (this.texCoordSetMap != null)
10454 	    return this.texCoordSetMap.length;
10455 	else
10456 	    return 0;
10457     }
10458 
getTexCoordSetMap(int [] texCoordSetMap)10459     void getTexCoordSetMap(int [] texCoordSetMap) {
10460 
10461 	if (this.texCoordSetMap!=null) {
10462 	    for (int i = 0; i < this.texCoordSetMap.length; i++) {
10463 	         texCoordSetMap[i] = this.texCoordSetMap[i];
10464 	    }
10465 	}
10466     }
10467 
freeDlistId()10468     void freeDlistId() {
10469 	if (dlistId != -1) {
10470 	    VirtualUniverse.mc.freeDisplayListId(dlistObj);
10471 	    dlistId = -1;
10472 	}
10473     }
10474 
assignDlistId()10475     void assignDlistId() {
10476 	if (dlistId == -1) {
10477 	    dlistObj = VirtualUniverse.mc.getDisplayListId();
10478 	    dlistId = dlistObj.intValue();
10479 	}
10480     }
10481 
10482     // Add the specified render atom as a user of this geometry array
10483     // (for the specified render bin)
addDlistUser(RenderBin renderBin, RenderAtomListInfo ra)10484     void addDlistUser(RenderBin renderBin, RenderAtomListInfo ra) {
10485 	if (dlistUsers == null) {
10486 	    dlistUsers = new HashMap(2, 1.0f);
10487 	}
10488 
10489 	Set raSet = (Set)dlistUsers.get(renderBin);
10490 	if (raSet == null) {
10491 	    raSet = new HashSet();
10492 	    dlistUsers.put(renderBin, raSet);
10493 	}
10494 	raSet.add(ra);
10495     }
10496 
10497     // Remove the specified render atom from the set of users of this
10498     // geometry array (for the specified render bin)
removeDlistUser(RenderBin renderBin, RenderAtomListInfo ra)10499     void removeDlistUser(RenderBin renderBin, RenderAtomListInfo ra) {
10500 	if (dlistUsers == null) {
10501 	    // Nothing to do
10502 	    return;
10503 	}
10504 
10505 	Set raSet = (Set)dlistUsers.get(renderBin);
10506 	if (raSet == null) {
10507 	    // Nothing to do
10508 	    return;
10509 	}
10510 	raSet.remove(ra);
10511     }
10512 
10513     // Returns true if the set of render atoms using this geometry
10514     // array in the specified render bin is empty.
isDlistUserSetEmpty(RenderBin renderBin)10515     boolean isDlistUserSetEmpty(RenderBin renderBin) {
10516 	if (dlistUsers == null) {
10517 	    return true;
10518 	}
10519 
10520 	Set raSet = (Set)dlistUsers.get(renderBin);
10521 	if (raSet == null) {
10522 	    return true;
10523 	}
10524 	return raSet.isEmpty();
10525     }
10526 
10527     // This method is used for debugging only
numDlistUsers(RenderBin renderBin)10528     int numDlistUsers(RenderBin renderBin) {
10529 	if (isDlistUserSetEmpty(renderBin)) {
10530 	    return 0;
10531 	}
10532 	Set raSet = (Set)dlistUsers.get(renderBin);
10533 	return raSet.size();
10534     }
10535 
setDlistTimeStamp(int rdrBit, long timeStamp)10536     void setDlistTimeStamp(int rdrBit, long timeStamp) {
10537 	int index = getIndex(rdrBit);
10538 	if (index >= timeStampPerDlist.length) {
10539 	    long[] newList = new long[index * 2];
10540 	    for (int i = 0; i < timeStampPerDlist.length; i++) {
10541 		 newList[i] = timeStampPerDlist[i];
10542 	    }
10543 	    timeStampPerDlist = newList;
10544 	}
10545 	timeStampPerDlist[index] = timeStamp;
10546     }
10547 
getDlistTimeStamp(int rdrBit)10548     long getDlistTimeStamp(int rdrBit) {
10549 	int index = getIndex(rdrBit);
10550        // If index is greater than what currently exists, increase
10551        // the array and return zero
10552        if (index >= timeStampPerDlist.length) {
10553            setDlistTimeStamp(rdrBit, 0);
10554        }
10555        return timeStampPerDlist[index];
10556     }
10557 
getIndex(int bit)10558     int getIndex(int bit) {
10559 	int num = 0;
10560 
10561 	while (bit > 0) {
10562 	    num++;
10563 	    bit >>= 1;
10564 	}
10565 	return num;
10566     }
10567 
10568 
isWriteStatic()10569     boolean isWriteStatic() {
10570 
10571 	if (source.getCapability(GeometryArray.ALLOW_COORDINATE_WRITE ) ||
10572 	    source.getCapability(GeometryArray.ALLOW_COLOR_WRITE) ||
10573 	    source.getCapability(GeometryArray.ALLOW_NORMAL_WRITE) ||
10574 	    source.getCapability(GeometryArray.ALLOW_TEXCOORD_WRITE) ||
10575             source.getCapability(GeometryArray.ALLOW_VERTEX_ATTR_WRITE) ||
10576 	    source.getCapability(GeometryArray.ALLOW_COUNT_WRITE) ||
10577 	    source.getCapability(GeometryArray.ALLOW_REF_DATA_WRITE))
10578 	    return false;
10579 
10580 	return true;
10581     }
10582 
10583     /**
10584      * The functions below are only used in compile mode
10585      */
setCompiled(ArrayList curList)10586     void setCompiled(ArrayList curList) {
10587 	int i;
10588 	int num = curList.size();
10589 	int offset = 0;
10590 	geoOffset = new int[num];
10591 	compileVcount = new int[num];
10592 	int vcount = 0, vformat = 0;
10593 	vcount = 0;
10594 	isCompiled = true;
10595 
10596 	if (num > 0)
10597 	    source = ((SceneGraphObjectRetained)curList.get(0)).source;
10598 	for (i = 0; i < num; i++) {
10599 	    // Build the back mapping
10600 	    GeometryArrayRetained geo = (GeometryArrayRetained)curList.get(i);
10601 	    ((GeometryArray)geo.source).retained = this;
10602 	    compileVcount[i] = geo.getValidVertexCount();
10603 	    vcount += geo.getValidVertexCount();
10604 	    geoOffset[i] = offset;
10605 	    offset += geo.stride() * compileVcount[i];
10606 	    vformat = geo.getVertexFormat();
10607 	}
10608 	createGeometryArrayData(vcount, vformat);
10609 
10610 	// Assign the initial and valid fields
10611 	validVertexCount = vcount;
10612 	initialVertexIndex = 0;
10613 
10614 	mergeGeometryArrays(curList);
10615 
10616     }
10617 
10618     /*
10619     // Ununsed
10620     int getVertexCount(int index) {
10621 	return compileVcount[index];
10622     }
10623 
10624 
10625     int getValidVertexCount(int index) {
10626 	return compileVcount[index];
10627     }
10628 
10629 
10630     int getInitialVertexIndex(int index) {
10631 	return 0;
10632     }
10633     */
10634 
mergeGeometryArrays(ArrayList list)10635     void mergeGeometryArrays(ArrayList list) {
10636 	float[] curVertexData;
10637 	int length, srcOffset;
10638 	int curOffset = 0;
10639 	// We only merge if the texCoordSetCount is 1 and there are no
10640         // vertex attrs
10641 	if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
10642 	    texCoordSetCount = 1;
10643 	    texCoordSetMap = new int[1];
10644 	    texCoordSetMap[0] = 1;
10645 	}
10646 	for (int i = 0; i < list.size(); i++) {
10647 	    GeometryArrayRetained geo = (GeometryArrayRetained)list.get(i);
10648 	    // Take into account the validVertexCount and initialVertexIndex
10649 	    curVertexData = geo.vertexData;
10650 	    length = geo.validVertexCount * stride;
10651 	    srcOffset = geo.initialVertexIndex * stride;
10652 	    System.arraycopy(curVertexData, srcOffset, this.vertexData, curOffset,
10653 			     length);
10654 	    curOffset += length;
10655 
10656 	    // assign geoBounds
10657 	    geoBounds.combine(geo.geoBounds);
10658 
10659 	}
10660 	this.centroid.set(geoBounds.getCenter());
10661     }
10662 
isMergeable()10663     boolean isMergeable() {
10664 
10665 	// For now, turn off by ref geometry
10666 	if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0)
10667 	    return false;
10668 
10669 	if (!isStatic())
10670 	    return false;
10671 
10672 	// If there is more than one set of texture coordinate set defined
10673 	// then don't merge geometry (we avoid dealing with texCoordSetMap
10674 	if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0 &&
10675 	    (texCoordSetCount > 1 ||
10676 	     texCoordSetMap != null && texCoordSetMap.length > 1)) {
10677 	    return false;
10678 	}
10679 
10680         // We will avoid merging geometry if there are any vertex attributes.
10681         if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
10682             return false;
10683         }
10684 
10685 	// If intersect is allowed turn off merging
10686 	if (source.getCapability(Geometry.ALLOW_INTERSECT))
10687 	    return false;
10688 
10689 	return true;
10690     }
10691 
compile(CompileState compState)10692     void compile(CompileState compState) {
10693         super.compile(compState);
10694 
10695 	if ((vertexFormat & GeometryArray.NORMALS) != 0) {
10696 	    compState.needNormalsTransform = true;
10697 	}
10698     }
10699 
mergeTransform(TransformGroupRetained xform)10700     void mergeTransform(TransformGroupRetained xform) {
10701 	if (geoBounds != null) {
10702 	    geoBounds.transform(xform.transform);
10703 	}
10704     }
10705 
10706     // This adds a MorphRetained to the list of users of this geometry
addMorphUser(MorphRetained m)10707     void addMorphUser(MorphRetained m) {
10708         int index;
10709         ArrayList morphList;
10710 
10711 	if(morphUniverseList == null) {
10712 	    morphUniverseList = new ArrayList(1);
10713 	    morphUserLists = new ArrayList(1);
10714 	}
10715         synchronized (morphUniverseList) {
10716             if (morphUniverseList.contains(m.universe)) {
10717                 index = morphUniverseList.indexOf(m.universe);
10718                 morphList = (ArrayList)morphUserLists.get(index);
10719                 morphList.add(m);
10720             } else {
10721                 morphUniverseList.add(m.universe);
10722                 morphList = new ArrayList(5);
10723                 morphList.add(m);
10724                 morphUserLists.add(morphList);
10725             }
10726         }
10727     }
10728 
10729     // This adds a MorphRetained to the list of users of this geometry
removeMorphUser(MorphRetained m)10730     void removeMorphUser(MorphRetained m) {
10731         int index;
10732         ArrayList morphList;
10733 
10734 	if(morphUniverseList == null)
10735 	    return;
10736 
10737         synchronized (morphUniverseList) {
10738             index = morphUniverseList.indexOf(m.universe);
10739             morphList = (ArrayList)morphUserLists.get(index);
10740             morphList.remove(morphList.indexOf(m));
10741             if (morphList.size() == 0) {
10742                 morphUserLists.remove(index);
10743                 morphUniverseList.remove(index);
10744             }
10745         }
10746     }
10747     // Initialize mirror object when geometry is first setLived
initMirrorGeometry()10748     void initMirrorGeometry() {
10749 	geomLock.getLock();
10750 	if (this instanceof IndexedGeometryArrayRetained) {
10751 	    if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) {
10752 		mirrorGeometry =
10753 		    ((IndexedGeometryArrayRetained)this).cloneNonIndexedGeometry();
10754 	    }
10755 	    else {
10756 		mirrorGeometry = null;
10757 	    }
10758 	}
10759 	geomLock.unLock();
10760 
10761     }
10762 
10763     // Update Mirror Object in response to change in geometry
updateMirrorGeometry()10764     void updateMirrorGeometry() {
10765 	geomLock.getLock();
10766 	if (this instanceof IndexedGeometryArrayRetained) {
10767 	    if (mirrorGeometry != null) {
10768 		mirrorGeometry =
10769 		    ((IndexedGeometryArrayRetained)this).cloneNonIndexedGeometry();
10770 	    }
10771 	}
10772 	geomLock.unLock();
10773 
10774     }
10775 
10776 
10777     // Used by the picking intersect routines
getVertexData(int i, Point3d pnts)10778     void getVertexData(int i, Point3d pnts) {
10779 	int offset;
10780 	if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
10781 	    offset = stride * i + coordinateOffset;
10782 	    pnts.x = this.vertexData[offset];
10783 	    pnts.y = this.vertexData[offset+1];
10784 	    pnts.z = this.vertexData[offset+2];
10785 	    return;
10786 	}
10787 
10788 	if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0 ) {
10789 	    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
10790 		offset = stride * i + coordinateOffset;
10791 		pnts.x = this.interLeavedVertexData[offset];
10792 		pnts.y = this.interLeavedVertexData[offset+1];
10793 		pnts.z = this.interLeavedVertexData[offset+2];
10794 	    }
10795 	    else {
10796 		switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10797 		case GeometryArrayRetained.PF:
10798 		    offset = i*3;
10799 		    pnts.x = this.floatRefCoords[offset];
10800 		    pnts.y = this.floatRefCoords[offset+1];
10801 		    pnts.z = this.floatRefCoords[offset+2];
10802 		    break;
10803 		case GeometryArrayRetained.PD:
10804 		    offset = i*3;
10805 		    pnts.x = this.doubleRefCoords[offset];
10806 		    pnts.y = this.doubleRefCoords[offset+1];
10807 		    pnts.z = this.doubleRefCoords[offset+2];
10808 		    break;
10809 		case GeometryArrayRetained.P3F:
10810 		    pnts.x = this.p3fRefCoords[i].x;
10811 		    pnts.y = this.p3fRefCoords[i].y;
10812 		    pnts.z = this.p3fRefCoords[i].z;
10813 		    break;
10814 		case GeometryArrayRetained.P3D:
10815 		    pnts.x = this.p3dRefCoords[i].x;
10816 		    pnts.y = this.p3dRefCoords[i].y;
10817 		    pnts.z = this.p3dRefCoords[i].z;
10818 		    break;
10819 		}
10820 	    }
10821 	}// end of non nio buffer
10822 	else { // NIO BUFFER
10823 	    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
10824 		offset = stride * i + coordinateOffset;
10825 		pnts.x = this.interleavedFloatBufferImpl.get(offset);
10826 		pnts.y = this.interleavedFloatBufferImpl.get(offset+1);
10827 		pnts.z = this.interleavedFloatBufferImpl.get(offset+2);
10828 	    }
10829 	    else {
10830 		switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10831 		case GeometryArrayRetained.PF:
10832 		    offset = i*3;
10833 		    pnts.x = this.floatBufferRefCoords.get(offset);
10834 		    pnts.y = this.floatBufferRefCoords.get(offset+1);
10835 		    pnts.z = this.floatBufferRefCoords.get(offset+2);
10836 		    break;
10837 		case GeometryArrayRetained.PD:
10838 		    offset = i*3;
10839 		    pnts.x = this.doubleBufferRefCoords.get(offset);
10840 		    pnts.y = this.doubleBufferRefCoords.get(offset+1);
10841 		    pnts.z = this.doubleBufferRefCoords.get(offset+2);
10842 		    break;
10843 		}
10844 	    }
10845 	} // end of nio buffer
10846     }
10847 
getCrossValue(Point3d p1, Point3d p2, Vector3d value)10848     void getCrossValue(Point3d p1, Point3d p2, Vector3d value) {
10849         value.x += p1.y*p2.z - p1.z*p2.y;
10850 	value.y += p2.x*p1.z - p2.z*p1.x;
10851         value.z += p1.x*p2.y - p1.y*p2.x;
10852     }
10853 
10854 
intersect(Transform3D thisLocalToVworld, Transform3D otherLocalToVworld, GeometryRetained geom)10855     boolean intersect(Transform3D thisLocalToVworld,
10856 		      Transform3D otherLocalToVworld, GeometryRetained  geom) {
10857 
10858 	Transform3D t3d =  new Transform3D();
10859 	boolean isIntersect = false;
10860 
10861 	if (geom instanceof GeometryArrayRetained ) {
10862 	    GeometryArrayRetained geomArray = (GeometryArrayRetained)  geom;
10863 
10864 	    if (geomArray.validVertexCount >= validVertexCount) {
10865 		t3d.invert(otherLocalToVworld);
10866 		t3d.mul(thisLocalToVworld);
10867 		isIntersect = intersect(t3d, geom);
10868 	    } else {
10869 		t3d.invert(thisLocalToVworld);
10870 		t3d.mul(otherLocalToVworld);
10871 		isIntersect = geomArray.intersect(t3d, this);
10872 	    }
10873 	} else {
10874 		t3d.invert(thisLocalToVworld);
10875 		t3d.mul(otherLocalToVworld);
10876 		isIntersect = geom.intersect(t3d, this);
10877 	}
10878 	return isIntersect;
10879     }
10880 
getNumCoordCount()10881     int getNumCoordCount() {
10882 	int count = 0;
10883 	if ((vertexFormat & GeometryArray.COORDINATES) != 0){
10884 	    if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0){
10885 		count = vertexCount;
10886 		return count;
10887 	    }
10888 
10889 	    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
10890 		if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
10891 		    switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10892 		    case PF:
10893 			count =  floatRefCoords.length/3;
10894 			break;
10895 		    case PD:
10896 			count = doubleRefCoords.length/3;
10897 			break;
10898 		    case P3F:
10899 			count = p3fRefCoords.length;
10900 			break;
10901 		    case P3D:
10902 			count = p3dRefCoords.length;
10903 			break;
10904 		    }
10905 		}
10906 		else {
10907 		    count = interLeavedVertexData.length/stride;
10908 		}
10909 	    }
10910 	    else { // nio buffer
10911 		if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
10912 		    switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10913 		    case PF:
10914 			count =  floatBufferRefCoords.limit()/3; // XXXX: limit or capacity?
10915 			break;
10916 		    case PD:
10917 			count = doubleBufferRefCoords.limit()/3;
10918 			break;
10919 		    }
10920 		}
10921 		else {
10922 		    count = interleavedFloatBufferImpl.limit()/stride;
10923 		}
10924 	    }
10925 	}
10926 	return count;
10927     }
10928 
getNumColorCount()10929     int getNumColorCount() {
10930 	int count = 0;
10931 	if ((vertexFormat & GeometryArray.COLOR) != 0){
10932 	    if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0){
10933 		count = vertexCount;
10934 		return count;
10935 	    }
10936 	    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
10937 		if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
10938 		    switch ((vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
10939 		    case CF:
10940 			if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10941 			    count =  floatRefColors.length/3;
10942 			}
10943 			else if ((vertexFormat & GeometryArray.COLOR_4)== GeometryArray.COLOR_4){
10944 			    count =  floatRefColors.length/4;
10945 			}
10946 			break;
10947 		    case CUB:
10948 			if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10949 			    count =  byteRefColors.length/3;
10950 			}
10951 			else if ((vertexFormat & GeometryArray.COLOR_4)== GeometryArray.COLOR_4){
10952 			    count =  byteRefColors.length/4;
10953 			}
10954 			break;
10955 		    case C3F:
10956 			count = c3fRefColors.length;
10957 			break;
10958 		    case C4F:
10959 			count = c4fRefColors.length;
10960 			break;
10961 		    case C3UB:
10962 			count = c3bRefColors.length;
10963 			break;
10964 		    case C4UB:
10965 			count = c4bRefColors.length;
10966 			break;
10967 		    }
10968 		}
10969 		else {
10970 		    count = interLeavedVertexData.length/stride;
10971 		}
10972 	    } // end of non nio buffer
10973 	    else {
10974 		if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
10975 		    switch ((vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
10976 		    case CF:
10977 			if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10978 			    count =  floatBufferRefColors.limit()/3;
10979 			}
10980 			else if ((vertexFormat & GeometryArray.COLOR_4)== GeometryArray.COLOR_4){
10981 			    count =  floatBufferRefColors.limit()/4;
10982 			}
10983 			break;
10984 		    case CUB:
10985 			if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10986 			    count =  byteBufferRefColors.limit()/3;
10987 			}
10988 			else if ((vertexFormat & GeometryArray.COLOR_4)== GeometryArray.COLOR_4){
10989 			    count =  byteBufferRefColors.limit()/4;
10990 			}
10991 			break;
10992 		    }
10993 		}
10994 		else {
10995 		    count = interleavedFloatBufferImpl.limit()/stride;
10996 		}
10997 	    } // end of nio buffer
10998 	}
10999 	return count;
11000     }
11001 
getNumNormalCount()11002     int getNumNormalCount() {
11003 	int count = 0;
11004 	if ((vertexFormat & GeometryArray.NORMALS) != 0){
11005 	    if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0){
11006 		count = vertexCount;
11007 		return count;
11008 	    }
11009 
11010 	    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11011 		if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
11012 		    switch ((vertexType & NORMAL_DEFINED)) {
11013 		    case NF:
11014 			count =  floatRefNormals.length/3;
11015 			break;
11016 		    case N3F:
11017 			count = v3fRefNormals.length;
11018 			break;
11019 		    }
11020 		}
11021 		else {
11022 		    count = interLeavedVertexData.length/stride;
11023 		}
11024 	    } // end of non nio buffer
11025 	    else {
11026 		if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
11027 		    if ((vertexType & NORMAL_DEFINED) == NF ) {
11028 			count =  floatBufferRefNormals.limit()/3;
11029 		    }
11030 		}
11031 		else {
11032 		    count = interleavedFloatBufferImpl.limit()/stride;
11033 		}
11034 	    }
11035 	}
11036 	return count;
11037     }
11038 
getNumTexCoordCount(int i)11039     int getNumTexCoordCount(int i) {
11040 	int count = 0;
11041 	if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0){
11042 	    if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0){
11043 		count = vertexCount;
11044 		return count;
11045 	    }
11046 
11047 	    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11048 		if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
11049 		    switch ((vertexType & TEXCOORD_DEFINED)) {
11050 		    case TF:
11051 			if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
11052 			    count = ((float[])refTexCoords[i]).length/2;
11053 			} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
11054 			    count = ((float[])refTexCoords[i]).length/3;
11055 			} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
11056 			    count = ((float[])refTexCoords[i]).length/4;
11057 			}
11058 
11059 			break;
11060 		    case T2F:
11061 			count = ((TexCoord2f[])refTexCoords[i]).length;
11062 			break;
11063 		    case T3F:
11064 			count = ((TexCoord3f[])refTexCoords[i]).length;
11065 		    }
11066 		}
11067 		else {
11068 		    count = interLeavedVertexData.length/stride;
11069 		}
11070 	    }
11071 	    else { // nio buffer
11072 		if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){
11073 		    if ((vertexType & TEXCOORD_DEFINED) == TF) {
11074 			FloatBufferWrapper texBuffer = (FloatBufferWrapper)(((J3DBuffer) refTexCoordsBuffer[i]).getBufferImpl());
11075 			if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
11076 			    count = texBuffer.limit()/2;
11077 			} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
11078 			    count = texBuffer.limit()/3;
11079 			} else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
11080 			    count = texBuffer.limit()/4;
11081 			}
11082 		    }
11083 		}
11084 		else {
11085 		    count = interleavedFloatBufferImpl.limit()/stride;
11086 		}
11087 	    }
11088 	}
11089 	return count;
11090     }
11091 
11092     // NOTE: we don't need a getNumVertexAttrCount method, since getNum*Count
11093     // is only called by Morph, which doesn't support vertex attrs
11094 
11095 
11096     // Found the min distance from center to the point/line/tri/quad
11097     // form by dist[]
computeMinDistance(Point3d coordinates[], Point3d center, Vector3d normal, double dist[], Point3d iPnt)11098     void computeMinDistance(Point3d coordinates[], Point3d center,
11099 			    Vector3d normal,
11100 			    double dist[], Point3d iPnt) {
11101 	double x, y, z;
11102 	int i, j;
11103 
11104 	if (coordinates.length == 1) {
11105 	    // a point
11106 	    iPnt.x = coordinates[0].x;
11107 	    iPnt.y = coordinates[0].y;
11108 	    iPnt.z = coordinates[0].z;
11109 	    x = iPnt.x - center.x;
11110 	    y = iPnt.y - center.y;
11111 	    z = iPnt.z - center.z;
11112 	    dist[0] = Math.sqrt(x*x + y*y + z*z);
11113 	    return;
11114 	}
11115 
11116 
11117 	if (coordinates.length == 2) {
11118 	    // a line
11119 	    dist[0] = Math.sqrt(Distance.pointToSegment(center,
11120 							coordinates[0],
11121 							coordinates[1],
11122 							iPnt, null));
11123 	    return;
11124 	}
11125 
11126 	double normalLen = 0;
11127 
11128 	if (normal == null) {
11129 	    Vector3d vec0 = new Vector3d();
11130 	    Vector3d vec1 = new Vector3d();
11131 	    normal = new Vector3d();
11132 	    // compute plane normal for coordinates.
11133 	    for (i=0; i<coordinates.length-1;) {
11134 		vec0.x = coordinates[i+1].x - coordinates[i].x;
11135 		vec0.y = coordinates[i+1].y - coordinates[i].y;
11136 		vec0.z = coordinates[i+1].z - coordinates[i++].z;
11137 		if(vec0.length() > 0.0)
11138 		    break;
11139 	    }
11140 
11141 	    for (j=i; j<coordinates.length-1; j++) {
11142 		vec1.x = coordinates[j+1].x - coordinates[j].x;
11143 		vec1.y = coordinates[j+1].y - coordinates[j].y;
11144 		vec1.z = coordinates[j+1].z - coordinates[j].z;
11145 		if(vec1.length() > 0.0)
11146 		    break;
11147 	    }
11148 
11149 	    if (j == (coordinates.length-1)) {
11150 		// Degenerate polygon, check with edge only
11151 		normal = null;
11152 	    } else {
11153 		normal.cross(vec0,vec1);
11154 	    }
11155 	}
11156 
11157 	if (normal != null) {
11158 	    normalLen = normal.length();
11159 	    if ( normalLen == 0.0) {
11160 		// Degenerate polygon, check with edge only
11161 		normal = null;
11162 	    }
11163 	}
11164 
11165 
11166 	if (coordinates.length == 3) {
11167 	    // a triangle
11168 	    if (normal != null) {
11169 		double d = -(normal.x*coordinates[0].x +
11170 			     normal.y*coordinates[0].y +
11171 			     normal.z*coordinates[0].z);
11172 		dist[0] = (normal.x*center.x + normal.y*center.y +
11173 			   normal.z*center.z +
11174 			   d)/normalLen;
11175 		iPnt.x = center.x - dist[0]*normal.x/normalLen;
11176 		iPnt.y = center.y - dist[0]*normal.y/normalLen;
11177 		iPnt.z = center.z - dist[0]*normal.z/normalLen;
11178 
11179 		 if (pointInTri(iPnt, coordinates[0], coordinates[1],
11180 				coordinates[2], normal)) {
11181 		     return;
11182 		 }
11183 	    }
11184 
11185 	    // checking point to line distance
11186 	    double minDist;
11187 	    Point3d minPnt = new Point3d();
11188 
11189 	    dist[0] = Distance.pointToSegment(center, coordinates[0],
11190 					      coordinates[1], iPnt, null);
11191 	    minDist = Distance.pointToSegment(center, coordinates[1],
11192 					      coordinates[2], minPnt, null);
11193 	    if (minDist < dist[0]) {
11194 		dist[0] = minDist;
11195 		iPnt.x = minPnt.x;
11196 		iPnt.y = minPnt.y;
11197 		iPnt.z = minPnt.z;
11198 	    }
11199 	    minDist = Distance.pointToSegment(center, coordinates[2],
11200 					      coordinates[0], minPnt, null);
11201 	    if (minDist < dist[0]) {
11202 		dist[0] = minDist;
11203 		iPnt.x = minPnt.x;
11204 		iPnt.y = minPnt.y;
11205 		iPnt.z = minPnt.z;
11206 	    }
11207 	    dist[0] = Math.sqrt(dist[0]);
11208 	    return;
11209 	}
11210 
11211 	// a quad
11212 	if (normal != null) {
11213 	    double d = -(normal.x*coordinates[0].x +
11214 			 normal.y*coordinates[0].y +
11215 			 normal.z*coordinates[0].z);
11216 	    dist[0] = (normal.x*center.x + normal.y*center.y +
11217 		       normal.z*center.z +
11218 		       d)/normalLen;
11219 	    iPnt.x = center.x - dist[0]*normal.x/normalLen;
11220 	    iPnt.y = center.y - dist[0]*normal.y/normalLen;
11221 	    iPnt.z = center.z - dist[0]*normal.z/normalLen;
11222 
11223 	    if (pointInTri(iPnt, coordinates[0], coordinates[1],
11224 			   coordinates[2], normal) ||
11225 		pointInTri(iPnt, coordinates[1], coordinates[2],
11226 			   coordinates[3], normal)) {
11227 		return;
11228 	    }
11229 	}
11230 
11231 	// checking point to line distance
11232 	double minDist;
11233 	Point3d minPnt = new Point3d();
11234 
11235 	dist[0] = Distance.pointToSegment(center, coordinates[0],
11236 					  coordinates[1], iPnt, null);
11237 	minDist = Distance.pointToSegment(center, coordinates[1],
11238 					  coordinates[2], minPnt, null);
11239 	if (minDist < dist[0]) {
11240 	    dist[0] = minDist;
11241 	    iPnt.x = minPnt.x;
11242 	    iPnt.y = minPnt.y;
11243 	    iPnt.z = minPnt.z;
11244 	}
11245 	minDist = Distance.pointToSegment(center, coordinates[2],
11246 					  coordinates[3], minPnt, null);
11247 	if (minDist < dist[0]) {
11248 	    dist[0] = minDist;
11249 	    iPnt.x = minPnt.x;
11250 	    iPnt.y = minPnt.y;
11251 	    iPnt.z = minPnt.z;
11252 	}
11253 
11254 	minDist = Distance.pointToSegment(center, coordinates[3],
11255 					  coordinates[0], minPnt, null);
11256 	if (minDist < dist[0]) {
11257 	    dist[0] = minDist;
11258 	    iPnt.x = minPnt.x;
11259 	    iPnt.y = minPnt.y;
11260 	    iPnt.z = minPnt.z;
11261 	}
11262 
11263 	dist[0] = Math.sqrt(dist[0]);
11264     }
11265 
handleFrequencyChange(int bit)11266     void handleFrequencyChange(int bit) {
11267 	int mask = 0;
11268 	if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11269 	    if ((bit == GeometryArray.ALLOW_COORDINATE_WRITE) ||
11270 		(((vertexFormat & GeometryArray.COLOR) != 0) &&
11271 		 bit == GeometryArray.ALLOW_COLOR_WRITE)||
11272 		(((vertexFormat & GeometryArray.NORMALS) != 0) &&
11273 		 bit == GeometryArray.ALLOW_NORMAL_WRITE) ||
11274 		(((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) &&
11275 		 bit == GeometryArray.ALLOW_TEXCOORD_WRITE) ||
11276 		(((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) &&
11277 		 bit == GeometryArray.ALLOW_VERTEX_ATTR_WRITE) ||
11278 		(bit == GeometryArray.ALLOW_COUNT_WRITE)) {
11279 		mask = 1;
11280 	    }
11281 	}
11282 	else {
11283 	    if (bit == GeometryArray.ALLOW_REF_DATA_WRITE)
11284 		mask = 1;
11285 	}
11286 	if (mask != 0) {
11287 	    setFrequencyChangeMask(bit, mask);
11288 	}
11289     }
11290 
getTexCoordType()11291     int getTexCoordType() {
11292         return texCoordType;
11293     }
11294 
getVertexAttrType()11295     int getVertexAttrType() {
11296         return vertexAttrType;
11297     }
11298 
11299 }
11300