How to create 3D rotation effect in Android OpenGL? - android

I am currently working on a 3D model viewer for Android using OpenGL-ES. I want to create a rotation effect according to the gesture given.
I know how to do single-axis rotation, such as rotate solely on the x-, y- or z-axis. However, my problem is that I don't know how to combine them all 3 together and have my app know in which axis I want to rotate depending on the touch gesture.
Gestures I have in mind were:
Swipe up/down for x-axis
Swipe left/right for y-axis
swipe in circular motion for z-axis
How can I do this?
EDIT: I found out that 3 types of swipes can make the moment very ugly. Therefore what I did was remove the z-axis motion. After removing that condition, I found that the other 2 work really well in conjunction with the same algorithm.

http://developer.android.com/resources/articles/gestures.html has some info on building a 'gesture library'. Not checked it out myself, but seems to fit what you're looking for
Alternatively, try something like gestureworks.com (again, I've not tried it myself)
I use a progressbar view for zooming in and out. I then use movement in x on the GLSurfaceView to rotate around the y axis and movement in y to rotate around the x axis
The problem with a gesture is that the response is not instant as the app tries to determine what gesture the user used. If you then use how far the user moves their finger to determine the amount to rotate/zoom then there is no instant feedback and so it takes time for the user to learn how to control rotate/zoom amount. I guess it would work if you were rotating/zooming by a set amount each gesture

It sounds like what you are looking to do is more math intensive than you might know. There are two ways to do this mathematically. (1) using quaternions (2) using basic linear algebra (but will result in gimbal lock if you arent careful.. but since you are just spinning then this is not a concern to you).. Lets go the second route since its easier.. What you need to do is recieve the beginning and end points of the swipe via a gesture implement and when you have those two points.. calculate the line that it makes. When you have that line, you can easily find the perpendicular vector to that line with high school math. That should now be your axis of rotation in your rotation matrix:
//Rotate around the axis based on the rotation matrix (rotation, x, y, z)
gl.glRotatef(rot, 1.0f, 1.0f, 0.0f);
No need for the Z rotation since you can not rotate in the Z plane with a 2D tablet. The 1.0f, 1.0f are the values that should be variables that represent the x,y of your vector. The (rot) should serve as the magnitude of the distance between the two points.
I havent done this in a while so let me know if you need more precision.

Related

Can we Draw line in android canvas between two points given by gyroscope?

Is it possible to draw a line from Point A(where user touched first) and Point B(where user touched second) in android over a camera.
The user can touch first point and rotate his camera in other direction to tap second point.
I am using gyroscope, accelerometer and magnetometer (Sensor Fusion) and I get x,y,z co-ordinates on touch.
But can we draw a 3D image on canvas where ever the user touches. Something similar to what MagicPlan app is doing.
Thanks #chipopo but the real concern is, is it possible to actually draw a line >between two points given by gyroscope sensor.
Short answer,no. Gyroscope is a rate sensor, not a position sensor. You need to do math to get Points.
Since your in Android, I would recommend Orientation
once you have this you need to decide on a radius that best fits your use case and also establish a reference orientation. Once you grab two orientations its up to you how to map shperical points to a 2d canvas.
One method I have used in the past is just plotting the delta pitch on Y and the delta heading on X, however you may need to think about what roll means to you in the context of what your app is trying to do.
You should probably use openGL, but you probably want a drawing library of some sort.

Stretching a sprite from point a to b starling

I am developing a mobile game for iOS and Android with Starling. I am very new to this framework. I need to add a sprite to the screen and then have the initial point on the screen that was touched be anchor point 1 and then the user will drag there finger which will adjust the second anchor point until they release their finger from the screen. Imagine several nodes that need connected by a line and you can picture what I am trying to do. The problem is that I can change the pivot to be at the beginning of the line but I dont know how to make the other anchor point work. I also cannot use anything other than a sprite as the line is animated by a sprite sheet. Any help that can be provided is greatly helpful, I have been thinking about this for a while now and can't seem to figure it out. Code is helpful and preferred but just giving me an outline of the concept would help as I can probably figure out code. Thanks!
I don't know actionscript but I'm sure if it is for android the touch event has 3 phases (generally): touch down, touch move, touch up.
You say you only have a sprite so define some variables:
initX, initY, finalX and finalY. All floats (or ints if you cast them). And a couple of booleans: set1 and set2 all false
On touch down you ask if set1== false if so, set initX=eventX and initY=eventY (eventX and eventY would be here the X and Y of the touch event). Then set set1=true
On touch move you do the same as above, with set2. if set2==false, set finalX=eventX and finalY=eventY, then set2=true.
and you draw your sprite from (initX,initY) to (finalX,finalY) or if you're using width/height then finalX-initX for the width, finalY-initY for height.
I hope this helped. I didn't even know starling existed but since it's actionscript it must be pretty close to java in its syntax

how to implement panning in opengl program android

I am having a program in opengl es, in which a cube is getting rotated on user-touch along X,Y,Z axis.
Now I want to implement panning feature for the same (when user touches the cube with atleast 2 fingers--it wil get panned along the axis)...
Please anyone suggest me where do I start, I have searched too much on google stil unable to find any satisfactory example.
My code is similar to the code in API demos application which is by default installed on the emulator in which a cube is shown.
Panning can refer to a number of different things in a 3D context, but in general you're just going to be moving the camera around. This is just a matter of how you set up your modelview matrix; I recommend using some sort of 'lookat' function to calculate this, and simply change your eye coordinate.
For the most natural panning, the coordinate should be modified by multiplying your screenspace displacement vector by your existing modelview matrix with w=0, and add the resulting vector to your eye coordinate.

Open GL Android 3D Object Rotation Issue

I am having trouble rotating my 3D objects in Open GL. I start each draw frame by loading the identity (glLoadIdentity()) and then I push and pop on the stack according to what I need (for the camera, etc). I then want 3D objects to be able to roll, pitch and yaw and then have them displayed correctly.
Here is the catch... I want to be able to do incremental rotations as if I was flying an airplane. So every time the up button is pushed the object rotates around it's own x axis. But then if the object is pitched down and chooses to yaw, the rotation should then be around the object's up vector and not the Y axis.
I've tried doing the following:
glRotatef(pitchTotal, 1,0,0);
glRotatef(yawTotal, 0,1,0);
glRotate(rollTotal, 0,0,1);
and those don't seem to work. (Keeping in mind that the vectors are being computed correctly)I've also tried...
glRotatef(pitchTotal, 1,0,0);
glRotatef(yawTotal, 0,1,0);
glRotate(rollTotal, 0,0,1);
and I still get weird rotations.
Long story short... What is the proper way to rotate a 3D object in Open GL using the object's look, right and up vector?
You need to do the yaw rotation around (around Y) before you do the pitch one. Otherwise, the pitch will be off.
E.g. you have a 45 degrees downward pitch and a 180 degrees yaw. By doing the pitch first, and then rotate the yaw around the airplane's Y vector, the airplane would end up pointing up and backwards despite the pitch being downwards. By doing the yaw first, the plane points backwards, then the pitch around the plane's X vector will make it point downwards correctly.
The same logic applies for roll, which needs to be applied last.
So your code should be :
glRotatef(yawTotal, 0,1,0);
glRotatef(pitchTotal, 1,0,0);
glRotatef(rollTotal, 0,0,1);
Cumulative rotations will suffer from gimbal lock. Look at it this way: suppose you are in an aeroplane, flying level. You apply a yaw of 90 degrees anticlockwise. You then apply a roll of 90 degrees clockwise. You then apply a yaw of 90 degrees clockwise.
Your plane is now pointing straight downward — the total effect is a pitch of 90 degrees clockwise. But if you just tried to add up the different rotations then you'd end up with a roll of 90 degrees, and no pitch whatsoever because you at no point applied pitch to the plane.
Trying to store and update rotation as three separate angles doesn't work.
Common cited solutions are to use a quaternion or to store the object orientation directly as a matrix. The matrix solution is easier to build because you can prototype it with OpenGL's built-in matrix stacks. Most people also seem to find matrices easier to understand than quaternions.
So, assuming you want to go matrix, your prototype might do something like (please forgive my lack of decent Java knowledge; I'm going to write C essentially):
GLfloat myOrientation[16];
// to draw the object:
glMultMatrixf(myOrientation);
/* drawing here */
// to apply roll, assuming the modelview stack is active:
glPushMatrix(); // backup what's already on the stack
glLoadIdentity(); // start with the identity
glRotatef(angle, 0, 0, 1);
glMultMatrixf(myOrientation); // premultiply the current orientation by the roll
// update our record of orientation
glGetFloatv(GL_MODELVIEW_MATRIX, myOrientation);
glPopMatrix();
You possibly don't want to use the OpenGL stack in shipping code because it's not really built for this sort of use and so performance may be iffy. But you can prototype and profile rather than making an assumption. You also need to consider floating point precision problems — really you should be applying a step that ensures myOrientation is still orthonormal after it has been adjusted.
It's probably easiest to check Google for that, but briefly speaking you'll use the dot product to remove erroneous crosstalk from two of the axes to the third, then to remove from one of the first two axes from the second, then renormalise all three.
Thanks for the responses. The first response pointed me in the right direction, the second response helped a little too, but ultimately it boiled down to a combination of both. Initially, your 3D object should have a member variable which is a float array size 16. [0-15]. You then have to initialize it to the identity matrix. Then the member methods of your 3D object like "yawObject(float amount)" just know that you are yawing the object from "the objects point of view" and not the world, which would allow the incremental rotation. Inside the yawObject method (or pitch,roll ojbect) you need to call the Matrix.rotateM(myfloatarray,0,angle,0,1,0). That will store the new rotation matrix (as describe in the first response). You can then when you are about to draw your object, multiply the model matrix by the myfloatarray matrix using gl.glMultMatrix.
Good luck and let me know if you need more information than that.

How do I rotate a canvas without disturbing the coordinate system in Android?

I am trying to rotate a canvas with canvas.rotate and move an object on it at the same time. The problem is that with the rotation, the coordinate system of the canvas rotates as well, so I get cases when my object is supposed to be moving along the y axis, but the y axis is rotated on place of the x axis. It is a mess. Is there a way to go around this?
It's using matrix math; if you do things in the opposite order (translate then rotate, or vice versa), you'll get the opposite effect.
Also, use SetMatrix(null) to clear the matrix to the identity between operations; not sure if that's the kind of mess you're having trouble with.

Categories

Resources