mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-14 04:24:05 +09:00
added sources for Slick
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054 Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A collection of IOException that failed image data loading
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class CompositeIOException extends IOException {
|
||||
/** The list of exceptions causing this one */
|
||||
private ArrayList exceptions = new ArrayList();
|
||||
|
||||
/**
|
||||
* Create a new composite IO Exception
|
||||
*/
|
||||
public CompositeIOException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an exception that caused this exceptino
|
||||
*
|
||||
* @param e The exception
|
||||
*/
|
||||
public void addException(Exception e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Throwable#getMessage()
|
||||
*/
|
||||
public String getMessage() {
|
||||
String msg = "Composite Exception: \n";
|
||||
for (int i=0;i<exceptions.size();i++) {
|
||||
msg += "\t"+((IOException) exceptions.get(i)).getMessage()+"\n";
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A composite data source that checks multiple loaders in order of
|
||||
* preference
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class CompositeImageData implements LoadableImageData {
|
||||
/** The list of images sources in order of preference to try loading the data with */
|
||||
private ArrayList sources = new ArrayList();
|
||||
/** The data source that worked and was used - or null if no luck */
|
||||
private LoadableImageData picked;
|
||||
|
||||
/**
|
||||
* Add a potentional source of image data
|
||||
*
|
||||
* @param data The data source to try
|
||||
*/
|
||||
public void add(LoadableImageData data) {
|
||||
sources.add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis) throws IOException {
|
||||
return loadImage(fis, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {
|
||||
return loadImage(fis, flipped, false, transparent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream is, boolean flipped, boolean forceAlpha, int[] transparent) throws IOException {
|
||||
CompositeIOException exception = new CompositeIOException();
|
||||
ByteBuffer buffer = null;
|
||||
|
||||
BufferedInputStream in = new BufferedInputStream(is, is.available());
|
||||
in.mark(is.available());
|
||||
|
||||
// cycle through our source until one of them works
|
||||
for (int i=0;i<sources.size();i++) {
|
||||
in.reset();
|
||||
try {
|
||||
LoadableImageData data = (LoadableImageData) sources.get(i);
|
||||
|
||||
buffer = data.loadImage(in, flipped, forceAlpha, transparent);
|
||||
picked = data;
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
Log.warn(sources.get(i).getClass()+" failed to read the data", e);
|
||||
exception.addException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (picked == null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the state of the image data and throw a
|
||||
* runtime exception if theres a problem
|
||||
*/
|
||||
private void checkPicked() {
|
||||
if (picked == null) {
|
||||
throw new RuntimeException("Attempt to make use of uninitialised or invalid composite image data");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getDepth()
|
||||
*/
|
||||
public int getDepth() {
|
||||
checkPicked();
|
||||
|
||||
return picked.getDepth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getHeight()
|
||||
*/
|
||||
public int getHeight() {
|
||||
checkPicked();
|
||||
|
||||
return picked.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()
|
||||
*/
|
||||
public ByteBuffer getImageBufferData() {
|
||||
checkPicked();
|
||||
|
||||
return picked.getImageBufferData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexHeight()
|
||||
*/
|
||||
public int getTexHeight() {
|
||||
checkPicked();
|
||||
|
||||
return picked.getTexHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexWidth()
|
||||
*/
|
||||
public int getTexWidth() {
|
||||
checkPicked();
|
||||
|
||||
return picked.getTexWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getWidth()
|
||||
*/
|
||||
public int getWidth() {
|
||||
checkPicked();
|
||||
|
||||
return picked.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#configureEdging(boolean)
|
||||
*/
|
||||
public void configureEdging(boolean edging) {
|
||||
for (int i=0;i<sources.size();i++) {
|
||||
((LoadableImageData) sources.get(i)).configureEdging(edging);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
183
lib/slick-source/org/newdawn/slick/opengl/CursorLoader.java
Normal file
183
lib/slick-source/org/newdawn/slick/opengl/CursorLoader.java
Normal file
@@ -0,0 +1,183 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.input.Cursor;
|
||||
import org.newdawn.slick.util.Log;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
|
||||
/**
|
||||
* A utility to load cursors (thanks go to Kappa for the animated cursor
|
||||
* loader)
|
||||
*
|
||||
* @author Kevin Glass
|
||||
* @author Kappa-One
|
||||
*/
|
||||
public class CursorLoader {
|
||||
/** The single instnace of this loader to exist */
|
||||
private static CursorLoader single = new CursorLoader();
|
||||
|
||||
/**
|
||||
* Retrieve the single instance of this loader - convinient huh?
|
||||
*
|
||||
* @return The single instance of the cursor loader
|
||||
*/
|
||||
public static CursorLoader get() {
|
||||
return single;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new cursor loader
|
||||
*/
|
||||
private CursorLoader() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cursor based on a image reference on the classpath
|
||||
*
|
||||
* @param ref The reference to the image to be loaded
|
||||
* @param x The x-coordinate of the cursor hotspot (left -> right)
|
||||
* @param y The y-coordinate of the cursor hotspot (bottom -> top)
|
||||
* @return The create cursor
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
* @throws LWJGLException Indicates a failure to create the hardware cursor
|
||||
*/
|
||||
public Cursor getCursor(String ref,int x,int y) throws IOException, LWJGLException {
|
||||
LoadableImageData imageData = null;
|
||||
|
||||
imageData = ImageDataFactory.getImageDataFor(ref);
|
||||
imageData.configureEdging(false);
|
||||
|
||||
ByteBuffer buf = imageData.loadImage(ResourceLoader.getResourceAsStream(ref), true, true, null);
|
||||
for (int i=0;i<buf.limit();i+=4) {
|
||||
byte red = buf.get(i);
|
||||
byte green = buf.get(i+1);
|
||||
byte blue = buf.get(i+2);
|
||||
byte alpha = buf.get(i+3);
|
||||
|
||||
buf.put(i+2, red);
|
||||
buf.put(i+1, green);
|
||||
buf.put(i, blue);
|
||||
buf.put(i+3, alpha);
|
||||
}
|
||||
|
||||
try {
|
||||
int yspot = imageData.getHeight() - y - 1;
|
||||
if (yspot < 0) {
|
||||
yspot = 0;
|
||||
}
|
||||
|
||||
return new Cursor(imageData.getTexWidth(), imageData.getTexHeight(), x, yspot, 1, buf.asIntBuffer(), null);
|
||||
} catch (Throwable e) {
|
||||
Log.info("Chances are you cursor is too small for this platform");
|
||||
throw new LWJGLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a cursor based on a set of image data
|
||||
*
|
||||
* @param buf The image data (stored in RGBA) to load the cursor from
|
||||
* @param x The x-coordinate of the cursor hotspot (left -> right)
|
||||
* @param y The y-coordinate of the cursor hotspot (bottom -> top)
|
||||
* @param width The width of the image data provided
|
||||
* @param height The height of the image data provided
|
||||
* @return The create cursor
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
* @throws LWJGLException Indicates a failure to create the hardware cursor
|
||||
*/
|
||||
public Cursor getCursor(ByteBuffer buf,int x,int y,int width,int height) throws IOException, LWJGLException {
|
||||
for (int i=0;i<buf.limit();i+=4) {
|
||||
byte red = buf.get(i);
|
||||
byte green = buf.get(i+1);
|
||||
byte blue = buf.get(i+2);
|
||||
byte alpha = buf.get(i+3);
|
||||
|
||||
buf.put(i+2, red);
|
||||
buf.put(i+1, green);
|
||||
buf.put(i, blue);
|
||||
buf.put(i+3, alpha);
|
||||
}
|
||||
|
||||
try {
|
||||
int yspot = height - y - 1;
|
||||
if (yspot < 0) {
|
||||
yspot = 0;
|
||||
}
|
||||
return new Cursor(width,height, x, yspot, 1, buf.asIntBuffer(), null);
|
||||
} catch (Throwable e) {
|
||||
Log.info("Chances are you cursor is too small for this platform");
|
||||
throw new LWJGLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cursor based on a set of image data
|
||||
*
|
||||
* @param imageData The data from which the cursor can read it's contents
|
||||
* @param x The x-coordinate of the cursor hotspot (left -> right)
|
||||
* @param y The y-coordinate of the cursor hotspot (bottom -> top)
|
||||
* @return The create cursor
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
* @throws LWJGLException Indicates a failure to create the hardware cursor
|
||||
*/
|
||||
public Cursor getCursor(ImageData imageData,int x,int y) throws IOException, LWJGLException {
|
||||
ByteBuffer buf = imageData.getImageBufferData();
|
||||
for (int i=0;i<buf.limit();i+=4) {
|
||||
byte red = buf.get(i);
|
||||
byte green = buf.get(i+1);
|
||||
byte blue = buf.get(i+2);
|
||||
byte alpha = buf.get(i+3);
|
||||
|
||||
buf.put(i+2, red);
|
||||
buf.put(i+1, green);
|
||||
buf.put(i, blue);
|
||||
buf.put(i+3, alpha);
|
||||
}
|
||||
|
||||
try {
|
||||
int yspot = imageData.getHeight() - y - 1;
|
||||
if (yspot < 0) {
|
||||
yspot = 0;
|
||||
}
|
||||
return new Cursor(imageData.getTexWidth(), imageData.getTexHeight(), x, yspot, 1, buf.asIntBuffer(), null);
|
||||
} catch (Throwable e) {
|
||||
Log.info("Chances are you cursor is too small for this platform");
|
||||
throw new LWJGLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cursor based on a image reference on the classpath. The image
|
||||
* is assumed to be a set/strip of cursor animation frames running from top to
|
||||
* bottom.
|
||||
*
|
||||
* @param ref The reference to the image to be loaded
|
||||
* @param x The x-coordinate of the cursor hotspot (left -> right)
|
||||
* @param y The y-coordinate of the cursor hotspot (bottom -> top)
|
||||
* @param width The x width of the cursor
|
||||
* @param height The y height of the cursor
|
||||
* @param cursorDelays image delays between changing frames in animation
|
||||
*
|
||||
* @return The created cursor
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
* @throws LWJGLException Indicates a failure to create the hardware cursor
|
||||
*/
|
||||
public Cursor getAnimatedCursor(String ref,int x,int y, int width, int height, int[] cursorDelays) throws IOException, LWJGLException {
|
||||
IntBuffer cursorDelaysBuffer = ByteBuffer.allocateDirect(cursorDelays.length*4).order(ByteOrder.nativeOrder()).asIntBuffer();
|
||||
for (int i=0;i<cursorDelays.length;i++) {
|
||||
cursorDelaysBuffer.put(cursorDelays[i]);
|
||||
}
|
||||
cursorDelaysBuffer.flip();
|
||||
|
||||
LoadableImageData imageData = new TGAImageData();
|
||||
ByteBuffer buf = imageData.loadImage(ResourceLoader.getResourceAsStream(ref), false, null);
|
||||
|
||||
return new Cursor(width, height, x, y, cursorDelays.length, buf.asIntBuffer(), cursorDelaysBuffer);
|
||||
}
|
||||
}
|
||||
234
lib/slick-source/org/newdawn/slick/opengl/DeferredTexture.java
Normal file
234
lib/slick-source/org/newdawn/slick/opengl/DeferredTexture.java
Normal file
@@ -0,0 +1,234 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.newdawn.slick.loading.DeferredResource;
|
||||
import org.newdawn.slick.loading.LoadingList;
|
||||
import org.newdawn.slick.opengl.renderer.SGL;
|
||||
|
||||
/**
|
||||
* A texture proxy that can be used to load a texture at a later date while still
|
||||
* allowing elements to reference it
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class DeferredTexture extends TextureImpl implements DeferredResource {
|
||||
/** The stream to read the texture from */
|
||||
private InputStream in;
|
||||
/** The name of the resource to load */
|
||||
private String resourceName;
|
||||
/** True if the image should be flipped */
|
||||
private boolean flipped;
|
||||
/** The filter to apply to the texture */
|
||||
private int filter;
|
||||
/** The texture we're proxying for */
|
||||
private TextureImpl target;
|
||||
/** The color to be transparent */
|
||||
private int[] trans;
|
||||
|
||||
/**
|
||||
* Create a new deferred texture
|
||||
*
|
||||
* @param in The input stream from which to read the texture
|
||||
* @param resourceName The name to give the resource
|
||||
* @param flipped True if the image should be flipped
|
||||
* @param filter The filter to apply
|
||||
* @param trans The colour to defined as transparent
|
||||
*/
|
||||
public DeferredTexture(InputStream in, String resourceName, boolean flipped, int filter, int[] trans) {
|
||||
this.in = in;
|
||||
this.resourceName = resourceName;
|
||||
this.flipped = flipped;
|
||||
this.filter = filter;
|
||||
this.trans = trans;
|
||||
|
||||
LoadingList.get().add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.loading.DeferredResource#load()
|
||||
*/
|
||||
public void load() throws IOException {
|
||||
boolean before = InternalTextureLoader.get().isDeferredLoading();
|
||||
InternalTextureLoader.get().setDeferredLoading(false);
|
||||
target = InternalTextureLoader.get().getTexture(in, resourceName, flipped, filter, trans);
|
||||
InternalTextureLoader.get().setDeferredLoading(before);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the target has been obtained already
|
||||
*/
|
||||
private void checkTarget() {
|
||||
if (target == null) {
|
||||
try {
|
||||
load();
|
||||
LoadingList.get().remove(this);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Attempt to use deferred texture before loading and resource not found: "+resourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#bind()
|
||||
*/
|
||||
public void bind() {
|
||||
checkTarget();
|
||||
|
||||
target.bind();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getHeight()
|
||||
*/
|
||||
public float getHeight() {
|
||||
checkTarget();
|
||||
|
||||
return target.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getImageHeight()
|
||||
*/
|
||||
public int getImageHeight() {
|
||||
checkTarget();
|
||||
return target.getImageHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getImageWidth()
|
||||
*/
|
||||
public int getImageWidth() {
|
||||
checkTarget();
|
||||
return target.getImageWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getTextureHeight()
|
||||
*/
|
||||
public int getTextureHeight() {
|
||||
checkTarget();
|
||||
return target.getTextureHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getTextureID()
|
||||
*/
|
||||
public int getTextureID() {
|
||||
checkTarget();
|
||||
return target.getTextureID();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getTextureRef()
|
||||
*/
|
||||
public String getTextureRef() {
|
||||
checkTarget();
|
||||
return target.getTextureRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getTextureWidth()
|
||||
*/
|
||||
public int getTextureWidth() {
|
||||
checkTarget();
|
||||
return target.getTextureWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getWidth()
|
||||
*/
|
||||
public float getWidth() {
|
||||
checkTarget();
|
||||
return target.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#release()
|
||||
*/
|
||||
public void release() {
|
||||
checkTarget();
|
||||
target.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#setAlpha(boolean)
|
||||
*/
|
||||
public void setAlpha(boolean alpha) {
|
||||
checkTarget();
|
||||
target.setAlpha(alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#setHeight(int)
|
||||
*/
|
||||
public void setHeight(int height) {
|
||||
checkTarget();
|
||||
target.setHeight(height);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#setTextureHeight(int)
|
||||
*/
|
||||
public void setTextureHeight(int texHeight) {
|
||||
checkTarget();
|
||||
target.setTextureHeight(texHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#setTextureID(int)
|
||||
*/
|
||||
public void setTextureID(int textureID) {
|
||||
checkTarget();
|
||||
target.setTextureID(textureID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#setTextureWidth(int)
|
||||
*/
|
||||
public void setTextureWidth(int texWidth) {
|
||||
checkTarget();
|
||||
target.setTextureWidth(texWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#setWidth(int)
|
||||
*/
|
||||
public void setWidth(int width) {
|
||||
checkTarget();
|
||||
target.setWidth(width);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.TextureImpl#getTextureData()
|
||||
*/
|
||||
public byte[] getTextureData() {
|
||||
checkTarget();
|
||||
return target.getTextureData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.loading.DeferredResource#getDescription()
|
||||
*/
|
||||
public String getDescription() {
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#hasAlpha()
|
||||
*/
|
||||
public boolean hasAlpha() {
|
||||
checkTarget();
|
||||
return target.hasAlpha();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#setTextureFilter(int)
|
||||
*/
|
||||
public void setTextureFilter(int textureFilter) {
|
||||
checkTarget();
|
||||
target.setTextureFilter(textureFilter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
|
||||
/**
|
||||
* An image data implementation which represents an empty texture
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class EmptyImageData implements ImageData {
|
||||
/** The width of the data */
|
||||
private int width;
|
||||
/** The height of the data */
|
||||
private int height;
|
||||
|
||||
/**
|
||||
* Create an empty image data source
|
||||
*
|
||||
* @param width The width of the source
|
||||
* @param height The height of the source
|
||||
*/
|
||||
public EmptyImageData(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getDepth()
|
||||
*/
|
||||
public int getDepth() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getHeight()
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()
|
||||
*/
|
||||
public ByteBuffer getImageBufferData() {
|
||||
return BufferUtils.createByteBuffer(getTexWidth() * getTexHeight() * 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexHeight()
|
||||
*/
|
||||
public int getTexHeight() {
|
||||
return InternalTextureLoader.get2Fold(height);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexWidth()
|
||||
*/
|
||||
public int getTexWidth() {
|
||||
return InternalTextureLoader.get2Fold(width);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getWidth()
|
||||
*/
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
}
|
||||
22
lib/slick-source/org/newdawn/slick/opengl/GLUtils.java
Normal file
22
lib/slick-source/org/newdawn/slick/opengl/GLUtils.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import org.newdawn.slick.opengl.renderer.Renderer;
|
||||
|
||||
/**
|
||||
* A collection of utilities to allow aid interaction with the GL provider
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public final class GLUtils {
|
||||
|
||||
/**
|
||||
* Check that we're in the right place to be doing GL operations
|
||||
*/
|
||||
public static void checkGLContext() {
|
||||
try {
|
||||
Renderer.get().glGetError();
|
||||
} catch (NullPointerException e) {
|
||||
throw new RuntimeException("OpenGL based resources (images, fonts, sprites etc) must be loaded as part of init() or the game loop. They cannot be loaded before initialisation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
55
lib/slick-source/org/newdawn/slick/opengl/ImageData.java
Normal file
55
lib/slick-source/org/newdawn/slick/opengl/ImageData.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A description of any class providing ImageData in a form suitable for OpenGL texture
|
||||
* creation.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public interface ImageData {
|
||||
|
||||
/**
|
||||
* Get the last bit depth read from a TGA
|
||||
*
|
||||
* @return The last bit depth read
|
||||
*/
|
||||
public int getDepth();
|
||||
|
||||
/**
|
||||
* Get the last width read from a TGA
|
||||
*
|
||||
* @return Get the last width in pixels fread from a TGA
|
||||
*/
|
||||
public int getWidth();
|
||||
|
||||
/**
|
||||
* Get the last height read from a TGA
|
||||
*
|
||||
* @return Get the last height in pixels fread from a TGA
|
||||
*/
|
||||
public int getHeight();
|
||||
|
||||
/**
|
||||
* Get the last required texture width for a loaded image
|
||||
*
|
||||
* @return Get the ast required texture width for a loaded image
|
||||
*/
|
||||
public int getTexWidth();
|
||||
|
||||
/**
|
||||
* Get the ast required texture height for a loaded image
|
||||
*
|
||||
* @return Get the ast required texture height for a loaded image
|
||||
*/
|
||||
public int getTexHeight();
|
||||
|
||||
/**
|
||||
* Get the store image
|
||||
*
|
||||
* @return The stored image
|
||||
*/
|
||||
public ByteBuffer getImageBufferData();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A static utility to create the appropriate image data for a particular reference.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class ImageDataFactory {
|
||||
/** True if we're going to use the native PNG loader - cached so it doesn't have
|
||||
* the security check repeatedly
|
||||
*/
|
||||
private static boolean usePngLoader = true;
|
||||
/** True if the PNG loader property has been checked */
|
||||
private static boolean pngLoaderPropertyChecked = false;
|
||||
|
||||
/** The name of the PNG loader configuration property */
|
||||
private static final String PNG_LOADER = "org.newdawn.slick.pngloader";
|
||||
|
||||
/**
|
||||
* Check PNG loader property. If set the native PNG loader will
|
||||
* not be used.
|
||||
*/
|
||||
private static void checkProperty() {
|
||||
if (!pngLoaderPropertyChecked) {
|
||||
pngLoaderPropertyChecked = true;
|
||||
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
String val = System.getProperty(PNG_LOADER);
|
||||
if ("false".equalsIgnoreCase(val)) {
|
||||
usePngLoader = false;
|
||||
}
|
||||
|
||||
Log.info("Use Java PNG Loader = " + usePngLoader);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
// ignore, security failure - probably an applet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an image data that is appropriate for the reference supplied
|
||||
*
|
||||
* @param ref The reference to the image to retrieve
|
||||
* @return The image data that can be used to retrieve the data for that resource
|
||||
*/
|
||||
public static LoadableImageData getImageDataFor(String ref) {
|
||||
LoadableImageData imageData;
|
||||
checkProperty();
|
||||
|
||||
ref = ref.toLowerCase();
|
||||
|
||||
if (ref.endsWith(".tga")) {
|
||||
return new TGAImageData();
|
||||
}
|
||||
if (ref.endsWith(".png")) {
|
||||
CompositeImageData data = new CompositeImageData();
|
||||
if (usePngLoader) {
|
||||
data.add(new PNGImageData());
|
||||
}
|
||||
data.add(new ImageIOImageData());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
return new ImageIOImageData();
|
||||
}
|
||||
}
|
||||
244
lib/slick-source/org/newdawn/slick/opengl/ImageIOImageData.java
Normal file
244
lib/slick-source/org/newdawn/slick/opengl/ImageIOImageData.java
Normal file
@@ -0,0 +1,244 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ComponentColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
/**
|
||||
* An image data provider that uses ImageIO to retrieve image data in a format
|
||||
* suitable for creating OpenGL textures. This implementation is used when
|
||||
* formats not natively supported by the library are required.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class ImageIOImageData implements LoadableImageData {
|
||||
/** The colour model including alpha for the GL image */
|
||||
private static final ColorModel glAlphaColorModel =
|
||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
|
||||
new int[] {8,8,8,8},
|
||||
true,
|
||||
false,
|
||||
ComponentColorModel.TRANSLUCENT,
|
||||
DataBuffer.TYPE_BYTE);
|
||||
|
||||
/** The colour model for the GL image */
|
||||
private static final ColorModel glColorModel =
|
||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
|
||||
new int[] {8,8,8,0},
|
||||
false,
|
||||
false,
|
||||
ComponentColorModel.OPAQUE,
|
||||
DataBuffer.TYPE_BYTE);
|
||||
|
||||
/** The bit depth of the image */
|
||||
private int depth;
|
||||
/** The height of the image */
|
||||
private int height;
|
||||
/** The width of the image */
|
||||
private int width;
|
||||
/** The width of the texture that should be created for the image */
|
||||
private int texWidth;
|
||||
/** The height of the texture that should be created for the image */
|
||||
private int texHeight;
|
||||
/** True if we should edge */
|
||||
private boolean edging = true;
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getDepth()
|
||||
*/
|
||||
public int getDepth() {
|
||||
return depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getHeight()
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexHeight()
|
||||
*/
|
||||
public int getTexHeight() {
|
||||
return texHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexWidth()
|
||||
*/
|
||||
public int getTexWidth() {
|
||||
return texWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getWidth()
|
||||
*/
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis) throws IOException {
|
||||
return loadImage(fis, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {
|
||||
return loadImage(fis, flipped, false, transparent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, boolean forceAlpha, int[] transparent) throws IOException {
|
||||
if (transparent != null) {
|
||||
forceAlpha = true;
|
||||
}
|
||||
|
||||
BufferedImage bufferedImage = ImageIO.read(fis);
|
||||
return imageToByteBuffer(bufferedImage, flipped, forceAlpha, transparent);
|
||||
}
|
||||
|
||||
public ByteBuffer imageToByteBuffer(BufferedImage image, boolean flipped, boolean forceAlpha, int[] transparent) {
|
||||
ByteBuffer imageBuffer = null;
|
||||
WritableRaster raster;
|
||||
BufferedImage texImage;
|
||||
|
||||
int texWidth = 2;
|
||||
int texHeight = 2;
|
||||
|
||||
// find the closest power of 2 for the width and height
|
||||
// of the produced texture
|
||||
|
||||
while (texWidth < image.getWidth()) {
|
||||
texWidth *= 2;
|
||||
}
|
||||
while (texHeight < image.getHeight()) {
|
||||
texHeight *= 2;
|
||||
}
|
||||
|
||||
this.width = image.getWidth();
|
||||
this.height = image.getHeight();
|
||||
this.texHeight = texHeight;
|
||||
this.texWidth = texWidth;
|
||||
|
||||
// create a raster that can be used by OpenGL as a source
|
||||
// for a texture
|
||||
boolean useAlpha = image.getColorModel().hasAlpha() || forceAlpha;
|
||||
|
||||
if (useAlpha) {
|
||||
depth = 32;
|
||||
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,4,null);
|
||||
texImage = new BufferedImage(glAlphaColorModel,raster,false,new Hashtable());
|
||||
} else {
|
||||
depth = 24;
|
||||
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,3,null);
|
||||
texImage = new BufferedImage(glColorModel,raster,false,new Hashtable());
|
||||
}
|
||||
|
||||
// copy the source image into the produced image
|
||||
Graphics2D g = (Graphics2D) texImage.getGraphics();
|
||||
|
||||
// only need to blank the image for mac compatibility if we're using alpha
|
||||
if (useAlpha) {
|
||||
g.setColor(new Color(0f,0f,0f,0f));
|
||||
g.fillRect(0,0,texWidth,texHeight);
|
||||
}
|
||||
|
||||
if (flipped) {
|
||||
g.scale(1,-1);
|
||||
g.drawImage(image,0,-height,null);
|
||||
} else {
|
||||
g.drawImage(image,0,0,null);
|
||||
}
|
||||
|
||||
if (edging) {
|
||||
if (height < texHeight - 1) {
|
||||
copyArea(texImage, 0, 0, width, 1, 0, texHeight-1);
|
||||
copyArea(texImage, 0, height-1, width, 1, 0, 1);
|
||||
}
|
||||
if (width < texWidth - 1) {
|
||||
copyArea(texImage, 0,0,1,height,texWidth-1,0);
|
||||
copyArea(texImage, width-1,0,1,height,1,0);
|
||||
}
|
||||
}
|
||||
|
||||
// build a byte buffer from the temporary image
|
||||
// that be used by OpenGL to produce a texture.
|
||||
byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData();
|
||||
|
||||
if (transparent != null) {
|
||||
for (int i=0;i<data.length;i+=4) {
|
||||
boolean match = true;
|
||||
for (int c=0;c<3;c++) {
|
||||
int value = data[i+c] < 0 ? 256 + data[i+c] : data[i+c];
|
||||
if (value != transparent[c]) {
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
data[i+3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imageBuffer = ByteBuffer.allocateDirect(data.length);
|
||||
imageBuffer.order(ByteOrder.nativeOrder());
|
||||
imageBuffer.put(data, 0, data.length);
|
||||
imageBuffer.flip();
|
||||
g.dispose();
|
||||
|
||||
return imageBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()
|
||||
*/
|
||||
public ByteBuffer getImageBufferData() {
|
||||
throw new RuntimeException("ImageIOImageData doesn't store it's image.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement of transform copy area for 1.4
|
||||
*
|
||||
* @param image The image to copy
|
||||
* @param x The x position to copy to
|
||||
* @param y The y position to copy to
|
||||
* @param width The width of the image
|
||||
* @param height The height of the image
|
||||
* @param dx The transform on the x axis
|
||||
* @param dy The transform on the y axis
|
||||
*/
|
||||
private void copyArea(BufferedImage image, int x, int y, int width, int height, int dx, int dy) {
|
||||
Graphics2D g = (Graphics2D) image.getGraphics();
|
||||
|
||||
g.drawImage(image.getSubimage(x, y, width, height),x+dx,y+dy,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#configureEdging(boolean)
|
||||
*/
|
||||
public void configureEdging(boolean edging) {
|
||||
this.edging = edging;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,530 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.newdawn.slick.opengl.renderer.Renderer;
|
||||
import org.newdawn.slick.opengl.renderer.SGL;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
|
||||
/**
|
||||
* A texture loaded based on many old versions that will load image data from a file
|
||||
* and produce OpenGL textures.
|
||||
*
|
||||
* @see ImageData
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class InternalTextureLoader {
|
||||
/** The renderer to use for all GL operations */
|
||||
protected static SGL GL = Renderer.get();
|
||||
/** The standard texture loaded used everywhere */
|
||||
private static final InternalTextureLoader loader = new InternalTextureLoader();
|
||||
|
||||
/**
|
||||
* Get the single instance of this texture loader
|
||||
*
|
||||
* @return The single instance of the texture loader
|
||||
*/
|
||||
public static InternalTextureLoader get() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
/** The table of textures that have been loaded in this loader */
|
||||
private HashMap texturesLinear = new HashMap();
|
||||
/** The table of textures that have been loaded in this loader */
|
||||
private HashMap texturesNearest = new HashMap();
|
||||
/** The destination pixel format */
|
||||
private int dstPixelFormat = SGL.GL_RGBA8;
|
||||
/** True if we're using deferred loading */
|
||||
private boolean deferred;
|
||||
/** True if we should hold texture data */
|
||||
private boolean holdTextureData;
|
||||
|
||||
/**
|
||||
* Create a new texture loader based on the game panel
|
||||
*/
|
||||
private InternalTextureLoader() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate where texture data should be held for reinitialising at a future
|
||||
* point.
|
||||
*
|
||||
* @param holdTextureData True if we should hold texture data
|
||||
*/
|
||||
public void setHoldTextureData(boolean holdTextureData) {
|
||||
this.holdTextureData = holdTextureData;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if we should only record the request to load in the intention
|
||||
* of loading the texture later
|
||||
*
|
||||
* @param deferred True if the we should load a token
|
||||
*/
|
||||
public void setDeferredLoading(boolean deferred) {
|
||||
this.deferred = deferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're using deferred loading
|
||||
*
|
||||
* @return True if we're loading deferred textures
|
||||
*/
|
||||
public boolean isDeferredLoading() {
|
||||
return deferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a particular named image from the cache
|
||||
*
|
||||
* @param name The name of the image to be cleared
|
||||
*/
|
||||
public void clear(String name) {
|
||||
texturesLinear.remove(name);
|
||||
texturesNearest.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear out the cached textures
|
||||
*/
|
||||
public void clear() {
|
||||
texturesLinear.clear();
|
||||
texturesNearest.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the loader to produce 16 bit textures
|
||||
*/
|
||||
public void set16BitMode() {
|
||||
dstPixelFormat = SGL.GL_RGBA16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new texture ID
|
||||
*
|
||||
* @return A new texture ID
|
||||
*/
|
||||
public static int createTextureID()
|
||||
{
|
||||
IntBuffer tmp = createIntBuffer(1);
|
||||
GL.glGenTextures(tmp);
|
||||
return tmp.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a texture from a specific file
|
||||
*
|
||||
* @param source The file to load the texture from
|
||||
* @param flipped True if we should flip the texture on the y axis while loading
|
||||
* @param filter The filter to use
|
||||
* @return The texture loaded
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
*/
|
||||
public Texture getTexture(File source, boolean flipped,int filter) throws IOException {
|
||||
String resourceName = source.getAbsolutePath();
|
||||
InputStream in = new FileInputStream(source);
|
||||
|
||||
return getTexture(in, resourceName, flipped, filter, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a texture from a specific file
|
||||
*
|
||||
* @param source The file to load the texture from
|
||||
* @param flipped True if we should flip the texture on the y axis while loading
|
||||
* @param filter The filter to use
|
||||
* @param transparent The colour to interpret as transparent or null if none
|
||||
* @return The texture loaded
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
*/
|
||||
public Texture getTexture(File source, boolean flipped,int filter, int[] transparent) throws IOException {
|
||||
String resourceName = source.getAbsolutePath();
|
||||
InputStream in = new FileInputStream(source);
|
||||
|
||||
return getTexture(in, resourceName, flipped, filter, transparent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a texture from a resource location
|
||||
*
|
||||
* @param resourceName The location to load the texture from
|
||||
* @param flipped True if we should flip the texture on the y axis while loading
|
||||
* @param filter The filter to use when scaling the texture
|
||||
* @return The texture loaded
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
*/
|
||||
public Texture getTexture(String resourceName, boolean flipped, int filter) throws IOException {
|
||||
InputStream in = ResourceLoader.getResourceAsStream(resourceName);
|
||||
|
||||
return getTexture(in, resourceName, flipped, filter, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a texture from a resource location
|
||||
*
|
||||
* @param resourceName The location to load the texture from
|
||||
* @param flipped True if we should flip the texture on the y axis while loading
|
||||
* @param filter The filter to use when scaling the texture
|
||||
* @param transparent The colour to interpret as transparent or null if none
|
||||
* @return The texture loaded
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
*/
|
||||
public Texture getTexture(String resourceName, boolean flipped, int filter, int[] transparent) throws IOException {
|
||||
InputStream in = ResourceLoader.getResourceAsStream(resourceName);
|
||||
|
||||
return getTexture(in, resourceName, flipped, filter, transparent);
|
||||
}
|
||||
/**
|
||||
* Get a texture from a image file
|
||||
*
|
||||
* @param in The stream from which we can load the image
|
||||
* @param resourceName The name to give this image in the internal cache
|
||||
* @param flipped True if we should flip the image on the y-axis while loading
|
||||
* @param filter The filter to use when scaling the texture
|
||||
* @return The texture loaded
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
*/
|
||||
public Texture getTexture(InputStream in, String resourceName, boolean flipped, int filter) throws IOException {
|
||||
return getTexture(in, resourceName, flipped, filter, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a texture from a image file
|
||||
*
|
||||
* @param in The stream from which we can load the image
|
||||
* @param resourceName The name to give this image in the internal cache
|
||||
* @param flipped True if we should flip the image on the y-axis while loading
|
||||
* @param filter The filter to use when scaling the texture
|
||||
* @param transparent The colour to interpret as transparent or null if none
|
||||
* @return The texture loaded
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
*/
|
||||
public TextureImpl getTexture(InputStream in, String resourceName, boolean flipped, int filter, int[] transparent) throws IOException {
|
||||
if (deferred) {
|
||||
return new DeferredTexture(in, resourceName, flipped, filter, transparent);
|
||||
}
|
||||
|
||||
HashMap hash = texturesLinear;
|
||||
if (filter == SGL.GL_NEAREST) {
|
||||
hash = texturesNearest;
|
||||
}
|
||||
|
||||
String resName = resourceName;
|
||||
if (transparent != null) {
|
||||
resName += ":"+transparent[0]+":"+transparent[1]+":"+transparent[2];
|
||||
}
|
||||
resName += ":"+flipped;
|
||||
|
||||
if (holdTextureData) {
|
||||
TextureImpl tex = (TextureImpl) hash.get(resName);
|
||||
if (tex != null) {
|
||||
return tex;
|
||||
}
|
||||
} else {
|
||||
SoftReference ref = (SoftReference) hash.get(resName);
|
||||
if (ref != null) {
|
||||
TextureImpl tex = (TextureImpl) ref.get();
|
||||
if (tex != null) {
|
||||
return tex;
|
||||
} else {
|
||||
hash.remove(resName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// horrible test until I can find something more suitable
|
||||
try {
|
||||
GL.glGetError();
|
||||
} catch (NullPointerException e) {
|
||||
throw new RuntimeException("Image based resources must be loaded as part of init() or the game loop. They cannot be loaded before initialisation.");
|
||||
}
|
||||
|
||||
TextureImpl tex = getTexture(in, resourceName,
|
||||
SGL.GL_TEXTURE_2D,
|
||||
filter,
|
||||
filter, flipped, transparent);
|
||||
|
||||
tex.setCacheName(resName);
|
||||
if (holdTextureData) {
|
||||
hash.put(resName, tex);
|
||||
} else {
|
||||
hash.put(resName, new SoftReference(tex));
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a texture from a image file
|
||||
*
|
||||
* @param in The stream from which we can load the image
|
||||
* @param resourceName The name to give this image in the internal cache
|
||||
* @param flipped True if we should flip the image on the y-axis while loading
|
||||
* @param target The texture target we're loading this texture into
|
||||
* @param minFilter The scaling down filter
|
||||
* @param magFilter The scaling up filter
|
||||
* @param transparent The colour to interpret as transparent or null if none
|
||||
* @return The texture loaded
|
||||
* @throws IOException Indicates a failure to load the image
|
||||
*/
|
||||
private TextureImpl getTexture(InputStream in,
|
||||
String resourceName,
|
||||
int target,
|
||||
int magFilter,
|
||||
int minFilter, boolean flipped, int[] transparent) throws IOException
|
||||
{
|
||||
// create the texture ID for this texture
|
||||
ByteBuffer textureBuffer;
|
||||
|
||||
LoadableImageData imageData = ImageDataFactory.getImageDataFor(resourceName);
|
||||
textureBuffer = imageData.loadImage(new BufferedInputStream(in), flipped, transparent);
|
||||
|
||||
int textureID = createTextureID();
|
||||
TextureImpl texture = new TextureImpl(resourceName, target, textureID);
|
||||
// bind this texture
|
||||
GL.glBindTexture(target, textureID);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
|
||||
boolean hasAlpha;
|
||||
|
||||
width = imageData.getWidth();
|
||||
height = imageData.getHeight();
|
||||
hasAlpha = imageData.getDepth() == 32;
|
||||
|
||||
texture.setTextureWidth(imageData.getTexWidth());
|
||||
texture.setTextureHeight(imageData.getTexHeight());
|
||||
|
||||
texWidth = texture.getTextureWidth();
|
||||
texHeight = texture.getTextureHeight();
|
||||
|
||||
IntBuffer temp = BufferUtils.createIntBuffer(16);
|
||||
GL.glGetInteger(SGL.GL_MAX_TEXTURE_SIZE, temp);
|
||||
int max = temp.get(0);
|
||||
if ((texWidth > max) || (texHeight > max)) {
|
||||
throw new IOException("Attempt to allocate a texture to big for the current hardware");
|
||||
}
|
||||
|
||||
int srcPixelFormat = hasAlpha ? SGL.GL_RGBA : SGL.GL_RGB;
|
||||
int componentCount = hasAlpha ? 4 : 3;
|
||||
|
||||
texture.setWidth(width);
|
||||
texture.setHeight(height);
|
||||
texture.setAlpha(hasAlpha);
|
||||
|
||||
if (holdTextureData) {
|
||||
texture.setTextureData(srcPixelFormat, componentCount, minFilter, magFilter, textureBuffer);
|
||||
}
|
||||
|
||||
GL.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, minFilter);
|
||||
GL.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, magFilter);
|
||||
|
||||
// produce a texture from the byte buffer
|
||||
GL.glTexImage2D(target,
|
||||
0,
|
||||
dstPixelFormat,
|
||||
get2Fold(width),
|
||||
get2Fold(height),
|
||||
0,
|
||||
srcPixelFormat,
|
||||
SGL.GL_UNSIGNED_BYTE,
|
||||
textureBuffer);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty texture
|
||||
*
|
||||
* @param width The width of the new texture
|
||||
* @param height The height of the new texture
|
||||
* @return The created empty texture
|
||||
* @throws IOException Indicates a failure to create the texture on the graphics hardware
|
||||
*/
|
||||
public Texture createTexture(final int width, final int height) throws IOException {
|
||||
return createTexture(width, height, SGL.GL_NEAREST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty texture
|
||||
*
|
||||
* @param width The width of the new texture
|
||||
* @param height The height of the new texture
|
||||
* @return The created empty texture
|
||||
* @throws IOException Indicates a failure to create the texture on the graphics hardware
|
||||
*/
|
||||
public Texture createTexture(final int width, final int height, final int filter) throws IOException {
|
||||
ImageData ds = new EmptyImageData(width, height);
|
||||
|
||||
return getTexture(ds, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a texture from a image file
|
||||
*
|
||||
* @param dataSource The image data to generate the texture from
|
||||
* @param filter The filter to use when scaling the texture
|
||||
* @return The texture created
|
||||
* @throws IOException Indicates the texture is too big for the hardware
|
||||
*/
|
||||
public Texture getTexture(ImageData dataSource, int filter) throws IOException
|
||||
{
|
||||
int target = SGL.GL_TEXTURE_2D;
|
||||
|
||||
ByteBuffer textureBuffer;
|
||||
textureBuffer = dataSource.getImageBufferData();
|
||||
|
||||
// create the texture ID for this texture
|
||||
int textureID = createTextureID();
|
||||
TextureImpl texture = new TextureImpl("generated:"+dataSource, target ,textureID);
|
||||
|
||||
int minFilter = filter;
|
||||
int magFilter = filter;
|
||||
boolean flipped = false;
|
||||
|
||||
// bind this texture
|
||||
GL.glBindTexture(target, textureID);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
|
||||
boolean hasAlpha;
|
||||
|
||||
width = dataSource.getWidth();
|
||||
height = dataSource.getHeight();
|
||||
hasAlpha = dataSource.getDepth() == 32;
|
||||
|
||||
texture.setTextureWidth(dataSource.getTexWidth());
|
||||
texture.setTextureHeight(dataSource.getTexHeight());
|
||||
|
||||
texWidth = texture.getTextureWidth();
|
||||
texHeight = texture.getTextureHeight();
|
||||
|
||||
int srcPixelFormat = hasAlpha ? SGL.GL_RGBA : SGL.GL_RGB;
|
||||
int componentCount = hasAlpha ? 4 : 3;
|
||||
|
||||
texture.setWidth(width);
|
||||
texture.setHeight(height);
|
||||
texture.setAlpha(hasAlpha);
|
||||
|
||||
IntBuffer temp = BufferUtils.createIntBuffer(16);
|
||||
GL.glGetInteger(SGL.GL_MAX_TEXTURE_SIZE, temp);
|
||||
int max = temp.get(0);
|
||||
if ((texWidth > max) || (texHeight > max)) {
|
||||
throw new IOException("Attempt to allocate a texture to big for the current hardware");
|
||||
}
|
||||
|
||||
if (holdTextureData) {
|
||||
texture.setTextureData(srcPixelFormat, componentCount, minFilter, magFilter, textureBuffer);
|
||||
}
|
||||
|
||||
GL.glTexParameteri(target, SGL.GL_TEXTURE_MIN_FILTER, minFilter);
|
||||
GL.glTexParameteri(target, SGL.GL_TEXTURE_MAG_FILTER, magFilter);
|
||||
|
||||
// produce a texture from the byte buffer
|
||||
GL.glTexImage2D(target,
|
||||
0,
|
||||
dstPixelFormat,
|
||||
get2Fold(width),
|
||||
get2Fold(height),
|
||||
0,
|
||||
srcPixelFormat,
|
||||
SGL.GL_UNSIGNED_BYTE,
|
||||
textureBuffer);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the closest greater power of 2 to the fold number
|
||||
*
|
||||
* @param fold The target number
|
||||
* @return The power of 2
|
||||
*/
|
||||
public static int get2Fold(int fold) {
|
||||
int ret = 2;
|
||||
while (ret < fold) {
|
||||
ret *= 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an integer buffer to hold specified ints
|
||||
* - strictly a utility method
|
||||
*
|
||||
* @param size how many int to contain
|
||||
* @return created IntBuffer
|
||||
*/
|
||||
public static IntBuffer createIntBuffer(int size) {
|
||||
ByteBuffer temp = ByteBuffer.allocateDirect(4 * size);
|
||||
temp.order(ByteOrder.nativeOrder());
|
||||
|
||||
return temp.asIntBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload all the textures loaded in this loader
|
||||
*/
|
||||
public void reload() {
|
||||
Iterator texs = texturesLinear.values().iterator();
|
||||
while (texs.hasNext()) {
|
||||
((TextureImpl) texs.next()).reload();
|
||||
}
|
||||
texs = texturesNearest.values().iterator();
|
||||
while (texs.hasNext()) {
|
||||
((TextureImpl) texs.next()).reload();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload a given texture blob
|
||||
*
|
||||
* @param texture The texture being reloaded
|
||||
* @param srcPixelFormat The source pixel format
|
||||
* @param componentCount The component count
|
||||
* @param minFilter The minification filter
|
||||
* @param magFilter The magnification filter
|
||||
* @param textureBuffer The pixel data
|
||||
* @return The ID of the newly created texture
|
||||
*/
|
||||
public int reload(TextureImpl texture, int srcPixelFormat, int componentCount,
|
||||
int minFilter, int magFilter, ByteBuffer textureBuffer) {
|
||||
int target = SGL.GL_TEXTURE_2D;
|
||||
int textureID = createTextureID();
|
||||
GL.glBindTexture(target, textureID);
|
||||
|
||||
GL.glTexParameteri(target, SGL.GL_TEXTURE_MIN_FILTER, minFilter);
|
||||
GL.glTexParameteri(target, SGL.GL_TEXTURE_MAG_FILTER, magFilter);
|
||||
|
||||
// produce a texture from the byte buffer
|
||||
GL.glTexImage2D(target,
|
||||
0,
|
||||
dstPixelFormat,
|
||||
texture.getTextureWidth(),
|
||||
texture.getTextureHeight(),
|
||||
0,
|
||||
srcPixelFormat,
|
||||
SGL.GL_UNSIGNED_BYTE,
|
||||
textureBuffer);
|
||||
|
||||
return textureID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* An image data source that can load images from a stream
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public interface LoadableImageData extends ImageData {
|
||||
/**
|
||||
* Configure the edging that can be used to make texture edges
|
||||
* loop more cleanly
|
||||
*
|
||||
* @param edging True if we should edge
|
||||
*/
|
||||
public void configureEdging(boolean edging);
|
||||
|
||||
/**
|
||||
* Load a image from the specified stream
|
||||
*
|
||||
* @param fis The stream from which we'll load the TGA
|
||||
* @throws IOException Indicates a failure to read the TGA
|
||||
* @return The byte buffer containing texture data
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis) throws IOException;
|
||||
|
||||
/**
|
||||
* Load a image from the specified stream
|
||||
*
|
||||
* @param fis The stream from which we'll load the TGA
|
||||
* @param flipped True if we loading in flipped mode (used for cursors)
|
||||
* @param transparent The colour to interpret as transparent or null if none
|
||||
* @return The byte buffer containing texture data
|
||||
* @throws IOException Indicates a failure to read the TGA
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Load a image from the specified stream
|
||||
*
|
||||
* @param fis The stream from which we'll load the TGA
|
||||
* @param flipped True if we loading in flipped mode (used for cursors)
|
||||
* @param forceAlpha Force the output to have an alpha channel
|
||||
* @param transparent The colour to interpret as transparent or null if none
|
||||
* @return The byte buffer containing texture data
|
||||
* @throws IOException Indicates a failure to read the TGA
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, boolean forceAlpha, int[] transparent)
|
||||
throws IOException;
|
||||
}
|
||||
762
lib/slick-source/org/newdawn/slick/opengl/PNGDecoder.java
Normal file
762
lib/slick-source/org/newdawn/slick/opengl/PNGDecoder.java
Normal file
@@ -0,0 +1,762 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2010, Matthias Mann
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 Matthias Mann 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) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
/**
|
||||
* A PNGDecoder. The slick PNG decoder is based on this class :)
|
||||
*
|
||||
* @author Matthias Mann
|
||||
*/
|
||||
public class PNGDecoder {
|
||||
public static Format ALPHA = new Format(1, true);
|
||||
public static Format LUMINANCE = new Format(1, false);
|
||||
public static Format LUMINANCE_ALPHA = new Format(2, true);
|
||||
public static Format RGB = new Format(3, false);
|
||||
public static Format RGBA = new Format(4, true);
|
||||
public static Format BGRA = new Format(4, true);
|
||||
public static Format ABGR = new Format(4, true);
|
||||
|
||||
public static class Format {
|
||||
|
||||
final int numComponents;
|
||||
final boolean hasAlpha;
|
||||
|
||||
private Format(int numComponents, boolean hasAlpha) {
|
||||
this.numComponents = numComponents;
|
||||
this.hasAlpha = hasAlpha;
|
||||
}
|
||||
|
||||
public int getNumComponents() {
|
||||
return numComponents;
|
||||
}
|
||||
|
||||
public boolean isHasAlpha() {
|
||||
return hasAlpha;
|
||||
}
|
||||
}
|
||||
|
||||
private static final byte[] SIGNATURE = {(byte)137, 80, 78, 71, 13, 10, 26, 10};
|
||||
|
||||
private static final int IHDR = 0x49484452;
|
||||
private static final int PLTE = 0x504C5445;
|
||||
private static final int tRNS = 0x74524E53;
|
||||
private static final int IDAT = 0x49444154;
|
||||
private static final int IEND = 0x49454E44;
|
||||
|
||||
private static final byte COLOR_GREYSCALE = 0;
|
||||
private static final byte COLOR_TRUECOLOR = 2;
|
||||
private static final byte COLOR_INDEXED = 3;
|
||||
private static final byte COLOR_GREYALPHA = 4;
|
||||
private static final byte COLOR_TRUEALPHA = 6;
|
||||
|
||||
private final InputStream input;
|
||||
private final CRC32 crc;
|
||||
private final byte[] buffer;
|
||||
|
||||
private int chunkLength;
|
||||
private int chunkType;
|
||||
private int chunkRemaining;
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private int bitdepth;
|
||||
private int colorType;
|
||||
private int bytesPerPixel;
|
||||
private byte[] palette;
|
||||
private byte[] paletteA;
|
||||
private byte[] transPixel;
|
||||
|
||||
public PNGDecoder(InputStream input) throws IOException {
|
||||
this.input = input;
|
||||
this.crc = new CRC32();
|
||||
this.buffer = new byte[4096];
|
||||
|
||||
readFully(buffer, 0, SIGNATURE.length);
|
||||
if(!checkSignature(buffer)) {
|
||||
throw new IOException("Not a valid PNG file");
|
||||
}
|
||||
|
||||
openChunk(IHDR);
|
||||
readIHDR();
|
||||
closeChunk();
|
||||
|
||||
searchIDAT: for(;;) {
|
||||
openChunk();
|
||||
switch (chunkType) {
|
||||
case IDAT:
|
||||
break searchIDAT;
|
||||
case PLTE:
|
||||
readPLTE();
|
||||
break;
|
||||
case tRNS:
|
||||
readtRNS();
|
||||
break;
|
||||
}
|
||||
closeChunk();
|
||||
}
|
||||
|
||||
if(colorType == COLOR_INDEXED && palette == null) {
|
||||
throw new IOException("Missing PLTE chunk");
|
||||
}
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public boolean hasAlpha() {
|
||||
return colorType == COLOR_TRUEALPHA ||
|
||||
paletteA != null || transPixel != null;
|
||||
}
|
||||
|
||||
public boolean isRGB() {
|
||||
return colorType == COLOR_TRUEALPHA ||
|
||||
colorType == COLOR_TRUECOLOR ||
|
||||
colorType == COLOR_INDEXED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the implemented format conversion for the desired format.
|
||||
*
|
||||
* @param fmt the desired format
|
||||
* @return format which best matches the desired format
|
||||
* @throws UnsupportedOperationException if this PNG file can't be decoded
|
||||
*/
|
||||
public Format decideTextureFormat(Format fmt) {
|
||||
switch (colorType) {
|
||||
case COLOR_TRUECOLOR:
|
||||
if ((fmt == ABGR) || (fmt == RGBA) || (fmt == BGRA) || (fmt == RGB)) {
|
||||
return fmt;
|
||||
}
|
||||
|
||||
return RGB;
|
||||
case COLOR_TRUEALPHA:
|
||||
if ((fmt == ABGR) || (fmt == RGBA) || (fmt == BGRA) || (fmt == RGB)) {
|
||||
return fmt;
|
||||
}
|
||||
|
||||
return RGBA;
|
||||
case COLOR_GREYSCALE:
|
||||
if ((fmt == LUMINANCE) || (fmt == ALPHA)) {
|
||||
return fmt;
|
||||
}
|
||||
|
||||
return LUMINANCE;
|
||||
case COLOR_GREYALPHA:
|
||||
return LUMINANCE_ALPHA;
|
||||
case COLOR_INDEXED:
|
||||
if ((fmt == ABGR) || (fmt == RGBA) || (fmt == BGRA)) {
|
||||
return fmt;
|
||||
}
|
||||
|
||||
return RGBA;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
}
|
||||
|
||||
public void decode(ByteBuffer buffer, int stride, Format fmt) throws IOException {
|
||||
final int offset = buffer.position();
|
||||
final int lineSize = ((width * bitdepth + 7) / 8) * bytesPerPixel;
|
||||
byte[] curLine = new byte[lineSize+1];
|
||||
byte[] prevLine = new byte[lineSize+1];
|
||||
byte[] palLine = (bitdepth < 8) ? new byte[width+1] : null;
|
||||
|
||||
final Inflater inflater = new Inflater();
|
||||
try {
|
||||
for(int y=0 ; y<height ; y++) {
|
||||
readChunkUnzip(inflater, curLine, 0, curLine.length);
|
||||
unfilter(curLine, prevLine);
|
||||
|
||||
buffer.position(offset + y*stride);
|
||||
|
||||
switch (colorType) {
|
||||
case COLOR_TRUECOLOR:
|
||||
if (fmt == ABGR) {
|
||||
copyRGBtoABGR(buffer, curLine);
|
||||
}
|
||||
else if (fmt == RGBA) {
|
||||
copyRGBtoRGBA(buffer, curLine);
|
||||
}
|
||||
else if (fmt == BGRA) {
|
||||
copyRGBtoBGRA(buffer, curLine);
|
||||
}
|
||||
else if (fmt == RGB) {
|
||||
copy(buffer, curLine);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported format for this image");
|
||||
}
|
||||
break;
|
||||
case COLOR_TRUEALPHA:
|
||||
if (fmt == ABGR) {
|
||||
copyRGBAtoABGR(buffer, curLine);
|
||||
} else if (fmt == RGBA) {
|
||||
copy(buffer, curLine);
|
||||
} else if (fmt == BGRA) {
|
||||
copyRGBAtoBGRA(buffer, curLine); break;
|
||||
} else if (fmt == RGB) {
|
||||
copyRGBAtoRGB(buffer, curLine); break;
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported format for this image");
|
||||
}
|
||||
break;
|
||||
case COLOR_GREYSCALE:
|
||||
if ((fmt == LUMINANCE) || (fmt == ALPHA)) {
|
||||
copy(buffer, curLine);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported format for this image");
|
||||
}
|
||||
break;
|
||||
case COLOR_GREYALPHA:
|
||||
if (fmt == LUMINANCE_ALPHA) {
|
||||
copy(buffer, curLine);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported format for this image");
|
||||
}
|
||||
break;
|
||||
case COLOR_INDEXED:
|
||||
switch(bitdepth) {
|
||||
case 8: palLine = curLine; break;
|
||||
case 4: expand4(curLine, palLine); break;
|
||||
case 2: expand2(curLine, palLine); break;
|
||||
case 1: expand1(curLine, palLine); break;
|
||||
default: throw new UnsupportedOperationException("Unsupported bitdepth for this image");
|
||||
}
|
||||
if (fmt == ABGR) {
|
||||
copyPALtoABGR(buffer, palLine);
|
||||
} else if (fmt == RGBA) {
|
||||
copyPALtoRGBA(buffer, palLine);
|
||||
} else if (fmt == BGRA) {
|
||||
copyPALtoBGRA(buffer, palLine);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unsupported format for this image");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
byte[] tmp = curLine;
|
||||
curLine = prevLine;
|
||||
prevLine = tmp;
|
||||
}
|
||||
} finally {
|
||||
inflater.end();
|
||||
}
|
||||
}
|
||||
|
||||
private void copy(ByteBuffer buffer, byte[] curLine) {
|
||||
buffer.put(curLine, 1, curLine.length-1);
|
||||
}
|
||||
|
||||
private void copyRGBtoABGR(ByteBuffer buffer, byte[] curLine) {
|
||||
if(transPixel != null) {
|
||||
byte tr = transPixel[1];
|
||||
byte tg = transPixel[3];
|
||||
byte tb = transPixel[5];
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=3) {
|
||||
byte r = curLine[i];
|
||||
byte g = curLine[i+1];
|
||||
byte b = curLine[i+2];
|
||||
byte a = (byte)0xFF;
|
||||
if(r==tr && g==tg && b==tb) {
|
||||
a = 0;
|
||||
}
|
||||
buffer.put(a).put(b).put(g).put(r);
|
||||
}
|
||||
} else {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=3) {
|
||||
buffer.put((byte)0xFF).put(curLine[i+2]).put(curLine[i+1]).put(curLine[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyRGBtoRGBA(ByteBuffer buffer, byte[] curLine) {
|
||||
if(transPixel != null) {
|
||||
byte tr = transPixel[1];
|
||||
byte tg = transPixel[3];
|
||||
byte tb = transPixel[5];
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=3) {
|
||||
byte r = curLine[i];
|
||||
byte g = curLine[i+1];
|
||||
byte b = curLine[i+2];
|
||||
byte a = (byte)0xFF;
|
||||
if(r==tr && g==tg && b==tb) {
|
||||
a = 0;
|
||||
}
|
||||
buffer.put(r).put(g).put(b).put(a);
|
||||
}
|
||||
} else {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=3) {
|
||||
buffer.put(curLine[i]).put(curLine[i+1]).put(curLine[i+2]).put((byte)0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyRGBtoBGRA(ByteBuffer buffer, byte[] curLine) {
|
||||
if(transPixel != null) {
|
||||
byte tr = transPixel[1];
|
||||
byte tg = transPixel[3];
|
||||
byte tb = transPixel[5];
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=3) {
|
||||
byte r = curLine[i];
|
||||
byte g = curLine[i+1];
|
||||
byte b = curLine[i+2];
|
||||
byte a = (byte)0xFF;
|
||||
if(r==tr && g==tg && b==tb) {
|
||||
a = 0;
|
||||
}
|
||||
buffer.put(b).put(g).put(r).put(a);
|
||||
}
|
||||
} else {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=3) {
|
||||
buffer.put(curLine[i+2]).put(curLine[i+1]).put(curLine[i]).put((byte)0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyRGBAtoABGR(ByteBuffer buffer, byte[] curLine) {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=4) {
|
||||
buffer.put(curLine[i+3]).put(curLine[i+2]).put(curLine[i+1]).put(curLine[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyRGBAtoBGRA(ByteBuffer buffer, byte[] curLine) {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=4) {
|
||||
buffer.put(curLine[i+2]).put(curLine[i+1]).put(curLine[i+0]).put(curLine[i+3]);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyRGBAtoRGB(ByteBuffer buffer, byte[] curLine) {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=4) {
|
||||
buffer.put(curLine[i]).put(curLine[i+1]).put(curLine[i+2]);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyPALtoABGR(ByteBuffer buffer, byte[] curLine) {
|
||||
if(paletteA != null) {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=1) {
|
||||
int idx = curLine[i] & 255;
|
||||
byte r = palette[idx*3 + 0];
|
||||
byte g = palette[idx*3 + 1];
|
||||
byte b = palette[idx*3 + 2];
|
||||
byte a = paletteA[idx];
|
||||
buffer.put(a).put(b).put(g).put(r);
|
||||
}
|
||||
} else {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=1) {
|
||||
int idx = curLine[i] & 255;
|
||||
byte r = palette[idx*3 + 0];
|
||||
byte g = palette[idx*3 + 1];
|
||||
byte b = palette[idx*3 + 2];
|
||||
byte a = (byte)0xFF;
|
||||
buffer.put(a).put(b).put(g).put(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyPALtoRGBA(ByteBuffer buffer, byte[] curLine) {
|
||||
if(paletteA != null) {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=1) {
|
||||
int idx = curLine[i] & 255;
|
||||
byte r = palette[idx*3 + 0];
|
||||
byte g = palette[idx*3 + 1];
|
||||
byte b = palette[idx*3 + 2];
|
||||
byte a = paletteA[idx];
|
||||
buffer.put(r).put(g).put(b).put(a);
|
||||
}
|
||||
} else {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=1) {
|
||||
int idx = curLine[i] & 255;
|
||||
byte r = palette[idx*3 + 0];
|
||||
byte g = palette[idx*3 + 1];
|
||||
byte b = palette[idx*3 + 2];
|
||||
byte a = (byte)0xFF;
|
||||
buffer.put(r).put(g).put(b).put(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyPALtoBGRA(ByteBuffer buffer, byte[] curLine) {
|
||||
if(paletteA != null) {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=1) {
|
||||
int idx = curLine[i] & 255;
|
||||
byte r = palette[idx*3 + 0];
|
||||
byte g = palette[idx*3 + 1];
|
||||
byte b = palette[idx*3 + 2];
|
||||
byte a = paletteA[idx];
|
||||
buffer.put(b).put(g).put(r).put(a);
|
||||
}
|
||||
} else {
|
||||
for(int i=1,n=curLine.length ; i<n ; i+=1) {
|
||||
int idx = curLine[i] & 255;
|
||||
byte r = palette[idx*3 + 0];
|
||||
byte g = palette[idx*3 + 1];
|
||||
byte b = palette[idx*3 + 2];
|
||||
byte a = (byte)0xFF;
|
||||
buffer.put(b).put(g).put(r).put(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void expand4(byte[] src, byte[] dst) {
|
||||
for(int i=1,n=dst.length ; i<n ; i+=2) {
|
||||
int val = src[1 + (i >> 1)] & 255;
|
||||
switch(n-i) {
|
||||
default: dst[i+1] = (byte)(val & 15);
|
||||
case 1: dst[i ] = (byte)(val >> 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void expand2(byte[] src, byte[] dst) {
|
||||
for(int i=1,n=dst.length ; i<n ; i+=4) {
|
||||
int val = src[1 + (i >> 2)] & 255;
|
||||
switch(n-i) {
|
||||
default: dst[i+3] = (byte)((val ) & 3);
|
||||
case 3: dst[i+2] = (byte)((val >> 2) & 3);
|
||||
case 2: dst[i+1] = (byte)((val >> 4) & 3);
|
||||
case 1: dst[i ] = (byte)((val >> 6) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void expand1(byte[] src, byte[] dst) {
|
||||
for(int i=1,n=dst.length ; i<n ; i+=8) {
|
||||
int val = src[1 + (i >> 3)] & 255;
|
||||
switch(n-i) {
|
||||
default: dst[i+7] = (byte)((val ) & 1);
|
||||
case 7: dst[i+6] = (byte)((val >> 1) & 1);
|
||||
case 6: dst[i+5] = (byte)((val >> 2) & 1);
|
||||
case 5: dst[i+4] = (byte)((val >> 3) & 1);
|
||||
case 4: dst[i+3] = (byte)((val >> 4) & 1);
|
||||
case 3: dst[i+2] = (byte)((val >> 5) & 1);
|
||||
case 2: dst[i+1] = (byte)((val >> 6) & 1);
|
||||
case 1: dst[i ] = (byte)((val >> 7) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unfilter(byte[] curLine, byte[] prevLine) throws IOException {
|
||||
switch (curLine[0]) {
|
||||
case 0: // none
|
||||
break;
|
||||
case 1:
|
||||
unfilterSub(curLine);
|
||||
break;
|
||||
case 2:
|
||||
unfilterUp(curLine, prevLine);
|
||||
break;
|
||||
case 3:
|
||||
unfilterAverage(curLine, prevLine);
|
||||
break;
|
||||
case 4:
|
||||
unfilterPaeth(curLine, prevLine);
|
||||
break;
|
||||
default:
|
||||
throw new IOException("invalide filter type in scanline: " + curLine[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private void unfilterSub(byte[] curLine) {
|
||||
final int bpp = this.bytesPerPixel;
|
||||
for(int i=bpp+1,n=curLine.length ; i<n ; ++i) {
|
||||
curLine[i] += curLine[i-bpp];
|
||||
}
|
||||
}
|
||||
|
||||
private void unfilterUp(byte[] curLine, byte[] prevLine) {
|
||||
final int bpp = this.bytesPerPixel;
|
||||
for(int i=1,n=curLine.length ; i<n ; ++i) {
|
||||
curLine[i] += prevLine[i];
|
||||
}
|
||||
}
|
||||
|
||||
private void unfilterAverage(byte[] curLine, byte[] prevLine) {
|
||||
final int bpp = this.bytesPerPixel;
|
||||
|
||||
int i;
|
||||
for(i=1 ; i<=bpp ; ++i) {
|
||||
curLine[i] += (byte)((prevLine[i] & 0xFF) >>> 1);
|
||||
}
|
||||
for(int n=curLine.length ; i<n ; ++i) {
|
||||
curLine[i] += (byte)(((prevLine[i] & 0xFF) + (curLine[i - bpp] & 0xFF)) >>> 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void unfilterPaeth(byte[] curLine, byte[] prevLine) {
|
||||
final int bpp = this.bytesPerPixel;
|
||||
|
||||
int i;
|
||||
for(i=1 ; i<=bpp ; ++i) {
|
||||
curLine[i] += prevLine[i];
|
||||
}
|
||||
for(int n=curLine.length ; i<n ; ++i) {
|
||||
int a = curLine[i - bpp] & 255;
|
||||
int b = prevLine[i] & 255;
|
||||
int c = prevLine[i - bpp] & 255;
|
||||
int p = a + b - c;
|
||||
int pa = p - a; if(pa < 0) pa = -pa;
|
||||
int pb = p - b; if(pb < 0) pb = -pb;
|
||||
int pc = p - c; if(pc < 0) pc = -pc;
|
||||
if(pa<=pb && pa<=pc)
|
||||
c = a;
|
||||
else if(pb<=pc)
|
||||
c = b;
|
||||
curLine[i] += (byte)c;
|
||||
}
|
||||
}
|
||||
|
||||
private void readIHDR() throws IOException {
|
||||
checkChunkLength(13);
|
||||
readChunk(buffer, 0, 13);
|
||||
width = readInt(buffer, 0);
|
||||
height = readInt(buffer, 4);
|
||||
bitdepth = buffer[8] & 255;
|
||||
colorType = buffer[9] & 255;
|
||||
|
||||
switch (colorType) {
|
||||
case COLOR_GREYSCALE:
|
||||
if(bitdepth != 8) {
|
||||
throw new IOException("Unsupported bit depth: " + bitdepth);
|
||||
}
|
||||
bytesPerPixel = 1;
|
||||
break;
|
||||
case COLOR_GREYALPHA:
|
||||
if(bitdepth != 8) {
|
||||
throw new IOException("Unsupported bit depth: " + bitdepth);
|
||||
}
|
||||
bytesPerPixel = 2;
|
||||
break;
|
||||
case COLOR_TRUECOLOR:
|
||||
if(bitdepth != 8) {
|
||||
throw new IOException("Unsupported bit depth: " + bitdepth);
|
||||
}
|
||||
bytesPerPixel = 3;
|
||||
break;
|
||||
case COLOR_TRUEALPHA:
|
||||
if(bitdepth != 8) {
|
||||
throw new IOException("Unsupported bit depth: " + bitdepth);
|
||||
}
|
||||
bytesPerPixel = 4;
|
||||
break;
|
||||
case COLOR_INDEXED:
|
||||
switch(bitdepth) {
|
||||
case 8:
|
||||
case 4:
|
||||
case 2:
|
||||
case 1:
|
||||
bytesPerPixel = 1;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Unsupported bit depth: " + bitdepth);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IOException("unsupported color format: " + colorType);
|
||||
}
|
||||
|
||||
if(buffer[10] != 0) {
|
||||
throw new IOException("unsupported compression method");
|
||||
}
|
||||
if(buffer[11] != 0) {
|
||||
throw new IOException("unsupported filtering method");
|
||||
}
|
||||
if(buffer[12] != 0) {
|
||||
throw new IOException("unsupported interlace method");
|
||||
}
|
||||
}
|
||||
|
||||
private void readPLTE() throws IOException {
|
||||
int paletteEntries = chunkLength / 3;
|
||||
if(paletteEntries < 1 || paletteEntries > 256 || (chunkLength % 3) != 0) {
|
||||
throw new IOException("PLTE chunk has wrong length");
|
||||
}
|
||||
palette = new byte[paletteEntries*3];
|
||||
readChunk(palette, 0, palette.length);
|
||||
}
|
||||
|
||||
private void readtRNS() throws IOException {
|
||||
switch (colorType) {
|
||||
case COLOR_GREYSCALE:
|
||||
checkChunkLength(2);
|
||||
transPixel = new byte[2];
|
||||
readChunk(transPixel, 0, 2);
|
||||
break;
|
||||
case COLOR_TRUECOLOR:
|
||||
checkChunkLength(6);
|
||||
transPixel = new byte[6];
|
||||
readChunk(transPixel, 0, 6);
|
||||
break;
|
||||
case COLOR_INDEXED:
|
||||
if(palette == null) {
|
||||
throw new IOException("tRNS chunk without PLTE chunk");
|
||||
}
|
||||
paletteA = new byte[palette.length/3];
|
||||
Arrays.fill(paletteA, (byte)0xFF);
|
||||
readChunk(paletteA, 0, paletteA.length);
|
||||
break;
|
||||
default:
|
||||
// just ignore it
|
||||
}
|
||||
}
|
||||
|
||||
private void closeChunk() throws IOException {
|
||||
if(chunkRemaining > 0) {
|
||||
// just skip the rest and the CRC
|
||||
skip(chunkRemaining + 4);
|
||||
} else {
|
||||
readFully(buffer, 0, 4);
|
||||
int expectedCrc = readInt(buffer, 0);
|
||||
int computedCrc = (int)crc.getValue();
|
||||
if(computedCrc != expectedCrc) {
|
||||
throw new IOException("Invalid CRC");
|
||||
}
|
||||
}
|
||||
chunkRemaining = 0;
|
||||
chunkLength = 0;
|
||||
chunkType = 0;
|
||||
}
|
||||
|
||||
private void openChunk() throws IOException {
|
||||
readFully(buffer, 0, 8);
|
||||
chunkLength = readInt(buffer, 0);
|
||||
chunkType = readInt(buffer, 4);
|
||||
chunkRemaining = chunkLength;
|
||||
crc.reset();
|
||||
crc.update(buffer, 4, 4); // only chunkType
|
||||
}
|
||||
|
||||
private void openChunk(int expected) throws IOException {
|
||||
openChunk();
|
||||
if(chunkType != expected) {
|
||||
throw new IOException("Expected chunk: " + Integer.toHexString(expected));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkChunkLength(int expected) throws IOException {
|
||||
if(chunkLength != expected) {
|
||||
throw new IOException("Chunk has wrong size");
|
||||
}
|
||||
}
|
||||
|
||||
private int readChunk(byte[] buffer, int offset, int length) throws IOException {
|
||||
if(length > chunkRemaining) {
|
||||
length = chunkRemaining;
|
||||
}
|
||||
readFully(buffer, offset, length);
|
||||
crc.update(buffer, offset, length);
|
||||
chunkRemaining -= length;
|
||||
return length;
|
||||
}
|
||||
|
||||
private void refillInflater(Inflater inflater) throws IOException {
|
||||
while(chunkRemaining == 0) {
|
||||
closeChunk();
|
||||
openChunk(IDAT);
|
||||
}
|
||||
int read = readChunk(buffer, 0, buffer.length);
|
||||
inflater.setInput(buffer, 0, read);
|
||||
}
|
||||
|
||||
private void readChunkUnzip(Inflater inflater, byte[] buffer, int offset, int length) throws IOException {
|
||||
try {
|
||||
do {
|
||||
int read = inflater.inflate(buffer, offset, length);
|
||||
if(read <= 0) {
|
||||
if(inflater.finished()) {
|
||||
throw new EOFException();
|
||||
}
|
||||
if(inflater.needsInput()) {
|
||||
refillInflater(inflater);
|
||||
} else {
|
||||
throw new IOException("Can't inflate " + length + " bytes");
|
||||
}
|
||||
} else {
|
||||
offset += read;
|
||||
length -= read;
|
||||
}
|
||||
} while(length > 0);
|
||||
} catch (DataFormatException ex) {
|
||||
throw (IOException)(new IOException("inflate error").initCause(ex));
|
||||
}
|
||||
}
|
||||
|
||||
private void readFully(byte[] buffer, int offset, int length) throws IOException {
|
||||
do {
|
||||
int read = input.read(buffer, offset, length);
|
||||
if(read < 0) {
|
||||
throw new EOFException();
|
||||
}
|
||||
offset += read;
|
||||
length -= read;
|
||||
} while(length > 0);
|
||||
}
|
||||
|
||||
private int readInt(byte[] buffer, int offset) {
|
||||
return
|
||||
((buffer[offset ] ) << 24) |
|
||||
((buffer[offset+1] & 255) << 16) |
|
||||
((buffer[offset+2] & 255) << 8) |
|
||||
((buffer[offset+3] & 255) );
|
||||
}
|
||||
|
||||
private void skip(long amount) throws IOException {
|
||||
while(amount > 0) {
|
||||
long skipped = input.skip(amount);
|
||||
if(skipped < 0) {
|
||||
throw new EOFException();
|
||||
}
|
||||
amount -= skipped;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkSignature(byte[] buffer) {
|
||||
for(int i=0 ; i<SIGNATURE.length ; i++) {
|
||||
if(buffer[i] != SIGNATURE[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
202
lib/slick-source/org/newdawn/slick/opengl/PNGImageData.java
Normal file
202
lib/slick-source/org/newdawn/slick/opengl/PNGImageData.java
Normal file
@@ -0,0 +1,202 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
|
||||
/**
|
||||
* The PNG imge data source that is pure java reading PNGs
|
||||
*
|
||||
* @author Matthias Mann (original code)
|
||||
*/
|
||||
public class PNGImageData implements LoadableImageData {
|
||||
/** The width of the data loaded */
|
||||
private int width;
|
||||
/** The height of the data loaded */
|
||||
private int height;
|
||||
/** The texture height */
|
||||
private int texHeight;
|
||||
/** The texture width */
|
||||
private int texWidth;
|
||||
/** The decoder used to load the PNG */
|
||||
private PNGDecoder decoder;
|
||||
/** The bit depth of the image */
|
||||
private int bitDepth;
|
||||
/** The scratch buffer storing the image data */
|
||||
private ByteBuffer scratch;
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getDepth()
|
||||
*/
|
||||
public int getDepth() {
|
||||
return bitDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()
|
||||
*/
|
||||
public ByteBuffer getImageBufferData() {
|
||||
return scratch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexHeight()
|
||||
*/
|
||||
public int getTexHeight() {
|
||||
return texHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexWidth()
|
||||
*/
|
||||
public int getTexWidth() {
|
||||
return texWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis) throws IOException {
|
||||
return loadImage(fis, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {
|
||||
return loadImage(fis, flipped, false, transparent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, boolean forceAlpha, int[] transparent) throws IOException {
|
||||
if (transparent != null) {
|
||||
forceAlpha = true;
|
||||
throw new IOException("Transparent color not support in custom PNG Decoder");
|
||||
}
|
||||
|
||||
PNGDecoder decoder = new PNGDecoder(fis);
|
||||
|
||||
if (!decoder.isRGB()) {
|
||||
throw new IOException("Only RGB formatted images are supported by the PNGLoader");
|
||||
}
|
||||
|
||||
width = decoder.getWidth();
|
||||
height = decoder.getHeight();
|
||||
texWidth = get2Fold(width);
|
||||
texHeight = get2Fold(height);
|
||||
|
||||
int perPixel = decoder.hasAlpha() ? 4 : 3;
|
||||
bitDepth = decoder.hasAlpha() ? 32 : 24;
|
||||
|
||||
// Get a pointer to the image memory
|
||||
scratch = BufferUtils.createByteBuffer(texWidth * texHeight * perPixel);
|
||||
decoder.decode(scratch, texWidth * perPixel, perPixel == 4 ? PNGDecoder.RGBA : PNGDecoder.RGB);
|
||||
|
||||
if (height < texHeight-1) {
|
||||
int topOffset = (texHeight-1) * (texWidth*perPixel);
|
||||
int bottomOffset = (height-1) * (texWidth*perPixel);
|
||||
for (int x=0;x<texWidth;x++) {
|
||||
for (int i=0;i<perPixel;i++) {
|
||||
scratch.put(topOffset+x+i, scratch.get(x+i));
|
||||
scratch.put(bottomOffset+(texWidth*perPixel)+x+i, scratch.get(bottomOffset+x+i));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (width < texWidth-1) {
|
||||
for (int y=0;y<texHeight;y++) {
|
||||
for (int i=0;i<perPixel;i++) {
|
||||
scratch.put(((y+1)*(texWidth*perPixel))-perPixel+i, scratch.get(y*(texWidth*perPixel)+i));
|
||||
scratch.put((y*(texWidth*perPixel))+(width*perPixel)+i, scratch.get((y*(texWidth*perPixel))+((width-1)*perPixel)+i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!decoder.hasAlpha() && forceAlpha) {
|
||||
ByteBuffer temp = BufferUtils.createByteBuffer(texWidth * texHeight * 4);
|
||||
for (int x=0;x<texWidth;x++) {
|
||||
for (int y=0;y<texHeight;y++) {
|
||||
int srcOffset = (y*3)+(x*texHeight*3);
|
||||
int dstOffset = (y*4)+(x*texHeight*4);
|
||||
|
||||
temp.put(dstOffset, scratch.get(srcOffset));
|
||||
temp.put(dstOffset+1, scratch.get(srcOffset+1));
|
||||
temp.put(dstOffset+2, scratch.get(srcOffset+2));
|
||||
if ((x < getHeight()) && (y < getWidth())) {
|
||||
temp.put(dstOffset+3, (byte) 255);
|
||||
} else {
|
||||
temp.put(dstOffset+3, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitDepth = 32;
|
||||
scratch = temp;
|
||||
}
|
||||
|
||||
if (transparent != null) {
|
||||
for (int i=0;i<texWidth*texHeight*4;i+=4) {
|
||||
boolean match = true;
|
||||
for (int c=0;c<3;c++) {
|
||||
if (toInt(scratch.get(i+c)) != transparent[c]) {
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
scratch.put(i+3, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scratch.position(0);
|
||||
|
||||
return scratch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe convert byte to int
|
||||
*
|
||||
* @param b The byte to convert
|
||||
* @return The converted byte
|
||||
*/
|
||||
private int toInt(byte b) {
|
||||
if (b < 0) {
|
||||
return 256+b;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the closest greater power of 2 to the fold number
|
||||
*
|
||||
* @param fold The target number
|
||||
* @return The power of 2
|
||||
*/
|
||||
private int get2Fold(int fold) {
|
||||
int ret = 2;
|
||||
while (ret < fold) {
|
||||
ret *= 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#configureEdging(boolean)
|
||||
*/
|
||||
public void configureEdging(boolean edging) {
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
122
lib/slick-source/org/newdawn/slick/opengl/SlickCallable.java
Normal file
122
lib/slick-source/org/newdawn/slick/opengl/SlickCallable.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.opengl.renderer.Renderer;
|
||||
|
||||
/**
|
||||
* A utility to allow performing GL operations without contaminating the
|
||||
* Slick OpenGL state. Note this will not protect you from OpenGL programming errors
|
||||
* like a glBegin() without a glEnd(), or glPush() without glPop() etc.
|
||||
*
|
||||
* Expected usage:
|
||||
*
|
||||
* <code>
|
||||
* SlickCallable callable = new SlickCallable() {
|
||||
* public performGLOperations() throws SlickException {
|
||||
* GL.glTranslate(0,0,1);
|
||||
* glBegin(GL.GL_POLYGONS);
|
||||
* glVertex(..);
|
||||
* ...
|
||||
* glEnd();
|
||||
* }
|
||||
* }
|
||||
* callable.call();
|
||||
* </code>
|
||||
*
|
||||
* Alternatively you can use the static methods directly
|
||||
*
|
||||
* <code>
|
||||
* SlickCallable.enterSafeBlock();
|
||||
*
|
||||
* GL.glTranslate(0,0,1);
|
||||
* glBegin(GL.GL_POLYGONS);
|
||||
* glVertex(..);
|
||||
* ...
|
||||
* glEnd();
|
||||
*
|
||||
* SlickCallable.leaveSafeBlock();
|
||||
* </code>
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public abstract class SlickCallable {
|
||||
/** The last texture used */
|
||||
private static Texture lastUsed;
|
||||
/** True if we're in a safe block */
|
||||
private static boolean inSafe = false;
|
||||
|
||||
|
||||
/**
|
||||
* Enter a safe block ensuring that all the OpenGL state that slick
|
||||
* uses is safe before touching the GL state directly.
|
||||
*/
|
||||
public static void enterSafeBlock()
|
||||
{
|
||||
if (inSafe) {
|
||||
return;
|
||||
}
|
||||
|
||||
Renderer.get().flush();
|
||||
lastUsed = TextureImpl.getLastBind();
|
||||
TextureImpl.bindNone();
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glPushMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glPushMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
inSafe = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave a safe block ensuring that all of Slick's OpenGL state is
|
||||
* restored since the last enter.
|
||||
*/
|
||||
public static void leaveSafeBlock()
|
||||
{
|
||||
if (!inSafe) {
|
||||
return;
|
||||
}
|
||||
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glPopMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glPopMatrix();
|
||||
GL11.glPopClientAttrib();
|
||||
GL11.glPopAttrib();
|
||||
|
||||
if (lastUsed != null) {
|
||||
lastUsed.bind();
|
||||
} else {
|
||||
TextureImpl.bindNone();
|
||||
}
|
||||
|
||||
inSafe = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cause this callable to perform it's GL operations (@see performGLOperations()). This
|
||||
* method will block until the GL operations have been performed.
|
||||
*
|
||||
* @throws SlickException Indicates a failure while performing the GL operations or
|
||||
* maintaing SlickState
|
||||
*/
|
||||
public final void call() throws SlickException {
|
||||
enterSafeBlock();
|
||||
|
||||
performGLOperations();
|
||||
|
||||
leaveSafeBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the GL operations that this callable is intended to. This operations should
|
||||
* not effect the slick OpenGL state.
|
||||
*
|
||||
* @throws SlickException Indicates a failure of some sort. This is user exception
|
||||
*/
|
||||
protected abstract void performGLOperations() throws SlickException;
|
||||
}
|
||||
319
lib/slick-source/org/newdawn/slick/opengl/TGAImageData.java
Normal file
319
lib/slick-source/org/newdawn/slick/opengl/TGAImageData.java
Normal file
@@ -0,0 +1,319 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
|
||||
/**
|
||||
* A utility to load TGAs. Note: NOT THREAD SAFE
|
||||
*
|
||||
* Fresh cut of code but largely influeneced by the TGA loading class
|
||||
* provided as part of the Java Monkey Engine (JME). Why not check out
|
||||
* what they're doing over at http://www.jmonkeyengine.com. kudos to
|
||||
* Mark Powell.
|
||||
*
|
||||
* @author Kevin Glass
|
||||
*/
|
||||
public class TGAImageData implements LoadableImageData {
|
||||
/** The width of the texture that needs to be generated */
|
||||
private int texWidth;
|
||||
/** The height of the texture that needs to be generated */
|
||||
private int texHeight;
|
||||
/** The width of the TGA image */
|
||||
private int width;
|
||||
/** The height of the TGA image */
|
||||
private int height;
|
||||
/** The bit depth of the image */
|
||||
private short pixelDepth;
|
||||
|
||||
/**
|
||||
* Create a new TGA Loader
|
||||
*/
|
||||
public TGAImageData() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the endian-ness of the short
|
||||
*
|
||||
* @param signedShort The short to flip
|
||||
* @return The flipped short
|
||||
*/
|
||||
private short flipEndian(short signedShort) {
|
||||
int input = signedShort & 0xFFFF;
|
||||
return (short) (input << 8 | (input & 0xFF00) >>> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getDepth()
|
||||
*/
|
||||
public int getDepth() {
|
||||
return pixelDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getWidth()
|
||||
*/
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getHeight()
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexWidth()
|
||||
*/
|
||||
public int getTexWidth() {
|
||||
return texWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getTexHeight()
|
||||
*/
|
||||
public int getTexHeight() {
|
||||
return texHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis) throws IOException {
|
||||
return loadImage(fis,true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {
|
||||
return loadImage(fis, flipped, false, transparent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])
|
||||
*/
|
||||
public ByteBuffer loadImage(InputStream fis, boolean flipped, boolean forceAlpha, int[] transparent) throws IOException {
|
||||
if (transparent != null) {
|
||||
forceAlpha = true;
|
||||
}
|
||||
byte red = 0;
|
||||
byte green = 0;
|
||||
byte blue = 0;
|
||||
byte alpha = 0;
|
||||
|
||||
BufferedInputStream bis = new BufferedInputStream(fis, 100000);
|
||||
DataInputStream dis = new DataInputStream(bis);
|
||||
|
||||
// Read in the Header
|
||||
short idLength = (short) dis.read();
|
||||
short colorMapType = (short) dis.read();
|
||||
short imageType = (short) dis.read();
|
||||
short cMapStart = flipEndian(dis.readShort());
|
||||
short cMapLength = flipEndian(dis.readShort());
|
||||
short cMapDepth = (short) dis.read();
|
||||
short xOffset = flipEndian(dis.readShort());
|
||||
short yOffset = flipEndian(dis.readShort());
|
||||
|
||||
if (imageType != 2) {
|
||||
throw new IOException("Slick only supports uncompressed RGB(A) TGA images");
|
||||
}
|
||||
|
||||
width = flipEndian(dis.readShort());
|
||||
height = flipEndian(dis.readShort());
|
||||
pixelDepth = (short) dis.read();
|
||||
if (pixelDepth == 32) {
|
||||
forceAlpha = false;
|
||||
}
|
||||
|
||||
texWidth = get2Fold(width);
|
||||
texHeight = get2Fold(height);
|
||||
|
||||
short imageDescriptor = (short) dis.read();
|
||||
if ((imageDescriptor & 0x0020) == 0) {
|
||||
flipped = !flipped;
|
||||
}
|
||||
|
||||
// Skip image ID
|
||||
if (idLength > 0) {
|
||||
bis.skip(idLength);
|
||||
}
|
||||
|
||||
byte[] rawData = null;
|
||||
if ((pixelDepth == 32) || (forceAlpha)) {
|
||||
pixelDepth = 32;
|
||||
rawData = new byte[texWidth * texHeight * 4];
|
||||
} else if (pixelDepth == 24) {
|
||||
rawData = new byte[texWidth * texHeight * 3];
|
||||
} else {
|
||||
throw new RuntimeException("Only 24 and 32 bit TGAs are supported");
|
||||
}
|
||||
|
||||
if (pixelDepth == 24) {
|
||||
if (flipped) {
|
||||
for (int i = height-1; i >= 0; i--) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
blue = dis.readByte();
|
||||
green = dis.readByte();
|
||||
red = dis.readByte();
|
||||
|
||||
int ofs = ((j + (i * texWidth)) * 3);
|
||||
rawData[ofs] = red;
|
||||
rawData[ofs + 1] = green;
|
||||
rawData[ofs + 2] = blue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
blue = dis.readByte();
|
||||
green = dis.readByte();
|
||||
red = dis.readByte();
|
||||
|
||||
int ofs = ((j + (i * texWidth)) * 3);
|
||||
rawData[ofs] = red;
|
||||
rawData[ofs + 1] = green;
|
||||
rawData[ofs + 2] = blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pixelDepth == 32) {
|
||||
if (flipped) {
|
||||
for (int i = height-1; i >= 0; i--) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
blue = dis.readByte();
|
||||
green = dis.readByte();
|
||||
red = dis.readByte();
|
||||
if (forceAlpha) {
|
||||
alpha = (byte) 255;
|
||||
} else {
|
||||
alpha = dis.readByte();
|
||||
}
|
||||
|
||||
int ofs = ((j + (i * texWidth)) * 4);
|
||||
|
||||
rawData[ofs] = red;
|
||||
rawData[ofs + 1] = green;
|
||||
rawData[ofs + 2] = blue;
|
||||
rawData[ofs + 3] = alpha;
|
||||
|
||||
if (alpha == 0) {
|
||||
rawData[ofs + 2] = (byte) 0;
|
||||
rawData[ofs + 1] = (byte) 0;
|
||||
rawData[ofs] = (byte) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
blue = dis.readByte();
|
||||
green = dis.readByte();
|
||||
red = dis.readByte();
|
||||
if (forceAlpha) {
|
||||
alpha = (byte) 255;
|
||||
} else {
|
||||
alpha = dis.readByte();
|
||||
}
|
||||
|
||||
int ofs = ((j + (i * texWidth)) * 4);
|
||||
|
||||
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
|
||||
rawData[ofs] = red;
|
||||
rawData[ofs + 1] = green;
|
||||
rawData[ofs + 2] = blue;
|
||||
rawData[ofs + 3] = alpha;
|
||||
} else {
|
||||
rawData[ofs] = red;
|
||||
rawData[ofs + 1] = green;
|
||||
rawData[ofs + 2] = blue;
|
||||
rawData[ofs + 3] = alpha;
|
||||
}
|
||||
|
||||
if (alpha == 0) {
|
||||
rawData[ofs + 2] = 0;
|
||||
rawData[ofs + 1] = 0;
|
||||
rawData[ofs] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fis.close();
|
||||
|
||||
if (transparent != null) {
|
||||
for (int i=0;i<rawData.length;i+=4) {
|
||||
boolean match = true;
|
||||
for (int c=0;c<3;c++) {
|
||||
if (rawData[i+c] != transparent[c]) {
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
rawData[i+3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get a pointer to the image memory
|
||||
ByteBuffer scratch = BufferUtils.createByteBuffer(rawData.length);
|
||||
scratch.put(rawData);
|
||||
|
||||
int perPixel = pixelDepth / 8;
|
||||
if (height < texHeight-1) {
|
||||
int topOffset = (texHeight-1) * (texWidth*perPixel);
|
||||
int bottomOffset = (height-1) * (texWidth*perPixel);
|
||||
for (int x=0;x<texWidth*perPixel;x++) {
|
||||
scratch.put(topOffset+x, scratch.get(x));
|
||||
scratch.put(bottomOffset+(texWidth*perPixel)+x, scratch.get((texWidth*perPixel)+x));
|
||||
}
|
||||
}
|
||||
if (width < texWidth-1) {
|
||||
for (int y=0;y<texHeight;y++) {
|
||||
for (int i=0;i<perPixel;i++) {
|
||||
scratch.put(((y+1)*(texWidth*perPixel))-perPixel+i, scratch.get(y*(texWidth*perPixel)+i));
|
||||
scratch.put((y*(texWidth*perPixel))+(width*perPixel)+i, scratch.get((y*(texWidth*perPixel))+((width-1)*perPixel)+i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scratch.flip();
|
||||
|
||||
return scratch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the closest greater power of 2 to the fold number
|
||||
*
|
||||
* @param fold The target number
|
||||
* @return The power of 2
|
||||
*/
|
||||
private int get2Fold(int fold) {
|
||||
int ret = 2;
|
||||
while (ret < fold) {
|
||||
ret *= 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()
|
||||
*/
|
||||
public ByteBuffer getImageBufferData() {
|
||||
throw new RuntimeException("TGAImageData doesn't store it's image.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.LoadableImageData#configureEdging(boolean)
|
||||
*/
|
||||
public void configureEdging(boolean edging) {
|
||||
}
|
||||
}
|
||||
97
lib/slick-source/org/newdawn/slick/opengl/Texture.java
Normal file
97
lib/slick-source/org/newdawn/slick/opengl/Texture.java
Normal file
@@ -0,0 +1,97 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
/**
|
||||
* The description of a texture loaded by the TextureLoader utility
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public interface Texture {
|
||||
|
||||
/**
|
||||
* Check if the texture has alpha
|
||||
*
|
||||
* @return True if the texture has alpha
|
||||
*/
|
||||
public boolean hasAlpha();
|
||||
|
||||
/**
|
||||
* Get the reference from which this texture was loaded
|
||||
*
|
||||
* @return The reference from which this texture was loaded
|
||||
*/
|
||||
public String getTextureRef();
|
||||
|
||||
/**
|
||||
* Bind the GL context to a texture
|
||||
*/
|
||||
public void bind();
|
||||
|
||||
/**
|
||||
* Get the height of the original image
|
||||
*
|
||||
* @return The height of the original image
|
||||
*/
|
||||
public int getImageHeight();
|
||||
|
||||
/**
|
||||
* Get the width of the original image
|
||||
*
|
||||
* @return The width of the original image
|
||||
*/
|
||||
public int getImageWidth();
|
||||
|
||||
/**
|
||||
* Get the height of the physical texture
|
||||
*
|
||||
* @return The height of physical texture
|
||||
*/
|
||||
public float getHeight();
|
||||
|
||||
/**
|
||||
* Get the width of the physical texture
|
||||
*
|
||||
* @return The width of physical texture
|
||||
*/
|
||||
public float getWidth();
|
||||
|
||||
/**
|
||||
* Get the height of the actual texture
|
||||
*
|
||||
* @return The height of the actual texture
|
||||
*/
|
||||
public int getTextureHeight();
|
||||
|
||||
/**
|
||||
* Get the width of the actual texture
|
||||
*
|
||||
* @return The width of the actual texture
|
||||
*/
|
||||
public int getTextureWidth();
|
||||
|
||||
/**
|
||||
* Destroy the texture reference
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Get the OpenGL texture ID for this texture
|
||||
*
|
||||
* @return The OpenGL texture ID
|
||||
*/
|
||||
public int getTextureID();
|
||||
|
||||
/**
|
||||
* Get the pixel data from the card for this texture
|
||||
*
|
||||
* @return The texture data from the card for this texture
|
||||
*/
|
||||
public byte[] getTextureData();
|
||||
|
||||
/**
|
||||
* Apply a given texture filter to the texture
|
||||
*
|
||||
* @param textureFilter The texture filter to apply (GL_LINEAR, GL_NEAREST, etc..)
|
||||
*/
|
||||
public void setTextureFilter(int textureFilter);
|
||||
|
||||
}
|
||||
377
lib/slick-source/org/newdawn/slick/opengl/TextureImpl.java
Normal file
377
lib/slick-source/org/newdawn/slick/opengl/TextureImpl.java
Normal file
@@ -0,0 +1,377 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.newdawn.slick.opengl.renderer.Renderer;
|
||||
import org.newdawn.slick.opengl.renderer.SGL;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A texture to be bound within JOGL. This object is responsible for
|
||||
* keeping track of a given OpenGL texture and for calculating the
|
||||
* texturing mapping coordinates of the full image.
|
||||
*
|
||||
* Since textures need to be powers of 2 the actual texture may be
|
||||
* considerably bigged that the source image and hence the texture
|
||||
* mapping coordinates need to be adjusted to matchup drawing the
|
||||
* sprite against the texture.
|
||||
*
|
||||
* @author Kevin Glass
|
||||
* @author Brian Matzon
|
||||
*/
|
||||
public class TextureImpl implements Texture {
|
||||
/** The renderer to use for all GL operations */
|
||||
protected static SGL GL = Renderer.get();
|
||||
|
||||
/** The last texture that was bound to */
|
||||
static Texture lastBind;
|
||||
|
||||
/**
|
||||
* Retrieve the last texture bound through the texture interface
|
||||
*
|
||||
* @return The last texture bound
|
||||
*/
|
||||
public static Texture getLastBind() {
|
||||
return lastBind;
|
||||
}
|
||||
|
||||
/** The GL target type */
|
||||
private int target;
|
||||
/** The GL texture ID */
|
||||
private int textureID;
|
||||
/** The height of the image */
|
||||
private int height;
|
||||
/** The width of the image */
|
||||
private int width;
|
||||
/** The width of the texture */
|
||||
private int texWidth;
|
||||
/** The height of the texture */
|
||||
private int texHeight;
|
||||
/** The ratio of the width of the image to the texture */
|
||||
private float widthRatio;
|
||||
/** The ratio of the height of the image to the texture */
|
||||
private float heightRatio;
|
||||
/** If this texture has alpha */
|
||||
private boolean alpha;
|
||||
/** The reference this texture was loaded from */
|
||||
private String ref;
|
||||
/** The name the texture has in the cache */
|
||||
private String cacheName;
|
||||
|
||||
/** Data used to reload this texture */
|
||||
private ReloadData reloadData;
|
||||
|
||||
/**
|
||||
* For subclasses to utilise
|
||||
*/
|
||||
protected TextureImpl() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new texture
|
||||
*
|
||||
* @param ref The reference this texture was loaded from
|
||||
* @param target The GL target
|
||||
* @param textureID The GL texture ID
|
||||
*/
|
||||
public TextureImpl(String ref, int target,int textureID) {
|
||||
this.target = target;
|
||||
this.ref = ref;
|
||||
this.textureID = textureID;
|
||||
lastBind = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name this texture is stored against in the cache
|
||||
*
|
||||
* @param cacheName The name the texture is stored against in the cache
|
||||
*/
|
||||
public void setCacheName(String cacheName) {
|
||||
this.cacheName = cacheName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#hasAlpha()
|
||||
*/
|
||||
public boolean hasAlpha() {
|
||||
return alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getTextureRef()
|
||||
*/
|
||||
public String getTextureRef() {
|
||||
return ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this texture has alpha
|
||||
*
|
||||
* @param alpha True, If this texture has alpha
|
||||
*/
|
||||
public void setAlpha(boolean alpha) {
|
||||
this.alpha = alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the binding of the texture
|
||||
*/
|
||||
public static void bindNone() {
|
||||
lastBind = null;
|
||||
GL.glDisable(SGL.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear slick caching of the last bound texture so that an
|
||||
* external texture binder can play with the context before returning
|
||||
* control to slick.
|
||||
*/
|
||||
public static void unbind() {
|
||||
lastBind = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#bind()
|
||||
*/
|
||||
public void bind() {
|
||||
if (lastBind != this) {
|
||||
lastBind = this;
|
||||
GL.glEnable(SGL.GL_TEXTURE_2D);
|
||||
GL.glBindTexture(target, textureID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of the image
|
||||
*
|
||||
* @param height The height of the image
|
||||
*/
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
setHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the image
|
||||
*
|
||||
* @param width The width of the image
|
||||
*/
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
setWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getImageHeight()
|
||||
*/
|
||||
public int getImageHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getImageWidth()
|
||||
*/
|
||||
public int getImageWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getHeight()
|
||||
*/
|
||||
public float getHeight() {
|
||||
return heightRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getWidth()
|
||||
*/
|
||||
public float getWidth() {
|
||||
return widthRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getTextureHeight()
|
||||
*/
|
||||
public int getTextureHeight() {
|
||||
return texHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getTextureWidth()
|
||||
*/
|
||||
public int getTextureWidth() {
|
||||
return texWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of this texture
|
||||
*
|
||||
* @param texHeight The height of the texture
|
||||
*/
|
||||
public void setTextureHeight(int texHeight) {
|
||||
this.texHeight = texHeight;
|
||||
setHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of this texture
|
||||
*
|
||||
* @param texWidth The width of the texture
|
||||
*/
|
||||
public void setTextureWidth(int texWidth) {
|
||||
this.texWidth = texWidth;
|
||||
setWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of the texture. This will update the
|
||||
* ratio also.
|
||||
*/
|
||||
private void setHeight() {
|
||||
if (texHeight != 0) {
|
||||
heightRatio = ((float) height)/texHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the texture. This will update the
|
||||
* ratio also.
|
||||
*/
|
||||
private void setWidth() {
|
||||
if (texWidth != 0) {
|
||||
widthRatio = ((float) width)/texWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#release()
|
||||
*/
|
||||
public void release() {
|
||||
IntBuffer texBuf = createIntBuffer(1);
|
||||
texBuf.put(textureID);
|
||||
texBuf.flip();
|
||||
|
||||
GL.glDeleteTextures(texBuf);
|
||||
|
||||
if (lastBind == this) {
|
||||
bindNone();
|
||||
}
|
||||
|
||||
if (cacheName != null) {
|
||||
InternalTextureLoader.get().clear(cacheName);
|
||||
} else {
|
||||
InternalTextureLoader.get().clear(ref);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getTextureID()
|
||||
*/
|
||||
public int getTextureID() {
|
||||
return textureID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the OpenGL texture ID for this texture
|
||||
*
|
||||
* @param textureID The OpenGL texture ID
|
||||
*/
|
||||
public void setTextureID(int textureID) {
|
||||
this.textureID = textureID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an integer buffer to hold specified ints
|
||||
* - strictly a utility method
|
||||
*
|
||||
* @param size how many int to contain
|
||||
* @return created IntBuffer
|
||||
*/
|
||||
protected IntBuffer createIntBuffer(int size) {
|
||||
ByteBuffer temp = ByteBuffer.allocateDirect(4 * size);
|
||||
temp.order(ByteOrder.nativeOrder());
|
||||
|
||||
return temp.asIntBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#getTextureData()
|
||||
*/
|
||||
public byte[] getTextureData() {
|
||||
ByteBuffer buffer = BufferUtils.createByteBuffer((hasAlpha() ? 4 : 3) * texWidth * texHeight);
|
||||
bind();
|
||||
GL.glGetTexImage(SGL.GL_TEXTURE_2D, 0, hasAlpha() ? SGL.GL_RGBA : SGL.GL_RGB, SGL.GL_UNSIGNED_BYTE,
|
||||
buffer);
|
||||
byte[] data = new byte[buffer.limit()];
|
||||
buffer.get(data);
|
||||
buffer.clear();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.Texture#setTextureFilter(int)
|
||||
*/
|
||||
public void setTextureFilter(int textureFilter) {
|
||||
bind();
|
||||
GL.glTexParameteri(target, SGL.GL_TEXTURE_MIN_FILTER, textureFilter);
|
||||
GL.glTexParameteri(target, SGL.GL_TEXTURE_MAG_FILTER, textureFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the texture data that this texture can be reloaded from
|
||||
*
|
||||
* @param srcPixelFormat The pixel format
|
||||
* @param componentCount The component count
|
||||
* @param minFilter The OpenGL minification filter
|
||||
* @param magFilter The OpenGL magnification filter
|
||||
* @param textureBuffer The texture buffer containing the data for the texture
|
||||
*/
|
||||
public void setTextureData(int srcPixelFormat, int componentCount,
|
||||
int minFilter, int magFilter, ByteBuffer textureBuffer) {
|
||||
reloadData = new ReloadData();
|
||||
reloadData.srcPixelFormat = srcPixelFormat;
|
||||
reloadData.componentCount = componentCount;
|
||||
reloadData.minFilter = minFilter;
|
||||
reloadData.magFilter = magFilter;
|
||||
reloadData.textureBuffer = textureBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload this texture
|
||||
*/
|
||||
public void reload() {
|
||||
if (reloadData != null) {
|
||||
textureID = reloadData.reload();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload this texture from it's original source data
|
||||
*/
|
||||
private class ReloadData {
|
||||
/** The src pixel format */
|
||||
private int srcPixelFormat;
|
||||
/** The component count */
|
||||
private int componentCount;
|
||||
/** The OpenGL minification filter */
|
||||
private int minFilter;
|
||||
/** The OpenGL magnification filter */
|
||||
private int magFilter;
|
||||
/** The texture buffer of pixel data */
|
||||
private ByteBuffer textureBuffer;
|
||||
|
||||
/**
|
||||
* Reload this texture
|
||||
*
|
||||
* @return The new texture ID assigned to this texture
|
||||
*/
|
||||
public int reload() {
|
||||
Log.error("Reloading texture: "+ref);
|
||||
return InternalTextureLoader.get().reload(TextureImpl.this, srcPixelFormat, componentCount, minFilter, magFilter, textureBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
66
lib/slick-source/org/newdawn/slick/opengl/TextureLoader.java
Normal file
66
lib/slick-source/org/newdawn/slick/opengl/TextureLoader.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package org.newdawn.slick.opengl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
/**
|
||||
* A utility class to wrap the Slick internal texture loader and present a
|
||||
* rational interface.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class TextureLoader {
|
||||
/**
|
||||
* Load a texture with a given format from the supplied input stream
|
||||
*
|
||||
* @param format The format of the texture to be loaded (something like "PNG" or "TGA")
|
||||
* @param in The input stream from which the image data will be read
|
||||
* @return The newly created texture
|
||||
* @throws IOException Indicates a failure to read the image data
|
||||
*/
|
||||
public static Texture getTexture(String format, InputStream in) throws IOException {
|
||||
return getTexture(format, in, false, GL11.GL_LINEAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a texture with a given format from the supplied input stream
|
||||
*
|
||||
* @param format The format of the texture to be loaded (something like "PNG" or "TGA")
|
||||
* @param in The input stream from which the image data will be read
|
||||
* @param flipped True if the image should be flipped vertically on loading
|
||||
* @return The newly created texture
|
||||
* @throws IOException Indicates a failure to read the image data
|
||||
*/
|
||||
public static Texture getTexture(String format, InputStream in, boolean flipped) throws IOException {
|
||||
return getTexture(format, in, flipped, GL11.GL_LINEAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a texture with a given format from the supplied input stream
|
||||
*
|
||||
* @param format The format of the texture to be loaded (something like "PNG" or "TGA")
|
||||
* @param in The input stream from which the image data will be read
|
||||
* @param filter The GL texture filter to use for scaling up and down
|
||||
* @return The newly created texture
|
||||
* @throws IOException Indicates a failure to read the image data
|
||||
*/
|
||||
public static Texture getTexture(String format, InputStream in, int filter) throws IOException {
|
||||
return getTexture(format, in, false, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a texture with a given format from the supplied input stream
|
||||
*
|
||||
* @param format The format of the texture to be loaded (something like "PNG" or "TGA")
|
||||
* @param in The input stream from which the image data will be read
|
||||
* @param flipped True if the image should be flipped vertically on loading
|
||||
* @param filter The GL texture filter to use for scaling up and down
|
||||
* @return The newly created texture
|
||||
* @throws IOException Indicates a failure to read the image data
|
||||
*/
|
||||
public static Texture getTexture(String format, InputStream in, boolean flipped, int filter) throws IOException {
|
||||
return InternalTextureLoader.get().getTexture(in, in.toString()+"."+format, flipped, filter);
|
||||
}
|
||||
}
|
||||
4
lib/slick-source/org/newdawn/slick/opengl/package.html
Normal file
4
lib/slick-source/org/newdawn/slick/opengl/package.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<BODY>
|
||||
This package contains the nitty gritty image manipulation code for using OpenGL with standard image formats. As
|
||||
a user you shouldn't need to access anything here directly.
|
||||
</BODY>
|
||||
@@ -0,0 +1,228 @@
|
||||
package org.newdawn.slick.opengl.pbuffer;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.EXTFramebufferObject;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GLContext;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.opengl.InternalTextureLoader;
|
||||
import org.newdawn.slick.opengl.SlickCallable;
|
||||
import org.newdawn.slick.opengl.Texture;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A graphics implementation that renders to an FBO
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class FBOGraphics extends Graphics {
|
||||
/** The image we're we're sort of rendering to */
|
||||
private Image image;
|
||||
/** The ID of the FBO in use */
|
||||
private int FBO;
|
||||
/** True if this context is valid */
|
||||
private boolean valid = true;
|
||||
|
||||
/**
|
||||
* Create a new graphics context around an FBO
|
||||
*
|
||||
* @param image The image we're rendering to
|
||||
* @throws SlickException Indicates a failure to use pbuffers
|
||||
*/
|
||||
public FBOGraphics(Image image) throws SlickException {
|
||||
super(image.getTexture().getTextureWidth(), image.getTexture().getTextureHeight());
|
||||
this.image = image;
|
||||
|
||||
Log.debug("Creating FBO "+image.getWidth()+"x"+image.getHeight());
|
||||
|
||||
boolean FBOEnabled = GLContext.getCapabilities().GL_EXT_framebuffer_object;
|
||||
if (!FBOEnabled) {
|
||||
throw new SlickException("Your OpenGL card does not support FBO and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the FBO for completeness as shown in the LWJGL tutorial
|
||||
*
|
||||
* @throws SlickException Indicates an incomplete FBO
|
||||
*/
|
||||
private void completeCheck() throws SlickException {
|
||||
int framebuffer = EXTFramebufferObject.glCheckFramebufferStatusEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT);
|
||||
switch ( framebuffer ) {
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
break;
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT exception" );
|
||||
case EXTFramebufferObject.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
throw new SlickException( "FrameBuffer: " + FBO
|
||||
+ ", has caused a GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT exception" );
|
||||
default:
|
||||
throw new SlickException( "Unexpected reply from glCheckFramebufferStatusEXT: " + framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the FBO that will be used to render to
|
||||
*
|
||||
* @throws SlickException
|
||||
*/
|
||||
private void init() throws SlickException {
|
||||
IntBuffer buffer = BufferUtils.createIntBuffer(1);
|
||||
EXTFramebufferObject.glGenFramebuffersEXT(buffer);
|
||||
FBO = buffer.get();
|
||||
|
||||
// for some reason FBOs won't work on textures unless you've absolutely just
|
||||
// created them.
|
||||
try {
|
||||
Texture tex = InternalTextureLoader.get().createTexture(image.getWidth(), image.getHeight(), image.getFilter());
|
||||
|
||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, FBO);
|
||||
EXTFramebufferObject.glFramebufferTexture2DEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT,
|
||||
EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL11.GL_TEXTURE_2D, tex.getTextureID(), 0);
|
||||
|
||||
completeCheck();
|
||||
unbind();
|
||||
|
||||
// Clear our destination area before using it
|
||||
clear();
|
||||
flush();
|
||||
|
||||
// keep hold of the original content
|
||||
drawImage(image, 0, 0);
|
||||
image.setTexture(tex);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new SlickException("Failed to create new texture for FBO");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind to the FBO created
|
||||
*/
|
||||
private void bind() {
|
||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, FBO);
|
||||
GL11.glReadBuffer(EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind from the FBO created
|
||||
*/
|
||||
private void unbind() {
|
||||
EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0);
|
||||
GL11.glReadBuffer(GL11.GL_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#disable()
|
||||
*/
|
||||
protected void disable() {
|
||||
GL.flush();
|
||||
|
||||
unbind();
|
||||
GL11.glPopClientAttrib();
|
||||
GL11.glPopAttrib();
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glPopMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glPopMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
SlickCallable.leaveSafeBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#enable()
|
||||
*/
|
||||
protected void enable() {
|
||||
if (!valid) {
|
||||
throw new RuntimeException("Attempt to use a destroy()ed offscreen graphics context.");
|
||||
}
|
||||
SlickCallable.enterSafeBlock();
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glPushClientAttrib(GL11.GL_ALL_CLIENT_ATTRIB_BITS);
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glPushMatrix();
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glPushMatrix();
|
||||
|
||||
bind();
|
||||
initGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the GL context
|
||||
*/
|
||||
protected void initGL() {
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
|
||||
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GL11.glClearDepth(1);
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GL11.glViewport(0,0,screenWidth,screenHeight);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glLoadIdentity();
|
||||
|
||||
enterOrtho();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter the orthographic mode
|
||||
*/
|
||||
protected void enterOrtho() {
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glOrtho(0, screenWidth, 0, screenHeight, 1, -1);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
IntBuffer buffer = BufferUtils.createIntBuffer(1);
|
||||
buffer.put(FBO);
|
||||
buffer.flip();
|
||||
|
||||
EXTFramebufferObject.glDeleteFramebuffersEXT(buffer);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
image.flushPixelData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package org.newdawn.slick.opengl.pbuffer;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.lwjgl.opengl.GLContext;
|
||||
import org.lwjgl.opengl.Pbuffer;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A factory to produce an appropriate render to texture graphics context based on current
|
||||
* hardware
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class GraphicsFactory {
|
||||
/** The graphics list of graphics contexts created */
|
||||
private static HashMap graphics = new HashMap();
|
||||
/** True if pbuffers are supported */
|
||||
private static boolean pbuffer = true;
|
||||
/** True if pbuffer render to texture are supported */
|
||||
private static boolean pbufferRT = true;
|
||||
/** True if fbo are supported */
|
||||
private static boolean fbo = true;
|
||||
/** True if we've initialised */
|
||||
private static boolean init = false;
|
||||
|
||||
/**
|
||||
* Initialise offscreen rendering by checking what buffers are supported
|
||||
* by the card
|
||||
*
|
||||
* @throws SlickException Indicates no buffers are supported
|
||||
*/
|
||||
private static void init() throws SlickException {
|
||||
init = true;
|
||||
|
||||
if (fbo) {
|
||||
fbo = GLContext.getCapabilities().GL_EXT_framebuffer_object;
|
||||
}
|
||||
pbuffer = (Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) != 0;
|
||||
pbufferRT = (Pbuffer.getCapabilities() & Pbuffer.RENDER_TEXTURE_SUPPORTED) != 0;
|
||||
|
||||
if (!fbo && !pbuffer && !pbufferRT) {
|
||||
throw new SlickException("Your OpenGL card does not support offscreen buffers and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
|
||||
Log.info("Offscreen Buffers FBO="+fbo+" PBUFFER="+pbuffer+" PBUFFERRT="+pbufferRT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force FBO use on or off
|
||||
*
|
||||
* @param useFBO True if we should try and use FBO for offscreen images
|
||||
*/
|
||||
public static void setUseFBO(boolean useFBO) {
|
||||
fbo = useFBO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're using FBO for dynamic textures
|
||||
*
|
||||
* @return True if we're using FBOs
|
||||
*/
|
||||
public static boolean usingFBO() {
|
||||
return fbo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're using PBuffer for dynamic textures
|
||||
*
|
||||
* @return True if we're using PBuffer
|
||||
*/
|
||||
public static boolean usingPBuffer() {
|
||||
return !fbo && pbuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a graphics context for a particular image
|
||||
*
|
||||
* @param image The image for which to retrieve the graphics context
|
||||
* @return The graphics context
|
||||
* @throws SlickException Indicates it wasn't possible to create a graphics context
|
||||
* given available hardware.
|
||||
*/
|
||||
public static Graphics getGraphicsForImage(Image image) throws SlickException {
|
||||
Graphics g = (Graphics) graphics.get(image.getTexture());
|
||||
|
||||
if (g == null) {
|
||||
g = createGraphics(image);
|
||||
graphics.put(image.getTexture(), g);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release any graphics context that is assocaited with the given image
|
||||
*
|
||||
* @param image The image to release
|
||||
* @throws SlickException Indicates a failure to release the context
|
||||
*/
|
||||
public static void releaseGraphicsForImage(Image image) throws SlickException {
|
||||
Graphics g = (Graphics) graphics.remove(image.getTexture());
|
||||
|
||||
if (g != null) {
|
||||
g.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an underlying graphics context for the given image
|
||||
*
|
||||
* @param image The image we want to render to
|
||||
* @return The graphics context created
|
||||
* @throws SlickException
|
||||
*/
|
||||
private static Graphics createGraphics(Image image) throws SlickException {
|
||||
init();
|
||||
|
||||
if (fbo) {
|
||||
try {
|
||||
return new FBOGraphics(image);
|
||||
} catch (Exception e) {
|
||||
fbo = false;
|
||||
Log.warn("FBO failed in use, falling back to PBuffer");
|
||||
}
|
||||
}
|
||||
|
||||
if (pbuffer) {
|
||||
if (pbufferRT) {
|
||||
return new PBufferGraphics(image);
|
||||
} else {
|
||||
return new PBufferUniqueGraphics(image);
|
||||
}
|
||||
}
|
||||
|
||||
throw new SlickException("Failed to create offscreen buffer even though the card reports it's possible");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package org.newdawn.slick.opengl.pbuffer;
|
||||
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.Pbuffer;
|
||||
import org.lwjgl.opengl.PixelFormat;
|
||||
import org.lwjgl.opengl.RenderTexture;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.opengl.SlickCallable;
|
||||
import org.newdawn.slick.opengl.Texture;
|
||||
import org.newdawn.slick.opengl.TextureImpl;
|
||||
import org.newdawn.slick.opengl.InternalTextureLoader;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A graphics implementation that renders to a PBuffer
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class PBufferGraphics extends Graphics {
|
||||
|
||||
/** The pbuffer we're going to render to */
|
||||
private Pbuffer pbuffer;
|
||||
/** The image we're we're sort of rendering to */
|
||||
private Image image;
|
||||
|
||||
/**
|
||||
* Create a new graphics context around a pbuffer
|
||||
*
|
||||
* @param image The image we're rendering to
|
||||
* @throws SlickException Indicates a failure to use pbuffers
|
||||
*/
|
||||
public PBufferGraphics(Image image) throws SlickException {
|
||||
super(image.getTexture().getTextureWidth(), image.getTexture().getTextureHeight());
|
||||
this.image = image;
|
||||
|
||||
Log.debug("Creating pbuffer(rtt) "+image.getWidth()+"x"+image.getHeight());
|
||||
if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
|
||||
throw new SlickException("Your OpenGL card does not support PBuffers and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
if ((Pbuffer.getCapabilities() & Pbuffer.RENDER_TEXTURE_SUPPORTED) == 0) {
|
||||
throw new SlickException("Your OpenGL card does not support Render-To-Texture and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the PBuffer that will be used to render to
|
||||
*
|
||||
* @throws SlickException
|
||||
*/
|
||||
private void init() throws SlickException {
|
||||
try {
|
||||
Texture tex = InternalTextureLoader.get().createTexture(image.getWidth(), image.getHeight(), image.getFilter());
|
||||
|
||||
final RenderTexture rt = new RenderTexture(false, true, false, false, RenderTexture.RENDER_TEXTURE_2D, 0);
|
||||
pbuffer = new Pbuffer(screenWidth, screenHeight, new PixelFormat(8, 0, 0), rt, null);
|
||||
|
||||
// Initialise state of the pbuffer context.
|
||||
pbuffer.makeCurrent();
|
||||
|
||||
initGL();
|
||||
GL.glBindTexture(GL11.GL_TEXTURE_2D, tex.getTextureID());
|
||||
pbuffer.releaseTexImage(Pbuffer.FRONT_LEFT_BUFFER);
|
||||
image.draw(0,0);
|
||||
image.setTexture(tex);
|
||||
|
||||
Display.makeCurrent();
|
||||
} catch (Exception e) {
|
||||
Log.error(e);
|
||||
throw new SlickException("Failed to create PBuffer for dynamic image. OpenGL driver failure?");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#disable()
|
||||
*/
|
||||
protected void disable() {
|
||||
GL.flush();
|
||||
|
||||
// Bind the texture after rendering.
|
||||
GL.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID());
|
||||
pbuffer.bindTexImage(Pbuffer.FRONT_LEFT_BUFFER);
|
||||
|
||||
try {
|
||||
Display.makeCurrent();
|
||||
} catch (LWJGLException e) {
|
||||
Log.error(e);
|
||||
}
|
||||
|
||||
SlickCallable.leaveSafeBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#enable()
|
||||
*/
|
||||
protected void enable() {
|
||||
SlickCallable.enterSafeBlock();
|
||||
|
||||
try {
|
||||
if (pbuffer.isBufferLost()) {
|
||||
pbuffer.destroy();
|
||||
init();
|
||||
}
|
||||
|
||||
pbuffer.makeCurrent();
|
||||
} catch (Exception e) {
|
||||
Log.error("Failed to recreate the PBuffer");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Put the renderer contents to the texture
|
||||
GL.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID());
|
||||
pbuffer.releaseTexImage(Pbuffer.FRONT_LEFT_BUFFER);
|
||||
TextureImpl.unbind();
|
||||
initGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the GL context
|
||||
*/
|
||||
protected void initGL() {
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
|
||||
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GL11.glClearDepth(1);
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GL11.glViewport(0,0,screenWidth,screenHeight);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glLoadIdentity();
|
||||
|
||||
enterOrtho();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter the orthographic mode
|
||||
*/
|
||||
protected void enterOrtho() {
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glOrtho(0, screenWidth, 0, screenHeight, 1, -1);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
pbuffer.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
image.flushPixelData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package org.newdawn.slick.opengl.pbuffer;
|
||||
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.Pbuffer;
|
||||
import org.lwjgl.opengl.PixelFormat;
|
||||
import org.newdawn.slick.Graphics;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.opengl.SlickCallable;
|
||||
import org.newdawn.slick.opengl.Texture;
|
||||
import org.newdawn.slick.opengl.TextureImpl;
|
||||
import org.newdawn.slick.opengl.InternalTextureLoader;
|
||||
import org.newdawn.slick.util.Log;
|
||||
|
||||
/**
|
||||
* A graphics implementation that renders to a PBuffer using a unique context, i.e.
|
||||
* without render to texture
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class PBufferUniqueGraphics extends Graphics {
|
||||
/** The pbuffer we're going to render to */
|
||||
private Pbuffer pbuffer;
|
||||
/** The image we're we're sort of rendering to */
|
||||
private Image image;
|
||||
|
||||
/**
|
||||
* Create a new graphics context around a pbuffer
|
||||
*
|
||||
* @param image The image we're rendering to
|
||||
* @throws SlickException Indicates a failure to use pbuffers
|
||||
*/
|
||||
public PBufferUniqueGraphics(Image image) throws SlickException {
|
||||
super(image.getTexture().getTextureWidth(), image.getTexture().getTextureHeight());
|
||||
this.image = image;
|
||||
|
||||
Log.debug("Creating pbuffer(unique) "+image.getWidth()+"x"+image.getHeight());
|
||||
if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
|
||||
throw new SlickException("Your OpenGL card does not support PBuffers and hence can't handle the dynamic images required for this application.");
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the PBuffer that will be used to render to
|
||||
*
|
||||
* @throws SlickException
|
||||
*/
|
||||
private void init() throws SlickException {
|
||||
try {
|
||||
Texture tex = InternalTextureLoader.get().createTexture(image.getWidth(), image.getHeight(), image.getFilter());
|
||||
|
||||
pbuffer = new Pbuffer(screenWidth, screenHeight, new PixelFormat(8, 0, 0), null, null);
|
||||
// Initialise state of the pbuffer context.
|
||||
pbuffer.makeCurrent();
|
||||
|
||||
initGL();
|
||||
image.draw(0,0);
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex.getTextureID());
|
||||
GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 0, 0,
|
||||
tex.getTextureWidth(),
|
||||
tex.getTextureHeight(), 0);
|
||||
image.setTexture(tex);
|
||||
|
||||
Display.makeCurrent();
|
||||
} catch (Exception e) {
|
||||
Log.error(e);
|
||||
throw new SlickException("Failed to create PBuffer for dynamic image. OpenGL driver failure?");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#disable()
|
||||
*/
|
||||
protected void disable() {
|
||||
// Bind the texture after rendering.
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, image.getTexture().getTextureID());
|
||||
GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 0, 0,
|
||||
image.getTexture().getTextureWidth(),
|
||||
image.getTexture().getTextureHeight(), 0);
|
||||
|
||||
try {
|
||||
Display.makeCurrent();
|
||||
} catch (LWJGLException e) {
|
||||
Log.error(e);
|
||||
}
|
||||
|
||||
SlickCallable.leaveSafeBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#enable()
|
||||
*/
|
||||
protected void enable() {
|
||||
SlickCallable.enterSafeBlock();
|
||||
|
||||
try {
|
||||
if (pbuffer.isBufferLost()) {
|
||||
pbuffer.destroy();
|
||||
init();
|
||||
}
|
||||
|
||||
pbuffer.makeCurrent();
|
||||
} catch (Exception e) {
|
||||
Log.error("Failed to recreate the PBuffer");
|
||||
Log.error(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Put the renderer contents to the texture
|
||||
TextureImpl.unbind();
|
||||
initGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the GL context
|
||||
*/
|
||||
protected void initGL() {
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
|
||||
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GL11.glClearDepth(1);
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GL11.glViewport(0,0,screenWidth,screenHeight);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GL11.glLoadIdentity();
|
||||
|
||||
enterOrtho();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter the orthographic mode
|
||||
*/
|
||||
protected void enterOrtho() {
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glOrtho(0, screenWidth, 0, screenHeight, 1, -1);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
pbuffer.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.Graphics#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
image.flushPixelData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.newdawn.slick.opengl.renderer;
|
||||
|
||||
/**
|
||||
* The default version of the renderer relies of GL calls to do everything.
|
||||
* Unfortunately this is driver dependent and often implemented inconsistantly
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class DefaultLineStripRenderer implements LineStripRenderer {
|
||||
/** The access to OpenGL */
|
||||
private SGL GL = Renderer.get();
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#end()
|
||||
*/
|
||||
public void end() {
|
||||
GL.glEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#setAntiAlias(boolean)
|
||||
*/
|
||||
public void setAntiAlias(boolean antialias) {
|
||||
if (antialias) {
|
||||
GL.glEnable(SGL.GL_LINE_SMOOTH);
|
||||
} else {
|
||||
GL.glDisable(SGL.GL_LINE_SMOOTH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#setWidth(float)
|
||||
*/
|
||||
public void setWidth(float width) {
|
||||
GL.glLineWidth(width);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#start()
|
||||
*/
|
||||
public void start() {
|
||||
GL.glBegin(SGL.GL_LINE_STRIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#vertex(float, float)
|
||||
*/
|
||||
public void vertex(float x, float y) {
|
||||
GL.glVertex2f(x,y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#color(float, float, float, float)
|
||||
*/
|
||||
public void color(float r, float g, float b, float a) {
|
||||
GL.glColor4f(r, g, b, a);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#setLineCaps(boolean)
|
||||
*/
|
||||
public void setLineCaps(boolean caps) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#applyGLLineFixes()
|
||||
*/
|
||||
public boolean applyGLLineFixes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
package org.newdawn.slick.opengl.renderer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import org.lwjgl.opengl.EXTSecondaryColor;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GLContext;
|
||||
|
||||
/**
|
||||
* The default OpenGL renderer, uses immediate mode for everything
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class ImmediateModeOGLRenderer implements SGL {
|
||||
/** The width of the display */
|
||||
private int width;
|
||||
/** The height of the display */
|
||||
private int height;
|
||||
/** The current colour */
|
||||
private float[] current = new float[] {1,1,1,1};
|
||||
/** The global colour scale */
|
||||
protected float alphaScale = 1;
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#initDisplay(int, int)
|
||||
*/
|
||||
public void initDisplay(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
String extensions = GL11.glGetString(GL11.GL_EXTENSIONS);
|
||||
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
|
||||
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GL11.glClearDepth(1);
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GL11.glViewport(0,0,width,height);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#enterOrtho(int, int)
|
||||
*/
|
||||
public void enterOrtho(int xsize, int ysize) {
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glOrtho(0, width, height, 0, 1, -1);
|
||||
GL11.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
GL11.glTranslatef((width-xsize)/2,
|
||||
(height-ysize)/2,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glBegin(int)
|
||||
*/
|
||||
public void glBegin(int geomType) {
|
||||
GL11.glBegin(geomType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glBindTexture(int, int)
|
||||
*/
|
||||
public void glBindTexture(int target, int id) {
|
||||
GL11.glBindTexture(target, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glBlendFunc(int, int)
|
||||
*/
|
||||
public void glBlendFunc(int src, int dest) {
|
||||
GL11.glBlendFunc(src, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glCallList(int)
|
||||
*/
|
||||
public void glCallList(int id) {
|
||||
GL11.glCallList(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glClear(int)
|
||||
*/
|
||||
public void glClear(int value) {
|
||||
GL11.glClear(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glClearColor(float, float, float, float)
|
||||
*/
|
||||
public void glClearColor(float red, float green, float blue, float alpha) {
|
||||
GL11.glClearColor(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glClipPlane(int, java.nio.DoubleBuffer)
|
||||
*/
|
||||
public void glClipPlane(int plane, DoubleBuffer buffer) {
|
||||
GL11.glClipPlane(plane, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glColor4f(float, float, float, float)
|
||||
*/
|
||||
public void glColor4f(float r, float g, float b, float a) {
|
||||
a *= alphaScale;
|
||||
|
||||
current[0] = r;
|
||||
current[1] = g;
|
||||
current[2] = b;
|
||||
current[3] = a;
|
||||
|
||||
GL11.glColor4f(r, g, b, a);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glColorMask(boolean, boolean, boolean, boolean)
|
||||
*/
|
||||
public void glColorMask(boolean red, boolean green, boolean blue, boolean alpha) {
|
||||
GL11.glColorMask(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glCopyTexImage2D(int, int, int, int, int, int, int, int)
|
||||
*/
|
||||
public void glCopyTexImage2D(int target, int level, int internalFormat, int x, int y, int width, int height, int border) {
|
||||
GL11.glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glDeleteTextures(java.nio.IntBuffer)
|
||||
*/
|
||||
public void glDeleteTextures(IntBuffer buffer) {
|
||||
GL11.glDeleteTextures(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glDisable(int)
|
||||
*/
|
||||
public void glDisable(int item) {
|
||||
GL11.glDisable(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glEnable(int)
|
||||
*/
|
||||
public void glEnable(int item) {
|
||||
GL11.glEnable(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glEnd()
|
||||
*/
|
||||
public void glEnd() {
|
||||
GL11.glEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glEndList()
|
||||
*/
|
||||
public void glEndList() {
|
||||
GL11.glEndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glGenLists(int)
|
||||
*/
|
||||
public int glGenLists(int count) {
|
||||
return GL11.glGenLists(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glGetFloat(int, java.nio.FloatBuffer)
|
||||
*/
|
||||
public void glGetFloat(int id, FloatBuffer ret) {
|
||||
GL11.glGetFloat(id, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glGetInteger(int, java.nio.IntBuffer)
|
||||
*/
|
||||
public void glGetInteger(int id, IntBuffer ret) {
|
||||
GL11.glGetInteger(id, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glGetTexImage(int, int, int, int, java.nio.ByteBuffer)
|
||||
*/
|
||||
public void glGetTexImage(int target, int level, int format, int type, ByteBuffer pixels) {
|
||||
GL11.glGetTexImage(target, level, format, type, pixels);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glLineWidth(float)
|
||||
*/
|
||||
public void glLineWidth(float width) {
|
||||
GL11.glLineWidth(width);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glLoadIdentity()
|
||||
*/
|
||||
public void glLoadIdentity() {
|
||||
GL11.glLoadIdentity();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glNewList(int, int)
|
||||
*/
|
||||
public void glNewList(int id, int option) {
|
||||
GL11.glNewList(id, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glPointSize(float)
|
||||
*/
|
||||
public void glPointSize(float size) {
|
||||
GL11.glPointSize(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glPopMatrix()
|
||||
*/
|
||||
public void glPopMatrix() {
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glPushMatrix()
|
||||
*/
|
||||
public void glPushMatrix() {
|
||||
GL11.glPushMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glReadPixels(int, int, int, int, int, int, java.nio.ByteBuffer)
|
||||
*/
|
||||
public void glReadPixels(int x, int y, int width, int height, int format, int type, ByteBuffer pixels) {
|
||||
GL11.glReadPixels(x, y, width, height, format, type, pixels);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glRotatef(float, float, float, float)
|
||||
*/
|
||||
public void glRotatef(float angle, float x, float y, float z) {
|
||||
GL11.glRotatef(angle, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glScalef(float, float, float)
|
||||
*/
|
||||
public void glScalef(float x, float y, float z) {
|
||||
GL11.glScalef(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glScissor(int, int, int, int)
|
||||
*/
|
||||
public void glScissor(int x, int y, int width, int height) {
|
||||
GL11.glScissor(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glTexCoord2f(float, float)
|
||||
*/
|
||||
public void glTexCoord2f(float u, float v) {
|
||||
GL11.glTexCoord2f(u, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glTexEnvi(int, int, int)
|
||||
*/
|
||||
public void glTexEnvi(int target, int mode, int value) {
|
||||
GL11.glTexEnvi(target, mode, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glTranslatef(float, float, float)
|
||||
*/
|
||||
public void glTranslatef(float x, float y, float z) {
|
||||
GL11.glTranslatef(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glVertex2f(float, float)
|
||||
*/
|
||||
public void glVertex2f(float x, float y) {
|
||||
GL11.glVertex2f(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glVertex3f(float, float, float)
|
||||
*/
|
||||
public void glVertex3f(float x, float y, float z) {
|
||||
GL11.glVertex3f(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glTexParameteri(int, int, int)
|
||||
*/
|
||||
public void glTexParameteri(int target, int param, int value) {
|
||||
GL11.glTexParameteri(target, param, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#getCurrentColor()
|
||||
*/
|
||||
public float[] getCurrentColor() {
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glDeleteLists(int, int)
|
||||
*/
|
||||
public void glDeleteLists(int list, int count) {
|
||||
GL11.glDeleteLists(list, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glClearDepth(float)
|
||||
*/
|
||||
public void glClearDepth(float value) {
|
||||
GL11.glClearDepth(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glDepthFunc(int)
|
||||
*/
|
||||
public void glDepthFunc(int func) {
|
||||
GL11.glDepthFunc(func);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glDepthMask(boolean)
|
||||
*/
|
||||
public void glDepthMask(boolean mask) {
|
||||
GL11.glDepthMask(mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#setGlobalAlphaScale(float)
|
||||
*/
|
||||
public void setGlobalAlphaScale(float alphaScale) {
|
||||
this.alphaScale = alphaScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glLoadMatrix(java.nio.FloatBuffer)
|
||||
*/
|
||||
public void glLoadMatrix(FloatBuffer buffer) {
|
||||
GL11.glLoadMatrix(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glGenTextures(java.nio.IntBuffer)
|
||||
*/
|
||||
public void glGenTextures(IntBuffer ids) {
|
||||
GL11.glGenTextures(ids);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glGetError()
|
||||
*/
|
||||
public void glGetError() {
|
||||
GL11.glGetError();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glTexImage2D(int, int, int, int, int, int, int, int, java.nio.ByteBuffer)
|
||||
*/
|
||||
public void glTexImage2D(int target, int i, int dstPixelFormat,
|
||||
int width, int height, int j, int srcPixelFormat,
|
||||
int glUnsignedByte, ByteBuffer textureBuffer) {
|
||||
GL11.glTexImage2D(target, i, dstPixelFormat, width, height, j, srcPixelFormat,glUnsignedByte,textureBuffer);
|
||||
}
|
||||
|
||||
public void glTexSubImage2D(int glTexture2d, int i, int pageX, int pageY,
|
||||
int width, int height, int glBgra, int glUnsignedByte,
|
||||
ByteBuffer scratchByteBuffer) {
|
||||
GL11.glTexSubImage2D(glTexture2d, i, pageX, pageY, width, height, glBgra, glUnsignedByte, scratchByteBuffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#canTextureMirrorClamp()
|
||||
*/
|
||||
public boolean canTextureMirrorClamp() {
|
||||
return GLContext.getCapabilities().GL_EXT_texture_mirror_clamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#canSecondaryColor()
|
||||
*/
|
||||
public boolean canSecondaryColor() {
|
||||
return GLContext.getCapabilities().GL_EXT_secondary_color;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glSecondaryColor3ubEXT(byte, byte, byte)
|
||||
*/
|
||||
public void glSecondaryColor3ubEXT(byte b, byte c, byte d) {
|
||||
EXTSecondaryColor.glSecondaryColor3ubEXT(b,c,d);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.newdawn.slick.opengl.renderer;
|
||||
|
||||
/**
|
||||
* The description of a class able to render line strips through
|
||||
* OpenGL
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public interface LineStripRenderer {
|
||||
/**
|
||||
* Check if we should apply default line fixes
|
||||
*
|
||||
* @return True if we should apply GL fixes
|
||||
*/
|
||||
public abstract boolean applyGLLineFixes();
|
||||
|
||||
/**
|
||||
* Start the line strips
|
||||
*/
|
||||
public abstract void start();
|
||||
|
||||
/**
|
||||
* End the line strips
|
||||
*/
|
||||
public abstract void end();
|
||||
|
||||
/**
|
||||
* Add a vertex
|
||||
*
|
||||
* @param x The x coordinate of the vertex
|
||||
* @param y The y coordinate of the vertex
|
||||
*/
|
||||
public abstract void vertex(float x, float y);
|
||||
|
||||
/**
|
||||
* Apply a colour to the next vertex
|
||||
*
|
||||
* @param r The red component of the colour
|
||||
* @param g The green component of the colour
|
||||
* @param b The blue component of the colour
|
||||
* @param a The alpha component of the colour
|
||||
*/
|
||||
public abstract void color(float r, float g, float b, float a);
|
||||
|
||||
/**
|
||||
* Set the width of the lines to be drawn
|
||||
*
|
||||
* @param width The width of the lines to be drawn
|
||||
*/
|
||||
public abstract void setWidth(float width);
|
||||
|
||||
/**
|
||||
* Indicate whether antialiasing should be applied
|
||||
*
|
||||
* @param antialias True if antialiasing should be applied
|
||||
*/
|
||||
public abstract void setAntiAlias(boolean antialias);
|
||||
|
||||
/**
|
||||
* Indicate if we should render end caps
|
||||
*
|
||||
* @param caps True if we should render end caps
|
||||
*/
|
||||
public void setLineCaps(boolean caps);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
package org.newdawn.slick.opengl.renderer;
|
||||
|
||||
/**
|
||||
* A line strip renderer that uses quads to generate lines
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class QuadBasedLineStripRenderer implements LineStripRenderer {
|
||||
/** The renderer used to interact with GL */
|
||||
private SGL GL = Renderer.get();
|
||||
|
||||
/** Maximum number of points allowed in a single strip */
|
||||
public static int MAX_POINTS = 10000;
|
||||
/** True if antialiasing is currently enabled */
|
||||
private boolean antialias;
|
||||
/** The width of the lines to draw */
|
||||
private float width = 1;
|
||||
/** The points to draw */
|
||||
private float[] points;
|
||||
/** The colours to draw */
|
||||
private float[] colours;
|
||||
/** The number of points to draw */
|
||||
private int pts;
|
||||
/** The number of colour points recorded */
|
||||
private int cpt;
|
||||
|
||||
/** The default renderer used when width = 1 */
|
||||
private DefaultLineStripRenderer def = new DefaultLineStripRenderer();
|
||||
/** Indicates need to render half colour */
|
||||
private boolean renderHalf;
|
||||
|
||||
/** True if we shoudl render end caps */
|
||||
private boolean lineCaps = false;
|
||||
|
||||
/**
|
||||
* Create a new strip renderer
|
||||
*/
|
||||
public QuadBasedLineStripRenderer() {
|
||||
points = new float[MAX_POINTS * 2];
|
||||
colours = new float[MAX_POINTS * 4];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if we should render end caps
|
||||
*
|
||||
* @param caps True if we should render end caps
|
||||
*/
|
||||
public void setLineCaps(boolean caps) {
|
||||
this.lineCaps = caps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#start()
|
||||
*/
|
||||
public void start() {
|
||||
if (width == 1) {
|
||||
def.start();
|
||||
return;
|
||||
}
|
||||
|
||||
pts = 0;
|
||||
cpt = 0;
|
||||
GL.flush();
|
||||
|
||||
float[] col = GL.getCurrentColor();
|
||||
color(col[0],col[1],col[2],col[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#end()
|
||||
*/
|
||||
public void end() {
|
||||
if (width == 1) {
|
||||
def.end();
|
||||
return;
|
||||
}
|
||||
|
||||
renderLines(points, pts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#vertex(float, float)
|
||||
*/
|
||||
public void vertex(float x, float y) {
|
||||
if (width == 1) {
|
||||
def.vertex(x,y);
|
||||
return;
|
||||
}
|
||||
|
||||
points[(pts*2)] = x;
|
||||
points[(pts*2)+1] = y;
|
||||
pts++;
|
||||
|
||||
int index = pts-1;
|
||||
color(colours[(index*4)], colours[(index*4)+1], colours[(index*4)+2], colours[(index*4)+3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#setWidth(float)
|
||||
*/
|
||||
public void setWidth(float width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#setAntiAlias(boolean)
|
||||
*/
|
||||
public void setAntiAlias(boolean antialias) {
|
||||
def.setAntiAlias(antialias);
|
||||
this.antialias = antialias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the lines applying antialiasing if required
|
||||
*
|
||||
* @param points The points to be rendered as lines
|
||||
* @param count The number of points to render
|
||||
*/
|
||||
public void renderLines(float[] points, int count) {
|
||||
if (antialias) {
|
||||
GL.glEnable(SGL.GL_POLYGON_SMOOTH);
|
||||
renderLinesImpl(points,count,width+1f);
|
||||
}
|
||||
|
||||
GL.glDisable(SGL.GL_POLYGON_SMOOTH);
|
||||
renderLinesImpl(points,count,width);
|
||||
|
||||
if (antialias) {
|
||||
GL.glEnable(SGL.GL_POLYGON_SMOOTH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the lines given
|
||||
*
|
||||
* @param points The points building up the lines
|
||||
* @param count The number of points to render
|
||||
* @param w The width to render at
|
||||
*/
|
||||
public void renderLinesImpl(float[] points, int count, float w) {
|
||||
float width = w / 2;
|
||||
|
||||
float lastx1 = 0;
|
||||
float lasty1 = 0;
|
||||
float lastx2 = 0;
|
||||
float lasty2 = 0;
|
||||
|
||||
GL.glBegin(SGL.GL_QUADS);
|
||||
for (int i=0;i<count+1;i++) {
|
||||
int current = i;
|
||||
int next = i+1;
|
||||
int prev = i-1;
|
||||
if (prev < 0) {
|
||||
prev += count;
|
||||
}
|
||||
if (next >= count) {
|
||||
next -= count;
|
||||
}
|
||||
if (current >= count) {
|
||||
current -= count;
|
||||
}
|
||||
|
||||
float x1 = points[(current*2)];
|
||||
float y1 = points[(current*2)+1];
|
||||
float x2 = points[(next*2)];
|
||||
float y2 = points[(next*2)+1];
|
||||
|
||||
// draw the next segment
|
||||
float dx = x2 - x1;
|
||||
float dy = y2 - y1;
|
||||
|
||||
if ((dx == 0) && (dy == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float d2 = (dx*dx)+(dy*dy);
|
||||
float d = (float) Math.sqrt(d2);
|
||||
dx *= width;
|
||||
dy *= width;
|
||||
dx /= d;
|
||||
dy /= d;
|
||||
|
||||
float tx = dy;
|
||||
float ty = -dx;
|
||||
|
||||
if (i != 0) {
|
||||
bindColor(prev);
|
||||
GL.glVertex3f(lastx1,lasty1,0);
|
||||
GL.glVertex3f(lastx2,lasty2,0);
|
||||
bindColor(current);
|
||||
GL.glVertex3f(x1+tx,y1+ty,0);
|
||||
GL.glVertex3f(x1-tx,y1-ty,0);
|
||||
}
|
||||
|
||||
lastx1 = x2-tx;
|
||||
lasty1 = y2-ty;
|
||||
lastx2 = x2+tx;
|
||||
lasty2 = y2+ty;
|
||||
|
||||
if (i < count-1) {
|
||||
bindColor(current);
|
||||
GL.glVertex3f(x1+tx,y1+ty,0);
|
||||
GL.glVertex3f(x1-tx,y1-ty,0);
|
||||
bindColor(next);
|
||||
GL.glVertex3f(x2-tx,y2-ty,0);
|
||||
GL.glVertex3f(x2+tx,y2+ty,0);
|
||||
}
|
||||
}
|
||||
|
||||
GL.glEnd();
|
||||
|
||||
float step = width <= 12.5f ? 5 : 180 / (float)Math.ceil(width / 2.5);
|
||||
|
||||
// start cap
|
||||
if (lineCaps) {
|
||||
float dx = points[2] - points[0];
|
||||
float dy = points[3] - points[1];
|
||||
float fang = (float) Math.toDegrees(Math.atan2(dy,dx)) + 90;
|
||||
|
||||
if ((dx != 0) || (dy != 0)) {
|
||||
GL.glBegin(SGL.GL_TRIANGLE_FAN);
|
||||
bindColor(0);
|
||||
GL.glVertex2f(points[0], points[1]);
|
||||
for (int i=0;i<180+step;i+=step) {
|
||||
float ang = (float) Math.toRadians(fang+i);
|
||||
GL.glVertex2f(points[0]+((float) (Math.cos(ang) * width)),
|
||||
points[1]+((float) (Math.sin(ang) * width)));
|
||||
}
|
||||
GL.glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
// end cap
|
||||
if (lineCaps) {
|
||||
float dx = points[(count*2)-2] - points[(count*2)-4];
|
||||
float dy = points[(count*2)-1] - points[(count*2)-3];
|
||||
float fang = (float) Math.toDegrees(Math.atan2(dy,dx)) - 90;
|
||||
|
||||
if ((dx != 0) || (dy != 0)) {
|
||||
GL.glBegin(SGL.GL_TRIANGLE_FAN);
|
||||
bindColor(count-1);
|
||||
GL.glVertex2f(points[(count*2)-2], points[(count*2)-1]);
|
||||
for (int i=0;i<180+step;i+=step) {
|
||||
float ang = (float) Math.toRadians(fang+i);
|
||||
GL.glVertex2f(points[(count*2)-2]+((float) (Math.cos(ang) * width)),
|
||||
points[(count*2)-1]+((float) (Math.sin(ang) * width)));
|
||||
}
|
||||
GL.glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the colour at a given index in the array
|
||||
*
|
||||
* @param index The index of the colour to bind
|
||||
*/
|
||||
private void bindColor(int index) {
|
||||
if (index < cpt) {
|
||||
if (renderHalf) {
|
||||
GL.glColor4f(colours[(index*4)]*0.5f, colours[(index*4)+1]*0.5f,
|
||||
colours[(index*4)+2]*0.5f, colours[(index*4)+3]*0.5f);
|
||||
} else {
|
||||
GL.glColor4f(colours[(index*4)], colours[(index*4)+1],
|
||||
colours[(index*4)+2], colours[(index*4)+3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.LineStripRenderer#color(float, float, float, float)
|
||||
*/
|
||||
public void color(float r, float g, float b, float a) {
|
||||
if (width == 1) {
|
||||
def.color(r,g,b,a);
|
||||
return;
|
||||
}
|
||||
|
||||
colours[(pts*4)] = r;
|
||||
colours[(pts*4)+1] = g;
|
||||
colours[(pts*4)+2] = b;
|
||||
colours[(pts*4)+3] = a;
|
||||
cpt++;
|
||||
}
|
||||
|
||||
public boolean applyGLLineFixes() {
|
||||
if (width == 1) {
|
||||
return def.applyGLLineFixes();
|
||||
}
|
||||
|
||||
return def.applyGLLineFixes();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package org.newdawn.slick.opengl.renderer;
|
||||
|
||||
|
||||
/**
|
||||
* The static holder for the current GL implementation. Note that this
|
||||
* renderer can only be set before the game has been started.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class Renderer {
|
||||
/** The indicator for immediate mode renderering (the default) */
|
||||
public static final int IMMEDIATE_RENDERER = 1;
|
||||
/** The indicator for vertex array based rendering */
|
||||
public static final int VERTEX_ARRAY_RENDERER = 2;
|
||||
|
||||
/** The indicator for direct GL line renderer (the default) */
|
||||
public static final int DEFAULT_LINE_STRIP_RENDERER = 3;
|
||||
/** The indicator for consistant quad based lines */
|
||||
public static final int QUAD_BASED_LINE_STRIP_RENDERER = 4;
|
||||
|
||||
|
||||
/** The renderer in use */
|
||||
private static SGL renderer = new ImmediateModeOGLRenderer();
|
||||
/** The line strip renderer to use */
|
||||
private static LineStripRenderer lineStripRenderer = new DefaultLineStripRenderer();
|
||||
|
||||
/**
|
||||
* Set the renderer to one of the known types
|
||||
*
|
||||
* @param type The type of renderer to use
|
||||
*/
|
||||
public static void setRenderer(int type) {
|
||||
switch (type) {
|
||||
case IMMEDIATE_RENDERER:
|
||||
setRenderer(new ImmediateModeOGLRenderer());
|
||||
return;
|
||||
case VERTEX_ARRAY_RENDERER:
|
||||
setRenderer(new VAOGLRenderer());
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Unknown renderer type: "+type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the line strip renderer to one of the known types
|
||||
*
|
||||
* @param type The type of renderer to use
|
||||
*/
|
||||
public static void setLineStripRenderer(int type) {
|
||||
switch (type) {
|
||||
case DEFAULT_LINE_STRIP_RENDERER:
|
||||
setLineStripRenderer(new DefaultLineStripRenderer());
|
||||
return;
|
||||
case QUAD_BASED_LINE_STRIP_RENDERER:
|
||||
setLineStripRenderer(new QuadBasedLineStripRenderer());
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Unknown line strip renderer type: "+type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the line strip renderer to be used globally
|
||||
*
|
||||
* @param renderer The line strip renderer to be used
|
||||
*/
|
||||
public static void setLineStripRenderer(LineStripRenderer renderer) {
|
||||
lineStripRenderer = renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the renderer to be used
|
||||
*
|
||||
* @param r The renderer to be used
|
||||
*/
|
||||
public static void setRenderer(SGL r) {
|
||||
renderer = r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the renderer to be used when accessing GL
|
||||
*
|
||||
* @return The renderer to be used when accessing GL
|
||||
*/
|
||||
public static SGL get() {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the line strip renderer to use
|
||||
*
|
||||
* @return The line strip renderer to use
|
||||
*/
|
||||
public static LineStripRenderer getLineStripRenderer() {
|
||||
return lineStripRenderer;
|
||||
}
|
||||
|
||||
}
|
||||
535
lib/slick-source/org/newdawn/slick/opengl/renderer/SGL.java
Normal file
535
lib/slick-source/org/newdawn/slick/opengl/renderer/SGL.java
Normal file
@@ -0,0 +1,535 @@
|
||||
package org.newdawn.slick.opengl.renderer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import org.lwjgl.opengl.EXTSecondaryColor;
|
||||
import org.lwjgl.opengl.EXTTextureMirrorClamp;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
/**
|
||||
* The description of the OpenGL functions used Slick. Any other rendering method will
|
||||
* need to emulate these.
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public interface SGL {
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TEXTURE_2D = GL11.GL_TEXTURE_2D;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_RGBA = GL11.GL_RGBA;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_RGB = GL11.GL_RGB;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_UNSIGNED_BYTE = GL11.GL_UNSIGNED_BYTE;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_LINEAR = GL11.GL_LINEAR;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_NEAREST = GL11.GL_NEAREST;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TEXTURE_MIN_FILTER = GL11.GL_TEXTURE_MIN_FILTER;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TEXTURE_MAG_FILTER = GL11.GL_TEXTURE_MAG_FILTER;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_POINT_SMOOTH = GL11.GL_POINT_SMOOTH;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_POLYGON_SMOOTH = GL11.GL_POLYGON_SMOOTH;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_LINE_SMOOTH = GL11.GL_LINE_SMOOTH;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_SCISSOR_TEST = GL11.GL_SCISSOR_TEST;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_MODULATE = GL11.GL_MODULATE;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TEXTURE_ENV = GL11.GL_TEXTURE_ENV;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TEXTURE_ENV_MODE = GL11.GL_TEXTURE_ENV_MODE;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_QUADS = GL11.GL_QUADS;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_POINTS = GL11.GL_POINTS;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_LINES = GL11.GL_LINES;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_LINE_STRIP = GL11.GL_LINE_STRIP;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TRIANGLES = GL11.GL_TRIANGLES;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TRIANGLE_FAN = GL11.GL_TRIANGLE_FAN;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_SRC_ALPHA = GL11.GL_SRC_ALPHA;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_ONE = GL11.GL_ONE;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_ONE_MINUS_DST_ALPHA = GL11.GL_ONE_MINUS_DST_ALPHA;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_DST_ALPHA = GL11.GL_DST_ALPHA;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_ONE_MINUS_SRC_ALPHA = GL11.GL_ONE_MINUS_SRC_ALPHA;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_COMPILE = GL11.GL_COMPILE;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_MAX_TEXTURE_SIZE = GL11.GL_MAX_TEXTURE_SIZE;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_COLOR_BUFFER_BIT = GL11.GL_COLOR_BUFFER_BIT;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_DEPTH_BUFFER_BIT = GL11.GL_DEPTH_BUFFER_BIT;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_BLEND = GL11.GL_BLEND;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_COLOR_CLEAR_VALUE = GL11.GL_COLOR_CLEAR_VALUE;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_LINE_WIDTH = GL11.GL_LINE_WIDTH;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_CLIP_PLANE0 = GL11.GL_CLIP_PLANE0;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_CLIP_PLANE1 = GL11.GL_CLIP_PLANE1;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_CLIP_PLANE2 = GL11.GL_CLIP_PLANE2;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_CLIP_PLANE3 = GL11.GL_CLIP_PLANE3;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_COMPILE_AND_EXECUTE = GL11.GL_COMPILE_AND_EXECUTE;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_RGBA8 = GL11.GL_RGBA;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_RGBA16 = GL11.GL_RGBA16;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_BGRA = GL12.GL_BGRA;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_MIRROR_CLAMP_TO_EDGE_EXT = EXTTextureMirrorClamp.GL_MIRROR_CLAMP_TO_EDGE_EXT;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TEXTURE_WRAP_S = GL11.GL_TEXTURE_WRAP_S;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_TEXTURE_WRAP_T = GL11.GL_TEXTURE_WRAP_T;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_CLAMP = GL11.GL_CLAMP;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_COLOR_SUM_EXT = EXTSecondaryColor.GL_COLOR_SUM_EXT;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_ALWAYS = GL11.GL_ALWAYS;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_DEPTH_TEST = GL11.GL_DEPTH_TEST;
|
||||
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_NOTEQUAL = GL11.GL_NOTEQUAL;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_EQUAL = GL11.GL_EQUAL;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_SRC_COLOR = GL11.GL_SRC_COLOR;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_ONE_MINUS_SRC_COLOR = GL11.GL_ONE_MINUS_SRC_COLOR;
|
||||
/** OpenGL Enum - @url http://www.opengl.org/documentation */
|
||||
public static final int GL_MODELVIEW_MATRIX = GL11.GL_MODELVIEW_MATRIX;
|
||||
|
||||
/**
|
||||
* Flush the current state of the renderer down to GL
|
||||
*/
|
||||
public void flush();
|
||||
|
||||
/**
|
||||
* Initialise the display
|
||||
*
|
||||
* @param width The width of the display
|
||||
* @param height The height of the display
|
||||
*/
|
||||
public void initDisplay(int width, int height);
|
||||
|
||||
/**
|
||||
* Enter orthographic mode
|
||||
*
|
||||
* @param xsize The size of the ortho display
|
||||
* @param ysize The size of the ortho display
|
||||
*/
|
||||
public void enterOrtho(int xsize, int ysize);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param red
|
||||
* @param green
|
||||
* @param blue
|
||||
* @param alpha
|
||||
*/
|
||||
public void glClearColor(float red, float green, float blue, float alpha);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param plane
|
||||
* @param buffer
|
||||
*/
|
||||
public void glClipPlane(int plane, DoubleBuffer buffer);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
public void glScissor(int x, int y, int width, int height);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param width
|
||||
*/
|
||||
public void glLineWidth(float width);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
public void glClear(int value);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param red
|
||||
* @param green
|
||||
* @param blue
|
||||
* @param alpha
|
||||
*/
|
||||
public void glColorMask(boolean red, boolean green, boolean blue, boolean alpha);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*/
|
||||
public void glLoadIdentity();
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param id
|
||||
* @param ret
|
||||
*/
|
||||
public void glGetInteger(int id, IntBuffer ret);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param id
|
||||
* @param ret
|
||||
*/
|
||||
public void glGetFloat(int id, FloatBuffer ret);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param item
|
||||
*/
|
||||
public void glEnable(int item);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param item
|
||||
*/
|
||||
public void glDisable(int item);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param target
|
||||
* @param id
|
||||
*/
|
||||
public void glBindTexture(int target, int id);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param target
|
||||
* @param level
|
||||
* @param format
|
||||
* @param type
|
||||
* @param pixels
|
||||
*/
|
||||
public void glGetTexImage(int target, int level, int format, int type, ByteBuffer pixels);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
public void glDeleteTextures(IntBuffer buffer);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param r
|
||||
* @param g
|
||||
* @param b
|
||||
* @param a
|
||||
*/
|
||||
public void glColor4f(float r, float g, float b, float a);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param u
|
||||
* @param v
|
||||
*/
|
||||
public void glTexCoord2f(float u, float v);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public void glVertex3f(float x, float y, float z);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
public void glVertex2f(float x, float y);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param angle
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public void glRotatef(float angle, float x, float y, float z);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public void glTranslatef(float x, float y, float z);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param geomType
|
||||
*/
|
||||
public void glBegin(int geomType);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*/
|
||||
public void glEnd();
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param target
|
||||
* @param mode
|
||||
* @param value
|
||||
*/
|
||||
public void glTexEnvi(int target, int mode, int value);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
public void glPointSize(float size);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public void glScalef(float x, float y, float z);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*/
|
||||
public void glPushMatrix();
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*/
|
||||
public void glPopMatrix();
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param src
|
||||
* @param dest
|
||||
*/
|
||||
public void glBlendFunc(int src, int dest);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param count
|
||||
* @return The index of the lists
|
||||
*/
|
||||
public int glGenLists(int count);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param id
|
||||
* @param option
|
||||
*/
|
||||
public void glNewList(int id, int option);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*/
|
||||
public void glEndList();
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void glCallList(int id);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param target
|
||||
* @param level
|
||||
* @param internalFormat
|
||||
* @param x
|
||||
* @param y
|
||||
* @param width
|
||||
* @param height
|
||||
* @param border
|
||||
*/
|
||||
public void glCopyTexImage2D(int target, int level, int internalFormat,
|
||||
int x, int y, int width, int height, int border);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param width
|
||||
* @param height
|
||||
* @param format
|
||||
* @param type
|
||||
* @param pixels
|
||||
*/
|
||||
public void glReadPixels(int x, int y, int width, int height, int format, int type,
|
||||
ByteBuffer pixels);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param target
|
||||
* @param param
|
||||
* @param value
|
||||
*/
|
||||
public void glTexParameteri(int target, int param, int value);
|
||||
|
||||
/**
|
||||
* Get the current colour being rendered
|
||||
*
|
||||
* @return The current colour being rendered
|
||||
*/
|
||||
public float[] getCurrentColor();
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param list
|
||||
* @param count
|
||||
*/
|
||||
public void glDeleteLists(int list, int count);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param mask
|
||||
*/
|
||||
public void glDepthMask(boolean mask);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
public void glClearDepth(float value);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param func
|
||||
*/
|
||||
public void glDepthFunc(int func);
|
||||
|
||||
/**
|
||||
* Set the scaling we'll apply to any colour binds in this renderer
|
||||
*
|
||||
* @param alphaScale The scale to apply to any colour binds
|
||||
*/
|
||||
public void setGlobalAlphaScale(float alphaScale);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param buffer
|
||||
*/
|
||||
public void glLoadMatrix(FloatBuffer buffer);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*
|
||||
* @param ids
|
||||
*/
|
||||
public void glGenTextures(IntBuffer ids);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*/
|
||||
public void glGetError();
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*/
|
||||
public void glTexImage2D(int target, int i, int dstPixelFormat,
|
||||
int get2Fold, int get2Fold2, int j, int srcPixelFormat,
|
||||
int glUnsignedByte, ByteBuffer textureBuffer);
|
||||
|
||||
/**
|
||||
* OpenGL Method - @url http://www.opengl.org/documentation/
|
||||
*/
|
||||
public void glTexSubImage2D(int glTexture2d, int i, int pageX, int pageY,
|
||||
int width, int height, int glBgra, int glUnsignedByte,
|
||||
ByteBuffer scratchByteBuffer);
|
||||
|
||||
/**
|
||||
* Check if the mirror clamp extension is available
|
||||
*
|
||||
* @return True if the mirro clamp extension is available
|
||||
*/
|
||||
public boolean canTextureMirrorClamp();
|
||||
|
||||
public boolean canSecondaryColor();
|
||||
|
||||
public void glSecondaryColor3ubEXT(byte b, byte c, byte d);
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
package org.newdawn.slick.opengl.renderer;
|
||||
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
/**
|
||||
* A renderer that caches all operations into an array, creates an opengl vertex array when
|
||||
* required and spits the data down to the card in batch mode
|
||||
*
|
||||
* @author kevin
|
||||
*/
|
||||
public class VAOGLRenderer extends ImmediateModeOGLRenderer {
|
||||
/** The tolerance to rendering immediate */
|
||||
private static final int TOLERANCE = 20;
|
||||
/** Indicates there is no current geometry buffer */
|
||||
public static final int NONE = -1;
|
||||
/** The maximum number of vertices draw in one batch */
|
||||
public static final int MAX_VERTS = 5000;
|
||||
|
||||
/** The type of the geometry array currently being built - i.e. GL_QUADS */
|
||||
private int currentType = NONE;
|
||||
/** The last colour applied */
|
||||
private float[] color = new float[] {1f,1f,1f,1f};
|
||||
/** The last texture applied */
|
||||
private float[] tex = new float[] {0f,0f};
|
||||
/** The index of the next vertex to be created */
|
||||
private int vertIndex;
|
||||
|
||||
/** The vertex data cached */
|
||||
private float[] verts = new float[MAX_VERTS*3];
|
||||
/** The vertex colour data cached */
|
||||
private float[] cols = new float[MAX_VERTS*4];
|
||||
/** The vertex texture coordiante data cached */
|
||||
private float[] texs = new float[MAX_VERTS*3];
|
||||
|
||||
/** The buffer used to pass the vertex data to the card */
|
||||
private FloatBuffer vertices = BufferUtils.createFloatBuffer(MAX_VERTS * 3);
|
||||
/** The buffer used to pass the vertex color data to the card */
|
||||
private FloatBuffer colors = BufferUtils.createFloatBuffer(MAX_VERTS * 4);
|
||||
/** The buffer used to pass the vertex texture coordinate data to the card */
|
||||
private FloatBuffer textures = BufferUtils.createFloatBuffer(MAX_VERTS * 2);
|
||||
|
||||
/** The stack for entering list creation mode - when we're creating a list we can't use our VAs */
|
||||
private int listMode = 0;
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#initDisplay(int, int)
|
||||
*/
|
||||
public void initDisplay(int width, int height) {
|
||||
super.initDisplay(width, height);
|
||||
|
||||
startBuffer();
|
||||
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
|
||||
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new buffer for a vertex array
|
||||
*/
|
||||
private void startBuffer() {
|
||||
vertIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the currently cached data down to the card
|
||||
*/
|
||||
private void flushBuffer() {
|
||||
if (vertIndex == 0) {
|
||||
return;
|
||||
}
|
||||
if (currentType == NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vertIndex < TOLERANCE) {
|
||||
GL11.glBegin(currentType);
|
||||
for (int i=0;i<vertIndex;i++) {
|
||||
GL11.glColor4f(cols[(i*4)+0], cols[(i*4)+1], cols[(i*4)+2], cols[(i*4)+3]);
|
||||
GL11.glTexCoord2f(texs[(i*2)+0], texs[(i*2)+1]);
|
||||
GL11.glVertex3f(verts[(i*3)+0], verts[(i*3)+1], verts[(i*3)+2]);
|
||||
}
|
||||
GL11.glEnd();
|
||||
currentType = NONE;
|
||||
return;
|
||||
}
|
||||
vertices.clear();
|
||||
colors.clear();
|
||||
textures.clear();
|
||||
|
||||
vertices.put(verts,0,vertIndex*3);
|
||||
colors.put(cols,0,vertIndex*4);
|
||||
textures.put(texs,0,vertIndex*2);
|
||||
|
||||
vertices.flip();
|
||||
colors.flip();
|
||||
textures.flip();
|
||||
|
||||
GL11.glVertexPointer(3,0,vertices);
|
||||
GL11.glColorPointer(4,0,colors);
|
||||
GL11.glTexCoordPointer(2,0,textures);
|
||||
|
||||
GL11.glDrawArrays(currentType, 0, vertIndex);
|
||||
currentType = NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the current buffer and restart it
|
||||
*/
|
||||
private void applyBuffer() {
|
||||
if (listMode > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vertIndex != 0) {
|
||||
flushBuffer();
|
||||
startBuffer();
|
||||
}
|
||||
|
||||
super.glColor4f(color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
applyBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glBegin(int)
|
||||
*/
|
||||
public void glBegin(int geomType) {
|
||||
if (listMode > 0) {
|
||||
super.glBegin(geomType);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentType != geomType) {
|
||||
applyBuffer();
|
||||
currentType = geomType;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glColor4f(float, float, float, float)
|
||||
*/
|
||||
public void glColor4f(float r, float g, float b, float a) {
|
||||
a *= alphaScale;
|
||||
|
||||
color[0] = r;
|
||||
color[1] = g;
|
||||
color[2] = b;
|
||||
color[3] = a;
|
||||
|
||||
if (listMode > 0) {
|
||||
super.glColor4f(r,g,b,a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glEnd()
|
||||
*/
|
||||
public void glEnd() {
|
||||
if (listMode > 0) {
|
||||
super.glEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glTexCoord2f(float, float)
|
||||
*/
|
||||
public void glTexCoord2f(float u, float v) {
|
||||
if (listMode > 0) {
|
||||
super.glTexCoord2f(u,v);
|
||||
return;
|
||||
}
|
||||
|
||||
tex[0] = u;
|
||||
tex[1] = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glVertex2f(float, float)
|
||||
*/
|
||||
public void glVertex2f(float x, float y) {
|
||||
if (listMode > 0) {
|
||||
super.glVertex2f(x,y);
|
||||
return;
|
||||
}
|
||||
|
||||
glVertex3f(x,y,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glVertex3f(float, float, float)
|
||||
*/
|
||||
public void glVertex3f(float x, float y, float z) {
|
||||
if (listMode > 0) {
|
||||
super.glVertex3f(x,y,z);
|
||||
return;
|
||||
}
|
||||
|
||||
verts[(vertIndex*3)+0] = x;
|
||||
verts[(vertIndex*3)+1] = y;
|
||||
verts[(vertIndex*3)+2] = z;
|
||||
cols[(vertIndex*4)+0] = color[0];
|
||||
cols[(vertIndex*4)+1] = color[1];
|
||||
cols[(vertIndex*4)+2] = color[2];
|
||||
cols[(vertIndex*4)+3] = color[3];
|
||||
texs[(vertIndex*2)+0] = tex[0];
|
||||
texs[(vertIndex*2)+1] = tex[1];
|
||||
vertIndex++;
|
||||
|
||||
if (vertIndex > MAX_VERTS - 50) {
|
||||
if (isSplittable(vertIndex, currentType)) {
|
||||
int type = currentType;
|
||||
applyBuffer();
|
||||
currentType = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the geometry being created can be split at the current index
|
||||
*
|
||||
* @param count The current index
|
||||
* @param type The type of geometry being built
|
||||
* @return True if the geometry can be split at the current index
|
||||
*/
|
||||
private boolean isSplittable(int count, int type) {
|
||||
switch (type) {
|
||||
case GL11.GL_QUADS:
|
||||
return count % 4 == 0;
|
||||
case GL11.GL_TRIANGLES:
|
||||
return count % 3 == 0;
|
||||
case GL11.GL_LINE:
|
||||
return count % 2 == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glBindTexture(int, int)
|
||||
*/
|
||||
public void glBindTexture(int target, int id) {
|
||||
applyBuffer();
|
||||
super.glBindTexture(target, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glBlendFunc(int, int)
|
||||
*/
|
||||
public void glBlendFunc(int src, int dest) {
|
||||
applyBuffer();
|
||||
super.glBlendFunc(src, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glCallList(int)
|
||||
*/
|
||||
public void glCallList(int id) {
|
||||
applyBuffer();
|
||||
super.glCallList(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glClear(int)
|
||||
*/
|
||||
public void glClear(int value) {
|
||||
applyBuffer();
|
||||
super.glClear(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glClipPlane(int, java.nio.DoubleBuffer)
|
||||
*/
|
||||
public void glClipPlane(int plane, DoubleBuffer buffer) {
|
||||
applyBuffer();
|
||||
super.glClipPlane(plane, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glColorMask(boolean, boolean, boolean, boolean)
|
||||
*/
|
||||
public void glColorMask(boolean red, boolean green, boolean blue, boolean alpha) {
|
||||
applyBuffer();
|
||||
super.glColorMask(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glDisable(int)
|
||||
*/
|
||||
public void glDisable(int item) {
|
||||
applyBuffer();
|
||||
super.glDisable(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glEnable(int)
|
||||
*/
|
||||
public void glEnable(int item) {
|
||||
applyBuffer();
|
||||
super.glEnable(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glLineWidth(float)
|
||||
*/
|
||||
public void glLineWidth(float width) {
|
||||
applyBuffer();
|
||||
super.glLineWidth(width);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glPointSize(float)
|
||||
*/
|
||||
public void glPointSize(float size) {
|
||||
applyBuffer();
|
||||
super.glPointSize(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glPopMatrix()
|
||||
*/
|
||||
public void glPopMatrix() {
|
||||
applyBuffer();
|
||||
super.glPopMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glPushMatrix()
|
||||
*/
|
||||
public void glPushMatrix() {
|
||||
applyBuffer();
|
||||
super.glPushMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glRotatef(float, float, float, float)
|
||||
*/
|
||||
public void glRotatef(float angle, float x, float y, float z) {
|
||||
applyBuffer();
|
||||
super.glRotatef(angle, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glScalef(float, float, float)
|
||||
*/
|
||||
public void glScalef(float x, float y, float z) {
|
||||
applyBuffer();
|
||||
super.glScalef(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glScissor(int, int, int, int)
|
||||
*/
|
||||
public void glScissor(int x, int y, int width, int height) {
|
||||
applyBuffer();
|
||||
super.glScissor(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glTexEnvi(int, int, int)
|
||||
*/
|
||||
public void glTexEnvi(int target, int mode, int value) {
|
||||
applyBuffer();
|
||||
super.glTexEnvi(target, mode, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glTranslatef(float, float, float)
|
||||
*/
|
||||
public void glTranslatef(float x, float y, float z) {
|
||||
applyBuffer();
|
||||
super.glTranslatef(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glEndList()
|
||||
*/
|
||||
public void glEndList() {
|
||||
listMode--;
|
||||
super.glEndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer#glNewList(int, int)
|
||||
*/
|
||||
public void glNewList(int id, int option) {
|
||||
listMode++;
|
||||
super.glNewList(id, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#getCurrentColor()
|
||||
*/
|
||||
public float[] getCurrentColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.opengl.renderer.SGL#glLoadMatrix(java.nio.FloatBuffer)
|
||||
*/
|
||||
public void glLoadMatrix(FloatBuffer buffer) {
|
||||
flushBuffer();
|
||||
super.glLoadMatrix(buffer);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user