1 /*
2  * $RCSfile: LwsLight.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:08 $
42  * $State: Exp $
43  */
44 
45 package com.sun.j3d.loaders.lw3d;
46 
47 
48 
49 import java.io.*;
50 import java.util.Vector;
51 import javax.media.j3d.*;
52 import javax.vecmath.*;
53 import java.util.Enumeration;
54 import com.sun.j3d.loaders.ParsingErrorException;
55 
56 /**
57  * This class creates a light object from the data in a Scene file. It
58  * instantiates an LwsMotion object to create any associated
59  * animations.
60  */
61 
62 class LwsLight extends TextfileParser implements LwsPrimitive {
63 
64     // data from the file
65     String           fileName;
66     String           objName;
67     LwsMotion        motion;
68     int              parent;
69     TransformGroup   objectTransform;
70     Vector           objectBehavior;
71     Color3f          color;
72     int              type;
73     Point3f          attenuation = new Point3f(1.0f, 0.0f, 0.0f);
74     float            spotConeAngle = (float)(Math.PI);
75     // Meta object, used for holding light and
76     LwLightObject    lwLight;
77     // light parameters
78     LwsEnvelopeLightIntensity intensityEnvelope = null;
79     Light            light = null;
80     final static int DIRECTIONAL = 0, POINT = 1, SPOT = 2;
81 
82     /**
83      * Constructor: parses stream and creates data structures for all
84      * light parameters currently handled by the loader
85      */
LwsLight(StreamTokenizer st, int totalFrames, float totalTime, int debugVals)86     LwsLight(StreamTokenizer st, int totalFrames, float totalTime,
87 	     int debugVals) throws ParsingErrorException {
88 
89 	debugPrinter.setValidOutput(debugVals);
90 
91 	debugOutput(TRACE, "LwsLight()");
92 	color = new Color3f(1f, 1f, 1f);
93 	lwLight = new LwLightObject(null, 0.0f, null);
94 
95 	parent = -1;
96 	debugOutputLn(LINE_TRACE, "about to get LightName");
97 	getAndCheckString(st, "LightName");
98 	debugOutputLn(LINE_TRACE, "about to get LightName value");
99 	objName = getName(st);
100 	debugOutputLn(LINE_TRACE, "got LightName");
101 	skip(st, "ShowLight", 2);
102 	debugOutputLn(LINE_TRACE, "got ShowLight");
103 	getAndCheckString(st, "LightMotion");
104 	debugOutputLn(LINE_TRACE, "got LightMotion");
105 	motion = new LwsMotion(st, totalFrames, totalTime);
106 	debugOutputLn(LINE_TRACE, "got motions");
107 
108 	// TODO: buggy way to stop processing the light.  Should actually
109 	// process required/optional fields in order and stop when there's
110 	// no more.  However, spec says "ShadowCasing" but the files say
111 	// "ShadowType".
112 
113 	while (!isCurrentToken(st, "ShowCamera") &&
114 	       !isCurrentToken(st, "AddLight")) {
115 	    // TODO:
116 	    // Things that we're not yet processing (and should):
117 	    // - EdgeAngle: for spotlights, this is the angle which
118 	    // contains the linear falloff toward the edge of the
119 	    // ConeAngle.  This doesn't directly map to J3d's
120 	    // "concentration" value, so it's left out for now.
121 
122 	    debugOutputLn(LINE_TRACE, "currentToken = " + st.sval);
123 
124 	    if (isCurrentToken(st, "ParentObject")) {
125 		parent = (int)getNumber(st);
126 	    }
127 	    else if (isCurrentToken(st, "LightColor")) {
128 		color.x = (float)getNumber(st)/255f;
129 		color.y = (float)getNumber(st)/255f;
130 		color.z = (float)getNumber(st)/255f;
131 		lwLight.setColor(color);
132 	    }
133 	    else if (isCurrentToken(st, "LgtIntensity")) {
134 		// TODO: must be able to handle envelopes here
135 		String className = getClass().getName();
136 		int classIndex = className.lastIndexOf('.');
137 		String packageName;
138 		if (classIndex < 0)
139 		    packageName = "";
140 		else
141 		    packageName = className.substring(0, classIndex) + ".";
142 		EnvelopeHandler env =
143 		    new EnvelopeHandler(st, totalFrames, totalTime,
144 			    packageName + "LwsEnvelopeLightIntensity");
145 		if (env.hasValue) {
146 		    float intensity = (float)env.theValue;
147 		    color.x *= intensity;
148 		    color.y *= intensity;
149 		    color.z *= intensity;
150 		    lwLight.setIntensity(intensity);
151 		}
152 		else {
153 		    intensityEnvelope =
154 			    (LwsEnvelopeLightIntensity)env.theEnvelope;
155 		}
156 	    }
157 	    else if (isCurrentToken(st, "LightType")) {
158 		type = (int)getNumber(st);
159 	    }
160 	    else if (isCurrentToken(st, "Falloff")) {
161 		float falloff = (float)getNumber(st);
162 		attenuation.y = 1.0f/(1.0f - falloff) - 1.0f;
163 	    }
164 	    else if (isCurrentToken(st, "ConeAngle")) {
165 		spotConeAngle = (float)getNumber(st) * (float)(Math.PI / 180.0);
166 	    }
167 	    try {
168 		st.nextToken();
169 	    }
170 	    catch (IOException e) {
171 		throw new ParsingErrorException(e.getMessage());
172 	    }
173 	}
174 	st.pushBack();   // push "ShowCamera" or "AddLight" back on stack
175     }
176 
getParent()177     int getParent() {
178 	return parent;
179     }
180 
181     /**
182      * Create Java3D objects from the data we got from the file
183      */
createJava3dObject(int loadBehaviors)184     void createJava3dObject(int loadBehaviors) {
185 	Matrix4d mat = new Matrix4d();
186 	mat.setIdentity();
187 	// Set the node's transform matrix according to the first frame
188 	// of the object's motion
189 	LwsFrame firstFrame = motion.getFirstFrame();
190 	firstFrame.setMatrix(mat);
191 	debugOutputLn(VALUES, "Light transform = " + mat);
192 	Transform3D t1 = new Transform3D();
193 	t1.set(mat);
194 	objectTransform = new TransformGroup(t1);
195 	objectTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
196 	Vector3f defaultDir = new Vector3f(0f, 0f, -1f);
197 	Point3f defaultPos = new Point3f(0f, 0f, 0f);
198 
199 	switch (type) {
200 	case DIRECTIONAL:
201 	    light = new DirectionalLight(color, defaultDir);
202 	    break;
203 	case POINT:
204 	    light = new PointLight(color, defaultPos, attenuation);
205 	    break;
206 	case SPOT:
207 	    // Note: spotConeAngle in lw3d is half that of Java3d...
208 	    light = new SpotLight(color, defaultPos, attenuation, defaultDir,
209 				  2 * spotConeAngle, 0.0f);
210 	    break;
211 	default:
212 	    // Shouldn't get here
213 	    break;
214 	}
215 
216 	light.setCapability(Light.ALLOW_COLOR_WRITE);
217 	if (light != null)  {
218 	  lwLight.setLight(light);
219 	  BoundingSphere bounds =
220 		    new BoundingSphere(new Point3d(0.0,0.0,0.0), 100000.0);
221 	  light.setInfluencingBounds(bounds);
222 	  objectTransform.addChild(light);
223 
224 	  // load behaviors if we have to
225 	  objectBehavior = new Vector();
226 	  if (loadBehaviors != 0) {
227 	    Behavior b;
228 	    b = null;
229 	    motion.createJava3dBehaviors(objectTransform);
230 	    b = motion.getBehaviors();
231 	    if (b != null)
232 	      objectBehavior.addElement(b);
233 
234 	    if (intensityEnvelope != null) {
235 	      b = null;
236 	      intensityEnvelope.createJava3dBehaviors(lwLight);
237 	      b = intensityEnvelope.getBehaviors();
238 	      if (b != null)
239 		objectBehavior.addElement(b);
240 	    }
241 	  }
242 	}
243     }
244 
getObjectNode()245     public TransformGroup getObjectNode()
246 	{
247 	    return objectTransform;
248 	}
249 
getLight()250     Light getLight() {
251 	return light;
252     }
253 
getObjectBehaviors()254     public Vector getObjectBehaviors()
255 	{
256 	    debugOutputLn(TRACE, "getObjectBehaviors()");
257 	    return objectBehavior;
258 	}
259 
260 
printVals()261     void printVals()
262 	{
263 	    debugOutputLn(VALUES, "  LIGHT vals: ");
264 	    debugOutputLn(VALUES, "   objName = " + objName);
265 	    motion.printVals();
266 	}
267 
268 
269 }
270