infinite terrain experiments
[shady.git] / world.cpp
blobcd254137b2af12d10dcecf6a4f32bae1d454f818
2 #include "world.hpp"
3 #include "transform.hpp"
4 #include "terrain.hpp"
5 #include "output.hpp"
6 #include "renderer.hpp" // for checkGl
8 extern "C" {
9 #include <GL/glew.h>
10 #include <GL/gl.h>
11 #include <GL/glu.h>
14 #include <cstdlib>
15 using std::rand;
18 class World::_Private {
20 friend class World;
22 _Private() : trrn(512, 64, 9), dlist(GL_NONE), vbo(GL_NONE) {
25 ~_Private() {
26 if(dlist) {
27 glDeleteLists(dlist, 1);
29 if(vbo) {
30 glDeleteBuffers(1, &vbo);
34 terrain trrn;
36 // OpenGL display list containing the world
37 GLuint dlist;
39 GLuint vbo;
41 // Transformation from model space to light space.
42 transform lightPos;
46 World::World() : _p(new World::_Private()) {
49 World::~World() {
50 delete _p;
53 #ifdef DRAW_NORMALS
54 static void drawNormals(const vec * p, int n, const vec & normal) {
55 vec nn = normal / 5;
56 for(int i = 0; i < n; i++) {
57 glBegin(GL_LINES);
58 glVertex3f(p[i].x, p[i].y, p[i].z);
59 glVertex3f(p[i].x + nn.x, p[i].y + nn.y, p[i].z + nn.z);
60 glEnd();
63 #else
64 #define drawNormals(p,n,normal)
65 #endif
67 static void drawTrinagle(const vec p[3]) {
69 vec n = calculateTriangleNormal(p);
70 glNormal3f(n.x, n.y, n.z);
72 glBegin(GL_TRIANGLES);
73 for(int i = 0; i < 3; i++) {
74 glVertex3f(p[i].x, p[i].y, p[i].z);
76 glEnd();
78 drawNormals(p, 3, n);
82 static void drawQuad(const vec p[4]) {
84 vec n = calculateNormal(p, 4);
85 glNormal3f(n.x, n.y, n.z);
87 glBegin(GL_QUADS);
88 for(int i = 0; i < 4; i++) {
89 glVertex3f(p[i].x, p[i].y, p[i].z);
91 glEnd();
93 drawNormals(p, 4, n);
97 static void drawQuads(const vec p[][4], int n) {
98 for(int i = 0; i < n; i++) {
99 drawQuad(p[i]);
103 static void drawTrinagles(const vec p[][3], int n) {
104 for(int i = 0; i < n; i++) {
105 drawTrinagle(p[i]);
109 static const float w = 0.1; // width of objects (height=1.0)
110 static float p = sqrt(2 * w * w);
112 static void drawCuboid() {
114 vec quads[6][4] = {
116 // side faces
118 vec(w, 0, w),
119 vec(w, 0, -w),
120 vec(w, 1, -w),
121 vec(w, 1, w)
122 }, {
123 vec(w, 1, w),
124 vec(-w, 1, w),
125 vec(-w, 0, w),
126 vec(w, 0, w)
127 }, {
128 vec(-w, 1, w),
129 vec(-w, 1, -w),
130 vec(-w, 0, -w),
131 vec(-w, 0, w)
132 }, {
133 vec(w, 0, -w),
134 vec(-w, 0, -w),
135 vec(-w, 1, -w),
136 vec(w, 1, -w)
139 // top/bottom face
141 vec(w, 1, w),
142 vec(w, 1, -w),
143 vec(-w, 1, -w),
144 vec(-w, 1, w)
145 }, {
146 vec(w, 0, w),
147 vec(-w, 0, w),
148 vec(-w, 0, -w),
149 vec(w, 0, -w)
154 drawQuads(quads, 5);
157 static void drawSquarePyramid() {
159 vec triangles[5][3] = {
162 vec(w, 0, w),
163 vec(w, 0, -w),
164 vec(0, 1, 0)
165 }, {
166 vec(0, 1, 0),
167 vec(-w, 0, w),
168 vec(w, 0, w)
169 }, {
170 vec(0, 1, 0),
171 vec(-w, 0, -w),
172 vec(-w, 0, w)
173 }, {
174 vec(w, 0, -w),
175 vec(-w, 0, -w),
176 vec(0, 1, 0)
181 drawTrinagles(triangles, 4);
183 // bottom face
184 vec quad[4] = {
185 vec(w, 0, w),
186 vec(-w, 0, w),
187 vec(-w, 0, -w),
188 vec(w, 0, -w)
191 drawQuad(quad);
194 static void drawTrianglePyramid() {
196 vec triangles[4][3] = {
199 vec(0, 1, 0),
200 vec(-w, 0, -w),
201 vec(-w, 0, w)
202 }, {
203 vec(-w, 0, w),
204 vec(p, 0, 0),
205 vec(0, 1, 0)
206 }, {
207 vec(0, 1, 0),
208 vec(p, 0, 0),
209 vec(-w, 0, -w)
212 // bottom face
214 vec(-w, 0, w),
215 vec(-w, 0, -w),
216 vec(p, 0, 0)
221 drawTrinagles(triangles, 3);
224 static void drawPrism() {
226 // side faces
227 vec quads[3][4] = {
230 vec(-w, 1, w),
231 vec(-w, 1, -w),
232 vec(-w, 0, -w),
233 vec(-w, 0, w)
234 }, {
235 vec(-w, 0, w),
236 vec(p, 0, 0),
237 vec(p, 1, 0),
238 vec(-w, 1, w)
239 }, {
240 vec(-w, 1, -w),
241 vec(p, 1, 0),
242 vec(p, 0, 0),
243 vec(-w, 0, -w)
247 drawQuads(quads, 3);
249 // top/bottom face
250 vec triangles[2][3] = {
253 vec(-w, 1, w),
254 vec(p, 1, 0),
255 vec(-w, 1, -w)
256 }, {
257 vec(-w, 0, w),
258 vec(-w, 0, -w),
259 vec(p, 0, 0)
264 drawTrinagles(triangles, 2);
267 void drawSphere() {
269 //create sphere
270 GLUquadric * quadr = gluNewQuadric();
271 glTranslatef(0, 0.2, 0);
272 gluSphere(quadr, 0.2, 20, 20);
273 glTranslatef(0, -0.2, 0);
274 gluDeleteQuadric(quadr);
278 void World::render(vec pos) const {
280 glBindBuffer(GL_ARRAY_BUFFER, _p->vbo);
281 _p->trrn.drawVertices(pos);
283 checkGl("rendering terrain");
285 glCallList(_p->dlist);
287 checkGl("rendering objects");
290 void World::generate() {
292 int trrnRandRes = rand() % 2 ? 4 : 8; // 8 or 16
293 float trrnDiv = 1.35 + 0.1*(float)(rand()%1024)/1024; // 1.35-1.45
294 float trrnExp = 0.7 + 1.3*(float)(rand()%1024)/1024; //0.7-2
295 int trrnSeed = rand();
296 _p->trrn.generate(trrnRandRes,trrnDiv,trrnExp,trrnSeed);
298 glBindBuffer(GL_ARRAY_BUFFER, _p->vbo);
299 _p->trrn.generateVertices();
301 //create world
302 glNewList(_p->dlist, GL_COMPILE);
304 static const float a = 10.0; // width/height of area with objects
306 /*// Floor
307 glNormal3f(0, 1, 0);
308 glBegin(GL_QUADS);
309 glColor3d(0.3, 0.3, 0.5);
310 glVertex3d(10 * a, 0.0, 10 * a);
311 glColor3d(0.3, 0.5, 0.3);
312 glVertex3d(10 * a, 0.0, 10 * -a);
313 glColor3d(0.3, 0.3, 0.3);
314 glVertex3d(10 * -a, 0.0, 10 * -a);
315 glColor3d(0.5, 0.3, 0.3);
316 glVertex3d(10 * -a, 0.0, 10 * a);
317 glEnd();*/
319 //_p->trrn.drawGl();
321 // Create some random objects.
322 int nitems = (int)randVar(40.0, 5.0);
323 for(int i = 0; i < nitems; ++i) {
325 glPushMatrix();
327 float x = randVal(-a, a);
328 float y = randVal(-a, a);
329 float z = heightAt(x, y);
330 glTranslatef(x, z, y);
332 float scale = randVar(2.5, 1.0);
333 float scale2 = randVar(0.75 * scale, 0.5);
334 glScalef(scale, scale2, scale);
336 glRotatef(randVal(0.0, 360.0), 0.0, 1.0, 0.0);
338 glColor3f(randVal(0.0,1.0), randVal(0.0,1.0), randVal(0.0,1.0));
340 float type = randVal();
342 if(type >= 0.8) {
343 drawCuboid();
344 } else if(type >= 0.60) {
345 drawSquarePyramid();
346 } else if(type >= 0.4) {
347 drawPrism();
348 } else if(type >= 0.2) {
349 drawSphere();
350 } else {
351 drawTrianglePyramid();
354 glPopMatrix();
358 glEndList();
360 checkGl("generating new world");
362 float rx = r(-135.0);
363 float ry = r(40.0);
364 float rz = r(0.0);
365 float tx = 10.0;
366 float ty = 10.0;
367 float tz = 4.0 + heightAt(ty, -tx);
369 _p->lightPos = t_rotateZ(rz) * t_rotateX(ry) * t_rotateY(rx) * t_translate(vec(-ty, -tz, tx));
373 float World::heightAt(float x, float y) const {
374 return _p->trrn.heightAt(x, y);
377 bool World::init() {
378 _p->dlist = glGenLists(1);
379 if(!_p->dlist) {
380 GLenum error = glGetError();
381 ERROR("generating world display list: %d: %s", error, gluErrorString(error));
382 return false;
384 glGenBuffers(1, &_p->vbo);
385 if(!_p->vbo) {
386 GLenum error = glGetError();
387 ERROR("generating terrain VBO: %d: %s", error, gluErrorString(error));
388 return false;
390 return true;
393 const transform & World::getLightPosition() const {
394 return _p->lightPos;