001: /*
002: * $RCSfile: SensorBeamEcho.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.4 $
041: * $Date: 2007/02/09 17:20:14 $
042: * $State: Exp $
043: */
044:
045: package com.sun.j3d.utils.behaviors.sensor;
046:
047: import javax.media.j3d.Shape3D;
048: import javax.media.j3d.Material;
049: import javax.media.j3d.Appearance;
050: import javax.media.j3d.Transform3D;
051: import javax.media.j3d.GeometryArray;
052: import javax.media.j3d.TriangleStripArray;
053: import javax.media.j3d.TransparencyAttributes;
054: import javax.vecmath.AxisAngle4f;
055: import javax.vecmath.Point3d;
056: import javax.vecmath.Point3f;
057: import javax.vecmath.Vector3f;
058:
059: /**
060: * A Shape3D representing a beam pointing from the origin of a
061: * sensor's local coordinate system to its hotspot.
062: *
063: * @since Java 3D 1.3
064: */
065: public class SensorBeamEcho extends Shape3D {
066: /**
067: * Creates a SensorBeamEcho. Read and write capabilities are granted
068: * for the Appearance, Material, TransparencyAttributes, and
069: * TransparencyAttributes mode and value.
070: *
071: * @param hotspot location of the sensor's hotspot in the sensor's
072: * local coordinate system; this must not be (0, 0, 0)
073: * @param baseWidth width of the beam in meters
074: * @param enableLighting boolean indicating whether normals should be
075: * generated and lighting enabled
076: * @exception IllegalArgumentException if hotspot is (0, 0, 0)
077: */
078: public SensorBeamEcho(Point3d hotspot, double baseWidth,
079: boolean enableLighting) {
080: super ();
081:
082: if (hotspot.distance(new Point3d()) == 0.0)
083: throw new IllegalArgumentException(
084: "\nBeam echo can't have hotspot at origin");
085:
086: Vector3f axis = new Vector3f((float) hotspot.x,
087: (float) hotspot.y, (float) hotspot.z);
088:
089: Vector3f axis1 = new Vector3f();
090: axis1.normalize(axis);
091:
092: // Choose an arbitrary vector normal to the beam axis.
093: Vector3f normal = new Vector3f(0.0f, 1.0f, 0.0f);
094: normal.cross(axis1, normal);
095: if (normal.lengthSquared() < 0.5f) {
096: normal.set(0.0f, 0.0f, 1.0f);
097: normal.cross(axis1, normal);
098: }
099: normal.normalize();
100:
101: // Create cap vertices and normals.
102: int divisions = 18;
103: Point3f[] cap0 = new Point3f[divisions];
104: Point3f[] cap1 = new Point3f[divisions];
105: Vector3f[] capNormals = new Vector3f[divisions];
106: Vector3f cap0Normal = new Vector3f(axis1);
107: Vector3f cap1Normal = new Vector3f(axis1);
108: cap0Normal.negate();
109:
110: AxisAngle4f aa4f = new AxisAngle4f(axis1, -(float) Math.PI
111: / ((float) divisions / 2.0f));
112: Transform3D t3d = new Transform3D();
113: t3d.set(aa4f);
114:
115: float halfWidth = (float) baseWidth / 2.0f;
116: for (int i = 0; i < divisions; i++) {
117: capNormals[i] = new Vector3f(normal);
118: cap0[i] = new Point3f(normal);
119: cap0[i].scale(halfWidth);
120: cap1[i] = new Point3f(cap0[i]);
121: cap1[i].add(axis);
122: t3d.transform(normal);
123: }
124:
125: // The beam cylinder is created with 3 triangle strips. The first
126: // strip contains the side facets (2 + 2*divisions vertices), and
127: // the other two strips are the caps (divisions vertices each).
128: int vertexCount = 2 + (4 * divisions);
129: Point3f[] vertices = new Point3f[vertexCount];
130: Vector3f[] normals = new Vector3f[vertexCount];
131:
132: // Side facets.
133: for (int i = 0; i < divisions; i++) {
134: vertices[i * 2] = cap0[i];
135: vertices[(i * 2) + 1] = cap1[i];
136:
137: normals[i * 2] = capNormals[i];
138: normals[(i * 2) + 1] = capNormals[i];
139: }
140:
141: vertices[divisions * 2] = cap0[0];
142: vertices[(divisions * 2) + 1] = cap1[0];
143:
144: normals[divisions * 2] = capNormals[0];
145: normals[(divisions * 2) + 1] = capNormals[0];
146:
147: // Strips for caps created by criss-crossing the interior.
148: int v = (divisions + 1) * 2;
149: vertices[v] = cap0[0];
150: normals[v++] = cap0Normal;
151:
152: int j = 1;
153: int k = divisions - 1;
154: while (j <= k) {
155: vertices[v] = cap0[j++];
156: normals[v++] = cap0Normal;
157: if (j > k)
158: break;
159: vertices[v] = cap0[k--];
160: normals[v++] = cap0Normal;
161: }
162:
163: vertices[v] = cap1[0];
164: normals[v++] = cap1Normal;
165:
166: j = 1;
167: k = divisions - 1;
168: while (j <= k) {
169: vertices[v] = cap1[k--];
170: normals[v++] = cap1Normal;
171: if (j > k)
172: break;
173: vertices[v] = cap1[j++];
174: normals[v++] = cap1Normal;
175: }
176:
177: // Create the TriangleStripArray.
178: int vertexFormat;
179: Material m = new Material();
180: m.setCapability(Material.ALLOW_COMPONENT_READ);
181: m.setCapability(Material.ALLOW_COMPONENT_WRITE);
182:
183: if (enableLighting) {
184: vertexFormat = GeometryArray.COORDINATES
185: | GeometryArray.NORMALS;
186: m.setLightingEnable(true);
187: } else {
188: vertexFormat = GeometryArray.COORDINATES;
189: m.setLightingEnable(false);
190: }
191:
192: int[] stripCounts = new int[3];
193: stripCounts[0] = 2 + (2 * divisions);
194: stripCounts[1] = divisions;
195: stripCounts[2] = divisions;
196:
197: TriangleStripArray tsa = new TriangleStripArray(vertexCount,
198: vertexFormat, stripCounts);
199:
200: tsa.setCoordinates(0, vertices);
201: if (enableLighting)
202: tsa.setNormals(0, normals);
203:
204: Appearance a = new Appearance();
205: a.setMaterial(m);
206: a.setCapability(Appearance.ALLOW_MATERIAL_READ);
207: a.setCapability(Appearance.ALLOW_MATERIAL_WRITE);
208:
209: TransparencyAttributes ta = new TransparencyAttributes();
210: ta.setCapability(TransparencyAttributes.ALLOW_MODE_READ);
211: ta.setCapability(TransparencyAttributes.ALLOW_MODE_WRITE);
212: ta.setCapability(TransparencyAttributes.ALLOW_VALUE_READ);
213: ta.setCapability(TransparencyAttributes.ALLOW_VALUE_WRITE);
214: ta
215: .setCapability(TransparencyAttributes.ALLOW_BLEND_FUNCTION_READ);
216: ta
217: .setCapability(TransparencyAttributes.ALLOW_BLEND_FUNCTION_WRITE);
218:
219: a.setTransparencyAttributes(ta);
220: a.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ);
221: a.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE);
222:
223: setGeometry(tsa);
224: setAppearance(a);
225:
226: setCapability(ALLOW_APPEARANCE_READ);
227: setCapability(ALLOW_APPEARANCE_WRITE);
228: }
229: }
|