PDA

View Full Version : 3D terrain generation (Animation)



umair akhtar
11-26-2009, 02:41 PM
Hello
I have to make an animation which can randomly generate a terrain then with the help of mouse one can rotate the camera to have a 3D view of it. I am able to rotate the camera, generate some lighting effects. But the problem i am facing is that since i am a beginner i am not aware of the co-ordinate system and most of the functions and their purpose like glortho(), loadIdentity(), glMatrixMode(GL_MODELVIEW), glMatrixMode(GL_PROJECTION), glperspective(), therefore i am not able to show any geometric graphics on screen as well as i m not able to change background color. I would be extremely grateful if anyone can help me out understanding glut functions and their purpose here is the code i developed:



#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <iostream>
#include "Canvas3D.h"
#include <fstream>
#include <stdlib.h> // to include functions like "rand()"
#include <math.h> // to include functions like sin, cos, exp etc.
#include <Glut.h>



float x,y;
int mousex,mousey;
float angle;
int bit=1;
int oldx=350;
int oldy=350;
Point3D heightmap[50];
Point3D basemap[50];
void myInit()
{ // *************** myInit **************
glClearColor(1.0,1.0,1.0, 0.0); // set white background color
glColor3f(2.0, 2.0, 2.0); // set the drawing color
glPointSize(1.0); // a dot will be 1 by 1 pixels
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowSize(700,700);
glutInitWindowPosition(80,80);
glutCreateWindow("Terrain Generation");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,700.0,0.0,700.0,0.0,700.0);

glMatrixMode(GL_MODELVIEW); // position and aim the camera
glLoadIdentity();
gluLookAt(1.0,1.0,2.0,0.0,0.0,0.0,0.0,1.0,0.0);
glViewport(0, 0, 700, 700);

}
void light()
{
glEnable(GL_LIGHTING); //Enable lighting

glEnable(GL_LIGHT1); //Enable light #1
glEnable(GL_NORMALIZE); //Have OpenGL automatically normalize our normals
glShadeModel(GL_SMOOTH); //Enable smooth shading

}

void display()
{
//drawing the house
//
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat lightColor1[] = {0.5f, 0.2f, 0.2f, 1.0f};
GLfloat lightPos1[] = {-1.0f, 0.5f, 0.5f, 0.0f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);

for(int i=0; i<50; i++)
{
basemap[i].y = 200.0;
heightmap[i].y= (rand()%30)*5.0;
basemap[i].x=(100+(i+1)*5.0);
heightmap[i].x=(100+(i+1)*5.0);
basemap[i].z=(100+(i+1)*5.0);
heightmap[i].z=(100+(i+1)*5.0);
}

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.0,1.0,2.0,0.0,0.0,0.0,0.0,1.0,0.0);

//if(bit=1)
//{
//glutWireTeapot(2.0);
////glutSolidSphere(0.5f,15, 8);
//glFlush();
//glutSwapBuffers();
//}
//bit=0;
//
}
void mymouse(int a,int b)
{


mousex=a;
mousey=b;
if ((mousex - oldx) > 0) // mouse moved to the right
angle += 3.0f;
else if ((mousex - oldx) < 0) // mouse moved to the left
angle -= 3.0f;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cos(3.1415*angle/180),1.0,sin(3.1415*(angle)/180),0.0,0.0,0.0,0.0,1.0,0.0);

glColor3f(2.0f,2.0f,7.0f);
glutWireTeapot(400.0);

/*glBegin(GL_TRIANGLES); //not working
glVertex3f(200.0,300.0,100.0);
glVertex3f(100.0,200.0,100.0);
glVertex3f(400.0,400.0,100.0);
glEnd();*/


glFlush();
glutSwapBuffers();

oldx=mousex;
oldy=mousey;


}

void main(int argc,char **argv)
{
glutInit(&amp;argc, argv); // initialize the toolkit
myInit();
light();
glutDisplayFunc(display); // register the redraw functions
glutMotionFunc(mymouse);
glutMainLoop();

}

marshats
11-30-2009, 07:30 PM
You are close :) You just have to be careful when you call glCommands relative to when the window is actaully created by glut. And you need to separate your display calls from calculations of the modelview/projection matrices ... I suggest reading the famous Redbook (http://www.opengl.org/documentation/red_book/). Chapter 1 has a good introduction to the GLUT library.

Some comments:
1. no need to call glFlush() since it is implicit in glutSwapBuffers().

2. All your scene drawing should be in the glut display callback ie don't draw things as the mouse moves. Instead, at the end of the mouse move, function request a display() call by issuing glutPostRedisplay()

3. You have to have a window before you start calling glCommands ... this explains why you weren't able to change the background color -- the fix is to move glClearColor etc AFTER glutCreateWindow in myInit()

4. The reason your glBegin(GL_TRIANGLES) are not being drawn is because they are outside of the viewing volume set set by both your PROJECTION_MATRIX and MODELVIEW_MATRIX. To understand this I suggest reading OpenGL Redbook, Chapter 3. (http://www.glprogramming.com/red/chapter03.html) in it entirety. And try some of its relevant samples from source code. (http://www.opengl.org/resources/code/samples/redbook/)

5. To use DEPTH it is not enough to call glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ), you also have to explicitly enable it with glEnable(GL_DEPTH_TEST) call

In the meantime, take a look at the modifications to your code to fix some of the above comments. PS I work in Linux and you didn't give the Canvas3d.h header so I had to use some "#IFDEF WINDOWS" macros to remove unnecessary OS specific code and recreate your Point3D struct-- I expect it to compile and run as is in both Linux and Windows but if you have problems you can just put the header declarations back to what you had.


#ifdef WINDOWS
#include "stdafx.h"
#include <conio.h>
#include "Canvas3D.h"
#include <Glut.h>
#endif
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <stdlib.h> // to include functions like "rand()"
#include <math.h> // to include functions like sin, cos, exp etc.


#ifndef WINDOWS
#include <GL/glut.h>
class Point3D
{
public:
float x;
float y;
float z;
};
#endif

float x;
float y;
int mousex,mousey;
float angle;
int bit=1;
int oldx=350;
int oldy=350;
Point3D heightmap[50];
Point3D basemap[50];
void myInit()
{ // *************** myInit **************
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowSize(700,700);
glutInitWindowPosition(80,80);
glutCreateWindow("Terrain Generation");
// now window exists, ok to call glCommands now
glClearColor(0.5,0.5,0.5,1.0);// set GREY background color
glColor3f(2.0, 2.0, 2.0); // set the drawing color until glColor called with new values
glPointSize(1.0); // a dot will be 1 by 1 pixels
glEnable(GL_DEPTH_TEST); // don't forget to enable depth testing, not enough to set in glutInitDisplayMode(...)
}


void light()
{
glEnable(GL_LIGHTING); //Enable lighting

glEnable(GL_LIGHT1); //Enable light #1
glEnable(GL_NORMALIZE); //Have OpenGL automatically normalize our normals
glShadeModel(GL_SMOOTH); //Enable smooth shading

}


void display()
{
//drawing the house
//
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat lightColor1[] = {0.5f, 0.2f, 0.2f, 1.0f};
GLfloat lightPos1[] = {-1.0f, 0.5f, 0.5f, 0.0f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);

for(int i=0; i<50; i++)
{
basemap[i].y = 200.0;
heightmap[i].y= (rand()%30)*5.0;
basemap[i].x=(100+(i+1)*5.0);
heightmap[i].x=(100+(i+1)*5.0);
basemap[i].z=(100+(i+1)*5.0);
heightmap[i].z=(100+(i+1)*5.0);
}

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cos(3.1415*angle/180),1.0,sin(3.1415*(angle)/180),0.0,0.0,0.0,0.0,1.0,0.0);

// ok start drawing now

//if(bit=1)
//{
//glutWireTeapot(2.0);
////glutSolidSphere(0.5f,15, 8);
//}
//bit=0;
//

glColor3f(2.0f,2.0f,7.0f);
glutSolidTeapot(200.0);

glColor3f(1.0f,1.0f,1.0f);
glPushMatrix();
glScalef(100.,100.,100.);
glTranslatef(-1,-1.,-1.);
glBegin(GL_TRIANGLES);
glVertex3f(-1.0,-1.0,0.0);
glVertex3f( 1.0,-1.0,0.0);
glVertex3f(-1.0, 1.0,0.0);
glEnd();
glPopMatrix();

glutSwapBuffers();
}


void reshape(int w, int h)
{
// Set the viewport to be the entire window
glViewport(0, 0, w, h); // use all the pixels of the window

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-350.0,350.0,-350.0,350.0,-350.0,350.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cos(3.1415*angle/180),1.0,sin(3.1415*(angle)/180),0.0,0.0,0.0,0.0,1.0,0.0);
}

void mymouse(int a,int b)
{
mousex=a;
mousey=b;
if ((mousex - oldx) > 0) // mouse moved to the right
angle += 3.0f;
else if ((mousex - oldx) < 0) // mouse moved to the left
angle -= 3.0f;

oldx=mousex;
oldy=mousey;

glutPostRedisplay();
}


int main(int argc,char **argv) //ANSI C requires integer be returned!
{
glutInit(&amp;argc, argv); // initialize the toolkit
myInit();
light();
glutDisplayFunc(display); // register the redraw functions
glutMotionFunc(mymouse);
glutReshapeFunc(reshape);
glutMainLoop();

return 0;
}