2.5-D Doom Style Game
Luiji99

Hey guys,

I've been wondering how to create a 2.5-D game similar to DOOM 1 using OpenGL rendering, and I was hoping that I could bounce this design stuff on you guys so that you can tell me if I'm spot on or have no idea what I'm talking about.

So the main thing that I think about is how level maps would be structured. If figure it would consist of an array of rooms, in this format:

#SelectExpand
1struct room /* essentially the same thing as a sector */ 2{ 3 char name[8]; /* used so that actions can manipulate it */ 4 ALLEGRO_BITMAP *ceiling_texture, *floor_texture; /* textures */ 5 int ceiling_height, floor_height; /* heights */ 6 int first_x, first_y; /* first vertex */ 7 struct line *first_line; /* the first linedef */ 8 struct sprite *first_sprite; /* the first sprite */ 9}; 10 11enum { MAX_ROOMS = 256; } 12int room_count = 0; 13struct room rooms[MAX_ROOMS];

Then lines would be stored as this:

#SelectExpand
1struct line /* (linedef) */ 2{ 3 char name[8]; /* just like in rooms */ 4 char action[8]; /* name of the script used when this line is hit, mostly consisting of a standard set like 'TOGLDOOR" to open/close a door */ 5 6 /* texture used when the ceiling height if different from the surrounding ones, the normal middle texture and the bottom texture for the floor with a similar purpose to top_tex */ 7 ALLEGRO_BITMAP *top_texture_front, *middle_texture_front, *bottom_texture_front; 8 ALLEGRO_BITMAP *top_texture_back, *middle_texture_back, *bottom_texture_back; 9 10 int new_x, new_y; /* new vertex (lines go from previous x,y to current x,y) */ 11 12 struct line *next_line; /* the next line in the singly-linked list */ 13 14 /* i like portal rendering, so the linked_with attribute would make two lines as a portal between two rooms -- rooms do not share lines, ever -- null if it does not link */ 15 struct line *link_line; 16};

And lastly, sprites would be as simple as:

#SelectExpand
1 /* the x and y position of the sprite, relative to the world, not the room */ 2 int x, y; 3 4 /* the angle of the sprite */ 5 int angle; 6 7 /* the texture currently used to represent the sprite */ 8 ALLEGRO_BITMAP *texture; 9 10 /* the script called to update the sprite's logic (essentially indicates type, i.e. GLUEBLOB would be the name of a function that's called to make the sprite act like a glue-blob) */ 11 char update[8];

Bitmaps would be stored in the game format as names in char[8] style.

Would this work? Are the data structures efficient? Should I split linedefs into sidedefs so that each side can be scripted separately, or so that sides with the same texture information share them to reduce memory usage? Should I use short for vertices, instead of int? Is my link_line system impractical? Have I gone insane? :o

Also, how would I do collision detection? Is there a tutorial on how to do collisions between lines and bounding cylinders (I imagine cylinders are the best option for sprites, am I right?).

Thank you for any time you can spare, I know this is a very long message and I'm probably asking for more than I think I am.

- Luiji Maryo

P.S. I'm REALLY hoping that I formatted the code tags correctly. Otherwise, this may be incomprehensible.

Neil Roy

I've never done this before myself, but when I edited Doom levels back in the day, you could "peg" your wall textures to top or bottom, this basically told the game where to align the textures to. If you pegged them to the top, it aligned them to the top of the wall. So if you're wall was a door that raised up and was pegged to the bottom, the texture would move up with the door, if it was pegged to the top and a door opened up, the door would open, but the texture would remain "still", drawn from the top down.

I made a simple 3D "game" with opengl that could be edited in 2D, just used a grid and you place objects, blocks whatever onto each one.

Luiji99

I guess pegging could be implemented with just two integers for each side of the wall indicating PEG_TOP, PEG_BOTTOM or PEG_NONE. That could be pretty useful...

I think that would actually be necessary for doors, otherwise the sides of them would move up to and then there'd be no walls. Wouldn't result in a hall-of-mirrors in OpenGL, but would result in black strips, which would be kind of lame.

I should probably implement a grid-type 2.5-D game before I get too far into this line of thought. I've written a Wolfenstein 3-D-style 2.5-D raycaster before using software rendering, maybe I should try my hand at using OpenGL. But then, what culling algorithm would I use? Or maybe it's not even necessary for a game like that. You know what they say, "don't even think about optimization until it becomes truley necessary."

I'm still interested in whether or not my design would be functional, though. I would also like to note that all files would be compressed with BZip2 or something, so the sidedef compression would really only be useful after loading, not before-hand (I think).

Thanks,
- Luiji

Neil Roy

I don't see why your idea wouldn't work. You take the lines that make up the sectors, each straight line then gets made into a flat polygon. If you're using opengl than you might still have to work out optimization issues. It does feel like it would be more work to me than a fully 3D game.

As for optimization, it is actually something you should think about ahead of time. I didn't think about it at all when experimenting with 3D, I created a test 3D program with terrain, water, trees etc... it wasn't until I started to think about how to do collision detection in 3D that I realized I should have organized my data completely differently. Personally I feel that a lot of amateur 3D tutorials out there (and even ones in books) are poorly written a they don't teach anything about organizing your data.

Your 3D data for your world should be organized so you can easily check polygons for collisions and optimizations. Something like a quad tree structure so you can easily narrow down which polygons are close to the player's position, then you can check them for collisions (without checking every polygon in the game) and optimize the game for speed, and video cards aren't as fast at 3D as one might imagine. Commercial games do a lot of optimization.

I think looking into how to do things like Quad trees or whatever method you prefer should be your first thing to look into for full 3D games anyhow so you can design your game.

Even for your 2.5D game, organizing your data so you can check only the polygons close to the player and optimize for speed is important, even if you don't plan to do that stuff now when you code, you will regret it if you have a lot of code written then realize you done it wrong all along and have to redo it.

Luiji99

I've thought about collision detection optimization. I figure since I would make a oriented around small rooms, quad-trees would be excessive since I could just check for collisions between objects in the same room, though dynamic quad trees could probably be implemented after the fact (I've read up on them already, BTW). I could probably optimize out most logic in invisible rooms, too, since the player wouldn't see what's happening. Essentially I would have only scripts in the current room execute, which would be fine since scripts that effect other rooms would still exist in the current room.

For a simple Wolfenstein 2.5-D where levels are so tiny, I still don't think optimization is super-necessary. However, when I do think about possible culling techniques it becomes much harder if I do it true-Wolfenstein, due to the grid-oriented map design. Since the entire game is just a bunch of cells in one big grid, its hard to implement anything like portals, BSP or whatever else one might have in mind, since technically its just one big sector.

There are really only two primary problems I'm not sure how to solve in a DOOM-style engine, though. The first problem is collision detection between pairs of circles and circles with lines. The closest things that I can find to tutorials on it seem very complicated, and I'm trying to make sure that the tutorials are not just overcomplicating the process (I've found many that do that).

The second problem is polygon culling. I'm set with using portals, but I can't exactly figure out how they should be implemented. Linking walls seems somewhat functional, but I'm sure there's a better way to do it. My main love for portals comes from the fact that (1) you can detect if they're opened or closed with floor_height==ceiling_height and (2) if they're not within the viewing frustum, I can also ignore them. So, rendering everything should be as simple as rendering the current room, the rooms visible through portals within view, the rooms through their visible portals, etc.

I don't think a DOOM engine is any more complicated then a full-on 3-D engine. In the case of rendering, they're pretty similar. The primary limitation is the level format, which I find to be much simpler since it is 2-D. Furthermore, since collision detection can be implemented in 2-D, that should be simpler to implement, too.

I don't really know. They're might be better alternatives to portal rendering, but I don't see any as elegant.

Neil Roy
Luiji99 said:

There are really only two primary problems I'm not sure how to solve in a DOOM-style engine, though. The first problem is collision detection between pairs of circles and circles with lines. The closest things that I can find to tutorials on it seem very complicated, and I'm trying to make sure that the tutorials are not just overcomplicating the process (I've found many that do that).

One method to use is to check the radius of each circle and just check the distance from whatever is colliding with it and the radius. If the radius is less than or equal the radius of the circle, you have a collision.

At least in 2D, which in case of a Doom engine should work.

As for the rest of it, I have only really experimented so any thoughts I have on it are just that, thoughts. ;)

Luiji99

Haha, while I was away from the computer a friend of mine told me the same thing. It just seems so obvious now!

To detect a collision between two circles, simply find the distance between the two circle's center points and, if it is less than the sum of the circles' radius, then there is a collision:

#SelectExpand
1struct circle { float cx, cy, radius; } 2 3bool 4check_collide_circle_with_circle (circle1, circle2) 5 struct circle circle1, circle2; 6{ 7 float dx = circle2.cx - circle1.cx; 8 float dy = circle2.cy - circle1.cy; 9 float distance = sqrt (dx * dx + dy * dy); 10 return distance < circle1.radius + circle2.radius; 11} 12 13/* tested and functional! */

Collisions between a line and a circle would be as simple as comparing the perpendicular distance between the line and the center of the circle. If the distance is less, then there is a collision. Otherwise, there is not. However, I've been struggling to implement this method because all the information I can find on determining such a distance requires finding the constants of general form, and it seems the only way to do that is rearrange point-slope form, which I program my computer to do AFAIK.

It's driving me insane. However, at least I have half of the solution I'm looking for. It makes everything much more bearable and less scary. :)

Thanks,
- Luiji

Neil Roy

I know the feeling. I have put programming 3D games on the back burner after creating a really nice outdoor "game" (not a game, you can just wander around the terrain), with nice hills, water, trees etc... but then came collision, and all that math. My head exploded and I put my ideas of 3D programming on hold. I did do a simple collision on it, you can't collide with trees, but you do follow the hills and swim in the water by checking the height map you're walking on and adjusting your height, the water having a fixed level on the entire map and adjusting your speed and sound effects when you reach that level.

I did some nice things with it though, I wrapped the levels so that you can walk in a straight line endlessly, each side of the level matches the opposite side (like textures that you want to match seemlessly) so you can't really tell where the map ends and when you wrap around. I got the idea from Battlefield 1942. I would love to create some sort of non-violent game of exploration with a HUGE 3D world that is generated at runtime, something like how Elite game generated it's entire universe at run time, just using the same random number seed you can get the same world each time without any map data (you would have to make your own random number generator as well so it stays the same). Anyhow, I'm off on a tangent here.

If you're curious: Test3D.zip

Another game I did (again, not a game, just a world you can wander around in) was like a huge flat city map, has a skybox made with Terragen. The map editor is 2D, grid form. You place buildings, there are two heights for them, roads, grass, has a rocky cliff border. It uses 2D collision detection, just checks if you're moving onto a grid with a building. You can't fly over any buildings but it was meant to be a walking/driving game eventually with no flying so not a problem. I was thinking of adding an option to load in 3D models that fit on the square tiles, houses etc... to make it look better. As is it works like Wolfenstien, textures are applied to all sides of a cube.

If you're curious: City3D.zip

Comes with an allegro made level editor (don't click in the lower right black, area or it crashes, I'll fix it some day. ;))

Luiji99

Those sound cool, and I would totally try them out, but I've been trained pretty hard to be paranoid about everything I download. I just haven't known you long enough. =P (No offense.)

I didn't realize that I could post back here. I thought it was auto-locked for some reason. shrug Anyway, I figured out how to do circle-line collisions:

#SelectExpand
1struct circle { float cx, cy; } 2struct line { float x1, y1, x2, y2; } 3 4bool check_collide_circle_with_line (circle, line) 5 struct circle circle; 6 struct line line; 7{ 8 /* geometry relative to the center of the circle */ 9 float r = circle.radius 10 float x1 = line.x1 - circle.cx; 11 float y1 = line.y1 - circle.cy; 12 float x2 = line.x2 - circle.cx; 13 float y2 = line.y2 - circle.cy; 14 15 /* bounding-box collision is needed, because the next algorithm detects 16 collision with true lines, not just line segments */ 17 18 /* thank you allegro.cc the bounding-box algorithm */ 19 20 /* bounding box for the line */ 21 float line_x = x1 < x2 ? x1 : x2; 22 float line_y = y1 < y1 ? y1 : y2; 23 float line_w = fabs (x1 - x2); 24 float line_h = fabs (y1 - y2); 25 26 /* bounding box for the circle */ 27 float circ_x = -r; 28 float circ_y = -r; 29 float circ_w = r * 2; 30 float circ_h = r * 2; 31 32 if (line_x > circ_x + circ_w || line_y > circ_y + circ_h 33 || circ_x > line_x + line_w || circ_y > line_y + line_h) 34 return false; 35 36 /* circle-line intersection -- thank you mathworld.wolfram.com */ 37 38 float dx = x2 - x1; 39 float dy = y2 - y1; 40 float dr = sqrt (dx * dx + dy * dy); 41 42 float D = x1 * y2 - x2 * y1; 43 44 float delta = r * r * dr * dr - D * D; 45 46 return delta >= 0; 47}

Reasonably more complicated then circle-circle collision, but still relatively simple compared to some other algorithms I've seen.

So I've decided that before I get into DOOM-style games that I would like to do a Wolfenstein-type thing. I've got a plot set up, so it would be more then just a test of rendering technology. Awhile back I successfully wrote a software renderer for such graphics using a tutorial from lodev.org/cgtutor, but now I would like to use a hardware renderer.

Hardware rendering shouldn't be too complicated. I know how the system works, but I'm trying to figure out how I should do occlusion culling, or if it's even necessary for this type of game, considering the short levels and such. The basic format I have for levels is a grid where each cell is either empty, a wall or a spawning point for a sprite, so I could probably generate more complicated structures from that if I wanted (i.e. wall-based geometry instead of cell-based).

I'm going to look into how Wolfenstein for the iPhone did this all. I'm pretty sure that they did OpenGL rendering...

Thanks,
- L

========== EDIT ==========

I now realize that the reason I couldn't post is because Allegro.CC wanted me to edit my post instead of double-posting. I help administrate a forum somewhere else that has tons of problems with double-posting, I just might steal this idea. =)

Anyway, I did a quick look through the iWolf sources on GitHub and quickly discovered how simple the process was:

1. Set up a new array of boolean values of the same dimensions as the grid. Each cell indicates whether or not it is visible. Set all cells to false by default.
2. Run a raycast, but instead of rendering each vertical line that is encountered, just mark the hit cell as visible.
3. Render all of the visible cells.

It's really simple, and I can still use the raycasting technique I learned from lodev. It's pretty awesome! =D

Coming soon, USDepBEx!!!!

Thanks,
- L

Neil Roy

Well here's come screen shots of the programs just to give an idea of how they look... first the City3D editor, a 2D grid editor, easy to use...

{"name":"606246","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/a\/aaf8d1bf641ce29192e11b4de61eb19d.jpg","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/a\/aaf8d1bf641ce29192e11b4de61eb19d"}606246

And when you run the game with this level, this is what it looks like...

{"name":"606247","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/5\/858daefcdb64cf50788ae637ec9cf1b8.jpg","w":800,"h":600,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/5\/858daefcdb64cf50788ae637ec9cf1b8"}606247

Your view here is from the bottom left corner of what you see in the editor screen looking north. It looks pretty good with decent graphics and what not.

Finally this is my full 3D terrain, the water animates in it, you can walk forever in any direction. I want to make this a program that generates random worlds and keeps generating them as you move. Just an idea...

{"name":"606248","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/4\/e4eb0a58078fd22aa1199eb3226ea78d.jpg","w":960,"h":540,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/e\/4\/e4eb0a58078fd22aa1199eb3226ea78d"}606248

If you're interested in downloading them, I upload them directly to my own website, so they're definitely virus free. But I understand your apprehension.

Luiji99

Eh...I think you seem trustworthy enough for me to run it, especially since I'm hiding behind WINE anyway so it's very unlikely you'd design a virus to break out of it and I'm executing them in unique environments. =)

City3D seems to be following the same concept as I: use a grid so that map editing is easier. =) (It also makes rendering much easier when you use the right culling techniques).

I couldn't get CityMap or Test3D to run...just got "Program Encountered an Error" messages from WINE. =/ Probably just a WINE incompatibility or something.

CityMap looks pretty cool. I like the mega-block vibe it gives out. I noticed in your documentation you stated that you wanted to figure out a way to skip the polygons that are right next to each other when you have multiple buildings merged together. You could probably implement that just by skipping polygons that are adjacent to a filled cell.

Anyway, I've encountered a pretty annoying problem. The raycaster I use from lodev.org/cgtutor/raycasting.html calculates player position based on an X-Y vector. This is all well and good, and it makes the raycaster simple, but I'm having a hell of a time applying a proper glRotatef to turn the world around the player. Any idea how to convert that vector into an angle? I've tried a bunch of algorithms, my most effective one being player_direction_x*90, which allows the player to turn for awhile, but then suddenly starts turning back when (s)he should still be turning the same direction. I'll keep playing with it for now...

Thanks,
- L

==================== EDIT ====================

Ah...figured out how to do it. 90+atan2(player_direction_y,player_direction_x)*180/ALLEGRO_PI. Does the charm. =)

Also turns out that I had to flip the entire level to make it render correctly. I think OpenGL uses the "correct" mathematical coordinate system instead of the one common in computer graphics. Worked that out...

One weird thing I'm getting is that the walls sometimes flicker. I have some theories as to how to resolve that...

Lastly, the weirdest thing...it runs at the same speed as the software renderer Vandevenne wrote. WTFH? Also, the raycaster only pumps the game from 60 to 70 FPS on my ATI card. What's the point when OpenGL is the same speed?! Glarf..!

Nonetheless, I'll blog about this all tomorrow. I think I'll stick to OpenGL, though, even though it runs at the same speed. The textured version might have different implications, and I'll be able to implement looking up and down without the dreaded y-shearing technique. =D (Plus, I <3 A5!)

The glass is half full. The glass is half full. The glass is half full...

EDIT 2: Forgot to credit Lode for explaining to me that atan2 returns radians that I need to convert to degrees. =)

Neil Roy

I was going to suggest atan2(), but only because I seen it mentioned recently. I'm not the best at math.

I do have looking up and down, flying etc... in City3D... if you press Page Up and Page Down you can move up and down, I have the display of rooftops off by default.

Also, my programs aren't Allegro (*gasp*), well, the City3D map editor is Allegro 4, but not the main program. Test3D uses the old GLUT library for 3D. City3D actually doesn't use any libraries at all and is straight WinAPI programming, using some NeHe tutorials to help me along. You may want to check them out if you haven't yet, they're very nicely done and don't use libraries so they should be easy to adapt to Allegro. I actually contributed the Dev-C++ versions of the tutorials, which should load in Code::Blocks or whatever (I don't know if they have Code::Block versions as well).

http://nehe.gamedev.net

I am busy with a current 2D game, but when I am done it I want to get back into 3D again. Convert one of my 3D projects to Allegro 5 and make something out of it... or start from scratch, I need to organize my data better so it can be checked for collisions and optimized. The heavy math in these areas usually deter me from completing something, but...

Edit: Almost forgot... blast that Linux for foiling my virus distribution!! :D

Specter Phoenix

Looking good so far :). One day, when I'm 90, I'll make something like that ;).

Neil Roy

Actually, doing the 3D landscape like I did was very easy. I used a black and white terrain height map that I generated with Terragen. The lighter areas are higher, darker are lower. You just go over the map, read in each pixel colour, and set the height. On an 8bit B&W map, you get values from 0 to 255, then multiply them by some factor to set the height to what you like. I don't have proper collision in my program, but when you walk in it you follow the terrain. I simply check the terrain height where you currently are walking, and set the camera height (your point of view) to the same as the terrain.

I'm not the best at math (though I have tried learning more), so collision detection in 3D has been more of a challenge for me, but it isn't difficult to actually render the 3D. The City3D program I made is very simple, it's just a 2D grid map, any location that has a building I draw one of two textured cubes on it which are easy to do. It has collision, but 2D collision, I check the 2D map like you normally would for a 2D game.

Check out some of the 3D tutorials online.

Specter Phoenix

This is me we are talking about here :P.
Ability:
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Motivation:
|||||||||||||||||||||||||||||||
Confidence:
||

Elias

Well, if you think you have a lot of ability, it means you also have some confidence :)

Neil Roy

;D, mine was more like:

Ability:
|||||||||||||||
Motivation:
|||||||||||||||||||||||||
Confidence:
|||||

But my confidence went up as I started to see a 3D world developing before my eyes. But then it dropped off fast when I looked into organizing the data and doing 3D collision. ;)

I am kind of proud of my City3D program, mainly due to the fact that it is 100% Windows API programming, no help from libraries. I had to learn how to get the text from a bitmap, I created a function to print out text as well as all the 3D stuff and graphic mode etc... it's been quite interesting. It took me back to the days of DOS programming when I was writing my own graphic library for use in my games. I probably would have gotten a lot further if it wasn't for this blasted Allegro library. ;)

Luiji99

The Windows API is "technically" a library. If you really wanted to be library-less, you'd have to manage with pure interrupts and syscalls. =)

Neil Roy
Luiji99 said:

The Windows API is "technically" a library. If you really wanted to be library-less, you'd have to manage with pure interrupts and syscalls. =)

I used to in the good old days of DOS. I created my own library of functions for setting up graphics modes and what not. I loved that. I actually did look into Windows machine language programming, looks fun to be honest. :)

Luiji99

Heh, the age of DOS seems esoteric by today's standards, doesn't it?

Also, I am much less disheartened about the lack of a significant speed difference between Vandevenne's software renderer and my hardware renderer. Why? Well, for one, I remembered that OpenGL isn't supposed to be optimized for more than ~60FPS IIRC. More importantly, though, because at 1024x768 resolution with 256x256 wall textures, my engine runs ~6x faster. =D

Neil Roy

Nice!

Tobias Dammers
Luiji99 said:

Eh...I think you seem trustworthy enough for me to run it, especially since I'm hiding behind WINE anyway so it's very unlikely you'd design a virus to break out of it and I'm executing them in unique environments. =)

WINE does absolutely nothing to protect you. It's not an emulator, it's not a sandbox, it's not a virtual machine. WINE is just the Windows API implemented on top of a GNU/Linux system. UNIX permissions can be used to limit the damage WINE can do, but that's about it - if your UNIX user can do damage, then so can programs running in WINE.

If you want some actual protection, set up a virtual machine, and lock down its networking to NAT (if you have to connect outbound, but not act as a server), host-only (if you need to act as a server, but don't require outbound connections), a dual-NIC setup using one of each, with appropriate firewall rules, or better yet, completely disable networking if you don't need it.

Anyway.

As far as level structure goes, IIRC Doom uses a sector-based renderer, that is, every room (sector) holds pointers to adjacent sectors (per wall), and each character holds a pointer to the sector it is currently in. This information is used for two things: collision detection (if you know what sector you're in, you only have to check for wall collisions against this one sector, rather than checking against all the walls in the entire level, and if you do find a wall collision against an 'open' wall, you can use this information to update the current sector pointer of your character), and rendering (this one's a bit trickier, but what the engine does, off the top of my head, is that it starts rendering the current sector; closed walls are simply drawn, while open walls recurse into drawing the adjacent sector. This approach, if done right, avoids all overdraw except for sprites).

This approach used to be extremely efficient back in the days, when texturing and such was all done on the CPU, and the bottleneck was pumping pixels to the graphics card. With OpenGL and modern GPU's, the situation is completely different - z-buffering is free, pixel fill rate is seldom the bottleneck, and most of the rendering work is done on the GPU. Considering this, I'd just build a vertex buffer for the static part of the level, keep it on the GPU, and just render the entire level every time; doors I would probably separate out and render individually, same for sprites. Modern GPU's can easily render a kajillion polygons, once you have the vertex and texture data in GPU memory.

Luiji99

I know WINE isn't an emulator (it's actually a recursive acronym for Wine Is Not an Emulator). My original statement wasn't very clear: I mean that spyware, which 99% of the time infects Windows operating system executables in System32 and the like, will be wiped out when I delete the unique environment I set up to execute them. Furthermore, any virus that attempts to damage my user files will be sad to know that I backed them up before running Neil Roy's programs. Lastly, I analyzed the contents of my file system afterwards to find no damage or installation of previously non-existant executables (that wouldn't even be executable without WINE unless, in a very unlikely case, they knew how to spew Linux executables).

Anyway...I did know how the DOOM rendering engine functioned. I've read about it a lot because I think it's very interesting, though I wanted to avoid it in the architecture I wrote in the first post because of its complexity: it is binary-space-partitioned, requiring a binary tree of convex nodes to be constructed using a sluggish node builder that might even bug out and make the level render incorrectly. Hence, I wanted to try out Portal rendering, as it was nice and simple.

Also, GPU's are fast, but not that fast. If the level is big enough, polygon culling will become necessary. Although you're correct, the average DOOM level probably does not need polygon culling on a modern machine. iOS might need it still, though. =)

Of course there is also collision detection, which adds to the weight of non-sectored levels.

Thread #610529. Printed from Allegro.cc