Java – XY position of a certain Z depth
In processing (Java dialect), there are methods screenx, screeny (and screenz, but we'll skip it now)
Suppose I have an object with XYZ = 50100500 Then, using screenx and screeny, you can now display their positions on the canvas
float x = screenX(50,500); float y = screenY(50,500);
Here is the reference: http://processing.org/reference/screenX_.html
I'm interested in the reverse method For example, I want to use the sphere to apear on the canvas with x = 175 and y = 100 The Z value of the sphere should be 700 So what is the actual X and y position at z = 700 to make it appear as 175100 on the canvas?
So the method is float unscreenx (float x, float y, float z), which returns the x value
My math / programming skills are not so advanced (let's call it bad) (I'm more like a designer) so I'm looking for some help I'm ready to ask on the processing board, but more people here have a deeper understanding of matrices
The conventional screenx method in processing can be found here: https://github.com/processing/processing/blob/master/core/src/processing/opengl/PGraphicsOpenGL.java
public float screenX(float x,float z) { return screenXImpl(x,y,z); } protected float screenXImpl(float x,float z) { float ax = modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; float ay = modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; float az = modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; float aw = modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; return screenXImpl(ax,ay,az,aw); } protected float screenXImpl(float x,float z,float w) { float ox = projection.m00*x + projection.m01*y + projection.m02*z + projection.m03*w; float ow = projection.m30*x + projection.m31*y + projection.m32*z + projection.m33*w; if (nonZero(ow)) { ox /= ow; } float sx = width * (1 + ox) / 2.0f; return sx; }
For y and for Z (I don't understand Z, but let's ignore it) I think this may provide some insights on how to reverse it
Modelview and projection are a 3D matrix. The code is here: https://github.com/processing/processing/blob/master/core/src/processing/core/PMatrix3D.java But I think this is very basic and common
I also posted on the processing board, because you never know It explains the little difference I want http://forum.processing.org/topic/unscreenx-and-unscreeny
For the label describing this article, I don't go to the specific reason. I can imagine a programmer who has never used java, but a programmer who has used C and has matrix experience can still provide a good answer
I hope someone can help
Solution
I strongly recommend that you study some linear algebra or matrix mathematics for 3D graphics It's interesting and simple, but it's a little longer than so's answer I'll try:) Disclaimer: I don't know the API you're using!
It looks like you're returning three coordinates (usually called vertices) for a position But you also mentioned a projection matrix, which has four coordinates Typically, a shader or API will take 4 coordinates for vertices 10. Y, Z, w up To display them on the screen, it does the following:
xscreen = x/w yscreen = y/w zbuffer = z/w
This is useful because you can choose W. if you just do 2D drawing, you can put w = 1 But if you're doing 3D and want some perspective, you want to divide by the distance of the camera This is the purpose of the projection matrix It mainly takes the Z of your point, where Z represents the distance from the camera and places it in W It can also expand some things, such as vision
Review the code you released, which is what the last screenximpl function does It applies a projection matrix, which basically just moves Z to W and divides by W. finally, it makes an additional scale and offsets from (- 1,1) to (0, width pixels), but we can ignore it
Now, why should I talk about these things? All you want to do is get the X and Z coordinates of the given Xscreen, yscreen and zbuffer, right? Well, the trick is to go backwards In order to do this, you need to firmly grasp the progress:)
There are two questions: 1) do you really know or care about the zbuffer value? 2) Do you know what projection matrix does? 1) Let's say we don't care There are many possible values, so we may only choose one For 2) you will have to see what it does Some projection matrices may only take (x, Z, w) and output (x, 1) That will be 2D Or (x, y, Z, 1) will be equidistant But from a perspective, it usually (x, 1, z) Add some scaling and so on
I just noticed that your second screenximpl has passed X and w to the next stage This is sometimes useful, but for all practical situations where w will be 1
At this point, I realized that I was bad at explaining things.:) You really should pick up that linear algebra book. I learned from this book: http://www.amazon.com/Elementary-Linear-Algebra-Howard-Anton But it brings a good lecture, so I don't know how useful it is
in any case! Let's become more practical Back to your code: the last function of screenximpl We now know that the input w = 1 and ow = ~ Z and ox = ~ x; The wavy line here means some scale plus some offset The screen x we have to start is ~ ox / ow (1 / 2, * width.. this means wavy line) Now let's go back to 1)... If you want a special OUNCE - now choose one Otherwise, we can choose any For rendering, it may make sense to pick anything in front of the camera and be easy to use Like 1
protected float screenXImpl(float x,float w==1) { float ox = 1*x + 0*y + 0*z + 0*w; // == x float ow = 0*x + 0*y + 1*z + 0*w; // == z == 1 ox /= ow; // == ox float sx = width * (1 + ox) / 2.0f; return sx; }
WTF? SX = width * (1n) / 2? Why don't I say that? Well, all the zeros I put there may not be zeros But it will eventually become so simple Maybe not those people I'm trying to show you the important assumptions you have to make to return Now it should be as easy as returning from SX to cattle
That's the hard part! But you still need to go from the last function to the second function I think the first and the second are easy The function is undergoing a linear matrix transformation It's good for us It needs to input four values (x, z) and (w = 1) and implicitly output four other values (ax, aw) We can figure out how to return there manually! I have to do this at school Four unknowns, four equations You know ax, aw... Solving x, Z you get w = 1 for free! Very likely and good exercise, but also very boring The good news is that these equations are written in a way called a matrix (x,1)* MODELMATRIX =(ax,aw). It's really convenient because we can find modelmatrix ^ - 1 It is called inverse! Like 1 / 2 is the reciprocal of 2 times the real number, or - 1 is the reciprocal of plus 1 You really should read it. It's interesting, not difficult. By the way:) In any case, any standard library is used to obtain the inverse of the model matrix It may be similar to modelview Inverse(). Then use it to do the same function, and then you go back Simple!
Now, why didn't we do the same thing for the project matrix before? I'm glad you asked! That one needs four inputs (x, w) and spits out only three outputs (screenx, screeny, zbufferz) So we can't solve it without making some assumptions! In an intuitive way, if you have a 3D point and you project it on a 2D screen, there will be many possible solutions So we have to choose something And we can't use the convenient matrix inverse function
If it helps, please let me know I don't think it is, but I write very happily! In addition, Google for unproject in processing gives this: http://forum.processing.org/topic/read-3d-positions-gluunproject