I have a Qt/ openGL application and I display 2D element on screen whose coordinates depend on a 3D object coordinates. It's ok, when I move my 3D world, my 2D element follows well.
Now, I would like to move my 2D element on Y-screen axis in order to change the Y coordinate of my 3D object in openGL. So X and Z of the 3D object don't change, only its altitude Y.
How to do that?
I tried with gluUnproject with the new 2D coordinates but this function returns new (X1,Y1,Z1), you can't tell it "I already know X and Z, give me only Y1 giving those X and Z". And if, I take the returned Y1, and use it with my X and Z, of course, it doesn't work because if I gluProject(X,Y1,Z) it doesn't give me my 2D point.
I also tried that: I have two points (X,Y,Z) of my 3D object, and (X,Y+1,Z). I use gluProject on those 2 points, which gives me (winX,winY,winZ) and (winX1,winY1,winZ1) (of course winX=winX1). I deduce deltaY=abs(winY-winY1) which is the equivalent in pixels of 1 openGL unite on Y axis between my two 3D points. It works well but only if I don't do too big rotation so it's not the good solution.
Any ideas?
Related
I saw this figure in Leland Wilkinson's book the Grammar of Graphics and was wondering how I could go about creating something similar in R.
I am suspicious this could be done using rgl, persp3d, but there's a couple aspects that are unclear to me like how to create the conformal mapping shown in the coordinates of the XY plane, as well as how to create the 2D color map in a 3D context.
Any advice would be much appreciated. Thanks!
That should be possible with rgl, but there might be some snags in the details. Here's the outline:
The green surface does not appear to have a rectangular base,
so you'll pass matrices for all of x, y and z coordinates to surface3d() to draw it.
I can't tell if the map is on a flat surface with curved edges, or if it's a curved surface. In either case, you plot the surface with a 2D texture showing the map and the contours.
a. To produce that 2D texture, use whatever mapping software you've got, and output the image to a PNG file.
b. To put it on the surface, use surface3d() with arguments texture = <filename>, texture_s = ..., texture_t = ...) where texture_s and texture_t are set to coordinates in the image (bottom left = (0,0), top right = (1,1)) corresponding to each x and y location. The z value is
either constant or varying depending on whether you want it flat
or curved.
The axes will be drawn with axis3d.
I have azimuth , elevation and direction vector of the sun.. i want to place a view point on sun ray direction with some distance. Can anyone describe or provide a link to a resource that will help me understand and implement the required steps?
I used cartesian coordinate system to find direction vector from azimuth and elevation.and then for find
viewport origin.image for this question
x = distance
y = distance* tan azimuth
z = distance * tan elevation.
i want to find that distance value... how?
azimutal coordinate system is referencing to NEH (geometric North East High(Up)) reference frame !!!
in your link to image it is referencing to -Y axis which is not true unless you are not rendering the world but doing some nonlinear graph-plot projection so which one it is?
btw here ECEF/WGS84 and NEH you can find out how to compute NEH for WGS84
As I can see you have bad computation between coordinates so just to be clear this is how it looks like:
on the left is global Earth view and one NEH computed for its position (its origin). In the middle is surface aligned side view and on the right is surface aligned top view. Blue magenta green are input azimutal coordinates, Brown are x,y,z cartesian projections (where the coordinate is on its axis) so:
Dist'= Dist *cos(Elev );
z = Dist *sin(Elev );
x = Dist'*cos(Azimut);
y =-Dist'*sin(Azimut);
if you use different reference frame or axis orientations then change it accordingly ...
I suspect you use 4x4 homogenous transform matrices
for representing coordinate systems and also to hold your view-port so look here:
transform matrix anatomy
constructing the view-port
You need X,Y,Z axis vectors and O origin position. O you already have (at least you think) and Z axis is the ray direction so you should have it too. Now just compute X,Y as alignment to something (else the view will rotate around the ray) I use NEH for that so:
view.Z=Ray.Dir // ray direction
view.Y=NEH.Z // NEH up vector
view.X=view.Y x view.Z // cross product make view.X axis perpendicular to Y ansd Z
view.Y=view.Z x view.X // just to make all three axises perpendicular to each other
view.O=ground position - (distance*Ray.Dir);
To make it a valid view_port you have to:
view = inverse(view)*projection_matrix;
You need inverse matrix computation for that
if you want the whole thing
Then you also want to add the Sun/Earth position computation in that case look here:
complete Earth-Sun position by Kepler's equation
The distance
Now that is clear what is behind you just need to set the distance if you want to set it to Sun then it will be distance=1.0 AU; (astronomical unit) but that is huge distance and if you have perspective your earth will be very small instead use some closer distance to match your view size look here:
How to position the camera so that the object always has the same size
To view my 3D environment, I use the "true" 3D isometric projection (flat square on XZ plane, Y is "always" 0). I used the explanation on wikipedia: http://en.wikipedia.org/wiki/Isometric_projection to come to how to do this transformation:
The projection matrix is an orthographic projection matrix between some minimum and maximum coordinate.
The view matrix is two rotations: one around the Y-axis (n * 45 degrees) and one around the X-axis (arctan(sin(45 degrees))).
The result looks ok, so I think I have done it correctly.
But now I want to be able to pick a coordinate with the mouse. I have successfully implemented this by rendering coordinates to an invisible framebuffer and then getting the pixel under the mouse cursor to get the coordinate. Although this works fine, I would really like to see a mathematical sollution because I will need it to calculate bounding boxes, frustums of the area on the screen and stuff like that.
My instincts tell me to:
- go from screen-coordinates to 2D projection coordinates (or how do you say this, I mean transforming screen coordinates to a coordinate between -1 and +1 for both axisses, with y inverted)
- untransform the coordinate with the inverse of the view-matrix.
- yeah... untransform this coordinate with the inverse of the projection matrix, but as my instincts tell, this won't work as everything will have the same Z-coordinate.
This, while every information is perfectly available on the isometric view (I know that the Y value is always 0). So I should be able to convert the isometric 2D x,y coordinate to a calculated 3d (x, 0, z) coordinate without using scans or something like that.
My math isn't bad, but this is something I can't seem to grasp.
Edit: IMO. every different (x, 0, z) coordinate corresponds to a different (x2, y2) coordinate in isometric view. So I should be able to simply calculate a way from (x2, y2) to (x, 0, z). But how?
Anyone?
there is something called project and unproject to transform screen to world and vice versa....
You seem to miss some core concepts here (it’s been a while since I did this stuff, so minor errors included):
There are 3 kinds of coordinates involved here (there are more, these are the relevant ones): Scene, Projection and Window
Scene (3D) are the coordinates in your world
Projection (3D) are those coordinates after being transformed by camera position and projection
Window (2D) are the coordinates in your window. They are generated from projection by scaling x and y appropriately and discarding z (z is still used for “who’s in front?” calculations)
You can not transform from window to scene with a matrix, as every point in window does correspond to a whole line in scene. If you want (x, 0, z) coordinates, you can generate this line and intersect it with the y-plane.
If you want to do this by hand, generate two points in projection with the same (x,y) and different (arbitrary) z coordinates and transform them to scene by multiplying with the inverse of your projection transformation. Now intersect the line through those two points with your y-plane and you’re done.
Note that there should be a “static” solution (a single formula) to this problem – if you solve this all on paper, you should get to it.
I'm using a Lua API. I'm trying to transform 3D space coordinates to 2D space coordinates. I've asked google but I can't find anything apart from snippets using OpenGL function. I don't need source code or anything just a simple way on how to do it? I can acquire the Camera's perspective, the original position to be transformed, window size and aspect ratio if that's any help? Thanks in advance for any suggestions :)
If you're talking about transforming world-space (x,y,z) coordinates to screen-space (u,v) coordinates, then the basic approach is:
u = x / z;
v = y / z;
If the camera is not at the origin, transform (x,y,z) by the view matrix before the projection matrix. You may also want to adjust for the camera perspective, aspect ratio etc., in which case I'd refer to this Wikipedia article.
My apologies if you're looking for something specific to the Lua API, which I am not familiar with.
For 3d projection you will need a line of field of view.
For example on a 400*400 window ;
200 will be ok.
As you can see in the given image.
Actually you can increase or decrease this 200 value according to your screen size because using wrong value can stretch your 3d model.
IMAGE
So you can use the given formula to convert your 3d points to 2d points.
Here, x or y means new x or y coordinate after perspective projection and oldx and oldy means old x and y coordinates.
x=(200÷(200+z))*(oldx);
Same formula for y also.
Y=(200÷(200+z))*(oldy);
Here is a java code example for converting 3d coordinates to 2d coordinates with depth of z axis.
// 'double[] a' indicates your 3d coordinates.eg: a=[x,y,z];
// int b indicates whether you wanted to return your 2d x coordinate or y coordinate. 0 will return x and 1 will return y.
// if your image stretches then you can adjust the fovl(field of view line).
public static double PERSPECTIVE_PROJECTION(double[] a,int b){
int fovl=200;
double oldpos=a[b];
double z=a[2];
double newpos=(double)(fovl/(fovl+z))*oldpos;
return newpos;
}
I'm trying to figure out some calculations using arcs in 3d space but am a bit lost. Lets say that I want to animate an arc in 3d space to connect 2 x,y,z coordinates (both coordinates have a z value of 0, and are just points on a plane). I'm controlling the arc by sending it a starting x,y,z position, a rotation, a velocity, and a gravity value. If I know both the x,y,z coordinates that need to be connected, is there a way to calculate what the necessary rotation, velocity, and gravity values to connect it from the starting x,y,z coordinate to the ending one?
Thanks.
EDIT: Thanks tom10. To clarify, I'm making "arcs" by creating a parabola with particles. I'm trying to figure out how to ( by starting a parabola formed by a series particles with an beginning x,y,z,velocity,rotation,and gravity) determine where it will in end(the last x,y,z coordinates). So if it if these are the two coordinates that need to be connected:
x1=240;
y1=140;
z1=0;
x2=300;
y2=200;
z2=0;
how can the rotation, velocity, and gravity of this parabola be calculated using only these variables start the formation of the parabola:
x1=240;
y1=140;
z1=0;
rotation;
velocity;
gravity;
I am trying to keep the angle a constant value.
This link describes the ballistic trajectory to "hit a target at range x and altitude y when fired from (0,0) and with initial velocity v the required angle(s) of launch θ", which is what you want, right? To get your variables into the right form, set the rotation angle (in the x-y plane) so you're pointing in the right direction, that is atan(y/x), and from then on out, to match the usual terminology for 2D problem, rewrite your z to y, and the horizontal distance to the target (which is sqrt(xx + yy)) as x, and then you can directly use the formula in link.
Do the same as you'd do in 2D. You just have to convert your figures to an affine space by rotating the axis, so one of them becomes zero; then solve and undo the rotation.