I've been recently learning 3D math and such and I want to try out some of the rotation and scaling equations I've learned, but I've been having a difficult time.
I've been trying to convert my Vertex X, Y, Z coordinates to X and Y Screen Coordinates but the equation my book is telling me doesn't seem to work.
I've also made a little demo with very clear sourcecode.
Although It was made for the Game Boy Advance, the source
is very portable. So you might want to take a look at it :
http://www.gbadev.org/demos.php?showinfo=1314
the demo covers :
- basic 3D math
- 3D rotation
- Polygon filling routine
- backface culling
Jinroh at
Thanks.
Thanks for the quick reply 0xC0DE, I'll give those equations a shot.
It's nice to see another person who hangs out on GBADev and codes for the GBA, I remeber seeing your Kubus Demo. It was posted a few months after my Wolf-Pac game.
Your rotation equation looks like the one I learned so that's a good sign. I had all the rest of my math and stuff right, but
ScreenX = x * Draw_Distance / z;
ScreenY = y * Draw_Distance / z;
didn't seem to be working.
Thanks again.
Awesoken at
3D Projection.
If you want a 90 degree field of view from left to right (which is the default in most games), use this:
f = (screen_width/2) / vertex_z;
screenX = vertex_x * f + screen_width/2;
screenY = vertex_y * f + screen_height/2;
If you wish to view an object at the origin, you will need to add a small value to vertex_z in order to push the object in front of the camera.
3dEngineProgrammer at
To draw a polygon on screen do i have to project every pixel that way?
Jinroh at
Thanks Ken!
Thanks Ken, I tried both 0xC0DE's and my methods again and couldn't get it working quite right. Your's is working much better. But then again that's a given. :lol:
I've got a wireframe triangle rotating, so it seems I'm getting it.
To 3DEngineProgrammer:
You don't need project every pixel just every vertex. Then just draw lines to connect the ScreenX and ScreenY values of the vertex.
This is for a wireframe polygon, I've not done filled polys yet but the basic gist of it (as I understand it) is calculating the boundaries of the poly and filling it in with horizontal lines. Thus filling it in.
Does anybody have any recommended reading on Raster Polygons? I'm working to make a flat shaded engine, similar to the Polygonal Super Nintendo Games. I'm not setting my sights too high, I just want to make a few simple models and have them move around the screen or something. No texture mapping, Phong Shading, Gouraud Shading, just as simple as I can get. :P
Thanks again everybody!
3dEngineProgrammer at
Re: Thanks Ken!
Jinroh said
You don't need project every pixel just every vertex. Then just draw lines to connect the ScreenX and ScreenY values of the vertex.
This is for a wireframe polygon, I've not done filled polys yet but the basic gist of it (as I understand it) is calculating the boundaries of the poly and filling it in with horizontal lines. Thus filling it in.
It doesn't sound right to me,what if you want to draw a textured polygon?
I think you want to calculate every polygon's pixel color based on 2d texture projection on polygon's plane and then project this color to the screen.
How do you use zbuffer your way?
When you're drawing a line you're calculating the pixels(points) between the 2 line edges and project them on the screen.This is how draw the line works.
0xC0DE at
3dEngineProgrammer said
Jinroh said
You don't need project every pixel just every vertex. Then just draw lines to connect the ScreenX and ScreenY values of the vertex.
This is for a wireframe polygon, I've not done filled polys yet but the basic gist of it (as I understand it) is calculating the boundaries of the poly and filling it in with horizontal lines. Thus filling it in.
It doesn't sound right to me,what if you want to draw a textured polygon?
I think you want to calculate every polygon's pixel color based on 2d texture projection on polygon's plane and then project this color to the screen.
How do you use zbuffer your way?
When you're drawing a line you're calculating the pixels(points) between the 2 line edges and project them on the screen.This is how draw the line works.
polygons are always 2D shapes. here's some basic math behind it :
Here's the drawLine function, because I've seen some people using
the Bresenham's Algorithm, which would be very unneccery and slow.
/*
=================
= DrawLine
=================
*/
void DrawLine(int x1,int x2,int y,unsigned short kleur)
{
int i;
int offset = 120 * y;
for (i = x1; i < x2; i++)
v_buffer[offset + i] = kleur | kleur << 8;
}
3dEngineProgrammer at
0xC0DE said
polygons are always 2D shapes.
You mean after the projection on 2d screen space.
Where is the z coordinate?How will you do zbuffering with the above code?
0xC0DE at
3dEngineProgrammer said
0xC0DE said
polygons are always 2D shapes.
You mean after the projection on 2d screen space.
Where is the z coordinate?How will you do zbuffering with the above code?
it's always screenspace...
your model has vertex points (vectors) which hold x,y,z.
You translate the points to screenspace, and then you draw a
polygon between them.
Because you have the vertex points, you also have the z value.
A Zbuffer is nothing more then a array that stores the z value for
every pixel on screen, this can be calculated thanks to the vertex values.
Although I never really used Zbuffer myself, since I only program
for handhelds that have no 3D hardware support. And Zbuffer is
very slow in software mode and most of the time not really needed.
Most of the time you'll use sprites for objects in a game for low-end
systems (such as the Gameboy Advance or PDA). Since a sprite is flat,
all the pixels have the same depth. So you can easily sort them out.
For the map; just make sure you've got your data sorted out (BSP tree, or
other means), and you really don't need Zbuffer. 8)
3dEngineProgrammer at
3D Projection.
You mean you sort polygons according to viewer position and then render them without zbuffer?
I wonder how you calculate the right color of a pixel in screen using a textured polygon.
What i understand is that you fill the polygon on screen space.
Do you have pseudocode of how you fill a textured polygon on screenspace so i can understand how it works?
Jinroh at
Thanks 0XC0DE you're awesome. You explained that more clearly than I did.
So, yeah no Z Buffer for low end devices, thanks for that tidbit it keeps me from having to fiddle around with it and have it not work. Your the man, I was thinking I could just draw them from back to front or organize them with a BSP, but I wasn't sure if I should do either or a Z-Buffer.
I guess back to front would produce some unwanted overdraw though.
I'm working on this 3D stuff so I can port it to the GBA and play around with it there. I like coding for limited hardware. Sure I could do Mode 5/7 but where's the fun in that?
BTW: 0XC0DE, I like the way you ordered your cube's faces. I think I'll adopt that for my simple models, because writing a renderer for Triangle Fan, List, or Strip would slow me down a bit. Plus, if a Z Buffer slows down software rendering on the GBA that much, I'm sure calculating how to render the traingles would slow it down as well. lol. What video mode was that Cube Demo written in? I don't recall seeing the "adopted standard" macro anywhere I could be wrong. Just curious.
Take care guys,
Jinroh
Edited at
0xC0DE at
3dEngineProgrammer said
You mean you sort polygons according to viewer position and then render them without zbuffer?
I wonder how you calculate the right color of a pixel in screen using a textured polygon.
What i understand is that you fill the polygon on screen space.
Do you have pseudocode of how you fill a textured polygon on screenspace so i can understand how it works?
ok, although this code works fully, it's not good. But it's nice code to learn
from, since it's totally C no ASM optimized code. it consist out of 2 functions.
But again, I wouldn't recommer this for any 3D engine development.
although your ,ofcourse, free to do what ever you please with the sample code :wink:
hopefully it's helpfull :
void DrawTexturedLine(int lx,int rx,int y,int ul,int ur,int vl,int vr,unsigned int * texture,int width)
{
int x,ui,vi,swap;
int dx,du,dv;
Thanks 0XC0DE you're awesome. You explained that more clearly than I did.
So, yeah no Z Buffer for low end devices, thanks for that tidbit it keeps me from having to fiddle around with it and have it not work. Your the man, I was thinking I could just draw them from back to front or organize them with a BSP, but I wasn't sure if I should do either or a Z-Buffer.
I guess back to front would produce some unwanted overdraw though.
I'm working on this 3D stuff so I can port it to the GBA and play around with it there. I like coding for limited hardware. Sure I could do Mode 5/7 but where's the fun in that?
BTW: 0XC0DE, I like the way you ordered your cube's faces. I think I'll adopt that for my simple models, because writing a renderer for Triangle Fan, List, or Strip would slow me down a bit. Plus, if a Z Buffer slows down software rendering on the GBA that much, I'm sure calculating how to render the traingles would slow it down as well. lol. What video mode was that Cube Demo written in? I don't recall seeing the "adopted standard" macro anywhere I could be wrong. Just curious.
Take care guys,
Jinroh
the demo uses mode 4. I don't like marcos or libs. I like to keep it simple and
clean, so I use the register names themself :
about the rendering; most of the time I use some simple methods for
clipping.It depends on how much I want to render, for a few cubes backface
culling and the painters algorithm are good enough. With some extra simple
check it might be really good, now I think about it.
[edit]
wow, I suddenly have second thoughts. I forgot about other models.
For example the Utah Thea Pot. That one has multiple pieces.
I remember that there were some drawing bugs with my backface culling
for such models.
[edit2]
I've found the old demo, as you can see (although it's quite hard to
catch on a still image) some parts aren't clipping right).
before you ask; I used the "quake 2" logo because the demo
loads quake 2 models. It worked quite nicely and pretty fast for
C code only :wink:
3dEngineProgrammer at
Thanks i'll give it a try.The only problem is i am only familiar with OpenGL.I don't know how to render anything in Windows without gl.Is there any good site with low level graphics programming tutorials written in c without any assembly?
You need to put some comments in your code if you plan to work in a programming team cause you'll save a lot of time explaining things. :lol:
It's hard for another programmer to follow all this little similar variables through the code.
I wonder if Ken used zbuffering for rendering polygons.
Jinroh at
0XC0DE:
Despite the barely noticable clipping issues. Dang! That's pretty sweet having an .MD2 Teapot on the GBA like that. I wrote and .MD2 loader in DirectX (until I stopped using DX) so yeah, I understand what goes into it and right now anyway, I couldn't write a software rendered one. Wouldn't even know where to start :lol:
*Bows Out of Respect* I've got a lot of learning to do. The most hardcore true 3D thing I've done is recreate the Hologram of the Deathstar Plans from Episode IV out of pixels floating in the 3D space. They're spaced apart so they give it kinda the same effect.
3D Engine Programmer:
If you don't mind DOS Executables you can still do low-level programming in DOS with OpenWatcom it's a C/C++ Compiler that compiles to 16-Bit and 32-Bit DOS as well as Windows.
http://store.scitechsoft.com/product_info.php?products_id=37 That's the OpenWatcom Download, don't worry you don't need to donate any money.
http://www.geocities.com/siliconvalley/park/9784/links.html Steel's Programming Links has a lot of Low Level Tutorials Using DOS's Mode 13h Video Mode.
Anyway, other than Mode 13h you could start coding for the GBA if the mood struck you. It's more or less similar as far as the basics are concerned and you get the added bonus of having your code run on a handheld console!
Once you get into doing your own graphics routines and functions, you'll learn that doing them yourself is more rewarding....and easier than using an API.
CURSE YOU DIRECTX! :lol:
Anyway, thanks again guys,
Jinroh.
0xC0DE at
3dEngineProgrammer said
Thanks i'll give it a try.The only problem is i am only familiar with OpenGL.I don't know how to render anything in Windows without gl.Is there any good site with low level graphics programming tutorials written in c without any assembly?
You need to put some comments in your code if you plan to work in a programming team cause you'll save a lot of time explaining things. :lol:
It's hard for another programmer to follow all this little similar variables through the code.
I wonder if Ken used zbuffering for rendering polygons.
Well, I'm working as a prof game programming for more then 2 years now.
And we only added comments when something isn't clear from the start.
Most of the time we only add some kind of header above the function
which explains what it does. Other comments mostly get in the way of
readability.
But I can understand It's not that nice when you try to learn from the code.
Although I must admit; most of the time our teams are very small, one
or 2 persons. Since we only make handheld games.. So most of the time
nobody is looking at my code anyway except for me :)
And I've seen such functions so many times it's quite readable for me 8)
(although that shouldn't be an excuse for sloppy commenting :P)
masterlee at
I have a description of building an basic 3D-Enginge in Quick Basic avaible:
http://storm-master.dreael.ch/uploaded/program/224_30.zip
The included PDF-Shows everything you should knew.
Awesoken at
Everybody should know this?
OUT &H3D5, &HD
OUT &H3D4, &H7
OUT &H3D5, &H3E
OUT &H3D4, &H10
OUT &H3D5, &HEA
OUT &H3D4, &H11
OUT &H3D5, &HAC
OUT &H3D4, &H12
OUT &H3D5, &HDF
Sorry, but QuickBasic/Dos is no longer the best choice of language. Perhaps you could rewrite your tutorial in Evaldraw? : ) Evaldraw is missing some obvious features, but it's mature enough to handle the task.
@3dEngineProgrammer: Voxlap was my first engine to use a fullscreen Z-buffer. This was the only reasonable way to mix sprites with the world. Because the raycaster is free of overdraw, I use write-only for the Z-buffer during raycasting, which is nice. A brute-force Z-buffer would have been way too slow for Build, which had to run fast on 486's.
0xC0DE at
masterlee said
I have a description of building an basic 3D-Enginge in Quick Basic avaible:
http://storm-master.dreael.ch/uploaded/program/224_30.zip
The included PDF-Shows everything you should knew.
It's harder to read and slower then my example for gba (posted in this topic too).
Other then that, it looks nice for Qbasic.
counting_pine at
For some reason my QBASIC doesn't want to run it. It doesn't appear to like arrays in type blocks.
3dEngineProgrammer at
Awesoken said
Because the raycaster is free of overdraw, I use write-only for the Z-buffer during raycasting, which is nice.
Something i haven't cleared yet:
When you're using projection to render the screen you run on major overdraw.
When you're using raycasting you have no overdraw but what about the number of checks in cpu?Do you check every polygon with the rays starting from screen space?
Awesoken at
Your question is confusing. Voxlap does not render polygons (in the standard way), and Build does not use raycasting. In fact, I have never written a raycaster for arbitrary polygons. Obviously, checking every polygon in the world for every pixel of the screen isn't going to run fast. That's as brute-force as it gets. There are many techniques to speed it up. Sorry, I don't have time to cover it here.
3dEngineProgrammer at
Maybe i'm confusing what is raycasting.
I've read this article and maybe they should fix it:
http://en.wikipedia.org/wiki/Ray_casting#Duke_Nukem_3d
Awesoken at
Levels are designed as a series of convex polyhedral sectors
Sectors have never been restricted to being convex. Whoever wrote this has obviously never seen the Build editor. Why would someone just make this stuff up?
Rays are cast as in Wolfenstein 3d to determine texture and wall height in every column of the display,
This is so wrong it's insulting. First of all, Build can have many walls per column. Think of how a stairway works. If Build used raycasting as described here, it would have run a lot slower.
This is how Build really works: It starts by looking at the front-facing walls in the current sector. It then renders walls 1 at a time, starting with the first unoccluded wall it finds on the list. (There is always at least 1 unoccluded wall). I do hidden surface removal by remembering the highest and lowest points that have been drawn so far to each column. Ceilings and floors fill the gaps between these old high and low points and the tops and bottoms of the new wall. If a wall is a portal, I add the walls of the sector behind it to the list of walls left to consider. Rendering ends when either the wall list is empty, or all columns are filled.
Jinroh at
That's lame.
Sectors have never been restricted to being convex. Whoever wrote this has obviously never seen the Build editor. Why would someone just make this stuff up?
Wow Ken, that is lame that someone would just make up some explanation to how Build does it's thing.
Sure Build is far beyond my level of programming as I am blinded by its awesomeness. 8) But even so, I looked through the Build Source a while back because I was curious about whether a Nintendo DS port could be done effectively. Even so I understood relatively well how it rendered and did other such things. I couldn't port it I don't think, without a lot of time and effort, but I understood the basics of what it does.
But that brings up a point about Wikipedia, for being an "Encyclopedia" term used very loosely. It has some good info about some things like people that want to put a page up about their project or band or community or whatever, but for more concrete factual data it seems counterproductive that there is no real quality control. Besides the checker people that go through and delete politically charged messages from different campaign parties.
Quote:
Rays are cast as in Wolfenstein 3d to determine texture and wall height in every column of the display,
While we're on the subject of casting a ray for each screen column, I think my Raycaster is shaping up to be more mathematically correct. I did a lot of reading and trial and error kind of stuff, but found some good resources that helped me understand the raycasting process from a mathematical standpoint. That was my weakest point visualizing the math, though I am getting better. I'm getting basic 3D Math pretty well.
Anyway, I really appreciate the feedback you gave me on my raycaster a while back. If you hadn't I wouldn't really have known what the heck was wrong. So now I think it's looking better. I added some texture mapping last night so I'll have to post some screenshots of it in the next few days.
Thanks again Ken!
This is how Build really works:...
Hmm...I got some of it, it seems more ingenious and esoteric now :lol: I'll have to relook over the source. Thanks for the enlightenment Ken.
Jinroh at
NEW RAYCASTER REVEALED!
All right! Without further ado here are 3 shots of my new textured Raycaster!
Looks a heck of a lot better with corrected math and texture mapping. The great texture colors were created by me being too lazy to convert the colors to SDL's native format in my TGA loader. I think it looks trippily cool though. I'll eventually add code to convert the colors but until it gets more features it can be an Acidcaster :P
http://mypage.mtaloy.edu/~jjnst1/gapwalls.gif
In case you were curious about what it looked like before texture mapping and correct math. I'm sorry, but your eyes will heal. :lol:
http://mypage.mtaloy.edu/~jjnst1/texture.png There's the texture viewed normally.
0xC0DE at
3D Projection.
looks nice!
is this still in Qbasic ? if not, you could port it to GBA. That would be really cool :)
Jinroh at
Thanks.
Thanks for the feedback 0xC0DE I busted my brain cells since April-ish to get this far, so it's nice that I finally have something decent looking on screen. :P
You hit the nail right on the head though, I wanted to write this for the sole purpose of porting it to the GBA. It's written in straight C with SDL as it's Graphics Library, but I wrote it how I would for DOS Mode 13h so it's ripe for porting to the GBA since they use similar pixel plotting techniques.
I just finished porting the image loader for the textures to the GBA this morning thanks to the Drunken Coder's PCX example so the textures are loaded in and their colors are all correctly converted. Which is great, so we won't have to look at Purple and Gold textures for long :P
The image loader was the biggest hurdle for me since I had no idea how to use the assembler to include an image file in the ROM image. But now, that it seems to be out of the way the rest, sans optimization, should fall into place rather well. *Knocks on Wood*
The hardest part though, will probably be the sprites. I'm terrible with anything but Raster Sprites on the GBA.
I wrote a sprite class that uses OAM and it works fine for:
1. Sprites that are only one frame.
2. Sprites that are in Modes 0-2
But if I have a sprite sheet that I load in, all OAM memory has the first sprite in the sheet. I'll have to check over it again, but it seems like it should work. I could be crazy though.
Anyway, sorry for the uber long post. And thanks for the feedback.
0xC0DE at
Re: Thanks.
Jinroh said
Thanks for the feedback 0xC0DE I busted my brain cells since April-ish to get this far, so it's nice that I finally have something decent looking on screen. :P
You hit the nail right on the head though, I wanted to write this for the sole purpose of porting it to the GBA. It's written in straight C with SDL as it's Graphics Library, but I wrote it how I would for DOS Mode 13h so it's ripe for porting to the GBA since they use similar pixel plotting techniques.
I just finished porting the image loader for the textures to the GBA this morning thanks to the Drunken Coder's PCX example so the textures are loaded in and their colors are all correctly converted. Which is great, so we won't have to look at Purple and Gold textures for long :P
The image loader was the biggest hurdle for me since I had no idea how to use the assembler to include an image file in the ROM image. But now, that it seems to be out of the way the rest, sans optimization, should fall into place rather well. *Knocks on Wood*
An image loader, although very cool that you could make one, doesn
Jinroh at
Right on.
An image loader, although very cool that you could make one, doesn