Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Discussion / How do I turn 2D to 3D

Author
Message
Libervurto
17
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 6th Sep 2008 21:41 Edited at: 6th Sep 2008 21:41
I've been working with a very basic language that only draws 2D shapes including a very useful filled triangle.
I'm currently trying to make 3D graphics using these triangles but I'm totally stuck with the Z axis.

What I have so far is 3 major arrays, one is a vertex field where the coordinates of all the vertices are stored, the second is a polygon array which indexes the vertices that are used in each polygon (good as you can use the same vertex in multiple polygons), and the third is an object array which indexes the polygons that make up each object.

This all seems to be working fine and I can draw 2D shapes using these arrays, but my problem is displaying this 3D world. I know that the Z position of a vertex in relation to the camera distorts its X and Y coordinates on screen but I can't work out the maths.

My main aim is to make a top down game like the original GTA but to have a fully rotational world would be awesome.

can anyone help?

cheers

It is far better to complete a 10 line program than to start a 10,000 line program.
BlobVanDam
15
Years of Service
User Offline
Joined: 26th Jul 2008
Location: one of Cybertrons moons
Posted: 7th Sep 2008 11:51
So you're trying to write a basic GTA style 3D renderer in 2D using DarkBASIC? Wouldn't it be easier to actually use 3D? Then you wouldn't need to write it yourself. I'd also like to know what you're doing to write all of this vertex/poly data if it's not done through a 3D modeller!
Latch
17
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 9th Sep 2008 05:20
@OBese87
You are working with a non DB version of BASIC, or a scripting language you are making yourself?

At any rate read through my comments in this old post to start with:

http://forum.thegamecreators.com/?m=forum_view&t=110661&b=10

The basic idea is finding some imaginary distance into your monitor that the 3d world is drawn on. You can call this the view plane, for our intents and purposes I'll call it zdist# . This is the z camera distance of the 3d world where 1 3d unit = 1 screen pixel. You can find this distance based on the screen resolution and a field of view (FOV) for your camera.

In DarkBASIC, the FOV is about 62 degrees. Using right triangle math pulled from the trig equalities of SOHCAHTOA I can calculate that zdist#.

SOH = sin(theta)=opposite/hypotenuse
CAH = cos(theta)=adjacent/hypotenuse
TOA = tan(theta)=opposite/adjacent

If I stare straight into the monitor, I can form an imaginary right triangle from my eye to the center of the screen to the top or the bottom of the screen. Let's take the top of the screen. From my eye to the top of the screen and from my eye to the center of the screen an angle is formed. This is angle theta. I've decided ahead of time that I want my FOV to be 62 degrees just like DB. That means the WHOLE top to bottom of the screen to my eye would be 62 degrees. So what would be theta if my view is from the center of the screen to the top only? 31 degrees.

So what do I know? I know theta=31 and I also know the resolution of my screen (or I can find it easily enough). So, I know my resolution is set to 800x600. That means from top to bottom there are 600 pixels. But since I'm looking from the center to the top, I only need half of that. So what do I know now?

I know theta=31 degrees
I know some side of my right triangle = 300 untis. But which side? Well, a 90 degree angle forms from my eye to the center to the top. Directly across from that 90 degree angle is the sloping line from the top of the screen to my eye. This is the hypotenuse. So I know my 300 units is not the hypotenuse. Well, it just so happens that theta is formed at my eye, so the line straight into the screen is adjacent to theta and I know it's not 300 units. That leaves the side opposite of theta. So now what do I know?

theta=31 degrees
opposite=300 units

If I look at the trig equalities, I can see what I can use these to values to get. I know I want zdist, and that is the distance to the view plane straight into the monitor. We already figured out that that is the adjacent side. So our equation is

TOA = tan(theta) = opposite/adjacent

We need to juggle it around so we can solve for adjacent:

zdist# = adjacent = opposite/tan(theta)
zdist#=300/tan(31)

I gotta go for now. I'll write more if I get a chance. You use zdist# to calculate the 2d screen positions of a 3d vertex.

Enjoy your day.
Libervurto
17
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 9th Sep 2008 18:34 Edited at: 9th Sep 2008 18:49
@Latch
Thanks that is a great explanation, I'll have to read through it a couple of hundred times before I fully understand it though

@BlobVanDam
I'm not using DB for this, I'm using an old version of basic that doesn't have 3D commands. The whole point is so I can learn how 3D works. If I understand that, I'll be able to use DB much better.

PS I'm plotting the 3D data myself using arrays


Haven't tested it but that's similar to how I did it. I've only done the 2D because that's all I have working at the moment but you get the idea.

It is far better to complete a 10 line program than to start a 10,000 line program.
Latch
17
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 10th Sep 2008 15:08
Ok, onward...

Zdist is important because it is used to calculate a ratio of the x and y screen positions relative to how far away the 3d point is from the camera position. X and Y screen positions are the X and Y 3d position divided by the z span between the camera and the vertex. The larger the z span is, the smaller the 2d x and y and the closer they are together. The smaller the z span, the larger the 2d x and y will be and the further apart. Make sense?

So starting with the idea that the X and Y 2d positions are the 3d x and y divided by the z distance between the 3d vertex and the camera, the initial equation might look like this if our vertex is (x,y,z) and the camera is (camx,camy,camz)

screenx = x / (z-camz)
screeny = y / (z-camz)

It's a start, but not the whole story. We have to also account for the camera x and y as well as the vertex x and y relative to each other. The camera could be shifted up down left or right of the vertex or vice versa. So we have to look at the difference between the 3d xs and ys of the vertex and the camera. To account for these offsets, we'll just subtract one from the other. Our equations start to take better shape:

screenx = (x-camx) / (z-camz)
screeny = (y-camy) / (z-camz)

Now we're getting into it! Remeber, we're dealing with a specific screen resolution, so we have to account for where the screenx and screeny actually end up. If we treat the center of the screen as an imaginary 0,0,z, we have to find a way to position screenx and y correctly. What is the center of the screen relative to the resolution? Half of the screen width and half of the screen height. We'll call those hw and hh. So now, relative to the center of the screen, our equations start to look even more meaningful:

screenx = ((x-camx) / (z-camz)) + hw
screeny = ((y-camy) / (z-camz)) + hh

But what about all the trouble we went through to find zdist ? Now we have to understand it's importance. Remember, zdist is the imaginary distance the camera is away from the screen where 1 3d unit is equal to 1 pixel. That means there's a ratio formed between zdist# and the actual z span between the vertex and the camera (z-camz). So if the camera to the vertex z distance = zdist, then the ratio is 1 and that means the 3d X and Y values will be the exact pixel positions relative to hw,hh. The ratio looks like:

zdist/(z-camz)

Now, in terms of our main equations, we have to include this ratio:

screenx = (((x-camx)*zdist)/(z-camz))+hw
screeny = (((y-camy)*zdist)/(z-camz))+hh

The only thing is that the Y screen values run from 0 to max from the top to the bottom. In 3d, Y runs the opposite way. A simple adjustment should fix that:

screeny = hh-(((y-camy)*zdist)/(z-camz))

Enjoy your day.
Libervurto
17
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 11th Sep 2008 01:10
After pulling out my amazingly useful pocket maths book I finally cracked it!
I've made a cube, it evens rotates with some code I pulled from a demo program.
I seem to have done it a bit differently though, I don't have it here but it was something like this


Something like that, I might have made an error but that's the jist of it.
I think my AC is like your zdist but I am confused about the differences the opposite line (the one that runs parallel to the screen). I'll copy the full code out and post it tomorrow.

I can't thank you enough Latch, I knew I was lacking a bit of knowledge that was crucial to this and you steered me right to it.

PS I'm assuming when you say "my eye" you mean from the camera.

It is far better to complete a 10 line program than to start a 10,000 line program.
Satchmo
18
Years of Service
User Offline
Joined: 29th May 2005
Location:
Posted: 11th Sep 2008 01:20
Is there anyway you could post an executable? I'm interested to see what you've got.

Latch
17
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 11th Sep 2008 01:43
Quote: "PS I'm assuming when you say "my eye" you mean from the camera"


Yes and no - but no mostly. When I say from "my eye" I'm saying from a center view of the computer monitor to some imaginary distance which becomes zdist. zdist always remains the same in my method. The camera distance can change. The cameras changing distance relative to zdist is what helps calculate the screen coordinates. This allows me to change the field of view if I wish by changing the angle at which zdist is calculated or just by changing the value of zdist. The yes part is that zdist represents the camera distance at which a 3d unit is equal to a screen pixel position based on the current resolution.

In your equations:
vx= (vertexX/BC)*300 +hw
vy= (vertexY/BC)*300 +hh

I wonder if you are hard coding 300 because that was the value I used. The only reason I use 300 is because in the example, I was assuming an 800x600 screen resolution and using 300 is half the height. Using half the height in the zdist calculation helps to manage the skewing of 3d objects on screens where the width is larger than the height.

Enjoy your day.
Libervurto
17
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 11th Sep 2008 02:18
Quote: "I wonder if you are hard coding 300 because that was the value I used. The only reason I use 300 is because in the example, I was assuming an 800x600 screen resolution and using 300 is half the height. Using half the height in the zdist calculation helps to manage the skewing of 3d objects on screens where the width is larger than the height."

Ah, yes that's right, I originally put in the screen resolution and it skewed the cube, so I just stuck with 300.

Quote: "When I say from "my eye" I'm saying from a center view of the computer monitor to some imaginary distance which becomes zdist."

So is zdist the zdepth of the world?

anyway I'm sure you'll be able to see where I'm going when I post the code.

@Satchmo
I'll post it tomorrow, it's 99% the same as DB.

It is far better to complete a 10 line program than to start a 10,000 line program.
Libervurto
17
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 18th Sep 2008 01:33
Sorry about the wait, unfortunately its not working
Maybe a typo or maybe there's something that doesn't quite work in DB


A small program that works is better than a large one that doesn't.

DBC Challenge Rank: Rookie
Latch
17
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 18th Sep 2008 03:27
In your function



you calculate vpos() using references to sh and sw but neither are defined or passed to the function so their value would always be zero.

Since this function appears in other functions as well, those will not be functions as you expect either. Don't know if that's the fix, but I'm sure it's throwing the calculations off.

Enjoy your day.
Libervurto
17
Years of Service
User Offline
Joined: 30th Jun 2006
Location: On Toast
Posted: 19th Sep 2008 00:40
Thanks Latch, I've changed it to an array


It works but it doesn't seem to be recalculating the perspective because when the pyramid rotates the furthest points look skewed as they move toward the camera. I had this exact problem the first time I wrote the program but can't remember how I fixed it.

A small program that works is better than a large one that doesn't.

DBC Challenge Rank: Rookie

Login to post a reply

Server time is: 2024-05-05 03:28:07
Your offset time is: 2024-05-05 03:28:07