1 /*
2  * $RCSfile: TextureUnitState.java,v $
3  *
4  * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6  *
7  * This code is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 only, as
9  * published by the Free Software Foundation.  Sun designates this
10  * particular file as subject to the "Classpath" exception as provided
11  * by Sun in the LICENSE file that accompanied this code.
12  *
13  * This code is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16  * version 2 for more details (a copy is included in the LICENSE file that
17  * accompanied this code).
18  *
19  * You should have received a copy of the GNU General Public License version
20  * 2 along with this work; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
24  * CA 95054 USA or visit www.sun.com if you need additional information or
25  * have any questions.
26  *
27  * $Revision: 1.7 $
28  * $Date: 2008/02/28 20:17:32 $
29  * $State: Exp $
30  */
31 
32 package javax.media.j3d;
33 
34 import java.util.Hashtable;
35 
36 /**
37  * The TextureUnitState object defines all texture mapping state for a
38  * single texture unit.  An appearance object contains an array of
39  * texture unit state objects to define the state for multiple texture
40  * mapping units.  The texture unit state consists of the
41  * following:
42  *
43  * <p>
44  * <ul>
45  * <li>Texture - defines the texture image and filtering
46  * parameters used when texture mapping is enabled. These attributes
47  * are defined in a Texture object.</li><p>
48  *
49  * <li>Texture attributes - defines the attributes that apply to
50  * texture mapping, such as the texture mode, texture transform,
51  * blend color, and perspective correction mode. These attributes
52  * are defined in a TextureAttributes object.</li><p>
53  *
54  * <li>Texture coordinate generation - defines the attributes
55  * that apply to texture coordinate generation, such as whether
56  * texture coordinate generation is enabled, coordinate format
57  * (2D or 3D coordinates), coordinate generation mode (object
58  * linear, eye linear, or spherical reflection mapping), and the
59  * R, S, and T coordinate plane equations. These attributes
60  * are defined in a TexCoordGeneration object.</li><p>
61  * </ul>
62  *
63  * @see Appearance
64  * @see Texture
65  * @see TextureAttributes
66  * @see TexCoordGeneration
67  *
68  * @since Java 3D 1.2
69  */
70 public class TextureUnitState extends NodeComponent {
71 
72     /**
73      * Specifies that this TextureUnitState object allows reading its
74      * texture, texture attribute, or texture coordinate generation
75      * component information.
76      */
77     public static final int ALLOW_STATE_READ =
78 	CapabilityBits.TEXTURE_UNIT_STATE_ALLOW_STATE_READ;
79 
80     /**
81      * Specifies that this TextureUnitState object allows writing its
82      * texture, texture attribute, or texture coordinate generation
83      * component information.
84      */
85     public static final int ALLOW_STATE_WRITE =
86 	CapabilityBits.TEXTURE_UNIT_STATE_ALLOW_STATE_WRITE;
87 
88    // Array for setting default read capabilities
89     private static final int[] readCapabilities = {
90         ALLOW_STATE_READ
91     };
92 
93     /**
94      * Constructs a TextureUnitState component object using defaults for all
95      * state variables. All component object references are initialized
96      * to null.
97      */
TextureUnitState()98     public TextureUnitState() {
99 	// Just use default values
100         // set default read capabilities
101         setDefaultReadCapabilities(readCapabilities);
102     }
103 
104     /**
105      * Constructs a TextureUnitState component object using the specified
106      * component objects.
107      *
108      * @param texture object that specifies the desired texture
109      * map and texture parameters
110      * @param textureAttributes object that specifies the desired
111      * texture attributes
112      * @param texCoordGeneration object that specifies the texture coordinate
113      * generation parameters
114      */
TextureUnitState(Texture texture, TextureAttributes textureAttributes, TexCoordGeneration texCoordGeneration)115     public TextureUnitState(Texture texture,
116 			     TextureAttributes textureAttributes,
117 			     TexCoordGeneration texCoordGeneration) {
118         // set default read capabilities
119         setDefaultReadCapabilities(readCapabilities);
120 
121 	((TextureUnitStateRetained)this.retained).initTexture(texture);
122 	((TextureUnitStateRetained)this.retained).initTextureAttributes(
123 							textureAttributes);
124 	((TextureUnitStateRetained)this.retained).initTexCoordGeneration(
125 							texCoordGeneration);
126     }
127 
128     /**
129      * Creates the retained mode TextureUnitStateRetained object that this
130      * TextureUnitState component object will point to.
131      */
createRetained()132     void createRetained() {
133 	this.retained = new TextureUnitStateRetained();
134 	this.retained.setSource(this);
135     }
136 
137     /**
138      * Sets the texture, texture attributes, and texture coordinate
139      * generation components in this TextureUnitState object to the
140      * specified component objects.
141      *
142      * @param texture object that specifies the desired texture
143      * map and texture parameters
144      * @param textureAttributes object that specifies the desired
145      * texture attributes
146      * @param texCoordGeneration object that specifies the texture coordinate
147      * generation parameters
148      *
149      * @exception IllegalSharingException if this TextureUnitState is live and
150      * the specified texture refers to an ImageComponent2D that is being used
151      * by a Canvas3D as an off-screen buffer.
152      *
153      * @exception IllegalSharingException if this TextureUnitState is
154      * being used by an immediate mode context and
155      * the specified texture refers to an ImageComponent2D that is being used
156      * by a Canvas3D as an off-screen buffer.
157      */
set(Texture texture, TextureAttributes textureAttributes, TexCoordGeneration texCoordGeneration)158     public void set(Texture texture,
159 		    TextureAttributes textureAttributes,
160 		    TexCoordGeneration texCoordGeneration) {
161 
162 	if (isLiveOrCompiled())
163 	    if (!this.getCapability(ALLOW_STATE_WRITE))
164 		throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState0"));
165 
166         // Do illegal sharing check
167         if(texture != null) {
168             TextureRetained texRetained = (TextureRetained)texture.retained;
169             ImageComponent[] images = texRetained.getImages();
170             if(images != null) {
171                 for(int i=0; i<images.length; i++) {
172                     validateImageIllegalSharing(images[i]);
173                 }
174             }
175         }
176 
177 	((TextureUnitStateRetained)this.retained).setTextureUnitState(
178 				texture, textureAttributes, texCoordGeneration);
179     }
180 
181     /**
182      * Sets the texture object to the specified object.
183      * Setting it to null disables texture mapping for the
184      * texture unit corresponding to this TextureUnitState object.
185      *
186      * @param texture object that specifies the desired texture
187      * map and texture parameters
188      *
189      * @exception CapabilityNotSetException if appropriate capability is
190      * not set and this object is part of live or compiled scene graph
191      *
192      * @exception IllegalSharingException if this TextureUnitState is live and
193      * the specified texture refers to an ImageComponent2D that is being used
194      * by a Canvas3D as an off-screen buffer.
195      *
196      * @exception IllegalSharingException if this TextureUnitState is
197      * being used by an immediate mode context and
198      * the specified texture refers to an ImageComponent2D that is being used
199      * by a Canvas3D as an off-screen buffer.
200      */
setTexture(Texture texture)201     public void setTexture(Texture texture) {
202 	if (isLiveOrCompiled())
203 	    if (!this.getCapability(ALLOW_STATE_WRITE))
204 		throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState0"));
205 
206         // Do illegal sharing check
207         if(texture != null) {
208             TextureRetained texRetained = (TextureRetained)texture.retained;
209             ImageComponent[] images = texRetained.getImages();
210             if(images != null) {
211                 for(int i=0; i<images.length; i++) {
212                     validateImageIllegalSharing(images[i]);
213                 }
214             }
215         }
216 
217 	((TextureUnitStateRetained)this.retained).setTexture(texture);
218     }
219 
220     /**
221      * Retrieves the current texture object.
222      * @return the texture object
223      * @exception CapabilityNotSetException if appropriate capability is
224      * not set and this object is part of live or compiled scene graph
225      */
getTexture()226     public Texture getTexture() {
227 	if (isLiveOrCompiled())
228 	    if (!this.getCapability(ALLOW_STATE_READ))
229 		throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState1"));
230 
231 	return ((TextureUnitStateRetained)this.retained).getTexture();
232     }
233 
234     /**
235      * Sets the textureAttributes object to the specified object.
236      * Setting it to null will result in default attribute usage for the.
237      * texture unit corresponding to this TextureUnitState object.
238      * @param textureAttributes object that specifies the desired
239      * texture attributes
240      * @exception CapabilityNotSetException if appropriate capability is
241      * not set and this object is part of live or compiled scene graph
242      */
setTextureAttributes(TextureAttributes textureAttributes)243     public void setTextureAttributes(TextureAttributes textureAttributes) {
244 	if (isLiveOrCompiled())
245 	    if (!this.getCapability(ALLOW_STATE_WRITE))
246 		throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState2"));
247 
248 	((TextureUnitStateRetained)this.retained).setTextureAttributes(textureAttributes);
249     }
250 
251     /**
252      * Retrieves the current textureAttributes object.
253      * @return the textureAttributes object
254      * @exception CapabilityNotSetException if appropriate capability is
255      * not set and this object is part of live or compiled scene graph
256      */
getTextureAttributes()257     public TextureAttributes getTextureAttributes() {
258 	if (isLiveOrCompiled())
259 	    if (!this.getCapability(ALLOW_STATE_READ))
260 		throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState3"));
261 
262 	return ((TextureUnitStateRetained)this.retained).getTextureAttributes();
263     }
264 
265     /**
266      * Sets the texCoordGeneration object to the specified object.
267      * Setting it to null disables texture coordinate generation for the
268      * texture unit corresponding to this TextureUnitState object.
269      * @param texCoordGeneration object that specifies the texture coordinate
270      * generation parameters
271      * @exception CapabilityNotSetException if appropriate capability is
272      * not set and this object is part of live or compiled scene graph
273      */
setTexCoordGeneration(TexCoordGeneration texCoordGeneration)274     public void setTexCoordGeneration(TexCoordGeneration texCoordGeneration) {
275 	if (isLiveOrCompiled())
276 	    if (!this.getCapability(ALLOW_STATE_WRITE))
277 		throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState4"));
278 
279 	((TextureUnitStateRetained)this.retained).setTexCoordGeneration(texCoordGeneration);
280     }
281 
282     /**
283      * Retrieves the current texCoordGeneration object.
284      * @return the texCoordGeneration object
285      * @exception CapabilityNotSetException if appropriate capability is
286      * not set and this object is part of live or compiled scene graph
287      */
getTexCoordGeneration()288     public TexCoordGeneration getTexCoordGeneration() {
289 	if (isLiveOrCompiled())
290 	    if (!this.getCapability(ALLOW_STATE_READ))
291 		throw new CapabilityNotSetException(J3dI18N.getString("TextureUnitState5"));
292 
293 	return ((TextureUnitStateRetained)this.retained).getTexCoordGeneration();
294     }
295 
296 
297     /**
298      * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate)
299      */
cloneNodeComponent()300     public NodeComponent cloneNodeComponent() {
301         TextureUnitState ts = new TextureUnitState();
302         ts.duplicateNodeComponent(this);
303         return ts;
304     }
305 
306     /**
307      * NOTE: Applications should <i>not</i> call this method directly.
308      * It should only be called by the cloneNode method.
309      *
310      * @deprecated replaced with duplicateNodeComponent(
311      *  NodeComponent originalNodeComponent, boolean forceDuplicate)
312      */
duplicateNodeComponent(NodeComponent originalNodeComponent)313     public void duplicateNodeComponent(NodeComponent originalNodeComponent) {
314 	checkDuplicateNodeComponent(originalNodeComponent);
315     }
316 
317     /**
318      * Copies all TextureUnitState information from
319      * <code>originalNodeComponent</code> into
320      * the current node.  This method is called from the
321      * <code>cloneNode</code> method which is, in turn, called by the
322      * <code>cloneTree</code> method.<P>
323      *
324      * @param originalNodeComponent the original node to duplicate.
325      * @param forceDuplicate when set to <code>true</code>, causes the
326      *  <code>duplicateOnCloneTree</code> flag to be ignored.  When
327      *  <code>false</code>, the value of each node's
328      *  <code>duplicateOnCloneTree</code> variable determines whether
329      *  NodeComponent data is duplicated or copied.
330      *
331      * @exception RestrictedAccessException if this object is part of a live
332      *  or compiled scenegraph.
333      *
334      * @see Node#cloneTree
335      * @see NodeComponent#setDuplicateOnCloneTree
336      */
duplicateAttributes(NodeComponent originalNodeComponent, boolean forceDuplicate)337     void duplicateAttributes(NodeComponent originalNodeComponent,
338 			     boolean forceDuplicate) {
339 	super.duplicateAttributes(originalNodeComponent, forceDuplicate);
340 
341 	Hashtable hashtable = originalNodeComponent.nodeHashtable;
342 
343 	TextureUnitStateRetained app = (TextureUnitStateRetained) originalNodeComponent.retained;
344 
345 	TextureUnitStateRetained rt = (TextureUnitStateRetained) retained;
346 
347 	rt.setTexture((Texture) getNodeComponent(app.getTexture(),
348 						 forceDuplicate,
349 						 hashtable));
350 
351 	rt.setTextureAttributes((TextureAttributes) getNodeComponent(
352 						app.getTextureAttributes(),
353 						forceDuplicate,
354 						hashtable));
355 
356 	rt.setTexCoordGeneration((TexCoordGeneration) getNodeComponent(
357 						app.getTexCoordGeneration(),
358 						forceDuplicate,
359 						hashtable));
360     }
361 
362     /**
363      *  This function is called from getNodeComponent() to see if any of
364      *  the sub-NodeComponents  duplicateOnCloneTree flag is true.
365      *  If it is the case, current NodeComponent needs to
366      *  duplicate also even though current duplicateOnCloneTree flag is false.
367      *  This should be overwrite by NodeComponent which contains sub-NodeComponent.
368      */
duplicateChild()369     boolean duplicateChild() {
370 	if (getDuplicateOnCloneTree())
371 	    return true;
372 
373 	TextureUnitStateRetained rt = (TextureUnitStateRetained) retained;
374 
375 	NodeComponent nc = rt.getTexture();
376 	if ((nc != null) && nc.duplicateChild())
377 	    return true;
378 
379 	nc = rt.getTextureAttributes();
380 	if ((nc != null) && nc.getDuplicateOnCloneTree())
381 	    return true;
382 
383 	nc = rt.getTexCoordGeneration();
384 	if ((nc != null) && nc.getDuplicateOnCloneTree())
385 	    return true;
386 
387 	return false;
388     }
389 }
390