Two questions regarding a current project

Started by
6 comments, last by Zakwayda 18 years, 3 months ago
I've been working on a firefighter-based game in OpenGL, and I've run into a couple problems. One of them is GL-related and one isn't, so I figured I'd play it safe and post it in the general forum. 1: I'm having difficulty getting the particles for the fire effects to render properly. If I disable GL_DEPTH_TEST, then they render perfectly, except that I can see them through walls (screenshot). If I enable GL_DEPTH_TEST, then the blending doesn't work properly (screenshot). Is there any way to have both proper blending and proper depth testing? 2: The game world is tile-based, fairly large, and has to store numerous values in each Tile (fire strength, fuel, elevation, etcetera). Unfortunately, if I try and add any more information to the Tile class or make the map array any larger, then I get a stack overflow error. What would be a good workaround for this? Thanks in advance.
Advertisement
For number 2, have you tried allocating on the heap rather than the stack? Unless you have a *lot* of tiles, I doubt you'll run out of memory in this case.

For number 1, you'll probably get an answer here but would certainly get an answer in the OpenGL forum. (I'd say post just that question there, but I don't want to get you in trouble for cross-posting...) In any case, what order are you rendering in? Are you rendering all of the fire particles after rendering the level geometry (walls and so on)?
Quote:Original post by jyk
For number 2, have you tried allocating on the heap rather than the stack? Unless you have a *lot* of tiles, I doubt you'll run out of memory in this case.

For number 1, you'll probably get an answer here but would certainly get an answer in the OpenGL forum. (I'd say post just that question there, but I don't want to get you in trouble for cross-posting...) In any case, what order are you rendering in? Are you rendering all of the fire particles after rendering the level geometry (walls and so on)?


Oh boy, we're getting into areas I'm not too familiar with... how do I specify whether to allocate on the heap or the stack? And what's the difference (I used to know this)?

I'm rendering all the particles after all the tiles. Seeing as how the particles aren't associated with the tiles, I don't see how I could really do it any other way...

Thanks for the prompt reply!
Allocating on stack:
void function(){	int number;	// allocated on stack}

Allocating on heap:
void function(){	int* number_ptr = new int;	// or	int* another_number_ptr = (int*) malloc( sizeof(int) );}


The stack is basically where all the variables that are created inside a function, like example 1, reside. It also includes a bunch of information about the function, return addresses when you leave the function, etc, etc, housekeeping stuff that you probably just don't need to know or care about right now.

The heap is a section of memory that you can use when you ask the OS to allocate you some (by the way of "new" or "malloc"). When you are done with this memory, you must de-allocate it ( by the way of "delete" or "free").

The heap has much more memory for you to use than the stack.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
You don't want to disable depth testing, because that's what will cause the walls to occlude the particles. You want to disable writing to the z-buffer, so that you don't affect the existing depth information by drawing the particles. Look at glDepthMask.
You must turn on depth-test in order for fire to be occluded properly. Now, in addition you must turn off depth-write so that quads drawn behind other quads still show. That might look ok in your case, but in general, it still isn't good enough. There are three solutions:
  1. Sort the quads from farthest to closest. That way each quad will be drawn in font of the previous quads and never behind them.
  2. Use additive blending (no alpha, just make the transparent pixels black). This works because the result of addition is the same no matter what the operand order is. The nice thing about this is that fire looks good using additive blending. However, it doesn't always work well in other cases.
  3. Use alpha test. This works because transparent pixels are not drawn and therefore do not affect the depth buffer. In this case, you turn on depth-write. Unfortunately, this doesn't work well with partial transparency (when alpha values are somewhere between 0 and 1).
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
OH! That's what the heap is. I've worked with it before, just not by name.

The glDepthMask actually seems to have worked like a charm. I very much appreciate the suggestion - now I can actually get cracking on the rest of the project!
Well, almost, anyways. I know that

Particle *p;
p = new Particle[MAX_PARTICLE]

creates an array of particles, but how do you do this with a two-dimensional array? "map = new Tile[MAX_SIZE][MAX_SIZE]" generates a whole bunch of errors, top of the list being "Cannot convert from class Tile (*)[64] to class Tile *." If I change map from 'Tile *map' to 'Tile **map', then I still get that error, but the other 56 dissapear. This is shaky territory for me... I admit to not really knowing what I'm doing to much precision. All your help is appreciated.
Quote:Original post by kobuscrispi
creates an array of particles, but how do you do this with a two-dimensional array? "map = new Tile[MAX_SIZE][MAX_SIZE]" generates a whole bunch of errors...
You can create a dynamic 2d array by creating an array of pointers (to whatever kind of object the array is for, and with as many entries as there are columns/rows), and then using each one of these pointers to allocate an array of actual objects (with as many entries as there are rows/columns). When you delete, you delete the individual arrays first, and then the 'master' array of pointers.

However, that's messy and error-prone. A better option is to allocate one big 1-dimensional array:
map = new Tile[MAX_SIZE*MAX_SIZE];
And index into it using [i*MAX_SIZE+j] or something similar. To make indexing easier, you can write a function that hides the details of converting from 2d to 1d indexing.

Finally, use std::vector<> rather than new if you can:
std::vector<Tile> map(MAX_SIZE*MAX_SIZE);
Which will take care of the details of memory management, including automatic cleanup. Just ask if any of that requires clarification.

This topic is closed to new replies.

Advertisement