3d - 2d line conversions

Started by
5 comments, last by Reiken 21 years ago
I need to get an equation that will convert a 2 3dimentional positions in space into 2, 2dimentional points so I can simulate 3dimnetional perspective on a 2d screen, I''d appreciate any help. >> Reiken Cahn
Advertisement
the way things are transformed onto the screen:

raw coords in 4 component form (almost always with w as 1) - so effectivly 3 component, are multiplied by the modelview matrix, a 4x4 matrix, due to w usually being 1, it acts like a 3x3 with translation.
Then, they are multiplied by the projection matrix, another 4x4.

Finally, the output is once again, a 4 component vector. The vector is then scaled so the w component remains 1, hence the vector is divided by the w component. The resulting x and y components are screen coordinates, with correct perspective correction.

Thats the GL/D3D way, I suggest you follow that.

| - Project-X - my mega project.. getting warmer - | - adDeath - an ad blocker I made - | - email me - |
close, but no cigar;

ok, what I need to do is simulate perspective to make a 3dimentional wireframe engine. So I need to get some code that will convert the location of 2 vertices in a 3dimentional environment into 2 2dimentional vertices that can then have a line drawn between them. All I need is the equation/s for the conversion.

>> Reiken Chan
I think I can help on this one, I started 3d programming through my own 2d wireframe "engine" =)
Say you have a structure with the positions(normal x, y and z coords) of point one, and two, which you later will draw the 2d lines between.
A quick cut from my old code:
for(int loop1 = 0 ; loop1 < NRdots ; loop1++){	l1x = ((256 * dots[loop1][0].x) / dots[loop1][0].z );	l1y = ((256 * dots[loop1][0].y) / dots[loop1][0].z );	l2x = ((256 * dots[loop1][1].x) / dots[loop1][0].z );	l2y = ((256 * dots[loop1][1].y) / dots[loop1][0].z );				line(r1x , r2x , r1y , r2y , DR , DG , DB , hDC);} 

Dots is a struct with x, y and z.
Dots [0] is the first point of the line [1] is the second.
Line takes first x of the first point, then x of the second point, then y of the first point and y of the second point and draws a line with the colors specified with DR, DG and DB.
A bit old code I know =)
The 256 that I multiply the X and Y coordinates with is the factor that decides how much smaller things get in the distance.


What about this code, would this work?;
/x2 and y2 being the 2dimentional coords
/x3, y3 and z3 being the 3dimentional coords
x2 = ((x3/z3)*zoom) + (screenlen/2)
y2 = ((y3/z3)*zoom) + (screenhei/2)


This is the sort of code I am looking for.

Anyway, that''s C++ code, what library did you use to draw lines and do 2dimentional graphics?
Thanks

>> Reiken Chan
I believe Reiken wishes an even simpler version of the above method, a perspective transform done without a matrix.

It goes x2d = focus * x3d /z3d and
y2d = focus * y3d /z3d.

Focus stands for the field of view angle, the angle representing how much you take in...

\ /
\/
^focus

You should experiment to find a good focus.

x2d = focus * x / (z3d - Z_offset) + X_offfset;
y2d = focus * y / (z3d - Z_offset) + Y_offfset;

The extra values, the offsets allow zooming in and simple translation left and right.

Below is an example of the above statement. I apologize for the 16 bit assembly, this is old code written for a 486 40 mhz in Turbo C++ 3.0. It is the same as the above statement with hard coded offsets.


      void DAX_3DROOT::PerspectiveTransform(int x3d1,int y3d1,int z3d1,int &x2d1,int &y2d1){int tx2d1,ty2d1;asm{ mov bx,z3d1  		// move z3d1 into register BX : denominator add bx,0x29      // add 41 to bx  (depth) mov ax,x3d1      // move x3d1 into ax : numerator shl ax,0x08      // shift ax left 8 or multiply ax by 256  (fov) mov cx,ax        // move ax into cx. CX will be a temp or storage. mov ax,0xA0      // move 160 into ax mul bx           // multiply ax by bx    (160 * BX) mov dx,ax        // put ax somewhere... dx mov ax,cx        // put cx back in ax, (original value) add ax,dx        // add ax with dx xor dx,dx        // clear dx to zero so no divide error =) div bx           // divide it all by bx or (AX + DX / BX) mov tx2d1,ax      // put our final value in x2d1 yaaayyy... thank god xor ax,ax        /********************Clear all*******************/ xor cx,cx        //  and do it all over for y2d1 mov ax,y3d1      // move y3d1 into ax : numerator shl ax,0x08      // shift ax left 8 or multiply ax by 256  (fov) mov cx,ax        // move ax into cx. CX will be a temp or storage. mov ax,0x64      // move 100 into ax mul bx           // multiply ax by bx    (100 * BX) mov dx,ax        // put ax somewhere... dx mov ax,cx        // put cx back in ax, (original value) add ax,dx        // add ax with dx xor dx,dx        // clear dx to zero so no divide error =) div bx           // divide it all by bx or (AX + DX / BX) mov ty2d1,ax      // put our final value in y2d1 };x2d1 = tx2d1;y2d1 = ty2d1;}void DAX_3DROOT::line3D(int x3d1,int y3d1,int z3d1,int x3d2, int y3d2,int z3d2,int c){int x2d1 , y2d1, x2d2, y2d2;PerspectiveTransform(x3d1,y3d1,z3d1,x2d1,y2d1);PerspectiveTransform(x3d2,y3d2,z3d2,x2d2,y2d2);vdp->line(x2d1, y2d1, x2d2, y2d2,c);}       


Btw: This was part of a graphics library project for DOS, which did everything from plotting pixels to drawing rotating wireframe cubes


[edited by - Daerax on April 21, 2003 11:06:10 PM]
http://users.senet.com.au/~dlannan/SourceCode/qbsource.zip

Some old qbasic source of mine - 3d_obj.bas has an example of what I think you are looking for. Being in basic, its pretty simple to understand :-)

Hope this helps.

This topic is closed to new replies.

Advertisement