001: /*
002: * $RCSfile: Quadrics.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 05:25:49 $
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: class Quadrics extends Object {
055:
056: Quadrics() {
057: }
058:
059: // new disk code to remove transforms in the primitive code
060: GeomBuffer disk(double r, int xdiv, double y, boolean outside,
061: boolean texCoordYUp) {
062:
063: double theta, dtheta, sign, sinTheta, cosTheta;
064:
065: if (outside)
066: sign = 1.0;
067: else
068: sign = -1.0;
069:
070: dtheta = 2.0 * Math.PI / xdiv;
071:
072: GeomBuffer gbuf = new GeomBuffer(xdiv + 2);
073:
074: gbuf.begin(GeomBuffer.TRIANGLE_FAN);
075: gbuf.normal3d(0.0, 1.0 * sign, 0.0);
076: gbuf.texCoord2d(0.5, 0.5);
077: gbuf.vertex3d(0.0, y, 0.0);
078:
079: // create the disk by evaluating points along the unit circle.
080: // theta is the angle around the y-axis. Then we obtain
081: // (cos(theta), sin(theta)) = (x,z) sample points. The y value
082: // was passed in as a parameter.
083: // texture coordinates are obtain from the unit circle centered at
084: // (.5, .5) in s, t space. thus portions of the texture are not used.
085:
086: if (!outside) {
087: for (int i = 0; i <= xdiv; i++) {
088: theta = i * dtheta;
089: // add 90 degrees to theta so lines up wtih the body
090: sinTheta = Math.sin(theta - Math.PI / 2.0);
091: cosTheta = Math.cos(theta - Math.PI / 2.0);
092: gbuf.normal3d(0.0, 1.0 * sign, 0.0);
093: if (texCoordYUp) {
094: gbuf.texCoord2d(0.5 + cosTheta * 0.5,
095: 1.0 - (0.5 + sinTheta * 0.5));
096: } else {
097: gbuf.texCoord2d(0.5 + cosTheta * 0.5,
098: 0.5 + sinTheta * 0.5);
099: }
100: gbuf.vertex3d(r * cosTheta, y, r * sinTheta);
101: }
102: } else {
103: for (int i = xdiv; i >= 0; i--) {
104: theta = i * dtheta;
105: // add 90 degrees to theta so lines up with the body
106: sinTheta = Math.sin(theta - Math.PI / 2.0);
107: cosTheta = Math.cos(theta - Math.PI / 2.0);
108: gbuf.normal3d(0.0, 1.0 * sign, 0.0);
109: if (texCoordYUp) {
110: gbuf.texCoord2d(0.5 + cosTheta * 0.5,
111: 1.0 - (0.5 - sinTheta * 0.5));
112: } else {
113: gbuf.texCoord2d(0.5 + cosTheta * 0.5,
114: 0.5 - sinTheta * 0.5);
115: }
116: gbuf.vertex3d(cosTheta * r, y, sinTheta * r);
117: }
118: }
119:
120: gbuf.end();
121: return gbuf;
122: }
123:
124: // new cylinder to remove transforms in the cylinder code and to optimize
125: // by using triangle strip
126: GeomBuffer cylinder(double height, double radius, int xdiv,
127: int ydiv, boolean outside, boolean texCoordYUp) {
128:
129: double sign;
130:
131: if (outside)
132: sign = 1.0;
133: else
134: sign = -1.0;
135:
136: // compute the deltas
137: double dtheta = 2.0 * Math.PI / (double) xdiv;
138: double dy = height / (double) ydiv;
139: double du = 1.0 / (double) xdiv;
140: double dv = 1.0 / (double) ydiv;
141:
142: GeomBuffer gbuf = new GeomBuffer(ydiv * 2 * (xdiv + 1));
143:
144: double s = 0.0, t = 0.0;
145: double px, pz, qx, qz;
146: double py = -height / 2.0;
147: double qy;
148:
149: gbuf.begin(GeomBuffer.QUAD_STRIP);
150:
151: for (int i = 0; i < ydiv; i++) {
152: qy = py + dy;
153: if (outside) {
154: px = Math.cos(xdiv * dtheta - Math.PI / 2.0);
155: pz = Math.sin(xdiv * dtheta - Math.PI / 2.0);
156: qx = Math.cos((xdiv - 1) * dtheta - Math.PI / 2.0);
157: qz = Math.sin((xdiv - 1) * dtheta - Math.PI / 2.0);
158:
159: // vert 2
160: gbuf.normal3d(px * sign, 0.0, pz * sign);
161: if (texCoordYUp) {
162: gbuf.texCoord2d(s, 1.0 - (t + dv));
163: } else {
164: gbuf.texCoord2d(s, t + dv);
165: }
166: gbuf.vertex3d(px * radius, qy, pz * radius);
167:
168: // vert 1
169: gbuf.normal3d(px * sign, 0.0, pz * sign);
170: if (texCoordYUp) {
171: gbuf.texCoord2d(s, 1.0 - t);
172: } else {
173: gbuf.texCoord2d(s, t);
174: }
175: gbuf.vertex3d(px * radius, py, pz * radius);
176:
177: // vert 4
178: gbuf.normal3d(qx * sign, 0.0, qz * sign);
179: if (texCoordYUp) {
180: gbuf.texCoord2d(s + du, 1.0 - (t + dv));
181: } else {
182: gbuf.texCoord2d(s + du, t + dv);
183: }
184: gbuf.vertex3d(qx * radius, qy, qz * radius);
185:
186: // vert 3
187: gbuf.normal3d(qx * sign, 0.0, qz * sign);
188: if (texCoordYUp) {
189: gbuf.texCoord2d(s + du, 1.0 - t);
190: } else {
191: gbuf.texCoord2d(s + du, t);
192: }
193: gbuf.vertex3d(qx * radius, py, qz * radius);
194:
195: s += (du * 2.0);
196:
197: for (int j = xdiv - 2; j >= 0; j--) {
198: px = Math.cos(j * dtheta - Math.PI / 2.0);
199: pz = Math.sin(j * dtheta - Math.PI / 2.0);
200:
201: // vert 6
202: gbuf.normal3d(px * sign, 0.0, pz * sign);
203: if (texCoordYUp) {
204: gbuf.texCoord2d(s, 1.0 - (t + dv));
205: } else {
206: gbuf.texCoord2d(s, t + dv);
207: }
208: gbuf.vertex3d(px * radius, qy, pz * radius);
209:
210: // vert 5
211: gbuf.normal3d(px * sign, 0.0, pz * sign);
212: if (texCoordYUp) {
213: gbuf.texCoord2d(s, 1.0 - t);
214: } else {
215: gbuf.texCoord2d(s, t);
216: }
217: gbuf.vertex3d(px * radius, py, pz * radius);
218:
219: s += du;
220: }
221:
222: } else {
223: // c = 0;
224: px = Math.cos(-Math.PI / 2.0);
225: pz = Math.sin(-Math.PI / 2.0);
226: qx = Math.cos(dtheta - Math.PI / 2.0);
227: qz = Math.sin(dtheta - Math.PI / 2.0);
228:
229: gbuf.normal3d(px * sign, 0.0, pz * sign);
230: if (texCoordYUp) {
231: gbuf.texCoord2d(s, 1.0 - (t + dv));
232: } else {
233: gbuf.texCoord2d(s, t + dv);
234: }
235: gbuf.vertex3d(px * radius, qy, pz * radius);
236:
237: // vert 1
238: gbuf.normal3d(px * sign, 0.0, pz * sign);
239: if (texCoordYUp) {
240: gbuf.texCoord2d(s, 1.0 - t);
241: } else {
242: gbuf.texCoord2d(s, t);
243: }
244: gbuf.vertex3d(px * radius, py, pz * radius);
245:
246: gbuf.normal3d(qx * sign, 0.0, qz * sign);
247: if (texCoordYUp) {
248: gbuf.texCoord2d(s + du, 1.0 - (t + dv));
249: } else {
250: gbuf.texCoord2d(s + du, t + dv);
251: }
252: gbuf.vertex3d(qx * radius, qy, qz * radius);
253:
254: gbuf.normal3d(qx * sign, 0.0, qz * sign);
255: if (texCoordYUp) {
256: gbuf.texCoord2d(s + du, 1.0 - t);
257: } else {
258: gbuf.texCoord2d(s + du, t);
259: }
260: gbuf.vertex3d(qx * radius, py, qz * radius);
261:
262: s += (du * 2.0);
263:
264: for (int j = 2; j <= xdiv; j++) {
265: px = Math.cos(j * dtheta - Math.PI / 2.0);
266: pz = Math.sin(j * dtheta - Math.PI / 2.0);
267:
268: gbuf.normal3d(px * sign, 0.0, pz * sign);
269: if (texCoordYUp) {
270: gbuf.texCoord2d(s, 1.0 - (t + dv));
271: } else {
272: gbuf.texCoord2d(s, t + dv);
273: }
274: gbuf.vertex3d(px * radius, qy, pz * radius);
275:
276: gbuf.normal3d(px * sign, 0.0, pz * sign);
277: if (texCoordYUp) {
278: gbuf.texCoord2d(s, 1.0 - t);
279: } else {
280: gbuf.texCoord2d(s, t);
281: }
282: gbuf.vertex3d(px * radius, py, pz * radius);
283:
284: s += du;
285: }
286:
287: }
288: s = 0.0;
289: t += dv;
290: py += dy;
291: }
292:
293: gbuf.end();
294:
295: return gbuf;
296: }
297:
298: // new coneBody method to remove transform in the Cone primitive
299: // and to optimize by using triangle strip
300: GeomBuffer coneBody(double bottom, double top, double bottomR,
301: double topR, int xdiv, int ydiv, double dv,
302: boolean outside, boolean texCoordYUp) {
303:
304: double r, sign;
305:
306: if (outside)
307: sign = 1.0;
308: else
309: sign = -1.0;
310:
311: // compute the deltas
312: double dtheta = 2.0 * Math.PI / (double) xdiv;
313: double dr = (topR - bottomR) / (double) ydiv;
314: double height = top - bottom;
315: double dy = height / (double) ydiv;
316: double ynormal = (bottomR - topR) / height;
317: double du = 1.0 / (double) xdiv;
318: // double dv = 1.0/(double)(ydiv+1);
319:
320: GeomBuffer gbuf = new GeomBuffer(ydiv * 2 * (xdiv + 1));
321:
322: double s = 0.0, t = 0.0;
323: double px, pz, qx, qz;
324: double py = bottom;
325: double qy;
326: r = bottomR;
327:
328: gbuf.begin(GeomBuffer.QUAD_STRIP);
329:
330: for (int i = 0; i < ydiv; i++) {
331: qy = py + dy;
332: if (outside) {
333: px = Math.cos(xdiv * dtheta - Math.PI / 2.0);
334: pz = Math.sin(xdiv * dtheta - Math.PI / 2.0);
335: qx = Math.cos((xdiv - 1) * dtheta - Math.PI / 2.0);
336: qz = Math.sin((xdiv - 1) * dtheta - Math.PI / 2.0);
337:
338: // vert2
339: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
340: if (texCoordYUp) {
341: gbuf.texCoord2d(s, 1.0 - (t + dv));
342: } else {
343: gbuf.texCoord2d(s, t + dv);
344: }
345: gbuf.vertex3d(px * (r + dr), qy, pz * (r + dr));
346:
347: // vert1
348: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
349: if (texCoordYUp) {
350: gbuf.texCoord2d(s, 1.0 - t);
351: } else {
352: gbuf.texCoord2d(s, t);
353: }
354: gbuf.vertex3d(px * r, py, pz * r);
355:
356: // vert4
357: gbuf.normal3d(qx * sign, ynormal * sign, qz * sign);
358: if (texCoordYUp) {
359: gbuf.texCoord2d(s + du, 1.0 - (t + dv));
360: } else {
361: gbuf.texCoord2d(s + du, t + dv);
362: }
363: gbuf.vertex3d(qx * (r + dr), qy, qz * (r + dr));
364:
365: // vert3
366: gbuf.normal3d(qx * sign, ynormal * sign, qz * sign);
367: if (texCoordYUp) {
368: gbuf.texCoord2d(s + du, 1.0 - t);
369: } else {
370: gbuf.texCoord2d(s + du, t);
371: }
372: gbuf.vertex3d(qx * r, py, qz * r);
373:
374: s += (du * 2.0);
375:
376: for (int j = xdiv - 2; j >= 0; j--) {
377: px = Math.cos(j * dtheta - Math.PI / 2.0);
378: pz = Math.sin(j * dtheta - Math.PI / 2.0);
379:
380: // vert 6
381: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
382: if (texCoordYUp) {
383: gbuf.texCoord2d(s, 1.0 - (t + dv));
384: } else {
385: gbuf.texCoord2d(s, t + dv);
386: }
387: gbuf.vertex3d(px * (r + dr), qy, pz * (r + dr));
388:
389: // vert 5
390: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
391: if (texCoordYUp) {
392: gbuf.texCoord2d(s, 1.0 - t);
393: } else {
394: gbuf.texCoord2d(s, t);
395: }
396: gbuf.vertex3d(px * r, py, pz * r);
397:
398: s += du;
399: }
400: } else {
401: px = Math.cos(-Math.PI / 2.0);
402: pz = Math.sin(-Math.PI / 2.0);
403: qx = Math.cos(dtheta - Math.PI / 2.0);
404: qz = Math.sin(dtheta - Math.PI / 2.0);
405:
406: // vert1
407: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
408: if (texCoordYUp) {
409: gbuf.texCoord2d(s, 1.0 - (t + dv));
410: } else {
411: gbuf.texCoord2d(s, t + dv);
412: }
413: gbuf.vertex3d(px * (r + dr), qy, pz * (r + dr));
414:
415: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
416: if (texCoordYUp) {
417: gbuf.texCoord2d(s, 1.0 - t);
418: } else {
419: gbuf.texCoord2d(s, t);
420: }
421: gbuf.vertex3d(px * r, py, pz * r);
422:
423: gbuf.normal3d(qx * sign, ynormal * sign, qz * sign);
424: if (texCoordYUp) {
425: gbuf.texCoord2d(s + du, 1.0 - (t + dv));
426: } else {
427: gbuf.texCoord2d(s + du, t + dv);
428: }
429: gbuf.vertex3d(qx * (r + dr), qy, qz * (r + dr));
430:
431: gbuf.normal3d(qx * sign, ynormal * sign, qz * sign);
432: if (texCoordYUp) {
433: gbuf.texCoord2d(s + du, 1.0 - t);
434: } else {
435: gbuf.texCoord2d(s + du, t);
436: }
437: gbuf.vertex3d(qx * r, py, qz * r);
438:
439: s += (du * 2.0);
440:
441: for (int j = 2; j <= xdiv; j++) {
442: px = Math.cos(j * dtheta - Math.PI / 2.0);
443: pz = Math.sin(j * dtheta - Math.PI / 2.0);
444:
445: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
446: if (texCoordYUp) {
447: gbuf.texCoord2d(s, 1.0 - (t + dv));
448: } else {
449: gbuf.texCoord2d(s, t + dv);
450: }
451: gbuf.vertex3d(px * (r + dr), qy, pz * (r + dr));
452:
453: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
454: if (texCoordYUp) {
455: gbuf.texCoord2d(s, 1.0 - t);
456: } else {
457: gbuf.texCoord2d(s, t);
458: }
459: gbuf.vertex3d(px * r, py, pz * r);
460:
461: s += du;
462: }
463: }
464: s = 0.0;
465: t += dv;
466: py += dy;
467: r += dr;
468: }
469: gbuf.end();
470:
471: return gbuf;
472: }
473:
474: // new coneTop method to remove transforms in the cone code
475: GeomBuffer coneTop(double bottom, double radius, double height,
476: int xdiv, double t, boolean outside, boolean texCoordYUp) {
477:
478: double sign;
479:
480: if (outside)
481: sign = 1.0;
482: else
483: sign = -1.0;
484:
485: // compute the deltas
486: double dtheta = 2.0 * Math.PI / (double) xdiv;
487: double ynormal = radius / height;
488: double du = 1.0 / (double) xdiv;
489: double top = bottom + height;
490:
491: // initialize the geometry buffer
492: GeomBuffer gbuf = new GeomBuffer(xdiv + 2);
493: gbuf.begin(GeomBuffer.TRIANGLE_FAN);
494:
495: // add the tip, which is the center of the fan
496: gbuf.normal3d(0.0, ynormal * sign, 0.0);
497: if (texCoordYUp) {
498: gbuf.texCoord2d(.5, 0.0);
499: } else {
500: gbuf.texCoord2d(.5, 1.0);
501: }
502: gbuf.vertex3d(0.0, top, 0.0);
503:
504: // go around the circle and add the rest of the fan
505: double s = 0.0;
506: double px, pz;
507: if (outside) {
508: for (int i = xdiv; i >= 0; i--) {
509: px = Math.cos(i * dtheta - Math.PI / 2.0);
510: pz = Math.sin(i * dtheta - Math.PI / 2.0);
511: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
512: if (texCoordYUp) {
513: gbuf.texCoord2d(s, 1.0 - t);
514: } else {
515: gbuf.texCoord2d(s, t);
516: }
517: gbuf.vertex3d(px * radius, bottom, pz * radius);
518:
519: s += du;
520: }
521: } else {
522: for (int i = 0; i <= xdiv; i++) {
523: px = Math.cos(i * dtheta - Math.PI / 2.0);
524: pz = Math.sin(i * dtheta - Math.PI / 2.0);
525: gbuf.normal3d(px * sign, ynormal * sign, pz * sign);
526: if (texCoordYUp) {
527: gbuf.texCoord2d(s, 1.0 - t);
528: } else {
529: gbuf.texCoord2d(s, t);
530: }
531: gbuf.vertex3d(px * radius, bottom, pz * radius);
532: s += du;
533: }
534: }
535: gbuf.end();
536: return gbuf;
537: }
538: }
|