summaryrefslogtreecommitdiff
path: root/scene.cpp
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2011-07-01 17:20:53 +0200
committerJon Bergli Heier <snakebite@jvnv.net>2011-07-02 18:10:14 +0200
commit75a90df8bf7f38e746e021c23248e1607931132c (patch)
treedf2b4f48d5157f775c719192484188a2b0b8a04a /scene.cpp
parent90d570822f85f70c31f80789ad6791cebd904468 (diff)
Import and render tree models.
Trees are loaded from the new trees.blend using assimp. Tree objects are then received from the server and rendered on the given terrain locations. Each chunk now holds a list of objects and coordinates, which can be used to easily add other models as well. Also moded the GLSL fog code to its own shader which can be linked in different programs.
Diffstat (limited to 'scene.cpp')
-rw-r--r--scene.cpp89
1 files changed, 89 insertions, 0 deletions
diff --git a/scene.cpp b/scene.cpp
index 1fda39e..4e884a6 100644
--- a/scene.cpp
+++ b/scene.cpp
@@ -5,6 +5,7 @@
#include <SDL_image.h>
#include <boost/format.hpp>
#include <boost/bind.hpp>
+#include <assimp/aiPostProcess.h>
#include "gl.h"
@@ -27,10 +28,13 @@ Scene::Scene() {
tool = NULL;
/* setup shader programs */
+ GLFragmentShader fog_fragment("shaders/fog_fragment.glsl");
+
GLVertexShader terrain_vertex("shaders/terrain_vertex.glsl");
GLFragmentShader terrain_fragment("shaders/terrain_fragment.glsl");
terrain_program.attach(terrain_vertex);
terrain_program.attach(terrain_fragment);
+ terrain_program.attach(fog_fragment);
terrain_program.link();
GLFragmentShader water_fragment("shaders/water_fragment.glsl");
@@ -38,12 +42,24 @@ Scene::Scene() {
water_program.attach(water_fragment);
water_program.link();
+ GLVertexShader tree_vertex("shaders/tree_vertex.glsl");
+ GLFragmentShader tree_fragment("shaders/tree_fragment.glsl");
+ tree_program.attach(tree_vertex);
+ tree_program.attach(tree_fragment);
+ tree_program.attach(fog_fragment);
+ tree_program.link();
+
terrain_program.use();
GLint tex = glGetUniformLocation(terrain_program.get_program(), "tex");
GLint texv[] = {0, 1, 2};
glUniform1iv(tex, 3, texv);
GLint markloc = glGetUniformLocation(terrain_program.get_program(), "marktex");
glUniform1i(markloc, 3);
+
+ tree_program.use();
+ tex = glGetUniformLocation(tree_program.get_program(), "tex");
+ glUniform1iv(tex, 1, texv);
+
glUseProgram(0);
/* load textures */
@@ -54,6 +70,17 @@ Scene::Scene() {
marker_texture = load_texture("textures/cross.png");
placeholder_texture = load_texture("textures/placeholder.png");
+ tree_scene = ai_importer.ReadFile("models/trees.blend", aiProcess_Triangulate);
+
+ for(unsigned int i = 0; i < tree_scene->mNumTextures; i++) {
+ aiTexture *texture = tree_scene->mTextures[i];
+ GLuint tx = load_texture(texture);
+ std::string name = (boost::format("*%d") % i).str();
+ scene_textures.insert(std::pair<std::string, GLuint>(name, tx));
+ }
+
+ tree = new models::Tree(tree_scene, scene_textures);
+
/* init terrain */
terrain = new Terrain();
@@ -78,6 +105,7 @@ Scene::~Scene() {
delete lua;
if(tool)
delete tool;
+ delete tree;
if(terrain)
delete terrain;
delete font;
@@ -380,6 +408,8 @@ void Scene::render() {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
+ Terrain::Chunk::ObjectList trees;
+
// render terrain
if(render_terrain) {
const float fog_color[4] = {1, 1, 1, 0};
@@ -417,6 +447,9 @@ void Scene::render() {
// draw chunk VBOs
for(std::list<Terrain::Chunk*>::iterator it = terrain->chunks.begin(); it != terrain->chunks.end(); it++) {
Terrain::Chunk *chunk = *it;
+
+ trees.insert(trees.end(), chunk->objects.begin(), chunk->objects.end());
+
glPushMatrix();
glTranslatef(-pos.x + chunk->x, -pos.y, -pos.z + chunk->y);
glUniform2f(chunk_pos, chunk->x, chunk->y);
@@ -548,7 +581,39 @@ void Scene::render() {
(*it)->render(font, steps, placeholder_texture);
}
+ // don't pop matrix; use translated player position
+
+ // rotate to point upwards along the y-aksis
+ glRotatef(-90, 1, 0, 0);
+ glEnable(GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ tree_program.use();
+
+ GLint player_pos = glGetUniformLocation(tree_program.get_program(), "player_pos");
+ glUniform3f(player_pos, pos.x, pos.y, pos.z);
+
+ GLint tree_pos = glGetUniformLocation(tree_program.get_program(), "tree_pos");
+
+ //tree->render();
+ for(Terrain::Chunk::ObjectList::iterator it = trees.begin(); it != trees.end(); it++) {
+ glPushMatrix();
+ Vector3 pos(it->second);
+ glUniform3f(tree_pos, pos.x, pos.y, pos.z);
+ // rotated around x-axis; swap y and z, do magic to fix positions
+ glTranslatef(pos.x, -pos.z, pos.y+.5);
+ it->first->render();
+ glPopMatrix();
+ }
+
glPopMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+ glUseProgram(0);
+
+ // active texture # must be reset before rendering UI stuff
+ glActiveTexture(GL_TEXTURE0);
// HUD
video::ortho();
@@ -608,6 +673,30 @@ GLuint Scene::load_texture(const char *filename) {
return texture;
}
+GLuint Scene::load_texture(aiTexture *texture) {
+ GLuint tex;
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ if(texture->mHeight == 0) {
+ SDL_RWops *rw = SDL_RWFromConstMem(texture->pcData, texture->mWidth);
+ SDL_Surface *image = IMG_Load_RW(rw, 1);
+ if(image->format->Amask) {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, image->w, image->h, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
+ } else {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image->w, image->h, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);
+ }
+
+ SDL_FreeSurface(image);
+ } else {
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texture->mWidth, texture->mHeight, GL_BGRA, GL_UNSIGNED_BYTE, texture->pcData);
+ }
+
+ return tex;
+}
+
static bool playerlist_sort(Vector3 pos, Player::p a, Player::p b) {
return (a->get_pos() - pos).length() > (b->get_pos() - pos).length();
}