001: /*
002: * $RCSfile: Extrusion.java,v $
003: *
004: * @(#)Extrusion.java 1.23 99/03/24 15:56:40
005: *
006: * Copyright (c) 1996-1999 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.2 $
033: * $Date: 2005/02/03 23:06:55 $
034: * $State: Exp $
035: */
036: /*
037: * @Author: Rick Goldberg
038: *
039: */
040: package org.jdesktop.j3d.loaders.vrml97.impl;
041:
042: import com.sun.j3d.utils.geometry.GeometryInfo;
043: import com.sun.j3d.utils.geometry.NormalGenerator;
044: import com.sun.j3d.utils.geometry.Stripifier;
045: import javax.media.j3d.BoundingBox;
046: import javax.media.j3d.GeometryArray;
047: import javax.media.j3d.IndexedQuadArray;
048: import javax.media.j3d.Shape3D;
049: import javax.media.j3d.Transform3D;
050: import javax.vecmath.*;
051:
052: /** Description of the Class */
053: class Extrusion extends Geometry implements Ownable {
054:
055: SFBool beginCap;
056: SFBool ccw;
057: SFBool convex;
058: SFFloat creaseAngle;
059: MFVec2f crossSection;
060: SFBool endCap;
061: MFRotation orientation;
062: MFVec2f scale;
063: SFBool solid;
064: MFVec3f spine;
065:
066: GeometryArray impl;
067: BoundingBox bounds;
068: GeometryInfo gi;
069: Shape owner;
070:
071: Point3f[] spines;
072: Vector3f[] scales;
073: AxisAngle4f[] orientations;
074: Transform3D[] spineTransforms;
075: Point3f[] crossSectionPts;
076: // will contain the per spine
077: // transform composed with orientation
078: Matrix3f[] rotations;
079: Transform3D[] transforms;
080:
081: // data -> gi
082: Point3f[] coords;
083: int[] coordIndex;
084: int[] stripCounts;
085:
086: boolean collinear = false;
087: boolean closed = false;// spines
088:
089: float[] a2 = new float[2];
090: float[] a3 = new float[3];
091: float[] a4 = new float[4];
092:
093: int numTris = 0;
094:
095: boolean hardDebug = false;
096:
097: /**
098: *Constructor for the Extrusion object
099: *
100: *@param loader Description of the Parameter
101: */
102: public Extrusion(Loader loader) {
103: super (loader);
104: beginCap = new SFBool(true);
105: endCap = new SFBool(true);
106: ccw = new SFBool(true);
107: convex = new SFBool(true);
108: solid = new SFBool(true);
109: if (loader.autoSmooth) {
110: creaseAngle = new SFFloat(.9f);
111: } else {
112: creaseAngle = new SFFloat(0);
113: }
114: crossSection = new MFVec2f(5, new float[10]);
115: crossSection.set1Value(0, 1.0f, 1.0f);
116: crossSection.set1Value(1, 1.0f, -1.0f);
117: crossSection.set1Value(2, -1.0f, -1.0f);
118: crossSection.set1Value(3, -1.0f, 1.0f);
119: crossSection.set1Value(4, 1.0f, 1.0f);
120: spine = new MFVec3f(2, new float[6]);
121: spine.set1Value(0, 0.0f, 0.0f, 0.0f);
122: spine.set1Value(1, 0.0f, 1.0f, 0.0f);
123: orientation = new MFRotation(1, new float[4]);
124: orientation.set1Value(0, 0.0f, 0.0f, 1.0f, 0.0f);
125: scale = new MFVec2f(new float[2]);
126: scale.set1Value(0, 1.0f, 1.0f);
127: initFields();
128: }
129:
130: /**
131: *Constructor for the Extrusion object
132: *
133: *@param loader Description of the Parameter
134: *@param beginCap Description of the Parameter
135: *@param ccw Description of the Parameter
136: *@param convex Description of the Parameter
137: *@param creaseAngle Description of the Parameter
138: *@param crossSection Description of the Parameter
139: *@param endCap Description of the Parameter
140: *@param orientation Description of the Parameter
141: *@param scale Description of the Parameter
142: *@param solid Description of the Parameter
143: *@param spine Description of the Parameter
144: */
145: Extrusion(Loader loader, SFBool beginCap, SFBool ccw,
146: SFBool convex, SFFloat creaseAngle, MFVec2f crossSection,
147: SFBool endCap, MFRotation orientation, MFVec2f scale,
148: SFBool solid, MFVec3f spine) {
149:
150: super (loader);
151: this .beginCap = beginCap;
152: this .ccw = ccw;
153: this .convex = convex;
154: this .creaseAngle = creaseAngle;
155: this .crossSection = crossSection;
156: this .endCap = endCap;
157: this .orientation = orientation;
158: this .scale = scale;
159: this .solid = solid;
160: this .spine = spine;
161: initFields();
162: }
163:
164: /**
165: * Description of the Method
166: *
167: *@return Description of the Return Value
168: */
169: public boolean haveTexture() {
170: return false;
171: }
172:
173: /**
174: * Gets the numTris attribute of the Extrusion object
175: *
176: *@return The numTris value
177: */
178: public int getNumTris() {
179: return numTris;
180: }
181:
182: /**
183: * Gets the implGeom attribute of the Extrusion object
184: *
185: *@return The implGeom value
186: */
187: javax.media.j3d.Geometry getImplGeom() {
188: return impl;
189: }
190:
191: /**
192: * Gets the boundingBox attribute of the Extrusion object
193: *
194: *@return The boundingBox value
195: */
196: BoundingBox getBoundingBox() {
197:
198: // create a tiny bounding box about a coordinate
199: // to seed the placement
200: Point3d epsilon = new Point3d(.000001, .000001, .000001);
201: Point3d lower = new Point3d(coords[0]);
202: Point3d upper = new Point3d(coords[0]);
203: lower.sub(epsilon);
204: upper.add(epsilon);
205:
206: bounds = new javax.media.j3d.BoundingBox(lower, upper);
207:
208: for (int c = 1; c < coords.length; c++) {
209: bounds.combine(new Point3d(coords[c]));
210: }
211: if (loader.debug) {
212: System.out.println(bounds);
213: }
214: return bounds;
215: }
216:
217: /** Description of the Method */
218: void initImpl() {
219:
220: // endcaps may need special handling
221: gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
222:
223: // convert vrml data to intermediate form
224: initSetup();
225:
226: // calculate per spine SCP transforms
227: // results in transforms[] being filled withs SCP info
228: // complete with scale, translation and orientation from
229: // fields
230: calculateSCP();
231:
232: // transform the crossSections to coordinates
233: createExtrusion();
234:
235: // indexify, including endcaps if needed
236: // leaves coordIndex with index and stripCounts with counts
237: // per facet.
238: createIndices();
239: if (hardDebug) {
240: System.out.println("coords");
241: for (int i = 0; i < coords.length; i++) {
242: System.out.println(coords[i]);
243: }
244: System.out.println("coordIndex");
245: for (int i = 0; i < coordIndex.length; i++) {
246: System.out.println(coordIndex[i]);
247: }
248: System.out.println("stripCounts");
249: for (int i = 0; i < stripCounts.length; i++) {
250: System.out.println(stripCounts[i]);
251: }
252: }
253: gi.setCoordinates(coords);
254: gi.setCoordinateIndices(coordIndex);
255: gi.setStripCounts(stripCounts);
256:
257: //Stripifier st = new Stripifier();
258: //st.stripify(gi);
259:
260: float ca = creaseAngle.getValue();
261: if (ca < 0.0f) {
262: ca = 0.0f;
263: }
264: if (ca > (float) Math.PI) {
265: ca -= (float) Math.PI;
266: }
267:
268: NormalGenerator ng = new NormalGenerator(ca);
269: ng.generateNormals(gi);
270:
271: impl = gi.getGeometryArray();
272:
273: implReady = true;
274:
275: }
276:
277: /** Description of the Method */
278: void initSetup() {
279: // load the crossSectionPts data
280: crossSectionPts = new Point3f[crossSection.getSize()];
281:
282: if (hardDebug) {
283: System.out.println(crossSection.getSize());
284: }
285: for (int i = 0; i < crossSectionPts.length; i++) {
286: crossSection.get1Value(i, a2);
287: crossSectionPts[i] = new Point3f(a2[0], 0.0f, a2[1]);
288: }
289:
290: // load the scales
291: // scales size may not match spine size, if so
292: // use previously set scale
293: scales = new Vector3f[spine.getSize()];
294: for (int i = 0; i < scales.length; i++) {
295: if (i < scale.getSize()) {
296: scale.get1Value(i, a2);
297: }
298: scales[i] = new Vector3f(a2[0], 1.0f, a2[1]);
299: }
300:
301: // load the spines
302: spines = new Point3f[spine.getSize()];
303: for (int i = 0; i < spines.length; i++) {
304: spine.get1Value(i, a3);
305: spines[i] = new Point3f(a3);
306: }
307:
308: // load the per spine orientation modifiers
309: orientations = new AxisAngle4f[spine.getSize()];
310: for (int i = 0; i < orientations.length; i++) {
311: if (i < orientation.getSize()) {
312: orientation.get1Value(i, a4);
313: }
314: orientations[i] = new AxisAngle4f(a4);
315: }
316:
317: rotations = new Matrix3f[spines.length];
318:
319: // if the tail meets the head
320: if (spines[0].equals(spines[spines.length - 1])) {
321: closed = true;
322: }
323:
324: // if entirely collinear
325: Vector3d v2 = new Vector3d();
326: Vector3d v1 = new Vector3d();
327: Vector3d v0 = new Vector3d();
328: double d = 0.0;
329: for (int i = 1; i < spines.length - 1; i++) {
330: v2.set(spines[i + 1]);
331: v1.set(spines[i]);
332: v0.set(spines[i - 1]);
333: v2.sub(v1);
334: v1.sub(v0);
335: v0.cross(v2, v1);
336: d += v0.dot(v0);
337: }
338: collinear = (d == 0.0);
339: if (hardDebug && collinear) {
340: System.out.println("spine is straight");
341: }
342:
343: }
344:
345: /** Description of the Method */
346: void calculateSCP() {
347: // find an orthonormal basis and construct rotation matrix
348: // for each spine. handle special cases in second pass
349: Vector3f[] x;
350: // find an orthonormal basis and construct rotation matrix
351: // for each spine. handle special cases in second pass
352: Vector3f[] y;
353: // find an orthonormal basis and construct rotation matrix
354: // for each spine. handle special cases in second pass
355: Vector3f[] z;
356: Vector3f u;
357: Vector3f v;
358: Vector3f zero = new Vector3f(0.0f, 0.0f, 0.0f);
359: int last = spines.length - 1;
360:
361: x = new Vector3f[spines.length];
362: y = new Vector3f[spines.length];
363: z = new Vector3f[spines.length];
364:
365: if (collinear) {
366: if (closed) {
367: throw new vrml.InvalidVRMLSyntaxException(
368: "invalid Extrusion data; looks like a solid of revolution");
369: }
370:
371: for (int i = 0; i < spines.length; i++) {
372: // redo, this should take the direction of y
373: x[i] = new Vector3f(1.0f, 0.0f, 0.0f);
374: y[i] = new Vector3f(0.0f, 1.0f, 0.0f);
375: z[i] = new Vector3f(0.0f, 0.0f, 1.0f);
376: }
377: } else {
378: // find y[i] for all but first and last
379: // most times the exception cases are bad data and hopefully
380: // wont happen. It is free to try catch you later, so hopes
381: // 99% cases will be one if faster by not checking the if
382: for (int i = 1; i < last; i++) {
383: y[i] = new Vector3f();
384: y[i].sub(spines[i + 1], spines[i - 1]);
385: try {
386: norm(y[i]);
387: } catch (ArithmeticException ae) {
388: if (hardDebug) {
389: System.out.println(ae + " " + y[i]);
390: }
391: // spines[i+1] equals spines[i-1]
392: try {
393: y[i].sub(spines[i + 1], spines[i]);
394: norm(y[i]);
395: } catch (ArithmeticException ae1) {
396: if (hardDebug) {
397: System.out.println(ae1 + " " + y[i]);
398: }
399: // spines[i+1] equaled spines[i]
400: try {
401: y[i].sub(spines[i], spines[i - 1]);
402: norm(y[i]);
403: } catch (ArithmeticException ae2) {
404: if (hardDebug) {
405: System.out.println(ae2 + " " + y[i]);
406: }
407: // spines[i] equaled spines[i-1]
408: // real bad case, do something
409: int w = i + 2;
410: while ((w < last + 1)
411: && (spines[i - 1].equals(spines[w]))) {
412: w++;
413: }
414: if (w < last + 1) {
415: y[i].sub(spines[w], spines[i - 1]);
416: if (hardDebug) {
417: System.out.println("did something "
418: + y[i]);
419: }
420: norm(y[i]);// should never divide by zero here
421: } else {// worst worst case
422: if (hardDebug) {
423: System.out.println("worst worst y "
424: + y[i]);
425: }
426: y[i] = new Vector3f(0.0f, 1.0f, 0.0f);
427: }
428: }
429: }
430: }
431: }
432: // y for ends
433: if (closed) {
434: // closed and not collinear -> not all one point
435: y[0] = new Vector3f();
436: y[0].sub(spines[1], spines[last - 1]);
437: try {
438: norm(y[0]);
439: } catch (ArithmeticException ae) {
440: // bad case that the spine[n-2] == spine[1]
441: int w = last - 2;
442: while ((w > 1) && (spines[1].equals(spines[w]))) {
443: w--;
444: }
445: if (w > 1) {
446: y[0].sub(spines[1], spines[w]);
447: norm(y[0]);// should never divide by zero here
448: } else {
449: // how did this happen?
450: y[0].set(0.0f, 0.0f, 1.0f);
451: }
452: }
453: y[last] = new Vector3f(y[0]);
454: } else {
455: y[0] = new Vector3f();
456: y[last] = new Vector3f();
457: y[0].sub(spines[1], spines[0]);
458: try {
459: norm(y[0]);
460: } catch (ArithmeticException ae) {
461: int w = 2;
462: while ((w < last) && (spines[0].equals(spines[w]))) {
463: w++;
464: }
465: if (w < last) {
466: y[0].sub(spines[w], spines[0]);
467: norm(y[0]);// should not divide by zero here
468: } else {
469: y[0].set(0.0f, 0.0f, 1.0f);
470: }
471: }
472: y[last] = new Vector3f();
473: y[last].sub(spines[last], spines[last - 1]);
474: try {
475: norm(y[last]);
476: } catch (ArithmeticException ae) {
477: int w = last - 2;
478: while ((w > -1) && (spines[last].equals(spines[w]))) {
479: w--;
480: }
481: if (w > -1) {
482: y[last].sub(spines[last], spines[w]);
483: norm(y[last]);
484: } else {
485: y[last].set(0.0f, 0.0f, 1.0f);
486: }
487: }
488: }
489: // now z axis for each spine
490: // first all except first and last
491:
492: boolean recheck = false;
493: for (int i = 1; i < last; i++) {
494: u = new Vector3f();
495: v = new Vector3f();
496: z[i] = new Vector3f();
497: u.sub(spines[i - 1], spines[i]);
498: v.sub(spines[i + 1], spines[i]);
499: // spec seems backwards on u and v
500: // shouldn't it be z[i].cross(u,v)???
501: //z[i].cross(v,u);
502: z[i].cross(u, v);
503: try {
504: norm(z[i]);
505: } catch (ArithmeticException ae) {
506: recheck = true;
507: }
508: }
509: if (closed) {
510: z[0] = z[last] = new Vector3f();
511: u = new Vector3f();
512: v = new Vector3f();
513: u.sub(spines[last - 1], spines[0]);
514: v.sub(spines[1], spines[0]);
515: try {
516: z[0].cross(u, v);
517: } catch (ArithmeticException ae) {
518: recheck = true;
519: }
520: } else {// not closed
521: z[0] = new Vector3f(z[1]);
522: z[last] = new Vector3f(z[last - 1]);
523: }
524: if (recheck) {// found adjacent collinear spines
525: // first z has no length ?
526: if (hardDebug) {
527: System.out
528: .println("rechecking, found adjacent collinear spines");
529: }
530: if (z[0].dot(z[0]) == 0.0f) {
531: for (int i = 1; i < spines.length; i++) {
532: if (z[i].dot(z[i]) > 0.0f) {
533: z[0] = new Vector3f(z[i]);
534: }
535: }
536: // test again could be most degenerate of cases
537: if (z[0].dot(z[0]) == 0.0f) {
538: z[0] = new Vector3f(0.0f, 0.0f, 1.0f);
539: }
540: }
541:
542: // check rest of z's
543: for (int i = 1; i < last + 1; i++) {
544: if (z[i].dot(z[i]) == 0.0f) {
545: z[i] = new Vector3f(z[i - 1]);
546: }
547: }
548: }
549: // finally, do a neighbor comparison
550: // and evaluate the x's
551: for (int i = 0; i < spines.length; i++) {
552: if (i > 0) {
553: if (z[i].dot(z[i - 1]) < 0.0f) {
554: z[i].negate();
555: }
556: }
557:
558: // at this point, y and z should be nice
559: x[i] = new Vector3f();
560: x[i].cross(z[i], y[i]);
561: try {
562: norm(x[i]);
563: } catch (ArithmeticException ae) {
564: // this should not happen
565: ae.printStackTrace();
566: }
567: if (hardDebug) {
568: System.out.println("x[" + i + "] " + x[i]);
569: }
570: }
571:
572: }
573:
574: // should now have orthonormal vectors for each
575: // spine. create the rotation matrix with scale for
576: // each spine. spec is unclear whether a twist imparted
577: // at one of the spines is inherited by its "children"
578: // so assume not.
579:
580: // also, the order looks like SxTxRscpxRo , ie ,
581: // the spec doc looks suspect, double check
582:
583: Matrix3f m = new Matrix3f();
584: transforms = new Transform3D[spines.length];
585:
586: for (int i = 0; i < spines.length; i++) {
587: rotations[i] = new Matrix3f();
588: if (hardDebug) {
589: System.out.println("orthos " + i + " " + x[i] + " "
590: + y[i] + " " + z[i] + " " + orientations[i]);
591: }
592: rotations[i].setRow(0, x[i]);
593: rotations[i].setRow(1, y[i]);
594: rotations[i].setRow(2, z[i]);
595: m.set(orientations[i]);
596: rotations[i].mul(m);
597: transforms[i] = new Transform3D();
598: transforms[i].setScale(new Vector3d(scales[i]));
599: transforms[i].setTranslation(new Vector3d(spines[i]));
600: transforms[i].setRotation(rotations[i]);
601: }
602: }
603:
604: // create a list of unique coords ( of Point3f )
605: // by applying the transforms to the crossSectionPts
606: /** Description of the Method */
607: void createExtrusion() {
608:
609: coords = new Point3f[spines.length * crossSectionPts.length];
610:
611: for (int i = 0; i < spines.length; i++) {
612: for (int j = 0; j < crossSectionPts.length; j++) {
613: int ind = i * (crossSectionPts.length) + j;
614: coords[ind] = new Point3f(crossSectionPts[j]);
615: transforms[i].transform(coords[ind]);
616: }
617: }
618: }
619:
620: // wind the coords with indexed connectivity and create
621: // stripCounts see page 47 of small bluebook
622: /** Description of the Method */
623: void createIndices() {
624: int m = 0;// coordIndex length
625: int k = crossSectionPts.length;
626: int l = coords.length;
627: int s = 0;
628: int n = 0;// coordIndex count
629: if (endCap.value) {
630: m += k - 1;
631: s++;
632: }
633: if (beginCap.value) {
634: m += k - 1;
635: s++;
636: }
637: m += (spines.length - 1) * (4 * (k - 1));
638: coordIndex = new int[m];
639: if (hardDebug) {
640: System.out.println("coordIndexSize" + m);
641: }
642: stripCounts = new int[s + (spines.length - 1) * (k - 1)];
643: s = 0;
644: if (hardDebug) {
645: System.out.println("stripCounts.length"
646: + stripCounts.length);
647: }
648: if (hardDebug) {
649: System.out.println("spines.length" + spines.length);
650: }
651: // start with extrusion body from bottom
652: for (int i = 0; i < spines.length - 1; i++) {
653: if (hardDebug) {
654: System.out.println(" i " + i);
655: }
656: for (int j = 0; j < k - 1; j++) {
657: if (hardDebug) {
658: System.out.println(" j " + j);
659: }
660: // create a quad
661: if (ccw.value) {
662: if (hardDebug) {
663: System.out.println("i " + i + " j " + j + " k "
664: + k);
665: }
666: coordIndex[n++] = (i * k) + j;
667: if (hardDebug) {
668: System.out.println((n - 1) + " "
669: + ((i * k) + (j)));
670: }
671: coordIndex[n++] = (i * k) + j + 1;
672: if (hardDebug) {
673: System.out.println((n - 1) + " "
674: + ((i * k) + (j + 1)));
675: }
676: coordIndex[n++] = ((i + 1) * k) + j + 1;
677: if (hardDebug) {
678: System.out.println((n - 1) + " "
679: + (((i + 1) * k) + (j + 1)));
680: }
681: coordIndex[n++] = ((i + 1) * k) + j;
682: if (hardDebug) {
683: System.out.println((n - 1) + " "
684: + (((i + 1) * k) + (j)));
685: }
686: } else {
687: coordIndex[n++] = (i * k) + j;
688: coordIndex[n++] = ((i + 1) * k) + j;
689: coordIndex[n++] = ((i + 1) * k) + j + 1;
690: coordIndex[n++] = (i * k) + j + 1;
691: }
692: stripCounts[s++] = 4;
693: numTris += 2;
694: }
695: }
696: // add top and bottom
697: // note: when switching cw from ccw notice that
698: // the index is off by one, this is ok since there
699: // is one extra point in the cross-section, each
700: // cap has 2 ways to be drawn
701: // also note top and bottom caps are reverse oriented to
702: // each other
703: if (beginCap.value && endCap.value) {
704: int indB = m - (2 * (k - 1));
705: int indE = m - (k - 1);
706: if (!ccw.value) {
707: for (int i = 0; i < k - 1; i++) {
708: coordIndex[indB++] = i;
709: }
710:
711: for (int i = l - 1; i > l - k; i--) {
712: coordIndex[indE++] = i;
713: }
714:
715: } else {
716: for (int i = k - 1; i > 0; i--) {
717: coordIndex[indB++] = i;
718: }
719: for (int i = 0; i < k - 1; i++) {
720: coordIndex[indE++] = l - (k - 1) + i;
721: }
722: }
723: stripCounts[s++] = k - 1;
724: stripCounts[s++] = k - 1;
725: numTris += k - 1;// best guess what gi did?
726: } else if (beginCap.value) {
727: int ind = m - (k - 1);
728: if (!ccw.value) {
729: for (int i = 0; i < k - 1; i++) {
730: coordIndex[ind++] = i;
731: }
732: } else {// this is ok since extra x-sectpt give off by one
733: for (int i = k - 1; i > 0; i--) {
734: coordIndex[ind++] = i;
735: }
736: }
737: stripCounts[s++] = k - 1;
738: numTris += k - 1;
739: } else if (endCap.value) {
740: int ind = m - (k - 1);
741: if (ccw.value) {
742: for (int i = l - (k - 1); i < l; i++) {
743: coordIndex[ind++] = i;
744: }
745: } else {
746: for (int i = l - 1; i > l - k; i--) {
747: coordIndex[ind++] = i;
748: }
749: }
750: stripCounts[s++] = k - 1;
751: numTris += k - 1;
752: }
753: }
754:
755: // the vecmath package was not throwing ArithmeticExceptions as
756: // expected from the normalize() method.
757: /**
758: * Description of the Method
759: *
760: *@param n Description of the Parameter
761: */
762: void norm(Vector3f n) {
763: float norml = (float) Math.sqrt(n.x * n.x + n.y * n.y + n.z
764: * n.z);
765: if (norml == 0.0f) {
766: throw new ArithmeticException();
767: }
768:
769: n.x /= norml;
770: n.y /= norml;
771: n.z /= norml;
772: }
773:
774: /**
775: * Description of the Method
776: *
777: *@param eventInName Description of the Parameter
778: *@param time Description of the Parameter
779: */
780: public void notifyMethod(String eventInName, double time) {
781: if (!eventInName.startsWith("route_")) {
782: initImpl();
783: ((Shape3D) (owner.implNode)).setGeometry(impl);
784: } else {
785: ((Shape3D) (owner.implNode))
786: .setCapability(Shape3D.ALLOW_GEOMETRY_WRITE);
787: }
788: }
789:
790: /** Description of the Method */
791: void initFields() {
792:
793: beginCap.init(this , FieldSpec, Field.FIELD, "beginCap");
794: ccw.init(this , FieldSpec, Field.FIELD, "ccw");
795: convex.init(this , FieldSpec, Field.FIELD, "convex");
796: creaseAngle.init(this , FieldSpec, Field.FIELD, "creaseAngle");
797: crossSection.init(this , FieldSpec, Field.EVENT_IN,
798: "crossSection");
799: endCap.init(this , FieldSpec, Field.FIELD, "endCap");
800: orientation
801: .init(this , FieldSpec, Field.EVENT_IN, "orientation");
802: scale.init(this , FieldSpec, Field.EVENT_IN, "scale");
803: solid.init(this , FieldSpec, Field.FIELD, "solid");
804: spine.init(this , FieldSpec, Field.EVENT_IN, "spine");
805: }
806:
807: /**
808: * Description of the Method
809: *
810: *@return Description of the Return Value
811: */
812: public Object clone() {
813: return new Extrusion(loader, (SFBool) beginCap.clone(),
814: (SFBool) ccw.clone(), (SFBool) convex.clone(),
815: (SFFloat) creaseAngle.clone(), (MFVec2f) crossSection
816: .clone(), (SFBool) endCap.clone(),
817: (MFRotation) orientation.clone(), (MFVec2f) scale
818: .clone(), (SFBool) solid.clone(),
819: (MFVec3f) spine.clone());
820: }
821:
822: /**
823: * Gets the type attribute of the Extrusion object
824: *
825: *@return The type value
826: */
827: public String getType() {
828: return "Extrusion";
829: }
830:
831: /**
832: * Gets the solid attribute of the Extrusion object
833: *
834: *@return The solid value
835: */
836: public boolean getSolid() {
837: return solid.value;
838: }
839:
840: /**
841: * Sets the owner attribute of the Extrusion object
842: *
843: *@param owner The new owner value
844: */
845: public void setOwner(Shape owner) {
846: this.owner = owner;
847: }
848: }
|