/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.scenegraph; import org.openmali.types.twodee.Dim2i; import org.openmali.types.twodee.Sized2iRO; import org.jagatoo.loaders.textures.AbstractTextureImage; import org.jagatoo.opengl.enums.TextureImageFormat; import org.jagatoo.opengl.enums.TextureImageInternalFormat; import org.xith3d.render.CanvasPeer; import org.xith3d.utility.logging.X3DLog; /** * {@link TextureImage} defines attributes that apply to one * mipmap-level of a {@link Texture}. * * @author David Yazel * @author Marvin Froehlich (aka Qudus) */ public abstract class TextureImage extends NodeComponent implements AbstractTextureImage { /** * The image data format. */ private final TextureImageFormat format; /** * The desired image format for the graphics card. This is only a hint. */ private TextureImageInternalFormat internalFormat; /** * The image's size. */ private final Dim2i size = new Dim2i(); /** * The image's original size (before scaling to powers of two). */ private final Dim2i orgSize = new Dim2i(); private boolean hasData = true; protected void setHasData( boolean hasData ) { this.hasData = hasData; } public final boolean hasData() { return ( hasData ); } /** * Get the image format. This is the format in which the data is specified. */ public final TextureImageFormat getFormat() { return ( format ); } /** * @return true if the {@link TextureImage} contains explicit alpha data. * This does not count for compressed formats. */ public final boolean hasAlpha() { return ( getFormat().hasAlpha() ); } /** * @return true if the {@link TextureImage} contains compressed data. */ public final boolean isCompressed() { return ( getFormat().isCompressed() ); } /** * Sets the desired internal format. Setting a internal format that is incompatible * is no error, this method ensures that the internal format is always compatible * with the data format. * * @param internalFormat */ public final void setInternalFormat( TextureImageInternalFormat internalFormat ) { switch ( format ) { case INTENSITY: switch ( internalFormat ) { case INTENSITY: case INTENSITY4: case INTENSITY8: this.internalFormat = internalFormat; break; default: this.internalFormat = TextureImageInternalFormat.INTENSITY; } break; case LUMINANCE: switch ( internalFormat ) { case LUMINANCE: case LUMINANCE4: case LUMINANCE8: this.internalFormat = internalFormat; break; default: this.internalFormat = TextureImageInternalFormat.LUMINANCE; } break; case ALPHA: switch ( internalFormat ) { case ALPHA: case ALPHA4: case ALPHA8: this.internalFormat = internalFormat; break; default: this.internalFormat = TextureImageInternalFormat.ALPHA; } break; case LUMINANCE_ALPHA: switch ( internalFormat ) { case LUM_ALPHA: case LUM4_ALPHA4: case LUM8_ALPHA8: this.internalFormat = internalFormat; break; default: this.internalFormat = TextureImageInternalFormat.LUM_ALPHA; } break; case RGB: switch ( internalFormat ) { case RGB: case RGB4: case RGB5: case RGB8: case R3_G3_B2: case RGB_DXT1: case RGBA_DXT1: case RGBA_DXT3: case RGBA_DXT5: this.internalFormat = internalFormat; break; default: this.internalFormat = TextureImageInternalFormat.RGB; } break; case RGBA: switch ( internalFormat ) { case RGBA: case RGBA4: case RGB5_A1: case RGBA8: case RGBA_DXT1: case RGBA_DXT3: case RGBA_DXT5: this.internalFormat = internalFormat; break; default: this.internalFormat = TextureImageInternalFormat.RGBA; } break; case RGB_DXT1: this.internalFormat = TextureImageInternalFormat.RGB_DXT1; break; case RGBA_DXT1: this.internalFormat = TextureImageInternalFormat.RGBA_DXT1; break; case RGBA_DXT3: this.internalFormat = TextureImageInternalFormat.RGBA_DXT3; break; case RGBA_DXT5: this.internalFormat = TextureImageInternalFormat.RGBA_DXT5; break; case DEPTH: if ( internalFormat != null ) { switch ( internalFormat ) { case DEPTH16: case DEPTH24: case DEPTH32: this.internalFormat = internalFormat; break; default: this.internalFormat = TextureImageInternalFormat.DEPTH24; } } else { this.internalFormat = null; } break; default: throw new IllegalArgumentException( "Invalid data format: " + format ); } } /** * Get the internal image format. This is a format hint for the graphic driver. */ public final TextureImageInternalFormat getInternalFormat() { return ( internalFormat ); } /** * @return true if the image should be stroed in compressed form on the graphics card. */ public final boolean isInternalFormatCompressed() { return ( getInternalFormat().isCompressed() ); } protected void setSize( int width, int height ) { this.size.set( width, height ); } /** * @return the image's size. */ public final Sized2iRO getSize() { return ( size ); } /** * @return the image's width. */ public final int getWidth() { return ( size.getWidth() ); } /** * @return the image's height. */ public final int getHeight() { return ( size.getHeight() ); } protected void setOriginalSize( int orgWidth, int orgHeight ) { this.orgSize.set( orgWidth, orgHeight ); } /** * @return the image's original size (before scaling to powers of two). */ public Sized2iRO getOriginalSize() { return ( orgSize ); } /** * @return the image's original width (before scaling to powers of two). */ public int getOriginalWidth() { return ( orgSize.getWidth() ); } /** * @return the image's original height (before scaling to powers of two). */ public int getOriginalHeight() { return ( orgSize.getHeight() ); } protected final int calculateNeededImageSize() { int sizeMultiplier = 0; switch ( format ) { case RGB_DXT1: case RGBA_DXT1: // DXT1 has a block size of 8 and 4x4 pixel blocks return ( ( ( getWidth() + 3 ) / 4 ) * ( ( getHeight() + 3 ) / 4 ) * 8 ); case RGBA_DXT3: case RGBA_DXT5: // DXT3 & DXT5 have a block sizes of 16 and 4x4 pixel blocks return ( ( ( getWidth() + 3 ) / 4 ) * ( ( getHeight() + 3 ) / 4 ) * 16 ); case RGB: //each pixel contains three eight bit channels, one each for red, green and blue. sizeMultiplier = 3; break; case RGBA: // each pixel contains four eight bit channels, one each for red, green, blue and alpha. sizeMultiplier = 4; break; case LUMINANCE_ALPHA: // each pixel contains two eight bit channels, one each for luminance and alpha. sizeMultiplier = 2; break; case ALPHA: case INTENSITY: case LUMINANCE: // each pixel contains one eight bit channel, the channel can be luminance, alpha or intensity. sizeMultiplier = 1; break; case DEPTH: //each pixel contains 24 bit depth. sizeMultiplier = 3; break; default: X3DLog.exception( "TextureImage2D.setImage(): The image object contains a value, ", format, ", in the format that is unknown." ); break; } return ( sizeMultiplier * getWidth() * getHeight() ); } /** * {@inheritDoc} */ @Override public void freeOpenGLResources( CanvasPeer canvasPeer ) { } public TextureImage( TextureImageFormat format, int width, int height, int orgWidth, int orgHeight, TextureImageInternalFormat internalFormat ) { super( false ); this.format = format; this.size.set( width, height ); this.orgSize.set( orgWidth, orgHeight ); setInternalFormat( internalFormat ); } /** * Constructs a new {@link TextureImage} object. */ public TextureImage( TextureImageFormat format, int width, int height, int orgWidth, int orgHeight ) { // just a dummy internal format, will be automatically corrected by setInternalFormat() this( format, width, height, orgWidth, orgHeight, TextureImageInternalFormat.getFallbackInternalFormat( format ) ); } }