From ff7b7c8838f55dc0f2e76f903630f1d3d2941d5a Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 14 Dec 2009 13:54:34 +0100 Subject: Added everything... -.- --- BSPTree.cpp | 83 +++++++----- BSPTree.h | 93 +++++++------ CMakeLists.txt | 11 +- FindGLPng.cmake | 16 +++ Game.cpp | 47 ++++--- Game.h | 6 + Level.cpp | 260 ++++++++++++++++++++++++++++++++++++ Level.h | 74 +++++++++++ Renderer.cpp | 34 ++++- Renderer.h | 26 ++-- Texture.cpp | 44 ++++++ Texture.h | 40 ++++++ Triangle.h | 90 ++++++++++--- config.h | 2 +- gl.h | 25 +++- levels/level.dtd | 61 +++++++++ levels/level.xml | 392 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tex/blue.png | Bin 0 -> 80980 bytes tex/cursor.png | Bin 0 -> 651 bytes tex/dark.png | Bin 0 -> 40686 bytes tex/door.png | Bin 0 -> 110154 bytes tex/fire.png | Bin 0 -> 63077 bytes tex/green.png | Bin 0 -> 708834 bytes tex/green2.png | Bin 0 -> 79738 bytes tex/light.png | Bin 0 -> 215452 bytes tex/lightmap.png | Bin 0 -> 13789 bytes tex/lightmap2.png | Bin 0 -> 31318 bytes tex/medib.png | Bin 0 -> 136 bytes tex/metallic.png | Bin 0 -> 570955 bytes tex/metallic2.png | Bin 0 -> 546156 bytes tex/textur.png | Bin 0 -> 86779 bytes tex/wall1.png | Bin 0 -> 435 bytes tex/wall2.png | Bin 0 -> 698 bytes tex/wall3.png | Bin 0 -> 1298 bytes tex/wall4.png | Bin 0 -> 22161 bytes tex/wall5.png | Bin 0 -> 12430 bytes zoom.cpp | 24 +++- 37 files changed, 1194 insertions(+), 134 deletions(-) create mode 100644 FindGLPng.cmake create mode 100644 Level.cpp create mode 100644 Level.h create mode 100644 Texture.cpp create mode 100644 Texture.h create mode 100644 levels/level.dtd create mode 100644 levels/level.xml create mode 100644 tex/blue.png create mode 100644 tex/cursor.png create mode 100644 tex/dark.png create mode 100644 tex/door.png create mode 100644 tex/fire.png create mode 100644 tex/green.png create mode 100644 tex/green2.png create mode 100644 tex/light.png create mode 100644 tex/lightmap.png create mode 100644 tex/lightmap2.png create mode 100644 tex/medib.png create mode 100644 tex/metallic.png create mode 100644 tex/metallic2.png create mode 100644 tex/textur.png create mode 100644 tex/wall1.png create mode 100644 tex/wall2.png create mode 100644 tex/wall3.png create mode 100644 tex/wall4.png create mode 100644 tex/wall5.png diff --git a/BSPTree.cpp b/BSPTree.cpp index fa2f1c0..a94c77a 100644 --- a/BSPTree.cpp +++ b/BSPTree.cpp @@ -1,5 +1,23 @@ -#include "BSPTree.h" +/* + * BSPTree.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ +#include "BSPTree.h" namespace Zoom { @@ -9,20 +27,20 @@ vmml::vec3f BSPTree::Plane::intersection(const vmml::vec3f &p, const vmml::vec3f return p + r*dir; } -void BSPTree::Plane::partition(const Triangle &t, std::list *front, std::list *back) const { +void BSPTree::Plane::partition(const TriangleRecord &t, std::list *front, std::list *back) const { for(int i = 0; i < 3; ++i) { - if(contains(t.getVertex(i))) { - const vmml::vec3f *v[3] = {&t.getVertex(i), &t.getVertex((i+1)%3), &t.getVertex((i+2)%3)}; + if(contains(t.triangle.getVertex(i))) { + const vmml::vec3f *v[3] = {&t.triangle.getVertex(i), &t.triangle.getVertex((i+1)%3), &t.triangle.getVertex((i+2)%3)}; vmml::vec3f is = intersection(*v[1], *v[2]-*v[1]); if(isInFront(*v[1])) { - front->push_back(Triangle(*v[0], *v[1], is, t.getColor())); - back->push_back(Triangle(*v[0], is, *v[2], t.getColor())); + front->push_back(TriangleRecord(Triangle(*v[0], *v[1], is, t.triangle.getColor()), t.data)); + back->push_back(TriangleRecord(Triangle(*v[0], is, *v[2], t.triangle.getColor()), t.data)); } else { - back->push_back(Triangle(*v[0], *v[1], is, t.getColor())); - front->push_back(Triangle(*v[0], is, *v[2], t.getColor())); + back->push_back(TriangleRecord(Triangle(*v[0], *v[1], is, t.triangle.getColor()), t.data)); + front->push_back(TriangleRecord(Triangle(*v[0], is, *v[2], t.triangle.getColor()), t.data)); } return; @@ -30,7 +48,7 @@ void BSPTree::Plane::partition(const Triangle &t, std::list *front, st } for(int i = 0; i < 3; ++i) { - const vmml::vec3f *v[3] = {&t.getVertex(i), &t.getVertex((i+1)%3), &t.getVertex((i+2)%3)}; + const vmml::vec3f *v[3] = {&t.triangle.getVertex(i), &t.triangle.getVertex((i+1)%3), &t.triangle.getVertex((i+2)%3)}; if((isInFront(*v[0]) && isBehind(*v[1]) && isBehind(*v[2])) || (isBehind(*v[0]) && isInFront(*v[1]) && isInFront(*v[2]))) { @@ -38,14 +56,14 @@ void BSPTree::Plane::partition(const Triangle &t, std::list *front, st vmml::vec3f is2 = intersection(*v[0], *v[2]-*v[0]); if(isInFront(*v[0])) { - front->push_back(Triangle(*v[0], is1, is2, t.getColor())); - back->push_back(Triangle(is1, *v[1], is2, t.getColor())); - back->push_back(Triangle(*v[1], *v[2], is2, t.getColor())); + front->push_back(TriangleRecord(Triangle(*v[0], is1, is2, t.triangle.getColor()), t.data)); + back->push_back(TriangleRecord(Triangle(is1, *v[1], is2, t.triangle.getColor()), t.data)); + back->push_back(TriangleRecord(Triangle(*v[1], *v[2], is2, t.triangle.getColor()), t.data)); } else { - back->push_back(Triangle(*v[0], is1, is2, t.getColor())); - front->push_back(Triangle(is1, *v[1], is2, t.getColor())); - front->push_back(Triangle(*v[1], *v[2], is2, t.getColor())); + back->push_back(TriangleRecord(Triangle(*v[0], is1, is2, t.triangle.getColor()), t.data)); + front->push_back(TriangleRecord(Triangle(is1, *v[1], is2, t.triangle.getColor()), t.data)); + front->push_back(TriangleRecord(Triangle(*v[1], *v[2], is2, t.triangle.getColor()), t.data)); } return; @@ -54,7 +72,7 @@ void BSPTree::Plane::partition(const Triangle &t, std::list *front, st } -BSPTree::BSPTree(const std::list &triangles) : frontTree(0), backTree(0) { +BSPTree::BSPTree(const std::list &triangles) : frontTree(0), backTree(0) { const Triangle *planeT = findNearestTriangle(triangles, findCenter(triangles)); if(!planeT) @@ -62,29 +80,26 @@ BSPTree::BSPTree(const std::list &triangles) : frontTree(0), backTree( plane = Plane(*planeT); - std::list front, back; + std::list front, back; - for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { - if(t->getNormal().squared_length() == 0) + for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { + if(t->triangle.isDegenerate()) continue; - if(plane.contains(*t)) { + if(plane.contains(t->triangle)) { this->triangles.push_back(*t); continue; } - else if(plane.isInFront(*t)) { + else if(plane.isInFront(t->triangle)) { front.push_back(*t); continue; } - else if(plane.isBehind(*t)) { + else if(plane.isBehind(t->triangle)) { back.push_back(*t); continue; } - std::list frontPart, backPart; - plane.partition(*t, &frontPart, &backPart); - front.splice(front.end(), frontPart); - back.splice(back.end(), backPart); + plane.partition(*t, &front, &back); } if(!front.empty()) @@ -117,28 +132,28 @@ BSPTree& BSPTree::operator=(const BSPTree &tree) { return *this; } -vmml::vec3f BSPTree::findCenter(const std::list &triangles) { +vmml::vec3f BSPTree::findCenter(const std::list &triangles) { vmml::vec3f v; - for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { - v += t->getCenter(); + for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { + v += t->triangle.getCenter(); } return v/triangles.size(); } -const Triangle* BSPTree::findNearestTriangle(const std::list &triangles, const vmml::vec3f &v) { +const Triangle* BSPTree::findNearestTriangle(const std::list &triangles, const vmml::vec3f &v) { const Triangle *current = 0; float distanceSq; - for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { - if(t->getNormal().squared_length() == 0) + for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { + if(t->triangle.isDegenerate()) continue; - float d = t->getCenter().squared_distance(v); + float d = t->triangle.getCenter().squared_distance(v); if(!current || d < distanceSq) { - current = &*t; + current = &t->triangle; distanceSq = d; } } diff --git a/BSPTree.h b/BSPTree.h index 47ba411..1944ef1 100644 --- a/BSPTree.h +++ b/BSPTree.h @@ -1,20 +1,61 @@ +/* + * BSPTree.h + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + #ifndef ZOOM_BSPTREE_H_ #define ZOOM_BSPTREE_H_ #include "Triangle.h" #include #include + #include +#include namespace Zoom { class BSPTree { + public: + class TriangleData { + protected: + TriangleData() {} + + public: + virtual ~TriangleData() {} + }; + + struct TriangleRecord { + public: + TriangleRecord(Triangle triangle0, boost::shared_ptr data0) + : triangle(triangle0), data(data0) {} + TriangleRecord(Triangle triangle0) : triangle(triangle0) {} + TriangleRecord() {} + + Triangle triangle; + boost::shared_ptr data; + }; + private: class Plane { public: Plane() : d(0) {} Plane(const vmml::vec3f &n, float d0) : normal(n), d(d0) {} - Plane(const Triangle &t) : normal(t.getNormal()), d(t.getVertex(0).dot(normal)) {} + Plane(const Triangle &t) : normal(t.computeNormal()), d(t.getVertex(0).dot(normal)) {} bool contains(const vmml::vec3f &v) const { return (fabsf(normal.dot(v) - d) < 1E-6); @@ -62,7 +103,7 @@ class BSPTree { } vmml::vec3f intersection(const vmml::vec3f &p, const vmml::vec3f &dir) const; - void partition(const Triangle &t, std::list *front, std::list *back) const; + void partition(const TriangleRecord &t, std::list *front, std::list *back) const; private: vmml::vec3f normal; @@ -70,7 +111,7 @@ class BSPTree { }; public: - BSPTree(const std::list &triangles); + BSPTree(const std::list &triangles); BSPTree(const BSPTree &tree) : frontTree(0), backTree(0) { *this = tree; @@ -86,16 +127,6 @@ class BSPTree { BSPTree& operator=(const BSPTree &tree); - template - void visit(const T& visitor, const vmml::vec3f &p) { - doVisit(visitor, p); - } - - template - void visit(T& visitor, const vmml::vec3f &p) { - doVisit(visitor, p); - } - template void visit(const T& visitor, const vmml::vec3f &p) const { doVisit(visitor, p); @@ -108,42 +139,16 @@ class BSPTree { private: Plane plane; - std::list triangles; + std::list triangles; BSPTree *frontTree, *backTree; - template - void doVisit(T& visitor, const vmml::vec3f &p) { - if(plane.isBehind(p)) { - if(frontTree) - frontTree->visit(visitor, p); - - for(std::list::iterator t = triangles.begin(); t != triangles.end(); ++t) { - visitor(*t); - } - - if(backTree) - backTree->visit(visitor, p); - } - else { - if(backTree) - backTree->visit(visitor, p); - - for(std::list::iterator t = triangles.begin(); t != triangles.end(); ++t) { - visitor(*t); - } - - if(frontTree) - frontTree->visit(visitor, p); - } - } - template void doVisit(T& visitor, const vmml::vec3f &p) const { if(plane.isBehind(p)) { if(frontTree) frontTree->visit(visitor, p); - for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { + for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { visitor(*t); } @@ -154,7 +159,7 @@ class BSPTree { if(backTree) backTree->visit(visitor, p); - for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { + for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { visitor(*t); } @@ -163,8 +168,8 @@ class BSPTree { } } - static vmml::vec3f findCenter(const std::list &triangles); - static const Triangle* findNearestTriangle(const std::list &triangles, const vmml::vec3f &v); + static vmml::vec3f findCenter(const std::list &triangles); + static const Triangle* findNearestTriangle(const std::list &triangles, const vmml::vec3f &v); }; } diff --git a/CMakeLists.txt b/CMakeLists.txt index da27b7b..6135c41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,25 @@ cmake_minimum_required(VERSION 2.6) project(ZOOM) +set(CMAKE_MODULE_PATH ${ZOOM_SOURCE_DIR}) + +find_package(Boost REQUIRED) find_package(OpenGL REQUIRED) +find_package(GLPng REQUIRED) +find_package(LibXml2 REQUIRED) -include_directories(${OPENGL_INCLUDE_DIR}) +include_directories(${Boost_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLPNG_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) add_executable(zoom BSPTree.cpp BSPTree.h Game.cpp Game.h config.h gl.h + Level.cpp Level.h Renderer.cpp Renderer.h + Texture.cpp Texture.h Triangle.h zoom.cpp ) -target_link_libraries(zoom ${OPENGL_LIBRARIES}) +target_link_libraries(zoom ${Boost_LIBRARIES} ${OPENGL_LIBRARIES} ${GLPNG_LIBRARY} ${LIBXML2_LIBRARIES}) diff --git a/FindGLPng.cmake b/FindGLPng.cmake new file mode 100644 index 0000000..f02b772 --- /dev/null +++ b/FindGLPng.cmake @@ -0,0 +1,16 @@ +FIND_PATH(GLPNG_INCLUDE_DIR GL/glpng.h) +FIND_LIBRARY(GLPNG_LIBRARY NAMES glpng) + +IF (GLPNG_INCLUDE_DIR AND GLPNG_LIBRARY) + SET(GLPNG_FOUND TRUE) +ENDIF (GLPNG_INCLUDE_DIR AND GLPNG_LIBRARY) + +IF (GLPNG_FOUND) + IF (NOT GLPng_FIND_QUIETLY) + MESSAGE(STATUS "Found glpng: ${GLPNG_LIBRARY}") + ENDIF (NOT GLPng_FIND_QUIETLY) +ELSE (GLPNG_FOUND) + IF (GLPng_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find glpng") + ENDIF (GLPng_FIND_REQUIRED) +ENDIF (GLPNG_FOUND) diff --git a/Game.cpp b/Game.cpp index bd028c2..46f942f 100644 --- a/Game.cpp +++ b/Game.cpp @@ -19,6 +19,7 @@ #include "Game.h" #include "BSPTree.h" +#include "Level.h" #include "Triangle.h" #include "gl.h" @@ -26,8 +27,9 @@ namespace Zoom { Game::Game(bool multisample) : angle(0) { glClearColor(0.0, 0.0, 0.0, 1.0); - //glEnable(GL_DEPTH_TEST); - //glDepthFunc(GL_LEQUAL); + glClearDepth(1.0); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); //glEnable(GL_BLEND); //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -37,43 +39,52 @@ Game::Game(bool multisample) : angle(0) { glEnable(GL_MULTISAMPLE_ARB); #endif - /*glEnable(GL_LIGHTING); - static const float light[] = {1, 1, 1, 0}; + glShadeModel(GL_SMOOTH); + + glEnable(GL_LIGHTING); + static const float light[] = {0, 0, 0, 1}; static const float lightColor[] = {1, 1, 1, 1}; glLightfv(GL_LIGHT0, GL_POSITION, light); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); - glEnable(GL_LIGHT0);*/ + glEnable(GL_LIGHT0); + + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); - //glEnable(GL_CULL_FACE); - //glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + glFrontFace(GL_CCW); glLoadIdentity(); - glTranslatef(0, 0, -5); + + loadLevel("level.xml"); +} + +bool Game::loadLevel(const std::string &name) { + level = Level::loadLevel(name); + + return level; } void Game::run(int delta) { - angle += delta*0.2; + angle += delta*0.01; if(angle >= 360) angle -= 360; } void Game::render() { - std::list triangles; - - triangles.push_back(Triangle(vmml::vec3f(-1, -1, 0), vmml::vec3f(1, -1, 0), vmml::vec3f(1, 1, 0), vmml::vec3f(0, 1, 0))); - triangles.push_back(Triangle(vmml::vec3f(-1, -1, 0), vmml::vec3f(-1, 1, 0), vmml::vec3f(1, 1, 0), vmml::vec3f(0, 1, 0))); - triangles.push_back(Triangle(vmml::vec3f(-1, -1, -1), vmml::vec3f(1, -1, -1), vmml::vec3f(1, 1, -1), vmml::vec3f(0, 0, 1))); - triangles.push_back(Triangle(vmml::vec3f(-1, -1, -1), vmml::vec3f(-1, 1, -1), vmml::vec3f(1, 1, -1), vmml::vec3f(0, 0, 1))); + std::list triangles; - BSPTree tree(triangles); + triangles.insert(triangles.end(), level->getRooms().front().walls.begin(), level->getRooms().front().walls.end()); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(angle, 1, 2, 1); + //glRotatef(3*angle, 0, -1, 2); + //glRotatef(5*angle, 2, -1, 0); - renderer.render(tree); + renderer.render(triangles); glPopMatrix(); } diff --git a/Game.h b/Game.h index dbd129a..7960497 100644 --- a/Game.h +++ b/Game.h @@ -21,20 +21,26 @@ #define ZOOM_GAME_H_ #include "Renderer.h" +#include +#include namespace Zoom { +class Level; class Triangle; class Game { public: Game(bool multisample); + bool loadLevel(const std::string &name); + void run(int delta); void render(); private: Renderer renderer; + boost::shared_ptr level; float angle; }; diff --git a/Level.cpp b/Level.cpp new file mode 100644 index 0000000..2867ab9 --- /dev/null +++ b/Level.cpp @@ -0,0 +1,260 @@ +/* + * Level.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "Level.h" +#include "Texture.h" +#include +#include + +#include + +namespace Zoom { + +boost::shared_ptr Level::loadLevel(const std::string &filename) { + boost::shared_ptr level; + + xmlDocPtr doc = xmlParseFile(("levels/"+filename).c_str()); + + if(doc) { + if(validateLevel(doc)) { + xmlNodePtr root = xmlDocGetRootElement(doc); + if(root && !xmlStrcmp(root->name, (xmlChar*)"level")) { + level = boost::shared_ptr(new Level); + + for(xmlNodePtr node = root->children; node != 0; node = node->next) { + if(node->type != XML_ELEMENT_NODE) + continue; + + if(!xmlStrcmp(node->name, (xmlChar*)"info")) { + level->loadLevelInfo(node); + } + else if(!xmlStrcmp(node->name, (xmlChar*)"rooms")) { + level->loadRooms(node); + } + else if(!xmlStrcmp(node->name, (xmlChar*)"textures")) { + level->loadTextures(node); + } + } + + for(std::list::iterator room = level->rooms.begin(); room != level->rooms.end(); ++room) { + for(std::list::iterator wall = room->walls.begin(); wall != room->walls.end(); ++wall) { + boost::shared_ptr wallData = boost::dynamic_pointer_cast(wall->data); + + if(!wallData->texture.empty()) { + std::map::iterator texture = level->textures.find(wallData->texture); + + if(texture != level->textures.end()) + wall->triangle.setTexture(texture->second); + } + } + } + } + } + + xmlFreeDoc(doc); + } + + xmlCleanupParser(); + + return level; +} + +void Level::loadLevelInfo(xmlNodePtr infoNode) { + for(xmlNodePtr node = infoNode->children; node != 0; node = node->next) { + if(node->type != XML_ELEMENT_NODE) + continue; + + if(!xmlStrcmp(node->name, (xmlChar*)"name")) { + xmlChar *data = xmlNodeGetContent(node); + name = (char*)data; + xmlFree(data); + } + else if(!xmlStrcmp(node->name, (xmlChar*)"desc")) { + xmlChar *data = xmlNodeGetContent(node); + description = (char*)data; + xmlFree(data); + } + else if(!xmlStrcmp(node->name, (xmlChar*)"start")) { + startPoint = loadVector(node); + } + } +} + +void Level::loadRooms(xmlNodePtr roomsNode) { + for(xmlNodePtr node = roomsNode->children; node != 0; node = node->next) { + if(node->type == XML_ELEMENT_NODE && !xmlStrcmp(node->name, (xmlChar*)"room")) { + loadRoom(node); + } + } +} + +void Level::loadRoom(xmlNodePtr roomNode) { + rooms.push_back(Room()); + + xmlChar *data = xmlGetProp(roomNode, (xmlChar*)"id"); + if(data) { + rooms.back().id = (char*)data; + + xmlFree(data); + } + + for(xmlNodePtr node = roomNode->children; node != 0; node = node->next) { + if(node->type == XML_ELEMENT_NODE && !xmlStrcmp(node->name, (xmlChar*)"triangle")) { + rooms.back().walls.push_back(loadWall(node)); + } + } +} + +void Level::loadTextures(xmlNodePtr texturesNode) { + for(xmlNodePtr node = texturesNode->children; node != 0; node = node->next) { + if(node->type == XML_ELEMENT_NODE && !xmlStrcmp(node->name, (xmlChar*)"texture")) { + std::string id, name; + + xmlChar *data = xmlGetProp(node, (xmlChar*)"id"); + if(data) { + id = (char*)data; + xmlFree(data); + } + + data = xmlGetProp(node, (xmlChar*)"name"); + if(data) { + name = (char*)data; + xmlFree(data); + } + + if(!id.empty() && !name.empty()) { + unsigned texture = Texture::loadTexture(name); + + if(texture) { + textures.insert(std::make_pair(id, texture)); + } + } + } + } +} + +BSPTree::TriangleRecord Level::loadWall(xmlNodePtr wallNode) { + boost::shared_ptr wallData(new WallData); + + BSPTree::TriangleRecord wall; + wall.data = wallData; + + + xmlChar *data = xmlGetProp(wallNode, (xmlChar*)"texture"); + if(data) { + wallData->texture = (char*)data; + xmlFree(data); + } + + int vertexNum = -1; + + for(xmlNodePtr node = wallNode->children; node != 0; node = node->next) { + if(node->type != XML_ELEMENT_NODE) + continue; + + if(!xmlStrcmp(node->name, (xmlChar*)"vertex")) { + if(++vertexNum > 2) + break; + + wall.triangle.setVertex(vertexNum, loadVector(node)); + } + else if(!xmlStrcmp(node->name, (xmlChar*)"normal")) { + if(vertexNum < 0) + continue; + + wall.triangle.setNormal(vertexNum, loadVector(node)); + } + else if(!xmlStrcmp(node->name, (xmlChar*)"texcoords")) { + if(vertexNum < 0) continue; + + data = xmlGetProp(node, (xmlChar*)"s"); + if(data) { + wall.triangle.getTexCoords(vertexNum)[0] = atof((char*)data); + xmlFree(data); + } + + data = xmlGetProp(node, (xmlChar*)"t"); + if(data) { + wall.triangle.getTexCoords(vertexNum)[1] = atof((char*)data); + xmlFree(data); + } + } + } + + vmml::vec3f normal = wall.triangle.computeNormal(); + + if(normal.squared_length() > 0) { + normal.normalize(); + + for(int i = 0; i < 3; ++i) { + if(wall.triangle.getNormal(i).squared_length() == 0) + wall.triangle.setNormal(i, normal); + } + } + + + return wall; +} + +vmml::vec3f Level::loadVector(xmlNodePtr node) { + vmml::vec3f ret(vmml::vec3f::ZERO); + + xmlChar *data = xmlGetProp(node, (xmlChar*)"x"); + if(data) { + ret.x() = atof((char*)data); + xmlFree(data); + } + + data = xmlGetProp(node, (xmlChar*)"y"); + if(data) { + ret.y() = atof((char*)data); + xmlFree(data); + } + + data = xmlGetProp(node, (xmlChar*)"z"); + if(data) { + ret.z() = atof((char*)data); + xmlFree(data); + } + + return ret; +} + +bool Level::validateLevel(xmlDocPtr doc) { + bool ret = false; + + xmlDtdPtr dtd = xmlParseDTD((xmlChar*)"-//libzoom//DTD level 0.1//EN", (xmlChar*)"levels/level.dtd"); + + if(dtd) { + xmlValidCtxtPtr validCtxt = xmlNewValidCtxt(); + + if(validCtxt) { + if(xmlValidateDtd(validCtxt, doc, dtd)) + ret = true; + + xmlFreeValidCtxt(validCtxt); + } + + xmlFreeDtd(dtd); + } + + return ret; +} + +} diff --git a/Level.h b/Level.h new file mode 100644 index 0000000..277b6e7 --- /dev/null +++ b/Level.h @@ -0,0 +1,74 @@ +/* + * Level.h + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#ifndef ZOOM_LEVEL_H_ +#define ZOOM_LEVEL_H_ + +#include "BSPTree.h" + +#include +#include +#include + +#include +#include +#include + +namespace Zoom { + +class Level { + public: + static boost::shared_ptr loadLevel(const std::string &filename); + + struct WallData : public BSPTree::TriangleData { + std::string texture; + }; + + struct Room { + std::string id; + std::list walls; + }; + + const std::list &getRooms() const { + return rooms; + } + + private: + std::list rooms; + std::map textures; + + std::string name, description; + vmml::vec3f startPoint; + + Level() {} + + void loadLevelInfo(xmlNodePtr infoNode); + void loadRooms(xmlNodePtr roomsNode); + void loadRoom(xmlNodePtr roomNode); + void loadTextures(xmlNodePtr texturesNode); + + static BSPTree::TriangleRecord loadWall(xmlNodePtr wallNode); + static vmml::vec3f loadVector(xmlNodePtr node); + + static bool validateLevel(xmlDocPtr doc); +}; + +} + +#endif /* ZOOM_LEVEL_H_ */ diff --git a/Renderer.cpp b/Renderer.cpp index bf9aadb..558e415 100644 --- a/Renderer.cpp +++ b/Renderer.cpp @@ -19,11 +19,10 @@ #include "Renderer.h" #include "BSPTree.h" +#include "gl.h" namespace Zoom { -const Renderer::RenderVisitor Renderer::renderVisitor = Renderer::RenderVisitor(); - void Renderer::render(const BSPTree &tree) { vmml::mat4f transform, inverseTransform; glGetFloatv(GL_MODELVIEW_MATRIX, transform.array); @@ -38,14 +37,39 @@ void Renderer::render(const BSPTree &tree) { } +void Renderer::render(const std::list &triangles) { + glBegin(GL_TRIANGLES); + for(std::list::const_iterator t = triangles.begin(); t != triangles.end(); ++t) { + renderTriangle(t->triangle); + } + glEnd(); +} + void Renderer::renderTriangle(const Triangle &t) { glColor4fv(t.getColor().array); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, t.getColor().array); - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (t.getColor()/2).array); - glNormal3fv(t.getNormal().array); + if(t.getTexture() != lastTexture) { + glEnd(); + + if(t.getTexture()) { + glBindTexture(GL_TEXTURE_2D, t.getTexture()); + + if(!lastTexture) { + glEnable(GL_TEXTURE_2D); + } + } + else { + glDisable(GL_TEXTURE_2D); + } + + lastTexture = t.getTexture(); + + glBegin(GL_TRIANGLES); + } for(int i = 0; i < 3; ++i) { + glTexCoord2fv(t.getTexCoords(i).array); + glNormal3fv(t.getNormal(i).array); glVertex3fv(t.getVertex(i).array); } } diff --git a/Renderer.h b/Renderer.h index d64a4fe..d72b5bb 100644 --- a/Renderer.h +++ b/Renderer.h @@ -20,25 +20,35 @@ #ifndef ZOOM_RENDERER_H_ #define ZOOM_RENDERER_H_ -namespace Zoom { +#include "BSPTree.h" -class Triangle; -class BSPTree; +namespace Zoom { class Renderer { public: + Renderer() : lastTexture(0), renderVisitor(this) {} + void render(const BSPTree &tree); + void render(const std::list &triangles); private: - static void renderTriangle(const Triangle &t); + void renderTriangle(const Triangle &t); - struct RenderVisitor { - void operator() (const Triangle &t) const { - renderTriangle(t); + class RenderVisitor { + public: + RenderVisitor(Renderer *renderer0) : renderer(renderer0) {} + + void operator() (const BSPTree::TriangleRecord &t) const { + renderer->renderTriangle(t.triangle); } + + private: + Renderer *renderer; }; - static const RenderVisitor renderVisitor; + unsigned lastTexture; + + const RenderVisitor renderVisitor; }; } diff --git a/Texture.cpp b/Texture.cpp new file mode 100644 index 0000000..d5ec1f2 --- /dev/null +++ b/Texture.cpp @@ -0,0 +1,44 @@ +/* + * Texture.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "Texture.h" +#include "gl.h" +#include + +namespace Zoom { + +std::map Texture::textures; + +unsigned Texture::loadTexture(const std::string &name) { + std::map::iterator it = textures.find(name); + + if(it != textures.end()) + return it->second; + + pngInfo info; + unsigned texture = pngBind(("tex/" + name).c_str(), PNG_NOMIPMAP, PNG_ALPHA, &info, GL_REPEAT, GL_LINEAR, GL_LINEAR); + + if(texture) { + textures.insert(std::make_pair(name, texture)); + } + + return texture; +} + +} diff --git a/Texture.h b/Texture.h new file mode 100644 index 0000000..fd078f3 --- /dev/null +++ b/Texture.h @@ -0,0 +1,40 @@ +/* + * Texture.h + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#ifndef ZOOM_TEXTURE_H_ +#define ZOOM_TEXTURE_H_ + +#include +#include + +namespace Zoom { + +class Texture { + public: + static unsigned loadTexture(const std::string &name); + + private: + Texture(); + + static std::map textures; +}; + +} + +#endif /* ZOOM_TEXTURE_H_ */ diff --git a/Triangle.h b/Triangle.h index 16b0d73..2b34c3f 100644 --- a/Triangle.h +++ b/Triangle.h @@ -1,7 +1,25 @@ +/* + * Triangle.h + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + #ifndef ZOOM_TRIANGLE_H_ #define ZOOM_TRIANGLE_H_ -#include "gl.h" #include #include @@ -9,36 +27,76 @@ namespace Zoom { class Triangle { public: - Triangle() : c(vmml::vec4f::ONE) { - v[0] = v[1] = v[2] = vmml::vec3f::ZERO; + Triangle() : color(vmml::vec4f::ONE), texture(0) { + vertices[0] = vertices[1] = vertices[2] = vmml::vec3f::ZERO; + normals[0] = normals[1] = normals[2] = vmml::vec3f::ZERO; + texcoords[0] = texcoords[1] = texcoords[2] = vmml::vec2f::ZERO; } - Triangle(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &v3, const vmml::vec4f &c0) : c(c0) { - v[0] = v1; - v[1] = v2; - v[2] = v3; + Triangle(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &v3, const vmml::vec4f &color0) : color(color0), texture(0) { + vertices[0] = v1; + vertices[1] = v2; + vertices[2] = v3; + + normals[0] = normals[1] = normals[2] = vmml::vec3f::ZERO; + texcoords[0] = texcoords[1] = texcoords[2] = vmml::vec2f::ZERO; } - const vmml::vec3f& getVertex(int i) const {return v[i];} - const vmml::vec4f& getColor() const {return c;} + const vmml::vec3f& getVertex(int i) const {return vertices[i];} + vmml::vec3f& getVertex(int i) {return vertices[i];} + void setVertex(int i, vmml::vec3f v) { + vertices[i] = v; + } + + const vmml::vec3f& getNormal(int i) const {return normals[i];} + vmml::vec3f& getNormal(int i) {return normals[i];} + void setNormal(int i, vmml::vec3f n) { + normals[i] = n; + } + + const vmml::vec2f& getTexCoords(int i) const {return texcoords[i];} + vmml::vec2f& getTexCoords(int i) {return texcoords[i];} + void setTexCoords(int i, vmml::vec2f t) { + texcoords[i] = t; + } + + unsigned getTexture() const { + return texture; + } + void setTexture(unsigned tex) { + texture = tex; + } + + const vmml::vec4f& getColor() const {return color;} + vmml::vec4f& getColor() {return color;} + void setColor(vmml::vec4f c) { + color = c; + } - vmml::vec3f getNormal() const { - return v[0].compute_normal(v[1], v[2]); + vmml::vec3f computeNormal() const { + return vertices[0].compute_normal(vertices[1], vertices[2]); } - void transform(const vmml::mat4f &m) { + bool isDegenerate() const { + return (computeNormal().squared_length() == 0); + } + + void transform(const vmml::mat4f &matrix) { for(int i = 0; i < 3; ++i) { - v[i] = m*v[i]; + vertices[i] = matrix*vertices[i]; } } vmml::vec3f getCenter() const { - return (v[0]+v[1]+v[2])/3; + return (vertices[0]+vertices[1]+vertices[2])/3; } private: - vmml::vec3f v[3]; - vmml::vec4f c; + vmml::vec3f vertices[3]; + vmml::vec3f normals[3]; + vmml::vec2f texcoords[3]; + vmml::vec4f color; + unsigned texture; }; } diff --git a/config.h b/config.h index 1c2e879..9af944d 100644 --- a/config.h +++ b/config.h @@ -20,7 +20,7 @@ #ifndef ZOOM_CONFIG_H_ #define ZOOM_CONFIG_H_ -#define MIN_FRAME_DELTA 16 +#define MIN_FRAME_DELTA 10 #define DEFAULT_WIDTH 800 #define DEFAULT_HEIGHT 600 diff --git a/gl.h b/gl.h index fb5face..22e0523 100644 --- a/gl.h +++ b/gl.h @@ -1,5 +1,24 @@ -#ifndef _GL_H_ -#define _GL_H_ +/* + * gl.h + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#ifndef ZOOM_GL_H_ +#define ZOOM_GL_H_ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -9,4 +28,4 @@ #include #include -#endif /* _GL_H_ */ +#endif /* ZOOM_GL_H_ */ diff --git a/levels/level.dtd b/levels/level.dtd new file mode 100644 index 0000000..8ef0604 --- /dev/null +++ b/levels/level.dtd @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/levels/level.xml b/levels/level.xml new file mode 100644 index 0000000..0cbc92f --- /dev/null +++ b/levels/level.xml @@ -0,0 +1,392 @@ + + + + + Test Level + Just a simple test level. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tex/blue.png b/tex/blue.png new file mode 100644 index 0000000..b730875 Binary files /dev/null and b/tex/blue.png differ diff --git a/tex/cursor.png b/tex/cursor.png new file mode 100644 index 0000000..4ee35ca Binary files /dev/null and b/tex/cursor.png differ diff --git a/tex/dark.png b/tex/dark.png new file mode 100644 index 0000000..f87c09f Binary files /dev/null and b/tex/dark.png differ diff --git a/tex/door.png b/tex/door.png new file mode 100644 index 0000000..0706ccd Binary files /dev/null and b/tex/door.png differ diff --git a/tex/fire.png b/tex/fire.png new file mode 100644 index 0000000..4371c34 Binary files /dev/null and b/tex/fire.png differ diff --git a/tex/green.png b/tex/green.png new file mode 100644 index 0000000..cfc6238 Binary files /dev/null and b/tex/green.png differ diff --git a/tex/green2.png b/tex/green2.png new file mode 100644 index 0000000..87c071b Binary files /dev/null and b/tex/green2.png differ diff --git a/tex/light.png b/tex/light.png new file mode 100644 index 0000000..3610a26 Binary files /dev/null and b/tex/light.png differ diff --git a/tex/lightmap.png b/tex/lightmap.png new file mode 100644 index 0000000..76c3b19 Binary files /dev/null and b/tex/lightmap.png differ diff --git a/tex/lightmap2.png b/tex/lightmap2.png new file mode 100644 index 0000000..97a151f Binary files /dev/null and b/tex/lightmap2.png differ diff --git a/tex/medib.png b/tex/medib.png new file mode 100644 index 0000000..00093b4 Binary files /dev/null and b/tex/medib.png differ diff --git a/tex/metallic.png b/tex/metallic.png new file mode 100644 index 0000000..d1177b1 Binary files /dev/null and b/tex/metallic.png differ diff --git a/tex/metallic2.png b/tex/metallic2.png new file mode 100644 index 0000000..4f8977c Binary files /dev/null and b/tex/metallic2.png differ diff --git a/tex/textur.png b/tex/textur.png new file mode 100644 index 0000000..96114d3 Binary files /dev/null and b/tex/textur.png differ diff --git a/tex/wall1.png b/tex/wall1.png new file mode 100644 index 0000000..e620a9b Binary files /dev/null and b/tex/wall1.png differ diff --git a/tex/wall2.png b/tex/wall2.png new file mode 100644 index 0000000..2fb39bd Binary files /dev/null and b/tex/wall2.png differ diff --git a/tex/wall3.png b/tex/wall3.png new file mode 100644 index 0000000..b30ee2a Binary files /dev/null and b/tex/wall3.png differ diff --git a/tex/wall4.png b/tex/wall4.png new file mode 100644 index 0000000..1bec600 Binary files /dev/null and b/tex/wall4.png differ diff --git a/tex/wall5.png b/tex/wall5.png new file mode 100644 index 0000000..a6c6a73 Binary files /dev/null and b/tex/wall5.png differ diff --git a/zoom.cpp b/zoom.cpp index 9535b8a..8f01c1b 100644 --- a/zoom.cpp +++ b/zoom.cpp @@ -1,3 +1,22 @@ +/* + * zoom.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + #include "Game.h" #include "config.h" #include "gl.h" @@ -13,9 +32,8 @@ void resize(int width, int height) { - if(height==0) - { - height=1; + if(height == 0) { + height = 1; } -- cgit v1.2.3