3D rotation while object being translated - android

I've been playing with Android animation framework and I found the following 3D rotation sample code:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Transition3d.html
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.html
It does pretty much what I want but I want the ImageView to rotate while it's being translated from point A to point B and the it should rotate along it's own center(which is moving) instead of the center of the container of screen.
Does anyone know how to do that?
-Rachel

Well it's pretty close to what you posted. Essentially you're multiplying the rotational matrix by the translation matrix. That's essentially what happens under the covers. Android hides that detail from you with it's API:
Matrix matrix = transformation.getMatrix();
matrix.rotate( rotateX, rotateY );
matrix.postTranslate( transX, transY );
Rotate first then translate will rotate the image around it's own axis first before translating it.

Related

Rotate item in a circle shape using phone accelerometer/gravity sensor vector

I'm trying to make a small circle move in another bigger circle as a ball moving in circle relative to Android phone tilting. I'm doing this in Godot but I think the principle is the same in all game engines probably. I make a scene in Godot and add two sprites as the two circles as the following picture. I get the accelerometer 3D vector, use x and y values and calculate the angle in x and y plate (relative to y axis i.e Vector2(0, 1) ) and rotate the mentioned scene to that degree using an animation, using this code
func _process(delta: float) -> void:
var vec3 = Input.get_accelerometer()
accelVec = Vector2(-stepify(vec3.x, 0.1), -stepify(vec3.y, 0.1))
var angle = accelVec.angle_to(Vector2(0, 1))
rotateTween.interpolate_property(self, "rotation", rotation, angle, 0.2,
Tween.TRANS_LINEAR)
rotateTween.start()
return
But the problem lies in here that when the x value of accelerometer 3D vector changes from a positive to negative value i.e when the ball is at top of the circle and is going to go to the other half of the circle, it actually moves from bottom of the circle to the desired point rather than from top of the circle.
I hope I explained the problem well, though I doubt it.
I added the Gif that shows actual test on an android phone here Testing in Android.
Any idea how to solve this problem?
Thanks in advance.
This is because Tween is interpolating linear values. It doesn't know it's working with angles, or that they should wrap around.
So when you're at -179 degrees and you tween to 179--a difference of 2 degrees--Tween just sees -179 -> 179 and goes through the whole circle.
You probably don't need a Tween here at all because _process() happens every frame.

Rotation of a figure around 2 different axis (say X and Y) (OpenGL ES 2.0)

I'm trying to rotate a figure based on the mouse position where a horizontal swipe will rotate it along the y axis and a vertical swipe will rotate it along the z axis. Now i followed the tutorial on android development and was able to create a rotation about the z axis. I now want to combine it with rotation along the y axis. Here is a part of my code:-
Matrix.setRotateM(mRotationMatrix,0,mAngle,0,0,-1.0f);
//i added the following line
Matrix.setRotateM(mRotationMatrix2,0,mAngle2,0,-1.0f,0);
Matrix.multiplyMM(scratch,0,mMVPMatrix,0,mRotationMatrix,0);
//and this line too
//i am rotating the already rotated figure on a different axis this time
Matrix.multiplyMM(temp,0,scratch,0,mRotationMatrix2,0);
mTriangle.draw(temp);
But when i run the above code, I am getting strange results. The code was working right before i added the 2 lines of code and the float matrix variable temp.
You should multiply only once with MVP, and do no transform after, so at the end just before drawing.
Since VP is doing the transformation from space to camera to screen (so further transforms would be awkward, like having a camera looking the screen displaying another camera ;-) ).

Cube rotation issue in opengl android

I want to rotate the cube when the user is touching it. To rotate it,is quite simple but actual problem is if the user is tilting it then always it should stop in particuler face(cube has 6 faces and i mean that only one face should be visible at one time). Please give your suggetion if anyone worked on that.
In the case of a cube this is simple: Face normals are the cartesian axes. So one looks straigt on a face if you constrain the rotations around the cartesian axes (X, Y, Z) and the rotation angles are multiple of pi/2 = 90°.
So in your code when the user stops interacting, set the rotation angles to the next multiple of 90°
fmod(round(angle/90) * 90, 360); // degrees
fmod(round(angle/(pi/2)) * pi/2, 2*pi); // radians
Either do it hard, or animate it.
If your object is not a cube, but arbitrary, you need to find the additional rotation for the face to get perpendicular to the view axis. This angle is determined by acos( scalar_product(normalize(face_normal), normalize(view_axis)) ) the axis of rotation is given by cross_product(normalize(face_normal), normalize(view_axis))

Billboarding in Android OpenGL ES 1.0

I'm trying to get billboarding to work, but having trouble with the last step.
After following these directions from NeHe's tutorials (http://nehe.gamedev.net/data/articles/article.asp?article=19) I have my look, right, and up vectors, and I have already translated the modelview matrix to the centerpoint of the billboard by using glTranslatef().
float[] m = {right.x,right.y,right.z,0f,
up.x,up.y,up.z,0f,
look.x,look.y,look.z,0f,
pos.x,pos.y,pos.z,1f}; //pos is the centerpoint position
gl.glMultMatrixf(m, 0);
When I try to create a multiplication matrix out of these like so, the billboards are displayed all over the place in the wrong positions and orientations.
I guess my problem is that I don't know how to correctly create and multiply the matrix. I tried doing this instead, but then half the lines (the ones that need to rotate counter-clockwise) are rotated in the wrong direction:
//normal is the vector that the billboard faces before any manipulations.
float angle = look.getAngleDeg(normal); //returns angle between 0 and 180.
gl.glRotatef(angle, up.x,up.y,up.z);
Got it, using my second method. Calculating the angle between vectors (arccos of the dot product) can only give an angle between 0 and 180, so half the time you want to negate the angle so the rotation is in the opposite direction.
This is easy to check...since I already have the right vector, I can just check if the angle between the right vector and the normal is acute. If it's acute, then you want to negate the original angle.

How to use an OpenCV rotation and translation vector with OpenGL ES in Android?

I'm am working on a basic augmented reality application on Android. What I did so far is detect a square with opencv and then using cvFindExtrinsicCameraParams2() I calculated a rotation and translation vector. For this I used 4 object points, which are just the corners of a square around (0,0,0) and the 4 corners of the square in the image.
This yields me a pretty good rotation and translation matrix. I also calculated the rotation matrix with cvRodrigues2() since using this is easier than the rotation vector. As long as I use these to draw some points in the image everything works fine. My next step is however to pass these vectors and the matrix back to java and then use them with OpenGL to draw a square in an OpenGLView. The square should be exactly around the square in the image which is displayed behind the OpenGLView.
My problem is that I cannot find the correct way of using the rotation matrix and translation vector in OpenGL. I started of with exactly the same object points as used for the openCV functions. Then I applied the rotation matrix and translation vector in pretty much any possible way I could think of. Sadly none of these approaches produce a result which is anyway near what I hoped for. Can anyone tell me how to use them correctly?
So far the "closest" results I have gotten, was when randomly multiplying the whole matrix with -1. But most of the time the squares still look mirror inverted or rotated for 180 degrees. So I guess it was just a lucky hit, but not the right approach.
Okay after some more testing I finally managed to get it to work. While I don't understand it... it does 'work'. For anyone who will need to do this in the future here is my solution.
float rv[3]; // the rotation vector
float rotMat[9]; // rotation matrix
float tv[3]; // translation vector.
rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2];
//Convert the rotation vector into a matrix here.
//Complete matrix ready to use for OpenGL
float RTMat[] = {rotMat[0], rotMat[3], rotMat[6], 0.0f,
rotMat[1], rotMat[4], rotMat[7], 0.0f,
rotMat[2], rotMat[5], rotMat[8], 0.0f,
tv[0], -tv[1], -tv[2], 1.0f};
As genpfault said in his comment everything needs to be transposed since OpenGL since OpenGL needs a column-major order. (Thanks for the comment, I saw that page earlier already.) Furthermore the y and z rotation angle as well as the y and z translation need to be multiplied by -1. This is what I find a bit weird. Why only those and not the x values too?
This works as it should I guess. But corners the don't match exactly. I guess this is caused by some wrong openGLView configurations. So even though I am still not a 100% happy with my solution I guess it is the answer to my question.
Pandoro's method really works! In case someone wondering "how to convert the rotation vector into a rotation matrix" here's how I did it. By the way, I've used these in OpenGL 2, not ES.
// use the rotation vector generated from OpenCV's cvFindExtrinsicCameraParams2()
float rv[] = {rotation->data.fl[0], rotation->data.fl[1], rotation->data.fl[2] };
// use the translation vector generated from OpenCV's cvFindExtrinsicCameraParams2()
float tv[] = {translation->data.fl[0], translation->data.fl[1], translation->data.fl[2]} ;
float rm[9];
// rotation matrix
CvMat* rotMat = cvCreateMat (3, 3, CV_32FC1);
// rotation vectors can be converted to a 3-by-3 rotation matrix
// by calling cvRodrigues2() - Source: O'Reilly Learning OpenCV
cvRodrigues2(rotation, rotMat, NULL);
for(int i=0; i<9; i++){
rm[i] = rotMat->data.fl[i];
}
rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2];
//Convert the rotation vector into a matrix here.
//Complete matrix ready to use for OpenGL
float RTMat[] = {rm[0], rm[3], rm[6], 0.0f,
rm[1], rm[4], rm[7], 0.0f,
rm[2], rm[5], rm[8], 0.0f,
tv[0], -tv[1], -tv[2], 1.0f};
Good luck!

Categories

Resources