1 /*
2  * $RCSfile: J3dLwoParser.java,v $
3  *
4  * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistribution of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  *
13  * - Redistribution in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  *
18  * Neither the name of Sun Microsystems, Inc. or the names of
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * This software is provided "AS IS," without a warranty of any
23  * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
24  * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
26  * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
27  * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
28  * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
29  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
30  * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
31  * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
32  * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
33  * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGES.
35  *
36  * You acknowledge that this software is not designed, licensed or
37  * intended for use in the design, construction, operation or
38  * maintenance of any nuclear facility.
39  *
40  * $Revision: 1.4 $
41  * $Date: 2007/02/09 17:20:07 $
42  * $State: Exp $
43  */
44 
45 package com.sun.j3d.loaders.lw3d;
46 
47 import java.awt.Component;
48 import java.awt.Image;
49 import java.util.Enumeration;
50 import java.util.Vector;
51 import com.sun.j3d.utils.geometry.GeometryInfo;
52 import com.sun.j3d.utils.geometry.NormalGenerator;
53 import com.sun.j3d.utils.geometry.Stripifier;
54 import com.sun.j3d.utils.image.TextureLoader;
55 import com.sun.j3d.loaders.IncorrectFormatException;
56 import java.io.FileNotFoundException;
57 
58 import javax.media.j3d.*;
59 import javax.vecmath.*;
60 
61 import java.net.*;
62 
63 
64 /**
65  * This class is responsible for turning Lightwave geometry data into
66  * Java3D geometry. It is a subclass of LwoObject and calls that
67  * superclass when first instantiated to parse the binary file and turn it
68  * into intermediate data structures. J3dLwoParser then goes through
69  * those data structures and turns them into Java3D objects. For each
70  * ShapeHolder object created by the parent class, this class retrieves
71  * the geometry data and associated surface data, creates the
72  * appropriate Geometry object (usually IndexedTriangleFanArray,
73  * unless the object is points or lines), including calculating normals for
74  * the polygons and sets up the Appearance according to the surface
75  * parameters (including calculating texture coordinates if necessary).
76  */
77 
78 class J3dLwoParser extends LwoParser {
79 
80     float normalCoordsArray[];
81     int normalIndicesArray[];
82     Shape3D objectShape;
83     Color3f color, diffuseColor, specularColor, emissiveColor;
84     float shininess;
85     Vector objectShapeList = new Vector();
86 
87     /**
88      * Constructor: Calls LwoObject to parse file and create data structures
89      */
J3dLwoParser(String fileName, int debugVals)90     J3dLwoParser(String fileName,
91 		 int debugVals) throws FileNotFoundException {
92 		     super(fileName, debugVals);
93     }
94 
J3dLwoParser(URL url, int debugVals)95     J3dLwoParser(URL url, int debugVals)
96 	throws FileNotFoundException {
97 	    super(url, debugVals);
98     }
99 
getSurf(int length)100     void getSurf(int length) throws FileNotFoundException {
101 	super.getSurf(length);
102     }
103 
104 
105     /**
106      * Turns LwoObject's data structures (created from the binary geometry
107      * file) into Java3d objects
108      */
createJava3dGeometry()109     void createJava3dGeometry() throws IncorrectFormatException {
110 
111 	GeometryArray object;
112 	LwoTexture texture;
113 
114 	for (Enumeration e = shapeList.elements();
115 	     e.hasMoreElements() ;) {
116 	    int vertexFormat = javax.media.j3d.GeometryArray.COORDINATES;
117 	    ShapeHolder shape = (ShapeHolder)e.nextElement();
118 	    debugOutputLn(LINE_TRACE, "about to create Arrays for Shape");
119 	    debugOutputLn(VALUES, "shape = " + shape);
120 	    shape.createArrays(true);
121 	    int vertexCount = shape.coordsArray.length/3;
122 	    int indexCount = 0;
123 	    if (shape.facetIndices != null)
124 		indexCount = shape.facetIndices.length;
125 	    debugOutputLn(VALUES, "numSurf = " + shape.numSurf);
126 	    // Find the right surface.  Note: surfaces are indexed by
127 	    // name.  So take this surf number, look up the name of that
128 	    // surface in surfaceNameList, then take that name and
129 	    // find the matching LwoSurface
130 	    String surfName =
131 		(String)surfNameList.elementAt(shape.numSurf - 1);
132 	    LwoSurface surf = null;
133 	    for (int surfNum = 0;
134 		 surfNum < surfaceList.size();
135 		 ++surfNum) {
136 		LwoSurface tempSurf =
137 		    (LwoSurface)surfaceList.elementAt(surfNum);
138 		String tempSurfName = tempSurf.surfName;
139 		if (surfName.equals(tempSurfName)) {
140 		    surf = tempSurf;
141 		    break;
142 		}
143 	    }
144 	    if (surf == null) {
145 		throw new IncorrectFormatException(
146 		    "bad surf for surfnum/name = " + shape.numSurf + ", " +
147 		    surfName);
148 	    }
149 	    debugOutputLn(VALUES, "surf = " + surf);
150 
151 	    // Get the LwoTexture object (if any) for the surface
152 	    texture = surf.getTexture();
153 
154 	    Appearance appearance = new Appearance();
155 	    if (shape.facetSizes[0] == 1) {
156 		// This case happens if the objects are points
157 		// Note that points are colored, not lit
158 		object = new
159 		    javax.media.j3d.PointArray(vertexCount, vertexFormat);
160 		object.setCoordinates(0, shape.coordsArray);
161 		ColoringAttributes colorAtt =
162 		    new ColoringAttributes(surf.getColor(),
163 					   ColoringAttributes.FASTEST);
164 		PointAttributes pointStyle = new PointAttributes();
165 		pointStyle.setPointSize(1);
166 
167 		appearance.setColoringAttributes(colorAtt);
168 		appearance.setPointAttributes(pointStyle);
169 	    }
170 	    else if (shape.facetSizes[0] == 2) {
171 		// This case happens if the objects are lines
172 		// Note that lines are colored, not lit
173 		debugOutputLn(LINE_TRACE, "Creating IndexedLineArray");
174 		object = new javax.media.j3d.LineArray(vertexCount,
175 						       vertexFormat);
176 		object.setCoordinates(0, shape.coordsArray);
177 		ColoringAttributes colorAtt =
178 		    new ColoringAttributes(surf.getColor(),
179 					   ColoringAttributes.FASTEST);
180 		appearance.setColoringAttributes(colorAtt);
181 	    }
182 	    else {
183 		// This is the case for any polygonal objects
184 		debugOutputLn(LINE_TRACE, "Creating IndexedTriFanArray");
185 				// create triFanArray
186 		vertexFormat |= javax.media.j3d.GeometryArray.NORMALS;
187 
188 		debugOutputLn(LINE_TRACE, "about to process vertices/indices, facetIndices = " +
189 			      shape.facetIndices);
190 		if (shape.facetIndices != null) {
191 		    float[] textureCoords = null;
192 		    int[] textureIndices = null;
193 
194 		    debugOutputLn(LINE_TRACE, "setting vertexCount, normind = " + shape.normalIndices);
195 		    // If these are null we're going direct (non-indexed)
196 		    debugOutputLn(LINE_TRACE, "vtxcount, format, indcount = " +
197 				  vertexCount + ", " + vertexFormat +
198 				  ", " + indexCount);
199 		    if (texture != null) {
200 			// There's a texture here - need to create the appropriate arrays
201 			// and  calculate texture coordinates for the object
202 			vertexFormat |= GeometryArray.TEXTURE_COORDINATE_2;
203 			textureCoords = new float[vertexCount * 2];
204 			textureIndices = new int[shape.facetIndices.length];
205 			calculateTextureCoords(texture, shape.coordsArray,
206 					       shape.facetIndices,
207 					       textureCoords, textureIndices);
208 			debugOutputLn(LINE_TRACE, "textureCoords:");
209 			debugOutputLn(LINE_TRACE, "texture Coords, Indices.length = " + textureCoords.length + ", " + textureIndices.length);
210 		    }
211 		    debugOutputLn(LINE_TRACE, "about to create GeometryInfo");
212 
213 		    // Use the GeometryInfo utility to calculate smooth normals
214 		    GeometryInfo gi =
215 			new GeometryInfo(GeometryInfo.TRIANGLE_FAN_ARRAY);
216 		    gi.setCoordinates(shape.coordsArray);
217 		    gi.setCoordinateIndices(shape.facetIndices);
218 		    gi.setStripCounts(shape.facetSizes);
219 		    if (texture != null) {
220 			gi.setTextureCoordinateParams(1, 2);
221 			gi.setTextureCoordinates(0, textureCoords);
222 			gi.setTextureCoordinateIndices(0, textureIndices);
223 		    }
224 		    gi.recomputeIndices();
225 		    NormalGenerator ng =
226 			new NormalGenerator(surf.getCreaseAngle());
227 		    ng.generateNormals(gi);
228 		    Stripifier st = new Stripifier();
229 		    st.stripify(gi);
230 		    object = gi.getGeometryArray(true, true, false);
231 		    debugOutputLn(LINE_TRACE, "done.");
232 		}
233 		else {
234 		    // This case is called if LwoObject did not create facet
235 		    // indices.  This code is not currently used because facet
236 		    // indices are always created for polygonal objects
237 		    debugOutputLn(LINE_TRACE,
238 				  "about to create trifanarray with " +
239 				  "vertexCount, facetSizes.len = " +
240 				  vertexCount + ", " +
241 				  shape.facetSizes.length);
242 		    object = new
243 			javax.media.j3d.TriangleFanArray(vertexCount,
244 							 vertexFormat,
245 							 shape.facetSizes);
246 		    object.setCoordinates(0, shape.coordsArray);
247 		    object.setNormals(0, shape.normalCoords);
248 		    debugOutputLn(VALUES, "passed in normalCoords, length = " +
249 				  shape.normalCoords.length);
250 		}
251 		debugOutputLn(LINE_TRACE, "created fan array");
252 
253 		// Setup Appearance given the surface parameters
254 		Material material = new Material(surf.getColor(),
255 						 surf.getEmissiveColor(),
256 						 surf.getDiffuseColor(),
257 						 surf.getSpecularColor(),
258 						 surf.getShininess());
259 		material.setLightingEnable(true);
260 		appearance.setMaterial(material);
261 		if (surf.getTransparency() != 0f) {
262 		    TransparencyAttributes ta = new TransparencyAttributes();
263 		    ta.setTransparency(surf.getTransparency());
264 		    ta.setTransparencyMode(ta.BLENDED);
265 		    appearance.setTransparencyAttributes(ta);
266 		}
267 		if (texture != null) {
268 		    debugOutputLn(LINE_TRACE, "texture != null, enable texturing");
269 		    Texture tex = texture.getTexture();
270 		    tex.setEnable(true);
271 		    appearance.setTexture(tex);
272 		    TextureAttributes ta = new TextureAttributes();
273 		    if (texture.getType().equals("DTEX"))
274 			ta.setTextureMode(TextureAttributes.MODULATE);
275 		    else if (texture.getType().equals("CTEX"))
276 			ta.setTextureMode(TextureAttributes.DECAL);
277 		    appearance.setTextureAttributes(ta);
278 		}
279 		else {
280 		    debugOutputLn(LINE_TRACE, "texture == null, no texture to use");
281 		}
282 	    }
283 	    debugOutputLn(LINE_TRACE, "done creating object");
284 
285 	    // This does gc
286 	    shape.nullify();
287 
288 	    objectShape = new Shape3D(object);
289 
290 	    // Combine the appearance and geometry
291 	    objectShape.setAppearance(appearance);
292 	    objectShapeList.addElement(objectShape);
293 	}
294     }
295 
296     /**
297      * Calculate texture coordinates for the geometry given the texture
298      * map properties specified in the LwoTexture object
299      */
calculateTextureCoords(LwoTexture texture, float verts[], int indices[], float[] textureCoords, int[] textureIndices)300     void calculateTextureCoords(LwoTexture texture,
301 				float verts[], int indices[],
302 				float[] textureCoords, int[] textureIndices) {
303 
304       /*
305 	   the actual math in these coord calculations comes directly from
306 	   Newtek - they posted sample code to help compute tex coords based
307 	   on the type of mapping:
308 
309 	   Here are some simplified code fragments showing how LightWave
310 	   computes UV coordinates from X, Y, and Z.  If the resulting
311 	   UV coordinates are not in the range from 0 to 1, the
312 	   appropriate integer should be added to them to bring them into
313 	   that range (the fract function should have accomplished
314 	   this by subtracting the floor of each number from itself).
315 	   Then they can be multiplied by the width and height (in pixels)
316 	   of an image map to determine which pixel to look up.  The
317 	   texture size, center, and tiling parameters are taken right
318 	   off the texture control panel.
319 
320 
321 	   x -= xTextureCenter;
322 	   y -= yTextureCenter;
323 	   z -= zTextureCenter;
324 	   if (textureType == TT_PLANAR) {
325 	   s = (textureAxis == TA_X) ? z / zTextureSize + .5 :
326 	   x / xTextureSize + .5;
327 	   t = (textureAxis == TA_Y) ? -z / zTextureSize + .5 :
328 	   -y / yTextureSize + .5;
329 	   u = fract(s);
330 	   v = fract(t);
331 	   }
332 	   else if (type == TT_CYLINDRICAL) {
333 	   if (textureAxis == TA_X) {
334 	   xyztoh(z,x,-y,&lon);
335 	   t = -x / xTextureSize + .5;
336 	   }
337 	   else if (textureAxis == TA_Y) {
338 	   xyztoh(-x,y,z,&lon);
339 	   t = -y / yTextureSize + .5;
340 	   }
341 	   else {
342 	   xyztoh(-x,z,-y,&lon);
343 	   t = -z / zTextureSize + .5;
344 	   }
345 	   lon = 1.0 - lon / TWOPI;
346 	   if (widthTiling != 1.0)
347 	   lon = fract(lon) * widthTiling;
348 	   u = fract(lon);
349 	   v = fract(t);
350 	   }
351 	   else if (type == TT_SPHERICAL) {
352 	   if (textureAxis == TA_X)
353 	   xyztohp(z,x,-y,&lon,&lat);
354 	   else if (textureAxis == TA_Y)
355 	   xyztohp(-x,y,z,&lon,&lat);
356 	   else
357 	   xyztohp(-x,z,-y,&lon,&lat);
358 	   lon = 1.0 - lon / TWOPI;
359 	   lat = .5 - lat / PI;
360 	   if (widthTiling != 1.0)
361 	   lon = fract(lon) * widthTiling;
362 	   if (heightTiling != 1.0)
363 	   lat = fract(lat) * heightTiling;
364 	   u = fract(lon);
365 	   v = fract(lat);
366 	   }
367 
368 	   support functions:
369 
370 	   void xyztoh(float x,float y,float z,float *h)
371 	   {
372 	   if (x == 0.0 && z == 0.0)
373 	   *h = 0.0;
374 	   else {
375 	   if (z == 0.0)
376 	   *h = (x < 0.0) ? HALFPI : -HALFPI;
377 	   else if (z < 0.0)
378 	   *h = -atan(x / z) + PI;
379 	   else
380 	   *h = -atan(x / z);
381 	   }
382 	   }
383 
384 	   void xyztohp(float x,float y,float z,float *h,float *p)
385 	   {
386 	   if (x == 0.0 && z == 0.0) {
387 	   *h = 0.0;
388 	   if (y != 0.0)
389 	   *p = (y < 0.0) ? -HALFPI : HALFPI;
390 	   else
391 	   *p = 0.0;
392 	   }
393 	   else {
394 	   if (z == 0.0)
395 	   *h = (x < 0.0) ? HALFPI : -HALFPI;
396 	   else if (z < 0.0)
397 	   *h = -atan(x / z) + PI;
398 	   else
399 	   *h = -atan(x / z);
400 	   x = sqrt(x * x + z * z);
401 	   if (x == 0.0)
402 	   *p = (y < 0.0) ? -HALFPI : HALFPI;
403 	   else
404 	   *p = atan(y / x);
405 	   }
406 	   }
407       */
408 
409 	debugOutputLn(TRACE, "calculateTextureCoords()");
410 	// Compute texture coord stuff
411 	float sx = 0, sz = 0, ty = 0, tz = 0;
412 	double s, t;
413 	int textureAxis = texture.getTextureAxis();
414 	Vector3f textureSize = texture.getTextureSize();
415 	Vector3f textureCenter = texture.getTextureCenter();
416 
417 	String mappingType = texture.getMappingType();
418 	if (mappingType.startsWith("Cylindrical"))
419 	    calculateCylindricalTextureCoords(textureAxis, textureSize,
420 					      textureCenter, textureCoords,
421 					      textureIndices,
422 					      verts, indices);
423 	else if (mappingType.startsWith("Spherical"))
424 	    calculateSphericalTextureCoords(textureAxis,
425 					    textureCenter, textureCoords,
426 					    textureIndices,
427 					    verts, indices);
428 	else if (mappingType.startsWith("Planar"))
429 	    calculatePlanarTextureCoords(textureAxis, textureSize,
430 					 textureCenter, textureCoords,
431 					 textureIndices,
432 					 verts, indices);
433 
434     }
435 
436     /** See the comments in calculateTextureCoordinates*/
xyztoh(float x,float y,float z)437     double xyztoh(float x,float y,float z) {
438 	if (x == 0.0 && z == 0.0)
439 	    return 0.0;
440 	else {
441 	    if (z == 0.0)
442 		return (x < 0.0) ? Math.PI/2.0 : -Math.PI/2.0;
443 	    else if (z < 0.0)
444 		return -Math.atan(x / z) + Math.PI;
445 	    else
446 		return -Math.atan(x / z);
447 	}
448     }
449 
450     /** See the comments in calculateTextureCoordinates*/
xyztop(float x,float y,float z)451     double xyztop(float x,float y,float z) {
452 	double p;
453 
454 	if (x == 0.0 && z == 0.0) {
455 	    if (y != 0.0)
456 		p = (y < 0.0) ? -Math.PI/2 : Math.PI/2;
457 	    else
458 		p = 0.0;
459 	}
460 	else {
461 	    x = (float)Math.sqrt(x * x + z * z);
462 	    if (x == 0.0)
463 		p = (y < 0.0) ? -Math.PI/2 : Math.PI/2;
464 	    else
465 		p = Math.atan(y / x);
466 	}
467 	return p;
468     }
469 
470 
471     /** See the comments in calculateTextureCoordinates*/
calculateSphericalTextureCoords(int textureAxis, Vector3f textureCenter, float textureCoords[], int textureIndices[], float verts[], int indices[])472     void calculateSphericalTextureCoords(int textureAxis,
473 					 Vector3f textureCenter,
474 					 float textureCoords[],
475 					 int textureIndices[],
476 					 float verts[], int indices[]) {
477 	debugOutputLn(TRACE, "calculateSphericalTextureCoords");
478 	double s, t;
479 
480 
481 	for (int i = 0; i < indices.length; ++i) {
482 	    float x = verts[3*indices[i]] - textureCenter.x;
483 	    float y = verts[3*indices[i]+1] - textureCenter.y;
484 	    float z = -(verts[3*indices[i]+2] + textureCenter.z);
485 	    if (textureAxis == 1){ // X Axis
486 		s = xyztoh(z, x, -y);
487 		t = xyztop(z,x,-y);
488 	    }
489 	    else if (textureAxis == 2) { // Y Axis
490 		s = xyztoh(-x,y,z);
491 		t = xyztop(-x,y,z);
492 	    }
493 	    else {			// Z Axis
494 		s = xyztoh(-x,z,-y);
495 		t = xyztop(-x,z,-y);
496 	    }
497 	    s = 1.0 - s / (2*Math.PI);
498 	    t = -(.5 - t / Math.PI);
499 	    textureCoords[indices[i]*2] = (float)s;
500 	    textureCoords[indices[i]*2 + 1] = (float)t;
501 	    textureIndices[i] = indices[i];
502 	}
503     }
504 
505     /** See the comments in calculateTextureCoordinates*/
calculateCylindricalTextureCoords(int textureAxis, Vector3f textureSize, Vector3f textureCenter, float textureCoords[], int textureIndices[], float verts[], int indices[])506     void calculateCylindricalTextureCoords(int textureAxis,
507 					   Vector3f textureSize,
508 					   Vector3f textureCenter,
509 					   float textureCoords[],
510 					   int textureIndices[],
511 					   float verts[], int indices[]) {
512 	debugOutputLn(TRACE, "calculateCylindricalTextureCoords");
513 	debugOutputLn(VALUES, "axis, size, center, tc, ti, v, i = " +
514 		      textureAxis + ", " +
515 		      textureSize + ", " +
516 		      textureCenter + ", " +
517 		      textureCoords + ", " +
518 		      textureIndices + ", " +
519 		      verts + ", " +
520 		      indices);
521 	double s, t;
522 
523 	debugOutputLn(VALUES, "Cyl Texture Coords:");
524 	for (int i = 0; i < indices.length; ++i) {
525 	    float x = verts[3*indices[i]] - textureCenter.x;
526 	    float y = verts[3*indices[i]+1] - textureCenter.y;
527 	    float z = -(verts[3*indices[i]+2] + textureCenter.z);
528 	    // Negate z value because we invert geom z's to swap handedness
529 	    if (textureAxis == 1) { // X axis
530 		s = xyztoh(z,x,-y);
531 		t = x / textureSize.x + .5;
532 	    }
533 	    else if (textureAxis == 2) { // Y Axis
534 		s = xyztoh(-x,y,z);
535 		t = y / textureSize.y + .5;
536 	    }
537 	    else {
538 		s = xyztoh(-x,z,-y);
539 		t = z / textureSize.z + .5;
540 	    }
541 	    s = 1.0 - s / (2*Math.PI);
542 	    textureCoords[indices[i]*2] = (float)s;
543 	    textureCoords[indices[i]*2 + 1] = (float)t;
544 	    textureIndices[i] = indices[i];
545 	    debugOutputLn(VALUES, "x, y, z = " +
546 			  x + ", " + y + ", " + z + "    " +
547 			  "s, t = " + s + ", " + t);
548 	}
549     }
550 
551     /** See the comments in calculateTextureCoordinates*/
calculatePlanarTextureCoords(int textureAxis, Vector3f textureSize, Vector3f textureCenter, float textureCoords[], int textureIndices[], float verts[], int indices[])552     void calculatePlanarTextureCoords(int textureAxis, Vector3f textureSize,
553 				      Vector3f textureCenter,
554 				      float textureCoords[],
555 				      int textureIndices[],
556 				      float verts[], int indices[]) {
557 	debugOutputLn(TRACE, "calculatePlanarTextureCoords");
558 	debugOutputLn(VALUES, "size, center, axis = " +
559 		      textureSize + textureCenter + ", " + textureAxis);
560 	float sx = 0, sz = 0, ty = 0, tz = 0;
561 	double s, t;
562 
563 	if (textureAxis == 1) {		// X Axis
564 	    sz = -1.0f / textureSize.z;  // Negate because we negate z in geom
565 	    ty = 1.0f / textureSize.y;
566 	}
567 	else if (textureAxis == 2) {	// Y Axis
568 	    sx = 1.0f / textureSize.x;
569 	    tz = -1.0f / textureSize.z;  // Negate because we negate z in geom
570 	}
571 	else {				// Z Axis
572 	    sx = 1.0f / textureSize.x;
573 	    ty = 1.0f / textureSize.y;
574 	}
575 
576 	debugOutputLn(VALUES, "Planar Texture Coords:");
577 	for (int i = 0; i < indices.length; ++i) {
578 	    float x = verts[3*indices[i]] - textureCenter.x;
579 	    float y = verts[3*indices[i]+1] - textureCenter.y;
580 	    float z = verts[3*indices[i]+2] + textureCenter.z;
581 	    s = x*sx + z*sz + .5;
582 	    t = y*ty + z*tz + .5;
583 	    textureCoords[indices[i]*2] = (float)s;
584 	    textureCoords[indices[i]*2 + 1] = (float)t;
585 	    textureIndices[i] = indices[i];
586 	    debugOutputLn(VALUES, "x, y, z = " +
587 			  x + ", " + y + ", " + z + "    " +
588 			  "s, t = " + s + ", " + t);
589 	}
590     }
591 
592 
getJava3dShape()593     Shape3D getJava3dShape() {
594 	return objectShape;
595     }
596 
getJava3dShapeList()597     Vector getJava3dShapeList() {
598 	return objectShapeList;
599     }
600 
601 }
602