Moved Plane to MathUtil; some other tweaks

This commit is contained in:
Matthias Schiffer 2009-12-17 02:14:32 +01:00
parent ea08fea654
commit bc797d4c8b
7 changed files with 109 additions and 89 deletions

View file

@ -21,20 +21,15 @@
namespace Zoom { 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::partition(const TriangleRecord &t, std::list<TriangleRecord> *front, std::list<TriangleRecord> *back) const {
}
void BSPTree::Plane::partition(const TriangleRecord &t, std::list<TriangleRecord> *front, std::list<TriangleRecord> *back) const {
for(int i = 0; i < 3; ++i) { for(int i = 0; i < 3; ++i) {
if(contains(t.triangle.getVertex(i))) { if(plane.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)}; 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]); vmml::vec3f is = plane.intersection(*v[1], *v[2]-*v[1]);
if(isInFront(*v[1])) { if(plane.isInFront(*v[1])) {
front->push_back(TriangleRecord(Triangle(*v[0], *v[1], is, t.triangle.getColor()), t.data)); 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)); back->push_back(TriangleRecord(Triangle(*v[0], is, *v[2], t.triangle.getColor()), t.data));
} }
@ -50,12 +45,12 @@ void BSPTree::Plane::partition(const TriangleRecord &t, std::list<TriangleRecord
for(int i = 0; i < 3; ++i) { 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)}; 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])) if((plane.isInFront(*v[0]) && plane.isBehind(*v[1]) && plane.isBehind(*v[2]))
|| (isBehind(*v[0]) && isInFront(*v[1]) && isInFront(*v[2]))) { || (plane.isBehind(*v[0]) && plane.isInFront(*v[1]) && plane.isInFront(*v[2]))) {
vmml::vec3f is1 = intersection(*v[0], *v[1]-*v[0]); vmml::vec3f is1 = plane.intersection(*v[0], *v[1]-*v[0]);
vmml::vec3f is2 = intersection(*v[0], *v[2]-*v[0]); vmml::vec3f is2 = plane.intersection(*v[0], *v[2]-*v[0]);
if(isInFront(*v[0])) { if(plane.isInFront(*v[0])) {
front->push_back(TriangleRecord(Triangle(*v[0], is1, is2, t.triangle.getColor()), t.data)); 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(is1, *v[1], is2, t.triangle.getColor()), t.data));
back->push_back(TriangleRecord(Triangle(*v[1], *v[2], is2, t.triangle.getColor()), t.data)); back->push_back(TriangleRecord(Triangle(*v[1], *v[2], is2, t.triangle.getColor()), t.data));
@ -78,7 +73,7 @@ BSPTree::BSPTree(const std::list<TriangleRecord> &triangles) : frontTree(0), bac
if(!planeT) if(!planeT)
return; return;
plane = Plane(*planeT); plane = MathUtil::Plane(*planeT);
std::list<TriangleRecord> front, back; std::list<TriangleRecord> front, back;
@ -99,7 +94,7 @@ BSPTree::BSPTree(const std::list<TriangleRecord> &triangles) : frontTree(0), bac
continue; continue;
} }
plane.partition(*t, &front, &back); partition(*t, &front, &back);
} }
if(!front.empty()) if(!front.empty())

View file

@ -21,6 +21,8 @@
#define ZOOM_BSPTREE_H_ #define ZOOM_BSPTREE_H_
#include "Triangle.h" #include "Triangle.h"
#include "MathUtil.h"
#include <list> #include <list>
#include <cmath> #include <cmath>
@ -50,66 +52,6 @@ class BSPTree {
boost::shared_ptr<TriangleData> data; 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: public:
BSPTree(const std::list<TriangleRecord> &triangles); BSPTree(const std::list<TriangleRecord> &triangles);
@ -138,7 +80,7 @@ class BSPTree {
} }
private: private:
Plane plane; MathUtil::Plane plane;
std::list<TriangleRecord> triangles; std::list<TriangleRecord> triangles;
BSPTree *frontTree, *backTree; BSPTree *frontTree, *backTree;
@ -168,6 +110,8 @@ class BSPTree {
} }
} }
void partition(const TriangleRecord &t, std::list<TriangleRecord> *front, std::list<TriangleRecord> *back) const;
static vmml::vec3f findCenter(const std::list<TriangleRecord> &triangles); static vmml::vec3f findCenter(const std::list<TriangleRecord> &triangles);
static const Triangle* findNearestTriangle(const std::list<TriangleRecord> &triangles, const vmml::vec3f &v); static const Triangle* findNearestTriangle(const std::list<TriangleRecord> &triangles, const vmml::vec3f &v);
}; };

View file

@ -30,7 +30,7 @@
namespace Zoom { namespace Zoom {
Game::Game(bool multisample) : playerPos(vmml::vec3f::ZERO), playerRot(vmml::mat4f::IDENTITY), Game::Game(bool multisample) : playerPos(vmml::vec3f::ZERO), playerRot(vmml::mat4f::IDENTITY),
input(NONE), lightPos(0) { input(0), lightPos(0) {
glClearColor(0.0, 0.0, 0.0, 1.0); glClearColor(0.0, 0.0, 0.0, 1.0);
glClearDepth(1.0); glClearDepth(1.0);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
@ -80,6 +80,8 @@ void Game::run(int delta) {
lightPos += delta; lightPos += delta;
lightPos %= 24000; lightPos %= 24000;
playerRot.rotate_y(delta*M_PI/180/40);
if(input & FORWARD) { if(input & FORWARD) {
playerPos -= playerRot*vmml::vec3f::UNIT_Z*0.01*delta; playerPos -= playerRot*vmml::vec3f::UNIT_Z*0.01*delta;
} }
@ -127,7 +129,20 @@ void Game::render() {
glLoadMatrixf(inverse.array); glLoadMatrixf(inverse.array);
glLightfv(GL_LIGHT0, GL_POSITION, light); glLightfv(GL_LIGHT0, GL_POSITION, light);
renderer.render(triangles); renderer.render(triangles);
/*glBegin(GL_LINES);
glColor3f(0, 0, 1);
glVertex4f(-1, -0.5, -2, 1);
glVertex4f(1, -0.5, -2, 1);
glColor3f(1, 0, 0);
glVertex4f(0, -0.5, -2, 1);
glVertex4f(1, 0, 0, 0);
glEnd();*/
} }
} }

View file

@ -32,7 +32,6 @@ class Triangle;
class Game { class Game {
public: public:
enum Input { enum Input {
NONE = 0,
FORWARD = (1 << 0), FORWARD = (1 << 0),
BACKWARD = (1 << 1), BACKWARD = (1 << 1),
LEFT = (1 << 2), LEFT = (1 << 2),
@ -44,7 +43,7 @@ class Game {
bool loadLevel(const std::string &name); bool loadLevel(const std::string &name);
void setInput(unsigned input) { void setInput(unsigned input) {
this->input = static_cast<Input>(input); this->input = input;
} }
void run(int delta); void run(int delta);
@ -59,7 +58,7 @@ class Game {
vmml::vec3f playerPos; vmml::vec3f playerPos;
vmml::mat4f playerRot; vmml::mat4f playerRot;
Input input; unsigned input;
int lightPos; int lightPos;
}; };

View file

@ -22,14 +22,23 @@
namespace Zoom { namespace Zoom {
const float MathUtil::EPSILON = 1E-6;
vmml::vec3f MathUtil::Plane::intersection(const vmml::vec3f &p, const vmml::vec3f &dir) const {
float r = (d - p.dot(normal))/dir.dot(normal);
return p + r*dir;
}
vmml::mat4f MathUtil::perspective(float fovy, float aspect, float zNear) { vmml::mat4f MathUtil::perspective(float fovy, float aspect, float zNear) {
float f = 1/std::tan(fovy*M_PI/360); float f = 1/std::tan(fovy*M_PI/360);
vmml::mat4f ret(vmml::mat4f::ZERO); vmml::mat4f ret(vmml::mat4f::ZERO);
ret[0][0] = f/aspect; ret[0][0] = f/aspect;
ret[1][1] = f; ret[1][1] = f;
ret[2][2] = -1; ret[2][2] = EPSILON-1;
ret[2][3] = -2*zNear; ret[2][3] = (EPSILON-2)*zNear;
ret[3][2] = -1; ret[3][2] = -1;
return ret; return ret;

View file

@ -20,12 +20,73 @@
#ifndef ZOOM_MATHUTIL_H_ #ifndef ZOOM_MATHUTIL_H_
#define ZOOM_MATHUTIL_H_ #define ZOOM_MATHUTIL_H_
#include "Triangle.h"
#include <vmmlib/matrix.hpp> #include <vmmlib/matrix.hpp>
namespace Zoom { namespace Zoom {
class MathUtil { class MathUtil {
public: public:
static const float EPSILON;
class Plane {
public:
Plane(const vmml::vec3f &n = vmml::vec3f::ZERO, float d0 = 0) : 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) < EPSILON);
}
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;
private:
vmml::vec3f normal;
float d;
};
static vmml::mat4f perspective(float fovy, float aspect, float zNear); static vmml::mat4f perspective(float fovy, float aspect, float zNear);
private: private:

View file

@ -32,8 +32,7 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
void resize(int width, int height) void resize(int width, int height) {
{
if(height == 0) { if(height == 0) {
height = 1; height = 1;
} }
@ -180,13 +179,11 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
bool running = true; bool running = true;
MSG msg; MSG msg;
while(running) while(running) {
{
unsigned long delta = 0; unsigned long delta = 0;
unsigned long ticks = GetTickCount(); unsigned long ticks = GetTickCount();
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
{
if(msg.message == WM_QUIT) if(msg.message == WM_QUIT)
{ {
running = false; running = false;