Moved source files to src; sort triangles by texture.
This commit is contained in:
parent
a4fa46a4fd
commit
d9f44af7ae
18 changed files with 68 additions and 45 deletions
164
src/BSPTree.cpp
Normal file
164
src/BSPTree.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* BSPTree.cpp
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "BSPTree.h"
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
vmml::vec3f BSPTree::Plane::intersection(const vmml::vec3f &p, const vmml::vec3f &dir) const {
|
||||
float r = (d - p.dot(normal))/dir.dot(normal);
|
||||
|
||||
return p + r*dir;
|
||||
}
|
||||
|
||||
void BSPTree::Plane::partition(const TriangleRecord &t, std::list<TriangleRecord> *front, std::list<TriangleRecord> *back) const {
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
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(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(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;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
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]))) {
|
||||
vmml::vec3f is1 = intersection(*v[0], *v[1]-*v[0]);
|
||||
vmml::vec3f is2 = intersection(*v[0], *v[2]-*v[0]);
|
||||
|
||||
if(isInFront(*v[0])) {
|
||||
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(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BSPTree::BSPTree(const std::list<TriangleRecord> &triangles) : frontTree(0), backTree(0) {
|
||||
const Triangle *planeT = findNearestTriangle(triangles, findCenter(triangles));
|
||||
|
||||
if(!planeT)
|
||||
return;
|
||||
|
||||
plane = Plane(*planeT);
|
||||
|
||||
std::list<TriangleRecord> front, back;
|
||||
|
||||
for(std::list<TriangleRecord>::const_iterator t = triangles.begin(); t != triangles.end(); ++t) {
|
||||
if(t->triangle.isDegenerate())
|
||||
continue;
|
||||
|
||||
if(plane.contains(t->triangle)) {
|
||||
this->triangles.push_back(*t);
|
||||
continue;
|
||||
}
|
||||
else if(plane.isInFront(t->triangle)) {
|
||||
front.push_back(*t);
|
||||
continue;
|
||||
}
|
||||
else if(plane.isBehind(t->triangle)) {
|
||||
back.push_back(*t);
|
||||
continue;
|
||||
}
|
||||
|
||||
plane.partition(*t, &front, &back);
|
||||
}
|
||||
|
||||
if(!front.empty())
|
||||
frontTree = new BSPTree(front);
|
||||
|
||||
if(!back.empty())
|
||||
backTree = new BSPTree(back);
|
||||
}
|
||||
|
||||
BSPTree& BSPTree::operator=(const BSPTree &tree) {
|
||||
if(frontTree) {
|
||||
delete frontTree;
|
||||
frontTree = 0;
|
||||
}
|
||||
|
||||
if(backTree) {
|
||||
delete backTree;
|
||||
backTree = 0;
|
||||
}
|
||||
|
||||
plane = tree.plane;
|
||||
triangles = tree.triangles;
|
||||
|
||||
if(tree.frontTree)
|
||||
frontTree = new BSPTree(*tree.frontTree);
|
||||
|
||||
if(tree.backTree)
|
||||
backTree = new BSPTree(*tree.backTree);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
vmml::vec3f BSPTree::findCenter(const std::list<TriangleRecord> &triangles) {
|
||||
vmml::vec3f v;
|
||||
|
||||
for(std::list<TriangleRecord>::const_iterator t = triangles.begin(); t != triangles.end(); ++t) {
|
||||
v += t->triangle.getCenter();
|
||||
}
|
||||
|
||||
return v/triangles.size();
|
||||
}
|
||||
|
||||
const Triangle* BSPTree::findNearestTriangle(const std::list<TriangleRecord> &triangles, const vmml::vec3f &v) {
|
||||
const Triangle *current = 0;
|
||||
float distanceSq;
|
||||
|
||||
for(std::list<TriangleRecord>::const_iterator t = triangles.begin(); t != triangles.end(); ++t) {
|
||||
if(t->triangle.isDegenerate())
|
||||
continue;
|
||||
|
||||
float d = t->triangle.getCenter().squared_distance(v);
|
||||
|
||||
if(!current || d < distanceSq) {
|
||||
current = &t->triangle;
|
||||
distanceSq = d;
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
}
|
177
src/BSPTree.h
Normal file
177
src/BSPTree.h
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* BSPTree.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_BSPTREE_H_
|
||||
#define ZOOM_BSPTREE_H_
|
||||
|
||||
#include "Triangle.h"
|
||||
#include <list>
|
||||
#include <cmath>
|
||||
|
||||
#include <vmmlib/vector.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
class BSPTree {
|
||||
public:
|
||||
class TriangleData {
|
||||
protected:
|
||||
TriangleData() {}
|
||||
|
||||
public:
|
||||
virtual ~TriangleData() {}
|
||||
};
|
||||
|
||||
struct TriangleRecord {
|
||||
public:
|
||||
TriangleRecord(Triangle triangle0, boost::shared_ptr<TriangleData> data0)
|
||||
: triangle(triangle0), data(data0) {}
|
||||
TriangleRecord(Triangle triangle0) : triangle(triangle0) {}
|
||||
TriangleRecord() {}
|
||||
|
||||
Triangle triangle;
|
||||
boost::shared_ptr<TriangleData> 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.computeNormal()), d(t.getVertex(0).dot(normal)) {}
|
||||
|
||||
bool contains(const vmml::vec3f &v) const {
|
||||
return (fabsf(normal.dot(v) - d) < 1E-6);
|
||||
}
|
||||
|
||||
bool isBehind(const vmml::vec3f &v) const {
|
||||
return (normal.dot(v) - d) < 0;
|
||||
}
|
||||
|
||||
bool isInFront(const vmml::vec3f &v) const {
|
||||
return (normal.dot(v) - d) > 0;
|
||||
}
|
||||
|
||||
|
||||
bool contains(const Triangle &t) const {
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
if(!contains(t.getVertex(i)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isBehind(const Triangle &t) const {
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
if(!isBehind(t.getVertex(i)) && !contains(t.getVertex(i)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isInFront(const Triangle &t) const {
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
if(!isInFront(t.getVertex(i)) && !contains(t.getVertex(i)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const vmml::vec3f& getNormal() const {
|
||||
return normal;
|
||||
}
|
||||
|
||||
vmml::vec3f intersection(const vmml::vec3f &p, const vmml::vec3f &dir) const;
|
||||
void partition(const TriangleRecord &t, std::list<TriangleRecord> *front, std::list<TriangleRecord> *back) const;
|
||||
|
||||
private:
|
||||
vmml::vec3f normal;
|
||||
float d;
|
||||
};
|
||||
|
||||
public:
|
||||
BSPTree(const std::list<TriangleRecord> &triangles);
|
||||
|
||||
BSPTree(const BSPTree &tree) : frontTree(0), backTree(0) {
|
||||
*this = tree;
|
||||
}
|
||||
|
||||
virtual ~BSPTree() {
|
||||
if(frontTree)
|
||||
delete frontTree;
|
||||
|
||||
if(backTree)
|
||||
delete backTree;
|
||||
}
|
||||
|
||||
BSPTree& operator=(const BSPTree &tree);
|
||||
|
||||
template<typename T>
|
||||
void visit(const T& visitor, const vmml::vec3f &p) const {
|
||||
doVisit<const T>(visitor, p);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void visit(T& visitor, const vmml::vec3f &p) const {
|
||||
doVisit(visitor, p);
|
||||
}
|
||||
|
||||
private:
|
||||
Plane plane;
|
||||
std::list<TriangleRecord> triangles;
|
||||
BSPTree *frontTree, *backTree;
|
||||
|
||||
template<typename T>
|
||||
void doVisit(T& visitor, const vmml::vec3f &p) const {
|
||||
if(plane.isBehind(p)) {
|
||||
if(frontTree)
|
||||
frontTree->visit(visitor, p);
|
||||
|
||||
for(std::list<TriangleRecord>::const_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<TriangleRecord>::const_iterator t = triangles.begin(); t != triangles.end(); ++t) {
|
||||
visitor(*t);
|
||||
}
|
||||
|
||||
if(frontTree)
|
||||
frontTree->visit(visitor, p);
|
||||
}
|
||||
}
|
||||
|
||||
static vmml::vec3f findCenter(const std::list<TriangleRecord> &triangles);
|
||||
static const Triangle* findNearestTriangle(const std::list<TriangleRecord> &triangles, const vmml::vec3f &v);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ZOOM_BSPTREE_H_ */
|
13
src/CMakeLists.txt
Normal file
13
src/CMakeLists.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
add_executable(zoom
|
||||
BSPTree.cpp BSPTree.h
|
||||
Game.cpp Game.h
|
||||
config.h
|
||||
gl.h
|
||||
Level.cpp Level.h
|
||||
Renderer.cpp Renderer.h
|
||||
Shader.cpp Shader.h
|
||||
Texture.cpp Texture.h
|
||||
Triangle.h
|
||||
zoom.cpp
|
||||
)
|
||||
target_link_libraries(zoom ${Boost_LIBRARIES} ${OPENGL_LIBRARIES} ${GLEW_LIBRARY} ${GLPNG_LIBRARY} ${LIBXML2_LIBRARIES})
|
129
src/Game.cpp
Normal file
129
src/Game.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Game.cpp
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Game.h"
|
||||
#include "BSPTree.h"
|
||||
#include "Level.h"
|
||||
#include "Shader.h"
|
||||
#include "Triangle.h"
|
||||
#include "gl.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
Game::Game(bool multisample) : angle(0), lightPos(0) {
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClearDepth(1.0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
//glEnable(GL_BLEND);
|
||||
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
#ifndef _WIN32
|
||||
if(multisample)
|
||||
glEnable(GL_MULTISAMPLE_ARB);
|
||||
#endif
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, vmml::vec4f::ZERO.array);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, vmml::vec4f::ONE.array);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, vmml::vec4f::ONE.array);
|
||||
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0);
|
||||
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.3);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vmml::vec4f::ONE.array);
|
||||
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 128);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
Shader::loadProgram("default.vert", "default.frag");
|
||||
|
||||
loadLevel("level.xml");
|
||||
triangles.insert(triangles.end(), level->getRooms().front().walls.begin(), level->getRooms().front().walls.end());
|
||||
std::sort(triangles.begin(), triangles.end(), Renderer::TextureSorter());
|
||||
}
|
||||
|
||||
bool Game::loadLevel(const std::string &name) {
|
||||
level = Level::loadLevel(name);
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
void Game::run(int delta) {
|
||||
angle += delta*0.01;
|
||||
|
||||
if(angle >= 360)
|
||||
angle -= 360;
|
||||
|
||||
lightPos += delta;
|
||||
lightPos %= 24000;
|
||||
}
|
||||
|
||||
void Game::render() {
|
||||
int i;
|
||||
float light[] = {0, 0, 0, 1};
|
||||
|
||||
if(lightPos < 12000) i = lightPos;
|
||||
else i = 24000 - lightPos;
|
||||
|
||||
if(i < 4000) {
|
||||
light[0] = 0.0;
|
||||
light[2] = -i * 0.001;
|
||||
}
|
||||
else if(i < 8000) {
|
||||
light[0] = (i-4000) * 0.001;
|
||||
light[2] = -4.0;
|
||||
}
|
||||
else if(i < 12000) {
|
||||
light[0] = 4.0;
|
||||
light[2] = -4.0 - (i-8000) * 0.001;
|
||||
}
|
||||
else {
|
||||
light[0] = 4.0;
|
||||
light[2] = -8.0;
|
||||
}
|
||||
|
||||
/*std::vector<BSPTree::TriangleRecord> triangles(level->getRooms().front().walls.begin(),
|
||||
level->getRooms().front().walls.end());
|
||||
std::sort(triangles.begin(), triangles.end(), Renderer::TextureSorter());*/
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(15, 1, 2, 1);
|
||||
/*glRotatef(5*angle, 0, -1, 2);
|
||||
glRotatef(7*angle, 2, -1, 0);
|
||||
glRotatef(11*angle, 2, -1, 2);*/
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light);
|
||||
//renderer.render(std::list<BSPTree::TriangleRecord>(triangles.begin(), triangles.end()));
|
||||
renderer.render(triangles);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
}
|
53
src/Game.h
Normal file
53
src/Game.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Game.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_GAME_H_
|
||||
#define ZOOM_GAME_H_
|
||||
|
||||
#include "Renderer.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <string>
|
||||
|
||||
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> level;
|
||||
std::vector<BSPTree::TriangleRecord> triangles;
|
||||
|
||||
float angle;
|
||||
int lightPos;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ZOOM_GAME_H_ */
|
260
src/Level.cpp
Normal file
260
src/Level.cpp
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Level.cpp
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Level.h"
|
||||
#include "Texture.h"
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/valid.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
boost::shared_ptr<Level> Level::loadLevel(const std::string &filename) {
|
||||
boost::shared_ptr<Level> 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<Level>(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<Room>::iterator room = level->rooms.begin(); room != level->rooms.end(); ++room) {
|
||||
for(std::list<BSPTree::TriangleRecord>::iterator wall = room->walls.begin(); wall != room->walls.end(); ++wall) {
|
||||
boost::shared_ptr<WallData> wallData = boost::dynamic_pointer_cast<WallData>(wall->data);
|
||||
|
||||
if(!wallData->texture.empty()) {
|
||||
std::map<std::string, unsigned>::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> 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;
|
||||
}
|
||||
|
||||
}
|
74
src/Level.h
Normal file
74
src/Level.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Level.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_LEVEL_H_
|
||||
#define ZOOM_LEVEL_H_
|
||||
|
||||
#include "BSPTree.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <libxml/parser.h>
|
||||
#include <vmmlib/vector.hpp>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
class Level {
|
||||
public:
|
||||
static boost::shared_ptr<Level> loadLevel(const std::string &filename);
|
||||
|
||||
struct WallData : public BSPTree::TriangleData {
|
||||
std::string texture;
|
||||
};
|
||||
|
||||
struct Room {
|
||||
std::string id;
|
||||
std::list<BSPTree::TriangleRecord> walls;
|
||||
};
|
||||
|
||||
const std::list<Room> &getRooms() const {
|
||||
return rooms;
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<Room> rooms;
|
||||
std::map<std::string, unsigned> 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_ */
|
69
src/Renderer.cpp
Normal file
69
src/Renderer.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Renderer.cpp
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Renderer.h"
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
void Renderer::render(const BSPTree &tree) {
|
||||
vmml::mat4f transform, inverseTransform;
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, transform.array);
|
||||
|
||||
transform.inverse(inverseTransform);
|
||||
|
||||
vmml::vec3f viewPoint = inverseTransform*vmml::vec3f::ZERO;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
tree.visit(renderVisitor, viewPoint);
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
void Renderer::renderTriangle(const Triangle &t) {
|
||||
glColor4fv(t.getColor().array);
|
||||
|
||||
if(t.getTexture() != activeTexture) {
|
||||
glEnd();
|
||||
useTexture(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);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::useTexture(unsigned texture) {
|
||||
if(texture) {
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
if(activeTexture) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
else {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
activeTexture = texture;
|
||||
}
|
||||
|
||||
}
|
78
src/Renderer.h
Normal file
78
src/Renderer.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Renderer.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_RENDERER_H_
|
||||
#define ZOOM_RENDERER_H_
|
||||
|
||||
#include "BSPTree.h"
|
||||
#include "gl.h"
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer() : activeTexture(0), renderVisitor(this) {}
|
||||
|
||||
void render(const BSPTree &tree);
|
||||
|
||||
template <typename T>
|
||||
void render(const T &triangles) {
|
||||
typename T::const_iterator t = triangles.begin();
|
||||
if(t == triangles.end())
|
||||
return;
|
||||
|
||||
useTexture(t->triangle.getTexture());
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(; t != triangles.end(); ++t) {
|
||||
renderTriangle(t->triangle);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
struct TextureSorter {
|
||||
bool operator() (const BSPTree::TriangleRecord &t1, const BSPTree::TriangleRecord &t2) {
|
||||
return (t1.triangle.getTexture() < t2.triangle.getTexture());
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
void renderTriangle(const Triangle &t);
|
||||
void useTexture(unsigned texture);
|
||||
|
||||
class RenderVisitor {
|
||||
public:
|
||||
RenderVisitor(Renderer *renderer0) : renderer(renderer0) {}
|
||||
|
||||
void operator() (const BSPTree::TriangleRecord &t) const {
|
||||
renderer->renderTriangle(t.triangle);
|
||||
}
|
||||
|
||||
private:
|
||||
Renderer *renderer;
|
||||
};
|
||||
|
||||
unsigned activeTexture;
|
||||
|
||||
const RenderVisitor renderVisitor;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ZOOM_RENDERER_H_ */
|
95
src/Shader.cpp
Normal file
95
src/Shader.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Shader.cpp
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Shader.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <boost/scoped_array.hpp>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
bool Shader::loadProgram(const std::string &vertexShader, const std::string &fragmentShader) {
|
||||
GLhandleARB program, vs = 0, fs = 0;
|
||||
|
||||
if(!vertexShader.empty())
|
||||
vs = loadShader(vertexShader, GL_VERTEX_SHADER_ARB);
|
||||
|
||||
if(!fragmentShader.empty())
|
||||
fs = loadShader(fragmentShader, GL_FRAGMENT_SHADER_ARB);
|
||||
|
||||
program = glCreateProgramObjectARB();
|
||||
|
||||
if(vs)
|
||||
glAttachObjectARB(program, vs);
|
||||
|
||||
if(fs)
|
||||
glAttachObjectARB(program, fs);
|
||||
|
||||
glLinkProgramARB(program);
|
||||
printInfoLog(program);
|
||||
|
||||
glUseProgramObjectARB(program);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLhandleARB Shader::loadShader(const std::string &name, GLenum type) {
|
||||
std::vector<std::string> lines;
|
||||
std::ifstream file(("shader/" + name).c_str(), std::ios_base::in);
|
||||
if(!file.good())
|
||||
throw std::ios::failure("Can't read file '" + name + "'");
|
||||
|
||||
while(file.good() && !file.eof()) {
|
||||
std::string line;
|
||||
std::getline(file, line);
|
||||
|
||||
if(!line.empty())
|
||||
lines.push_back(line);
|
||||
}
|
||||
|
||||
boost::scoped_array<const char *> strings(new const char*[lines.size()]);
|
||||
for(std::size_t i = 0; i < lines.size(); ++i) {
|
||||
strings[i] = lines[i].c_str();
|
||||
}
|
||||
|
||||
GLhandleARB shader = glCreateShaderObjectARB(type);
|
||||
glShaderSourceARB(shader, lines.size(), strings.get(), 0);
|
||||
glCompileShaderARB(shader);
|
||||
printInfoLog(shader);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void Shader::printInfoLog(GLhandleARB obj) {
|
||||
int length = 0;
|
||||
|
||||
glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
|
||||
|
||||
if(length > 0) {
|
||||
boost::scoped_array<char> log(new char[length]);
|
||||
|
||||
int foo;
|
||||
glGetInfoLogARB(obj, length, &foo, log.get());
|
||||
std::cerr << log.get() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
41
src/Shader.h
Normal file
41
src/Shader.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Shader.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_SHADER_H_
|
||||
#define ZOOM_SHADER_H_
|
||||
|
||||
#include "gl.h"
|
||||
#include <string>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
static bool loadProgram(const std::string &vertexShader, const std::string &fragmentShader);
|
||||
|
||||
private:
|
||||
Shader();
|
||||
|
||||
static GLhandleARB loadShader(const std::string &name, GLenum type);
|
||||
static void printInfoLog(GLhandleARB obj);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ZOOM_SHADER_H_ */
|
44
src/Texture.cpp
Normal file
44
src/Texture.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Texture.cpp
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Texture.h"
|
||||
#include "gl.h"
|
||||
#include <GL/glpng.h>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
std::map<std::string, unsigned> Texture::textures;
|
||||
|
||||
unsigned Texture::loadTexture(const std::string &name) {
|
||||
std::map<std::string, unsigned>::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;
|
||||
}
|
||||
|
||||
}
|
40
src/Texture.h
Normal file
40
src/Texture.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Texture.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_TEXTURE_H_
|
||||
#define ZOOM_TEXTURE_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
static unsigned loadTexture(const std::string &name);
|
||||
|
||||
private:
|
||||
Texture();
|
||||
|
||||
static std::map<std::string, unsigned> textures;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ZOOM_TEXTURE_H_ */
|
105
src/Triangle.h
Normal file
105
src/Triangle.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Triangle.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_TRIANGLE_H_
|
||||
#define ZOOM_TRIANGLE_H_
|
||||
|
||||
#include <vmmlib/vector.hpp>
|
||||
#include <vmmlib/matrix.hpp>
|
||||
|
||||
namespace Zoom {
|
||||
|
||||
class Triangle {
|
||||
public:
|
||||
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 &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 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 computeNormal() const {
|
||||
return vertices[0].compute_normal(vertices[1], vertices[2]);
|
||||
}
|
||||
|
||||
bool isDegenerate() const {
|
||||
return (computeNormal().squared_length() == 0);
|
||||
}
|
||||
|
||||
void transform(const vmml::mat4f &matrix) {
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
vertices[i] = matrix*vertices[i];
|
||||
}
|
||||
}
|
||||
|
||||
vmml::vec3f getCenter() const {
|
||||
return (vertices[0]+vertices[1]+vertices[2])/3;
|
||||
}
|
||||
|
||||
private:
|
||||
vmml::vec3f vertices[3];
|
||||
vmml::vec3f normals[3];
|
||||
vmml::vec2f texcoords[3];
|
||||
vmml::vec4f color;
|
||||
unsigned texture;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /*ZOOM_TRIANGLE_H_*/
|
||||
|
27
src/config.h
Normal file
27
src/config.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* config.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_CONFIG_H_
|
||||
#define ZOOM_CONFIG_H_
|
||||
|
||||
#define MIN_FRAME_DELTA 10
|
||||
#define DEFAULT_WIDTH 800
|
||||
#define DEFAULT_HEIGHT 600
|
||||
|
||||
#endif /* ZOOM_CONFIG_H_ */
|
32
src/gl.h
Normal file
32
src/gl.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* gl.h
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ZOOM_GL_H_
|
||||
#define ZOOM_GL_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
#endif /* ZOOM_GL_H_ */
|
398
src/zoom.cpp
Normal file
398
src/zoom.cpp
Normal file
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* zoom.cpp
|
||||
*
|
||||
* Copyright (C) 2009 Matthias Schiffer <matthias@gamezock.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Game.h"
|
||||
#include "config.h"
|
||||
#include "gl.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
#include <iostream>
|
||||
#include <X11/X.h>
|
||||
#include <GL/glx.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void resize(int width, int height)
|
||||
{
|
||||
if(height == 0) {
|
||||
height = 1;
|
||||
}
|
||||
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(50.0f, (GLfloat)width/(GLfloat)height, 0.1, 1000);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC);
|
||||
void WGLUninit(HWND hWnd, HDC hDC, HGLRC hRC);
|
||||
LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
bool WGLInit(HINSTANCE hInstance, HWND *hWnd, HDC *hDC, HGLRC *hRC) {
|
||||
WNDCLASS wc;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
wc.lpfnWndProc = (WNDPROC)wndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = 0;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = "3D";
|
||||
|
||||
if (!RegisterClass(&wc)) {
|
||||
MessageBox(0, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
|
||||
return false; // Exit And Return FALSE
|
||||
}
|
||||
|
||||
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
DWORD dwStyle = WS_OVERLAPPEDWINDOW;
|
||||
|
||||
RECT windowRect;
|
||||
windowRect.left = 0;
|
||||
windowRect.right = DEFAULT_WIDTH;
|
||||
windowRect.top = 0;
|
||||
windowRect.bottom = DEFAULT_HEIGHT;
|
||||
|
||||
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
|
||||
|
||||
*hWnd = CreateWindowEx(dwExStyle, "3D" /* Class Name */, "3D" /* Title*/, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle,
|
||||
0, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, 0, 0, hInstance, 0);
|
||||
if(!*hWnd) {
|
||||
MessageBox(0, "Window Creation Error.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
static PIXELFORMATDESCRIPTOR pfd = {
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
|
||||
1, // Version Number
|
||||
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
||||
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
|
||||
PFD_DOUBLEBUFFER, // Must Support Double Buffering
|
||||
PFD_TYPE_RGBA, // Request An RGBA Format
|
||||
16, // Select Our Color Depth
|
||||
0, 0, 0, 0, 0, 0, // Color Bits Ignored
|
||||
0, // No Alpha Buffer
|
||||
0, // Shift Bit Ignored
|
||||
0, // No Accumulation Buffer
|
||||
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||
16, // 16Bit Z-Buffer (Depth Buffer)
|
||||
0, // No Stencil Buffer
|
||||
0, // No Auxiliary Buffer
|
||||
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||
0, // Reserved
|
||||
0, 0, 0 // Layer Masks Ignored
|
||||
};
|
||||
|
||||
*hDC=GetDC(*hWnd);
|
||||
if (!*hDC) {
|
||||
WGLUninit(*hWnd, 0, 0);
|
||||
MessageBox(0, "Can't Create A GL Device Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint pixelFormat = ChoosePixelFormat(*hDC, &pfd);
|
||||
if(!pixelFormat) {
|
||||
WGLUninit(*hWnd, *hDC, 0);
|
||||
MessageBox(0, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!SetPixelFormat(*hDC, pixelFormat, &pfd)) {
|
||||
WGLUninit(*hWnd, *hDC, 0);
|
||||
MessageBox(0, "Can't Set The PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
*hRC=wglCreateContext(*hDC);
|
||||
if(!*hRC) {
|
||||
WGLUninit(*hWnd, *hDC, 0);
|
||||
MessageBox(0, "Can't Create A GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!wglMakeCurrent(*hDC, *hRC)) {
|
||||
WGLUninit(*hWnd, *hDC, *hRC);
|
||||
MessageBox(0, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
ShowWindow(*hWnd, SW_SHOW);
|
||||
SetForegroundWindow(*hWnd);
|
||||
SetFocus(*hWnd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WGLUninit(HWND hWnd, HDC hDC, HGLRC hRC) {
|
||||
wglMakeCurrent(0, 0);
|
||||
|
||||
if(hRC)
|
||||
wglDeleteContext(hRC);
|
||||
|
||||
if(hDC)
|
||||
ReleaseDC(hWnd, hDC);
|
||||
|
||||
if(hWnd)
|
||||
DestroyWindow(hWnd);
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
||||
HWND hWnd = 0;
|
||||
HDC hDC = 0;
|
||||
HGLRC hRC = 0;
|
||||
|
||||
if(!WGLInit(hInstance, &hWnd, &hDC, &hRC)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
glewInit();
|
||||
|
||||
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
bool running = true;
|
||||
MSG msg;
|
||||
|
||||
while(running)
|
||||
{
|
||||
unsigned long delta = 0;
|
||||
unsigned long ticks = GetTickCount();
|
||||
|
||||
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if(msg.message == WM_QUIT)
|
||||
{
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
else // If Not, Deal With Window Messages
|
||||
{
|
||||
TranslateMessage(&msg); // Translate The Message
|
||||
DispatchMessage(&msg); // Dispatch The Message
|
||||
}
|
||||
}
|
||||
|
||||
delta = GetTickCount()-ticks;
|
||||
|
||||
if(delta < MIN_FRAME_DELTA) {
|
||||
Sleep(MIN_FRAME_DELTA - delta);
|
||||
delta = GetTickCount()-ticks;
|
||||
}
|
||||
|
||||
ticks += delta;
|
||||
|
||||
static DisplayClass render;
|
||||
render.renderScene(delta);
|
||||
SwapBuffers(hDC);
|
||||
}
|
||||
|
||||
WGLUninit(hWnd, hDC, hRC);
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
switch(uMsg) {
|
||||
case WM_CLOSE:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
|
||||
case WM_SIZE:
|
||||
resize(LOWORD(lParam), HIWORD(lParam));
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, bool *multisample) {
|
||||
static const int msAttributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_X_RENDERABLE, True,
|
||||
GLX_DOUBLEBUFFER, True,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
GLX_SAMPLE_BUFFERS, 1,
|
||||
GLX_SAMPLES, 4,
|
||||
None};
|
||||
|
||||
static const int attributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_X_RENDERABLE, True,
|
||||
GLX_DOUBLEBUFFER, True,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
None};
|
||||
|
||||
bool ok = false;
|
||||
*multisample = true;
|
||||
|
||||
int nElements;
|
||||
GLXFBConfig *fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), msAttributeList, &nElements);
|
||||
if(!fbConfig || !nElements) {
|
||||
if(fbConfig) {
|
||||
XFree(fbConfig);
|
||||
}
|
||||
|
||||
*multisample = false;
|
||||
fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), attributeList, &nElements);
|
||||
}
|
||||
|
||||
if(fbConfig && nElements) {
|
||||
XVisualInfo *vi = glXGetVisualFromFBConfig(disp, *fbConfig);
|
||||
|
||||
if(vi) {
|
||||
Colormap cmap = XCreateColormap(disp, RootWindow(disp, vi->screen), vi->visual, AllocNone);
|
||||
XSetWindowAttributes swa;
|
||||
swa.colormap = cmap;
|
||||
swa.border_pixel = 0;
|
||||
swa.event_mask = StructureNotifyMask/* | PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask*/;
|
||||
|
||||
*wnd = XCreateWindow(disp, RootWindow(disp, vi->screen), 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, 0, vi->depth, InputOutput,
|
||||
vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa);
|
||||
|
||||
XClassHint chint;
|
||||
chint.res_name = const_cast<char*>("3D");
|
||||
chint.res_class = const_cast<char*>("3d");
|
||||
XSetClassHint(disp, *wnd, &chint);
|
||||
|
||||
char *str = const_cast<char*>("3D");
|
||||
XTextProperty name;
|
||||
if(XStringListToTextProperty(&str, 1, &name) != 0)
|
||||
{
|
||||
XSetWMName(disp, *wnd, &name);
|
||||
XFree(name.value);
|
||||
}
|
||||
|
||||
XSetWMProtocols(disp, *wnd, &windele, 1);
|
||||
|
||||
XMapWindow(disp, *wnd);
|
||||
|
||||
*gc = glXCreateContext(disp, vi, NULL, True);
|
||||
|
||||
glXMakeCurrent(disp, *wnd, *gc);
|
||||
|
||||
ok = true;
|
||||
|
||||
XFree(vi);
|
||||
}
|
||||
}
|
||||
|
||||
if(fbConfig)
|
||||
XFree(fbConfig);
|
||||
|
||||
XSync(disp, 0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
int main() {
|
||||
Display *disp = XOpenDisplay(0);
|
||||
Atom windele = XInternAtom(disp, "WM_DELETE_WINDOW", False);
|
||||
Window wnd;
|
||||
GLXContext gc;
|
||||
|
||||
bool multisample;
|
||||
if(!GLXinit(disp, windele, &wnd, &gc, &multisample))
|
||||
return 1;
|
||||
|
||||
glewInit();
|
||||
|
||||
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
Zoom::Game game(multisample);
|
||||
|
||||
GLint samples;
|
||||
glGetIntegerv(GL_SAMPLES, &samples);
|
||||
std::cerr << "Using " << samples << " samples" << std::endl;
|
||||
|
||||
bool running = true;
|
||||
|
||||
unsigned long delta = 0;
|
||||
unsigned long frames = 0, tocks = 0;
|
||||
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
unsigned long ticks = tv.tv_usec;
|
||||
|
||||
while(running) {
|
||||
while(XPending(disp)) {
|
||||
XEvent event;
|
||||
XNextEvent(disp, &event);
|
||||
switch(event.type) {
|
||||
case ConfigureNotify:
|
||||
resize(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
|
||||
case ClientMessage:
|
||||
if(static_cast<Atom>(event.xclient.data.l[0]) == windele)
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!running) break;
|
||||
|
||||
game.run(delta);
|
||||
|
||||
game.render();
|
||||
glXSwapBuffers(disp, wnd);
|
||||
XSync(disp, 0);
|
||||
|
||||
long slept = 0;
|
||||
gettimeofday(&tv, NULL);
|
||||
delta = ((tv.tv_usec + 1000000 - ticks)%1000000)/1000;
|
||||
|
||||
if(delta < MIN_FRAME_DELTA) {
|
||||
usleep((MIN_FRAME_DELTA-delta)*1000);
|
||||
slept += (MIN_FRAME_DELTA-delta);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
delta = ((tv.tv_usec + 1000000 - ticks)%1000000)/1000;
|
||||
}
|
||||
|
||||
ticks = (ticks + delta*1000) % 1000000;
|
||||
|
||||
frames++;
|
||||
tocks += delta*1000;
|
||||
if(tocks > 1000000) {
|
||||
std::cerr << frames << " fps; slept a total of " << slept << " ms" << std::endl;
|
||||
frames = 0;
|
||||
tocks -= 1000000;
|
||||
slept = 0;
|
||||
}
|
||||
}
|
||||
|
||||
XDestroyWindow(disp, wnd);
|
||||
glXDestroyContext(disp, gc);
|
||||
XCloseDisplay(disp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
Reference in a new issue