/* * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. * */ package javax.media.j3d; import java.util.Hashtable; import javax.vecmath.Color4f; import javax.vecmath.Point2f; import javax.vecmath.Point3f; import javax.vecmath.Tuple3f; /** * The Texture object is a component object of an Appearance object * that defines the texture properties used when texture mapping is * enabled. The Texture object is an abstract class and all texture * objects must be created as either a Texture2D object or a * Texture3D object. *

* Each Texture object has the following properties:

*

* *

* Note that as of Java 3D 1.5, the texture width and height are no longer * required to be an exact power of two. However, not all graphics devices * supports non-power-of-two textures. If non-power-of-two texture mapping is * unsupported on a particular Canvas3D, textures with a width or height that * are not an exact power of two are ignored for that canvas. * * @see Canvas3D#queryProperties */ public abstract class Texture extends NodeComponent { /** * Specifies that this Texture object allows reading its * enable flag. */ public static final int ALLOW_ENABLE_READ = CapabilityBits.TEXTURE_ALLOW_ENABLE_READ; /** * Specifies that this Texture object allows writing its * enable flag. */ public static final int ALLOW_ENABLE_WRITE = CapabilityBits.TEXTURE_ALLOW_ENABLE_WRITE; /** * Specifies that this Texture object allows reading its * boundary mode information. */ public static final int ALLOW_BOUNDARY_MODE_READ = CapabilityBits.TEXTURE_ALLOW_BOUNDARY_MODE_READ; /** * Specifies that this Texture object allows reading its * filter information. */ public static final int ALLOW_FILTER_READ = CapabilityBits.TEXTURE_ALLOW_FILTER_READ; /** * Specifies that this Texture object allows reading its * image component information. */ public static final int ALLOW_IMAGE_READ = CapabilityBits.TEXTURE_ALLOW_IMAGE_READ; /** * Specifies that this Texture object allows writing its * image component information. * * @since Java 3D 1.2 */ public static final int ALLOW_IMAGE_WRITE = CapabilityBits.TEXTURE_ALLOW_IMAGE_WRITE; /** * Specifies that this Texture object allows reading its * format information. * * @since Java 3D 1.2 */ public static final int ALLOW_FORMAT_READ = CapabilityBits.TEXTURE_ALLOW_FORMAT_READ; /** * Specifies that this Texture object allows reading its * size information (e.g., width, height, number of mipmap levels, * boundary width). * * @since Java 3D 1.2 */ public static final int ALLOW_SIZE_READ = CapabilityBits.TEXTURE_ALLOW_SIZE_READ; /** * Specifies that this Texture object allows reading its * mipmap mode information. */ public static final int ALLOW_MIPMAP_MODE_READ = CapabilityBits.TEXTURE_ALLOW_MIPMAP_MODE_READ; /** * Specifies that this Texture object allows reading its * boundary color information. */ public static final int ALLOW_BOUNDARY_COLOR_READ = CapabilityBits.TEXTURE_ALLOW_BOUNDARY_COLOR_READ; /** * Specifies that this Texture object allows reading its LOD range * information (e.g., base level, maximum level, minimum lod, * maximum lod, lod offset) * * @since Java 3D 1.3 */ public static final int ALLOW_LOD_RANGE_READ = CapabilityBits.TEXTURE_ALLOW_LOD_RANGE_READ; /** * Specifies that this Texture object allows writing its LOD range * information (e.g., base level, maximum level, minimum lod, * maximum lod, lod offset) * * @since Java 3D 1.3 */ public static final int ALLOW_LOD_RANGE_WRITE = CapabilityBits.TEXTURE_ALLOW_LOD_RANGE_WRITE; /** * Specifies that this Texture object allows reading its anistropic * filter information (e.g., anisotropic mode, anisotropic filter) * * @since Java 3D 1.3 */ public static final int ALLOW_ANISOTROPIC_FILTER_READ = CapabilityBits.TEXTURE_ALLOW_ANISOTROPIC_FILTER_READ; /** * Specifies that this Texture object allows reading its sharpen * texture function information. * * @since Java 3D 1.3 */ public static final int ALLOW_SHARPEN_TEXTURE_READ = CapabilityBits.TEXTURE_ALLOW_SHARPEN_TEXTURE_READ; /** * Specifies that this Texture object allows reading its filter4 * function information. * * @since Java 3D 1.3 */ public static final int ALLOW_FILTER4_READ = CapabilityBits.TEXTURE_ALLOW_FILTER4_READ; /** * Uses the fastest available method for processing geometry. * This value can be used as a parameter to setMinFilter and * setMagFilter. * @see #setMinFilter * @see #setMagFilter */ public static final int FASTEST = 0; /** * Uses the nicest available method for processing geometry. * This value can be used as a parameter to setMinFilter and * setMagFilter. * @see #setMinFilter * @see #setMagFilter */ public static final int NICEST = 1; /** * Select the nearest texel in level 0 texture map. * Maps to NEAREST. * @see #setMinFilter * @see #setMagFilter */ public static final int BASE_LEVEL_POINT = 2; /** * Performs bilinear interpolation on the four nearest texels * in level 0 texture map. * Maps to LINEAR. * @see #setMinFilter * @see #setMagFilter */ public static final int BASE_LEVEL_LINEAR = 3; /** * Selects the nearest texel in the nearest mipmap. * Maps to NEAREST_MIPMAP_NEAREST. * @see #setMinFilter */ public static final int MULTI_LEVEL_POINT = 4; /** * Performs tri-linear interpolation of texels between four * texels each from two nearest mipmap levels. * Maps to LINEAR_MIPMAP_LINEAR, but an implementation can * fall back to LINEAR_MIPMAP_NEAREST or NEAREST_MIPMAP_LINEAR. * @see #setMinFilter */ public static final int MULTI_LEVEL_LINEAR = 5; // NOTE: values 6, 7, and 8 are reserved for the LINEAR_DETAIL* // filter modes in Texture2D /** * Sharpens the resulting image by extrapolating * from the base level plus one image to the base level image of this * texture object. * * @since Java 3D 1.3 * @see #setMagFilter */ public static final int LINEAR_SHARPEN = 9; /** * Performs linear sharpen filter for the rgb * components only. The alpha component is computed using * BASE_LEVEL_LINEAR filter. * * @since Java 3D 1.3 * @see #setMagFilter */ public static final int LINEAR_SHARPEN_RGB = 10; /** * Performs linear sharpen filter for the alpha * component only. The rgb components are computed using * BASE_LEVEL_LINEAR filter. * * @since Java 3D 1.3 * @see #setMagFilter */ public static final int LINEAR_SHARPEN_ALPHA = 11; /** * Applies an application-supplied weight function * on the nearest 4x4 texels in the base level texture image. * * @since Java 3D 1.3 * @see #setMinFilter * @see #setMagFilter */ public static final int FILTER4 = 12; // Texture boundary mode parameter values /** * Clamps texture coordinates to be in the range [0, 1]. * Texture boundary texels or the constant boundary color if boundary * width is 0 will be used for U,V values that fall * outside this range. */ public static final int CLAMP = 2; /** * Repeats the texture by wrapping texture coordinates that are outside * the range [0,1]. Only the fractional portion of the texture * coordinates is used; the integer portion is discarded. */ public static final int WRAP = 3; /** * Clamps texture coordinates such that filtering * will not sample a texture boundary texel. Texels at the edge of the * texture will be used instead. * * @since Java 3D 1.3 */ public static final int CLAMP_TO_EDGE = 4; /** * Clamps texture coordinates such that filtering * will sample only texture boundary texels. If the texture does not * have a boundary, that is the boundary width is equal to 0, then the * constant boundary color will be used.

* * @since Java 3D 1.3 */ public static final int CLAMP_TO_BOUNDARY = 5; /** * Indicates that Texture object only has one level. If multiple * levels are needed, they will be implicitly computed. */ public static final int BASE_LEVEL = 1; /** * Indicates that this Texture object has multiple images, one for * each mipmap level. In this mode, there are * log2(max(width,height))+1 * separate images. */ public static final int MULTI_LEVEL_MIPMAP = 2; // Texture format parameter values /** * Specifies Texture contains only Intensity values. */ public static final int INTENSITY = 1; /** * Specifies Texture contains only luminance values. */ public static final int LUMINANCE = 2; /** * Specifies Texture contains only Alpha values. */ public static final int ALPHA = 3; /** * Specifies Texture contains Luminance and Alpha values. */ public static final int LUMINANCE_ALPHA = 4; /** * Specifies Texture contains Red, Green and Blue color values. */ public static final int RGB = 5; /** * Specifies Texture contains Red, Green, Blue color values * and Alpha value. */ public static final int RGBA = 6; /** * No anisotropic filter. * * @since Java 3D 1.3 * @see #setAnisotropicFilterMode */ public static final int ANISOTROPIC_NONE = 0; /** * Uses the degree of anisotropy in both the minification and * magnification filters. * * @since Java 3D 1.3 * @see #setAnisotropicFilterMode */ public static final int ANISOTROPIC_SINGLE_VALUE = 1; // Array for setting default read capabilities private static final int[] readCapabilities = { ALLOW_ANISOTROPIC_FILTER_READ, ALLOW_BOUNDARY_COLOR_READ, ALLOW_BOUNDARY_MODE_READ, ALLOW_ENABLE_READ, ALLOW_FILTER4_READ, ALLOW_FILTER_READ, ALLOW_FORMAT_READ, ALLOW_IMAGE_READ, ALLOW_LOD_RANGE_READ, ALLOW_MIPMAP_MODE_READ, ALLOW_SHARPEN_TEXTURE_READ, ALLOW_SIZE_READ }; /** * Constructs a Texture object with default parameters. * The default values are as follows: * *

* Note that the default constructor creates a texture object with * a width and height of 0 and is, therefore, not useful. */ public Texture() { // Just use default values // set default read capabilities setDefaultReadCapabilities(readCapabilities); } /** * Constructs an empty Texture object with specified mipMapMode, * format, width and height. Defaults are used for all other * parameters. If mipMapMode is set to * BASE_LEVEL, then the image at level 0 must be set * by the application (using either the setImage or * setImages method). If mipMapMode is * set to MULTI_LEVEL_MIPMAP, then images for levels * Base Level through Maximum Level must be set. * Note that a texture with a non-power-of-two width or height will * only be rendered on a graphics device that supports non-power-of-two * textures. * * @param mipMapMode type of mipmap for this Texture: one of * BASE_LEVEL, MULTI_LEVEL_MIPMAP * @param format data format of Textures saved in this object. * One of INTENSITY, LUMINANCE, ALPHA, LUMINANCE_ALPHA, RGB, RGBA * @param width width of image at level 0. * @param height height of image at level 0. * @exception IllegalArgumentException if width or height are not greater * than 0, or if an invalid format or mipMapMode is specified. */ public Texture(int mipMapMode, int format, int width, int height) { // set default read capabilities setDefaultReadCapabilities(readCapabilities); if ((mipMapMode != BASE_LEVEL) && (mipMapMode != MULTI_LEVEL_MIPMAP)) throw new IllegalArgumentException(J3dI18N.getString("Texture0")); if ((format != INTENSITY) && (format != LUMINANCE) && (format != ALPHA) && (format != LUMINANCE_ALPHA) && (format != RGB) && (format != RGBA)) { throw new IllegalArgumentException(J3dI18N.getString("Texture1")); } if (width < 1) { throw new IllegalArgumentException(J3dI18N.getString("Texture46")); } if (height < 1) { throw new IllegalArgumentException(J3dI18N.getString("Texture47")); } int widthLevels; int heightLevels; widthLevels = getLevelsNPOT(width); heightLevels = getLevelsNPOT(height); ((TextureRetained)this.retained).initialize(format, width, widthLevels, height, heightLevels, mipMapMode, 0); } /** * Constructs an empty Texture object with specified mipMapMode, * format, width, height, and boundaryWidth. * Defaults are used for all other * parameters. If mipMapMode is set to * BASE_LEVEL, then the image at level 0 must be set * by the application (using either the setImage or * setImages method). If mipMapMode is * set to MULTI_LEVEL_MIPMAP, then images for levels * Base Level through Maximum Level must be set. * Note that a texture with a non-power-of-two width or height will * only be rendered on a graphics device that supports non-power-of-two * textures. * * @param mipMapMode type of mipmap for this Texture: one of * BASE_LEVEL, MULTI_LEVEL_MIPMAP * @param format data format of Textures saved in this object. * One of INTENSITY, LUMINANCE, ALPHA, LUMINANCE_ALPHA, RGB, RGBA * @param width width of image at level 0. This * does not include the width of the boundary. * @param height height of image at level 0. This * does not include the width of the boundary. * @param boundaryWidth width of the boundary, which must be 0 or 1. * @exception IllegalArgumentException if width or height are not greater * than 0, if an invalid format or mipMapMode is specified, or * if the boundaryWidth is < 0 or > 1 * * @since Java 3D 1.3 */ public Texture(int mipMapMode, int format, int width, int height, int boundaryWidth) { // set default read capabilities setDefaultReadCapabilities(readCapabilities); if ((mipMapMode != BASE_LEVEL) && (mipMapMode != MULTI_LEVEL_MIPMAP)) throw new IllegalArgumentException(J3dI18N.getString("Texture0")); if ((format != INTENSITY) && (format != LUMINANCE) && (format != ALPHA) && (format != LUMINANCE_ALPHA) && (format != RGB) && (format != RGBA)) { throw new IllegalArgumentException(J3dI18N.getString("Texture1")); } if (width < 1) { throw new IllegalArgumentException(J3dI18N.getString("Texture46")); } if (height < 1) { throw new IllegalArgumentException(J3dI18N.getString("Texture47")); } int widthLevels; int heightLevels; widthLevels = getLevelsNPOT(width); heightLevels = getLevelsNPOT(height); if (boundaryWidth < 0 || boundaryWidth > 1) throw new IllegalArgumentException(J3dI18N.getString("Texture30")); ((TextureRetained)this.retained).initialize(format, width, widthLevels, height, heightLevels, mipMapMode, boundaryWidth); } /** * Sets the boundary mode for the S coordinate in this texture object. * @param boundaryModeS the boundary mode for the S coordinate. * One of: CLAMP, WRAP, CLAMP_TO_EDGE, or CLAMP_TO_BOUNDARY. * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * @exception IllegalArgumentException if boundaryModeS * is a value other than CLAMP, WRAP, * CLAMP_TO_EDGE, or CLAMP_TO_BOUNDARY. */ public void setBoundaryModeS(int boundaryModeS) { checkForLiveOrCompiled(); switch (boundaryModeS) { case Texture.CLAMP: case Texture.WRAP: case Texture.CLAMP_TO_EDGE: case Texture.CLAMP_TO_BOUNDARY: break; default: throw new IllegalArgumentException(J3dI18N.getString("Texture31")); } ((TextureRetained)this.retained).initBoundaryModeS(boundaryModeS); } /** * Retrieves the boundary mode for the S coordinate. * @return the current boundary mode for the S coordinate. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public int getBoundaryModeS() { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_BOUNDARY_MODE_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture4")); return ((TextureRetained)this.retained).getBoundaryModeS(); } /** * Sets the boundary mode for the T coordinate in this texture object. * @param boundaryModeT the boundary mode for the T coordinate. * One of: CLAMP, WRAP, CLAMP_TO_EDGE, or CLAMP_TO_BOUNDARY. * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * @exception IllegalArgumentException if boundaryModeT * is a value other than CLAMP, WRAP, * CLAMP_TO_EDGE, or CLAMP_TO_BOUNDARY. */ public void setBoundaryModeT(int boundaryModeT) { checkForLiveOrCompiled(); switch (boundaryModeT) { case Texture.CLAMP: case Texture.WRAP: case Texture.CLAMP_TO_EDGE: case Texture.CLAMP_TO_BOUNDARY: break; default: throw new IllegalArgumentException(J3dI18N.getString("Texture31")); } ((TextureRetained)this.retained).initBoundaryModeT(boundaryModeT); } /** * Retrieves the boundary mode for the T coordinate. * @return the current boundary mode for the T coordinate. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public int getBoundaryModeT() { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_BOUNDARY_MODE_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture4")); return ((TextureRetained)this.retained).getBoundaryModeT(); } /** * Sets the minification filter function. This * function is used when the pixel being rendered maps to an area * greater than one texel. * @param minFilter the minification filter. One of: * FASTEST, NICEST, BASE_LEVEL_POINT, BASE_LEVEL_LINEAR, * MULTI_LEVEL_POINT, MULTI_LEVEL_LINEAR, or FILTER4 * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * @exception IllegalArgumentException if minFilter * is a value other than FASTEST, NICEST, * BASE_LEVEL_POINT, BASE_LEVEL_LINEAR, * MULTI_LEVEL_POINT, MULTI_LEVEL_LINEAR, or * FILTER4. * * @see Canvas3D#queryProperties */ public void setMinFilter(int minFilter) { checkForLiveOrCompiled(); switch (minFilter) { case FASTEST: case NICEST: case BASE_LEVEL_POINT: case BASE_LEVEL_LINEAR: case MULTI_LEVEL_POINT: case MULTI_LEVEL_LINEAR: case FILTER4: break; default: throw new IllegalArgumentException(J3dI18N.getString("Texture28")); } ((TextureRetained)this.retained).initMinFilter(minFilter); } /** * Retrieves the minification filter. * @return the current minification filter function. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public int getMinFilter() { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_FILTER_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture6")); return ((TextureRetained)this.retained).getMinFilter(); } /** * Sets the magnification filter function. This * function is used when the pixel being rendered maps to an area * less than or equal to one texel. * @param magFilter the magnification filter, one of: * FASTEST, NICEST, BASE_LEVEL_POINT, BASE_LEVEL_LINEAR, * LINEAR_SHARPEN, LINEAR_SHARPEN_RGB, LINEAR_SHARPEN_ALPHA, or FILTER4. * * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * @exception IllegalArgumentException if magFilter * is a value other than FASTEST, NICEST, * BASE_LEVEL_POINT, BASE_LEVEL_LINEAR, * LINEAR_SHARPEN, LINEAR_SHARPEN_RGB, * LINEAR_SHARPEN_ALPHA, or * FILTER4. * * @see Canvas3D#queryProperties */ public void setMagFilter(int magFilter) { checkForLiveOrCompiled(); switch (magFilter) { case FASTEST: case NICEST: case BASE_LEVEL_POINT: case BASE_LEVEL_LINEAR: case LINEAR_SHARPEN: case LINEAR_SHARPEN_RGB: case LINEAR_SHARPEN_ALPHA: case FILTER4: break; default: throw new IllegalArgumentException(J3dI18N.getString("Texture29")); } ((TextureRetained)this.retained).initMagFilter(magFilter); } /** * Retrieves the magnification filter. * @return the current magnification filter function. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public int getMagFilter() { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_FILTER_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture6")); return ((TextureRetained)this.retained).getMagFilter(); } /** * Sets the image for a specified mipmap level. Note that the image size * must be the correct size for the specified mipmap level. The image size * of the base level image, that is level 0, must be the same size * in each dimension (width, height, depth) as this * texture, excluding the border, if any. * Each successive mipmap level must be 1/2 the size of the previous level, * such that size[n] = floor(size[n-1]/2), exluding * the border. * * @param level mipmap level to set: 0 is the base level * @param image ImageComponent object containing the texture image * for the specified mipmap level * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @exception IllegalArgumentException if an ImageComponent3D is * used in a Texture2D object or if an ImageComponent2D is used in a * Texture3D object. * * @exception IllegalArgumentException if the image being set at this * level is not the correct size for this level. * * @exception IllegalSharingException if this Texture is live and * the specified image is being used by a Canvas3D as an off-screen buffer. * * @exception IllegalSharingException if this Texture is * being used by an immediate mode context and * the specified image is being used by a Canvas3D as an off-screen buffer. */ public void setImage(int level, ImageComponent image) { if (isLiveOrCompiled()) { if(!this.getCapability(ALLOW_IMAGE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("Texture15")); } // Do illegal sharing check validateImageIllegalSharing(image); if (isLive()) ((TextureRetained)this.retained).setImage(level, image); else ((TextureRetained)this.retained).initImage(level, image); } /** * Retrieves the image for a specified mipmap level. * @param level mipmap level to get: 0 is the base level * @return the ImageComponent object containing the texture image at * the specified mipmap level. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public ImageComponent getImage(int level) { if (isLiveOrCompiled()) { if(!this.getCapability(ALLOW_IMAGE_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture9")); } return ((TextureRetained)this.retained).getImage(level); } /** * Sets the array of images for all mipmap levels. Note that the image size * of the base level image, images[0], must be the same size * in each dimension (width, height, depth) as this * texture, excluding the border, if any. * Each successive mipmap level must be 1/2 the size of the previous level, * such that size[n] = floor(size[n-1]/2), exluding * the border. * * @param images array of ImageComponent objects * containing the texture images for all mipmap levels * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @exception IllegalArgumentException if an ImageComponent3D is * used in a Texture2D object or if an ImageComponent2D is used in a * Texture3D object. * * @exception IllegalArgumentException if images.length is * not equal to the total number of mipmap levels. * * @exception IllegalArgumentException if the size of each dimension * of the image at a given level in the * images array is not the correct size. * * @exception IllegalSharingException if this Texture is live and * any of the specified images are being used by a Canvas3D as an * off-screen buffer. * * @exception IllegalSharingException if this Texture is * being used by an immediate mode context and * any of the specified images are being used by a Canvas3D as an * off-screen buffer. * * @since Java 3D 1.2 */ public void setImages(ImageComponent[] images) { if (isLiveOrCompiled()) { if(!this.getCapability(ALLOW_IMAGE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("Texture15")); } // Do illegal sharing check for(int i=0; imipMapMode is * MULTI_LEVEL_MIPMAP; otherwise it returns 1. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.2 */ public int numMipMapLevels() { if (isLiveOrCompiled()) { if(!this.getCapability(ALLOW_SIZE_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture18")); } return ((TextureRetained)this.retained).numMipMapLevels(); } /** * Sets mipmap mode for texture mapping for this texture object. * @param mipMapMode the new mipmap mode for this object. One of: * BASE_LEVEL or MULTI_LEVEL_MIPMAP. * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * @exception IllegalArgumentException if mipMapMode * is a value other than BASE_LEVEL or * MULTI_LEVEL_MIPMAP. */ public void setMipMapMode(int mipMapMode) { checkForLiveOrCompiled(); ((TextureRetained)this.retained).initMipMapMode(mipMapMode); } /** * Retrieves current mipmap mode. * @return current mipmap mode of this texture object. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public int getMipMapMode() { if (isLiveOrCompiled()) if(!this.getCapability(ALLOW_MIPMAP_MODE_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture10")); return ((TextureRetained)this.retained).getMipMapMode(); } /** * Enables or disables texture mapping for this * appearance component object. * @param state true or false to enable or disable texture mapping * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public void setEnable(boolean state) { if (isLiveOrCompiled()) { if(!this.getCapability(ALLOW_ENABLE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("Texture11")); } if (isLive()) ((TextureRetained)this.retained).setEnable(state); else ((TextureRetained)this.retained).initEnable(state); } /** * Retrieves the state of the texture enable flag. * @return true if texture mapping is enabled, * false if texture mapping is disabled * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public boolean getEnable() { if (isLiveOrCompiled()) { if(!this.getCapability(ALLOW_ENABLE_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture12")); } return ((TextureRetained)this.retained).getEnable(); } // Internal j3d usage method // Returns n if num is 2**n // Returns -1 if num is 0 or negative or if // num is NOT power of 2. // NOTE: ********** Assumes 32 bit integer****************** static int getPowerOf2(int num) { int i, tmp; // Can only handle positive numbers, return error. if (num < 1) return -1; for (i=0, tmp = num; i < 32;i++) { // Check if leftmost bit is 1 if ((tmp & 0x80000000) != 0) { //Check if any other bit is 1 if ((tmp & 0x7fffffff) == 0) return 31-i;//valid power of 2 integer else return -1;//invalid non-power-of-2 integer } tmp <<= 1; } //Can't reach here because we have already checked for 0 return -1; } // returns number of levels using NPOT rules for mipmap generation // which say that each level should be floor(size/2) of previous level static int getLevelsNPOT(int num) { int tmp, levels = 0; tmp = num; while (tmp > 1) { tmp = tmp / 2; levels++; } return levels; } /** * Sets the texture boundary color for this texture object. The * texture boundary color is used when boundaryModeS or boundaryModeT * is set to CLAMP or CLAMP_TO_BOUNDARY and if texture boundary is not * specified. * @param boundaryColor the new texture boundary color. * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. */ public void setBoundaryColor(Color4f boundaryColor) { checkForLiveOrCompiled(); ((TextureRetained)this.retained).initBoundaryColor(boundaryColor); } /** * Sets the texture boundary color for this texture object. The * texture boundary color is used when boundaryModeS or boundaryModeT * is set to CLAMP or CLAMP_TO_BOUNDARY and if texture boundary is not * specified. * @param r the red component of the color. * @param g the green component of the color. * @param b the blue component of the color. * @param a the alpha component of the color. * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. */ public void setBoundaryColor(float r, float g, float b, float a) { checkForLiveOrCompiled(); ((TextureRetained)this.retained).initBoundaryColor(r, g, b, a); } /** * Retrieves the texture boundary color for this texture object. * @param boundaryColor the vector that will receive the * current texture boundary color. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ public void getBoundaryColor(Color4f boundaryColor) { if (isLiveOrCompiled()) { if(!this.getCapability(ALLOW_BOUNDARY_COLOR_READ)) throw new CapabilityNotSetException(J3dI18N.getString("Texture13")); } ((TextureRetained)this.retained).getBoundaryColor(boundaryColor); } /** * Specifies the base level for this texture object. * @param baseLevel index of the lowest defined mipmap level. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * @exception IllegalArgumentException if specified baseLevel < 0, or * if baseLevel > maximumLevel * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setBaseLevel(int baseLevel) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_WRITE)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture32")); } } if (isLive()) { ((TextureRetained)this.retained).setBaseLevel(baseLevel); } else { ((TextureRetained)this.retained).initBaseLevel(baseLevel); } } /** * Retrieves the base level for this texture object. * @return base level for this texture object. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public int getBaseLevel() { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture34")); } } return ((TextureRetained)this.retained).getBaseLevel(); } /** * Specifies the maximum level for this texture object. * @param maximumLevel index of the highest defined mipmap level. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * @exception IllegalArgumentException if specified * maximumLevel < baseLevel, or * if maximumLevel > log2(max(width,height)) * @exception IllegalArgumentException if mipMipMapMode is equal to BASE_LEVEL * and maximumLevel is not equal to zero. * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setMaximumLevel(int maximumLevel) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_WRITE)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture33")); } } if (isLive()) { ((TextureRetained)this.retained).setMaximumLevel(maximumLevel); } else { ((TextureRetained)this.retained).initMaximumLevel(maximumLevel); } } /** * Retrieves the maximum level for this texture object. * @return maximum level for this texture object. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public int getMaximumLevel() { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture35")); } } return ((TextureRetained)this.retained).getMaximumLevel(); } /** * Specifies the minimum level-of-detail for this texture object. * @param minimumLod the minimum level-of-detail. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * @exception IllegalArgumentException if specified lod > maximum lod * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setMinimumLOD(float minimumLod) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_WRITE)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture38")); } } if (isLive()) { ((TextureRetained)this.retained).setMinimumLOD(minimumLod); } else { ((TextureRetained)this.retained).initMinimumLOD(minimumLod); } } /** * Retrieves the minimum level-of-detail for this texture object. * @return the minimum level-of-detail * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public float getMinimumLOD() { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture40")); } } return ((TextureRetained)this.retained).getMinimumLOD(); } /** * Specifies the maximum level-of-detail for this texture object. * @param maximumLod the maximum level-of-detail. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * @exception IllegalArgumentException if specified lod < minimum lod * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setMaximumLOD(float maximumLod) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_WRITE)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture39")); } } if (isLive()) { ((TextureRetained)this.retained).setMaximumLOD(maximumLod); } else { ((TextureRetained)this.retained).initMaximumLOD(maximumLod); } } /** * Retrieves the maximum level-of-detail for this texture object. * @return the maximum level-of-detail * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public float getMaximumLOD() { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture41")); } } return ((TextureRetained)this.retained).getMaximumLOD(); } /** * Specifies the LOD offset for this texture object. * @param s the s component of the LOD offset * @param t the t component of the LOD offset * @param r the r component of the LOD offset * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setLodOffset(float s, float t, float r) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_WRITE)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture44")); } } if (isLive()) { ((TextureRetained)this.retained).setLodOffset(s, t, r); } else { ((TextureRetained)this.retained).initLodOffset(s, t, r); } } /** * Specifies the LOD offset for this texture object. * @param offset the LOD offset * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setLodOffset(Tuple3f offset) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_WRITE)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture44")); } } if (isLive()) { ((TextureRetained)this.retained).setLodOffset( offset.x, offset.y, offset.z); } else { ((TextureRetained)this.retained).initLodOffset( offset.x, offset.y, offset.z); } } /** * Retrieves the LOD offset for this texture object. * @param offset the vector that will receive the * current LOD offset. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public void getLodOffset(Tuple3f offset) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_LOD_RANGE_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture45")); } } ((TextureRetained)this.retained).getLodOffset(offset); } /** * Specifies the anisotropic filter mode for this texture object. * @param mode the anisotropic filter mode. One of * ANISOTROPIC_NONE or ANISOTROPIC_SINGLE_VALUE. * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * @exception IllegalArgumentException if * mode is a value other than * ANISOTROPIC_NONE or ANISOTROPIC_SINGLE_VALUE * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setAnisotropicFilterMode(int mode) { checkForLiveOrCompiled(); if ((mode != ANISOTROPIC_NONE) && (mode != ANISOTROPIC_SINGLE_VALUE)) { throw new IllegalArgumentException( J3dI18N.getString("Texture25")); } ((TextureRetained)this.retained).initAnisotropicFilterMode(mode); } /** * Retrieves the anisotropic filter mode for this texture object. * @return the currrent anisotropic filter mode of this texture object. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public int getAnisotropicFilterMode() { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_ANISOTROPIC_FILTER_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture26")); } } return ((TextureRetained)this.retained).getAnisotropicFilterMode(); } /** * Specifies the degree of anisotropy to be * used when the anisotropic filter mode specifies * ANISOTROPIC_SINGLE_VALUE. * @param degree degree of anisotropy * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * @exception IllegalArgumentException if * degree < 1.0 or * degree > the maximum degree of anisotropy. * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setAnisotropicFilterDegree(float degree) { checkForLiveOrCompiled(); if (degree < 1.0) { throw new IllegalArgumentException( J3dI18N.getString("Texture27")); } ((TextureRetained)this.retained).initAnisotropicFilterDegree(degree); } /** * Retrieves the anisotropic filter degree for this texture object. * @return the current degree of anisotropy of this texture object * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public float getAnisotropicFilterDegree() { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_ANISOTROPIC_FILTER_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture26")); } } return ((TextureRetained)this.retained).getAnisotropicFilterDegree(); } /** * sets the sharpen texture LOD function for this texture object. * @param lod array containing the level-of-detail values. * @param pts array containing the function values for the corresponding * level-of-detail values. * * @exception IllegalStateException if the length of lod * does not match the length of pts * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setSharpenTextureFunc(float[] lod, float[] pts) { checkForLiveOrCompiled(); if (((lod != null) && (pts != null) && (lod.length == pts.length)) || ((lod == null) && (pts == null))) { ((TextureRetained)this.retained).initSharpenTextureFunc(lod, pts); } else { throw new IllegalStateException( J3dI18N.getString("Texture22")); } } /** * sets the sharpen texture LOD function for this texture object. * The Point2f x,y values are defined as follows: x is the lod value, * y is the corresponding function value. * * @param pts array of Point2f containing the lod as well as the * corresponding function value. * * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setSharpenTextureFunc(Point2f[] pts) { checkForLiveOrCompiled(); ((TextureRetained)this.retained).initSharpenTextureFunc(pts); } /** * Gets the number of points in the sharpen texture LOD function for this * texture object. * * @return the number of points in the sharpen texture LOD function. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public int getSharpenTextureFuncPointsCount() { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_SHARPEN_TEXTURE_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture21")); } } return ((TextureRetained)this.retained).getSharpenTextureFuncPointsCount(); } /** * Copies the array of sharpen texture LOD function points into the * specified arrays. The arrays must be large enough to hold all the * points. * * @param lod the array to receive the level-of-detail values. * @param pts the array to receive the function values for the * corresponding level-of-detail values. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public void getSharpenTextureFunc(float[] lod, float[] pts) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_SHARPEN_TEXTURE_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture21")); } } ((TextureRetained)this.retained).getSharpenTextureFunc( lod, pts); } /** * Copies the array of sharpen texture LOD function points including * the lod values and the corresponding function values into the * specified array. The array must be large enough to hold all the points. * The individual array elements must be allocated by the caller as well. * * @param pts the array to receive the sharpen texture LOD function points * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public void getSharpenTextureFunc(Point2f[] pts) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_SHARPEN_TEXTURE_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture21")); } } ((TextureRetained)this.retained).getSharpenTextureFunc(pts); } /** * sets the filter4 function for this texture object. * @param weights array containing samples of the filter4 function. * * @exception IllegalArgumentException if the length of * weight < 4 * @exception RestrictedAccessException if the method is called * when this object is part of live or compiled scene graph. * * @since Java 3D 1.3 * @see Canvas3D#queryProperties */ public void setFilter4Func(float[] weights) { checkForLiveOrCompiled(); if ((weights == null) || (weights.length < 4)) { throw new IllegalArgumentException( J3dI18N.getString("Texture24")); } else { ((TextureRetained)this.retained).initFilter4Func(weights); } } /** * Retrieves the number of filter4 function values for this * texture object. * * @return the number of filter4 function values * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public int getFilter4FuncPointsCount() { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_FILTER4_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture23")); } } return (((TextureRetained)this.retained).getFilter4FuncPointsCount()); } /** * Copies the array of filter4 function values into the specified * array. The array must be large enough to hold all the values. * * @param weights the array to receive the function values. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @since Java 3D 1.3 */ public void getFilter4Func(float[] weights) { if (isLiveOrCompiled()) { if (!this.getCapability(ALLOW_FILTER4_READ)) { throw new CapabilityNotSetException( J3dI18N.getString("Texture23")); } } ((TextureRetained)this.retained).getFilter4Func(weights); } /** * Copies all node information from originalNodeComponent * into the current node. This method is called from the * duplicateNode method. This routine does * the actual duplication of all "local data" (any data defined in * this object). * * @param originalNodeComponent the original node to duplicate. * @param forceDuplicate when set to true, causes the * duplicateOnCloneTree flag to be ignored. When * false, the value of each node's * duplicateOnCloneTree variable determines whether * NodeComponent data is duplicated or copied. * * @see Node#cloneTree * @see NodeComponent#setDuplicateOnCloneTree */ @Override void duplicateAttributes(NodeComponent originalNodeComponent, boolean forceDuplicate) { super.duplicateAttributes(originalNodeComponent, forceDuplicate); Hashtable hashtable = originalNodeComponent.nodeHashtable; TextureRetained tex = (TextureRetained) originalNodeComponent.retained; TextureRetained rt = (TextureRetained) retained; rt.initBoundaryModeS(tex.getBoundaryModeS()); rt.initBoundaryModeT(tex.getBoundaryModeT()); rt.initMinFilter(tex.getMinFilter()); rt.initMagFilter(tex.getMagFilter()); rt.initMipMapMode(tex.getMipMapMode()); rt.initEnable(tex.getEnable()); rt.initAnisotropicFilterMode(tex.getAnisotropicFilterMode()); rt.initAnisotropicFilterDegree(tex.getAnisotropicFilterDegree()); rt.initSharpenTextureFunc(tex.getSharpenTextureFunc()); rt.initFilter4Func(tex.getFilter4Func()); rt.initBaseLevel(tex.getBaseLevel()); rt.initMaximumLevel(tex.getMaximumLevel()); rt.initMinimumLOD(tex.getMinimumLOD()); rt.initMaximumLOD(tex.getMaximumLOD()); Point3f offset = new Point3f(); tex.getLodOffset(offset); rt.initLodOffset(offset.x, offset.y, offset.z); Color4f c = new Color4f(); tex.getBoundaryColor(c); rt.initBoundaryColor(c); // No API available to get the current level for (int i=tex.maxLevels-1; i>=0; i-- ) { ImageComponent image = (ImageComponent) getNodeComponent(tex.getImage(i), forceDuplicate, hashtable); if (image != null) { rt.initImage(i, image); } } // XXXX: clone new v1.2 attributes? // NOTE: This sppears to have already been done } /** * This function is called from getNodeComponent() to see if any of * the sub-NodeComponents duplicateOnCloneTree flag is true. * If it is the case, current NodeComponent needs to * duplicate also even though current duplicateOnCloneTree flag is false. * This should be overwrite by NodeComponent which contains sub-NodeComponent. */ @Override boolean duplicateChild() { if (getDuplicateOnCloneTree()) return true; int level = ((TextureRetained) this.retained).maxLevels; TextureRetained rt = (TextureRetained) retained; for (int i=0; i < level; i++) { ImageComponent img = rt.getImage(i); if ((img != null) && img.getDuplicateOnCloneTree()) return true; } return false; } }