Discussion:
Drawing simple 3d shapes using lines
(too old to reply)
CG
2011-10-17 06:14:51 UTC
Permalink
How can I draw simple 3d shapes (like say a cube) using just
2d-line primitives? I am not worried about hidden surface elimination
etc or filling etc.

I just want to draw basic 3d shapes (even 1 shape like a cube is
sufficient).

Let's say I have 8 points (with x,y,z cordinates for each point) & 12
vertex definitions (formed with the eight points) how do I draw a cube
given that I have the following primitives.
- a drawpixel kind of function.
- a drawline (x1, y1, x2, y2) kind of function.

This is what I want to do
- Accept 8 points & 12 vertices (from a file).
- Draw the cube
- Accept a transformation (say rotate by 45 degrees about X axis).
- Transform the co-ordinates & draw the cube again.

I can write the code which can do the matrix multiplication transforms.
However, I am not able to figure out an easy way to draw a wireframe
kind of cube or any other 3d shape.
Nicolas Bonneel
2011-10-17 11:33:14 UTC
Permalink
Post by CG
How can I draw simple 3d shapes (like say a cube) using just
2d-line primitives? I am not worried about hidden surface elimination
etc or filling etc.
I just want to draw basic 3d shapes (even 1 shape like a cube is
sufficient).
Let's say I have 8 points (with x,y,z cordinates for each point) & 12
vertex definitions (formed with the eight points) how do I draw a cube
given that I have the following primitives.
- a drawpixel kind of function.
- a drawline (x1, y1, x2, y2) kind of function.
This is what I want to do
- Accept 8 points & 12 vertices (from a file).
- Draw the cube
- Accept a transformation (say rotate by 45 degrees about X axis).
- Transform the co-ordinates & draw the cube again.
I can write the code which can do the matrix multiplication transforms.
However, I am not able to figure out an easy way to draw a wireframe
kind of cube or any other 3d shape.
Hi,
First you need a camera model to look at your cube. To make it simple,
we are assuming that the camera is looking at the +z direction, is
placed at the origin and is a perspective camera.
Then, to obtain the (u,v) coordinate on screen of a 3d point (x,y,z),
you just have u=x/z and v=y/z. You'll finally need to scale your (u,v)
by a constant factor which depends on your field of view and screen
resolution, offset the (u,v) values to center the (0,0) in the middle of
the screen, and perhaps flipping the v axis if your (0,0) pixel is at
the top-left of your screen instead of bottom-left.
So, you might end up doing (u,v) = (k*x/z+c, -k*y/z+d), where (c,d) is
your screen center in pixels, and k a constant factor.

Finally, moving and/or turning the camera in the scene corresponds to
moving and/or turning the 3d points with the opposite camera motion. So
you can always bring your problem back to the model above (ie., a camera
pointing to the +z direction) by moving the points directly, multiplying
them by the inverse of the camera transformation matrix.

The OpenGL documentation often provides the formulas which are used in
the API. For instance, the documentation page for gluPerspective will
give you the more general projection matrix (for example, it will allow
you to find the "constant factor" I was talking about for the scaling).

Cheers
Nobody
2011-10-17 12:05:26 UTC
Permalink
Post by CG
This is what I want to do
- Accept 8 points & 12 vertices (from a file).
I presume that you mean 8 points and 12 edges.
Post by CG
- Draw the cube
- Accept a transformation (say rotate by 45 degrees about X axis).
- Transform the co-ordinates & draw the cube again.
I can write the code which can do the matrix multiplication transforms.
However, I am not able to figure out an easy way to draw a wireframe
kind of cube or any other 3d shape.
Which part are you missing?

A the simplest level, you can just transform the vertices, project from 3D
to 2D, and render each edge as a line between the transformed, projected
vertices.

However: if you use a perspective projection, you may need to clip the
edges at least to a plane in front of the viewer prior to projection, so
that you don't end up projecting points behind the viewer.
Hans-Bernhard Bröker
2011-10-17 23:56:33 UTC
Permalink
Post by CG
Let's say I have 8 points (with x,y,z cordinates for each point) & 12
vertex definitions (formed with the eight points)
That part makes no sense. 8 points form 8 vertices, or 24, but never 12.
Post by CG
I can write the code which can do the matrix multiplication transforms.
However, I am not able to figure out an easy way to draw a wireframe
kind of cube or any other 3d shape.
For a very simple start: just throw away the z coordinate and draw the
rest in 2D.
Nicolas Bonneel
2011-10-18 15:33:32 UTC
Permalink
Post by CG
Let's say I have 8 points (with x,y,z cordinates for each point) & 12
vertex definitions (formed with the eight points)
That part makes no sense. 8 points form 8 vertices, or 24, but never 12.
since he did the same mistake twice, I think he is just using the word
vertex/vertices for the word edge, and uses the word point for the word
vertex.

My boss always asks that : "how many points are there in a triangle?" =>
"an infinity!".
88888 dihedral
2011-10-19 19:53:56 UTC
Permalink
Post by CG
Let's say I have 8 points (with x,y,z cordinates for each point) & 12
vertex definitions (formed with the eight points)
That part makes no sense. 8 points form 8 vertices, or 24, but never 12.
since he did the same mistake twice, I think he is just using the word
vertex/vertices for the word edge, and uses the word point for the word
vertex.

My boss always asks that : "how many points are there in a triangle?" =>
"an infinity!".

======quoted in this thread===============================================

I think I can give some suggestions due to my experiences in 3D rendering projects for animations in 640x480 more than 10 minutes.

1. A line in 3D is mapped a line in the 2D grid points. A co-planar triangle is mapped to a triangle in the 2D grid points, too! Thus a fast line drawing routine is useful for prototypes, .i.e. the error tolerance in the color space can be sacrificed for the divisions. Of course, this is adjustable!

2. Replace the cos(x) and sin(x) in a fixed-bit length precision is useful in the matrix multiplications for the final transform of each point in a triangle. Of course, those transforms used to derive the final transform matrix can be calculated in double precisions! Don't use everything in floats!

3. The same methods can be applied to the B-spline curves in grid points!
TR Oltrogge
2011-10-19 22:01:34 UTC
Permalink
Post by CG
How can I draw simple 3d shapes (like say a cube) using just
2d-line primitives? I am not worried about hidden surface elimination
etc or filling etc.
I just want to draw basic 3d shapes (even 1 shape like a cube is
sufficient).
Let's say I have 8 points (with x,y,z cordinates for each point) & 12
vertex definitions (formed with the eight points) how do I draw a cube
given that I have the following primitives.
- a drawpixel kind of function.
- a drawline (x1, y1, x2, y2) kind of function.
This is what I want to do
- Accept 8 points & 12 vertices (from a file).
- Draw the cube
- Accept a transformation (say rotate by 45 degrees about X axis).
- Transform the co-ordinates & draw the cube again.
I can write the code which can do the matrix multiplication transforms.
However, I am not able to figure out an easy way to draw a wireframe
kind of cube or any other 3d shape.
I wanted to display 3D objects on my 2D screen, too. Thinking I would
solve the problem by using matrix multiplications to do all the
transformations was one way. But about 8 years ago I stumbled on a web
page that delighted me with its easy-to-understand (at least, for me)
use of vectors to figure out the position on the computer screen that
corresponds to a point in space as seen from a camera positioned
anywhere in space. Take a look at

http://members.tripod.com/~Paul_Kirby/vector/Vplanelineint.html

as a start. Unfortunately, the two pictures seem to have moved so they
don't show. I have them on my hard drive, though, so if you want to see
them I'll try to get them to you. While this vector method quite easily
generates a vector 'r' that, when applied at the origin, lands directly
at the point on the 2D screen that should be addressed, the conversion
of 'r' to screen coordinates is not intuitive. The author of the web
page simply says "Add a little programming and this is our pixel" and
does not solve this crucial second step! In my case I solved the "little
programming" final step by using direction cosines for converting from
one coordinate system (real 3D space) to another (screen space). Here's
my 'C' code for plotting a line in 3D space to a line on the screen's 2D
space...

//----------------------------------------------------------------------------------------------------------------
int draw_line_from_to_screen_xy(POINT *p1,POINT *p2,unsigned long color) {
/*
Given two points in 3D space, the camera position, and screen
location as a rectangular portion of a plane,
compute the computer screen coordinates and draw a straight line
between the points on the screen.
*/
float tstart,tfinish,t1,t2;
VECTOR c,a,n,b,tempv1,tempv2,rstart,rfinish;
double a11,a12,a13,a21,a22,a23,a31,a32,a33; //Direction cosines
int X_pixels,Y_pixels; //Number of pixels for each
axis of the display screen
VECTOR screen_z; //The normal to the screen
(computed from 'screen')
VECTOR v; //The position vector of our
arbitrary point on the screen in real-world basis vectors
VECTOR screen_corner; //Generated position vector
for screen's origin point in real-world basis vectors
VECTOR s; //Computed vector
'in-the-screen' from screen's origin in real-world basis vectors
VECTOR screen_coords; //Converted vector
'in-the-screen' from screen's origin in screen basis vectors
int X_pos_start,Y_pos_start; //Actual pixel position on
the screen based on screen's resolution
int X_pos_finish,Y_pos_finish; //Actual pixel position on
the screen based on screen's resolution
VECTOR real_x_axis={1.0,0.0,0.0}; //The real-world unit-length
basis vectors
VECTOR real_y_axis={0.0,1.0,0.0};
VECTOR real_z_axis={0.0,0.0,1.0};
if (SCREEN_METHOD==2) { //If calculating 'screen' from camera
direction, distance, and field of view
/*
tan(45/2) = 1/2-the-diagonal-distance /
distance-from-camera-to-screen

Therefore...

the-diagonal-distance = 2 * tan(45/2) *
distance-from-camera-to-screen [call this result D]

If the two sides of the screen are X and Y, then the aspect
ratio of the screen is X:Y, its value
is computed as X/Y, and we'll call this result R. Also, X^2 +
Y^2 = D^2 according to the Pythagorean
theorem. We can now solve for X and Y as from these two equations...

X^2 + Y^2 = D^2 [Eq 1]
X/Y = R [Eq 2]

X = R * Y [Rearrange Eq 2]
(R * Y)^2 + Y^2 = D^2 [Subst into Eq 1]
R^2 * Y^2 + Y^2 = D^2 [Mpy]
(R^2 + 1) * Y^2 = D^2 [Factor]
Y^2 = D^2 / (R^2 + 1) [Rearrange]
Y = SQRT(D^2 / (R^2 + 1) ) [Take SQRT]
X = Y * R [From Eq 2]
*/
}
/*
Since our screen is described with the 'plane_pt_2v' method we don't
have the normal to the screen as
required by the logic I found on the internet for determining the
position vector of an object's vertex
on an arbitrary screen. Generate it now by taking the cross product
of the two screen definition vectors.
*/
if (cross_product(&screen.pv1,&screen.pv2,&screen_z)) { //Generate
normal to the screen, length not crucial
fprintf(stderr,"draw_line_from_to_screen_xy: invalid screen
definition\n");
return(1); //Screen's 2 vectors are invalid (null or parallel)
}
/*
Use the logic gleaned from the internet to compute the vector 'r',
in real world coordinates, of a point lying
on the surface of a display screen. This internet logic describes
the display screen as a plane that has a
given normal vector 'n' and goes through a given real world point
'c'. The point 'c' is exactly 'screen_dist'
in front of the camera.

This internet logic does *not* compute the coordinates needed to
access the display screen. This is done in a
second step that does a coordinate transformation of the 'r' vector
from the real world basis vectors to
screen world basis vectors.
*/

//CONVERSION OF FIRST POINT TO A POSITION VECTOR THAT ENDS ON THE SCREEN
vector_1_point(p1,&a); //Establish vector 'a', the
real point imaged
vector_1_point(&camera_loc,&b); //Establish vector 'b'
n=screen_z; //Establish vector 'n' as the
screen's normal, previously calculated
vector_1_point(&screen.pp,&c); //'c' is constructed from the
point that defines the screen
vector_sub(&c,&a,&tempv1); //'c' - 'a'
t1=dot_product(&tempv1,&n); //( 'c' - 'a' ) . 'n'
vector_sub(&b,&a,&tempv2); //'b' - 'a'
/*
If the dot product of 'b'-'a' & 'n' goes to zero then either (1) the
point 'a' is at the camera
location (i.e. b=a) or (2) the screen is *essentially* parallel to
the camera direction. In either
case we want 'rstart' to equal 'a', so set tstart to 0.0.
*/
if ((t2=dot_product(&tempv2,&n))==0.0) //( 'b' - 'a' ) . 'n'
tstart=0.0;
else
tstart=t1/t2; //( ( 'c' - 'a' ) . 'n' ) / (
( 'b' - 'a' ) . 'n' ) )
vector_mpy(&tempv2,tstart); //t ( 'b' - 'a' )
vector_add(&a,&tempv2,&rstart); //'r' = 'a' + t ( 'b' - 'a' )

//CONVERSION OF SECOND POINT TO A POSITION VECTOR THAT ENDS ON THE SCREEN
vector_1_point(p2,&a); //Establish vector 'a', the
real point imaged
vector_1_point(&camera_loc,&b); //Establish vector 'b'
n=screen_z; //Establish vector 'n' as the
screen's normal, previously calculated
vector_1_point(&screen.pp,&c); //'c' is constructed from the
point that defines the screen
vector_sub(&c,&a,&tempv1); //'c' - 'a'
t1=dot_product(&tempv1,&n); //( 'c' - 'a' ) . 'n'
vector_sub(&b,&a,&tempv2); //'b' - 'a'
if ((t2=dot_product(&tempv2,&n))==0.0) //( 'b' - 'a' ) . 'n'
tfinish=0.0;
else
tfinish=t1/t2; //( ( 'c' - 'a' ) . 'n' ) / (
( 'b' - 'a' ) . 'n' ) )
vector_mpy(&tempv2,tfinish); //t ( 'b' - 'a' )
vector_add(&a,&tempv2,&rfinish); //'r' = 'a' + t ( 'b' - 'a' )

//NEW LOGIC USING DIRECTION COSINES TO CONVERT FROM REAL-WORLD BASIS
VECTORS TO SCREEN-WORLD BASIS VECTORS
/*
We now have the vectors 'rstart' and 'rfinish', which are the
position vectors in real-world coordinates to the
start and end of the line we wish to draw on the screen's plane. My
latest "direction cosines" method of
calculating the screen X and Y pixel addresses for points requires a
"plane_from_pt_2v" description of the
screen. Eventually I'd like this logic to be inside VCTRSUPPORT.h
but it's compact enough for now to be coded
right in the application. Notice there is no clipping to screen
dimensions so I am relying on X-Window to
clip for me. This should be fixed but works OK for now.
*/

//CONVERSION OF FIRST POINT'S POSITION VECTOR TO SCREEN PIXEL ADDRESS
X_pixels=image.size_hints.width; //Get the screen's width in pixels
Y_pixels=image.size_hints.height; //Get the screen's height in pixels

a11=dot_product(&real_x_axis,&screen.pv1)/vector_length(&screen.pv1);
//Compute the nine direction cosines
a12=dot_product(&real_x_axis,&screen.pv2)/vector_length(&screen.pv2);
a13=dot_product(&real_x_axis,&screen_z) /vector_length(&screen_z );
a21=dot_product(&real_y_axis,&screen.pv1)/vector_length(&screen.pv1);
a22=dot_product(&real_y_axis,&screen.pv2)/vector_length(&screen.pv2);
a23=dot_product(&real_y_axis,&screen_z) /vector_length(&screen_z );
a31=dot_product(&real_z_axis,&screen.pv1)/vector_length(&screen.pv1);
a32=dot_product(&real_z_axis,&screen.pv2)/vector_length(&screen.pv2);
a33=dot_product(&real_z_axis,&screen_z) /vector_length(&screen_z );

vector_1_point(&screen.pp,&screen_corner); //Generate
position vector for screen's corner point
vector_sub(&rstart,&screen_corner,&s); //Compute
'in-the-screen' vector to our point in real-world basis vectors
screen_coords.x = a11 * s.x + a21 * s.y + a31 * s.z; //Convert basis
to screen basis vectors
screen_coords.y = a12 * s.x + a22 * s.y + a32 * s.z;
screen_coords.z = a13 * s.x + a23 * s.y + a33 * s.z;

X_pos_start=screen_coords.x/vector_length(&screen.pv1)*(double)X_pixels;
//Compute X pixel using point's position along X-axis

Y_pos_start=screen_coords.y/vector_length(&screen.pv2)*(double)Y_pixels;
//Compute Y pixel using point's position along Y-axis

//CONVERSION OF SECOND POINT'S POSITION VECTOR TO SCREEN PIXEL ADDRESS
vector_sub(&rfinish,&screen_corner,&s); //Compute
'in-the-screen' vector to our point in real-world basis vectors
screen_coords.x = a11 * s.x + a21 * s.y + a31 * s.z; //Convert basis
to screen basis vectors
screen_coords.y = a12 * s.x + a22 * s.y + a32 * s.z;
screen_coords.z = a13 * s.x + a23 * s.y + a33 * s.z;

X_pos_finish=screen_coords.x/vector_length(&screen.pv1)*(double)X_pixels; //Compute
X pixel using point's position along X-axis

Y_pos_finish=screen_coords.y/vector_length(&screen.pv2)*(double)Y_pixels; //Compute
Y pixel using point's position along Y-axis

//DRAW THE LINE ON THE SCREEN BETWEEN THE TWO POINTS
gcval.foreground=revamp(color);
if ((stat=XChangeGC(xserv,image.gc,GCForeground,&gcval))!=1) {
printf("xscrunch: XChangeGC returned %d\n",stat);
}

XDrawLine(xserv,image.window,image.gc,X_pos_start,Y_pos_start,X_pos_finish,Y_pos_finish);

XDrawLine(xserv,image.pixmap,image.gc,X_pos_start,Y_pos_start,X_pos_finish,Y_pos_finish);
return(0);
}
//----------------------------------------------------------------------------------------------------------------
88888 Dihedral
2011-10-20 18:27:48 UTC
Permalink
As I counted in the algorithm, the numerator in t needs 3 multiplications and additions, and the denominator needs three multiplications and additions, and one division per mapped point. Then one needs 3 multiplications for t(a-b). Therefore, the operation count per point is more than 10.
TR Oltrogge
2011-10-20 21:03:35 UTC
Permalink
Post by 88888 Dihedral
As I counted in the algorithm, the numerator in t needs 3 multiplications and additions, and the denominator needs three multiplications and additions, and one division per mapped point. Then one needs 3 multiplications for t(a-b). Therefore, the operation count per point is more than 10.
I have a reasonably fast computer so the algorithm doesn't hamper me!

Years ago (late 1980s) I purchased the book "Microcomputer Displays,
Graphics, and Animation" by Bruce Artwick, the author of the first
Microsoft Flight Simulator. To get his code to run on the 80286 machines
of those days he used all sorts of optimizations and I was impressed
with his ingenuity. However, when it came time for me to code I was not
concerned with speed as much as the math principals involved. Switching
to the "vector" method of looking at 3D geometries has given me some
useful tools that simplify my analysis and, for that, I'm grateful.
Noskosteve
2011-10-21 22:26:28 UTC
Permalink
Post by CG
How can I draw simple 3d shapes (like say a cube) using just
2d-line primitives? ...
I just want to draw basic 3d shapes (even 1 shape like a cube is
sufficient).
Let's say I have 8 points (with x,y,z cordinates for each point) ...
- a drawline (x1, y1, x2, y2) kind of function. ...
Ignoring the discussion about what a vertex is...

Do a search on "Perspective Projection".
If that doesn't yield something that works for you. I have a paper
that explains things in simple terms. It is for a different type of
system (laser light show graphics which is purely vector graphics -
lines connecting points) It may take some plodding through, but it
has a little talk about perspective, I'm pretty sure it has the basics
and it also has the equations of rotations. It describes nothing in
terms of matrises or transforms.
Email me or send a note via my web site CONTACT form.-
-
73, Steve, K9DCI USN (Vet) MOT (Ret) Ham (Yet)
-- I served during the cold war, so you can continue to be served a
cold one.

http://k9dci.home.comcast.net/
88888 Dihedral
2011-10-28 11:29:12 UTC
Permalink
I am calculating the movement of a point in 3D to a camera based coordinate system with theory in motor algebra in mechanics.
Vlad Sarella
2013-03-04 07:46:21 UTC
Permalink
I was reading on astronomy one day and I've heard it mentioned that Greek astronomers knew about perspective parallax, they couldn't detect it when they looked at stars, so they figured they are glued to the sky. What surprised me is how did those silly Greeks even knew about parallax, considering (as i thought) it requires some very complex modern maths to understand and reason about perspective. The answer is that Greeks had geometry, that's the only tool they could possibly have. So i tried to model a camera just using geometry and nothing else and to my surprise the math was much simpler than i anticipated, even Greeks could handle it, if they had algebra, that is.

Let’s model a simple geometrical camera. Imagine a projection plane. A focal point F behind the plane. And finally a collection of vertices in front of the plane that will be projected on it.

To perform a projection of some vertex V, draw a line between V and focal point F. Find intersection of that line with the projection plane. The intersection point S will be the perspective projection of V. That's about it. We will return to this shortly.

View Frustum. This is optional, but is important for performance. To create a view frustum. Construct a rectangle representing your screen on the projection plane. Define the far clipping plane parallel to projection plane. The near clipping plane is just same as projection plane. Now to construct left clipping plane of frustum, draw a line from focal point to top left corner of screen rectangle and find intersection of that line with far clipping plane. Construct a plane going through three points: bottom left corner of screen rectangle, top left corner of screen rectangle and the point of intersection with far clipping plane that you’ve just found in previous step. Using similar process construct the remaining right, top and bottom clipping planes.

Each clipping plane can be used a space divisor, that separates Cartesian space into two sides. To check if a point is inside the frustum, you simply check if it’s on the “correct” side of each of the six planes. Clipping geometry can be accomplished by finding intersections of geometry edges with the frustum planes and using those points to modify edges so that they fit the frustum precisely. For simple programs that don’t perform rasterization clipping is an optional performance trick that actually may take more computing power on a wrong hardware than if you don't do it at all.

I will not talk more about frustums, that was just a theory, some additional research may be required on your part to implement those optimizations. But i will tell you how to transition from geometrical model of projection to actual numerical transformation you can use and i will do it properly without jumping to conclusions.

To transition from geometry to algebra, we will employ services of a branch of mathematics called analytic geometry, it defines equations for basic geometrical objects such as planes and lines, just what we need.

First let’s model a projection plane and focal point. For focal point we just take the origin (0,0,0). You may be tempted to rebel against my assumptions and allow your camera to move in space and so set focal point to camera position. I would advise against it, by keeping camera fixated at the origin we can simplify many of the equations. This is how it’s done in OpenGL. In OpenGL camera is always fixated, to move camera, you move entire world around it, we will follow this tradition to favor simplicity over convenience.

To represent the plane, we could use some very complicated plane equation, but because our camera is fixated at the origin and aligned to all the axises we can simply say that the projection plane is:

z = D,

where D is distance of the plane from focal point.

A little advice. Sometimes when dealing with analytical geometry, you need to think of equations as descriptions of sets of points. Such is the case with this equation of projection plane z = D. It describes an infinite set of points in Cartesian space such that their z component is equal to some fixed value D. If this was inequality z > D, it would be describing a subspace of Cartesian space such that z is larger than some fixed value. Don’t try to think of those equations as graphs, you will fail, those are not functions you can easily draw. You may know another famous equation describing a set of points, a circle equation, x*x + y*y = r.

Let’s model a line going through the focal point (0,0,0) and some vertex V. There multiple ways you can represent a line, but the most convenient for our purposes is a parametric line equation:

P = P0 + N*t

where P is a point on a line,
P0 - initial point
N - direction vector
t - parameter

Parametric equations are not sets themselves, they are ordered enumerations of sets, which means they can be easily drawn or graphed. In this case parameter t is used to select points on a line, step through them in order by changing t.

If vertex is V and focal point is just (0,0,0), then for line going through these points:
N = (0,0,0) - V = -V
P0 = V

P = V - V*t

This equation also can be expanded into coordinate form, which we will need in order to peek at individual coordinates and reason about them.

x = vx - vx*t
y = vy - vy*t
z = vz - vz*t

We can use this equation to search for intersection point with the projection plane z = D. And we do this in a very efficient manner. By asking a question. At what parameter t is z coordinate equals D. The question can be incorporated into coordinate form of parametric line equation:

x = vx - vx*t
y = vy - vy*t
D = vz - vz*t

To find the needed t parameter we simply express it through third equation, the x and y equations are ignored.

t=-(D - vz )/vz

This is the answer. We found intersection point on the projection plane. It’s almost done. Now wrapping up.

Replace parameter t into equations x and y. Leave out equation z, since we know z will be equal to D anyway after projection.

x = vx - vx*(-(D - vz )/vz)
y = vy - vy*(-(D - vz )/vz)

This simplifies to a couple incredibly slim expressions:

x = D*vx/z
y = D*vy/z

The x and y the you get are still in world coordinates, so they have to be normalized to range of -1 to 1. This can be done relative to screen rectangle width and height, not the physical screen or resolution, but the screen rectangle used for frustum. Since it’s width and height will be defined also in world coordinates you can scale x and y to -1, 1 range using those dimensions as reference. Once you do that you will have screen space coordinates.

The result is simple, but the logic to arrive to that result was not. Some people may feel like cutting corners when they see formulas like that, they try to guess them and mess abounds, by using proper methods you can be sure of validity of your results, no matter how incredible or unlikely they seem.

A good free reference on analytic geometry that i used to discover formulas
"Course of analytic geometry" by Ruslan Sharipov (English) 2011
it can be found on archive.org for free.
Hans-Bernhard Bröker
2013-03-04 23:23:41 UTC
Permalink
Post by Vlad Sarella
What surprised me is how did those silly Greeks even knew
about parallax,
Your use of "silly" in that sentence came this close to disqualifying
your entire posting.

Actually those ancient Greek natural philosophers would have to have
been very unobservant _not_ to know about parallax. Everybody with a
working pair of eyes and a minimum of curiosity about the world knows
about parallax --- even though many may never have heard the term.

It's an obivous, almost trivial everyday observation that the same scene
looks subtly different if you close one eye, and then the other, while
everything else is kept the same: that's parallax right there. Kids
figure that out before their first day in school.
Jongware
2013-03-05 13:51:50 UTC
Permalink
Post by Hans-Bernhard Bröker
Post by Vlad Sarella
What surprised me is how did those silly Greeks even knew
about parallax,
Your use of "silly" in that sentence came this close to disqualifying
your entire posting.
Actually those ancient Greek natural philosophers would have to have
been very unobservant _not_ to know about parallax. Everybody with a
working pair of eyes and a minimum of curiosity about the world knows
about parallax --- even though many may never have heard the term.
It's an obivous, almost trivial everyday observation that the same scene
looks subtly different if you close one eye, and then the other, while
everything else is kept the same: that's parallax right there. Kids
figure that out before their first day in school.
Actually, they not only *knew* about parallax, they could even cleverly
subverted it; for example, in the design of the Parthenon.

"[..] when standing in front of it, perspective does not make it appear
like the columns are slanting inward, but instead the columns appear
perfectly straight up and down, which they are not."
(http://www.reddit.com/r/ArchitecturePorn/comments/17xwrt/what_the_parthenon_wouldve_look_like_in_classical/)

(Reaction)
"That's amazing. The greeks knew their shit."


[Jw]
Vlad Sarella
2013-03-05 22:40:32 UTC
Permalink
That's exactly why i felt so dumb, when i herd of it, because i couldn't figure out how to project a point on a plane. I was seeing all those complicated explanations using linear algebra, and you know there's no way those natural philosophers knew that stuff, that's recent. So i wanted a simple explanation, here you go, there was one.
Vlad Sarella
2013-03-04 08:55:06 UTC
Permalink
correction: i said "parametric equations are not sets". They are perfectly fine sets, i was wrong. You can think of them as organized, ordered sets.
Loading...