Hjälp med height maps i OpenGL GLUT
Jag försöker få en height map att fungera i OpenGL GLUT i ett program i C, men jag vet inte vad jag gör för fel.
Här är koden:
#include <GL/glut.h>
#include <math.h>
#include "helpers.h"
GLuint groundTexture;
int height, width;
unsigned char *imagedata;
void renderGround()
{
glPushAttrib(GL_ALL_ATTRIB_BITS);
// Your terrain should match this flat quad
glBegin(GL_POLYGON);
glNormal3f(0, 1, 0);
glTexCoord2f(0, 10);
glVertex3f(0, -0.01, 200);
glTexCoord2f(0, 0);
glVertex3f(200, -0.01, 200);
glTexCoord2f(10, 0);
glVertex3f(200, -0.01, 0);
glTexCoord2f(10, 10);
glVertex3f(0, -0.01, 0);
glEnd();
glPopAttrib();
}
void renderTerrain()
{
int row, col;
int x, y, z;
int step = 16;
int steps;
steps = step * 3;
glBegin( GL_QUADS );
for (row = 0; row < width-step; row += step)
for (col = 0; col < width-step; col += step)
{
x = row;
y = (int)imagedata[row + col*3] + (int)imagedata[row + col*3 + 1] + (int)imagedata[row + col*3 + 2];
z = col;
glVertex3i(x, y/100, x);
x = row;
y = (int)imagedata[row + (col + steps)*3] + (int)imagedata[row + (col + steps)*3+1] + (int)imagedata[row + (col + steps)*3+2];
z = col + steps;
glVertex3i(x, y/100, z);
x = row + steps;
y = (int)imagedata[row + steps + (col + steps)*3] + (int)imagedata[row + steps + (col + steps)*3+1] + (int)imagedata[row + steps + (col + steps)*3+2];
z = col + steps;
glVertex3i(x, y/100, z);
x = row + steps;
y = (int)imagedata[row + steps + (col * 3)] + (int)imagedata[row + steps + (col * 3)+1] + (int)imagedata[row + steps + (col * 3)+2];
z = col;
glVertex3i(x, y/100, z);
}
glEnd();
}
// Light and materials
GLfloat light_position[] = { 0.0, 1.0, 0.0, 0.0 }; // Directional from above
GLfloat mat_shininess[] = { 50.0 };
GLfloat mat_diffuseColor[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_specularColor[] = { 1.0, 1.0, 1.0, 1.0 };
void display()
{
// This function is called whenever it is time to render
// a new frame; due to the idle()-function below, this
// function will get called several times per second
// Clear framebuffer & zbuffer
glClearColor(0.3, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set current material
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuseColor);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specularColor);
// Place camera and light
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixd(getCameraMatrix());
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
// Render the scene!
renderGround();
renderTerrain();
// Swap front- and backbuffers
glutSwapBuffers();
}
void init()
{
int row, col;
// An ordinary texture
groundTexture = loadTexture("../textures/TropicalFoliage0025_1_S.jpg");
// A heightmap image
// imagedata = readppm("../heightmaps/44-terrain.ppm", &height, &width);
imagedata = readppm("../heightmaps/fft-terrain.ppm", &height, &width);
// Print out image contents.
// Warning! Only do this for small images or you will get incredible amounts of data!
if (width < 16)
for (row = 0; row < height; row++)
for (col = 0; col < width; col++)
{
printf("(%d, %d): R = %d, G = %d, B = %d\n", row, col, (int)imagedata[(row*width + col)*3], (int)imagedata[(row*width + col)*3+1], (int)imagedata[(row*width + col)*3+2]);
}
// Use the imagedata array for heights in the terrain!
// GL inits
glDisable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH); // Enable Gouraud shading
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, groundTexture);
}
void timer(int i)
{
glutTimerFunc(20, timer, i);
glutPostRedisplay();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
// Configure GLUT:
// - framebuffer with RGB + Alpha values per pixel
// - Z-buffer
// - two sets of above mentioned buffers, so that
// doublebuffering is possible
//
// Initial window size 800x800
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800, 800);
glutCreateWindow("Heightmap");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, 1, 0.01, 1000);
glMatrixMode(GL_MODELVIEW);
initHelperLibrary();
init();
// Register our display- and idle-functions with GLUT
glutDisplayFunc(display);
glutTimerFunc(20, timer, 0);
// Enter GLUT's main loop; this function will never return
glutMainLoop();
return 0;
}
Och här är koden som läser ppm-filer:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glut.h>
char *readppm(char *filename, int *height, int *width)
{
FILE *fd;
int k;
char c;
int i,j;
char b[100];
int red, green, blue;
long numbytes;
int n;
int m;
char *image;
fd = fopen(filename, "r");
if (fd == NULL)
{
printf("Could not open %s\n", filename);
return NULL;
}
c = getc(fd);
if (c=='P' || c=='p')
c = getc(fd);
if (c == '3')
{
printf("%s is a PPM file (plain text version)\n", filename);
// NOTE: This is not very good PPM code! Comments are not allowed
// except immediately after the magic number.
c = getc(fd);
if (c == '\n' || c == '\r') // Skip any line break and comments
{
c = getc(fd);
while(c == '#')
{
fscanf(fd, "%[^\n\r] ", b);
printf("%s\n",b);
c = getc(fd);
}
ungetc(c,fd);
}
fscanf(fd, "%d %d %d", &n, &m, &k);
printf("%d rows %d columns max value= %d\n",n,m,k);
numbytes = n * m * 3;
image = (char *) malloc(numbytes);
if (image == NULL)
{
printf("Memory allocation failed!\n");
return NULL;
}
for(i=n-1;i>=0;i--) for(j=0;j<m;j++)
{
fscanf(fd,"%d %d %d",&red, &green, &blue );
image[(i*n+j)*3]=red * 255 / k;
image[(i*n+j)*3+1]=green * 255 / k;
image[(i*n+j)*3+2]=blue * 255 / k;
}
}
else
if (c == '6')
{
printf("%s is a PPM file (raw version)!\n", filename);
c = getc(fd);
if (c == '\n' || c == '\r') // Skip any line break and comments
{
c = getc(fd);
while(c == '#')
{
fscanf(fd, "%[^\n\r] ", b);
printf("%s\n",b);
c = getc(fd);
}
ungetc(c,fd);
}
fscanf(fd, "%d %d %d", &n, &m, &k);
printf("%d rows %d columns max value= %d\n",n,m,k);
c = getc(fd); // Skip the last whitespace
numbytes = n * m * 3;
image = (char *) malloc(numbytes);
if (image == NULL)
{
printf("Memory allocation failed!\n");
return NULL;
}
// Read and re-order as necessary
for(i=n-1;i>=0;i--) for(j=0;j<m;j++)
{
image[(i*n+j)*3+0]=getc(fd);
image[(i*n+j)*3+1]=getc(fd);
image[(i*n+j)*3+2]=getc(fd);
}
}
else
{
printf("%s is not a PPM file!\n", filename);
return NULL;
}
printf("read image\n");
*height = n;
*width = m;
return image;
}