/**
* Copyright 2014 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.util.texture;
import java.io.IOException;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import javax.media.opengl.GL;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import com.jogamp.common.util.IOUtil;
/**
* Simple {@link TextureSequence} implementation
* allowing {@link #addFrame(GL, Texture) existing textures}
* or {@link #addFrame(GL, Class, String, String) image streams}
* to be used and replayed as {@link TextureSequence.TextureFrame frames}.
*/
public class ImageSequence implements TextureSequence {
private final int textureUnit;
private final boolean useBuildInTexLookup;
private final List frames = new ArrayList();
private final int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST };
private final int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE };
private volatile int frameIdx = 0;
private volatile boolean manualStepping = false;
private int textureFragmentShaderHashCode = 0;
public ImageSequence(final int textureUnit, final boolean useBuildInTexLookup) {
this.textureUnit = textureUnit;
this.useBuildInTexLookup = useBuildInTexLookup;
}
public void setParams(final int magFilter, final int minFilter, final int wrapS, final int wrapT) {
texMinMagFilter[0] = minFilter;
texMinMagFilter[1] = magFilter;
texWrapST[0] = wrapS;
texWrapST[1] = wrapT;
}
public final void addFrame(final GL gl, final Texture tex) {
final TextureSequence.TextureFrame frame = new TextureSequence.TextureFrame(tex);
frames.add(frame);
tex.bind(gl);
gl.glTexParameteri(getTextureTarget(), GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]);
gl.glTexParameteri(getTextureTarget(), GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]);
gl.glTexParameteri(getTextureTarget(), GL.GL_TEXTURE_WRAP_S, texWrapST[0]);
gl.glTexParameteri(getTextureTarget(), GL.GL_TEXTURE_WRAP_T, texWrapST[1]);
}
public final void addFrame(final GL gl, final Class> context, final String imageResourcePath, final String imageSuffix) throws IOException {
final URLConnection urlConn = IOUtil.getResource(context, imageResourcePath);
if(null != urlConn) {
final TextureData texData = TextureIO.newTextureData(GLProfile.getGL2ES2(), urlConn.getInputStream(), false, imageSuffix);
final Texture tex = new Texture(getTextureTarget());
tex.updateImage(gl, texData);
addFrame(gl, tex);
}
}
public final int getFrameCount() { return frames.size(); }
public final int getCurrentIdx() { return frameIdx; }
public final void setCurrentIdx(final int idx) throws IndexOutOfBoundsException {
if( 0 > idx || idx >= frames.size() ) {
throw new IndexOutOfBoundsException("idx shall be within 0 <= "+idx+" < "+frames.size());
}
frameIdx=idx;
}
public final void setManualStepping(final boolean v) { manualStepping = v; }
public final boolean getManualStepping() { return manualStepping; }
public final TextureSequence.TextureFrame getFrame(final int idx) { return frames.get(idx); }
public void destroy(final GL gl) throws GLException {
for(int i=frames.size()-1; i>=0; i--) {
frames.get(i).getTexture().destroy(gl);
}
frames.clear();
}
@Override
public int getTextureTarget() {
return GL.GL_TEXTURE_2D;
}
@Override
public int getTextureUnit() {
return textureUnit;
}
@Override
public int[] getTextureMinMagFilter() {
return texMinMagFilter;
}
@Override
public int[] getTextureWrapST() {
return texWrapST;
}
@Override
public boolean isTextureAvailable() { return frames.size() > 0; }
@Override
public TextureSequence.TextureFrame getLastTexture() throws IllegalStateException {
return frames.get(frameIdx); // may return null
}
@Override
public TextureSequence.TextureFrame getNextTexture(final GL gl) throws IllegalStateException {
if( !manualStepping ) {
frameIdx = ( frameIdx + 1 ) % frames.size();
}
return frames.get(frameIdx);
}
@Override
public String getRequiredExtensionsShaderStub() throws IllegalStateException {
return "// TextTextureSequence: No extensions required\n";
}
@Override
public String getTextureSampler2DType() throws IllegalStateException {
return "sampler2D" ;
}
private String textureLookupFunctionName = "myTexture2D";
@Override
public String getTextureLookupFunctionName(final String desiredFuncName) throws IllegalStateException {
if(useBuildInTexLookup) {
return "texture2D";
}
if(null != desiredFuncName && desiredFuncName.length()>0) {
textureLookupFunctionName = desiredFuncName;
}
return textureLookupFunctionName;
}
@Override
public String getTextureLookupFragmentShaderImpl() throws IllegalStateException {
if(useBuildInTexLookup) {
return "";
}
return
"\n"+
"vec4 "+textureLookupFunctionName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
" return texture2D(image, texCoord);\n"+
"}\n\n";
}
@Override
public int getTextureFragmentShaderHashCode() {
if( !isTextureAvailable() ) {
textureFragmentShaderHashCode = 0;
return 0;
} else if( 0 == textureFragmentShaderHashCode ) {
int hash = 31 + getTextureLookupFragmentShaderImpl().hashCode();
hash = ((hash << 5) - hash) + getTextureSampler2DType().hashCode();
textureFragmentShaderHashCode = hash;
}
return textureFragmentShaderHashCode;
}
}