001: /*
002: * $Header: /cvs/j3dfly/J3dFly/src/org/jdesktop/j3dfly/utils/environment/geometry/GeomBuffer.java,v 1.1 2005/04/20 21:04:54 paulby Exp $
003: *
004: * Sun Public License Notice
005: *
006: * The contents of this file are subject to the Sun Public License Version
007: * 1.0 (the "License"). You may not use this file except in compliance with
008: * the License. A copy of the License is available at http://www.sun.com/
009: *
010: * The Original Code is Java 3D(tm) Fly Through.
011: * The Initial Developer of the Original Code is Paul Byrne.
012: * Portions created by Paul Byrne are Copyright (C) 2002.
013: * All Rights Reserved.
014: *
015: * Contributor(s): Paul Byrne.
016: *
017: **/
018: package org.jdesktop.j3dfly.utils.environment.geometry;
019:
020: import java.io.*;
021: import java.util.*;
022: import javax.media.j3d.*;
023: import javax.vecmath.*;
024: import java.math.*;
025:
026: /**
027: * GeomBuffer allows OpenGL-like input of geometry data. It outputs
028: * Java 3D geometry array objects. This utility is to simplify porting
029: * of OpenGL programs to Java 3D.
030: *<p>
031: * Here is a sample code that use this utility to create some quads.
032: * <P><blockquote><pre>
033: *
034: * GeomBuffer gbuf = new GeomBuffer(100);
035: * gbuf.begin(GeomBuffer.QUADS);
036: *
037: * for (int i = 0; i < 5; i++){
038: * gbuf.normal3d(0.0, 1.0, 0.0);
039: * gbuf.vertex3d(1.0, 1.0, 0.0);
040: *
041: * gbuf.normal3d(0.0, 1.0, 0.0);
042: * gbuf.vertex3d(0.0, 1.0, 0.0);
043: *
044: * gbuf.normal3d(0.0, 1.0, 0.0);
045: * gbuf.vertex3d(0.0, 0.0, 0.0);
046: *
047: * gbuf.normal3d(0.0, 1.0, 0.0);
048: * gbuf.vertex3d(1.0, 0.0, 0.0);
049: * }
050: * gbuf.end();
051: * Shape3D shape = new Shape3D(gbuf.getGeom(GeomBuffer.GENERATE_NORMALS));
052: * </pre></blockquote>
053: * Notice, that you only need to specify some upperbound on the number of
054: * points you'll use at the beginning (100 in this case).
055: * <p>
056: * Currently, you are limited to one primitive type per geom buffer. Future
057: * versions will add support for mixed primitive types.
058: *
059: **/
060:
061: class GeomBuffer extends Object {
062:
063: //Supported Primitives
064: static final int QUAD_STRIP = 0x01;
065: static final int TRIANGLES = 0x02;
066: static final int QUADS = 0x04;
067: static final int TRIANGLE_FAN = 0x10;
068:
069: private int flags;
070: static final int GENERATE_NORMALS = 0x01;
071: static final int GENERATE_TEXTURE_COORDS = 0x02;
072: static final int GENERATE_COLOR_3 = 0x08;
073:
074: Point3f[] pts = null;
075: Vector3f[] normals = null;
076: TexCoord2f[] tcoords = null;
077: Color3f[] colors = null;
078: int currVertCnt;
079: int currPrimCnt;
080: int currentColorCnt;
081: int[] currPrimType = null, currPrimStartVertex = null,
082: currPrimEndVertex = null;
083: GeometryArray geometry;
084: int numVerts = 0;
085: int numTris = 0;
086: int numTexUnit = 1;
087: int texCoordSetMap[] = null;
088:
089: static final int debug = 0;
090:
091: /** Creates a geometry buffer of given number of vertices
092: * @param numVerts total number of vertices to allocate by this buffer.
093: * This is an upper bound estimate.
094: */
095: GeomBuffer(int numVerts, int numTexUnit) {
096: this .numTexUnit = numTexUnit;
097: pts = new Point3f[numVerts];
098: normals = new Vector3f[numVerts];
099: tcoords = new TexCoord2f[numVerts];
100: colors = new Color3f[numVerts];
101: // max primitives is numV/3
102: currPrimType = new int[numVerts / 3];
103: currPrimStartVertex = new int[numVerts / 3];
104: currPrimEndVertex = new int[numVerts / 3];
105: currVertCnt = 0;
106: currPrimCnt = 0;
107: currentColorCnt = 0;
108:
109: texCoordSetMap = new int[numTexUnit];
110: for (int i = 0; i < numTexUnit; i++)
111: texCoordSetMap[i] = 0;
112:
113: }
114:
115: GeomBuffer(int numVerts) {
116: this (numVerts, 1);
117: }
118:
119: /*
120: * Returns a Java 3D geometry array from the geometry buffer. You need to
121: * call begin, vertex3d, end, etc. before calling this, of course.
122: *
123: * @param format vertex format.
124: */
125:
126: GeometryArray getGeom(int format) {
127: GeometryArray obj;
128: flags = format;
129:
130: numTris = 0;
131:
132: //Switch based on first primitive.
133: switch (currPrimType[0]) {
134: case TRIANGLES:
135: obj = processTriangles();
136: if ((flags & Primitive.ENABLE_GEOMETRY_PICKING) != 0)
137: obj.setCapability(Geometry.ALLOW_INTERSECT);
138: return obj;
139: case QUADS:
140: obj = processQuads();
141: if ((flags & Primitive.ENABLE_GEOMETRY_PICKING) != 0)
142: obj.setCapability(Geometry.ALLOW_INTERSECT);
143: return obj;
144: case QUAD_STRIP:
145: obj = processQuadStrips();
146: if ((flags & Primitive.ENABLE_GEOMETRY_PICKING) != 0)
147: obj.setCapability(Geometry.ALLOW_INTERSECT);
148: return obj;
149: case TRIANGLE_FAN:
150: obj = processTriangleFan();
151: if ((flags & Primitive.ENABLE_GEOMETRY_PICKING) != 0) {
152: obj.setCapability(Geometry.ALLOW_INTERSECT);
153: }
154: return obj;
155: }
156: return null;
157: }
158:
159: /**
160: * Begins a new primitive given the primitive type.
161: *
162: * @param prim the primitive type (listed above).
163: *
164: **/
165:
166: void begin(int prim) {
167: if (debug >= 1)
168: System.out.println("quad");
169: currPrimType[currPrimCnt] = prim;
170: currPrimStartVertex[currPrimCnt] = currVertCnt;
171: }
172:
173: /**
174: * End of primitive.
175: *
176: *
177: **/
178: void end() {
179: if (debug >= 1)
180: System.out.println("end");
181: currPrimEndVertex[currPrimCnt] = currVertCnt;
182: currPrimCnt++;
183: }
184:
185: void color3f(float r, float g, float b) {
186: colors[currVertCnt] = new Color3f(r, g, b);
187: currentColorCnt++;
188: }
189:
190: void vertex3d(double x, double y, double z) {
191: if (debug >= 2)
192: System.out.println("v " + x + " " + y + " " + z);
193: pts[currVertCnt] = new Point3f((float) x, (float) y, (float) z);
194: currVertCnt++;
195: }
196:
197: void normal3d(double x, double y, double z) {
198: if (debug >= 2)
199: System.out.println("n " + x + " " + y + " " + z);
200: double sum = x * x + y * y + z * z;
201: if (Math.abs(sum - 1.0) > 0.001) {
202: if (debug >= 2)
203: System.out.println("normalizing");
204: double root = Math.sqrt(sum);
205: if (root > 0.000001) {
206: x /= root;
207: y /= root;
208: z /= root;
209: } else {
210: y = z = 0.0;
211: x = 1.0;
212: }
213: }
214: normals[currVertCnt] = new Vector3f((float) x, (float) y,
215: (float) z);
216: }
217:
218: void texCoord2d(double s, double t) {
219: if (debug >= 2)
220: System.out.println("t " + s + " " + t);
221: tcoords[currVertCnt] = new TexCoord2f((float) s, (float) t);
222: }
223:
224: /**
225: * Returns the Java 3D geometry gotten from calling getGeom.
226: *
227: **/
228:
229: GeometryArray getComputedGeometry() {
230: return geometry;
231: }
232:
233: int getNumTris() {
234: return numTris;
235: }
236:
237: int getNumVerts() {
238: return numVerts;
239: }
240:
241: private GeometryArray processQuadStrips() {
242: GeometryArray obj = null;
243: int i;
244: int totalVerts = 0;
245:
246: // Calculate how many vertices needed to hold all of the individual quads
247: int stripCounts[] = new int[currPrimCnt];
248: for (i = 0; i < currPrimCnt; i++) {
249: stripCounts[i] = currPrimEndVertex[i]
250: - currPrimStartVertex[i];
251: totalVerts += stripCounts[i];
252: }
253:
254: if (debug >= 1)
255: System.out.println("totalVerts " + totalVerts);
256:
257: int tsaFlags = TriangleStripArray.COORDINATES;
258: if ((flags & GENERATE_NORMALS) != 0)
259: tsaFlags |= TriangleStripArray.NORMALS;
260: if ((flags & GENERATE_TEXTURE_COORDS) != 0)
261: tsaFlags |= TriangleStripArray.TEXTURE_COORDINATE_2;
262: if ((flags & GENERATE_COLOR_3) != 0)
263: tsaFlags |= TriangleStripArray.COLOR_3;
264:
265: // Create GeometryArray to pass back
266: obj = new TriangleStripArray(totalVerts, tsaFlags, 1,
267: texCoordSetMap, stripCounts);
268:
269: // Allocate space to store new vertex info
270: Point3f[] newpts = new Point3f[totalVerts];
271: Vector3f[] newnormals = new Vector3f[totalVerts];
272: TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
273: Color3f[] newcolors = new Color3f[totalVerts];
274: int currVert = 0;
275:
276: // Repeat for each Quad Strip
277: for (i = 0; i < currPrimCnt; i++) {
278: // Output order for these quad arrays same as java 3d triangle strips
279: for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i]; j++) {
280: outVertex(newpts, newnormals, newtcoords, newcolors,
281: currVert++, pts, normals, tcoords, colors, j);
282: }
283: }
284: numVerts = currVert;
285: numTris += totalVerts - currPrimCnt * 2;
286:
287: obj.setCoordinates(0, newpts);
288: if ((flags & GENERATE_NORMALS) != 0)
289: obj.setNormals(0, newnormals);
290: if ((flags & GENERATE_TEXTURE_COORDS) != 0)
291: obj.setTextureCoordinates(0, 0, newtcoords);
292: if ((flags & GENERATE_COLOR_3) != 0)
293: obj.setColors(0, newcolors);
294:
295: geometry = obj;
296: return obj;
297: }
298:
299: private GeometryArray processQuads() {
300: throw new RuntimeException("Not implemented");
301: }
302:
303: /*
304: GeometryArray obj = null;
305: int i;
306: int totalVerts = 0;
307:
308: for (i = 0; i < currPrimCnt; i++){
309: totalVerts += currPrimEndVertex[i] - currPrimStartVertex[i];
310: }
311:
312: if (debug >= 1) System.out.println("totalVerts " + totalVerts);
313:
314: if (((flags & GENERATE_NORMALS) != 0) &&
315: ((flags & GENERATE_TEXTURE_COORDS) != 0)){
316: obj = new QuadArray(totalVerts,
317: QuadArray.COORDINATES |
318: QuadArray.NORMALS |
319: QuadArray.TEXTURE_COORDINATE_2,
320: 1, texCoordSetMap);
321: }
322: else
323: if (((flags & GENERATE_NORMALS) == 0) &&
324: ((flags & GENERATE_TEXTURE_COORDS) != 0)){
325: obj = new QuadArray(totalVerts,
326: QuadArray.COORDINATES |
327: QuadArray.TEXTURE_COORDINATE_2,
328: 1, texCoordSetMap);
329: }
330: else
331: if (((flags & GENERATE_NORMALS) != 0) &&
332: ((flags & GENERATE_TEXTURE_COORDS) == 0)){
333: obj = new QuadArray(totalVerts,
334: QuadArray.COORDINATES |
335: QuadArray.NORMALS);
336: }
337: else {
338: obj = new QuadArray(totalVerts,
339: QuadArray.COORDINATES);
340: }
341:
342: Point3f[] newpts = new Point3f[totalVerts];
343: Vector3f[] newnormals = new Vector3f[totalVerts];
344: TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
345: int currVert = 0;
346:
347: if (debug > 1) System.out.println("total prims " + currPrimCnt);
348:
349: for (i = 0; i < currPrimCnt; i++){
350: if (debug > 1) System.out.println("start " + currPrimStartVertex[i] +
351: " end " + currPrimEndVertex[i]);
352: for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i] - 3;j+=4){
353: outVertex(newpts, newnormals, newtcoords, currVert++,
354: pts, normals, tcoords, j);
355: outVertex(newpts, newnormals, newtcoords, currVert++,
356: pts, normals, tcoords, j + 1);
357: outVertex(newpts, newnormals, newtcoords, currVert++,
358: pts, normals, tcoords, j + 2);
359: outVertex(newpts, newnormals, newtcoords, currVert++,
360: pts, normals, tcoords, j + 3);
361: numTris += 2;
362: }
363: }
364: numVerts = currVert;
365:
366: obj.setCoordinates(0, newpts);
367: if ((flags & GENERATE_NORMALS) != 0)
368: obj.setNormals(0, newnormals);
369: if ((flags & GENERATE_TEXTURE_COORDS) != 0)
370: obj.setTextureCoordinates(0, 0, newtcoords);
371:
372: geometry = obj;
373: return obj;
374: }
375:
376: */
377: private GeometryArray processTriangles() {
378: throw new RuntimeException("Not Implemented");
379: }
380:
381: /*
382: GeometryArray obj = null;
383: int i;
384: int totalVerts = 0;
385:
386: for (i = 0; i < currPrimCnt; i++){
387: totalVerts += currPrimEndVertex[i] - currPrimStartVertex[i];
388: }
389:
390: if (debug >= 1) System.out.println("totalVerts " + totalVerts);
391:
392: if (((flags & GENERATE_NORMALS) != 0) &&
393: ((flags & GENERATE_TEXTURE_COORDS) != 0)){
394: obj = new TriangleArray(totalVerts,
395: TriangleArray.COORDINATES |
396: TriangleArray.NORMALS |
397: TriangleArray.TEXTURE_COORDINATE_2,
398: 1, texCoordSetMap);
399: }
400: else
401: if (((flags & GENERATE_NORMALS) == 0) &&
402: ((flags & GENERATE_TEXTURE_COORDS) != 0)){
403: obj = new TriangleArray(totalVerts,
404: TriangleArray.COORDINATES |
405: TriangleArray.TEXTURE_COORDINATE_2,
406: 1, texCoordSetMap);
407: }
408: else
409: if (((flags & GENERATE_NORMALS) != 0) &&
410: ((flags & GENERATE_TEXTURE_COORDS) == 0)){
411: obj = new TriangleArray(totalVerts,
412: TriangleArray.COORDINATES |
413: TriangleArray.NORMALS);
414: }
415: else {
416: obj = new TriangleArray(totalVerts,
417: TriangleArray.COORDINATES);
418: }
419:
420: Point3f[] newpts = new Point3f[totalVerts];
421: Vector3f[] newnormals = new Vector3f[totalVerts];
422: TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
423: int currVert = 0;
424:
425: for (i = 0; i < currPrimCnt; i++){
426: for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i] - 2;j+=3){
427: outVertex(newpts, newnormals, newtcoords, currVert++,
428: pts, normals, tcoords, j);
429: outVertex(newpts, newnormals, newtcoords, currVert++,
430: pts, normals, tcoords, j + 1);
431: outVertex(newpts, newnormals, newtcoords, currVert++,
432: pts, normals, tcoords, j + 2);
433: numTris += 1;
434: }
435: }
436: numVerts = currVert;
437:
438: obj.setCoordinates(0, newpts);
439: if ((flags & GENERATE_NORMALS) != 0)
440: obj.setNormals(0, newnormals);
441: if ((flags & GENERATE_TEXTURE_COORDS) != 0)
442: obj.setTextureCoordinates(0, 0, newtcoords);
443:
444: geometry = obj;
445: return obj;
446: }
447:
448: */
449: private GeometryArray processTriangleFan() {
450: throw new RuntimeException("Not Implemented");
451: }
452:
453: /*
454: if (debug > 0) System.out.println("processTriangleFan");
455:
456: GeometryArray obj = null;
457: int i;
458: int totalVerts = 0;
459:
460: int stripCounts[] = new int[currPrimCnt];
461:
462: // figure out how many vertices we need to hold the individual fans
463: for (i = 0; i < currPrimCnt; i++) {
464: stripCounts[i] = currPrimEndVertex[i] - currPrimStartVertex[i];
465: totalVerts += stripCounts[i];
466: }
467:
468: // figure out what flags we need
469: int tfFlags = TriangleFanArray.COORDINATES;
470: if ((flags & GENERATE_NORMALS) != 0) {
471: tfFlags |= TriangleFanArray.NORMALS;
472: }
473: if ((flags & GENERATE_TEXTURE_COORDS) != 0) {
474: tfFlags |= TriangleFanArray.TEXTURE_COORDINATE_2;
475: }
476:
477: // create the TriangleFanArray
478: obj = new TriangleFanArray(totalVerts, tfFlags, 1, texCoordSetMap,
479: stripCounts);
480:
481: // allocate space for vertex info
482: Point3f[] newpts = new Point3f[totalVerts];
483: Vector3f[] newnormals = new Vector3f[totalVerts];
484: TexCoord2f[] newtcoords = new TexCoord2f[totalVerts];
485:
486: int currVert = 0;
487:
488: // repeat for each fan
489: for (i = 0; i < currPrimCnt; i++) {
490: for (int j = currPrimStartVertex[i]; j < currPrimEndVertex[i]; j++) {
491: outVertex(newpts, newnormals, newtcoords, currVert++, pts,
492: normals, tcoords, j);
493: }
494: }
495:
496: for (i = 0; i < newpts.length; i++) {
497: if (debug > 1) System.out.println("i = " + i + " " + newpts[i]);
498: }
499:
500: numVerts = currVert;
501: numTris = totalVerts - currPrimCnt * 2;
502:
503: // set the coordinates on the GeometryArray
504: obj.setCoordinates(0, newpts);
505:
506: // set the normals and tex coords if necessary
507: if ((flags & GENERATE_NORMALS) != 0) {
508: obj.setNormals(0, newnormals);
509: }
510: if ((flags & GENERATE_TEXTURE_COORDS) != 0) {
511: obj.setTextureCoordinates(0, 0, newtcoords);
512: }
513: geometry = obj;
514: return obj;
515: }
516: **/
517:
518: void outVertex(Point3f[] dpts, Vector3f[] dnormals,
519: TexCoord2f[] dtcoords, Color3f[] dcolors, int dloc,
520: Point3f[] spts, Vector3f[] snormals, TexCoord2f[] stcoords,
521: Color3f[] scolors, int sloc) {
522: if (debug >= 1)
523: System.out.println("v " + spts[sloc].x + " " + spts[sloc].y
524: + " " + spts[sloc].z);
525:
526: // PSP: Do we really need new points here?
527:
528: dpts[dloc] = new Point3f(spts[sloc]);
529:
530: if ((flags & GENERATE_NORMALS) != 0) {
531: dnormals[dloc] = new Vector3f(snormals[sloc]);
532: }
533: if ((flags & GENERATE_TEXTURE_COORDS) != 0) {
534: if (debug >= 2)
535: System.out.println("final out tcoord");
536: dtcoords[dloc] = new TexCoord2f(stcoords[sloc]);
537: }
538: if ((flags & GENERATE_COLOR_3) != 0) {
539: dcolors[dloc] = new Color3f(scolors[sloc]);
540: }
541: }
542: }
|