OSDN Git Service

Set optimal mime types and executable settings.
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / image / Texture.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 package com.jme.image;
34
35 import java.io.IOException;
36
37 import com.jme.math.FastMath;
38 import com.jme.math.Matrix4f;
39 import com.jme.math.Quaternion;
40 import com.jme.math.Vector3f;
41 import com.jme.renderer.ColorRGBA;
42 import com.jme.util.TextureKey;
43 import com.jme.util.TextureManager;
44 import com.jme.util.export.InputCapsule;
45 import com.jme.util.export.JMEExporter;
46 import com.jme.util.export.JMEImporter;
47 import com.jme.util.export.OutputCapsule;
48 import com.jme.util.export.Savable;
49
50 /**
51  * <code>Texture</code> defines a texture object to be used to display an
52  * image on a piece of geometry. The image to be displayed is defined by the
53  * <code>Image</code> class. All attributes required for texture mapping are
54  * contained within this class. This includes mipmapping if desired,
55  * magnificationFilter options, apply options and correction options. Default
56  * values are as follows: minificationFilter - NearestNeighborNoMipMaps,
57  * magnificationFilter - NearestNeighbor, wrap - EdgeClamp on S,T and R, apply -
58  * Modulate, enivoronment - None.
59  * 
60  * @see com.jme.image.Image
61  * @author Mark Powell
62  * @author Joshua Slack
63  * @version $Id: Texture.java,v 1.44 2007/10/19 13:21:41 nca Exp $
64  */
65 public abstract class Texture implements Savable {
66     private static final long serialVersionUID = -3642148179543729674L;
67
68     public static boolean DEFAULT_STORE_TEXTURE = false;
69
70     public enum Type {
71         /**
72          * One dimensional texture. (basically a line)
73          */
74         OneDimensional,
75         /**
76          * Two dimensional texture (default). A rectangle.
77          */
78         TwoDimensional,
79         /**
80          * Three dimensional texture. (A cube)
81          */
82         ThreeDimensional,
83         /**
84          * A set of 6 TwoDimensional textures arranged as faces of a cube facing
85          * inwards.
86          */
87         CubeMap;
88     }
89     
90     public enum MinificationFilter {
91
92         /**
93          * Nearest neighbor interpolation is the fastest and crudest filtering
94          * method - it simply uses the color of the texel closest to the pixel
95          * center for the pixel color. While fast, this results in aliasing and
96          * shimmering during minification. (GL equivalent: GL_NEAREST)
97          */
98         NearestNeighborNoMipMaps(false),
99
100         /**
101          * In this method the four nearest texels to the pixel center are
102          * sampled (at texture level 0), and their colors are combined by
103          * weighted averages. Though smoother, without mipmaps it suffers the
104          * same aliasing and shimmering problems as nearest
105          * NearestNeighborNoMipMaps. (GL equivalent: GL_LINEAR)
106          */
107         BilinearNoMipMaps(false),
108
109         /**
110          * Same as NearestNeighborNoMipMaps except that instead of using samples
111          * from texture level 0, the closest mipmap level is chosen based on
112          * distance. This reduces the aliasing and shimmering significantly, but
113          * does not help with blockiness. (GL equivalent:
114          * GL_NEAREST_MIPMAP_NEAREST)
115          */
116         NearestNeighborNearestMipMap(true),
117
118         /**
119          * Same as BilinearNoMipMaps except that instead of using samples from
120          * texture level 0, the closest mipmap level is chosen based on
121          * distance. By using mipmapping we avoid the aliasing and shimmering
122          * problems of BilinearNoMipMaps. (GL equivalent:
123          * GL_LINEAR_MIPMAP_NEAREST)
124          */
125         BilinearNearestMipMap(true),
126
127         /**
128          * Similar to NearestNeighborNoMipMaps except that instead of using
129          * samples from texture level 0, a sample is chosen from each of the
130          * closest (by distance) two mipmap levels. A weighted average of these
131          * two samples is returned. (GL equivalent: GL_NEAREST_MIPMAP_LINEAR)
132          */
133         NearestNeighborLinearMipMap(true),
134
135         /**
136          * Trilinear filtering is a remedy to a common artifact seen in
137          * mipmapped bilinearly filtered images: an abrupt and very noticeable
138          * change in quality at boundaries where the renderer switches from one
139          * mipmap level to the next. Trilinear filtering solves this by doing a
140          * texture lookup and bilinear filtering on the two closest mipmap
141          * levels (one higher and one lower quality), and then linearly
142          * interpolating the results. This results in a smooth degradation of
143          * texture quality as distance from the viewer increases, rather than a
144          * series of sudden drops. Of course, closer than Level 0 there is only
145          * one mipmap level available, and the algorithm reverts to bilinear
146          * filtering (GL equivalent: GL_LINEAR_MIPMAP_LINEAR)
147          */
148         Trilinear(true);
149
150         private boolean usesMipMapLevels;
151
152         private MinificationFilter(boolean usesMipMapLevels) {
153             this.usesMipMapLevels = usesMipMapLevels;
154         }
155
156         public boolean usesMipMapLevels() {
157             return usesMipMapLevels;
158         }
159     }
160
161     public enum MagnificationFilter {
162
163         /**
164          * Nearest neighbor interpolation is the fastest and crudest filtering
165          * mode - it simply uses the color of the texel closest to the pixel
166          * center for the pixel color. While fast, this results in texture
167          * 'blockiness' during magnification. (GL equivalent: GL_NEAREST)
168          */
169         NearestNeighbor,
170
171         /**
172          * In this mode the four nearest texels to the pixel center are sampled
173          * (at the closest mipmap level), and their colors are combined by
174          * weighted average according to distance. This removes the 'blockiness'
175          * seen during magnification, as there is now a smooth gradient of color
176          * change from one texel to the next, instead of an abrupt jump as the
177          * pixel center crosses the texel boundary. (GL equivalent: GL_LINEAR)
178          */
179         Bilinear;
180
181     }
182
183     public enum WrapMode {
184         /**
185          * Only the fractional portion of the coordinate is considered.
186          */
187         Repeat,
188         /**
189          * Only the fractional portion of the coordinate is considered, but if
190          * the integer portion is odd, we'll use 1 - the fractional portion.
191          * (Introduced around OpenGL1.4) Falls back on Repeat if not supported.
192          */
193         MirroredRepeat,
194         /**
195          * coordinate will be clamped to [0,1]
196          */
197         Clamp,
198         /**
199          * mirrors and clamps the texture coordinate, where mirroring and
200          * clamping a value f computes:
201          * <code>mirrorClamp(f) = min(1, max(1/(2*N),
202          * abs(f)))</code> where N
203          * is the size of the one-, two-, or three-dimensional texture image in
204          * the direction of wrapping. (Introduced after OpenGL1.4) Falls back on
205          * Clamp if not supported.
206          */
207         MirrorClamp,
208         /**
209          * coordinate will be clamped to the range [-1/(2N), 1 + 1/(2N)] where N
210          * is the size of the texture in the direction of clamping. Falls back
211          * on Clamp if not supported.
212          */
213         BorderClamp,
214         /**
215          * Wrap mode MIRROR_CLAMP_TO_BORDER_EXT mirrors and clamps to border the
216          * texture coordinate, where mirroring and clamping to border a value f
217          * computes:
218          * <code>mirrorClampToBorder(f) = min(1+1/(2*N), max(1/(2*N), abs(f)))</code>
219          * where N is the size of the one-, two-, or three-dimensional texture
220          * image in the direction of wrapping." (Introduced after OpenGL1.4)
221          * Falls back on BorderClamp if not supported.
222          */
223         MirrorBorderClamp,
224         /**
225          * coordinate will be clamped to the range [1/(2N), 1 - 1/(2N)] where N
226          * is the size of the texture in the direction of clamping. Falls back
227          * on Clamp if not supported.
228          */
229         EdgeClamp,
230         /**
231          * mirrors and clamps to edge the texture coordinate, where mirroring
232          * and clamping to edge a value f computes:
233          * <code>mirrorClampToEdge(f) = min(1-1/(2*N), max(1/(2*N), abs(f)))</code>
234          * where N is the size of the one-, two-, or three-dimensional texture
235          * image in the direction of wrapping. (Introduced after OpenGL1.4)
236          * Falls back on EdgeClamp if not supported.
237          */
238         MirrorEdgeClamp;
239     }
240
241     public enum WrapAxis {
242         /**
243          * S wrapping (u or "horizontal" wrap)
244          */
245         S,
246         /**
247          * T wrapping (v or "vertical" wrap)
248          */
249         T,
250         /**
251          * R wrapping (w or "depth" wrap)
252          */
253         R;
254     }
255
256     public enum ApplyMode {
257         /**
258          * Apply modifier that replaces the previous pixel color with the
259          * texture color.
260          */
261         Replace,
262         /**
263          * Apply modifier that replaces the color values of the pixel but makes
264          * use of the alpha values.
265          */
266         Decal,
267         /**
268          * Apply modifier multiples the color of the pixel with the texture
269          * color.
270          */
271         Modulate,
272         /**
273          * Apply modifier that interpolates the color of the pixel with a blend
274          * color using the texture color, such that the final color value is Cv =
275          * (1 - Ct) * Cf + BlendColor * Ct Where Ct is the color of the texture
276          * and Cf is the initial pixel color.
277          */
278         Blend,
279         /**
280          * Apply modifier combines two textures based on the combine parameters
281          * set on this texture.
282          */
283         Combine,
284         /**
285          * Apply modifier adds two textures.
286          */
287         Add;
288     }
289
290     public enum EnvironmentalMapMode {
291         /**
292          * Use texture coordinates as they are. (Do not do texture coordinate
293          * generation.)
294          */
295         None,
296         /**
297          * TODO: add documentation
298          */
299         EyeLinear,
300         /**
301          * TODO: add documentation
302          */
303         ObjectLinear,
304         /**
305          * TODO: add documentation
306          */
307         SphereMap,
308         /**
309          * TODO: add documentation
310          */
311         NormalMap,
312         /**
313          * TODO: add documentation
314          */
315         ReflectionMap;
316     }
317
318     public enum CombinerFunctionRGB {
319         /** Arg0 */
320         Replace,
321         /** Arg0 * Arg1 */
322         Modulate,
323         /** Arg0 + Arg1 */
324         Add,
325         /** Arg0 + Arg1 - 0.5 */
326         AddSigned,
327         /** Arg0 * Arg2 + Arg1 * (1 - Arg2) */
328         Interpolate,
329         /** Arg0 - Arg1 */
330         Subtract,
331         /**
332          * 4 * ((Arg0r - 0.5) * (Arg1r - 0.5) + (Arg0g - 0.5) * (Arg1g - 0.5) +
333          * (Arg0b - 0.5) * (Arg1b - 0.5)) [ result placed in R,G,B ]
334          */
335         Dot3RGB,
336         /**
337          * 4 * ((Arg0r - 0.5) * (Arg1r - 0.5) + (Arg0g - 0.5) * (Arg1g - 0.5) +
338          * (Arg0b - 0.5) * (Arg1b - 0.5)) [ result placed in R,G,B,A ]
339          */
340         Dot3RGBA;
341     }
342
343     public enum CombinerFunctionAlpha {
344         /** Arg0 */
345         Replace,
346         /** Arg0 * Arg1 */
347         Modulate,
348         /** Arg0 + Arg1 */
349         Add,
350         /** Arg0 + Arg1 - 0.5 */
351         AddSigned,
352         /** Arg0 * Arg2 + Arg1 * (1 - Arg2) */
353         Interpolate,
354         /** Arg0 - Arg1 */
355         Subtract;
356     }
357
358     public enum CombinerSource {
359         /**
360          * The incoming fragment color from the previous texture unit. When used
361          * on texture unit 0, this is the same as using PrimaryColor.
362          */
363         Previous,
364         /** The blend color set on this texture. */
365         Constant,
366         /** The incoming fragment color before any texturing is applied. */
367         PrimaryColor,
368         /** The current texture unit's bound texture. */
369         CurrentTexture,
370         /** The texture bound on texture unit 0. */
371         TextureUnit0,
372         /** The texture bound on texture unit 1. */
373         TextureUnit1,
374         /** The texture bound on texture unit 2. */
375         TextureUnit2,
376         /** The texture bound on texture unit 3. */
377         TextureUnit3,
378         /** The texture bound on texture unit 4. */
379         TextureUnit4,
380         /** The texture bound on texture unit 5. */
381         TextureUnit5,
382         /** The texture bound on texture unit 6. */
383         TextureUnit6,
384         /** The texture bound on texture unit 7. */
385         TextureUnit7,
386         /** The texture bound on texture unit 8. */
387         TextureUnit8,
388         /** The texture bound on texture unit 9. */
389         TextureUnit9,
390         /** The texture bound on texture unit 10. */
391         TextureUnit10,
392         /** The texture bound on texture unit 11. */
393         TextureUnit11,
394         /** The texture bound on texture unit 12. */
395         TextureUnit12,
396         /** The texture bound on texture unit 13. */
397         TextureUnit13,
398         /** The texture bound on texture unit 14. */
399         TextureUnit14,
400         /** The texture bound on texture unit 15. */
401         TextureUnit15,
402         /** The texture bound on texture unit 16. */
403         TextureUnit16,
404         /** The texture bound on texture unit 17. */
405         TextureUnit17,
406         /** The texture bound on texture unit 18. */
407         TextureUnit18,
408         /** The texture bound on texture unit 19. */
409         TextureUnit19,
410         /** The texture bound on texture unit 20. */
411         TextureUnit20,
412         /** The texture bound on texture unit 21. */
413         TextureUnit21,
414         /** The texture bound on texture unit 22. */
415         TextureUnit22,
416         /** The texture bound on texture unit 23. */
417         TextureUnit23,
418         /** The texture bound on texture unit 24. */
419         TextureUnit24,
420         /** The texture bound on texture unit 25. */
421         TextureUnit25,
422         /** The texture bound on texture unit 26. */
423         TextureUnit26,
424         /** The texture bound on texture unit 27. */
425         TextureUnit27,
426         /** The texture bound on texture unit 28. */
427         TextureUnit28,
428         /** The texture bound on texture unit 29. */
429         TextureUnit29,
430         /** The texture bound on texture unit 30. */
431         TextureUnit30,
432         /** The texture bound on texture unit 31. */
433         TextureUnit31;
434     }
435
436     public enum CombinerOperandRGB {
437         SourceColor, OneMinusSourceColor, SourceAlpha, OneMinusSourceAlpha;
438     }
439
440     public enum CombinerOperandAlpha {
441         SourceAlpha, OneMinusSourceAlpha;
442     }
443
444     public enum CombinerScale {
445         /** No scale (1.0x) */
446         One(1.0f),
447         /** 2.0x */
448         Two(2.0f),
449         /** 4.0x */
450         Four(4.0f);
451
452         private float scale;
453
454         private CombinerScale(float scale) {
455             this.scale = scale;
456         }
457
458         public float floatValue() {
459             return scale;
460         }
461     }
462
463     /**
464      * When doing RenderToTexture operations with this texture, this value
465      * indicates what content to render into this texture.
466      */
467     public enum RenderToTextureType {
468         /**
469          *Each element is an RGB triple. OpenGL converts it to fixed-point or floating-point and assembles it into an RGBA element by attaching 1 for alpha. 
470          *Each component is then clamped to the range [0,1].
471          */
472         RGB, 
473         /**
474          * Each element contains all four components. OpenGL converts it to fixed-point or floating-point. 
475          * Each component is then clamped to the range [0,1].
476          */
477         RGBA, 
478         /**
479          * Each element is a single depth component clamped to the range [0, 1].
480          * Each component is then clamped to the range [0,1].
481          */
482         Depth, 
483         /**
484          * Each element is a luminance/alpha pair. OpenGL converts it to fixed-point or floating point, then assembles it into an RGBA element by replicating the luminance value three times for red, green, and blue.
485          * Each component is then clamped to the range [0,1].
486          */
487         Alpha, 
488         /**
489          * Each element is a single luminance value. OpenGL converts it to fixed-point or floating-point, then assembles it into an RGBA element by replicating the luminance value three times for red, green, and blue and attaching 1 for alpha.
490          * Each component is then clamped to the range [0,1].
491          */
492         Luminance, 
493         /**
494          * Each element is a luminance/alpha pair. OpenGL converts it to fixed-point or floating point, then assembles it into an RGBA element by replicating the luminance value three times for red, green, and blue.
495          * Each component is then clamped to the range [0,1].
496          */
497         LuminanceAlpha, 
498         /**
499          * Each element has both luminance (grayness) and alpha (transparency) information, but the luminance and alpha values at every texel are the same.
500          * Each component is then clamped to the range [0,1].
501          */
502         Intensity,
503         Alpha4, Alpha8, Alpha12, Alpha16, 
504         Luminance4, Luminance8, Luminance12, Luminance16, 
505                   Luminance4Alpha4,Luminance6Alpha2, Luminance8Alpha8,Luminance12Alpha4,
506                   Luminance12Alpha12, Luminance16Alpha16, 
507                   Intensity4, Intensity8, Intensity12, Intensity16, 
508                   R3_G3_B2, RGB4, RGB5, RGB8, RGB10, RGB12, RGB16, 
509                   RGBA2, RGBA4, RGB5_A1, RGBA8, RGB10_A2, RGBA12, RGBA16,
510                   //floats
511                   RGBA32F, RGB32F, Alpha32F, Intensity32F, Luminance32F, LuminanceAlpha32F,
512                   RGBA16F, RGB16F, Alpha16F, Intensity16F, Luminance16F, LuminanceAlpha16F;
513         
514     }
515     
516     /**
517      * The shadowing texture compare mode
518      */
519     public enum DepthTextureCompareMode {
520         /** Perform no shadow based comparsion */
521         None,
522         /** Perform a comparison between source depth and texture depth */
523         RtoTexture,
524     }
525
526     /**
527      * The shadowing texture compare function
528      */
529     public enum DepthTextureCompareFunc {
530         /** Outputs if the source depth is less than the texture depth */
531         LessThanEqual,
532         /** Outputs if the source depth is greater than the texture depth */
533         GreaterThanEqual
534     }
535     
536     /**
537      * The type of depth texture translation to output
538      */
539     public enum DepthTextureMode {
540         /** Output luminance values based on the depth comparison */
541         Luminance,
542         /** Output alpha values based on the depth comparison */
543         Alpha,
544         /** Output intensity values based on the depth comparison */
545         Intensity
546     }
547     
548     
549
550     // Optional String to point to where this texture is located
551     private String imageLocation = null;
552
553     // texture attributes.
554     private Image image = null;
555     private ColorRGBA blendColor = null; // If null, black (gl's default)
556     // will be used
557     private ColorRGBA borderColor = null; // If null, black (gl's default)
558     // will be used
559
560     private Vector3f translation = null;
561     private Vector3f scale = null;
562     private Quaternion rotation = null;
563     private Matrix4f matrix = null;
564
565     private float anisotropicFilterPercent = 0.0f;
566
567     private transient int textureId;
568     private ApplyMode apply = ApplyMode.Modulate;
569     private MinificationFilter minificationFilter = MinificationFilter.NearestNeighborNoMipMaps;
570     private MagnificationFilter magnificationFilter = MagnificationFilter.NearestNeighbor;
571     private EnvironmentalMapMode envMapMode = EnvironmentalMapMode.None;
572     private RenderToTextureType rttSource = RenderToTextureType.RGBA;
573     
574     private int memReq = 0;
575     private boolean hasBorder = false;
576
577     // The following will only used if apply is set to ApplyMode.Combine
578     private CombinerFunctionRGB combineFuncRGB = CombinerFunctionRGB.Modulate;
579     private CombinerSource combineSrc0RGB = CombinerSource.CurrentTexture;
580     private CombinerSource combineSrc1RGB = CombinerSource.Previous;
581     private CombinerSource combineSrc2RGB = CombinerSource.Constant;
582     private CombinerOperandRGB combineOp0RGB = CombinerOperandRGB.SourceColor;
583     private CombinerOperandRGB combineOp1RGB = CombinerOperandRGB.SourceColor;
584     private CombinerOperandRGB combineOp2RGB = CombinerOperandRGB.SourceAlpha;
585     private CombinerScale combineScaleRGB = CombinerScale.One;
586
587     private CombinerFunctionAlpha combineFuncAlpha = CombinerFunctionAlpha.Modulate;
588     private CombinerSource combineSrc0Alpha = CombinerSource.CurrentTexture;
589     private CombinerSource combineSrc1Alpha = CombinerSource.Previous;
590     private CombinerSource combineSrc2Alpha = CombinerSource.Constant;
591     private CombinerOperandAlpha combineOp0Alpha = CombinerOperandAlpha.SourceAlpha;
592     private CombinerOperandAlpha combineOp1Alpha = CombinerOperandAlpha.SourceAlpha;
593     private CombinerOperandAlpha combineOp2Alpha = CombinerOperandAlpha.SourceAlpha;
594     private CombinerScale combineScaleAlpha = CombinerScale.One;
595
596     private TextureKey key = null;
597     private transient boolean storeTexture = DEFAULT_STORE_TEXTURE;
598
599     private DepthTextureCompareMode depthCompareMode = DepthTextureCompareMode.None;
600     private DepthTextureCompareFunc depthCompareFunc = DepthTextureCompareFunc.GreaterThanEqual;
601     private DepthTextureMode depthMode = DepthTextureMode.Intensity;
602     
603     /**
604      * Constructor instantiates a new <code>Texture</code> object with default
605      * attributes.
606      */
607     public Texture() {
608         memReq = 0;
609     }
610     
611     /**
612      * <code>setBlendColor</code> sets a color that is used with
613      * CombinerSource.Constant
614      * 
615      * @param color
616      *            the new blend color - or null for the default (black)
617      */
618     public void setBlendColor(ColorRGBA color) {
619         this.blendColor = color != null ? color.clone() : null;
620     }
621
622     /**
623      * <code>setBorderColor</code> sets the color used when texture operations
624      * encounter the border of a texture.
625      * 
626      * @param color
627      *            the new border color - or null for the default (black)
628      */
629     public void setBorderColor(ColorRGBA color) {
630         this.borderColor = color != null ? color.clone() : null;
631     }
632
633     /**
634      * @return the MinificationFilterMode of this texture.
635      */
636     public MinificationFilter getMinificationFilter() {
637         return minificationFilter;
638     }
639
640     /**
641      * @param minificationFilter
642      *            the new MinificationFilterMode for this texture.
643      * @throws IllegalArgumentException
644      *             if minificationFilter is null
645      */
646     public void setMinificationFilter(MinificationFilter minificationFilter) {
647         if (minificationFilter == null) {
648             throw new IllegalArgumentException(
649                     "minificationFilter can not be null.");
650         }
651         this.minificationFilter = minificationFilter;
652     }
653
654     /**
655      * @return the MagnificationFilterMode of this texture.
656      */
657     public MagnificationFilter getMagnificationFilter() {
658         return magnificationFilter;
659     }
660
661     /**
662      * @param magnificationFilter
663      *            the new MagnificationFilter for this texture.
664      * @throws IllegalArgumentException
665      *             if magnificationFilter is null
666      */
667     public void setMagnificationFilter(MagnificationFilter magnificationFilter) {
668         if (magnificationFilter == null) {
669             throw new IllegalArgumentException(
670                     "magnificationFilter can not be null.");
671         }
672         this.magnificationFilter = magnificationFilter;
673     }
674
675     /**
676      * <code>setApply</code> sets the apply mode for this texture.
677      * 
678      * @param apply
679      *            the apply mode for this texture.
680      * @throws IllegalArgumentException
681      *             if apply is null
682      */
683     public void setApply(ApplyMode apply) {
684         if (apply == null) {
685             throw new IllegalArgumentException("apply can not be null.");
686         }
687         this.apply = apply;
688     }
689
690     /**
691      * <code>setImage</code> sets the image object that defines the texture.
692      * 
693      * @param image
694      *            the image that defines the texture.
695      */
696     public void setImage(Image image) {
697         this.image = image;
698         updateMemoryReq();
699     }
700
701     /**
702      * <code>getTextureId</code> returns the texture id of this texture. This
703      * id is required to be unique to any other texture objects running in the
704      * same JVM. However, no guarantees are made that it will be unique, and as
705      * such, the user is responsible for this.
706      * 
707      * @return the id of the texture.
708      */
709     public int getTextureId() {
710         return textureId;
711     }
712
713     /**
714      * <code>setTextureId</code> sets the texture id for this texture. Zero
715      * means no id is set.
716      * 
717      * @param textureId
718      *            the texture id of this texture.
719      */
720     public void setTextureId(int textureId) {
721         this.textureId = textureId;
722     }
723
724     /**
725      * <code>getImage</code> returns the image data that makes up this
726      * texture. If no image data has been set, this will return null.
727      * 
728      * @return the image data that makes up the texture.
729      */
730     public Image getImage() {
731         return image;
732     }
733
734     /**
735      * <code>getApply</code> returns the apply mode for the texture.
736      * 
737      * @return the apply mode of the texture.
738      */
739     public ApplyMode getApply() {
740         return apply;
741     }
742
743     /**
744      * <code>getBlendColor</code> returns the color set to be used with
745      * CombinerSource.Constant for this texture (as applicable) If null, black
746      * is assumed.
747      * 
748      * @return the blend color.
749      */
750     public ColorRGBA getBlendColor() {
751         return blendColor;
752     }
753
754     /**
755      * <code>getBorderColor</code> returns the color to be used for border
756      * operations. If null, black is assumed.
757      * 
758      * @return the border color.
759      */
760     public ColorRGBA getBorderColor() {
761         return borderColor;
762     }
763
764     /**
765      * <code>setWrap</code> sets the wrap mode of this texture for a
766      * particular axis.
767      * 
768      * @param axis
769      *            the texture axis to define a wrapmode on.
770      * @param mode
771      *            the wrap mode for the given axis of the texture.
772      * @throws IllegalArgumentException
773      *             if axis or mode are null or invalid for this type of texture
774      */
775     public abstract void setWrap(WrapAxis axis, WrapMode mode);
776
777     /**
778      * <code>setWrap</code> sets the wrap mode of this texture for all axis.
779      * 
780      * @param mode
781      *            the wrap mode for the given axis of the texture.
782      * @throws IllegalArgumentException
783      *             if mode is null or invalid for this type of texture
784      */
785     public abstract void setWrap(WrapMode mode);
786
787     /**
788      * <code>getWrap</code> returns the wrap mode for a given coordinate axis
789      * on this texture.
790      * 
791      * @param axis
792      *            the axis to return for
793      * @return the wrap mode of the texture.
794      * @throws IllegalArgumentException
795      *             if axis is null or invalid for this type of texture
796      */
797     public abstract WrapMode getWrap(WrapAxis axis);
798     
799     public abstract Type getType();
800     
801     /**
802      * @return Returns the combineFuncRGB.
803      */
804     public CombinerFunctionRGB getCombineFuncRGB() {
805         return combineFuncRGB;
806     }
807
808     /**
809      * @param combineFuncRGB
810      *            The combineFuncRGB to set.
811      * @throws IllegalArgumentException
812      *             if combineFuncRGB is null
813      */
814     public void setCombineFuncRGB(CombinerFunctionRGB combineFuncRGB) {
815         if (combineFuncRGB == null) {
816             throw new IllegalArgumentException("invalid CombinerFunctionRGB: null");
817         }
818         this.combineFuncRGB = combineFuncRGB;
819     }
820
821     /**
822      * @return Returns the combineOp0Alpha.
823      */
824     public CombinerOperandAlpha getCombineOp0Alpha() {
825         return combineOp0Alpha;
826     }
827
828     /**
829      * @param combineOp0Alpha
830      *            The combineOp0Alpha to set.
831      * @throws IllegalArgumentException
832      *             if combineOp0Alpha is null
833      */
834     public void setCombineOp0Alpha(CombinerOperandAlpha combineOp0Alpha) {
835         if (combineOp0Alpha == null) {
836             throw new IllegalArgumentException("invalid CombinerOperandAlpha: null");
837         }
838
839         this.combineOp0Alpha = combineOp0Alpha;
840     }
841
842     /**
843      * @return Returns the combineOp0RGB.
844      */
845     public CombinerOperandRGB getCombineOp0RGB() {
846         return combineOp0RGB;
847     }
848
849     /**
850      * @param combineOp0RGB
851      *            The combineOp0RGB to set.
852      * @throws IllegalArgumentException
853      *             if combineOp0RGB is null
854      */
855     public void setCombineOp0RGB(CombinerOperandRGB combineOp0RGB) {
856         if (combineOp0RGB == null) {
857             throw new IllegalArgumentException("invalid CombinerOperandRGB: null");
858         }
859         this.combineOp0RGB = combineOp0RGB;
860     }
861
862     /**
863      * @return Returns the combineOp1Alpha.
864      */
865     public CombinerOperandAlpha getCombineOp1Alpha() {
866         return combineOp1Alpha;
867     }
868
869     /**
870      * @param combineOp1Alpha
871      *            The combineOp1Alpha to set.
872      * @throws IllegalArgumentException
873      *             if combineOp1Alpha is null
874      */
875     public void setCombineOp1Alpha(CombinerOperandAlpha combineOp1Alpha) {
876         if (combineOp1Alpha == null) {
877             throw new IllegalArgumentException("invalid CombinerOperandAlpha: null");
878         }
879         this.combineOp1Alpha = combineOp1Alpha;
880     }
881
882     /**
883      * @return Returns the combineOp1RGB.
884      */
885     public CombinerOperandRGB getCombineOp1RGB() {
886         return combineOp1RGB;
887     }
888
889     /**
890      * @param combineOp1RGB
891      *            The combineOp1RGB to set.
892      * @throws IllegalArgumentException
893      *             if combineOp1RGB is null
894      */
895     public void setCombineOp1RGB(CombinerOperandRGB combineOp1RGB) {
896         if (combineOp1RGB == null) {
897             throw new IllegalArgumentException("invalid CombinerOperandRGB: null");
898         }
899         this.combineOp1RGB = combineOp1RGB;
900     }
901
902     /**
903      * @return Returns the combineOp2Alpha.
904      */
905     public CombinerOperandAlpha getCombineOp2Alpha() {
906         return combineOp2Alpha;
907     }
908
909     /**
910      * @param combineOp2Alpha
911      *            The combineOp2Alpha to set.
912      * @throws IllegalArgumentException
913      *             if combineOp2Alpha is null
914      */
915     public void setCombineOp2Alpha(CombinerOperandAlpha combineOp2Alpha) {
916         if (combineOp2Alpha == null) {
917             throw new IllegalArgumentException("invalid CombinerOperandAlpha: null");
918         }
919         this.combineOp2Alpha = combineOp2Alpha;
920     }
921
922     /**
923      * @return Returns the combineOp2RGB.
924      */
925     public CombinerOperandRGB getCombineOp2RGB() {
926         return combineOp2RGB;
927     }
928
929     /**
930      * @param combineOp2RGB
931      *            The combineOp2RGB to set.
932      * @throws IllegalArgumentException
933      *             if combineOp2RGB is null
934      */
935     public void setCombineOp2RGB(CombinerOperandRGB combineOp2RGB) {
936         if (combineOp2RGB == null) {
937             throw new IllegalArgumentException("invalid CombinerOperandRGB: null");
938         }
939         this.combineOp2RGB = combineOp2RGB;
940     }
941
942     /**
943      * @return Returns the combineScaleAlpha.
944      */
945     public CombinerScale getCombineScaleAlpha() {
946         return combineScaleAlpha;
947     }
948
949     /**
950      * @param combineScaleAlpha
951      *            The combineScaleAlpha to set.
952      * @throws IllegalArgumentException
953      *             if combineScaleAlpha is null
954      */
955     public void setCombineScaleAlpha(CombinerScale combineScaleAlpha) {
956         if (combineScaleAlpha == null) {
957             throw new IllegalArgumentException("invalid CombinerScale: null");
958         }
959         this.combineScaleAlpha = combineScaleAlpha;
960     }
961
962     /**
963      * @return Returns the combineScaleRGB.
964      */
965     public CombinerScale getCombineScaleRGB() {
966         return combineScaleRGB;
967     }
968
969     /**
970      * @param combineScaleRGB
971      *            The combineScaleRGB to set.
972      * @throws IllegalArgumentException
973      *             if combineScaleRGB is null
974      */
975     public void setCombineScaleRGB(CombinerScale combineScaleRGB) {
976         if (combineScaleRGB == null) {
977             throw new IllegalArgumentException("invalid CombinerScale: null");
978         }
979         this.combineScaleRGB = combineScaleRGB;
980     }
981
982     /**
983      * @return Returns the combineSrc0Alpha.
984      */
985     public CombinerSource getCombineSrc0Alpha() {
986         return combineSrc0Alpha;
987     }
988
989     /**
990      * @param combineSrc0Alpha
991      *            The combineSrc0Alpha to set.
992      * @throws IllegalArgumentException
993      *             if combineSrc0Alpha is null
994      */
995     public void setCombineSrc0Alpha(CombinerSource combineSrc0Alpha) {
996         if (combineSrc0Alpha == null) {
997             throw new IllegalArgumentException("invalid CombinerSource: null");
998         }
999         this.combineSrc0Alpha = combineSrc0Alpha;
1000     }
1001
1002     /**
1003      * @return Returns the combineSrc0RGB.
1004      */
1005     public CombinerSource getCombineSrc0RGB() {
1006         return combineSrc0RGB;
1007     }
1008
1009     /**
1010      * @param combineSrc0RGB
1011      *            The combineSrc0RGB to set.
1012      * @throws IllegalArgumentException
1013      *             if combineSrc0RGB is null
1014      */
1015     public void setCombineSrc0RGB(CombinerSource combineSrc0RGB) {
1016         if (combineSrc0RGB == null) {
1017             throw new IllegalArgumentException("invalid CombinerSource: null");
1018         }
1019         this.combineSrc0RGB = combineSrc0RGB;
1020     }
1021
1022     /**
1023      * @return Returns the combineSrc1Alpha.
1024      */
1025     public CombinerSource getCombineSrc1Alpha() {
1026         return combineSrc1Alpha;
1027     }
1028
1029     /**
1030      * @param combineSrc1Alpha
1031      *            The combineSrc1Alpha to set.
1032      * @throws IllegalArgumentException
1033      *             if combineSrc1Alpha is null
1034      */
1035     public void setCombineSrc1Alpha(CombinerSource combineSrc1Alpha) {
1036         if (combineSrc1Alpha == null) {
1037             throw new IllegalArgumentException("invalid CombinerSource: null");
1038         }
1039         this.combineSrc1Alpha = combineSrc1Alpha;
1040     }
1041
1042     /**
1043      * @return Returns the combineSrc1RGB.
1044      */
1045     public CombinerSource getCombineSrc1RGB() {
1046         return combineSrc1RGB;
1047     }
1048
1049     /**
1050      * @param combineSrc1RGB
1051      *            The combineSrc1RGB to set.
1052      * @throws IllegalArgumentException
1053      *             if combineSrc1RGB is null
1054      */
1055     public void setCombineSrc1RGB(CombinerSource combineSrc1RGB) {
1056         if (combineSrc1RGB == null) {
1057             throw new IllegalArgumentException("invalid CombinerSource: null");
1058         }
1059         this.combineSrc1RGB = combineSrc1RGB;
1060     }
1061
1062     /**
1063      * @return Returns the combineSrc2Alpha.
1064      */
1065     public CombinerSource getCombineSrc2Alpha() {
1066         return combineSrc2Alpha;
1067     }
1068
1069     /**
1070      * @param combineSrc2Alpha
1071      *            The combineSrc2Alpha to set.
1072      * @throws IllegalArgumentException
1073      *             if combineSrc2Alpha is null
1074      */
1075     public void setCombineSrc2Alpha(CombinerSource combineSrc2Alpha) {
1076         if (combineSrc2Alpha == null) {
1077             throw new IllegalArgumentException("invalid CombinerSource: null");
1078         }
1079         this.combineSrc2Alpha = combineSrc2Alpha;
1080     }
1081
1082     /**
1083      * @return Returns the combineSrc2RGB.
1084      */
1085     public CombinerSource getCombineSrc2RGB() {
1086         return combineSrc2RGB;
1087     }
1088
1089     /**
1090      * @param combineSrc2RGB
1091      *            The combineSrc2RGB to set.
1092      * @throws IllegalArgumentException
1093      *             if combineSrc2RGB is null
1094      */
1095     public void setCombineSrc2RGB(CombinerSource combineSrc2RGB) {
1096         if (combineSrc2RGB == null) {
1097             throw new IllegalArgumentException("invalid CombinerSource: null");
1098         }
1099         this.combineSrc2RGB = combineSrc2RGB;
1100     }
1101
1102     /**
1103      * @return Returns the combineFuncAlpha.
1104      */
1105     public CombinerFunctionAlpha getCombineFuncAlpha() {
1106         return combineFuncAlpha;
1107     }
1108
1109     /**
1110      * @param combineFuncAlpha
1111      *            The combineFuncAlpha to set.
1112      * @throws IllegalArgumentException
1113      *             if combineFuncAlpha is null
1114      */
1115     public void setCombineFuncAlpha(CombinerFunctionAlpha combineFuncAlpha) {
1116         if (combineFuncAlpha == null) {
1117             throw new IllegalArgumentException("invalid CombinerFunctionAlpha: null");
1118         }
1119         this.combineFuncAlpha = combineFuncAlpha;
1120     }
1121
1122     /**
1123      * @param envMapMode
1124      * @throws IllegalArgumentException
1125      *             if envMapMode is null
1126      */
1127     public void setEnvironmentalMapMode(EnvironmentalMapMode envMapMode) {
1128         if (envMapMode == null) {
1129             throw new IllegalArgumentException("invalid EnvironmentalMapMode: null");
1130         }
1131         this.envMapMode = envMapMode;
1132     }
1133
1134     public EnvironmentalMapMode getEnvironmentalMapMode() {
1135         return envMapMode;
1136     }
1137
1138     public String getImageLocation() {
1139         return imageLocation;
1140     }
1141
1142     public void setImageLocation(String imageLocation) {
1143         this.imageLocation = imageLocation;
1144     }
1145
1146     /**
1147      * @return the anisotropic filtering level for this texture as a percentage
1148      *         (0.0 - 1.0)
1149      */
1150     public float getAnisotropicFilterPercent() {
1151         return anisotropicFilterPercent;
1152     }
1153
1154     /**
1155      * @param percent
1156      *            the anisotropic filtering level for this texture as a
1157      *            percentage (0.0 - 1.0)
1158      */
1159     public void setAnisotropicFilterPercent(float percent) {
1160         if (percent > 1.0f)
1161             percent = 1.0f;
1162         else if (percent < 0.0f)
1163             percent = 0.0f;
1164         this.anisotropicFilterPercent = percent;
1165     }
1166
1167     public boolean equals(Object other) {
1168         if (other == this) {
1169             return true;
1170         }
1171         if (!(other instanceof Texture)) {
1172             return false;
1173         }
1174         
1175         Texture that = (Texture) other;
1176         if (this.textureId != that.textureId)
1177             return false;
1178         if (this.textureId == 0) {
1179             if (this.getImage() != null
1180                     && !this.getImage().equals(that.getImage()))
1181                 return false;
1182             if (this.getImage() == null && that.getImage() != null)
1183                 return false;
1184             if (this.getAnisotropicFilterPercent() != that
1185                     .getAnisotropicFilterPercent())
1186                 return false;
1187             if (this.getApply() != that.getApply())
1188                 return false;
1189             if (this.getCombineFuncAlpha() != that.getCombineFuncAlpha())
1190                 return false;
1191             if (this.getCombineFuncRGB() != that.getCombineFuncRGB())
1192                 return false;
1193             if (this.getCombineOp0Alpha() != that.getCombineOp0Alpha())
1194                 return false;
1195             if (this.getCombineOp1RGB() != that.getCombineOp1RGB())
1196                 return false;
1197             if (this.getCombineOp2Alpha() != that.getCombineOp2Alpha())
1198                 return false;
1199             if (this.getCombineOp2RGB() != that.getCombineOp2RGB())
1200                 return false;
1201             if (this.getCombineScaleAlpha() != that.getCombineScaleAlpha())
1202                 return false;
1203             if (this.getCombineScaleRGB() != that.getCombineScaleRGB())
1204                 return false;
1205             if (this.getCombineSrc0Alpha() != that.getCombineSrc0Alpha())
1206                 return false;
1207             if (this.getCombineSrc0RGB() != that.getCombineSrc0RGB())
1208                 return false;
1209             if (this.getCombineSrc1Alpha() != that.getCombineSrc1Alpha())
1210                 return false;
1211             if (this.getCombineSrc1RGB() != that.getCombineSrc1RGB())
1212                 return false;
1213             if (this.getCombineSrc2Alpha() != that.getCombineSrc2Alpha())
1214                 return false;
1215             if (this.getCombineSrc2RGB() != that.getCombineSrc2RGB())
1216                 return false;
1217             if (this.getEnvironmentalMapMode() != that
1218                     .getEnvironmentalMapMode())
1219                 return false;
1220             if (this.getMagnificationFilter() != that.getMagnificationFilter())
1221                 return false;
1222             if (this.getMinificationFilter() != that.getMinificationFilter())
1223                 return false;
1224             if (this.getBlendColor() != null
1225                     && !this.getBlendColor().equals(that.getBlendColor()))
1226                 return false;
1227             if (this.getBlendColor() == null && that.getBlendColor() != null)
1228                 return false;
1229         }
1230         return true;
1231     }
1232
1233     public abstract Texture createSimpleClone();
1234
1235     /**
1236      * Retreive a basic clone of this Texture (ie, clone everything but the
1237      * image data, which is shared)
1238      * 
1239      * @return Texture
1240      */
1241     public Texture createSimpleClone(Texture rVal) {
1242         rVal.setApply(apply);
1243         rVal.setCombineFuncAlpha(combineFuncAlpha);
1244         rVal.setCombineFuncRGB(combineFuncRGB);
1245         rVal.setCombineOp0Alpha(combineOp0Alpha);
1246         rVal.setCombineOp0RGB(combineOp0RGB);
1247         rVal.setCombineOp1Alpha(combineOp1Alpha);
1248         rVal.setCombineOp1RGB(combineOp1RGB);
1249         rVal.setCombineOp2Alpha(combineOp2Alpha);
1250         rVal.setCombineOp2RGB(combineOp2RGB);
1251         rVal.setCombineScaleAlpha(combineScaleAlpha);
1252         rVal.setCombineScaleRGB(combineScaleRGB);
1253         rVal.setCombineSrc0Alpha(combineSrc0Alpha);
1254         rVal.setCombineSrc0RGB(combineSrc0RGB);
1255         rVal.setCombineSrc1Alpha(combineSrc1Alpha);
1256         rVal.setCombineSrc1RGB(combineSrc1RGB);
1257         rVal.setCombineSrc2Alpha(combineSrc2Alpha);
1258         rVal.setCombineSrc2RGB(combineSrc2RGB);
1259         rVal.setEnvironmentalMapMode(envMapMode);
1260         rVal.setMinificationFilter(minificationFilter);
1261         rVal.setMagnificationFilter(magnificationFilter);
1262         rVal.setHasBorder(hasBorder);
1263         rVal.setAnisotropicFilterPercent(anisotropicFilterPercent);
1264         rVal.setImage(image); // NOT CLONED.
1265         rVal.memReq = memReq;
1266         rVal.setImageLocation(imageLocation);
1267         rVal.setTextureId(textureId);
1268         rVal.setBlendColor(blendColor != null ? blendColor.clone() : null);
1269         if (scale != null)
1270             rVal.setScale(scale);
1271         if (translation != null)
1272             rVal.setTranslation(translation);
1273         if (rotation != null)
1274             rVal.setRotation(rotation);
1275         if (matrix != null)
1276             rVal.setMatrix(matrix);
1277         if (getTextureKey() != null) {
1278             rVal.setTextureKey(getTextureKey());
1279         }
1280         return rVal;
1281     }
1282
1283     /**
1284      * @return Returns the rotation.
1285      */
1286     public Quaternion getRotation() {
1287         return rotation;
1288     }
1289
1290     /**
1291      * @param rotation
1292      *            The rotation to set.
1293      */
1294     public void setRotation(Quaternion rotation) {
1295         this.rotation = rotation;
1296     }
1297
1298     /**
1299      * @return the texture matrix set on this texture or null if none is set.
1300      */
1301     public Matrix4f getMatrix() {
1302         return matrix;
1303     }
1304
1305     /**
1306      * @param matrix
1307      *            The matrix to set on this Texture. If null, rotation, scale
1308      *            and/or translation will be used.
1309      */
1310     public void setMatrix(Matrix4f matrix) {
1311         this.matrix = matrix;
1312     }
1313
1314     /**
1315      * @return Returns the scale.
1316      */
1317     public Vector3f getScale() {
1318         return scale;
1319     }
1320
1321     /**
1322      * @param scale
1323      *            The scale to set.
1324      */
1325     public void setScale(Vector3f scale) {
1326         this.scale = scale;
1327     }
1328
1329     /**
1330      * @return Returns the translation.
1331      */
1332     public Vector3f getTranslation() {
1333         return translation;
1334     }
1335
1336     /**
1337      * @param translation
1338      *            The translation to set.
1339      */
1340     public void setTranslation(Vector3f translation) {
1341         this.translation = translation;
1342     }
1343
1344     /**
1345      * @return Returns the rttSource.
1346      */
1347     public RenderToTextureType getRTTSource() {
1348         return rttSource;
1349     }
1350
1351     /**
1352      * @param rttSource
1353      *            The rttSource to set.
1354      * @throws IllegalArgumentException
1355      *             if rttSource is null
1356      */
1357     public void setRenderToTextureType(RenderToTextureType rttSource) {
1358         if (rttSource == null) {
1359             throw new IllegalArgumentException("invalid RenderToTextureType: null");
1360         }
1361         this.rttSource = rttSource;
1362     }
1363
1364     /**
1365      * @return the estimated footprint of this texture in bytes
1366      */
1367     public int getMemoryReq() {
1368         return memReq;
1369     }
1370
1371     public void updateMemoryReq() {
1372         if (image != null) {
1373             int width = image.getWidth(), height = image.getHeight();
1374             memReq = width * height;
1375             int bpp = Image.getEstimatedByteSize(image.getFormat());
1376             memReq *= bpp;
1377             if (this.getMinificationFilter().usesMipMapLevels()
1378                     || image.hasMipmaps()) {
1379                 if (FastMath.isPowerOfTwo(image.getWidth())
1380                         && FastMath.isPowerOfTwo(image.getHeight()))
1381                     memReq *= 1.33333f;
1382                 else
1383                     memReq *= 2.0f; // XXX: Is this right?
1384             }
1385         }
1386     }
1387
1388     public void write(JMEExporter e) throws IOException {
1389
1390         OutputCapsule capsule = e.getCapsule(this);
1391         capsule.write(imageLocation, "imageLocation", null);
1392         if (storeTexture) {
1393             capsule.write(image, "image", null);
1394         }
1395         capsule.write(blendColor, "blendColor", null);
1396         capsule.write(borderColor, "borderColor", null);
1397         capsule.write(translation, "translation", null);
1398         capsule.write(scale, "scale", null);
1399         capsule.write(rotation, "rotation", null);
1400         capsule.write(matrix, "matrix", null);
1401         capsule.write(hasBorder, "hasBorder", false);
1402         capsule.write(anisotropicFilterPercent, "anisotropicFilterPercent",
1403                 0.0f);
1404         capsule.write(minificationFilter, "minificationFilter",
1405                 MinificationFilter.NearestNeighborNoMipMaps);
1406         capsule.write(magnificationFilter, "magnificationFilter",
1407                 MagnificationFilter.NearestNeighbor);
1408         capsule.write(apply, "apply", ApplyMode.Modulate);
1409         capsule.write(envMapMode, "envMapMode", EnvironmentalMapMode.None);
1410         capsule.write(rttSource, "rttSource", RenderToTextureType.RGBA);
1411         capsule.write(memReq, "memReq", 0);
1412         capsule.write(combineFuncRGB, "combineFuncRGB",
1413                 CombinerFunctionRGB.Replace);
1414         capsule.write(combineFuncAlpha, "combineFuncAlpha",
1415                 CombinerFunctionAlpha.Replace);
1416         capsule.write(combineSrc0RGB, "combineSrc0RGB",
1417                 CombinerSource.CurrentTexture);
1418         capsule
1419                 .write(combineSrc1RGB, "combineSrc1RGB",
1420                         CombinerSource.Previous);
1421         capsule
1422                 .write(combineSrc2RGB, "combineSrc2RGB",
1423                         CombinerSource.Constant);
1424         capsule.write(combineSrc0Alpha, "combineSrc0Alpha",
1425                 CombinerSource.CurrentTexture);
1426         capsule.write(combineSrc1Alpha, "combineSrc1Alpha",
1427                 CombinerSource.Previous);
1428         capsule.write(combineSrc2Alpha, "combineSrc2Alpha",
1429                 CombinerSource.Constant);
1430         capsule.write(combineOp0RGB, "combineOp0RGB",
1431                 CombinerOperandRGB.SourceColor);
1432         capsule.write(combineOp1RGB, "combineOp1RGB",
1433                 CombinerOperandRGB.SourceColor);
1434         capsule.write(combineOp2RGB, "combineOp2RGB",
1435                 CombinerOperandRGB.SourceAlpha);
1436         capsule.write(combineOp0Alpha, "combineOp0Alpha",
1437                 CombinerOperandAlpha.SourceAlpha);
1438         capsule.write(combineOp1Alpha, "combineOp1Alpha",
1439                 CombinerOperandAlpha.SourceAlpha);
1440         capsule.write(combineOp2Alpha, "combineOp2Alpha",
1441                 CombinerOperandAlpha.SourceAlpha);
1442         capsule.write(combineScaleRGB, "combineScaleRGB", CombinerScale.One);
1443         capsule
1444                 .write(combineScaleAlpha, "combineScaleAlpha",
1445                         CombinerScale.One);
1446         if (!storeTexture) {
1447             capsule.write(key, "textureKey", null);
1448         }
1449     }
1450
1451     public void read(JMEImporter e) throws IOException {
1452         InputCapsule capsule = e.getCapsule(this);
1453         imageLocation = capsule.readString("imageLocation", null);
1454         image = (Image) capsule.readSavable("image", null);
1455         if (image == null) {
1456             key = (TextureKey) capsule.readSavable("textureKey", null);
1457             if (key != null && key.getLocation() != null) {
1458                 TextureManager.loadTexture(this, key);
1459             }
1460         }
1461         blendColor = (ColorRGBA) capsule.readSavable("blendColor", null);
1462         borderColor = (ColorRGBA) capsule.readSavable("borderColor", null);
1463         translation = (Vector3f) capsule.readSavable("translation", null);
1464         scale = (Vector3f) capsule.readSavable("scale", null);
1465         rotation = (Quaternion) capsule.readSavable("rotation", null);
1466         matrix = (Matrix4f) capsule.readSavable("matrix", null);
1467         hasBorder = capsule.readBoolean("hasBorder", false);
1468         anisotropicFilterPercent = capsule.readFloat(
1469                 "anisotropicFilterPercent", 0.0f);
1470         minificationFilter = capsule.readEnum("minificationFilter",
1471                 MinificationFilter.class,
1472                 MinificationFilter.NearestNeighborNoMipMaps);
1473         magnificationFilter = capsule.readEnum("magnificationFilter",
1474                 MagnificationFilter.class, MagnificationFilter.NearestNeighbor);
1475         apply = capsule.readEnum("apply", ApplyMode.class, ApplyMode.Modulate);
1476         envMapMode = capsule.readEnum("envMapMode", EnvironmentalMapMode.class,
1477                 EnvironmentalMapMode.None);
1478         rttSource = capsule.readEnum("rttSource", RenderToTextureType.class,
1479                 RenderToTextureType.RGBA);
1480         memReq = capsule.readInt("memReq", 0);
1481         combineFuncRGB = capsule.readEnum("combineFuncRGB",
1482                 CombinerFunctionRGB.class, CombinerFunctionRGB.Replace);
1483         combineFuncAlpha = capsule.readEnum("combineFuncAlpha",
1484                 CombinerFunctionAlpha.class, CombinerFunctionAlpha.Replace);
1485         combineSrc0RGB = capsule.readEnum("combineSrc0RGB",
1486                 CombinerSource.class, CombinerSource.CurrentTexture);
1487         combineSrc1RGB = capsule.readEnum("combineSrc1RGB",
1488                 CombinerSource.class, CombinerSource.Previous);
1489         combineSrc2RGB = capsule.readEnum("combineSrc2RGB",
1490                 CombinerSource.class, CombinerSource.Constant);
1491         combineSrc0Alpha = capsule.readEnum("combineSrc0Alpha",
1492                 CombinerSource.class, CombinerSource.CurrentTexture);
1493         combineSrc1Alpha = capsule.readEnum("combineSrc1Alpha",
1494                 CombinerSource.class, CombinerSource.Previous);
1495         combineSrc2Alpha = capsule.readEnum("combineSrc2Alpha",
1496                 CombinerSource.class, CombinerSource.Constant);
1497         combineOp0RGB = capsule.readEnum("combineOp0RGB",
1498                 CombinerOperandRGB.class, CombinerOperandRGB.SourceColor);
1499         combineOp1RGB = capsule.readEnum("combineOp1RGB",
1500                 CombinerOperandRGB.class, CombinerOperandRGB.SourceColor);
1501         combineOp2RGB = capsule.readEnum("combineOp2RGB",
1502                 CombinerOperandRGB.class, CombinerOperandRGB.SourceAlpha);
1503         combineOp0Alpha = capsule.readEnum("combineOp0Alpha",
1504                 CombinerOperandAlpha.class, CombinerOperandAlpha.SourceAlpha);
1505         combineOp1Alpha = capsule.readEnum("combineOp1Alpha",
1506                 CombinerOperandAlpha.class, CombinerOperandAlpha.SourceAlpha);
1507         combineOp2Alpha = capsule.readEnum("combineOp2Alpha",
1508                 CombinerOperandAlpha.class, CombinerOperandAlpha.SourceAlpha);
1509         combineScaleRGB = capsule.readEnum("combineScaleRGB",
1510                 CombinerScale.class, CombinerScale.One);
1511         combineScaleAlpha = capsule.readEnum("combineScaleAlpha",
1512                 CombinerScale.class, CombinerScale.One);
1513     }
1514
1515     public Class<? extends Texture> getClassTag() {
1516         return this.getClass();
1517     }
1518
1519     public void setTextureKey(TextureKey tkey) {
1520         this.key = tkey;
1521     }
1522
1523     public TextureKey getTextureKey() {
1524         return key;
1525     }
1526
1527     public boolean isStoreTexture() {
1528         return storeTexture;
1529     }
1530
1531     public void setStoreTexture(boolean storeTexture) {
1532         this.storeTexture = storeTexture;
1533     }
1534
1535     public boolean hasBorder() {
1536         return hasBorder;
1537     }
1538
1539     public void setHasBorder(boolean hasBorder) {
1540         this.hasBorder = hasBorder;
1541     }
1542
1543     /**
1544      * Get the depth texture compare function 
1545      * 
1546      * @return The depth texture compare function
1547      */
1548         public DepthTextureCompareFunc getDepthCompareFunc() {
1549                 return depthCompareFunc;
1550         }
1551
1552     /**
1553      * Set the depth texture compare function 
1554      * 
1555      * param depthCompareFunc The depth texture compare function
1556      */
1557         public void setDepthCompareFunc(DepthTextureCompareFunc depthCompareFunc) {
1558                 this.depthCompareFunc = depthCompareFunc;
1559         }
1560
1561         /**
1562          * Get the depth texture apply mode
1563          * 
1564          * @return The depth texture apply mode
1565          */
1566         public DepthTextureMode getDepthMode() {
1567                 return depthMode;
1568         }
1569
1570         /**
1571          * Set the depth texture apply mode
1572          * 
1573          * param depthMode The depth texture apply mode
1574          */
1575         public void setDepthMode(DepthTextureMode depthMode) {
1576                 this.depthMode = depthMode;
1577         }
1578
1579         /**
1580          * Get the depth texture compare mode
1581          * 
1582          * @return The depth texture compare mode
1583          */
1584         public DepthTextureCompareMode getDepthCompareMode() {
1585                 return depthCompareMode;
1586         }
1587
1588         /**
1589          * Set the depth texture compare mode
1590          * 
1591          * @param depthCompareMode The depth texture compare mode
1592          */
1593         public void setDepthCompareMode(DepthTextureCompareMode depthCompareMode) {
1594                 this.depthCompareMode = depthCompareMode;
1595         }
1596 }
1597