summaryrefslogtreecommitdiff
path: root/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp331
1 files changed, 331 insertions, 0 deletions
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..b653427
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,331 @@
+#include "video.h"
+#include "scene.h"
+#include "vector.h"
+#include "quadtree.h"
+
+#include <SDL_image.h>
+#include <FTGL/ftgl.h>
+#include <boost/format.hpp>
+#include <boost/shared_ptr.hpp>
+
+#define GL_GLEXT_PROTOTYPES
+#include <SDL_opengl.h>
+//#include <GL/gl.h>
+#include <GL/gl.h>
+//#include <GL/glu.h>
+
+#include <iostream>
+#include <cmath>
+#include <list>
+#include <vector>
+#include <map>
+#include <queue>
+
+FTFont *font;
+
+Scene scene;
+
+struct hit_record {
+ uint32_t hits;
+ int32_t min_z;
+ int32_t max_z;
+ uint32_t name;
+};
+
+// TODO: reimplement
+int select(Quadtree& qt, int x, int y) {
+ y = 600-y;
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ GLuint buf[64] = {0};
+ GLint hits, view[4] = {0};
+ uint32_t id = 0;
+ glSelectBuffer(64, buf);
+ glGetIntegerv(GL_VIEWPORT, view);
+ glRenderMode(GL_SELECT);
+ glInitNames();
+
+ //glPushName(0);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ gluPickMatrix(x, y, 1, 1, view);
+ gluPerspective(45, (float)view[2] / (float)view[3], 1, 10000);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ scene.lookat();
+
+ std::vector<Quadtree::QuadNode*> nodes;
+ uint32_t index = 0;
+ std::queue<Quadtree::QuadNode*> q;
+ q.push(qt.root);
+ while(!q.empty()) {
+ Quadtree::QuadNode *node = q.front();
+ q.pop();
+ if(node->vertex_array) {
+ glPushName(++index);
+ /*glBegin(GL_QUADS);
+ glVertex3f(node->x - node->width/2,
+ glEnd();*/
+ glPopName();
+ node->draw();
+ } else
+ for(int i = 0; i < 4; i++)
+ q.push(node->children[i]);
+ }
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ //glMatrixMode(GL_MODELVIEW);
+ //glFlush();
+ hits = glRenderMode(GL_RENDER);
+ //std::cout << "hits: " << hits << std::endl;
+ for(int i = 0; i < hits; i++) {
+ struct hit_record *hit = (struct hit_record*)(buf + i*sizeof(hit_record));
+ //std::cout << " hits: " << hit->hits << " min_z: " << hit->min_z << " max_z: " << hit->max_z << std::endl;
+ if(hit->hits == 1 && hit->name > 0)
+ id = hit->name;
+ }
+ glMatrixMode(GL_MODELVIEW);
+ //std::cout << "id: " << id << std::endl;
+ if(id > 0) {
+ //return map[vectors[id-1]];
+ }
+ //return Vector3::p();
+ //return id;
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ video::width = 800;
+ video::height = 600;
+ video::init();
+
+ font = new FTTextureFont("font.ttf");
+ font->FaceSize(10);
+
+ SDL_Surface *hm = IMG_Load("heightmap6.png");
+ unsigned char *pixels = (unsigned char*)hm->pixels;
+ float *heightmap = new float[hm->w * hm->h];
+ for(int x = 0; x < hm->w; x++) {
+ for(int y = 0; y < hm->h; y++) {
+ heightmap[y*hm->w + x] = ((float)(pixels[y*hm->w + x]) / 256) * 20;
+ }
+ }
+ int level = 3;
+ Quadtree *qt = new Quadtree(hm->w, hm->h, heightmap, level);
+ //Quadtree qt(qt_size, qt_size, (int)ceil(sqrt(qt_size)));
+
+ GLuint grass_texture;
+ {
+ SDL_Surface *surface = IMG_Load("Grass0073_3_S.jpg");
+ SDL_Surface *image = SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, surface->h, 32,
+ 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+ SDL_Rect area;
+ area.x = area.y = 0;
+ area.w = surface->w;
+ area.h = surface->h;
+ SDL_BlitSurface(surface, &area, image, &area);
+ //glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glGenTextures(1, &grass_texture);
+ glBindTexture(GL_TEXTURE_2D, grass_texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ if(image->format->Amask) {
+ //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, image->w, image->h, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
+ } else {
+ //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image->w, image->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image->w, image->h, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);
+ }
+ SDL_FreeSurface(surface);
+ SDL_FreeSurface(image);
+ }
+
+ //SDL_WM_GrabInput(SDL_GRAB_ON);
+
+ SDL_Event event;
+ bool running = true;
+ bool grid = false;
+ SDL_WarpMouse(video::width/2, video::height/2);
+ unsigned int last_time = SDL_GetTicks();
+ /*boost::timer t;
+ double last_time = 0;*/
+ while(running) {
+ unsigned int time = SDL_GetTicks();
+ //double time = t.elapsed();
+ //t.restart();
+ unsigned int steps = time - last_time + 1;
+ //double steps = (time - last_time) * 1000;
+ last_time = time;
+ while(SDL_PollEvent(&event)) {
+ switch(event.type) {
+ case SDL_QUIT:
+ running = false;
+ break;
+ case SDL_KEYDOWN:
+ switch(event.key.keysym.sym) {
+ case SDLK_ESCAPE:
+ running = false;
+ break;
+ case SDLK_g:
+ grid = !grid;
+ break;
+ case SDLK_KP_PLUS:
+ delete qt;
+ qt = new Quadtree(hm->w, hm->h, heightmap, ++level);
+ break;
+ case SDLK_KP_MINUS:
+ if(level > 0) {
+ delete qt;
+ qt = new Quadtree(hm->w, hm->h, heightmap, --level);
+ }
+ break;
+ case SDLK_SPACE:
+ scene.yvel = .05;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SDL_MOUSEBUTTONUP:
+ switch(event.button.button) {
+ case SDL_BUTTON_LEFT:
+ // TODO: reimplement selection
+ break;
+ case SDL_BUTTON_WHEELUP:
+ case SDL_BUTTON_WHEELDOWN:
+ // TODO: reimplement?
+ break;
+ }
+ case SDL_MOUSEMOTION:
+ if(event.motion.x == video::width/2 && event.motion.y == video::height/2)
+ break;
+ scene.yaw += (float)event.motion.xrel / 500;
+ scene.pitch += (float)event.motion.yrel / 500;
+ if(scene.yaw > 2*M_PI)
+ scene.yaw -= 2*M_PI;
+ else if(scene.yaw < 0)
+ scene.yaw += 2*M_PI;
+ if(scene.pitch > M_PI)
+ scene.pitch = M_PI;
+ else if(scene.pitch < 0)
+ scene.pitch = 0;
+ SDL_WarpMouse(video::width/2, video::height/2);
+ break;
+ }
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+ video::persp();
+
+ unsigned char *keystate = SDL_GetKeyState(NULL);
+ float forward = 0;
+ float right = 0;
+ bool moved = false;
+ if(keystate[SDLK_w]) {
+ moved = true;
+ forward++;
+ }
+ if(keystate[SDLK_s]) {
+ moved = true;
+ forward--;
+ }
+ if(keystate[SDLK_a]) {
+ moved = true;
+ right--;
+ }
+ if(keystate[SDLK_d]) {
+ moved = true;
+ right++;
+ }
+ if(keystate[SDLK_q])
+ scene.pos.y -= 0.002*steps;
+ if(keystate[SDLK_e])
+ scene.pos.y += 0.002*steps*(keystate[SDLK_LSHIFT]?10:1);
+ if(moved && (forward || right))
+ scene.move(forward, right, steps*(keystate[SDLK_LSHIFT]?10:1));
+
+ std::string move_str;
+ {
+ Quadtree::QuadNode *node = qt->find(scene.pos.x, scene.pos.z);
+ if(node) {
+ float y = node->get_height(scene.pos.x, scene.pos.z);
+ if(scene.pos.y > y && !keystate[SDLK_e])
+ scene.yvel -= 9.81 * steps / 85000;
+ if(scene.yvel < -.5)
+ scene.yvel = -.5;
+ scene.pos.y += scene.yvel;
+ if(scene.pos.y < y) {
+ scene.pos.y = y;
+ scene.yvel = 0;
+ }
+ move_str = (boost::format("%s %.2f,%.2f %dx%d") % scene.pos.str() % node->x % node->y % node->width % node->height).str();
+ }
+ }
+
+ scene.lookat();
+
+ glEnable(GL_LIGHTING);
+ //const float light_pos[4] = {50, 20, 50, 1};
+ const float light_pos[4] = {0, 1, 0, 0};
+ glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
+
+ if(!grid) {
+ glBindTexture(GL_TEXTURE_2D, grass_texture);
+ glEnable(GL_TEXTURE_2D);
+ glBindBuffer(GL_ARRAY_BUFFER, qt->vbo_object);
+ glVertexPointer(3, GL_FLOAT, 0, NULL);
+ glNormalPointer(GL_FLOAT, 0, (GLvoid*)(qt->vertices*3*sizeof(float)));
+ glTexCoordPointer(2, GL_FLOAT, 0, (GLvoid*)(qt->vertices*3*sizeof(float)*2));
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDrawArrays(GL_TRIANGLES, 0, qt->vertices);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ } else {
+ std::queue<Quadtree::QuadNode*> q;
+ q.push(qt->root);
+ glBindTexture(GL_TEXTURE_2D, grass_texture);
+ glEnable(GL_TEXTURE_2D);
+ while(!q.empty()) {
+ Quadtree::QuadNode *node = q.front();
+ q.pop();
+ if(node->vertex_array) {
+ grid ? node->draw_grid() : node->draw();
+ } else
+ for(int i = 0; i < 4; i++)
+ q.push(node->children[i]);
+ }
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_LIGHTING);
+
+ video::ortho();
+ float height = font->LineHeight();
+ glColor3f(1, 1, 1);
+ glTranslatef(0, 600-height, 0);
+ font->Render((boost::format("%dx%d %d levels %d nodes tree creation time: %f steps: %d")
+ % qt->width % qt->height % qt->levels % qt->nodes % qt->init_time % steps).str().c_str());
+ //glTranslatef(0, height, 0);
+ //font->Render((boost::format("selected: %x") % selected).str().c_str());
+ glTranslatef(0, -height, 0);
+ font->Render(move_str.c_str());
+ /*if(selected) {
+ glTranslatef(0, height, 0);
+ //font->Render((boost::format("(%s %s %s %s)") % selected->a->str() % selected->b->str() % selected->c->str() % selected->d->str()).str().c_str());
+ font->Render(selected->str().c_str());
+ }*/
+
+ SDL_GL_SwapBuffers();
+
+ usleep(1000);
+ }
+
+ video::free();
+
+ return 0;
+}