diff options
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 331 |
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; +} |