Drawing Terrain

Ok for my upcoming paintball game’s terrain engine I’ve ran into a problem. The problem is I read a raw image file into memory, specifically an array of unsigned chars. Now how should I go about drawing it? I wanto be able to draw it with line strips, triangle strips, and texture it depending on what mode the user selects. Thank you

No ideas? Perhaps if I ellaborate some more:

I’m loading my terrain for my game from a grayscale raw file. I want the grayscale raw file to indicate how high the corresponding spot of terrain is. For example if a pixel is completely black then the terrain at that spot will be very low. If the pixel is completely white then the terrain at that spot will be very high. So, how do I draw it?

If you are reading in a raw file, then just turn that data into vertex data.

You read in the first and second line of data to create your tiangle strips.

Then move the second line data to the fist line and read in aother line until all lines have been processed.

Originally posted by 31337:
[b]No ideas? Perhaps if I ellaborate some more:

I’m loading my terrain for my game from a grayscale raw file. I want the grayscale raw file to indicate how high the corresponding spot of terrain is. For example if a pixel is completely black then the terrain at that spot will be very low. If the pixel is completely white then the terrain at that spot will be very high. So, how do I draw it?[/b]

Ok now after I’ve debugged my reading code I’m not really getting the results I like. I don’t think its reading the raw file correctly because the array gets the same value for all the slots. But after reading your insight nexusone I think I can draw it after I get it reading correctly. Here’s what my reading code looks like (somewhat):

// dynamic file io.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <fstream.h>
#include <iostream.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
	if (FILE *inputfile = fopen("test.raw", "rb")) {
		char c;
		int howLarge = 0;
		int counter = 0;
		unsigned char *data;
		while(c = fgetc(inputfile) != EOF) {
			howLarge++;
		}
		data = new unsigned char [howLarge];
		
		fclose(inputfile);
		FILE *inputfileAGAIN = fopen("test.raw", "rb");

		while(c = fgetc(inputfileAGAIN) != EOF) {
			data[counter] = c;
			counter++;
		}
		fclose(inputfileAGAIN);
		for(int i = 0; i<howLarge; i++) {
			if(int(data[i])!=1) {
			cout << int(data[i]) << " ";
			}
		}
	}

	return 0;
}

.raw format is simply rgbrgbrgb over and over
where each value is in the range [0,255]? If thats the case, then you have to make c an unsigned char or any value you try to store in c greater than 127 will become garbage.

Also, you dont have to close and reopen the file, just fseek(inputfile,0,SEEK_SET) to return to the beginning of the file.

Old GLman

sweet! thanks a lot I’ll add in the fseek thing and try changing c to being unsigned.

I should have known that! doh!

ok I made the changes you suggested however it seems that everything still equals 1. This is not good seeing as how the raw file is an image created using the clouds filter in photoshop to produce grays throughout the picture. Any other ideas? Thanks GL Man you rock

Hey, I think its a problem with using fgetc. Do something like this instead:

if (FILE *inputfile = fopen(“test.raw”, “rb”)) {
unsigned char c;
int howLarge = 0;
int counter = 0;
unsigned char *data;

  while(c = fgetc(inputfile) != EOF) {
  	howLarge++;		
  }
  
  data = new unsigned char [howLarge];
  
  fseek(inputfile,0,SEEK_SET);
  
  fread(data,1,howLarge,inputfile);

  fclose(inputfile);
  
  for(int i = 0; i<howLarge; i++) {
  		printf("%i ",data[i]);
  }	

}
return 0;

Old GLman

wahoo that worked, but can you explain why? Thanks

Im not sure how fgetc reads from the file. fread works better though because you can read the whole thing in at once, plus you can specify how many elements to read in, and what size they are, in this case 1, or sizeof(unsigned char).

Old GLman

I think this is why, here’s an excerpt from this page:
http://ciips.ee.uwa.edu.au/~morris/Year1/CLP110/io_fun.html

But what’s the value of EOF? If we look in the ASCII code tables, we will see that all 256 possible values of an eight-bit character are assigned some meaning. Look back and note that fgetc is an int function - not a char one as we might expect! char objects can take values from 0 to 255, leaving a rather large number of choices for EOF which do not conflict with the 256 possible char values. Thus when fgetc finds an end on the input stream (as it might if it was reading a file), it returns EOF (often assigned the value -1), rather than a value in (0,255) which could be interpreted as a char.

Hmm, so I could do int c; while((c = fgetc(inputfile)>=0)

Now I’m working out drawing it. Here’s my strategy that doesn’t seem to be working:

glLoadIdentity();
glColor3f(1, 1, 1);
for(int i; i < sqrt(howLarge); i++) {
for(int j; j < sqrt(howLarge); j++) {
glVertex3f(i, float(data[i*j]/255.0), j);
}
}

Well, sqrt(howLarge) will not work because howLarge = 3 * width * height, where 3 refers to the 3 components r, g, and b. Say my image is 128 * 128. So 3128128 = 49152. sqrt(49152) = 221.7, which obviously wont work.

You should use a single channel image; ie. grayscale. It will be much easier to work with for what you want to do. If you want to do it the way your currently using you should take the r, g, and b values and average them to get a single value. Then scale it if you want, and pass it as the y component of a vertex.

EDIT: Also I just notices your not initializing i and j to 0. That could be a problem

Old GLman

[This message has been edited by Old GLman (edited 11-21-2002).]

You must also keep in mind that for doing tri-strips you want to alternate between two rows of data:


/|/|/|/|/|

So you want something like:

for (int i = 0; i < (size_y - 1); i++) {
Begin(TRI_STRIP)
for(int j = 0; j < size_x; j++) {
Vertex3i(j, data[j + i * size_x] >> SV, i);
Vertex3i(j, date[j + i * size_x + size_x] >> SV, i + 1);
End(); // TRI_STRIP
}
}

Where SV is some scale value that you find appropriate.

Remember that i and (i+1) will both be referenced in the same tristrip, so be carefull not to adress out of your data. (that is why the first loop only runs to (size_y - 1).

I hope this helps.

This is my first post, so do not be too hard on me if it does not work.

– Per B.

GL Man, I’m using a grayscale image. Does this mean that my sqrt() method will work? Per B I kindof get what your saying but right now I’m just worried about line strips.