# Problems generating terrain with OpenGL

• 04-22-2007
OnionKnight
Problems generating terrain with OpenGL
I am making a simple FPS game engine for my final project in school but I am having trouble understanding why my terrain won't be drawn. It's also quite unfortunate that I was told that the project had to be finished and presented next week like three days ago. Everybody had the idea that we had at least one month to go before that so it was quite suprising, especially to me since I had barely begun my work which isn't good news when you don't know the API you're working with.

Anyways, the terrain is generated as a 3D-plot of the sums of two polynomials, fx and fy. These are also given a definition range, which will then be stretched out to match the definition range of the map.
With my test-map that I generated the x-function is
-x^4 + 2x^3 + 2x^2 - 4x + 1
and the range which the functions is defined for is -1.5 to 2.5
The y-function is
-0.05y^2 + 2
and is defined for the range -7 to 7.
Then the height for a given point is generated as simple as fx(x) + fy(y).
The definition range for the map is -50 and 50. What all that means is for example that fx(-50) would be converted into fx(-1.5) and then applied to the polynomial.

But enough talk, this is how the map looks like when I generated it in Mathematica:
http://img74.imageshack.us/img74/4410/92946098bz7.png
By iterating through -50 to 50 for the x and y and writing it to a file I found that my implementation works, and produces the same heights for a given {x, y} that Mathematica does.

Here's the code for computation, it can get a bit ugly since I've had to hack this together pretty quick.
Code:

```int world_dim[2]; /* dim = dimension, but is actually more like definition ranges */ double fxdim[2]; double fydim[2]; double* fx = NULL; /* List of coefficients for polynomial functions */ double* fy = NULL; int fxlen = 0; /* Array lengths for previous list */ int fylen = 0; double compute_height (double x, double y) {         return compute_x(x) + compute_y(y); } double compute_x (double x) {         int i;         double val = fx[0];         x = (x - world_dim[0])*(fxdim[1] - fxdim[0])/(world_dim[1] - world_dim[0]) + fxdim[0];         for (i = 1; i < fxlen; i++)                 val = val*x + fx[i];         return val; } double compute_y (double y) {         int i;         double val = fy[0];         y = (y - world_dim[0])*(fydim[1] - fydim[0])/(world_dim[1] - world_dim[0]) + fydim[0];         for (i = 1; i < fylen; i++)                 val = val*y + fy[i];         return val; }```
Since the terrain is constant, I also have a function to generate terrain into an array of heights. Each element is spaced by 1 x and y, which means the spacing of the vertices will also be 1.

Code:

```double* terrain = NULL; BOOL generate_terrain (void) {         int x, y, imax;         if (terrain != NULL)                 free(terrain);         imax = world_dim[1] - world_dim[0] + 1;         if ((terrain = malloc(sizeof(*terrain)*(imax + 1)*(imax + 1))) != NULL) {                 for (x = 0; x <= imax; x++) {                         for (y = 0; y <= imax; y++) {                                 terrain[y*imax + x] = compute_height(x + world_dim[0], y + world_dim[0]);                         }                 }                 return TRUE;         }         return FALSE; }```
Finally, I there's the function to render the world as well as a function to grab a suitable color for the height (normal height = green grass, high = snow-covered mountain, low = red lava (player dies when height < 0)).
Code:

```void render_world (void) {         double x, y;         int ix, iy, imax;         double terrain_color[3];         imax = world_dim[1] - world_dim[0] + 1;         for (x = world_dim[0], ix = 0; ix < imax; x++, ix++) {                 glBegin(GL_TRIANGLE_STRIP);                         for (y = world_dim[0], iy = 0; iy < imax; y++, iy++) {                                 get_color3dv(terrain_color, terrain[iy*imax + ix]);                                 glColor3dv(terrain_color); glVertex3d(x, terrain[iy*imax + ix], y);                                 get_color3dv(terrain_color, terrain[iy*imax + ix + 1]);                                 glColor3dv(terrain_color); glVertex3d(x + 1, terrain[iy*imax + ix + 1], y);                         }                 glEnd();         } }```
Notice that this is when it gets ugly. The world reader module assumes that x and y define the plane and z is the height. The actual OpenGL app uses the default orientation where x and z is the plane, and y is the height.
FWIW I used quads at first, but that didn't make a difference.

Now, onto the last piece of code, the render function of the app:
Code:

```GLvoid render (GLvoid) {         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         glLoadIdentity();         follow_entity(&player);         render_world();         //draw_entities(monsters, draw_monster);         render_sky();         /* Draw crosshair */         glPushMatrix();         glLoadIdentity();         glScaled((0.05*HEIGHT)/WIDTH, 0.05, 1.0);         glColor3d(0.0, 1.0, 0.0);         glLineWidth(2);         glBegin(GL_LINES);                 glVertex2d(-1.0,  0.0);                 glVertex2d(-0.2,  0.0);                 glVertex2d( 1.0,  0.0);                 glVertex2d( 0.2,  0.0);                 glVertex2d( 0.0, -1.0);                 glVertex2d( 0.0, -0.2);                 glVertex2d( 0.0,  1.0);                 glVertex2d( 0.0,  0.2);         glEnd();         glPopMatrix();         glFlush(); }```
Code:

```#define ENTITY_SIGHT 25 void follow_entity (entity* e) {         gluLookAt(e->x, e->y + 0.9*e->sy, e->z,                   e->x + ENTITY_SIGHT*sin(e->rxz*M_PI/180),                   e->y + ENTITY_SIGHT*sin(e->ryz*M_PI/180) + 0.9*e->sy,                   e->z + ENTITY_SIGHT*-cos(e->rxz*M_PI/180),                   0.0, 1.0, 0.0); }```
At the start of the game, the player has a x and z pos of 0, the rotations are 0 so the modelview matrix is the identity matrix translated a few units (-3.18, after falling a bit due to gravity) on the y-axis, so I don't think that the camera is being the problem (I should see at least something).

What happens is that not even the slightest bit of terrain is generated, no matter how i spin and turn.

EDIT: Attatching the whole project, rename it from .txt to .rar

EDIT: I commented out the skybox rendering (seems like it was in the way) and drew a red quad in front of the player at start. It seems my player movements aren't correct, though I don't know why. Somethings wrong with the gluLookAt() call though, possibly an effect of me handling angles the wrong way as well.

Code:

```GLvoid render (GLvoid) {         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         glLoadIdentity();         follow_entity(&player);         glColor3d(1.0, 0.0, 0.0);         glBegin(GL_QUADS);                 glVertex3d(-0.5, -0.5 + 3.18, -1.0);                 glVertex3d( 0.5, -0.5 + 3.18, -1.0);                 glVertex3d( 0.5,  0.5 + 3.18, -1.0);                 glVertex3d(-0.5,  0.5 + 3.18, -1.0);         glEnd();         render_world();         //draw_entities(monsters, draw_monster);         //render_sky();```
EDIT/UPDATE:
I noticed that gluLookAt() didn't have any effect on the near and far clipping places so tucked in a
glOrtho(-1.0, 1.0, -1.0, 1.0, -ENTITY_SIGHT, ENTITY_SIGHT); before the call, and there seems to be some generated terrain, placed behind the player. Still I have to do something about the camera. Matrices confuse me, and it doesn't help that I have a headache right now.
• 04-22-2007
VirtualAce
Way too complicated for simple terrain. Use a greyscale heightmap and a scaling factor.

Code:

``` fHeight=HeightMap[offset]*fScaleFactor;```
• 04-22-2007
OnionKnight
Well I guess I should've thought about that from the beginning but that won't really help me now would it?
I noticed that when I use S and X to look up and down I am able to see the terrain. It's strange as it seems like the terrain beyond some point (-1.0, relative z?) doesn't wan't to be shown; a very narrow vision. My controls seem to be faulty as well, but that shouldn't be interfering with the terrain drawing. It's mostly issues with moving in the wrong direction and spinning too fast.
The terrain is drawn, gravity works and looking at it with wireframe mode on I can see those hills from the 3D plot. The display is just very wrong.
• 04-22-2007
OnionKnight
Finally, I seem to be getting somewhere! I found this excellent link explaining how the camera and stuff works.
http://www.opengl.org/resources/faq/...al/viewing.htm

Although, it is still really screwed up. It seems a projection is quite important to have.
Updated the code to
Code:

```GLvoid render (GLvoid) {         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         glMatrixMode(GL_PROJECTION);         glLoadIdentity();         gluPerspective(90.0, (float) WIDTH/HEIGHT, -ENTITY_SIGHT, ENTITY_SIGHT);         glMatrixMode(GL_MODELVIEW);         glLoadIdentity();         follow_entity(&player);         render_sky();```
Also, about the znear and zfar, are they not relative to your position (modelview matrix)?
I tried doubling their value, but then things started disappearing. If I halve it I see slightly more. Pretty strange but I'll to deal with that later since school starts in an hour.

EDIT: Who am I kidding? Anyways, I also felt I needed to drop something else.
For some reason, I see the back of the hills (the red area, which denotes h < 0) instead of the front (which should be green). These images, taken in different rendering modes might clear things up.
http://img254.imageshack.us/img254/9519/fillwu1.png
http://img254.imageshack.us/img254/8480/linesme3.png
http://img132.imageshack.us/img132/9215/pointsxn2.png
I have a feeling that this is a pretty simple fault. Probably the depth-buffer being backwards.

If need be, there's an svn repository at svn://onionknight.no-ip.org/projekt/trunk/

EDIT: Ok, so suddenly all the problems I've adressed pretty much vanished by setting
Code:

`gluPerspective(45.0f, (GLfloat) WIDTH/HEIGHT, 0.1f, 2*ENTITY_SIGHT);`
• 04-23-2007
VirtualAce
Well I can assist you but I do not use OpenGL. However in order to help you I need to understand exactly how your terrain system works.

That screenshot does not make sense to me and I cannot tell what is going on. Perhap placing a skybox in your world will assist you and us with spatial orientation.

My terrain engine as it stands so far: I really haven't done much with it since this shot except add a sky shader.
So ask away and I'll see if I can help you. There are 2 of us here that have done a lot with terrain engines. I think Perspective is the other and I believe he implemented an LOD terrain engine. I post this screenshot for credibility so you know I'm not talking out of my arse.
• 04-23-2007
Perspective
>gluPerspective(90.0, (float) WIDTH/HEIGHT, -ENTITY_SIGHT, ENTITY_SIGHT);

The near clip should never be negative !!!!! Set it to 1 or 10.
• 04-24-2007
OnionKnight
I've seen your posts so I know you know stuff. The game works pretty good now, except that the skybox is not shown and instead a white background is placed. I'd post some screens and all that but right now I have bumped into compiler errors, and they don't make sense at all. Unfortunately I hadn't test-compiled the source for some time so I'm not exactly sure where to begin isolating code but it was after I started implementing some simple AI.
Code:

```ogl.c: In function `draw_entities': ogl.c:3: error: parameter `oglclass' is initialized ogl.c:8: error: parameter `displaymode' is initialized ogl.c:9: error: parameter `player' is initialized ogl.c:16: error: parameter `entities' is initialized ogl.c:22: error: syntax error before '{' token ogl.c:24: error: parameter `size' is initialized ogl.c:27: error: syntax error before "memset" ogl.c:63: error: storage class specified for parameter `hrc' ogl.c:64: error: storage class specified for parameter `re' ogl.c:64: error: parameter `re' is initialized ogl.c:65: error: storage class specified for parameter `square_view' ogl.c:65: error: parameter `square_view' is initialized ogl.c:66: error: storage class specified for parameter `display_fps' ogl.c:66: error: parameter `display_fps' is initialized ogl.c:67: error: storage class specified for parameter `last_tick' ogl.c:69: error: syntax error before "switch" ogl.c:76: error: parameter `pfd' is initialized ogl.c:94: error: syntax error before "if" ogl.c:163: error: parameter `size' is initialized ogl.c:163: error: redefinition of parameter 'size' ogl.c:24: error: previous definition of 'size' was here ogl.c:165: error: syntax error before "if" ogl.c:273: error: parameter `tick' is initialized ogl.c:278: error: syntax error before "sprintf" ogl.c:310: error: syntax error before "__builtin_va_start" ogl.c:326: error: syntax error before "glGetFloatv"```
"in function draw_entities:", that is cute considering how it whines about global variables being initialized which doesn't tell me anything since that's what they should be. At first I thought the was some sort of conflict somewhere, but that doesn't seem to be the case. It might be the header files clashing with each other but I can't find anything incriminating. The compiler seems to have gotten irritated after including "ogl.h" and starts yelling at the stuff following it for no reason at all.

EDIT: Oh I found that draw_entities was missing a semicolon in ogl.h. Still crazy errors since if that would happen in a source file it would just say "syntax before <next line>"

Okay so back to the skybox. I want to render it like it was a static background, no fancy 6 quad with sense of actual sky by having it scroll. The function I have right now is a bit hackish in nature since it just runs over the matrices and turns off z-buffering. I was thinking that it might be better if I just placed it very deep down on the player's vision and make some scaling corection so that the background will go from (0, 0) to (WIDTH, HEIGHT) in screen coordinates.
I don't really understand how projection matrix maps to the screen, but when I just make the modelview matrix an identity matrix and map it like the projection was orthogonal it seems that my quad who has an aspect ratio of 1:1 gets clamped down to the aspect ratio of the screen, 4:3 is that correct?

Attatching .txt-rar.
• 04-24-2007
VirtualAce
You won't be able to use a 2D quad to represent the background and have it look correct for all camera angles. Hence the need for a skybox.
• 04-26-2007
OnionKnight
I didn't want it to look correct, I was just thinking of some quick hack to make it cover up the whole screen. glScaled(0.45, 0.55, 1.0) worked out pretty good.
The original problem is resolved, and I presented my project today so this thread may die peacefully. It had some flaws but overall it turned out pretty good. Now that I don't have a blowtorch up my ass I'm gonna take my time and continue reading documentations.