I have a touchRotationMatrix that I do the following:
Matrix.setIdentityM(identity, 0);
Matrix.rotateM(identity, 0, x, 0,1,0);
Matrix.multiplyMV(v, 0, identity, 0, v, 0)
Matrix.rotateM(identity, 0, y, 1,0,0);
Matrix.rotateM(identity, 0, y, v[0],v[1],v[2]);
Matrix.multiplyMM(touchRotationMatrix, 0, identity, 0, touchRotationMatrix, 0);
X and Y are the normalized rotation deltas.
This is applied to my model matrix like so:
Matrix.multiplyMM(mModelMatrix, 0, mModelMatrix, 0,touchRotationMatrix,0);
The problem here is that any rotation that I do is on its own axes.
Let me illustrate why I don't want this:
If I rotate from left to right, it's like turning your head which is good.
If I rotate up first, then rotate from left to right, I end up looking at the floor or the ceiling. This makes sense because it is rotating on its axes.
My question is, how do I make it that the x rotation isn't happening on its own axes?
I hope I am clear, any guidance or help would be very much appreciated! Thanks!
P.S I'm not an expert in OpenGL nor in LinearAlgebra.
Not so clear but either
Matrix.setRotateM(identity, 0, y, 1,0,0);
Matrix.multiplyMM(touchRotationMatrix, 0, identity, 0, touchRotationMatrix, 0);
Matrix.rotateM(touchRotationMatrix, 0, x, 0,1,0);
or
Matrix.setRotateM(identity, 0, x, 0,1,0);
Matrix.multiplyMM(touchRotationMatrix, 0, identity, 0, touchRotationMatrix, 0);
Matrix.rotateM(touchRotationMatrix, 0, y, 1,0,0);
might work as you expect.
Related
I want to rotate an element around a specific point defined by me and dynamically changed.
I am orientating myself at the guidelines from the google developers site.
My first approach is this:
scratch = new float[16];
Matrix.setIdentityM(mRotationMatrix, 0);
Matrix.setRotateM(mRotationMatrix, 0, angle, 0, 0, 1f);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
element.draw(scratch);
This rotates the object around the center of the screen.
What do I have to add/change to make the object rotate around some other point?
Add a translation operation.
Grafika's Sprite2d class provides an example:
/**
* Re-computes mModelViewMatrix, based on the current values for rotation, scale, and
* translation.
*/
private void recomputeMatrix() {
float[] modelView = mModelViewMatrix;
Matrix.setIdentityM(modelView, 0);
Matrix.translateM(modelView, 0, mPosX, mPosY, 0.0f);
if (mAngle != 0.0f) {
Matrix.rotateM(modelView, 0, mAngle, 0.0f, 0.0f, 1.0f);
}
Matrix.scaleM(modelView, 0, mScaleX, mScaleY, 1.0f);
mMatrixReady = true;
}
This positions the object, then rotates it around the center of the object.
You need to translate the matrix in the reverse direction of the point first, then rotate and then translate it back. Look at it as if the rotation is always rotating around the center of the world, and the translation moves the center of the world.
Something like this (untested):
scratch = new float[16];
Matrix.setIdentityM(mRotationMatrix, 0);
Matrix.translateM(mRotationMatrix, 0, -x, -y, -z);
Matrix.rotateM(mRotationMatrix, 0, angle, 0, 0, 1f);
Matrix.translateM(mRotationMatrix, 0, x, y, z);
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
element.draw(scratch);
The x, y and z values need to be calculated as the delta between the current position of the object in the world and the position of the point you want to rotate around. You need to do that calculation yourself, but that's pretty trivial.
I'm trying to work on some OpenGL stuff. What I've got up to now is a viewport, in which I'm drawing some imaginary "borders" by using GL_LINES. It looks like this, with setLookAt set as follows:
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5, 0, 0, 0, 0, 1, 0);
My frustum is set: Matrix.frustumM(mProjectionMatrix, 0, -2, 2, -2, 2, 1, 11); so I'm positioned somewhere inside the "cube".
Now what I'm trying to achieve is let the user look around. I'm capturing onTouchEvents, passing any movement in x/y direction to the renderer. What I'm doing next is rotating all lines drawn by the specific angle I received from the touch listener.
It then looks like this:
So the cube is not rotated around the viewer or the eye-center, but instead around some point that I don't know where it's coming from.
My problem is: how can I rotate the object around the viewer's center/position? Do I have to rotate the mViewMatrix which comes from setLookAtM? If yes, simply by using Matrix.setRotateM(mViewMatrix, ...)?
The Line's drawing method looks like this:
public void draw(float[] mViewMatrix, float[] mProjectionMatrix) {
Matrix.multiplyMM(mViewProjectionMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
GLES20.glUseProgram(iProgId);
lineBuffer.position(0);
GLES20.glVertexAttribPointer(iPosition, 3, GLES20.GL_FLOAT, false, 0, lineBuffer);
GLES20.glEnableVertexAttribArray(iPosition);
colorBuffer.position(0);
GLES20.glVertexAttribPointer(iColor, 3, GLES20.GL_FLOAT, false, 0, colorBuffer);
GLES20.glEnableVertexAttribArray(iColor);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.rotateM(mModelMatrix, 0, rotX, 1, 0, 0);
Matrix.rotateM(mModelMatrix, 0, -rotY, 0, 1, 0);
Matrix.setIdentityM(mViewProjectionMatrix, 0);
Matrix.multiplyMM(mViewProjectionMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
//GLES20.glUniformMatrix4fv(iVPMatrix, 1, false, mMVPMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewProjectionMatrix, 0);
GLES20.glUniformMatrix4fv(iVPMatrix, 1, false, mMVPMatrix, 0);
//GLES20.glDrawElements(GLES20.GL_LINES, mVertices.length/2, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
GLES20.glDrawArrays(GLES20.GL_LINES, 0, mVertices.length / 2);
}
look at function takes 3 vertices, eye position, target position and up vector. Basically it generates a matrix that moves scene around to render scene like you are looking from eye position to target position. In your example your is at 0,0,0 and looks at 5, 0, 0 (so you are looking at +x direction and up is defined as 0, 1, 0 (higher y value means object will be at top of window.)
Instead of using those constants, first define a camera position.
float cameraX, cameraY, cameraY;
it is harder to work with target vectors, so instead use an angle that defines which direction you are looking at
float angle;
and to calculate targetVector use this angle.
float targetX = cameraX + cos(angle);
float targetY = cameraY;
float targetZ = cameraZ + sin(angle);
Now to move camera around, you have to modify cameraX-Y-Z. If you want to move forward you should move your camera towards to target vector. For example to move 10 unit forward.
targetX += cos(angle)*10;
targetY += sin(angle)*10;
You also need to recalculate target vector since target position also should move.
If you want to move backwards, use -= operator instead. If you want to move sides then you have to add or remove angle PI/2 in those calculations.
To rotate camera around just increase/decrease angle and recalculate target vector.
This is a very basic camera and you won't be able to look up or down. You have to use pitch/yaw camera to be able to look up and down.
I am trying to write an Android application that can translate a triangle a have used the
http://developer.android.com/training/graphics/opengl/motion.html code from Google but when I replaced the
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0);
with
Matrix.translate(mMVPMatrix,0,dx,dy,0);
the triangle was moving also on the Z axis and it did not look like a translation at all
What can i do ?
The following code:
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0);
means:
mRotationMatrix <-- Create a rotation matrix of mAngle degrees around axis -Z
mMVPMatrix <-- The product of mRotationMatrix and mMVPMatrix
While the following:
Matrix.translate(mMVPMatrix,0,dx,dy,0);
means:
mMVPMatrix <-- Translate mMVPMatrix of dx along X axis and dy along Y axis
I assume that mMVPMatrix is a perspective projection (and the P of MVP usually suggests that). Usually you don't translate stuff that has already been projected. Try the following instead:
Matrix.setIdentityM(mTranslationMatrix, 0);
Matrix.translateM(mTranslationMatrix, 0, dx, dy, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mTranslationMatrix, 0, mMVPMatrix, 0);
I dont think you want to translate your MVP matrix, you want to create an identity matrix, translate it, then multiply it with the mMVPMatrix.
I know that isnt exist pushmatrix, popmatrix, and the matrix stack, loadidentity, rotate, translate etc.
How can I rewrite my existing 1.0-1.1 engine to work with 2.0?
I tried this first:
void glRotate(float x, float y, float z) {
Matrix.setRotateM(mMMatrix, 0, x, 1, 0, 0);
Matrix.setRotateM(mMMatrix, 0, y, 0, 1, 0);
Matrix.setRotateM(mMMatrix, 0, z, 0, 0, 1);
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
}
void glTranslate(float x, float y, float z) {
Matrix.translateM(mMMatrix, 0, x, y, z);
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
}
glTranslate it is not working, how can I translate my modell in the world?
glRotate only rotate in Z my object, x,y doesnt work at all.
+
How to implement a matrix stack/glpush/glpopmatrix? Anybody has a shema for that?
Try use
Matrix.setIdentityM(mMMatrix, 0);
before calculating matrix transformations.
And use Matrix.rotateM() instead of Matrix.setRotateM().
I have had the same problem as you about 1 year ago.
I had to write from scratch most of those functions and I can assure you it is a bloody mess and very error prone.
I suggest you to start from a very valid implementation you can find in the file "esTransform.c" in the samples directory of the OpenGL Gold Book (OpenGL ES 2.0 Programming Guide).
The book is this one:
http://opengles-book.com/downloads.html
The code can be downloaded from google code here:
http://code.google.com/p/opengles-book-samples/
I suggest you anyway to buy the book, it becomes quickly your opengl ES 2.0 bible and it is very well done.
Just to conclude, check the usage license of the source code before you go into production.
i'am new in OpenGL ES. Can you helps me to calculate world coordinates of cube after rotate and translate. For example:
first i rotate cube:
gl.glRotatef(90, 1, 0, 0);
than change his position
gl.glTranslatef(10, 0, 0);
How can i calculate his "new" world coordinates? I read about glGetFloatv(GL_MODELVIEW_MATRIX , matrix) but not understand it. Maybe someone can provide sample code.
EDIT:
I found solution. Android code
float[] matrix = new float[] {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1,
};
Matrix.rotateM(matrix, 0, rx, 1, 0, 0);
Matrix.rotateM(matrix, 0, ry, 0, 1, 0);
Matrix.rotateM(matrix, 0, rz, 0, 0, 1);
Matrix.translateM(matrix, 0, x, y, z);
x = matrix[12];
y = matrix[13];
z = matrix[14];
Thanks for answers.
Although you have an answer for the part you want, in terms of the rest of your question, you'd do something like (please forgive me if I make any Java errors, I'm not really an Android person):
float[] matrix = new float[16];
gl.glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
// check out matrix[12], matrix[13] and matrix[14] now for the world location
// that (0, 0, 0) [, 1)] would be mapped to
That getFloatv just reads back the current value of the modelview matrix into the float buffer specified. In OpenGL 4x4 matrices are specified so that index 0 is the top left, index 3 is the lowest number in the first column and 12 is the number furthest to the right in the first row. That's usually referred to as column-major layout, though the OpenGL FAQ isn't entirely happy with the term.