2 * Copyright (c) 2003-2009 jMonkeyEngine
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
33 package com.jme.image;
35 import java.io.IOException;
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;
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.
60 * @see com.jme.image.Image
62 * @author Joshua Slack
63 * @version $Id: Texture.java,v 1.44 2007/10/19 13:21:41 nca Exp $
65 public abstract class Texture implements Savable {
66 private static final long serialVersionUID = -3642148179543729674L;
68 public static boolean DEFAULT_STORE_TEXTURE = false;
72 * One dimensional texture. (basically a line)
76 * Two dimensional texture (default). A rectangle.
80 * Three dimensional texture. (A cube)
84 * A set of 6 TwoDimensional textures arranged as faces of a cube facing
90 public enum MinificationFilter {
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)
98 NearestNeighborNoMipMaps(false),
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)
107 BilinearNoMipMaps(false),
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)
116 NearestNeighborNearestMipMap(true),
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)
125 BilinearNearestMipMap(true),
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)
133 NearestNeighborLinearMipMap(true),
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)
150 private boolean usesMipMapLevels;
152 private MinificationFilter(boolean usesMipMapLevels) {
153 this.usesMipMapLevels = usesMipMapLevels;
156 public boolean usesMipMapLevels() {
157 return usesMipMapLevels;
161 public enum MagnificationFilter {
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)
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)
183 public enum WrapMode {
185 * Only the fractional portion of the coordinate is considered.
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.
195 * coordinate will be clamped to [0,1]
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.
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.
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
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.
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.
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.
241 public enum WrapAxis {
243 * S wrapping (u or "horizontal" wrap)
247 * T wrapping (v or "vertical" wrap)
251 * R wrapping (w or "depth" wrap)
256 public enum ApplyMode {
258 * Apply modifier that replaces the previous pixel color with the
263 * Apply modifier that replaces the color values of the pixel but makes
264 * use of the alpha values.
268 * Apply modifier multiples the color of the pixel with the texture
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.
280 * Apply modifier combines two textures based on the combine parameters
281 * set on this texture.
285 * Apply modifier adds two textures.
290 public enum EnvironmentalMapMode {
292 * Use texture coordinates as they are. (Do not do texture coordinate
297 * TODO: add documentation
301 * TODO: add documentation
305 * TODO: add documentation
309 * TODO: add documentation
313 * TODO: add documentation
318 public enum CombinerFunctionRGB {
325 /** Arg0 + Arg1 - 0.5 */
327 /** Arg0 * Arg2 + Arg1 * (1 - Arg2) */
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 ]
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 ]
343 public enum CombinerFunctionAlpha {
350 /** Arg0 + Arg1 - 0.5 */
352 /** Arg0 * Arg2 + Arg1 * (1 - Arg2) */
358 public enum CombinerSource {
360 * The incoming fragment color from the previous texture unit. When used
361 * on texture unit 0, this is the same as using PrimaryColor.
364 /** The blend color set on this texture. */
366 /** The incoming fragment color before any texturing is applied. */
368 /** The current texture unit's bound texture. */
370 /** The texture bound on texture unit 0. */
372 /** The texture bound on texture unit 1. */
374 /** The texture bound on texture unit 2. */
376 /** The texture bound on texture unit 3. */
378 /** The texture bound on texture unit 4. */
380 /** The texture bound on texture unit 5. */
382 /** The texture bound on texture unit 6. */
384 /** The texture bound on texture unit 7. */
386 /** The texture bound on texture unit 8. */
388 /** The texture bound on texture unit 9. */
390 /** The texture bound on texture unit 10. */
392 /** The texture bound on texture unit 11. */
394 /** The texture bound on texture unit 12. */
396 /** The texture bound on texture unit 13. */
398 /** The texture bound on texture unit 14. */
400 /** The texture bound on texture unit 15. */
402 /** The texture bound on texture unit 16. */
404 /** The texture bound on texture unit 17. */
406 /** The texture bound on texture unit 18. */
408 /** The texture bound on texture unit 19. */
410 /** The texture bound on texture unit 20. */
412 /** The texture bound on texture unit 21. */
414 /** The texture bound on texture unit 22. */
416 /** The texture bound on texture unit 23. */
418 /** The texture bound on texture unit 24. */
420 /** The texture bound on texture unit 25. */
422 /** The texture bound on texture unit 26. */
424 /** The texture bound on texture unit 27. */
426 /** The texture bound on texture unit 28. */
428 /** The texture bound on texture unit 29. */
430 /** The texture bound on texture unit 30. */
432 /** The texture bound on texture unit 31. */
436 public enum CombinerOperandRGB {
437 SourceColor, OneMinusSourceColor, SourceAlpha, OneMinusSourceAlpha;
440 public enum CombinerOperandAlpha {
441 SourceAlpha, OneMinusSourceAlpha;
444 public enum CombinerScale {
445 /** No scale (1.0x) */
454 private CombinerScale(float scale) {
458 public float floatValue() {
464 * When doing RenderToTexture operations with this texture, this value
465 * indicates what content to render into this texture.
467 public enum RenderToTextureType {
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].
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].
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].
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].
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].
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].
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].
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,
511 RGBA32F, RGB32F, Alpha32F, Intensity32F, Luminance32F, LuminanceAlpha32F,
512 RGBA16F, RGB16F, Alpha16F, Intensity16F, Luminance16F, LuminanceAlpha16F;
517 * The shadowing texture compare mode
519 public enum DepthTextureCompareMode {
520 /** Perform no shadow based comparsion */
522 /** Perform a comparison between source depth and texture depth */
527 * The shadowing texture compare function
529 public enum DepthTextureCompareFunc {
530 /** Outputs if the source depth is less than the texture depth */
532 /** Outputs if the source depth is greater than the texture depth */
537 * The type of depth texture translation to output
539 public enum DepthTextureMode {
540 /** Output luminance values based on the depth comparison */
542 /** Output alpha values based on the depth comparison */
544 /** Output intensity values based on the depth comparison */
550 // Optional String to point to where this texture is located
551 private String imageLocation = null;
553 // texture attributes.
554 private Image image = null;
555 private ColorRGBA blendColor = null; // If null, black (gl's default)
557 private ColorRGBA borderColor = null; // If null, black (gl's default)
560 private Vector3f translation = null;
561 private Vector3f scale = null;
562 private Quaternion rotation = null;
563 private Matrix4f matrix = null;
565 private float anisotropicFilterPercent = 0.0f;
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;
574 private int memReq = 0;
575 private boolean hasBorder = false;
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;
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;
596 private TextureKey key = null;
597 private transient boolean storeTexture = DEFAULT_STORE_TEXTURE;
599 private DepthTextureCompareMode depthCompareMode = DepthTextureCompareMode.None;
600 private DepthTextureCompareFunc depthCompareFunc = DepthTextureCompareFunc.GreaterThanEqual;
601 private DepthTextureMode depthMode = DepthTextureMode.Intensity;
604 * Constructor instantiates a new <code>Texture</code> object with default
612 * <code>setBlendColor</code> sets a color that is used with
613 * CombinerSource.Constant
616 * the new blend color - or null for the default (black)
618 public void setBlendColor(ColorRGBA color) {
619 this.blendColor = color != null ? color.clone() : null;
623 * <code>setBorderColor</code> sets the color used when texture operations
624 * encounter the border of a texture.
627 * the new border color - or null for the default (black)
629 public void setBorderColor(ColorRGBA color) {
630 this.borderColor = color != null ? color.clone() : null;
634 * @return the MinificationFilterMode of this texture.
636 public MinificationFilter getMinificationFilter() {
637 return minificationFilter;
641 * @param minificationFilter
642 * the new MinificationFilterMode for this texture.
643 * @throws IllegalArgumentException
644 * if minificationFilter is null
646 public void setMinificationFilter(MinificationFilter minificationFilter) {
647 if (minificationFilter == null) {
648 throw new IllegalArgumentException(
649 "minificationFilter can not be null.");
651 this.minificationFilter = minificationFilter;
655 * @return the MagnificationFilterMode of this texture.
657 public MagnificationFilter getMagnificationFilter() {
658 return magnificationFilter;
662 * @param magnificationFilter
663 * the new MagnificationFilter for this texture.
664 * @throws IllegalArgumentException
665 * if magnificationFilter is null
667 public void setMagnificationFilter(MagnificationFilter magnificationFilter) {
668 if (magnificationFilter == null) {
669 throw new IllegalArgumentException(
670 "magnificationFilter can not be null.");
672 this.magnificationFilter = magnificationFilter;
676 * <code>setApply</code> sets the apply mode for this texture.
679 * the apply mode for this texture.
680 * @throws IllegalArgumentException
683 public void setApply(ApplyMode apply) {
685 throw new IllegalArgumentException("apply can not be null.");
691 * <code>setImage</code> sets the image object that defines the texture.
694 * the image that defines the texture.
696 public void setImage(Image image) {
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.
707 * @return the id of the texture.
709 public int getTextureId() {
714 * <code>setTextureId</code> sets the texture id for this texture. Zero
715 * means no id is set.
718 * the texture id of this texture.
720 public void setTextureId(int textureId) {
721 this.textureId = textureId;
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.
728 * @return the image data that makes up the texture.
730 public Image getImage() {
735 * <code>getApply</code> returns the apply mode for the texture.
737 * @return the apply mode of the texture.
739 public ApplyMode getApply() {
744 * <code>getBlendColor</code> returns the color set to be used with
745 * CombinerSource.Constant for this texture (as applicable) If null, black
748 * @return the blend color.
750 public ColorRGBA getBlendColor() {
755 * <code>getBorderColor</code> returns the color to be used for border
756 * operations. If null, black is assumed.
758 * @return the border color.
760 public ColorRGBA getBorderColor() {
765 * <code>setWrap</code> sets the wrap mode of this texture for a
769 * the texture axis to define a wrapmode on.
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
775 public abstract void setWrap(WrapAxis axis, WrapMode mode);
778 * <code>setWrap</code> sets the wrap mode of this texture for all axis.
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
785 public abstract void setWrap(WrapMode mode);
788 * <code>getWrap</code> returns the wrap mode for a given coordinate 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
797 public abstract WrapMode getWrap(WrapAxis axis);
799 public abstract Type getType();
802 * @return Returns the combineFuncRGB.
804 public CombinerFunctionRGB getCombineFuncRGB() {
805 return combineFuncRGB;
809 * @param combineFuncRGB
810 * The combineFuncRGB to set.
811 * @throws IllegalArgumentException
812 * if combineFuncRGB is null
814 public void setCombineFuncRGB(CombinerFunctionRGB combineFuncRGB) {
815 if (combineFuncRGB == null) {
816 throw new IllegalArgumentException("invalid CombinerFunctionRGB: null");
818 this.combineFuncRGB = combineFuncRGB;
822 * @return Returns the combineOp0Alpha.
824 public CombinerOperandAlpha getCombineOp0Alpha() {
825 return combineOp0Alpha;
829 * @param combineOp0Alpha
830 * The combineOp0Alpha to set.
831 * @throws IllegalArgumentException
832 * if combineOp0Alpha is null
834 public void setCombineOp0Alpha(CombinerOperandAlpha combineOp0Alpha) {
835 if (combineOp0Alpha == null) {
836 throw new IllegalArgumentException("invalid CombinerOperandAlpha: null");
839 this.combineOp0Alpha = combineOp0Alpha;
843 * @return Returns the combineOp0RGB.
845 public CombinerOperandRGB getCombineOp0RGB() {
846 return combineOp0RGB;
850 * @param combineOp0RGB
851 * The combineOp0RGB to set.
852 * @throws IllegalArgumentException
853 * if combineOp0RGB is null
855 public void setCombineOp0RGB(CombinerOperandRGB combineOp0RGB) {
856 if (combineOp0RGB == null) {
857 throw new IllegalArgumentException("invalid CombinerOperandRGB: null");
859 this.combineOp0RGB = combineOp0RGB;
863 * @return Returns the combineOp1Alpha.
865 public CombinerOperandAlpha getCombineOp1Alpha() {
866 return combineOp1Alpha;
870 * @param combineOp1Alpha
871 * The combineOp1Alpha to set.
872 * @throws IllegalArgumentException
873 * if combineOp1Alpha is null
875 public void setCombineOp1Alpha(CombinerOperandAlpha combineOp1Alpha) {
876 if (combineOp1Alpha == null) {
877 throw new IllegalArgumentException("invalid CombinerOperandAlpha: null");
879 this.combineOp1Alpha = combineOp1Alpha;
883 * @return Returns the combineOp1RGB.
885 public CombinerOperandRGB getCombineOp1RGB() {
886 return combineOp1RGB;
890 * @param combineOp1RGB
891 * The combineOp1RGB to set.
892 * @throws IllegalArgumentException
893 * if combineOp1RGB is null
895 public void setCombineOp1RGB(CombinerOperandRGB combineOp1RGB) {
896 if (combineOp1RGB == null) {
897 throw new IllegalArgumentException("invalid CombinerOperandRGB: null");
899 this.combineOp1RGB = combineOp1RGB;
903 * @return Returns the combineOp2Alpha.
905 public CombinerOperandAlpha getCombineOp2Alpha() {
906 return combineOp2Alpha;
910 * @param combineOp2Alpha
911 * The combineOp2Alpha to set.
912 * @throws IllegalArgumentException
913 * if combineOp2Alpha is null
915 public void setCombineOp2Alpha(CombinerOperandAlpha combineOp2Alpha) {
916 if (combineOp2Alpha == null) {
917 throw new IllegalArgumentException("invalid CombinerOperandAlpha: null");
919 this.combineOp2Alpha = combineOp2Alpha;
923 * @return Returns the combineOp2RGB.
925 public CombinerOperandRGB getCombineOp2RGB() {
926 return combineOp2RGB;
930 * @param combineOp2RGB
931 * The combineOp2RGB to set.
932 * @throws IllegalArgumentException
933 * if combineOp2RGB is null
935 public void setCombineOp2RGB(CombinerOperandRGB combineOp2RGB) {
936 if (combineOp2RGB == null) {
937 throw new IllegalArgumentException("invalid CombinerOperandRGB: null");
939 this.combineOp2RGB = combineOp2RGB;
943 * @return Returns the combineScaleAlpha.
945 public CombinerScale getCombineScaleAlpha() {
946 return combineScaleAlpha;
950 * @param combineScaleAlpha
951 * The combineScaleAlpha to set.
952 * @throws IllegalArgumentException
953 * if combineScaleAlpha is null
955 public void setCombineScaleAlpha(CombinerScale combineScaleAlpha) {
956 if (combineScaleAlpha == null) {
957 throw new IllegalArgumentException("invalid CombinerScale: null");
959 this.combineScaleAlpha = combineScaleAlpha;
963 * @return Returns the combineScaleRGB.
965 public CombinerScale getCombineScaleRGB() {
966 return combineScaleRGB;
970 * @param combineScaleRGB
971 * The combineScaleRGB to set.
972 * @throws IllegalArgumentException
973 * if combineScaleRGB is null
975 public void setCombineScaleRGB(CombinerScale combineScaleRGB) {
976 if (combineScaleRGB == null) {
977 throw new IllegalArgumentException("invalid CombinerScale: null");
979 this.combineScaleRGB = combineScaleRGB;
983 * @return Returns the combineSrc0Alpha.
985 public CombinerSource getCombineSrc0Alpha() {
986 return combineSrc0Alpha;
990 * @param combineSrc0Alpha
991 * The combineSrc0Alpha to set.
992 * @throws IllegalArgumentException
993 * if combineSrc0Alpha is null
995 public void setCombineSrc0Alpha(CombinerSource combineSrc0Alpha) {
996 if (combineSrc0Alpha == null) {
997 throw new IllegalArgumentException("invalid CombinerSource: null");
999 this.combineSrc0Alpha = combineSrc0Alpha;
1003 * @return Returns the combineSrc0RGB.
1005 public CombinerSource getCombineSrc0RGB() {
1006 return combineSrc0RGB;
1010 * @param combineSrc0RGB
1011 * The combineSrc0RGB to set.
1012 * @throws IllegalArgumentException
1013 * if combineSrc0RGB is null
1015 public void setCombineSrc0RGB(CombinerSource combineSrc0RGB) {
1016 if (combineSrc0RGB == null) {
1017 throw new IllegalArgumentException("invalid CombinerSource: null");
1019 this.combineSrc0RGB = combineSrc0RGB;
1023 * @return Returns the combineSrc1Alpha.
1025 public CombinerSource getCombineSrc1Alpha() {
1026 return combineSrc1Alpha;
1030 * @param combineSrc1Alpha
1031 * The combineSrc1Alpha to set.
1032 * @throws IllegalArgumentException
1033 * if combineSrc1Alpha is null
1035 public void setCombineSrc1Alpha(CombinerSource combineSrc1Alpha) {
1036 if (combineSrc1Alpha == null) {
1037 throw new IllegalArgumentException("invalid CombinerSource: null");
1039 this.combineSrc1Alpha = combineSrc1Alpha;
1043 * @return Returns the combineSrc1RGB.
1045 public CombinerSource getCombineSrc1RGB() {
1046 return combineSrc1RGB;
1050 * @param combineSrc1RGB
1051 * The combineSrc1RGB to set.
1052 * @throws IllegalArgumentException
1053 * if combineSrc1RGB is null
1055 public void setCombineSrc1RGB(CombinerSource combineSrc1RGB) {
1056 if (combineSrc1RGB == null) {
1057 throw new IllegalArgumentException("invalid CombinerSource: null");
1059 this.combineSrc1RGB = combineSrc1RGB;
1063 * @return Returns the combineSrc2Alpha.
1065 public CombinerSource getCombineSrc2Alpha() {
1066 return combineSrc2Alpha;
1070 * @param combineSrc2Alpha
1071 * The combineSrc2Alpha to set.
1072 * @throws IllegalArgumentException
1073 * if combineSrc2Alpha is null
1075 public void setCombineSrc2Alpha(CombinerSource combineSrc2Alpha) {
1076 if (combineSrc2Alpha == null) {
1077 throw new IllegalArgumentException("invalid CombinerSource: null");
1079 this.combineSrc2Alpha = combineSrc2Alpha;
1083 * @return Returns the combineSrc2RGB.
1085 public CombinerSource getCombineSrc2RGB() {
1086 return combineSrc2RGB;
1090 * @param combineSrc2RGB
1091 * The combineSrc2RGB to set.
1092 * @throws IllegalArgumentException
1093 * if combineSrc2RGB is null
1095 public void setCombineSrc2RGB(CombinerSource combineSrc2RGB) {
1096 if (combineSrc2RGB == null) {
1097 throw new IllegalArgumentException("invalid CombinerSource: null");
1099 this.combineSrc2RGB = combineSrc2RGB;
1103 * @return Returns the combineFuncAlpha.
1105 public CombinerFunctionAlpha getCombineFuncAlpha() {
1106 return combineFuncAlpha;
1110 * @param combineFuncAlpha
1111 * The combineFuncAlpha to set.
1112 * @throws IllegalArgumentException
1113 * if combineFuncAlpha is null
1115 public void setCombineFuncAlpha(CombinerFunctionAlpha combineFuncAlpha) {
1116 if (combineFuncAlpha == null) {
1117 throw new IllegalArgumentException("invalid CombinerFunctionAlpha: null");
1119 this.combineFuncAlpha = combineFuncAlpha;
1124 * @throws IllegalArgumentException
1125 * if envMapMode is null
1127 public void setEnvironmentalMapMode(EnvironmentalMapMode envMapMode) {
1128 if (envMapMode == null) {
1129 throw new IllegalArgumentException("invalid EnvironmentalMapMode: null");
1131 this.envMapMode = envMapMode;
1134 public EnvironmentalMapMode getEnvironmentalMapMode() {
1138 public String getImageLocation() {
1139 return imageLocation;
1142 public void setImageLocation(String imageLocation) {
1143 this.imageLocation = imageLocation;
1147 * @return the anisotropic filtering level for this texture as a percentage
1150 public float getAnisotropicFilterPercent() {
1151 return anisotropicFilterPercent;
1156 * the anisotropic filtering level for this texture as a
1157 * percentage (0.0 - 1.0)
1159 public void setAnisotropicFilterPercent(float percent) {
1162 else if (percent < 0.0f)
1164 this.anisotropicFilterPercent = percent;
1167 public boolean equals(Object other) {
1168 if (other == this) {
1171 if (!(other instanceof Texture)) {
1175 Texture that = (Texture) other;
1176 if (this.textureId != that.textureId)
1178 if (this.textureId == 0) {
1179 if (this.getImage() != null
1180 && !this.getImage().equals(that.getImage()))
1182 if (this.getImage() == null && that.getImage() != null)
1184 if (this.getAnisotropicFilterPercent() != that
1185 .getAnisotropicFilterPercent())
1187 if (this.getApply() != that.getApply())
1189 if (this.getCombineFuncAlpha() != that.getCombineFuncAlpha())
1191 if (this.getCombineFuncRGB() != that.getCombineFuncRGB())
1193 if (this.getCombineOp0Alpha() != that.getCombineOp0Alpha())
1195 if (this.getCombineOp1RGB() != that.getCombineOp1RGB())
1197 if (this.getCombineOp2Alpha() != that.getCombineOp2Alpha())
1199 if (this.getCombineOp2RGB() != that.getCombineOp2RGB())
1201 if (this.getCombineScaleAlpha() != that.getCombineScaleAlpha())
1203 if (this.getCombineScaleRGB() != that.getCombineScaleRGB())
1205 if (this.getCombineSrc0Alpha() != that.getCombineSrc0Alpha())
1207 if (this.getCombineSrc0RGB() != that.getCombineSrc0RGB())
1209 if (this.getCombineSrc1Alpha() != that.getCombineSrc1Alpha())
1211 if (this.getCombineSrc1RGB() != that.getCombineSrc1RGB())
1213 if (this.getCombineSrc2Alpha() != that.getCombineSrc2Alpha())
1215 if (this.getCombineSrc2RGB() != that.getCombineSrc2RGB())
1217 if (this.getEnvironmentalMapMode() != that
1218 .getEnvironmentalMapMode())
1220 if (this.getMagnificationFilter() != that.getMagnificationFilter())
1222 if (this.getMinificationFilter() != that.getMinificationFilter())
1224 if (this.getBlendColor() != null
1225 && !this.getBlendColor().equals(that.getBlendColor()))
1227 if (this.getBlendColor() == null && that.getBlendColor() != null)
1233 public abstract Texture createSimpleClone();
1236 * Retreive a basic clone of this Texture (ie, clone everything but the
1237 * image data, which is shared)
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);
1270 rVal.setScale(scale);
1271 if (translation != null)
1272 rVal.setTranslation(translation);
1273 if (rotation != null)
1274 rVal.setRotation(rotation);
1276 rVal.setMatrix(matrix);
1277 if (getTextureKey() != null) {
1278 rVal.setTextureKey(getTextureKey());
1284 * @return Returns the rotation.
1286 public Quaternion getRotation() {
1292 * The rotation to set.
1294 public void setRotation(Quaternion rotation) {
1295 this.rotation = rotation;
1299 * @return the texture matrix set on this texture or null if none is set.
1301 public Matrix4f getMatrix() {
1307 * The matrix to set on this Texture. If null, rotation, scale
1308 * and/or translation will be used.
1310 public void setMatrix(Matrix4f matrix) {
1311 this.matrix = matrix;
1315 * @return Returns the scale.
1317 public Vector3f getScale() {
1325 public void setScale(Vector3f scale) {
1330 * @return Returns the translation.
1332 public Vector3f getTranslation() {
1337 * @param translation
1338 * The translation to set.
1340 public void setTranslation(Vector3f translation) {
1341 this.translation = translation;
1345 * @return Returns the rttSource.
1347 public RenderToTextureType getRTTSource() {
1353 * The rttSource to set.
1354 * @throws IllegalArgumentException
1355 * if rttSource is null
1357 public void setRenderToTextureType(RenderToTextureType rttSource) {
1358 if (rttSource == null) {
1359 throw new IllegalArgumentException("invalid RenderToTextureType: null");
1361 this.rttSource = rttSource;
1365 * @return the estimated footprint of this texture in bytes
1367 public int getMemoryReq() {
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());
1377 if (this.getMinificationFilter().usesMipMapLevels()
1378 || image.hasMipmaps()) {
1379 if (FastMath.isPowerOfTwo(image.getWidth())
1380 && FastMath.isPowerOfTwo(image.getHeight()))
1383 memReq *= 2.0f; // XXX: Is this right?
1388 public void write(JMEExporter e) throws IOException {
1390 OutputCapsule capsule = e.getCapsule(this);
1391 capsule.write(imageLocation, "imageLocation", null);
1393 capsule.write(image, "image", null);
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",
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);
1419 .write(combineSrc1RGB, "combineSrc1RGB",
1420 CombinerSource.Previous);
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);
1444 .write(combineScaleAlpha, "combineScaleAlpha",
1446 if (!storeTexture) {
1447 capsule.write(key, "textureKey", null);
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);
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);
1515 public Class<? extends Texture> getClassTag() {
1516 return this.getClass();
1519 public void setTextureKey(TextureKey tkey) {
1523 public TextureKey getTextureKey() {
1527 public boolean isStoreTexture() {
1528 return storeTexture;
1531 public void setStoreTexture(boolean storeTexture) {
1532 this.storeTexture = storeTexture;
1535 public boolean hasBorder() {
1539 public void setHasBorder(boolean hasBorder) {
1540 this.hasBorder = hasBorder;
1544 * Get the depth texture compare function
1546 * @return The depth texture compare function
1548 public DepthTextureCompareFunc getDepthCompareFunc() {
1549 return depthCompareFunc;
1553 * Set the depth texture compare function
1555 * param depthCompareFunc The depth texture compare function
1557 public void setDepthCompareFunc(DepthTextureCompareFunc depthCompareFunc) {
1558 this.depthCompareFunc = depthCompareFunc;
1562 * Get the depth texture apply mode
1564 * @return The depth texture apply mode
1566 public DepthTextureMode getDepthMode() {
1571 * Set the depth texture apply mode
1573 * param depthMode The depth texture apply mode
1575 public void setDepthMode(DepthTextureMode depthMode) {
1576 this.depthMode = depthMode;
1580 * Get the depth texture compare mode
1582 * @return The depth texture compare mode
1584 public DepthTextureCompareMode getDepthCompareMode() {
1585 return depthCompareMode;
1589 * Set the depth texture compare mode
1591 * @param depthCompareMode The depth texture compare mode
1593 public void setDepthCompareMode(DepthTextureCompareMode depthCompareMode) {
1594 this.depthCompareMode = depthCompareMode;