001: /*
002: * $RCSfile: IndexedFaceSet.java,v $
003: *
004: * @(#)IndexedFaceSet.java 1.66 99/03/05 17:13:57
005: *
006: * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
007: *
008: * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
009: * modify and redistribute this software in source and binary code form,
010: * provided that i) this copyright notice and license appear on all copies of
011: * the software; and ii) Licensee does not utilize the software in a manner
012: * which is disparaging to Sun.
013: *
014: * This software is provided "AS IS," without a warranty of any kind. ALL
015: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
016: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
017: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
018: * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
019: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
020: * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
021: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
022: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
023: * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
024: * POSSIBILITY OF SUCH DAMAGES.
025: *
026: * This software is not designed or intended for use in on-line control of
027: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
028: * the design, construction, operation or maintenance of any nuclear
029: * facility. Licensee represents and warrants that it will not use or
030: * redistribute the Software for such purposes.
031: *
032: * $Revision: 1.4 $
033: * $Date: 2006/04/05 09:55:09 $
034: * $State: Exp $
035: */
036: /*
037: * @Author: Rick Goldberg
038: * @Author: Doug Gehringer
039: */
040: package org.jdesktop.j3d.loaders.vrml97.impl;
041:
042: import com.sun.j3d.utils.geometry.*;
043: import java.util.*;
044: import javax.media.j3d.BoundingBox;
045: import javax.media.j3d.GeometryArray;
046: import javax.media.j3d.IndexedGeometryArray;
047: import javax.media.j3d.Shape3D;
048: import javax.vecmath.*;
049:
050: /** Description of the Class */
051: public class IndexedFaceSet extends Geometry implements Reusable,
052: Ownable {
053:
054: GeometryArray impl;
055:
056: // eventIn
057: MFInt32 colorIndex;
058: MFInt32 coordIndex;
059: MFInt32 normalIndex;
060: MFInt32 texCoordIndex;
061:
062: SFNode color;
063: SFNode coord;
064: SFNode normal;
065: SFNode texCoord;
066:
067: // field
068: SFBool ccw;
069: SFBool colorPerVertex;
070: SFBool convex;
071: SFFloat creaseAngle;
072: SFBool normalPerVertex;
073: SFBool solid;
074:
075: int numTris = 0;
076:
077: int constSize = 0;
078: boolean isConstSize = false;
079: int vertexCount;
080: int vertexFormat;
081: int numFaces;
082: int numIndices;
083: boolean haveNormals = false;
084: boolean haveColors = false;
085: boolean haveTexture = false;
086: int[] facetSizes;
087: int[] implCoordIndex;
088: int[] implNormalIndex;
089: int[] implColorIndex;
090: int[] implTexIndex;
091: float[] indexColorVals;
092: float[] indexTexVals;
093:
094: static String warnId = new String("IndexedFaceSet()");
095:
096: // Reusable buffers, Length is allocated size
097: Point3f[] coordArray = null;
098: int coordArrayLength = 0;
099: Vector3f[] normalArray = null;
100: int normalArrayLength = 0;
101: int[] tempFace;
102: int tempFaceLength = 0;
103:
104: GeometryInfo gi;
105:
106: BoundingBox bounds;
107: boolean allTriangles;
108:
109: // impl types
110: /** Description of the Field */
111: protected final static int GENERAL = 100;
112: /** Description of the Field */
113: protected final static int TRIS = 101;
114: /** Description of the Field */
115: protected final static int QUAD = 102;
116:
117: int implType;
118: javax.media.j3d.IndexedTriangleFanArray implIndexed;
119: javax.media.j3d.TriangleArray implTris;
120: Shape owner;
121:
122: /**
123: *Constructor for the IndexedFaceSet object
124: *
125: *@param loader Description of the Parameter
126: */
127: public IndexedFaceSet(Loader loader) {
128: super (loader);
129: colorIndex = new MFInt32();
130: coordIndex = new MFInt32();
131: normalIndex = new MFInt32();
132: texCoordIndex = new MFInt32();
133:
134: coord = new SFNode(null);
135: normal = new SFNode(null);
136: color = new SFNode(null);
137: texCoord = new SFNode(null);
138:
139: ccw = new SFBool(true);
140: colorPerVertex = new SFBool(true);
141: convex = new SFBool(true);
142: if (loader.autoSmooth) {
143: creaseAngle = new SFFloat(3.14f);
144: } else {
145: creaseAngle = new SFFloat(0.0f);
146: }
147: normalPerVertex = new SFBool(true);
148: solid = new SFBool(true);
149:
150: initFields();
151: }
152:
153: /**
154: *Constructor for the IndexedFaceSet object
155: *
156: *@param loader Description of the Parameter
157: *@param colorIndex Description of the Parameter
158: *@param coordIndex Description of the Parameter
159: *@param normalIndex Description of the Parameter
160: *@param texCoordIndex Description of the Parameter
161: *@param coord Description of the Parameter
162: *@param normal Description of the Parameter
163: *@param color Description of the Parameter
164: *@param texCoord Description of the Parameter
165: *@param ccw Description of the Parameter
166: *@param colorPerVertex Description of the Parameter
167: *@param convex Description of the Parameter
168: *@param creaseAngle Description of the Parameter
169: *@param normalPerVertex Description of the Parameter
170: *@param solid Description of the Parameter
171: */
172: IndexedFaceSet(Loader loader, MFInt32 colorIndex,
173: MFInt32 coordIndex, MFInt32 normalIndex,
174: MFInt32 texCoordIndex, SFNode coord, SFNode normal,
175: SFNode color, SFNode texCoord, SFBool ccw,
176: SFBool colorPerVertex, SFBool convex, SFFloat creaseAngle,
177: SFBool normalPerVertex, SFBool solid) {
178: super (loader);
179: this .colorIndex = colorIndex;
180: this .coordIndex = coordIndex;
181: this .normalIndex = normalIndex;
182: this .texCoordIndex = texCoordIndex;
183: this .coord = coord;
184: this .normal = normal;
185: this .color = color;
186: this .texCoord = texCoord;
187: this .ccw = ccw;
188: this .colorPerVertex = colorPerVertex;
189: this .convex = convex;
190: this .creaseAngle = creaseAngle;
191: this .normalPerVertex = normalPerVertex;
192: this .solid = solid;
193:
194: initFields();
195: }
196:
197: /** Description of the Method */
198: public void reset() {
199: }
200:
201: /*
202: haveNormals = false;
203: haveColors = false;
204: haveTexture = false;
205: colorIndex.reset();
206: coordIndex.reset();
207: normalIndex.reset();
208: texCoordIndex.reset();
209: coord.reset();
210: normal.reset();
211: color.reset();
212: texCoord.reset();
213: ccw.reset();
214: colorPerVertex.reset();
215: convex.reset();
216: creaseAngle.reset();
217: normalPerVertex.reset();
218: solid.reset();
219: numTris = 0;
220: impl = null;
221: implReady = false;
222: }
223: */
224: // counts number of faces and picks impl type
225: /** Description of the Method */
226: private void initSetup() {
227: Coordinate coordNode = (Coordinate) coord.node;
228: int coordValsSize = coordNode.point.size;
229: float[] coordVals = coordNode.point.value;
230: int coordListSize = coordIndex.size;
231: int[] coordList = coordIndex.value;
232: numFaces = 0;
233: numIndices = 0;
234: int curSize = 0;
235:
236: constSize = 0;
237: isConstSize = false;
238:
239: // initialize the bounding box
240: bounds = coordNode.point.getBoundingBox();
241:
242: // some modelers seem to overrun their coords
243: for (int i = 0; i < coordListSize; i++) {
244: if (coordList[i] > coordValsSize - 1) {
245: // index overran actual coords, wrap around
246: coordList[i] %= coordValsSize;
247: }
248: }
249:
250: if (normal.node != null) {
251: Normal normalNode = (Normal) normal.node;
252: float[] norms = normalNode.vector.value;
253:
254: if (normalIndex.size > 0) {
255: for (int i = 0; i < normalIndex.size; i++) {
256: if (normalIndex.value[i] > norms.length - 1) {
257: normalIndex.value[i] %= norms.length;
258: }
259: }
260: }
261: }
262: // TBD same for color and texture
263:
264: // count how many faces and indices
265: boolean lastCoord = false;
266: for (int i = 0; i < coordListSize; i++) {
267: if (coordList[i] == -1) {
268: numTris += curSize - 2;
269: if (numFaces == 0) {
270: isConstSize = true;
271: constSize = curSize;
272: ;
273: } else {
274: if (curSize != constSize) {
275: isConstSize = false;
276: }
277: }
278: numFaces++;
279: curSize = 0;
280: lastCoord = false;
281: } else {
282: numIndices++;
283: curSize++;
284: lastCoord = true;
285: }
286: }
287: if (lastCoord) {
288: // coord list ended with a coord, finish off the last face
289: numTris += curSize - 2;
290: if (numFaces == 0) {
291: isConstSize = true;
292: constSize = curSize;
293: ;
294: } else {
295: if (curSize != constSize) {
296: isConstSize = false;
297: }
298: }
299: numFaces++;
300: }
301: implType = GENERAL;
302: if (isConstSize == true) {
303: if (constSize == 4) {
304: implType = QUAD;
305: if (loader.debug) {
306: System.out.println("Const size IFS with "
307: + numFaces + " quads");
308: }
309: } else if (constSize == 3) {
310: implType = TRIS;
311: if (loader.debug) {
312: System.out.println("Const size IFS with "
313: + numFaces + " tris");
314: }
315: } else {
316: if (loader.debug) {
317: System.out.println("Const size IFS with "
318: + numFaces + " faces of size " + constSize);
319: }
320: }
321: } else {
322: if (loader.debug) {
323: System.out.println("Variable size IFS, numIndicies = "
324: + numIndices);
325: System.out.println("curSize = " + curSize);
326: System.out.println("numFaces = " + numFaces);
327: System.out.println("(Index)coordList.length= "
328: + coordList.length);
329: System.out.println("(Points)coordVals.length= "
330: + coordVals.length);
331: }
332: }
333: }
334:
335: /**
336: * Description of the Method
337: *
338: *@param normalValSize Description of the Parameter
339: *@param normalVals Description of the Parameter
340: */
341: void copyNormals(int normalValSize, float[] normalVals) {
342: int i;
343: int curVal;
344: // initialize the normal Vector3f array
345: int numNormals = normalValSize / 3;
346: if (normalArrayLength < numNormals) {
347: Vector3f[] newNormalArray = new Vector3f[numNormals];
348: if (normalArray != null) {
349: System.arraycopy(normalArray, 0, newNormalArray, 0,
350: normalArrayLength);
351: }
352: for (i = normalArrayLength; i < numNormals; i++) {
353: newNormalArray[i] = new Vector3f();
354: }
355: normalArray = newNormalArray;
356: normalArrayLength = numNormals;
357: }
358: for (i = 0, curVal = 0; i < numNormals; i++) {
359: normalArray[i].x = normalVals[curVal++];
360: normalArray[i].y = normalVals[curVal++];
361: normalArray[i].z = normalVals[curVal++];
362: }
363: }
364:
365: /**
366: * Description of the Method
367: *
368: *@param coordListSize Description of the Parameter
369: *@param coordList Description of the Parameter
370: */
371: private void setupIndexNormals(int coordListSize, int[] coordList) {
372: haveNormals = false;
373:
374: int normalListSize = normalIndex.size;
375: int[] normalList = normalIndex.value;
376:
377: if (normalPerVertex.value == true) {
378: if ((normalList == null) || (normalListSize == 0)) {
379: normalListSize = coordListSize;
380: normalList = coordList;
381: }
382:
383: if (normalList == coordList) {
384: implNormalIndex = implCoordIndex;
385: } else {
386: implNormalIndex = new int[numIndices];
387: if (!normalIndex.fillImplArraysTest(facetSizes,
388: implNormalIndex)) {
389: loader.warning(warnId,
390: "facet sizes on normalIndex "
391: + " don't match coordIndex");
392: }
393: }
394: // the field's normals are the vertex normals
395: Normal normalNode = (Normal) normal.node;
396: if (normalNode != null) {
397: int normalValSize = normalNode.vector.size;
398: float[] normalVals = normalNode.vector.value;
399: if (normalVals == null) {
400: loader
401: .warning(warnId,
402: "normalVals is null, ignoring "
403: + "normals");
404: return;
405: }
406: copyNormals(normalValSize, normalVals);
407:
408: // assume that normVals is correctly sized for the indicies
409: haveNormals = true;
410: } else {// No normals included - must generate them
411: haveNormals = false;
412: }
413: } else {
414: // normal per facet
415: if ((normalListSize > 0) && (normalListSize != numFaces)) {
416: loader.warning(warnId,
417: "normalIndex length != number of faces");
418: }
419:
420: // set up the normal indicies
421: implNormalIndex = new int[numIndices];
422: int curIndex = 0;
423: for (int curFace = 0; curFace < numFaces; curFace++) {
424: for (int j = 0; j < facetSizes[curFace]; j++) {
425: if (curFace < normalListSize) {
426: implNormalIndex[curIndex++] = normalList[curFace];
427: } else {
428: // this is the std defn for normalList == null
429: implNormalIndex[curIndex++] = curFace;
430: }
431: }
432: }
433:
434: // the field's normals are the facet normals
435: Normal normalNode = (Normal) normal.node;
436: if (normalNode != null) {
437: int normalValSize = normalNode.vector.size;
438: float[] normalVals = normalNode.vector.value;
439: if (normalListSize == 0) {
440: //if (normalValSize != (numFaces * 3)) {
441: //loader.warning(warnId, "normals length != (number of " +
442: //" faces * 3)");
443: //return;
444: //}
445: }
446: copyNormals(normalValSize, normalVals);
447: haveNormals = true;
448: }
449: }
450: }
451:
452: /**
453: * Description of the Method
454: *
455: *@param coordListSize Description of the Parameter
456: *@param coordList Description of the Parameter
457: */
458: private void setupIndexTextures(int coordListSize, int[] coordList) {
459:
460: haveTexture = false;
461:
462: int texListSize = texCoordIndex.size;
463: int[] texList = texCoordIndex.value;
464: if ((texList == null) || (texListSize == 0)) {
465: texListSize = coordListSize;
466: texList = coordList;
467: }
468:
469: if (texList == coordList) {
470: implTexIndex = implCoordIndex;
471: } else {
472: implTexIndex = new int[numIndices];
473: if (texCoordIndex.fillImplArraysTest(facetSizes,
474: implTexIndex) == false) {
475: loader.warning(warnId, "texCoordIndex does not match "
476: + "coordIndex");
477: }
478: }
479:
480: // the field's texCoords are the vertex texCoords
481: TextureCoordinate texNode = (TextureCoordinate) texCoord.node;
482: if (texNode != null) {
483: indexTexVals = texNode.point.vals;
484: if (indexTexVals == null) {
485: loader.warning(warnId, "texture value is null");
486: return;
487: }
488: // assume that texVals is correctly sized for the indicies
489: haveTexture = true;
490: }
491: }
492:
493: /**
494: * Description of the Method
495: *
496: *@param coordListSize Description of the Parameter
497: *@param coordList Description of the Parameter
498: */
499: private void setupIndexColors(int coordListSize, int[] coordList) {
500:
501: haveColors = false;
502:
503: int colorListSize = colorIndex.size;
504: int[] colorList = colorIndex.value;
505:
506: if (colorPerVertex.value == true) {
507: if ((colorList == null) || (colorListSize == 0)) {
508: colorListSize = coordListSize;
509: colorList = coordList;
510: }
511:
512: if (colorList == coordList) {
513: implColorIndex = implCoordIndex;
514: } else {
515: implColorIndex = new int[numIndices];
516: if (!colorIndex.fillImplArraysTest(facetSizes,
517: implColorIndex)) {
518: loader.warning(warnId, "colorIndex does not match "
519: + "coordIndex");
520: }
521: }
522: // the field's colors are the vertex colors
523: Color colorNode = (Color) color.node;
524: if (colorNode != null) {
525: indexColorVals = colorNode.color.vals;
526: if (indexColorVals == null) {
527: loader.warning(warnId, "color is null");
528: return;
529: }
530: // assume that normVals is correctly sized for the indicies
531: haveColors = true;
532: }
533: } else {
534: // color per facet
535: if ((colorListSize > 0) && (colorListSize != numFaces)) {
536: loader.warning(warnId, "colorIndex size != num faces");
537: }
538:
539: // set up the color indicies
540: implColorIndex = new int[numIndices];
541: int curIndex = 0;
542: for (int curFace = 0; curFace < numFaces; curFace++) {
543: for (int j = 0; j < facetSizes[curFace]; j++) {
544: if (curFace < colorListSize) {
545: implColorIndex[curIndex++] = colorList[curFace];
546: } else {
547: // this is the std defn for colorList == null
548: implColorIndex[curIndex++] = curFace;
549: }
550: }
551: }
552:
553: // the field's colors are the facet colors
554: Color colorNode = (Color) color.node;
555: if (colorNode != null) {
556: indexColorVals = colorNode.color.vals;
557: if (colorListSize == 0) {
558: // only do test if no color index values
559: if (indexColorVals.length != (numFaces * 3)) {
560: loader.warning(warnId,
561: "color size != (3 * num faces)");
562: return;
563: }
564: }
565: haveColors = true;
566: }
567: }
568: }
569:
570: /** Description of the Method */
571: private void buildIndexLists() {
572: Coordinate coordNode = (Coordinate) coord.node;
573: int coordValSize = coordNode.point.size;
574: float[] coordVals = coordNode.point.value;
575: int coordListSize = coordIndex.size;
576: int[] coordList = coordIndex.value;
577: int i;
578: int curVal;
579:
580: // get the arrays from the fields into the arrays GeomInfo wants
581:
582: // initialize the coord Point3f array
583: int numCoords = coordValSize / 3;
584: if (coordArrayLength < numCoords) {
585: Point3f[] newCoordArray = new Point3f[coordValSize / 3];
586: if (coordArray != null) {
587: System.arraycopy(coordArray, 0, newCoordArray, 0,
588: coordArrayLength);
589: }
590: for (i = coordArrayLength; i < numCoords; i++) {
591: newCoordArray[i] = new Point3f();
592: }
593: coordArray = newCoordArray;
594: coordArrayLength = numCoords;
595: }
596: for (i = 0, curVal = 0; i < numCoords; i++) {
597: coordArray[i].x = coordVals[curVal++];
598: coordArray[i].y = coordVals[curVal++];
599: coordArray[i].z = coordVals[curVal++];
600: }
601:
602: // allocate the arrays
603: // can't resuse these arrays (yet) because .length is used to
604: // determine the number of active elements
605: facetSizes = new int[numFaces];
606: implCoordIndex = new int[numIndices];
607:
608: // fill in the arrays
609: coordIndex.fillImplArrays(facetSizes, implCoordIndex);
610:
611: if (!ccw.getValue()) {
612: //System.out.println("CW winding - reverse facet ordering");
613: int curIndex = 0;
614: for (i = 0; i < numFaces; ++i) {
615: int curFaceSize = facetSizes[i];
616: if (tempFaceLength < curFaceSize) {
617: tempFace = new int[curFaceSize];
618: }
619: tempFaceLength = curFaceSize;
620: int faceBeginIndex = curIndex;
621: for (int j = 0; j < curFaceSize; ++j) {
622: tempFace[j] = implCoordIndex[curIndex];
623: curIndex++;
624: }
625: for (int j = 0; j < curFaceSize; ++j) {
626: implCoordIndex[faceBeginIndex + j] = tempFace[tempFaceLength
627: - j - 1];
628: }
629: }
630: }
631: // try to set up the data we need for normals
632: setupIndexNormals(coordListSize, coordList);
633:
634: // try to set up the data we need for colors
635: setupIndexColors(coordListSize, coordList);
636:
637: // try to set up the data we need for colors
638: setupIndexTextures(coordListSize, coordList);
639: }
640:
641: /** Description of the Method */
642: public void initImpl() {
643: Coordinate coordNode = (Coordinate) coord.node;
644: TextureCoordinate texCoordNode = (TextureCoordinate) texCoord.node;
645: Normal normalNode = (Normal) normal.node;
646: Color colorNode = (Color) color.node;
647: if ((coordNode == null) || (coordIndex.size <= 0)) {
648: if (loader.debug) {
649: System.out.println("IFS coordIndex.size ="
650: + coordIndex.size);
651: }
652: //loader.warning(warnId, "no coordinates");
653: } else {
654: // attach this to the coordinate
655: // should also be done for any of the Normal, TexCoord...
656: if (coordNode != null) {
657: coordNode.owner = this ;
658: }
659: if (normalNode != null) {
660: normalNode.owner = this ;
661: }
662: if (texCoordNode != null) {
663: texCoordNode.owner = this ;
664: }
665: if (colorNode != null) {
666: colorNode.owner = this ;
667: }
668:
669: // use getGeometryArray(), it will use less memory (using indexed
670: // will copy the coordArrays to J3D, which may be a waste if the
671: // coordArray has been reused so that it is larger than it has
672: // to be)
673:
674: // ?? any set method is a copy whether it is indexed or not. -rg
675:
676: try {
677: buildImpl();
678: impl = gi.getGeometryArray();
679: } catch (java.lang.ArrayIndexOutOfBoundsException aioobe) {
680: // some cases fool the gi hashtable?
681: // workaround: do it agian
682: buildImpl();
683: impl = gi.getIndexedGeometryArray();
684: }
685: }
686:
687: loader.cleanUp();
688: implReady = true;
689: }
690:
691: /** Description of the Method */
692: void buildImpl() {
693:
694: gi = null;
695: initSetup();
696: if (implType == TRIS) {
697: gi = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
698: } else if (implType == QUAD) {
699: gi = new GeometryInfo(GeometryInfo.QUAD_ARRAY);
700: } else {
701: // TODO? handle non-convex with POLYGON
702: gi = new GeometryInfo(GeometryInfo.TRIANGLE_FAN_ARRAY);
703: }
704:
705: buildIndexLists();
706:
707: gi.setCoordinates(coordArray);
708: gi.setCoordinateIndices(implCoordIndex);
709: if (implType == GENERAL) {
710: gi.setStripCounts(facetSizes);
711: }
712: if (haveColors) {
713: gi.setColors3(indexColorVals);
714: gi.setColorIndices(implColorIndex);
715: }
716: if (haveTexture) {
717: gi.setTextureCoordinateParams(1, 2);
718: gi.setTextureCoordinates(0, indexTexVals);
719: if (!ccw.getValue()) {
720: int[] implTexIndexCW = new int[implTexIndex.length];
721: for (int i = 0; i < implTexIndex.length; i++) {
722: implTexIndexCW[i] = implTexIndex[implTexIndex.length
723: - (i + 1)];
724: }
725: implTexIndex = implTexIndexCW;
726: }
727: gi.setTextureCoordinateIndices(0, implTexIndex);
728: }
729: if (haveNormals) {
730: gi.setNormals(normalArray);
731: gi.setNormalIndices(implNormalIndex);
732: validateIndexes();
733: } else {
734: // note setting crease angle to max when really it is
735: // 0 is not called for in the spec, but it looks much better.
736: // this should perhaps be a browser settable menu option.
737: float ca = creaseAngle.getValue();
738: if (ca < 0.0f) {
739: ca = 0.0f;
740: }
741: if (ca > (float) Math.PI) {
742: ca -= (float) Math.PI;
743: }
744: validateIndexes();
745: NormalGenerator ng = new NormalGenerator(ca);
746: ng.generateNormals(gi);
747: }
748:
749: ///if (implType != TRIS) { // stripifier doesn't beat TRIS (yet)
750: ///Stripifier st = new Stripifier();
751: ///st.stripify(gi);
752: ///}
753:
754: }
755:
756: void validateIndexes() throws vrml.InvalidVRMLSyntaxException {
757: try {
758: gi.recomputeIndices();
759: } catch (IllegalArgumentException e) {
760: vrml.InvalidVRMLSyntaxException i = new vrml.InvalidVRMLSyntaxException(
761: (defName == null) ? "in IndexedFaceSet" : "in DEF "
762: + defName);
763: i.initCause(e);
764: throw i;
765: } catch (ArrayIndexOutOfBoundsException e) {
766: vrml.InvalidVRMLSyntaxException i = new vrml.InvalidVRMLSyntaxException(
767: (defName == null) ? "in IndexedFaceSet" : "in DEF "
768: + defName);
769: i.initCause(e);
770: throw i;
771: }
772: }
773:
774: /**
775: * Gets the implGeom attribute of the IndexedFaceSet object
776: *
777: *@return The implGeom value
778: */
779: public javax.media.j3d.Geometry getImplGeom() {
780: return (javax.media.j3d.Geometry) impl;
781: }
782:
783: /**
784: * Gets the boundingBox attribute of the IndexedFaceSet object
785: *
786: *@return The boundingBox value
787: */
788: public BoundingBox getBoundingBox() {
789: return bounds;
790: }
791:
792: /**
793: * Description of the Method
794: *
795: *@return Description of the Return Value
796: */
797: public boolean haveTexture() {
798: return haveTexture;
799: }
800:
801: /**
802: * Gets the numTris attribute of the IndexedFaceSet object
803: *
804: *@return The numTris value
805: */
806: public int getNumTris() {
807: if (loader.debug) {
808: System.out.println("IFS num tris: " + numTris);
809: }
810: return numTris;
811: }
812:
813: /**
814: * Description of the Method
815: *
816: *@param eventInName Description of the Parameter
817: *@param time Description of the Parameter
818: */
819: public void notifyMethod(String eventInName, double time) {
820: // when we handle these events we'll have to check the counts against
821: // the impl object. If the impl sizes or format change, then we will
822: // have to make a new impl and update any group objects which have
823: // references to impl.
824: if ((eventInName.equals("coord"))
825: || (eventInName.equals("color"))
826: || (eventInName.equals("normal"))
827: || (eventInName.equals("coordIndex"))
828: || (eventInName.equals("colorIndex"))
829: || (eventInName.equals("normalIndex"))
830: || (eventInName.equals("texCoord"))
831: || (eventInName.equals("texCoordIndex"))) {
832: if (loader.debug) {
833: System.out.println("updating IFS impl from route!");
834: }
835: initImpl();
836: ((Shape3D) (owner.implNode)).setGeometry(impl);
837: } else if ((eventInName.equals("route_coord"))
838: || (eventInName.equals("route_coordIndex"))
839: || (eventInName.equals("route_coord_point"))
840: || (eventInName.equals("route_color"))
841: || (eventInName.equals("route_colorIndex"))
842: || (eventInName.equals("route_normal"))
843: || (eventInName.equals("route_normalIndex"))
844: || (eventInName.equals("route_texCoord"))
845: || (eventInName.equals("route_texCoordIndex"))) {
846: impl.setCapability(GeometryArray.ALLOW_COORDINATE_WRITE);
847: impl.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
848: impl.setCapability(GeometryArray.ALLOW_NORMAL_WRITE);
849: impl.setCapability(GeometryArray.ALLOW_NORMAL_READ);
850: impl.setCapability(GeometryArray.ALLOW_TEXCOORD_WRITE);
851: impl.setCapability(GeometryArray.ALLOW_TEXCOORD_READ);
852: impl.setCapability(GeometryArray.ALLOW_COLOR_WRITE);
853: impl.setCapability(GeometryArray.ALLOW_COLOR_READ);
854:
855: ((Shape3D) (owner.implNode))
856: .setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
857:
858: } else {
859: System.err.println("IndexFaceSet.notifyMethod(): unknown "
860: + "eventInName: " + eventInName);
861: }
862: }
863:
864: /**
865: * Description of the Method
866: *
867: *@return Description of the Return Value
868: */
869: public Object clone() {
870: if (loader.debug) {
871: System.out.println("IFS.clone() called");
872: }
873: Object o = new IndexedFaceSet(loader, (MFInt32) colorIndex
874: .clone(), (MFInt32) coordIndex.clone(),
875: (MFInt32) normalIndex.clone(), (MFInt32) texCoordIndex
876: .clone(), (SFNode) coord.clone(),
877: (SFNode) normal.clone(), (SFNode) color.clone(),
878: (SFNode) texCoord.clone(), (SFBool) ccw.clone(),
879: (SFBool) colorPerVertex.clone(), (SFBool) convex
880: .clone(), (SFFloat) creaseAngle.clone(),
881: (SFBool) normalPerVertex.clone(), (SFBool) solid
882: .clone());
883: loader.cleanUp();
884: return o;
885: }
886:
887: /**
888: * Gets the type attribute of the IndexedFaceSet object
889: *
890: *@return The type value
891: */
892: public String getType() {
893: return "IndexedFaceSet";
894: }
895:
896: /** Description of the Method */
897: void initFields() {
898: colorIndex.init(this , FieldSpec, Field.EVENT_IN, "colorIndex");
899: coordIndex.init(this , FieldSpec, Field.EVENT_IN, "coordIndex");
900: normalIndex
901: .init(this , FieldSpec, Field.EVENT_IN, "normalIndex");
902: texCoordIndex.init(this , FieldSpec, Field.EVENT_IN,
903: "texCoordIndex");
904:
905: color.init(this , FieldSpec, Field.EXPOSED_FIELD, "color");
906: coord.init(this , FieldSpec, Field.EXPOSED_FIELD, "coord");
907: normal.init(this , FieldSpec, Field.EXPOSED_FIELD, "normal");
908: texCoord.init(this , FieldSpec, Field.EXPOSED_FIELD, "texCoord");
909:
910: ccw.init(this , FieldSpec, Field.FIELD, "ccw");
911: colorPerVertex.init(this , FieldSpec, Field.FIELD,
912: "colorPerVertex");
913: convex.init(this , FieldSpec, Field.FIELD, "convex");
914: creaseAngle.init(this , FieldSpec, Field.FIELD, "creaseAngle");
915: normalPerVertex.init(this , FieldSpec, Field.FIELD,
916: "normalPerVertex");
917: solid.init(this , FieldSpec, Field.FIELD, "solid");
918: }
919:
920: /**
921: * Description of the Method
922: *
923: *@return Description of the Return Value
924: */
925: public String toStringBody() {
926: String retval = "IndexedFaceSet {\n";
927: if (color.node != null) {
928: retval += "color " + color;
929: }
930: if (coord.node != null) {
931: retval += "coord " + coord;
932: }
933: if (normal.node != null) {
934: retval += "normal " + normal;
935: }
936: if (texCoord.node != null) {
937: retval += " texCoord " + texCoord;
938: }
939: if (ccw.value != true) {
940: retval += "ccw FALSE\n";
941: }
942: if (colorIndex.size != 0) {
943: retval += "colorIndex " + colorIndex;
944: }
945: if (colorPerVertex.value != true) {
946: retval += "colorPerVertex FALSE\n";
947: }
948: if (convex.value != true) {
949: retval += "convex FALSE\n";
950: }
951: if (coordIndex.size != 0) {
952: retval += "coordIndex " + coordIndex;
953: }
954: if (creaseAngle.value != 0.0) {
955: retval += "creaseAngle " + creaseAngle.value + "\n";
956: }
957: if (normalIndex.size != 0) {
958: retval += "normalIndex " + normalIndex;
959: }
960: if (normalPerVertex.value != true) {
961: retval += "normalPerVertex FALSE\n";
962: }
963: if (solid.value != true) {
964: retval += "solid FALSE\n";
965: }
966: if (texCoordIndex.size != 0) {
967: retval += "texCoordIndex " + texCoordIndex;
968: }
969: retval += "}";
970: return retval;
971: }
972:
973: // fulfill the Ownable interface
974: /**
975: * Gets the solid attribute of the IndexedFaceSet object
976: *
977: *@return The solid value
978: */
979: public boolean getSolid() {
980: return solid.value;
981: }
982:
983: /**
984: * Sets the owner attribute of the IndexedFaceSet object
985: *
986: *@param s The new owner value
987: */
988: public void setOwner(Shape s) {
989: this.owner = s;
990: }
991:
992: }
|