Rotating an object based on UI input - android

I want to rotate a object(Some thing like 3d cube ) without touching the surface , say I have a specific x,y,z axis UI and when I change this axis value From the UI , It in turn should turn the 3D object .

The rotation of your object, when being drawn, is set by some variables (a rotation matrix, or a quaternion or such).
Your UI will provide some values, either by widgets you retrieve the values from or by sending events. Using these values you adjust the drawing controlling variable and issue a full redraw of the scene.
OpenGL is not a scene graph. It doesn't maintain a scene, it just draws points, lines or triangles to a pixel based framebuffer. As soon as a primitive (point, line, triangle) has been drawn OpenGL has no recollection about it whatsoever. You want something altered => >ou redraw the whole scene.

The concept you're looking for is a "track ball". Here's some info:
Trackball

Related

How to detect clicks (touch) on specific parts of 3d model?

I need to load a 3d model to my app (is not a game, not that it makes any difference) and detect when the user touches specific parts of this model, to take different actions.
How can I do this? Is it possible?
I'm not familiar with Rajawali, but GitHub describes it as an OpenGL ES framework. As you described it in the comment above, you'll need to consider two basic user actions, and one action I'll add as helpful:
Swipe across the screen in some direction: change in X, change in Y.
Touch at some (x,y) point on screen with the car in some orientation.
(Optional) Zoom in/out to make it easier for a user to select small features such as side mirrors.
Depending on what OpenGL ES details Rajawali exposes, you'll need to do one or both of the following:
Learn about the four matrices that determine how a 3D scene is rendered on a 2D screen.
Find the Rajawali functions with names such as "lookAt" or "setViewpoint," and learn how to pass screen gesture info to these functions.
You can read about the four OpenGL matrices at length elsewhere. Even if Rajawali simplifies the coding a bit you should learn a bit about those matrices. Although your first inclination is to change the "model" matrix that affects the object's position and orientation, it's more likely that you'll be manipulating the "view" matrix that determines the point and direction in space from which the user sees the car. That is, the car will actually remain centered at (0,0,0), and the user's swipes, touches, and pinches will change the viewpoint.
Constraining movements so that the vehicle is always centered is nice both because your code can be a little simpler, and also because the user can't "lose" the car by sliding the viewpoint too far to one side.
The simplest change of viewpoint is a zoom, which in most iterations means simply changing the Z translation of the viewpoint matrix. Rajawali may make this simpler by providing zoomIn() and zoomOut() functions. Otherwise you'll need to do this:
In the callback or "event handler" provided by Rajawali/Android for a pinch, get the pinch-in or pinch-out value.
Call the Rajawali zoomIn() or zoomOut() function, if it exists. You will likely need to scale the value so that the amount of pinch matches expectations for zooming in and out of a car model.
Alternately, set the Z translation component of the view matrix.
Converting an (x,y) 2D screen touch point to a ray cast into 3D space can be tricky if Rajawali doesn't provide an appropriate function called something like "screenToWorld" that accepts a point in 2D screen space and a 3D point or 3D ray in world space. Spend time googling for "ray casting" for Rajawali. Here's a brief overview of what the code will need to do:
Convert a 2D touch point into a 3D ray pointed into the screen.
Check for the intersection(s) of the 3D ray and various subobjects.
(Optional) Change the color or otherwise highlight the selected object.
OpenGL does not provide a ray casting function, and I don't recommend implementing it on your own unless you have no choice. Various frameworks that wrap around or supplement OpenGL may provide this function. OpenGL coders will fault me for this description, but from memory here's how to convert a 2D touchpoint into a 3D ray pointing into the screen:
Get the (x,y) 2D screen touch point from a "touch" or "click" callback or event handler in Rajawali or Android.
Convert the 2D touch point to a 3D point. If I remember, this means setting Z to some value such as -1, 0, or 1. This is the base point of the ray.
Define a second 3D point with a different Z value. This is a far point of the ray.
Use the screen, projection, and view matrices to transform the 3D points into "world" space.
Given the 3D world coordinates for your base point and far point, use ray-object intersection to determine what object is intersected.
Again, Rajawali may provide some function that determines which object(s) are intersected by the ray. If multiple objects are returned, then pick the closest object. Since your vehicle is already subdivided into multiple subobjects this shouldn't be too hard. Implementing pinch-to-zoom can make it easier for a user to select a small object.
Swiping is analogous to a mouse move for OpenGL, and many starter projects for OpenGL describe how to convert a mouse move to a rotation. Assuming for the moment that the model rotates only about the vertical axis from the ground through the roof, then you simply need to change left/right swipes to positive/negative rotations about what in OpenGL is typically the Y-axis.
From Android/Rajawali, handle the "swipe" event handler or callback. This is analogous to a "mouseMove" function.
Translate the left/right swipe into a negative/positive value.
Call the rotateAboutY() function, if available, OR apply a rotation to the viewpoint matrix (which I won't describe here).
Given all that, I would suggest the following approach:
See if Rajawali provides convenience functions to convert screen coordinates to a world ray, to convert a screen swipe to a rotation, and to test a ray intersection with a series of objects.
Even if Rajawali provides these functions, read a little bit about the low-level OpenGL ES underneath, and the four matrices: screen, perspective, viewpoint, and model.
If Rajawali doesn't provide the convenience functions, look for a framework that does OR see if some other library that works with Rajawali can provide these convenience functions.
If you can't change frameworks or find a framework that hides the messy details, plan to spend a week or more studying OpenGL closely. You probably don't need to know about shaders, textures, etc., but you will need to understand the OpenGL 3D space, the four matrices, and so on.

Open GL timing with drawFrame thread

I have a 3D world that works well with a camera and game objects. When the camera 'renders' it positions the matrix in the location of the camera. To do this, I call the following code:
gl.glMultMatrixf(rotationArray,0);
gl.glTranslatef(position.getX(), position.getY(), position.getZ());
Now when each object gets rendered, I call this for each object. (Note that I push and pop the matrices appropriately)
gl.glTranslatef(position.getX(), position.getY(), position.getZ());
gl.glMultMatrixf(rotationArray,0);
Now my question comes into play of when I bring models into the world, I need certain Meshes to pivot not around the 0,0,0 point, but around a different point. I have an object called Mesh that has an ArrayList of submeshes. Each mesh (and submesh) have a pivot point location. (an x,y and z float).
Where do I translate the matricies so I pivot around the designated point? I've tried all sorts of combinations and nothing works!
Example:
gl.glTranslatef(position.getX(), position.getY(), position.getZ());
gl.glMultMatrixf(rotationArray,0);
gl.glTranslatef(pivotPoint.getX(),pivotPoint.getY(),pivotPoint.getZ());
and I've tried
gl.glTranslatef(pivotPoint.getX(),pivotPoint.getY(),pivotPoint.getZ());
gl.glMultMatrixf(rotationArray,0);
gl.glTranslatef(position.getX(), position.getY(), position.getZ());
This comes down to rotation around an arbitrary point. Traditionally when you rotate an object, you usually rotate it around the object's center but in this case you have a separate pivot point.
The process of rotating an object around any arbitrary point is:
Translate by -(RotationPoint)
Rotate
Translate by +(RotationPoint)

GluProject not working... If the object haves Z=-1.0f and it is scaled to (0.01f,0.01f,0.0f) which parameters I have to pass to GluProject?

Until now, I worked with gluProject, perspective projection, and a zoomable square centered on the screen with a lower left vertex (-1,-1,0). I zoom the square adjusting the Z axis.
For example, I zoomed the square to Z=-5, and I call gluProject with the openGL object parameters (-1,-1,0) to know the window pixels X,Y position of that vertex of the square. It works fine.
But now, I changed my architecture, and now I'm not using Z to zoom, I'm scaling to zoom. I have the square at Z=-1.0f, and initially it is scaled to (0.01f,0.01f,0.0f), is a small square.
Which X,Y,Z values do I have to pass to gluProject? I'm passing -1,-1,0, and gluProject is giving me erroneous x,y outPutCoords values, (-101.774124,-226.27419)
Again and again and again: gluProject does exactly the same thing like the OpenGL transformation pipeline (if called with OpenGL's matrices and viewport, of course). So whatever vertices you send to OpenGL, these are the vertices you have to put into gluProject.
If you render the polygon using the vertex (-1,-1,0), then you have to call gluProject with this vertex. Every other transformation (be it translation, scaling, rotation, or whatever) comes from the transformation matrices. But if you indeed render the polygon using the vertex (0.01, 0.01, 0), then you have to put this into gluProject.
Make sure you completely understand the OpenGL transformation pipeline (the answers to this question may help) and the workings of gluProject before continuing to use it and posting questions for every little input that you think gives wrong results.

OpenGL-ES: How to set an object at the coordinates of the touch?

I'm looking for a way to have an opengl object(triangles etc) at the location on the screen where you touch the screen. I now have an 3D pyramid on the screen, wich moves over the screen, based on the difference between the start of your touch, and where you dragged it to.
In normal surfaceViews I could just do something like element.x = event.getX(), but this will not work in openGL. So anyone has an idea?
ps: i'm using java/Android.
OpenGL is nor like a surface view, where each element is persistent. It's the 3D equivalent to pens and brushes. You need to keep track of all data yourself.
So in your touch event handler you use the input coordinate to project a ray so some plane perpendicular to the view. You've to implement this projection yourself, but it's easy enough: Search for "ray plane intersection". This gives you the coordinates on the plane, that corresponds with that points projection on the screen where the user touched. You use this coordinates to transform the object and redraw the scene.

Render object without creating a new buffer

I have code where I made a cube (using 12 triangles) and it moves back and forth in the z-direction.
Is there a way to render this cube (say) 5 times simultaneously just at different positions in space. As of now, I would have to create a new buffer for each cube, which seems wrong.
if CubeObj.draw() is your cube's draw function (likely a call to glVertexPointer then glDrawElements),
glPushMatrix(); //save the current matrix
glTranslatef(translatex, translatey, translatez);
//glRotatef(), glScale, etc.
CubeObj.draw();
glPopMatrix(); //restore the matrix
the glPush/PopMatrix() calls ensure that transformation commands in the block are only applied to that particular cube.
You can call your object's draw function multiple times without reconstructing the object.
That is to say, you could have another copy of the above code and change the transformation commands, and you would appear to have 2 separate cubes.
Hope this helped.
EDIT:
make sure you have a call to glLoadIdentity() at the top of your display function

Categories

Resources