Android OpenGL 3D collection

I'm on Android OpenGL-ES 2.0 and after all the restrictions that come with it, I can't figure out how to use the 2D screen for the three-dimensional points that I have. I can not get the right results.

I am trying to fire a beam at a point cloud, which then I can compare the distances of my points with the beam, finding the nearest point.

public class OpenGLRenderer extends Activity implements GLSurfaceView.Renderer { public PointCloud ptCloud; MatrixGrabber mg = new MatrixGrabber(); ... public void onDrawFrame(GL10 gl) { gl.glDisable(GL10.GL_COLOR_MATERIAL); gl.glDisable(GL10.GL_BLEND); gl.glDisable(GL10.GL_LIGHTING); //Background drawing if(customBackground) gl.glClearColor(backgroundRed, backgroundGreen, backgroundBlue, 1.0f); else gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); if (PointCloud.doneParsing == true) { if (envDone == false) setupEnvironment(); // Clears the screen and depth buffer. gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); GLU.gluPerspective(gl, 55.0f, (float) screenWidth / (float) screenHeight, 10.0f ,10000.0f); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); GLU.gluLookAt(gl, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); if(pickPointTrigger) pickPoint(gl); gl.glPushMatrix(); gl.glTranslatef(_xTranslate, _yTranslate, _zTranslate); gl.glTranslatef(centerX, centerY, centerZ); gl.glRotatef(_xAngle, 1f, 0f, 0f); gl.glRotatef(_yAngle, 0f, 1f, 0f); gl.glRotatef(_zAngle, 0f, 0f, 1f); gl.glTranslatef(-centerX, -centerY, -centerZ); ptCloud.draw(gl); gl.glPopMatrix(); } } } 

Here is my pick function. I set the location in the middle of the screen for debugging purposes only:

 public void pickPoint(GL10 gl){ mg.getCurrentState(gl); double mvmatrix[] = new double[16]; double projmatrix[] = new double[16]; int viewport[] = {0,0,screenWidth, screenHeight}; for(int i=0 ; i<16; i++){ mvmatrix[i] = mg.mModelView[i]; projmatrix[i] = mg.mProjection[i]; } mg.getCurrentState(gl); float realY = ((float) (screenHeight) - pickY); float nearCoords[] = { 0.0f, 0.0f, 0.0f, 0.0f }; float farCoords[] = { 0.0f, 0.0f, 0.0f, 0.0f }; GLU.gluUnProject(screenWidth/2, screenHeight/2, 0.0f, mg.mModelView, 0, mg.mProjection, 0, viewport, 0, nearCoords, 0); GLU.gluUnProject(screenWidth/2, screenHeight/2, 1.0f, mg.mModelView, 0, mg.mProjection, 0, viewport, 0, farCoords, 0); System.out.println("Near: " + nearCoords[0] + "," + nearCoords[1] + "," + nearCoords[2]); System.out.println("Far: " + farCoords[0] + "," + farCoords[1] + "," + farCoords[2]); //Plot the points in the scene nearMarker.set(nearCoords); farMarker.set(farCoords); markerOn = true; double diffX = nearCoords[0] - farCoords[0]; double diffY = nearCoords[1] - farCoords[1]; double diffZ = nearCoords[2] - farCoords[2]; double rayLength = Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2) + Math.pow(diffZ, 2)); System.out.println("rayLength: " + rayLength); pickPointTrigger = false; } 

The change in persepctive zNear and Far does not have the expected results, how will the further perspective point 1.0-1000.0 be at a distance of 11 units?

 GLU.gluPerspective(gl, 55.0f, (float) screenWidth / (float) screenHeight, 1.0f ,100.0f); ..... 07-18 11:23:50.430: INFO/System.out(31795): Near: 57.574852,-88.60514,37.272636 07-18 11:23:50.430: INFO/System.out(31795): Far: 0.57574844,0.098602295,0.2700405 07-18 11:23:50.430: INFO/System.out(31795): rayLength: 111.74275719790872 GLU.gluPerspective(gl, 55.0f, (float) width / (float) height, 10.0f , 1000.0f); ... 07-18 11:25:12.420: INFO/System.out(31847): Near: 5.7575016,-7.965394,3.6339219 07-18 11:25:12.420: INFO/System.out(31847): Far: 0.057574987,0.90500546,-0.06634784 07-18 11:25:12.420: INFO/System.out(31847): rayLength: 11.174307289026638 

Look for any suggestions or, hopefully, errors that you see in my code. Very grateful. I collect as much as I can (this has been a problem for a while).

+6
source share
1 answer

I am also working on this, it is a very annoying annoying problem. I have two potential conclusions: 1. Somehow, the resulting z depends on where the camera is, and not on how you expect. When camera z is at 0, the result of z is -1, regardless of what winZ is. Until now, I mainly looked at the resulting z, so I don’t have exact numbers for other coordinates, but now I messed up my code and your code, and I found that the messages being sent the beam length increases, the further the camera receives (0,0, 0). At (0,0,0) the beam length is reportedly equal to 0. An hour or so ago, I collected a bunch of points (cameraZ, winZ, resultZ) and connected them to Mathematica. The result seems to indicate a hyperbolic appearance of things; with one of the fixed variables, the other leads to the fact that the resulting z varies linearly, and the rate of change depends on the fixed variable.

My second result is http://www.gamedev.net/topic/420427-gluunproject-question/ ; swordfish quotes the formula:

WinZ = (1.0f / fNear-1.0f / fDistance) / (1.0f / fNear-1.0f / fFar)

Now this is not like the data I collected, but it is probably worth a look. I think I'll see if I can understand how math works and find out what happened. Let me know if you come up with anything. Oh, also, here is a formula tied to the collected data:

-0.11072114015496763 - 10.000231721597817 x - 0.0003149873867479971 x^2 - 0.8633277851535017 y + 9.990256062051143 xy + 8.767260632968973 * ^ - 9 y ^ 2

Wolfram Alpha does it like this: http://www.wolframalpha.com/input/?i=Plot3D [-0.11072114015496763% 60 + - + 10.000231721597817% 60 + x + - ++++ 0.0003149873867479971% 60 + x ^ 2 + - + 0.8633277851535017% 60 + y +% 2B ++++ 9.990256062051143% 60 + x + y +% 2B + 8.767260632968973% 60 * ^ - 9 + y ^ 2 +% 2C + {x% 2C + -15% 2C +++ +15}% 2C + {for% 2C + 0% 2C + 1}]


Aha! Success! As far as I can tell, gluUnProject is just broken. Or no one understands how to use it at all. Anyway, I created a function that properly overrides the gluProject function, which seems to be what they use to draw on the screen in some way! The code is as follows:

 public float[] unproject(float rx, float ry, float rz) {//TODO Factor in projection matrix float[] modelInv = new float[16]; if (!android.opengl.Matrix.invertM(modelInv, 0, mg.mModelView, 0)) throw new IllegalArgumentException("ModelView is not invertible."); float[] projInv = new float[16]; if (!android.opengl.Matrix.invertM(projInv, 0, mg.mProjection, 0)) throw new IllegalArgumentException("Projection is not invertible."); float[] combo = new float[16]; android.opengl.Matrix.multiplyMM(combo, 0, modelInv, 0, projInv, 0); float[] result = new float[4]; float vx = viewport[0]; float vy = viewport[1]; float vw = viewport[2]; float vh = viewport[3]; float[] rhsVec = {((2*(rx-vx))/vw)-1,((2*(ry-vy))/vh)-1,2*rz-1,1}; android.opengl.Matrix.multiplyMV(result, 0, combo, 0, rhsVec, 0); float d = 1 / result[3]; float[] endResult = {result[0] * d, result[1] * d, result[2] * d}; return endResult; } public float distanceToDepth(float distance) { return ((1/fNear) - (1/distance))/((1/fNear) - (1/fFar)); } 

Currently, it accepts the following global variables: mg - matrix grabber with current viewport matrices - float [4] with a viewport ({x, y, width, height})

The variables that it takes are equivalent to the ones gluUnProject should have done. For instance:

 float[] xyz = {0, 0, 0}; xyz = unproject(mouseX, viewport[3] - mouseY, 1); 

This will return the point under the mouse in the background. I also added a function to convert between the specified distance from the camera and its 0-1 ... representation ... thing. For instance:

 unproject(mouseX, viewport[3] - mouseY, distanceToDepth(5)); 

This will return the point under the mouse 5 units from the camera. I checked this using the method asked in the question - I checked the distance between the near plane and the long-range plan. With fNear 0.1 and fFar 100, the distance should be 99.9. As far as I can tell, I constantly got about 99.8977, regardless of the position or orientation of the camera. Haha, good thing that turned out. Let me know if you / don't have any problems with this, or if you want me to rewrite it to input resources instead of using global variables. Hope this helps a few people; I was curious about this for several days before seriously trying to fix it.


Hey, therefore, figuring out how it should be, I realized that they missed the implementation of gluUnProject. They forgot (not intended for anyone and didn’t tell anyone?), To divide into the fourth element of the resulting vector, which, as it were, normalizes the vector or something like that. gluProject sets it to 1 before applying matrices, so to complete them you need 1 when you cancel them. In short, you can use gluUnProject, but you need to pass it a float [4], and then divide all the resulting coordinates into a fourth, for example:

 float[] xyzw = {0, 0, 0, 0}; android.opengl.GLU.gluUnProject(rx, ry, rz, mg.mModelView, 0, mg.mProjection, 0, this.viewport, 0, xyzw, 0); xyzw[0] /= xyzw[3]; xyzw[1] /= xyzw[3]; xyzw[2] /= xyzw[3]; //xyzw[3] /= xyzw[3]; xyzw[3] = 1; return xyzw; 

xyzw should now contain the corresponding spatial coordinates. This seems to work just like the one I combined. It may be a little faster; I think they combined one of the steps.

+9
source

Source: https://habr.com/ru/post/892790/


All Articles