In Android OpenGL
it has the command setLookAtM to specific the position for the camera view
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY,
lookZ, upX, upY, upZ);
If I rotate camera, by using command rotateM
Matrix.rotateM(mViewMatrix, 0 , angle , 0.0f, 1.0f, 0.0f);
Then, How could I get the 'LookAt' the exact camera view from mViewMatrix ?
the camera view position, i want is x,y,z that camera look at
Be careful, as calling rotateM doesn't technically rotate the camera, it applies a rotation to any future objects drawn. (it doesn't mean the same thing).
However in general, if you have a view matrix, and you want to see which direction it is facing, you want to transform the eye space forward vector (0,0,1) by the inverse of the view matrix.
As the view matrix transforms vectors in world space into eye space, the inverse view matrix transforms vectors from eye space into world space.
So you can:
Apply arbitrary operations to the current view matrix
Take its inverse
Multiply the inverse matrix by (0,0,1,0). (note this is the same as just pulling out the third column of the inverse matrix).
After #3 you will have the direction of the camera eye in world space. Add this to the eye's position, and you should know at what point it is pointing.
I have finished my question
and this is my solution
first, I need to made this 3 matrix to get result of x, y, z position
private float[] mRotXMatrix = new float[] {
1, 0, 0, 0,
0, 0, 1, 0,
0, 1, 0, 0,
0, 0, 0, 1 };
private float[] mRotYMatrix = new float[] {
0, 0, 1, 0,
0, 1, 0, 0,
1, 0, 0, 0,
0, 0, 0, 1 };
private float[] mRotZMatrix = new float[] {
0, 1, 0, 0,
1, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 };
Then in onSensorChanged(SensorEvent e) method I rotate all these 3 matrix together with my camera view like this
Matrix.multiplyMM(mViewMatrix, 0, deltaRotationMatrix, 0, mViewMatrix, 0);
Matrix.multiplyMM(mRotXMatrix, 0, deltaRotationMatrix, 0, mRotXMatrix, 0);
Matrix.multiplyMM(mRotYMatrix, 0, deltaRotationMatrix, 0, mRotYMatrix, 0);
Matrix.multiplyMM(mRotZMatrix, 0, deltaRotationMatrix, 0, mRotZMatrix, 0);
And to get the X, Y, Z of my camera view, just get it from these matrix
viewX = mRotXMatrix[2];
viewY = -mRotYMatrix[6]; // +/- up to your initial camera view
viewZ = mRotZMatrix[10];
Related
Hi I am working on a AR android app. I am using ARToolkit6. In this app I want to view my 3D object( A Cube) on left half of the screen. With this eventually I want to display 3 cubes on the screen each on 1/3 of the screen area.
I was able to scale the 3D object by tweaking ModelView Matrix. What I read so far, I think I need to tweak projection matrix to achieve my goal. I tried looking solutions online. But Couldn't get it to work. Can anyone direct me to right path?
for (int trackableUID : trackableUIDs) {
// If the marker is visible, apply its transformation, and render a cube
if (ARToolKit.getInstance().queryMarkerVisible(trackableUID)) {
float[] projectionMatrix = ARToolKit.getInstance().getProjectionMatrix();
float[] modelViewMatrix = ARToolKit.getInstance().queryMarkerTransformation(trackableUID);
float[] scalingMat = {1, 0, 0, 0, 0, 3.0f, 0, 0, 0, 0, 1.0f, 0, 0.0f, 0, 0, 1};
float[] newModelView = modelViewMatrix;
multiplyMM(newModelView, 0, modelViewMatrix, 0, scalingMat, 0);
cube.draw(projectionMatrix, newModelView);
}
I followed the this link Set origin to top-left corner of screen in OpenGL ES 2 and (OpenGL ES) Objects away from view centre are stretched. So I translated the modelView Matrix but it doesn't solve the problem, the 3D object appears at the center of the screen. Can you explain how should I approach this problem? Thanks
#Override
public void draw() {
super.draw();
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glFrontFace(GLES20.GL_CCW);
// Look for trackables, and draw on each found one.
for (int trackableUID : trackableUIDs) {
// If the marker is visible, apply its transformation, and render a cube
if (ARToolKit.getInstance().queryMarkerVisible(trackableUID)) {
float[] projectionMatrix = ARToolKit.getInstance().getProjectionMatrix();
float[] modelViewMatrix = ARToolKit.getInstance().queryMarkerTransformation(trackableUID);
float[] scalingMat = {1, 0, 0, 0, 0, 3.0f, 0, 0, 0, 0, 1.0f, 0, 0.0f, 0, 0, 1};
multiplyMM(modelViewMatrix, 0, scalingMat, 0, modelViewMatrix, 0);
float[] rightModelMatrix = new float[16];
Matrix.setIdentityM(rightModelMatrix, 0);
// Translate outer sphere by 5 in x.
Matrix.translateM(rightModelMatrix, 0, 5.0f, 0.0f, 0.0f);
Matrix.multiplyMM(modelViewMatrix, 0, rightModelMatrix, 0, modelViewMatrix, 0);
cube.draw(projectionMatrix, modelViewMatrix);
}
}
Also tried this but the object gets displayed at the center of the screen.
glMatrixMode(GL_PROJECTION);
glTranslatef(5f, 0f, 0f);
I am having some problems with proper scene manipulations with OpenGL ES 2.0. On my screen I want to draw a rectangle and a cube. Rectangle should be moved to the bottom and scaled while cube should be moved to the top and scaled. What's more, I want to rotate this cube in all 3 axis.
This is what I've created so far:
#Override
public void onDrawFrame(GL10 gl) {
float[] scratch = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Matrix.setLookAtM(viewMatrix, 0, 0, 0, -6, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(MVPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
Matrix.translateM(scratchMatrix1, 0, 0, -1.1f, 0);
Matrix.scaleM(scratchMatrix3, 0, 0.5f, 0.5f, 0.5f);
Matrix.multiplyMM(scratchMatrix2, 0, scratchMatrix1, 0, scratchMatrix3, 0);
Matrix.multiplyMM(scratch, 0, scratchMatrix2, 0, MVPMatrix, 0);
rectangle.draw(scratch);
Matrix.setRotateM(scratchMatrix1, 0, angleXVal, 1.0f, 0, 0);
Matrix.setRotateM(rotationMatrix, 0, angleYVal, 0, 1.0f, 0);
Matrix.multiplyMM(scratchMatrix2, 0, rotationMatrix, 0, scratchMatrix1, 0);
Matrix.setRotateM(rotationMatrix, 0, angleZVal, 0, 0, 1.0f);
Matrix.multiplyMM(scratchMatrix3, 0, rotationMatrix, 0, scratchMatrix2, 0);
Matrix.translateM(scratchMatrix1, 0, 0, 0.3f, 0);
Matrix.multiplyMM(scratchMatrix2, 0, scratchMatrix3, 0, scratchMatrix1, 0);
Matrix.scaleM(scratchMatrix1, 0, 0.8f, 0.8f, 0.8f);
Matrix.multiplyMM(scratchMatrix3, 0, scratchMatrix2, 0, scratchMatrix1, 0);
Matrix.multiplyMM(scratch, 0, scratchMatrix2, 0, MVPMatrix, 0);
cube.draw(scratch);
}
The problem is that when I am rotating the cube also the rectangle is moving. It is this same with scale and translating of cube - it is pulling the rectangle.
For me it looks like the matrices are connected somewhere but I don't see where, because the rectangle is drawn first and scratch matrix is overwritten later.
Assuming that is your complete onDrawFrame() code, scratchMatrix1 etc are class member variables that persist from frame to frame.
That means that translations from one frame will carry over to the next, because Matrix.translateM() applies a translation to an existing matrix transform by adding to it, rather than setting the matrix to a given translation matrix and overwriting the previous values. So the translations will accumulate over several frames.
That means that when you translate the cube, the translation will still be sitting in scratchMatrix1 the next time onDrawFrame is called, and the rectangle translation will be added to it rather than be set afresh.
The same goes for Matrix.scaleM().
You can rectify this by initializing all the scratch matrices to identity at the start of the function, and again before beginning the calculation of the cube transform matrix:
Matrix.setIdentityM(scratchMatrix1, 0);
Matrix.setIdentityM(scratchMatrix2, 0);
Matrix.setIdentityM(scratchMatrix3, 0);
Matrix.setIdentityM(scratch, 0);
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 rotate moving object, but it rotates aroud the center of the coordinates system. How to make it rotate around itself while moving? The code is:
Matrix.translateM(mMMatrix, 0, 0, -y, 0);
Matrix.setRotateM(mMMatrix, 0, mAngle, 0, 0, 1.0f);
y += speed;
Matrix.translateM(mMMatrix, 0, 0, y, 0);
Don`t use the view matrix to rotate objects, this matrix is used as the camera for all the scene, To transform an object you should use the model matrix. To rotate if around its own center, you can use the following method:
public void transform(float[] mModelMatrix) {
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0, y, 0);
Matrix.rotateM(mModelMatrix, 0, mAngle, 0.0f, 0.0f, 1.0f);
}
Don`t forget use the identity matrix to reset the transformations in every loop.
I think your code is worng. You shoud update the value of 'y' before to apply any transformation.
public void onDrawFrame(GL10 gl) {
...
y += speed;
transform(mModelMatrix);
updateMVP(mModelMatrix, mViewMatrix, mProjectionMatrix, mMVPMatrix);
renderObject(mMVPMatrix);
...
}
The updateMVP method, will combine the model, view and projection matrices:
private void updateMVP(
float[] mModelMatrix,
float[] mViewMatrix,
float[] mProjectionMatrix,
float[] mMVPMatrix) {
// combine the model with the view matrix
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// combine the model-view with the projection matrix
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
}
And at last the render method, will execute the Shaders to paint the object:
public void renderObject(float[] mMVPMatrix) {
GLES20.glUseProgram(mProgram);
...
// Pass the MVP data into the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the shape
GLES20.glDrawElements (...);
}
I hope this will help you.
where do you make the object drawing?
I suppose it is after the code you have put up here, something like:
Matrix.translateM(mMMatrix, 0, 0, -y, 0);
Matrix.setRotateM(mMMatrix, 0, mAngle, 0, 0, 1.0f);
y += speed;
Matrix.translateM(mMMatrix, 0, 0, y, 0);
drawHere();//<<<<<<<<<<<<<<<<<<<
Then, the second translate call is the issue.
You should either move your draw call before the second translate.
or
the clean way to do it is:
Matrix.setIdentityM(mMMatrix, 0);//<<<<<<<<added
Matrix.translateM(mMMatrix, 0, 0, -y, 0);
Matrix.setRotateM(mMMatrix, 0, mAngle, 0, 0, 1.0f);
y += speed;
//Matrix.translateM(mMMatrix, 0, 0, y, 0); //<<<<<<<<<removed
drawHere();
I just used view matrix instead of model matrix and everything worked out. For details on model, view and projection matrices see.
I am trying to write code that will cycle between rendering an animation and rendering a heads up display. The animation works, however I am having difficulty switching between the animation's projection matrix and another orthographic projection matrix for the HUD.
The main loop runs as follows:
init();
while (isAnimationRunning) {
drawAnimation();
drawHUD();
}
And the initialization of the surface is:
void init(){
glEnableClientState(GL10.GL_VERTEX_ARRAY);
glClearColor(1, 1, 1, 1);
glMatrixMode(GL11.GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, windowWidth, windowHeight);
GLU.gluPerspective(gl11, 45.0f, windowWidth / windowHeight, 0.1f, 100.0f);
}
And the code for the animation rendering
void drawAnimation() {
glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL10.GL_MODELVIEW);
glLoadIdentity();
GLU.gluLookAt(gl11, x, y, zoom, x, y, 0, 0, 1, 0);
drawAnimationTextures();
}
And the code for the HUD rendering
void drawHUD(){
glMatrixMode(GL10.GL_MODELVIEW);
glPushMatrix();
// IF THIS LINE IS REMOVED THE ANIMATION DISPLAYS BUT NOT THE HUD
glLoadIdentity();
glClear(GL10.GL_COLOR_BUFFER_BIT);
GLU.gluLookAt(gl11, 0, 0, 2, 0, 0, 0, 0, 1, 0);
glMatrixMode(GL10.GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
GLU.gluPerspective(gl11, 45, aspectRatio, 0.1f, 100.0f);
glOrthof(-aspectRatio, aspectRatio, -1, 1, -4, 4);
drawHUDTexture();
glPopMatrix();
glMatrixMode(GL10.GL_MODELVIEW);
glPopMatrix();
}
The screen is blank when this code is implemented. Any ideas what the problem might be?
////////////////////////
void drawTexture(float x, float y, float z, float sizeX, float sizeY,...){
glEnable(GL10.GL_TEXTURE_2D);
glPushMatrix();
bindTexture(texture);
glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
glFrontFace(GL10.GL_CW);
glColor4f(RGB[0], RGB[1], RGB[2], alpha);
glTranslatef(x, y, z);
glScalef(sizeX, sizeY, sizeZ);
glVertexPointer(3, GL10.GL_FLOAT, 0, squareVertexBuffer);
glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
glPopMatrix();
}
Why are you clearing the framebuffer in both routines? You should call it once only in your top level loop. If the animation appears when you comment out the loadidentity but still have the glclear there I am puzzled.
It looks like the hud overwrites the whole screen, make it semi transparent to check this, it may be so large you're just seeing a small part of it.
plus your hud code is setting up a perspective view, then an ortho view - which one do you want?