001: /*
002: * $RCSfile: GeomBuffer.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.6 $
041: * $Date: 2007/04/24 18:50:59 $
042: * $State: Exp $
043: */
044:
045: package com.sun.j3d.utils.geometry;
046:
047: import com.sun.j3d.utils.geometry.*;
048: import java.io.*;
049: import java.util.*;
050: import javax.media.j3d.*;
051: import javax.vecmath.*;
052: import java.math.*;
053:
054: /**
055: * GeomBuffer allows OpenGL-like input of geometry data. It outputs
056: * Java 3D geometry array objects. This utility is to simplify porting
057: * of OpenGL programs to Java 3D.
058: *<p>
059: * Here is a sample code that use this utility to create some quads.
060: * <P><blockquote><pre>
061: *
062: * GeomBuffer gbuf = new GeomBuffer(100);
063: * gbuf.begin(GeomBuffer.QUADS);
064: *
065: * for (int i = 0; i < 5; i++){
066: * gbuf.normal3d(0.0, 1.0, 0.0);
067: * gbuf.vertex3d(1.0, 1.0, 0.0);
068: *
069: * gbuf.normal3d(0.0, 1.0, 0.0);
070: * gbuf.vertex3d(0.0, 1.0, 0.0);
071: *
072: * gbuf.normal3d(0.0, 1.0, 0.0);
073: * gbuf.vertex3d(0.0, 0.0, 0.0);
074: *
075: * gbuf.normal3d(0.0, 1.0, 0.0);
076: * gbuf.vertex3d(1.0, 0.0, 0.0);
077: * }
078: * gbuf.end();
079: * Shape3D shape = new Shape3D(gbuf.getGeom(GeomBuffer.GENERATE_NORMALS));
080: * </pre></blockquote>
081: * Notice, that you only need to specify some upperbound on the number of
082: * points you'll use at the beginning (100 in this case).
083: * <p>
084: * Currently, you are limited to one primitive type per geom buffer. Future
085: * versions will add support for mixed primitive types.
086: *
087: **/
088:
089: class GeomBuffer extends Object {
090:
091: //Supported Primitives
092: static final int QUAD_STRIP = 0x01;
093: static final int TRIANGLES = 0x02;
094: static final int QUADS = 0x04;
095: static final int TRIANGLE_FAN = 0x10;
096: static final int TRIANGLE_STRIP = 0x20;
097:
098: private int flags;
099:
100: Point3f[] pts = null;
101: Vector3f[] normals = null;
102: TexCoord2f[] tcoords = null;
103: int currVertCnt;
104: int currPrimCnt;
105: int[] currPrimType = null, currPrimStartVertex = null,
106: currPrimEndVertex = null;
107: GeometryArray geometry;
108: int numVerts = 0;
109: int numTris = 0;
110: int numTexUnit = 1;
111: int texCoordSetMap[] = null;
112:
113: static final int debug = 0;
114:
115: /** Creates a geometry buffer of given number of vertices
116: * @param numVerts total number of vertices to allocate by this buffer.
117: * This is an upper bound estimate.
118: */
119: GeomBuffer(int numVerts, int numTexUnit) {
120: this .numTexUnit = numTexUnit;
121: pts = new Point3f[numVerts];
122: normals = new Vector3f[numVerts];
123: tcoords = new TexCoord2f[numVerts];
124: // max primitives is numV/3
125: currPrimType = new int[numVerts / 3];
126: currPrimStartVertex = new int[numVerts / 3];
127: currPrimEndVertex = new int[numVerts / 3];
128: currVertCnt = 0;
129: currPrimCnt = 0;
130:
131: texCoordSetMap = new int[numTexUnit];
132: for (int i = 0; i < numTexUnit; i++)
133: texCoordSetMap[i] = 0;
134:
135: }
136:
137: GeomBuffer(int numVerts) {
138: this (numVerts, 1);
139: }
140:
141: /*
142: * Returns a Java 3D geometry array from the geometry buffer. You need to
143: * call begin, vertex3d, end, etc. before calling this, of course.
144: *
145: * @param format vertex format.
146: */
147:
148: GeometryArray getGeom(int format) {
149: GeometryArray obj = null;
150: flags = format;
151:
152: numTris = 0;
153:
154: //Switch based on first primitive.
155: switch (currPrimType[0]) {
156: case TRIANGLES:
157: obj = processTriangles();
158: break;
159: case QUADS:
160: obj = processQuads();
161: break;
162: case QUAD_STRIP:
163: case TRIANGLE_STRIP:
164: obj = processQuadStrips();
165: break;
166: case TRIANGLE_FAN:
167: obj = processTriangleFan();
168: break;
169: }
170: if ((obj != null)
171: && ((flags & Primitive.ENABLE_GEOMETRY_PICKING) != 0)) {
172: obj.setCapability(Geometry.ALLOW_INTERSECT);
173: obj.setCapability(GeometryArray.ALLOW_FORMAT_READ);
174: obj.setCapability(GeometryArray.ALLOW_COUNT_READ);
175: obj.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
176: }
177: return obj;
178: }
179:
180: /**
181: * Begins a new primitive given the primitive type.
182: *
183: * @param prim the primitive type (listed above).
184: *
185: **/
186:
187: void begin(int prim) {
188: if (debug >= 1)
189: System.out.println("quad");
190: currPrimType[currPrimCnt] = prim;
191: currPrimStartVertex[currPrimCnt] = currVertCnt;
192: }
193:
194: /**
195: * End of primitive.
196: *
197: *
198: **/
199: void end() {
200: if (debug >= 1)
201: System.out.println("end");
202: currPrimEndVertex[currPrimCnt] = currVertCnt;
203: currPrimCnt++;
204: }
205:
206: void vertex3d(double x, double y, double z) {
207:
208: if (debug >= 2)
209: System.out.println("v " + x + " " + y + " " + z);
210: pts[currVertCnt] = new Point3f((float) x, (float) y, (float) z);
211: currVertCnt++;
212: }
213:
214: void normal3d(double x, double y, double z) {
215: if (debug >= 2)
216: System.out.println("n " + x + " " + y + " " + z);
217: double sum = x * x + y * y + z * z;
218: if (Math.abs(sum - 1.0) > 0.001) {
219: if (debug >= 2)
220: System.out.println("normalizing");
221: double root = Math.sqrt(sum);
222: if (root > 0.000001) {
223: x /= root;
224: y /= root;
225: z /= root;
226: } else {
227: y = z = 0.0;
228: x = 1.0;
229: }
230: }
231: normals[currVertCnt] = new Vector3f((float) x, (float) y,
232: (float) z);
233: }
234:
235: void texCoord2d(double s, double t) {
236: if (debug >= 2)
237: System.out.println("t " + s + " " + t);
238: tcoords[currVertCnt] = new TexCoord2f((float) s, (float) t);
239: }
240:
241: // Return a reference to the texture coordinates of this geom buffer.
242: TexCoord2f[] getTexCoords() {
243: return tcoords;
244: }
245:
246: /**
247: * Returns the Java 3D geometry gotten from calling getGeom.
248: *
249: **/
250:
251: GeometryArray getComputedGeometry() {
252: return geometry;
253: }
254:
255: int getNumTris() {
256: return numTris;
257: }
258:
259: int getNumVerts() {
260: return numVerts;
261: }
262:
263: private GeometryArray processQuadStrips() {
264: GeometryArray obj = null;
265: int i;
266: int totalVerts = 0;
267:
268: // Calculate how many vertices needed to hold all of the individual quads
269: int stripCounts[] = new int[currPrimCnt];
270: for (i = 0; i < currPrimCnt; i++) {
271: stripCounts[i] = currPrimEndVertex[i]
272: - currPrimStartVertex[i];
273: totalVerts += stripCounts[i];
274: }
275:
276: if (debug >= 1)
277: System.out.println("totalVerts " + totalVerts);
278:
279: int tsaFlags = TriangleStripArray.COORDINATES;
280: if ((flags & Primitive.GENERATE_NORMALS) != 0)
281: tsaFlags |= TriangleStripArray.NORMALS;
282: if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)
283: tsaFlags |= TriangleStripArray.TEXTURE_COORDINATE_2;
284:
285: // Create GeometryArray to pass back
286: obj = new TriangleStripArray(totalVerts, tsaFlags, 1,
287: texCoordSetMap, stripCounts);
288:
289: // Allocate space to store new vertex info
290: Point3f[] newpts = new Point3f[totalVerts];
291: Vector3f[] newnormals = new Vector3f[totalVerts];
292: TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
293: int currVert = 0;
294:
295: // Repeat for each Quad Strip
296: for (i = 0; i < currPrimCnt; i++) {
297: // Output order for these quad arrays same as java 3d triangle strips
298: for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i]; j++) {
299: outVertex(newpts, newnormals, newtcoords, currVert++,
300: pts, normals, tcoords, j);
301: }
302:
303: }
304:
305: numVerts = currVert;
306: numTris += totalVerts - currPrimCnt * 2;
307:
308: obj.setCoordinates(0, newpts);
309: if ((flags & Primitive.GENERATE_NORMALS) != 0)
310: obj.setNormals(0, newnormals);
311: if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)
312: obj.setTextureCoordinates(0, 0, newtcoords);
313:
314: geometry = obj;
315: return obj;
316: }
317:
318: private GeometryArray processQuads() {
319: GeometryArray obj = null;
320: int i;
321: int totalVerts = 0;
322:
323: for (i = 0; i < currPrimCnt; i++) {
324: totalVerts += currPrimEndVertex[i] - currPrimStartVertex[i];
325: }
326:
327: if (debug >= 1)
328: System.out.println("totalVerts " + totalVerts);
329:
330: if (((flags & Primitive.GENERATE_NORMALS) != 0)
331: && ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)) {
332: obj = new QuadArray(totalVerts, QuadArray.COORDINATES
333: | QuadArray.NORMALS
334: | QuadArray.TEXTURE_COORDINATE_2, 1, texCoordSetMap);
335: } else if (((flags & Primitive.GENERATE_NORMALS) == 0)
336: && ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)) {
337: obj = new QuadArray(totalVerts, QuadArray.COORDINATES
338: | QuadArray.TEXTURE_COORDINATE_2, 1, texCoordSetMap);
339: } else if (((flags & Primitive.GENERATE_NORMALS) != 0)
340: && ((flags & Primitive.GENERATE_TEXTURE_COORDS) == 0)) {
341: obj = new QuadArray(totalVerts, QuadArray.COORDINATES
342: | QuadArray.NORMALS);
343: } else {
344: obj = new QuadArray(totalVerts, QuadArray.COORDINATES);
345: }
346:
347: Point3f[] newpts = new Point3f[totalVerts];
348: Vector3f[] newnormals = new Vector3f[totalVerts];
349: TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
350: int currVert = 0;
351:
352: if (debug > 1)
353: System.out.println("total prims " + currPrimCnt);
354:
355: for (i = 0; i < currPrimCnt; i++) {
356: if (debug > 1)
357: System.out.println("start " + currPrimStartVertex[i]
358: + " end " + currPrimEndVertex[i]);
359: for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i] - 3; j += 4) {
360: outVertex(newpts, newnormals, newtcoords, currVert++,
361: pts, normals, tcoords, j);
362: outVertex(newpts, newnormals, newtcoords, currVert++,
363: pts, normals, tcoords, j + 1);
364: outVertex(newpts, newnormals, newtcoords, currVert++,
365: pts, normals, tcoords, j + 2);
366: outVertex(newpts, newnormals, newtcoords, currVert++,
367: pts, normals, tcoords, j + 3);
368: numTris += 2;
369: }
370: }
371: numVerts = currVert;
372:
373: obj.setCoordinates(0, newpts);
374: if ((flags & Primitive.GENERATE_NORMALS) != 0)
375: obj.setNormals(0, newnormals);
376: if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)
377: obj.setTextureCoordinates(0, 0, newtcoords);
378:
379: geometry = obj;
380: return obj;
381: }
382:
383: private GeometryArray processTriangles() {
384: GeometryArray obj = null;
385: int i;
386: int totalVerts = 0;
387:
388: for (i = 0; i < currPrimCnt; i++) {
389: totalVerts += currPrimEndVertex[i] - currPrimStartVertex[i];
390: }
391:
392: if (debug >= 1)
393: System.out.println("totalVerts " + totalVerts);
394:
395: if (((flags & Primitive.GENERATE_NORMALS) != 0)
396: && ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)) {
397: obj = new TriangleArray(totalVerts,
398: TriangleArray.COORDINATES | TriangleArray.NORMALS
399: | TriangleArray.TEXTURE_COORDINATE_2, 1,
400: texCoordSetMap);
401: } else if (((flags & Primitive.GENERATE_NORMALS) == 0)
402: && ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)) {
403: obj = new TriangleArray(totalVerts,
404: TriangleArray.COORDINATES
405: | TriangleArray.TEXTURE_COORDINATE_2, 1,
406: texCoordSetMap);
407: } else if (((flags & Primitive.GENERATE_NORMALS) != 0)
408: && ((flags & Primitive.GENERATE_TEXTURE_COORDS) == 0)) {
409: obj = new TriangleArray(totalVerts,
410: TriangleArray.COORDINATES | TriangleArray.NORMALS);
411: } else {
412: obj = new TriangleArray(totalVerts,
413: TriangleArray.COORDINATES);
414: }
415:
416: Point3f[] newpts = new Point3f[totalVerts];
417: Vector3f[] newnormals = new Vector3f[totalVerts];
418: TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
419: int currVert = 0;
420:
421: for (i = 0; i < currPrimCnt; i++) {
422: for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i] - 2; j += 3) {
423: outVertex(newpts, newnormals, newtcoords, currVert++,
424: pts, normals, tcoords, j);
425: outVertex(newpts, newnormals, newtcoords, currVert++,
426: pts, normals, tcoords, j + 1);
427: outVertex(newpts, newnormals, newtcoords, currVert++,
428: pts, normals, tcoords, j + 2);
429: numTris += 1;
430: }
431: }
432: numVerts = currVert;
433:
434: obj.setCoordinates(0, newpts);
435: if ((flags & Primitive.GENERATE_NORMALS) != 0)
436: obj.setNormals(0, newnormals);
437: if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0)
438: obj.setTextureCoordinates(0, 0, newtcoords);
439:
440: geometry = obj;
441: return obj;
442: }
443:
444: private GeometryArray processTriangleFan() {
445: if (debug > 0)
446: System.out.println("processTriangleFan");
447:
448: GeometryArray obj = null;
449: int i;
450: int totalVerts = 0;
451:
452: int stripCounts[] = new int[currPrimCnt];
453:
454: // figure out how many vertices we need to hold the individual fans
455: for (i = 0; i < currPrimCnt; i++) {
456: stripCounts[i] = currPrimEndVertex[i]
457: - currPrimStartVertex[i];
458: totalVerts += stripCounts[i];
459: }
460:
461: // figure out what flags we need
462: int tfFlags = TriangleFanArray.COORDINATES;
463: if ((flags & Primitive.GENERATE_NORMALS) != 0) {
464: tfFlags |= TriangleFanArray.NORMALS;
465: }
466: if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) {
467: tfFlags |= TriangleFanArray.TEXTURE_COORDINATE_2;
468: }
469:
470: // create the TriangleFanArray
471: obj = new TriangleFanArray(totalVerts, tfFlags, 1,
472: texCoordSetMap, stripCounts);
473:
474: // allocate space for vertex info
475: Point3f[] newpts = new Point3f[totalVerts];
476: Vector3f[] newnormals = new Vector3f[totalVerts];
477: TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
478:
479: int currVert = 0;
480:
481: // repeat for each fan
482: for (i = 0; i < currPrimCnt; i++) {
483: for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i]; j++) {
484: outVertex(newpts, newnormals, newtcoords, currVert++,
485: pts, normals, tcoords, j);
486: }
487: }
488:
489: for (i = 0; i < newpts.length; i++) {
490: if (debug > 1)
491: System.out.println("i = " + i + " " + newpts[i]);
492: }
493:
494: numVerts = currVert;
495: numTris = totalVerts - currPrimCnt * 2;
496:
497: // set the coordinates on the GeometryArray
498: obj.setCoordinates(0, newpts);
499:
500: // set the normals and tex coords if necessary
501: if ((flags & Primitive.GENERATE_NORMALS) != 0) {
502: obj.setNormals(0, newnormals);
503: }
504: if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) {
505: obj.setTextureCoordinates(0, 0, newtcoords);
506: }
507: geometry = obj;
508: return obj;
509: }
510:
511: void outVertex(Point3f[] dpts, Vector3f[] dnormals,
512: TexCoord2f[] dtcoords, int dloc, Point3f[] spts,
513: Vector3f[] snormals, TexCoord2f[] stcoords, int sloc) {
514: if (debug >= 1)
515: System.out.println("v " + spts[sloc].x + " " + spts[sloc].y
516: + " " + spts[sloc].z);
517:
518: // PSP: Do we really need new points here?
519:
520: dpts[dloc] = new Point3f(spts[sloc]);
521:
522: if ((flags & Primitive.GENERATE_NORMALS) != 0) {
523: dnormals[dloc] = new Vector3f(snormals[sloc]);
524: }
525: if ((flags & Primitive.GENERATE_TEXTURE_COORDS) != 0) {
526: if (debug >= 2)
527: System.out.println("final out tcoord");
528: dtcoords[dloc] = new TexCoord2f(stcoords[sloc]);
529: }
530: }
531: }
|