I'm using Java OpenGL (JOGL 2.x, built from Git source). I'm rendering my scene to a framebuffer object with a color and a depth attachment. I'd like to convert the [0,1] depth buffer values into world-space distances. My depth attachment is defined as follows:
private void setupDepthFBOs(GL2 gl,
int width,
int height,
int[] frameBufferIds,
int[] colorBufferIds,
int[] depthBufferIds) {
// based on
// http://www.java2s.com/Code/Java/Advanced-Graphics/BloomOpenGL.htm
// generate a framebuffer object
gl.glGenFramebuffers(1, frameBufferIds, 0);
// bind the framebuffer
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBufferIds[0]);
// generate a texture in memory
gl.glGenTextures(1, colorBufferIds,0);
gl.glBindTexture(GL2.GL_TEXTURE_2D, colorBufferIds[0]);
// this will be an RGBA texture (4 bpp) with width, height..
gl.glTexImage2D(GL2.GL_TEXTURE_2D, // target texture type
0, // mipmap LOD level
GL2.GL_RGBA8, // internal pixel format
width, // width of generated image
height, // height of generated image
0, // border of image
GL2.GL_RGBA, // external pixel format
GL2.GL_UNSIGNED_BYTE, // datatype for each value
null); // buffer to store the texture in memory
// set some texture parameters?
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
// use the texture we just created in the framebuffer we just created
gl.glFramebufferTexture2D(
GL2.GL_FRAMEBUFFER, // target texture type
GL.GL_COLOR_ATTACHMENT0, // attachment point
GL.GL_TEXTURE_2D, // texture target type
colorBufferIds[0], // on-gpu id for texture
0); // mipmap lod level
gl.glGenTextures(1,depthBufferIds,0);
gl.glBindTexture(GL.GL_TEXTURE_2D,depthBufferIds[0]);
gl.glTexImage2D(GL2.GL_TEXTURE_2D, // target texture type
0, // mipmap LOD level
GL2.GL_DEPTH_COMPONENT24, // internal pixel format
//GL2.GL_DEPTH_COMPONENT
width, // width of generated image
height, // height of generated image
0, // border of image
GL2.GL_DEPTH_COMPONENT, // external pixel format
GL2.GL_UNSIGNED_INT, // datatype for each value
null); // buffer to store the texture in memory
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
GL.GL_DEPTH_ATTACHMENT,
GL.GL_TEXTURE_2D,
depthBufferIds[0],0);
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
int status = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);
if (status == GL2.GL_FRAMEBUFFER_COMPLETE) {
gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
} else {
throw new IllegalStateException("Frame Buffer Object not created. Status was: " + status);
}
}
This successfully creates a depth buffer, which I can read as a texture and render to the screen, or use as input to a shader (my intended eventual use case).
After some discussions on the IRC a few nights ago, I came up with the following formula relating the Projection Matrix (denoted here as p) and depth-buffer value to the distance to each point on screen in world-space:
z = (p_33)/(p_34 + depth)
(note: my projection matrix/eye is set up looking in the Z+ direction)
This produces almost-sane z-values, but there's a significant margin of error between the distance to known points in the scene, and the value returned by this equation.
Any ideas what I might be doing wrong here?
Here are my calculations, my result is different to yours:
Defined:
depth = out_z / out_w
out_z = in_z * p_33 + in_w * p_43
out_w = in_z * p_34 + in_w * p_44
Known:
in_w = 1, p_43 = -1, p_44 = 0
Working:
depth = (in_z * p_33 - 1) / (in_z * p_34)
depth = p_33 / p_34 - 1 / (in_z * p_34)
p_33 / p_34 - depth = 1 / (in_z * p_34)
1 / (p_33 / p_34 - depth) = in_z * p_34
1 / (p_33 / p_34 - depth) = in_z * p_34
1 / (p_33 - depth * p_34) = in_z
Related
I have a created bitmaps. Sizes are not specific. Sometimes 120x60 , 129x800 , 851x784. Its not have a specific value... I want to make these bitmaps resizing to 512x512 always but without changing original images aspect ratio. And without cropping. New image must have canvas 512x512 and original image must be center without any cropping.
I was resizing my bitmaps with this function but it makes images really bad because image fitting X and Y . I don't want image to fit x and y on same time fits one of it and keeps its aspect ratio.
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
}
What I have;
What I want;
Ok, so you're really close. I can't test this right now, but basically what needs to be changed is
1) You need to apply the same scale to both X and Y, so you need to pick the smaller one (try the bigger one if that doesn't work).
matrix.postScale(Math.min(scaleWidth, scaleHeight), Math.min(scaleWidth, scaleHeight));
2) The result will be a bitmap where at least one side is 512px large, the other one will be smaller. So you need to add the padding to fit that side to 512px (equally left and right/top and bottom for centering). In order to do so, you need to create an new bitmap of the desired size:
Bitmap outputimage = Bitmap.createBitmap(512,512, Bitmap.Config.ARGB_8888);
3) and lastly depending on what side of the resizedBitmap is 512px you need to draw resizedBitmap to the correct position in outputImage
Canvas can = new Canvas(outputimage);
can.drawBitmap(resizedBitmap, (512 - resizedBitmap.getWidth()) / 2, (512 - resizedBitmap.getHeight()) / 2, null);
Note here, that 512 - resizedBitmap.getWidth() results in 0 and therefor no padding at the side with correct size.
4) Now return outputImage
Here's a simplification in Kotlin that does both the scale and the translation with the matrix, skipping the intermediate bitmap.
Note that it also sets the background color to white for new pixels, which I needed for my image pipeline. Feel free to remove that if you don't need it.
fun resizedBitmapWithPadding(bitmap: Bitmap, newWidth: Int, newHeight: Int) : Bitmap {
val scale = min(newWidth.toFloat() / bitmap.width, newHeight.toFloat() / bitmap.height)
val scaledWidth = scale * bitmap.width
val scaledHeight = scale * bitmap.height
val matrix = Matrix()
matrix.postScale(scale, scale)
matrix.postTranslate(
(newWidth - scaledWidth) / 2f,
(newHeight - scaledHeight) / 2f
)
val outputBitmap = Bitmap.createBitmap(newWidth, newHeight, bitmap.config)
outputBitmap.eraseColor(Color.WHITE)
Canvas(outputBitmap).drawBitmap(
bitmap,
matrix,
null
)
return outputBitmap
}
Background Info:
I am using OpenGL and LWJGL 3 to draw some quads onto the screen. I need to know when the mouse is over a quad. When I render the quads to the screen, I use the OpenGL coordinates, ranging from -1 to 1 for both X and Y and with (0,0) at the center of the screen. When I get the mouse position I use
glfwSetCursorPosCallback();
which gives me the coordinates ranging from 0 to the width or height of the window and with (0,0) at the top left corner (below the title bar). I then take the mouse coordinate and calculate the OpenGL coordinates.
For example if my window size is (800, 600) and my mouse was at (200, 200) I would get (-0.5, 0.33) [since (400, 300) would map to (0, 0) in OpenGL's coordinates].
So here's my problem:
OpenGL includes the title bar in its coordinates, where as glfwSetCursorPosCallback(); does not. This means that if I render a vertex at (-0.5, 0.33) [like in my example] it renders at around (200, ~210).
As you can see, because the two coordinate systems cover different areas, its more difficult to switch between the coordinate systems.
I have searched for ways to exclude the title bar from OpenGL's coordinates, to completely get rid of the title bar and to get the height of the title bar (so I can include it in my calculations and make the correct adjustments). I haven't been able to figure out how to do any of these, so I'm looking for a way to do so, or a different method that will resolve my problem.
EDIT 1: Adding Code
#Nicol Bolas informed me that this is not how OpenGL normally works so there must be something causing this in my code. I believe I've provided the parts of my code that would be responsible for my problem:
Here is my Renderer class [I am using the drawQuad() method]
Note: I am not currently using the view, model, or projection matrices in my shaders.
public class Renderer {
private VertexArrayObject vao;
private VertexBufferObject vbo;
private ShaderProgram shaderProgram;
private FloatBuffer vertices;
private int numVertices;
private boolean drawing;
//private Font font;
//private Font debugFont;
public void drawQuad(float x, float y, float width, float height, Color c) {
/* Calculate Vertex positions */
float x1 = x;
float y1 = y;
float x2 = x + width;
float y2 = y - height;
/* Calculate color */
float r = c.getRed();
float g = c.getGreen();
float b = c.getBlue();
/* Put data into buffer */
vertices.put(x1).put(y1).put(0.0f).put(r).put(g).put(b);
vertices.put(x1).put(y2).put(0.0f).put(r).put(g).put(b);
vertices.put(x2).put(y2).put(0.0f).put(r).put(g).put(b);
vertices.put(x2).put(y1).put(0.0f).put(r).put(g).put(b);
/* We drawed X vertices */
numVertices += 4;
}
// Initialize renderer
public void init(){
// Set up shader programs
setupShaderProgram();
// Enable blending (?????)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
// Clears drawing area
public void clear() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
// Begin rendering
public void begin() {
if (drawing) throw new IllegalStateException("Renderer is already drawing.");
drawing = true;
numVertices = 0;
}
// End rendering
public void end() {
if (!drawing) throw new IllegalStateException("Renderer is not drawing.");
drawing = false;
flush();
}
// Flushes data to GPU to get rendered
public void flush() {
if (numVertices > 0) {
vertices.flip();
if (vao != null) vao.bind();
else vbo.bind(GL_ARRAY_BUFFER);
specifyVertexAttributes();
}
shaderProgram.use();
// Upload the new vertex data
vbo.bind(GL_ARRAY_BUFFER);
vbo.uploadSubData(GL_ARRAY_BUFFER, 0, vertices);
// Draw batch
glDrawArrays(GL_QUADS, 0, numVertices);
// Clear vertex data for next batch
vertices.clear();
numVertices = 0;
}
private void setupShaderProgram() {
// Generate VertexArrayObject
if (Game.is32Supported()) {
vao = new VertexArrayObject();
vao.bind();
} else {
throw new RuntimeException("OpenGL 3.2 not supported.");
}
// Generate VertexBufferObject
vbo = new VertexBufferObject();
vbo.bind(GL_ARRAY_BUFFER);
// Create FloatBuffer
vertices = MemoryUtil.memAllocFloat(4096);
// Upload null data to allocate storage for the VBO
long size = vertices.capacity() * Float.BYTES;
vbo.uploadData(GL_ARRAY_BUFFER, size, GL_DYNAMIC_DRAW);
// Initialize variables
numVertices = 0;
drawing = false;
// Load Shaders:
Shader vertexShader, fragmentShader;
if (Game.is32Supported()) {
vertexShader = Shader.loadShader(GL_VERTEX_SHADER, "res/shaders/vshader.vert");
fragmentShader = Shader.loadShader(GL_FRAGMENT_SHADER, "res/shaders/fshader.frag");
} else {
throw new RuntimeException("OpenGL 3.2 not supported.");
}
// Create ShaderProgram
shaderProgram = new ShaderProgram();
shaderProgram.attachShader(vertexShader);
shaderProgram.attachShader(fragmentShader);
if (Game.is32Supported()) {
shaderProgram.bindFragmentDataLocation(0, "fragColor");
}
shaderProgram.link();
shaderProgram.use();
// Delete linked shaders
vertexShader.delete();
fragmentShader.delete();
// Get width & height of framebuffer
long window = GLFW.glfwGetCurrentContext();
int width, height;
try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer widthBuffer = stack.mallocInt(1);
IntBuffer heightBuffer = stack.mallocInt(1);
GLFW.glfwGetFramebufferSize(window, widthBuffer, heightBuffer);
width = widthBuffer.get();
height = heightBuffer.get();
}
// Specify vertex pointers
specifyVertexAttributes();
// Set Model Matrix to identity matrix
Matrix4f model = new Matrix4f();
int uniModel = shaderProgram.getUniformLocation("model");
shaderProgram.setUniform(uniModel, model);
// Set View Matrix to identity matrix
Matrix4f view = new Matrix4f();
int uniView = shaderProgram.getUniformLocation("view");
shaderProgram.setUniform(uniView, view);
// Set Projection Matrix to an orthographic projection
Matrix4f projection = Matrix4f.orthographic(0f, width, 0f, height, -1f, 1f);
int uniProjection = shaderProgram.getUniformLocation("projection");
shaderProgram.setUniform(uniProjection, projection);
}
// Specifies the vertex shader pointers (attributes)
private void specifyVertexAttributes() {
int posAttrib = shaderProgram.getAttributeLocation("position");
shaderProgram.enableVertexAttribute(posAttrib);
shaderProgram.pointVertexAttribute(posAttrib, 3, 6 * Float.BYTES, 0);
int colAttrib = shaderProgram.getAttributeLocation("color");
shaderProgram.enableVertexAttribute(colAttrib);
shaderProgram.pointVertexAttribute(colAttrib, 3, 6 * Float.BYTES, 3 * Float.BYTES);
}
}
And here is my init() method that creates and sets up my window:
private void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set();
// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( !glfwInit() )
throw new IllegalStateException("Unable to initialize GLFW");
// Configure GLFW
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); // the window will be resizable
// ONLY ON MAC OSX (?)
//glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Tell GLFW to use OpenGL verison 3.x
//glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); // Tell GLFW to use OpenGL version x.2 (combined -> 3.2)
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // Should be forward compatible
// Create the window
window = glfwCreateWindow(WIDTH, HEIGHT, "Game_19_v0.0.1", NULL, NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
});
// Get the thread stack and push a new frame
try ( MemoryStack stack = stackPush() ) {
IntBuffer pWidth = stack.mallocInt(1); // int*
IntBuffer pHeight = stack.mallocInt(1); // int*
// Get the window size passed to glfwCreateWindow
glfwGetWindowSize(window, pWidth, pHeight);
// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center the window
glfwSetWindowPos(
window,
(vidmode.width() - pWidth.get(0)) / 2,
(vidmode.height() - pHeight.get(0)) / 2
);
} // the stack frame is popped automatically
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities();
// Input
glfwSetCursorPosCallback(window, cursorPosCallback = new MouseInput());
// Create renderer
renderer = new Renderer();
renderer.init();
// To Render:
buttonManager = new ButtonManager();
}
EDIT 2: Temporary Solution
I was able to use glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); to remove the entire border from the window, title bar included, which fixed the issue. Now however, I obviously don't have the options to close, minimize, etc., on my window, although I suppose I can program those in myself if necessary. Will update if I find out any other solutions.
GLFW functions typically work with the client area of a window (the inside window area not including titlebars, scrollbars, etc.) so glfwSetCursorPosCallback is giving you the expected values. If your OpenGL framebuffer is for some reason rendering things behind the title bar (whether it's an improper setup or just a platform specific detail) you should still be able to get the title bar size using glfwGetWindowFrameSize:
IntBuffer pLeft = stack.mallocInt(1); // int*
IntBuffer pTop = stack.mallocInt(1); // int*
IntBuffer pRight = stack.mallocInt(1); // int*
IntBuffer pBottom = stack.mallocInt(1); // int*
// Get the window border sizes
glfwGetWindowFrameSize(window, pLeft, pTop, pRight, pBottom);
(Disclaimer: I'm just following the syntax from your code above since I'm only familiar with the C++ API.)
The size of the title bar will be stored in the top variable and can then be added to whatever value you get from glfwSetCursorPosCallback and glfwGetWindowSize.
float adjustedYpos = ypos + top;
float adjustedHeight = height + top;
float normalizedY = adjustedYpos / adjustedHeight;
float openglY = normalizedY * -2.0f - 1.0f
This openglY value should be the OpenGL [-1, 1] clip-space coordinate adjusted based on the title bar size.
Does anyone know whether libGDX has a method for scrolling/shifting an image/texture within itself?
To explain; I would like to be able to scroll the contents (pixels) of an image, either vertically or horizontally within its own region. For example, if an image is shifted 1 pixel to the right, all pixels move 1 to the right and those on the right-most-edge are wrapped to the left-most-edge. The image size does not change, only the positioning of the pixels within it change.
I have mainly been working with the Sprite class, it can do a lot (scale, rotate, etc) but shift/scroll as I need it, isn't there.
Before writting the method myself, I thought I'd ask here...
The following worked for me, this was provided by Kush:
float delta = 0f;
// In the Actors act method
delta += Gdx.graphics.getDeltaTime();
// Horizontal
batch.draw(texture, 0, 0, width, height, 0 + delta * 10, 1, 1 + delta * 10, 0);
// Vertical
batch.draw(texture, 0, 0, width, height, 1, 0 + delta * 10, 0, 1 + delta * 10);
You won't need Sprite for this, draw directly Texture using batch. For wrapping first set
Texture texture = new Texture("example.png");
texture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
then draw using uv
batch.draw(texture, x, y, width, height, u, v, u2, v2);
or any other method that suits you in SpriteBatch.
I need to be able to create a copy of a texture and change certain colors in that copy into other colors in java. I am not very fimiliar with the OpenGL library and I have no idea what methods it offers to do this. I need to know a good way to change the color of a single pixel in a texture and how to get the color of a single pixel in a texture, and also how to copy a texture. I'm sorry if this question is too broad, but I'm looking for a broad answer.
You can use glTexSubImage2D function to change the color of a single pixel in a texture. Below is the function header:
void glTexSubImage2D( GLenum target, GLint level, GLint xoffset,
GLint yoffset, GLsizei width, GLsizei height, GLenum format,
GLenum type, const GLvoid *data);
Here:
target Specifies the target texture.
level Specifies the level-of-detail number. Level 0 is the base image
level. Level n is the nth mipmap reduction image.
xoffset Specifies a texel offset in the x direction within the
texture array.
yoffset Specifies a texel offset in the y direction within the
texture array.
width Specifies the width of the texture subimage.
height Specifies the height of the texture subimage
format Specifies the format of the pixel data.
type Specifies the data type of the pixel data.
Reference: https://www.opengl.org/sdk/docs/man2/xhtml/glTexSubImage2D.xml
AND
Below is a code snippet of how to use it I found in the website referenced at the bottom:
void updateTexture(const chip8& c8)
{
// Update pixels
for(int y = 0; y < 32; ++y)
for(int x = 0; x < 64; ++x)
if(c8.gfx[(y * 64) + x] == 0)
screenData[y][x][0] = screenData[y][x][1] = screenData[y][x][2] = 0; // Disabled
else
screenData[y][x][0] = screenData[y][x][1] = screenData[y][x][2] = 255; // Enabled
// Update Texture
glTexSubImage2D(GL_TEXTURE_2D, 0 ,0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)screenData);
glBegin( GL_QUADS );
glTexCoord2d(0.0, 0.0); glVertex2d(0.0, 0.0);
glTexCoord2d(1.0, 0.0); glVertex2d(display_width, 0.0);
glTexCoord2d(1.0, 1.0); glVertex2d(display_width, display_height);
glTexCoord2d(0.0, 1.0); glVertex2d(0.0, display_height);
glEnd();
}
Reference: http://www.multigesture.net/articles/how-to-draw-pixels-to-a-texture-opengl/
Hope that helps!
The easiest way to copy a texture is with glCopyTexImage2D(). This allows you to copy the content of the current framebuffer to a texture. If you want to use another texture as the source, you can set that texture as the content of a framebuffer object (FBO).
Let's say you already have a texture with name srcTexId that you want to use as the source of your copy operation. Now, you need to create a new texture for your destination first, which we will call dstTexId:
GLuint dstTexId = 0;
glGenTextures(1, &dstTexId);
glBindTexture(GL_TEXTURE_2D, dstTexId);
glTexParameteri(...);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
Note the use of NULL for the last argument. This means that the texture content is allocated with the given format/size, but the texture is not filled with data.
Now we need an FBO, and set it up with the source texture as the content:
GLuint fbo = 0;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D srcTexId, 0);
Everything is ready to perform the copy now:
glBindTexture(GL_TEXTURE_2D, dstTexId);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, width, height, 0);
Then you can clean up your bindings if you like to keep the state undisturbed:
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
Another option to copy a texture is glBlitFramebuffer(). To use it, you would create two FBOs, one for reading and one for writing. So it requires a bit more setup, but it's also more flexible. For example, it allows you to resize (scale) the content as part of the copy, which is not supported with glCopyTexImage2D().
To modify parts of a texture after you created the copy, use glTexSubImage2D().
I am trying to create a Rotatable an ImageView to which I will specify certain angle and pivot point and see it rotated around that pivot point. I tried something like this:
Matrix matrix = new Matrix();
matrix.postRotate(45, imageView.getWidth(), imageView.getHeight());
imageView.setScaleType(ScaleType.MATRIX);
imageView.setImageMatrix(matrix);
but the parameters of postRotate method (the second and third - the pivot points) make NO CHANGE at all. even if they are 0, 0 - it's the same thing.
So I wanna create a ImageView that would be rotated by certain angle when initialized. In this example 45 degrees. I tried setting the bounds and staff.. no help.
How do I do that? :/
You can rotate a ImageView by using setRotation(int);
// rotate imageView 45 around center pivot point
imageView.setPivotX(imageView.getWidth()/2);
imageView.setPivotY(imageView.getHeight()/2);
imageView.setRotation(45);
Reference: http://goo.gl/WhhGM
Edit: I had to shorten the link because of a ) in the url, some browsers don't like that.
This is how I use view.setRotation(float angle) in my apps, hope it will be helpful:
//to make rotation use next code
imageView.setPivotX(imageView.getWidth() / 2);
imageView.setPivotY(imageView.getHeight() / 2);
imageView.setRotation(45);
//to reset rotate state to initial position
imageView.setPivotX(imageView.getWidth() / 2);
imageView.setPivotY(imageView.getHeight() / 2);
imageView.setRotation(0);
Based on answer from Spencer
This function works for me.
public static Bitmap rotateImage (Bitmap srcBitmap, int width, int height, int rotation)
{
// create rotated image
Matrix matrix = new Matrix();
rotation = (rotation +1 ) % 3;
rotation = rotation * 90;
matrix.postRotate( rotation,
width,
height );
Bitmap rotatedBmp = Bitmap.createBitmap( srcBitmap,
0,
0,
srcBitmap.getWidth(),
srcBitmap.getHeight(),
matrix,
false );
return rotatedBmp;
}