mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Many improvements in the PImage/PTexture API
This commit is contained in:
@@ -1502,7 +1502,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
public PImage createImage(int wide, int high, int format) {
|
||||
PImage image = new PImage(wide, high, format);
|
||||
image.parent = this; // make save() work
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
// TODO: Check why textures doesn't work in formats other than ARGB...
|
||||
image.format = ARGB;
|
||||
image.loadTexture();
|
||||
@@ -1514,7 +1514,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
public PImage createImage(int wide, int high, int format, int filter) {
|
||||
PImage image = new PImage(wide, high, format);
|
||||
image.parent = this; // make save() work
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
// TODO: Check why textures doesn't work in formats other than ARGB...
|
||||
image.format = ARGB;
|
||||
image.loadTexture(filter);
|
||||
@@ -1526,7 +1526,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
public PImage createImage(int wide, int high, PTexture.Parameters params) {
|
||||
PImage image = new PImage(wide, high, params.format);
|
||||
image.parent = this; // make save() work
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
// TODO: Check why textures doesn't work in formats other than ARGB...
|
||||
image.format = ARGB;
|
||||
image.loadTexture(params);
|
||||
@@ -3314,7 +3314,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
// println("loadImage(" + filename + ") was " + nfc(much));
|
||||
PImage image = new PImage(bitmap);
|
||||
image.parent = this;
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
// TODO: Check why textures doesn't work in formats other than ARGB...
|
||||
image.format = ARGB;
|
||||
image.loadTexture(params);
|
||||
@@ -3493,7 +3493,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (filename.toLowerCase().endsWith(".obj")) {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
return new PShape3D(this, filename, mode);
|
||||
} else {
|
||||
throw new RuntimeException("OBJ files can be loaded only when using the A3D renderer.");
|
||||
@@ -3515,7 +3515,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
* Creates an empty 3D shape, with space for nvert vertices.
|
||||
*/
|
||||
public PShape3D createShape(int nvert, int kind, int mode) {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
PShape3D.Parameters params = PShape3D.newParameters(kind, mode);
|
||||
PShape3D model = new PShape3D(this, nvert, params);
|
||||
return model;
|
||||
@@ -3537,7 +3537,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
* Tesselates a PShape into a PShape3D with the desired drawing mode (STATID or DYNAMIC)..
|
||||
*/
|
||||
public PShape3D createShape(PShape shape, int mode) {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
PGraphicsAndroid3D a3d = (PGraphicsAndroid3D)g;
|
||||
a3d.beginShapeRecorderImpl();
|
||||
shape(shape, 0, 0, 1, 1);
|
||||
@@ -6921,7 +6921,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
|
||||
|
||||
public PShape beginRecord() {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
return ((PGraphicsAndroid3D) g).beginRecord();
|
||||
} else {
|
||||
throw new RuntimeException("The shapes recorder can only be used with the A3D renderer.");
|
||||
@@ -6930,7 +6930,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
|
||||
|
||||
public void beginShapesRecorder() {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
((PGraphicsAndroid3D) g).beginShapesRecorder();
|
||||
} else {
|
||||
throw new RuntimeException("The shapes recorder can only be used with the A3D renderer.");
|
||||
@@ -6939,7 +6939,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
|
||||
|
||||
public void beginShapeRecorder() {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
((PGraphicsAndroid3D) g).beginShapeRecorder();
|
||||
} else {
|
||||
throw new RuntimeException("The shape recorder can only be used with the A3D renderer.");
|
||||
@@ -6948,7 +6948,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
|
||||
|
||||
public void beginShapeRecorder(int kind) {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
((PGraphicsAndroid3D) g).beginShapeRecorder(kind);
|
||||
} else {
|
||||
throw new RuntimeException("The shape recorder can only be used with the A3D renderer.");
|
||||
@@ -7022,7 +7022,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
|
||||
|
||||
public void endRecord() {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
((PGraphicsAndroid3D) g).endRecord();
|
||||
} else {
|
||||
throw new RuntimeException("The shapes recorder can only be used with the A3D renderer.");
|
||||
@@ -7031,7 +7031,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
|
||||
|
||||
public PShape3D endShapesRecorder() {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
return ((PGraphicsAndroid3D) g).endShapesRecorder();
|
||||
} else {
|
||||
throw new RuntimeException("The shapes recorder can only be used with the A3D renderer.");
|
||||
@@ -7040,7 +7040,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
|
||||
|
||||
public PShape3D endShapeRecorder() {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
return ((PGraphicsAndroid3D) g).endShapeRecorder();
|
||||
} else {
|
||||
throw new RuntimeException("The shape recorder can only be used with the A3D renderer.");
|
||||
@@ -7049,7 +7049,7 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
|
||||
|
||||
public PShape3D endShapeRecorder(int mode) {
|
||||
if (g instanceof PGraphicsAndroid3D) {
|
||||
if (g.is3D()) {
|
||||
return ((PGraphicsAndroid3D) g).endShapeRecorder(mode);
|
||||
} else {
|
||||
throw new RuntimeException("The shape recorder can only be used with the A3D renderer.");
|
||||
|
||||
@@ -5094,7 +5094,7 @@ public class PGraphics extends PImage implements PConstants {
|
||||
// TODO: Discuss proper integration into PGraphics API.
|
||||
|
||||
public PImage getOffscreenImage() {
|
||||
if (!(this instanceof PGraphicsAndroid3D)) {
|
||||
if (!is3D()) {
|
||||
showMissingWarning("getOffscreenImage");
|
||||
}
|
||||
return null;
|
||||
@@ -5102,14 +5102,14 @@ public class PGraphics extends PImage implements PConstants {
|
||||
|
||||
|
||||
public void blend(int mode) {
|
||||
if (!(this instanceof PGraphicsAndroid3D)) {
|
||||
if (!is3D()) {
|
||||
showMissingWarning("blend");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void noBlend() {
|
||||
if (!(this instanceof PGraphicsAndroid3D)) {
|
||||
if (!is3D()) {
|
||||
showMissingWarning("noBlend");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ import processing.core.PShape3D.VertexGroup;
|
||||
// setRasterPos() is also commented out
|
||||
|
||||
/*
|
||||
* Android 3D renderer implemented with pure OpenGL ES 1.0/1.1
|
||||
* Android 3D renderer implemented with pure OpenGL ES 1.1
|
||||
* By Andres Colubri
|
||||
*
|
||||
* TODO: Comment A3D, PShape3D, PTexture, PFramebuffer,
|
||||
@@ -92,9 +92,6 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
/** Aspect ratio of camera's view. */
|
||||
public float cameraAspect;
|
||||
|
||||
protected float currentEyeX;
|
||||
protected float currentCenterY;
|
||||
|
||||
/** Modelview and projection matrices **/
|
||||
|
||||
// Array version for use with OpenGL
|
||||
@@ -3434,11 +3431,7 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
float centerY, float centerZ, float upX, float upY, float upZ) {
|
||||
eyeY = height - eyeY;
|
||||
centerY = height - centerY;
|
||||
|
||||
// Needed for properly setting ortographic projection.
|
||||
currentEyeX = eyeX;
|
||||
currentCenterY = centerY;
|
||||
|
||||
|
||||
// Calculating Z vector
|
||||
float z0 = eyeX - centerX;
|
||||
float z1 = eyeY - centerY;
|
||||
@@ -3564,20 +3557,21 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
}
|
||||
|
||||
/**
|
||||
* Properly setting the ortographic projection depends on the values
|
||||
* used to set the camera (eye and center).
|
||||
* Sets orthographic projection. The left, right, bottom and top
|
||||
* values refer to the top left corner of the screen, not to the
|
||||
* center or eye of the camera. This is like this because making
|
||||
* it relative to the camera is not very intuitive if we think
|
||||
* of the perspective function, which is also independent of the
|
||||
* camera position.
|
||||
*
|
||||
*/
|
||||
public void ortho(float left, float right, float bottom, float top,
|
||||
float near, float far) {
|
||||
// TODO: check if this equation is correct in the case the camera is not aligned
|
||||
// to the XYZ axis (I guess the eye-camera vector needs to be used to determine
|
||||
// the amounds to substract from left,right,bottom and top).
|
||||
left -= currentEyeX;
|
||||
right -= currentEyeX;
|
||||
left -= width/2;
|
||||
right -= width/2;
|
||||
|
||||
bottom -= currentCenterY;
|
||||
top -= currentCenterY;
|
||||
bottom -= height/2;
|
||||
top -= height/2;
|
||||
|
||||
float x = 2.0f / (right - left);
|
||||
float y = 2.0f / (top - bottom);
|
||||
@@ -4927,8 +4921,8 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
// Setting texture crop.
|
||||
gl11.glTexParameteriv(GL10.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, crop, 0);
|
||||
|
||||
// There is no need to setup orthographic projection or any related matrix set/restore
|
||||
// operations here because glDrawTexiOES operates on window coordinates directly:
|
||||
// There is no need to setup orthographic projection or call any related matrix set/restore
|
||||
// functions here because glDrawTexiOES operates on window coordinates directly:
|
||||
// "glDrawTexiOES takes window coordinates and bypasses the transform pipeline
|
||||
// (except for mapping Z to the depth range), so there is no need for any
|
||||
// matrix setup/restore code."
|
||||
@@ -5418,6 +5412,13 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
+ printConfig(egl, display, bestConfig);
|
||||
System.out.println(configStr);
|
||||
}
|
||||
PApplet.println("OPENGL DISPLAY CONFIG:");
|
||||
PApplet.println("redBits " + redBits);
|
||||
PApplet.println("greenBits " + greenBits);
|
||||
PApplet.println("blueBits " + blueBits);
|
||||
PApplet.println("alphaBits " + alphaBits);
|
||||
PApplet.println("depthBits " + depthBits);
|
||||
PApplet.println("stencilBits " + stencilBits);
|
||||
return bestConfig;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,16 @@ public class PImage implements PConstants, Cloneable {
|
||||
|
||||
protected Bitmap bitmap;
|
||||
protected PTexture texture;
|
||||
|
||||
// This boolean variable is used to indicate that there
|
||||
// was a change in the contents of the pixels array and
|
||||
// hasn't been transfered to the texture yet.
|
||||
protected boolean texUpdated = false;
|
||||
|
||||
// This boolean variable is used to indicate that there
|
||||
// was a change in the contents of the texture and
|
||||
// hasn't been transfered to the pixels array yet.
|
||||
protected boolean pixUpdated = true;
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
@@ -192,44 +202,79 @@ public class PImage implements PConstants, Cloneable {
|
||||
|
||||
|
||||
public void loadTexture() {
|
||||
texture = new PTexture(parent, width, height, new PTexture.Parameters(format));
|
||||
pixelsToTexture();
|
||||
if (texture == null) {
|
||||
texture = new PTexture(parent, width, height, new PTexture.Parameters(format));
|
||||
texUpdated = false;
|
||||
}
|
||||
if (pixels != null) {
|
||||
// loadTexture has lower "permissions" than loadPixels, because
|
||||
// loadPixels calls loadTexture which in turns creates the texture
|
||||
// if it is null, but the contrary doesn't happen (loadTexture cannot
|
||||
// result in the creation of the pixels array if it is null).
|
||||
pixelsToTexture();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void loadTexture(int filter) {
|
||||
texture = new PTexture(parent, width, height, new PTexture.Parameters(format, filter));
|
||||
pixelsToTexture();
|
||||
if (texture == null) {
|
||||
texture = new PTexture(parent, width, height, new PTexture.Parameters(format, filter));
|
||||
texUpdated = false;
|
||||
}
|
||||
if (pixels != null) {
|
||||
pixelsToTexture();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void loadTexture(PTexture.Parameters params) {
|
||||
texture = new PTexture(parent, width, height, params);
|
||||
pixelsToTexture();
|
||||
if (texture == null) {
|
||||
texture = new PTexture(parent, width, height, params);
|
||||
texUpdated = false;
|
||||
}
|
||||
if (pixels != null) {
|
||||
pixelsToTexture();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void pixelsToTexture() {
|
||||
loadPixels();
|
||||
texture.set(this);
|
||||
|
||||
public void setTexture(PTexture tex) {
|
||||
if (tex.width == width && tex.height == height) {
|
||||
texture.set(tex);
|
||||
pixUpdated = false;
|
||||
} else {
|
||||
System.err.println("PImage: cannot set texture with different resolution from PImage object");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void textureToPixels() {
|
||||
loadPixels();
|
||||
texture.get(pixels);
|
||||
}
|
||||
|
||||
|
||||
public void setTexture(PTexture texture) {
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public PTexture getTexture() {
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
public void updateTexture() {
|
||||
if (pixels != null) {
|
||||
textureToPixels();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void pixelsToTexture() {
|
||||
if (!texUpdated) {
|
||||
texture.set(pixels);
|
||||
texUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void textureToPixels() {
|
||||
if (!pixUpdated) {
|
||||
texture.get(pixels);
|
||||
pixUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -306,9 +351,8 @@ public class PImage implements PConstants, Cloneable {
|
||||
if (bitmap != null) {
|
||||
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
|
||||
}
|
||||
|
||||
if (texture != null) {
|
||||
// texture.get(pixels); HERE?
|
||||
if (parent.g.is3D()) {
|
||||
loadTexture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,12 +413,15 @@ public class PImage implements PConstants, Cloneable {
|
||||
}
|
||||
|
||||
if (texture != null) {
|
||||
// texture.set(this); HERE?
|
||||
texture.set(pixels, mx1, my1, mx2 - mx1, my2 - my1);
|
||||
// Assuming in good faith that the user only messed up
|
||||
// with the pixels in the specified region. We don't have
|
||||
// any way to know if he or she is lying.
|
||||
texUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// COPYING IMAGE DATA
|
||||
@@ -526,7 +573,7 @@ public class PImage implements PConstants, Cloneable {
|
||||
index2 += w;
|
||||
}
|
||||
}
|
||||
if (parent.g instanceof PGraphicsAndroid3D) {
|
||||
if (parent.g.is3D()) {
|
||||
// TODO: Check why textures doesn't work in formats other than ARGB...
|
||||
newbie.format = ARGB;
|
||||
newbie.loadTexture();
|
||||
@@ -541,7 +588,7 @@ public class PImage implements PConstants, Cloneable {
|
||||
public PImage get() {
|
||||
try {
|
||||
PImage img = (PImage) clone();
|
||||
if (parent.g instanceof PGraphicsAndroid3D) {
|
||||
if (parent.g.is3D()) {
|
||||
// TODO: Check why textures doesn't work in formats other than ARGB...
|
||||
img.format = ARGB;
|
||||
img.loadTexture();
|
||||
@@ -2744,4 +2791,3 @@ public class PImage implements PConstants, Cloneable {
|
||||
//return success;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,10 +35,9 @@ import android.opengl.GLUtils;
|
||||
import java.nio.*;
|
||||
|
||||
/**
|
||||
* This class adds an opengl texture to a PImage object.
|
||||
* This class wraps an OpenGL texture.
|
||||
* By Andres Colubri
|
||||
* TODO: Finish integration with PImage
|
||||
* TODO: Revise updating mechanism (what happens when the pixels change in the PImage, etc).
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PTexture implements PConstants {
|
||||
@@ -163,7 +162,7 @@ public class PTexture implements PConstants {
|
||||
|
||||
/**
|
||||
* Sets the size of the image and texture to width x height. If the texture is already initialized,
|
||||
* it first destroys the current opengl texture object and then creates a new one with the specified
|
||||
* it first destroys the current OpenGL texture object and then creates a new one with the specified
|
||||
* size.
|
||||
* @param width int
|
||||
* @param height int
|
||||
@@ -175,7 +174,7 @@ public class PTexture implements PConstants {
|
||||
|
||||
/**
|
||||
* Sets the size of the image and texture to width x height, and the parameters of the texture to params.
|
||||
* If the texture is already initialized, it first destroys the current opengl texture object and then creates
|
||||
* If the texture is already initialized, it first destroys the current OpenGL texture object and then creates
|
||||
* a new one with the specified size.
|
||||
* @param width int
|
||||
* @param height int
|
||||
@@ -190,17 +189,18 @@ public class PTexture implements PConstants {
|
||||
|
||||
|
||||
public void resize(int wide, int high) {
|
||||
// Creating new texture with the apropriate size.
|
||||
// Creating new texture with the appropriate size.
|
||||
PTexture tex = new PTexture(parent, wide, high, getParameters());
|
||||
|
||||
// Copying the contents of this texture into tex.
|
||||
tex.set(this);
|
||||
|
||||
// Now, overwriting this with tex.
|
||||
// Now, overwriting "this" with tex.
|
||||
copy(tex);
|
||||
|
||||
// Zeroing the texture id of tex, so the texture is not
|
||||
// deleted by opengl when the object is finalized by the GC.
|
||||
// deleted by OpenGL when the object is finalized by the GC.
|
||||
// "This" texture now wraps the one created in tex.
|
||||
tex.glTextureID = 0;
|
||||
}
|
||||
|
||||
@@ -224,10 +224,9 @@ public class PTexture implements PConstants {
|
||||
width = img.width;
|
||||
height = img.height;
|
||||
createTexture(width, height);
|
||||
}
|
||||
|
||||
}
|
||||
img.loadPixels();
|
||||
set(img.pixels, img.format);
|
||||
set(img.texture);
|
||||
}
|
||||
|
||||
|
||||
@@ -243,42 +242,58 @@ public class PTexture implements PConstants {
|
||||
width = h;
|
||||
createTexture(w, h);
|
||||
}
|
||||
|
||||
img.loadPixels();
|
||||
int p0;
|
||||
int dest[] = new int[w * h];
|
||||
for (int j = 0; j < h; j++) {
|
||||
p0 = y * img.width + x + (img.width - w) * j;
|
||||
PApplet.arrayCopy(img.pixels, p0 + w * j, dest, w * j, w);
|
||||
}
|
||||
|
||||
set(dest, img.format);
|
||||
img.loadPixels();
|
||||
set(img.texture, x, y, w, h);
|
||||
}
|
||||
|
||||
|
||||
public void set(PTexture tex) {
|
||||
set(tex, 0, 0, tex.width, tex.height);
|
||||
}
|
||||
|
||||
|
||||
// Copies source texture to this by means of FBO.
|
||||
public void set(PTexture tex) {
|
||||
public void set(PTexture tex, int x, int y, int w, int h) {
|
||||
if (tex == null) {
|
||||
throw new RuntimeException("PTexture: source texture is null");
|
||||
}
|
||||
|
||||
PFramebuffer fbo = new PFramebuffer(parent, glWidth, glHeight);
|
||||
// This is the color (destination) buffer of the FBO.
|
||||
// This texture is the color (destination) buffer of the FBO.
|
||||
fbo.setColorBuffer(this);
|
||||
fbo.disableDepthTest();
|
||||
|
||||
// FBO copy:
|
||||
a3d.pushFramebuffer();
|
||||
a3d.setFramebuffer(fbo);
|
||||
// Rendering tex into this.
|
||||
a3d.drawTexture(tex, 0, 0, tex.glWidth, tex.glHeight, 0, 0, glWidth, glHeight);
|
||||
// Rendering tex into "this", and scaling the source rectangle
|
||||
// to cover the entire destination region.
|
||||
a3d.drawTexture(tex, x, y, w, h, 0, 0, width, height);
|
||||
a3d.popFramebuffer();
|
||||
}
|
||||
|
||||
|
||||
public void set(int[] pixels) {
|
||||
set(pixels, ARGB);
|
||||
set(pixels, 0, 0, glWidth, glHeight, ARGB);
|
||||
}
|
||||
|
||||
|
||||
public void set(int[] intArray, int arrayFormat) {
|
||||
if (intArray.length != width * height) {
|
||||
public void set(int[] pixels, int format) {
|
||||
set(pixels, 0, 0, glWidth, glHeight, format);
|
||||
}
|
||||
|
||||
|
||||
public void set(int[] pixels, int x, int y, int w, int h) {
|
||||
set(pixels, x, y, w, h, ARGB);
|
||||
}
|
||||
|
||||
|
||||
public void set(int[] pixels, int x, int y, int w, int h, int format) {
|
||||
// TODO: Should we throw exceptions here or just a warning?
|
||||
if (pixels == null) {
|
||||
throw new RuntimeException("PTexture: null pixels array");
|
||||
}
|
||||
if (pixels.length != width * height) {
|
||||
throw new RuntimeException("PTexture: wrong length of pixels array");
|
||||
}
|
||||
|
||||
@@ -286,35 +301,53 @@ public class PTexture implements PConstants {
|
||||
createTexture(width, height);
|
||||
}
|
||||
|
||||
int[] convArray = new int[glWidth * glHeight];
|
||||
/*
|
||||
int p0;
|
||||
int dest[] = new int[w * h];
|
||||
for (int j = 0; j < h; j++) {
|
||||
p0 = y * img.width + x + (img.width - w) * j;
|
||||
PApplet.arrayCopy(img.pixels, p0 + w * j, dest, w * j, w);
|
||||
}
|
||||
int p0;
|
||||
int dest[] = new int[w * h];
|
||||
for (int j = 0; j < h; j++) {
|
||||
p0 = y * img.width + x + (img.width - w) * j;
|
||||
PApplet.arrayCopy(img.pixels, p0 + w * j, dest, w * j, w);
|
||||
}
|
||||
*/
|
||||
|
||||
gl.glEnable(glTarget);
|
||||
gl.glBindTexture(glTarget, glTextureID);
|
||||
|
||||
if (usingMipmaps) {
|
||||
if (a3d.gl11 != null && PGraphicsAndroid3D.mipmapSupported) {
|
||||
convertToRGBA(intArray, convArray, arrayFormat);
|
||||
int[] rgbaPixels = new int[glWidth * glHeight];
|
||||
convertToRGBA(pixels, rgbaPixels, format, 0, 0, width, height);
|
||||
gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
|
||||
gl.glTexSubImage2D(glTarget, 0, 0, 0, glWidth, glHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(convArray));
|
||||
gl.glTexSubImage2D(glTarget, 0, x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(rgbaPixels));
|
||||
} else {
|
||||
/*
|
||||
// Code by Mike Miller obtained from here:
|
||||
// http://insanitydesign.com/wp/2009/08/01/android-opengl-es-mipmaps/
|
||||
copyARGB(intArray, convArray);
|
||||
// TODO: Check if this algorithm works only for pot textures or for any resolution.
|
||||
// and adapt for copying only one texture rectangle.
|
||||
int[] argbPixels = new int[glWidth * glHeight];
|
||||
copyARGB(pixels, argbPixels);
|
||||
int level = 0;
|
||||
int w = glWidth;
|
||||
int h = glHeight;
|
||||
int w0 = glWidth;
|
||||
int h0 = glHeight;
|
||||
|
||||
// We create a Bitmap because then we use its built-in filtered downsampling
|
||||
// functionality.
|
||||
Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
|
||||
bitmap.setPixels(convArray, 0, w, 0, 0, w, h);
|
||||
bitmap.setPixels(argbPixels, 0, w0, 0, 0, w0, h0);
|
||||
|
||||
while (w >= 1 || h >= 1) {
|
||||
while (w0 >= 1 || h0 >= 1) {
|
||||
//First of all, generate the texture from our bitmap and set it to the according level
|
||||
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);
|
||||
|
||||
|
||||
// We are done.
|
||||
if (w == 1 || h == 1) {
|
||||
if (w0 == 1 || h0 == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -322,18 +355,25 @@ public class PTexture implements PConstants {
|
||||
level++;
|
||||
|
||||
// Downsampling bitmap
|
||||
h /= 2;
|
||||
w /= 2;
|
||||
Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, w, h, true);
|
||||
h0 /= 2;
|
||||
w0 /= 2;
|
||||
Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, w0, h0, true);
|
||||
|
||||
// Clean up
|
||||
bitmap.recycle();
|
||||
bitmap = bitmap2;
|
||||
}
|
||||
*/
|
||||
// No mipmaps for now.
|
||||
int[] rgbaPixels = new int[glWidth * glHeight];
|
||||
convertToRGBA(pixels, rgbaPixels, format, 0, 0, width, height);
|
||||
gl.glTexSubImage2D(glTarget, 0, x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(rgbaPixels));
|
||||
|
||||
}
|
||||
} else {
|
||||
convertToRGBA(intArray, convArray, arrayFormat);
|
||||
gl.glTexSubImage2D(glTarget, 0, 0, 0, glWidth, glHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(convArray));
|
||||
int[] rgbaPixels = new int[glWidth * glHeight];
|
||||
convertToRGBA(pixels, rgbaPixels, format, 0, 0, width, height);
|
||||
gl.glTexSubImage2D(glTarget, 0, x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(rgbaPixels));
|
||||
}
|
||||
|
||||
gl.glDisable(glTarget);
|
||||
@@ -342,13 +382,15 @@ public class PTexture implements PConstants {
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Update methods
|
||||
// Get methods
|
||||
|
||||
|
||||
/**
|
||||
* Copy texture to pixels. Involves video memory to main memory transfer (slow).
|
||||
*/
|
||||
public void get(int[] pixels) {
|
||||
// TODO: here is ok to create a new pixels array, or an error/warning
|
||||
// should be thrown instead?
|
||||
if ((pixels == null) || (pixels.length != width * height)) {
|
||||
pixels = new int[width * height];
|
||||
}
|
||||
@@ -398,7 +440,7 @@ public class PTexture implements PConstants {
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Get opengl parameters
|
||||
// Get OpenGL parameters
|
||||
|
||||
|
||||
protected int getGLWidth() {
|
||||
@@ -412,7 +454,7 @@ public class PTexture implements PConstants {
|
||||
|
||||
|
||||
/**
|
||||
* Provides the ID of the opengll texture object.
|
||||
* Provides the ID of the OpenGL texture object.
|
||||
* @return int
|
||||
*/
|
||||
protected int getGLTextureID() {
|
||||
@@ -592,7 +634,8 @@ public class PTexture implements PConstants {
|
||||
* @param tIntArray int[]
|
||||
* @param arrayFormat int
|
||||
*/
|
||||
protected void convertToRGBA(int[] intArray, int[] tIntArray, int arrayFormat) {
|
||||
// TODO: Finish handling of rectangular area.
|
||||
protected void convertToRGBA(int[] intArray, int[] tIntArray, int arrayFormat, int x0, int y0, int w, int h) {
|
||||
int t = 0;
|
||||
int p = 0;
|
||||
if (PGraphicsAndroid3D.BIG_ENDIAN) {
|
||||
|
||||
Reference in New Issue
Block a user