From f945e21bbd225d9a2beb0f8e623bf5b9a66fc846 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 26 Dec 2009 14:17:28 +0100 Subject: [PATCH 01/10] Optimized finding nearest plane --- src/Game.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Game.cpp b/src/Game.cpp index 5b61da7..e3aa72f 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -137,16 +137,24 @@ void Game::run(int delta) { ok = true; MathUtil::Plane nearestPlane; + float nearestDistance; for(std::vector::iterator t = triangles.begin(); t != triangles.end(); ++t) { if(Collision::test(t->getTriangle(), playerPos, PLAYER_RADIUS, playerMove)) { vmml::vec3f normal = t->getTriangle().computeNormal(); + if(normal.dot(playerMove) >= 0) + continue; + MathUtil::Plane p(normal, vmml::dot(normal, t->getTriangle().getVertex(0)+PLAYER_RADIUS*normal)); if(p.isInFront(playerPos) || p.contains(playerPos)) { - if(ok || p.distance(playerPos) < nearestPlane.distance(playerPos)) { + vmml::vec3f intersection = p.intersection(MathUtil::Ray(playerPos, playerMove)); + float distance = intersection.squared_distance(playerPos); + + if(ok || distance < nearestDistance) { ok = false; nearestPlane = p; + nearestDistance = distance; } } } From c85a39bb0ffabf11752329c73f502ef74ec1ef76 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 3 Jan 2010 08:19:56 +0100 Subject: [PATCH 02/10] Added correct edge collision --- src/Collision.cpp | 64 +++++++++++++++++++++++++++++++++++++++-------- src/Collision.h | 4 ++- src/Game.cpp | 6 ++++- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/Collision.cpp b/src/Collision.cpp index 7c72922..6c301da 100644 --- a/src/Collision.cpp +++ b/src/Collision.cpp @@ -18,6 +18,8 @@ */ #include "Collision.h" +#include +#include namespace Zoom { @@ -75,23 +77,63 @@ bool Collision::test(const Triangle &t, const MathUtil::Ray &ray, float *distanc return true; } -bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move) { - float distance; +bool Collision::testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { + vmml::vec3f edge = v2 - v1; - if(test(t, MathUtil::Ray(m - r*t.computeNormal(), move), &distance) && distance > -MathUtil::EPSILON) { - if(distance < 1) - return true; - else - return false; - } + vmml::vec3f avec = vmml::dot(edge, move)*edge / edge.squared_length() - move; + vmml::vec3f cvec = v1 + vmml::dot(edge, m-v1)*edge / edge.squared_length() - m; - vmml::vec3f collisionPoint = projectToNearestEdge(m, t); - vmml::vec3f movedPoint = projectToEdge(m, collisionPoint, collisionPoint - move); + float a = avec.squared_length(); + float b = vmml::dot(avec, cvec); + float c = cvec.squared_length() - r*r; - if(m.squared_distance(movedPoint) < r*r) + float rootSq = b*b - a*c; + if(rootSq < 0) + return false; + + float root = std::sqrt(rootSq); + + *distance = -(b + root)/a; + + float edgeFact = edge.dot(m + move*(*distance) - v1); + if(edgeFact < 0 || edgeFact > edge.squared_length()) + return false; + + if(*distance > -MathUtil::EPSILON && *distance < 1) return true; else return false; } +bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { + float d; + + if(test(t, MathUtil::Ray(m - r*t.computeNormal(), move), &d) && d > -MathUtil::EPSILON) { + if(distance) + *distance = d; + + if(d < 1) { + return true; + } + else { + return false; + } + } + + float minEdgeDistance = std::numeric_limits::infinity(); + + for(int i = 0; i < 3; ++i) { + if(testEdge(t.getVertex(i), t.getVertex((i+1)%3), m, r, move, &d)) { + if(d < minEdgeDistance) { + minEdgeDistance = d; + } + } + } + + if(distance) + *distance = minEdgeDistance; + + return (minEdgeDistance < 1); +} + } diff --git a/src/Collision.h b/src/Collision.h index 635a7d3..42e5399 100644 --- a/src/Collision.h +++ b/src/Collision.h @@ -27,11 +27,13 @@ namespace Zoom { class Collision { public: static bool test(const Triangle &t, const MathUtil::Ray &ray, float *distance = 0); - static bool test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move); + static bool test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance = 0); private: Collision(); + static bool testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance); + static vmml::vec3f projectToEdge(const vmml::vec3f& p, const vmml::vec3f& v1, const vmml::vec3f& v2); static vmml::vec3f projectToNearestEdge(const vmml::vec3f& p, const Triangle &t); }; diff --git a/src/Game.cpp b/src/Game.cpp index e3aa72f..f583312 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -30,7 +30,7 @@ namespace Zoom { -const float Game::PLAYER_SPEED = 10; +const float Game::PLAYER_SPEED = 3; const float Game::PLAYER_RADIUS = 0.3; Game::Game() : playerPos(vmml::vec3f::ZERO), playerRotY(vmml::mat4f::IDENTITY), playerRotX(0), @@ -157,6 +157,10 @@ void Game::run(int delta) { nearestDistance = distance; } } + else { + // TODO Edge collision + + } } } From 853d3978c5d4d1ab47f75fb1e5a11efe354dc79d Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 3 Jan 2010 19:52:54 +0100 Subject: [PATCH 03/10] Added corner collision --- src/Collision.cpp | 59 +++++++++++++++++++++++++++++++++++++++-------- src/Collision.h | 1 + 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/Collision.cpp b/src/Collision.cpp index 6c301da..91bfc95 100644 --- a/src/Collision.cpp +++ b/src/Collision.cpp @@ -84,16 +84,16 @@ bool Collision::testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmm vmml::vec3f cvec = v1 + vmml::dot(edge, m-v1)*edge / edge.squared_length() - m; float a = avec.squared_length(); - float b = vmml::dot(avec, cvec); + float b_2 = vmml::dot(avec, cvec); float c = cvec.squared_length() - r*r; - float rootSq = b*b - a*c; + float rootSq = b_2*b_2 - a*c; if(rootSq < 0) return false; float root = std::sqrt(rootSq); - *distance = -(b + root)/a; + *distance = -(b_2 + root)/a; float edgeFact = edge.dot(m + move*(*distance) - v1); if(edgeFact < 0 || edgeFact > edge.squared_length()) @@ -105,6 +105,25 @@ bool Collision::testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmm return false; } +bool Collision::testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { + float a = move.squared_length(); + float b_2 = vmml::dot(m-v, move); + float c = (m-v).squared_length() - r*r; + + float rootSq = b_2*b_2 - a*c; + if(rootSq < 0) + return false; + + float root = std::sqrt(rootSq); + + *distance = -(b_2 + root)/a; + + if(*distance > -MathUtil::EPSILON && *distance < 1) + return true; + else + return false; +} + bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { float d; @@ -120,20 +139,42 @@ bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmm } } - float minEdgeDistance = std::numeric_limits::infinity(); + bool collision = false; + float minDistance; for(int i = 0; i < 3; ++i) { if(testEdge(t.getVertex(i), t.getVertex((i+1)%3), m, r, move, &d)) { - if(d < minEdgeDistance) { - minEdgeDistance = d; + if(!collision || d < minDistance) { + minDistance = d; } } } - if(distance) - *distance = minEdgeDistance; + if(collision) { + if(distance) + *distance = minDistance; - return (minEdgeDistance < 1); + return true; + } + + collision = false; + for(int i = 0; i < 3; ++i) { + if(testVertex(t.getVertex(i), m, r, move, &d)) { + if(!collision || d < minDistance) { + minDistance = d; + } + } + } + + if(collision) { + if(distance) + *distance = minDistance; + + return true; + } + else { + return false; + } } } diff --git a/src/Collision.h b/src/Collision.h index 42e5399..df69289 100644 --- a/src/Collision.h +++ b/src/Collision.h @@ -33,6 +33,7 @@ class Collision { Collision(); static bool testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance); + static bool testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance); static vmml::vec3f projectToEdge(const vmml::vec3f& p, const vmml::vec3f& v1, const vmml::vec3f& v2); static vmml::vec3f projectToNearestEdge(const vmml::vec3f& p, const Triangle &t); From cc2a07f13d5f6613dabcd454790b088c9c273cbf Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 3 Jan 2010 20:23:00 +0100 Subject: [PATCH 04/10] Removed unused methods --- src/Collision.cpp | 27 --------------------------- src/Collision.h | 3 --- 2 files changed, 30 deletions(-) diff --git a/src/Collision.cpp b/src/Collision.cpp index 91bfc95..ea69b39 100644 --- a/src/Collision.cpp +++ b/src/Collision.cpp @@ -23,33 +23,6 @@ namespace Zoom { -vmml::vec3f Collision::projectToEdge(const vmml::vec3f& p, const vmml::vec3f& v1, const vmml::vec3f& v2) { - vmml::vec3f pVec = p - v1; - vmml::vec3f edge = v2 - v1; - - float lengthSq = edge.squared_length(); - float edgeProj = vmml::dot(edge, pVec); - - if(edgeProj < 0) return v1; - if(edgeProj > lengthSq) return v2; - - return v1 + (edgeProj/lengthSq)*edge; -} - -vmml::vec3f Collision::projectToNearestEdge(const vmml::vec3f& p, const Triangle &t) { - vmml::vec3f p1 = projectToEdge(p, t.getVertex(0), t.getVertex(1)); - vmml::vec3f p2 = projectToEdge(p, t.getVertex(1), t.getVertex(2)); - vmml::vec3f p3 = projectToEdge(p, t.getVertex(2), t.getVertex(0)); - - if(p.squared_distance(p1) < p.squared_distance(p2) && p.squared_distance(p1) < p.squared_distance(p3)) - return p1; - else if(p.squared_distance(p2) < p.squared_distance(p3)) - return p2; - else - return p3; -} - - bool Collision::test(const Triangle &t, const MathUtil::Ray &ray, float *distance) { vmml::vec3f edge1 = t.getVertex(1) - t.getVertex(0); vmml::vec3f edge2 = t.getVertex(2) - t.getVertex(0); diff --git a/src/Collision.h b/src/Collision.h index df69289..ba987b9 100644 --- a/src/Collision.h +++ b/src/Collision.h @@ -34,9 +34,6 @@ class Collision { static bool testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance); static bool testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance); - - static vmml::vec3f projectToEdge(const vmml::vec3f& p, const vmml::vec3f& v1, const vmml::vec3f& v2); - static vmml::vec3f projectToNearestEdge(const vmml::vec3f& p, const Triangle &t); }; } From 9d152e2773f28d4fb7066010d2ae9099873cb6fd Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 4 Jan 2010 01:02:33 +0100 Subject: [PATCH 05/10] Corrected edge & vertex collision --- src/Collision.cpp | 2 ++ src/Game.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Collision.cpp b/src/Collision.cpp index ea69b39..e552643 100644 --- a/src/Collision.cpp +++ b/src/Collision.cpp @@ -118,6 +118,7 @@ bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmm for(int i = 0; i < 3; ++i) { if(testEdge(t.getVertex(i), t.getVertex((i+1)%3), m, r, move, &d)) { if(!collision || d < minDistance) { + collision = true; minDistance = d; } } @@ -134,6 +135,7 @@ bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmm for(int i = 0; i < 3; ++i) { if(testVertex(t.getVertex(i), m, r, move, &d)) { if(!collision || d < minDistance) { + collision = true; minDistance = d; } } diff --git a/src/Game.cpp b/src/Game.cpp index f583312..aea829f 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -131,10 +131,10 @@ void Game::run(int delta) { vmml::vec3f origMove = playerMove; - bool ok = false; + bool collision = true; - while(!ok) { - ok = true; + while(collision) { + collision = false; MathUtil::Plane nearestPlane; float nearestDistance; @@ -150,8 +150,8 @@ void Game::run(int delta) { vmml::vec3f intersection = p.intersection(MathUtil::Ray(playerPos, playerMove)); float distance = intersection.squared_distance(playerPos); - if(ok || distance < nearestDistance) { - ok = false; + if(!collision || distance < nearestDistance) { + collision = true; nearestPlane = p; nearestDistance = distance; @@ -164,7 +164,7 @@ void Game::run(int delta) { } } - if(!ok) { + if(collision) { vmml::vec3f move; if(playerMove.dot(nearestPlane.getNormal()) == 0) From 648ce1d4541b8ea7e9c93c99f251f10277053131 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 4 Jan 2010 21:34:56 +0100 Subject: [PATCH 06/10] Optimized collision detection --- src/Collision.cpp | 56 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/Collision.cpp b/src/Collision.cpp index e552643..0161d5d 100644 --- a/src/Collision.cpp +++ b/src/Collision.cpp @@ -64,18 +64,31 @@ bool Collision::testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmm if(rootSq < 0) return false; - float root = std::sqrt(rootSq); + float minRoot = -a - b_2; + float maxRoot = a*MathUtil::EPSILON - b_2; - *distance = -(b_2 + root)/a; - - float edgeFact = edge.dot(m + move*(*distance) - v1); - if(edgeFact < 0 || edgeFact > edge.squared_length()) + if(minRoot < 0) + minRoot = 0; + if(maxRoot < 0) return false; - if(*distance > -MathUtil::EPSILON && *distance < 1) - return true; - else + if(rootSq < minRoot*minRoot || rootSq >= maxRoot*maxRoot) return false; + + minRoot = a*(edge.dot(m - v1) - edge.squared_length())/edge.dot(move) - b_2; + maxRoot = a*edge.dot(m - v1)/edge.dot(move) - b_2; + + if(minRoot < 0) + minRoot = 0; + if(maxRoot < 0) + return false; + + if(rootSq < minRoot*minRoot || rootSq > maxRoot*maxRoot) + return false; + + *distance = -(b_2 + std::sqrt(rootSq))/a; + + return true; } bool Collision::testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { @@ -87,24 +100,33 @@ bool Collision::testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, if(rootSq < 0) return false; - float root = std::sqrt(rootSq); + float minRoot = -a - b_2; + float maxRoot = a*MathUtil::EPSILON - b_2; - *distance = -(b_2 + root)/a; - - if(*distance > -MathUtil::EPSILON && *distance < 1) - return true; - else + if(minRoot < 0) + minRoot = 0; + if(maxRoot < 0) return false; + + if(rootSq <= minRoot*minRoot || rootSq >= maxRoot*maxRoot) + return false; + + *distance = -(b_2 + std::sqrt(rootSq))/a; + + return true; } bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { + if(move.squared_length() == 0) + return false; + float d; if(test(t, MathUtil::Ray(m - r*t.computeNormal(), move), &d) && d > -MathUtil::EPSILON) { - if(distance) - *distance = d; - if(d < 1) { + if(distance) + *distance = d; + return true; } else { From 2aa2097b6cffd6ed58e127b0ed4f76d6255ac495 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 5 Jan 2010 22:29:21 +0100 Subject: [PATCH 07/10] New and improved edge collision handling! Get it while it's hot! --- src/Collision.cpp | 33 +++++++++++++++++++++++++++++++-- src/Collision.h | 4 +++- src/Game.cpp | 40 +++++++++++++++------------------------- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/Collision.cpp b/src/Collision.cpp index 0161d5d..21ef083 100644 --- a/src/Collision.cpp +++ b/src/Collision.cpp @@ -50,6 +50,20 @@ bool Collision::test(const Triangle &t, const MathUtil::Ray &ray, float *distanc return true; } +vmml::vec3f Collision::projectToEdge(const vmml::vec3f& p, const vmml::vec3f& v1, const vmml::vec3f& v2) { + vmml::vec3f pVec = p - v1; + vmml::vec3f edge = v2 - v1; + + float lengthSq = edge.squared_length(); + float edgeProj = vmml::dot(edge, pVec); + + if(edgeProj < 0) return v1; + if(edgeProj > lengthSq) return v2; + + return v1 + (edgeProj/lengthSq)*edge; +} + + bool Collision::testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { vmml::vec3f edge = v2 - v1; @@ -116,16 +130,19 @@ bool Collision::testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, return true; } -bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance) { +bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance, vmml::vec3f *normal) { if(move.squared_length() == 0) return false; float d; - if(test(t, MathUtil::Ray(m - r*t.computeNormal(), move), &d) && d > -MathUtil::EPSILON) { + vmml::vec3f triangleNormal = t.computeNormal(); + if(test(t, MathUtil::Ray(m - r*triangleNormal, move), &d) && d > -MathUtil::EPSILON) { if(d < 1) { if(distance) *distance = d; + if(normal) + *normal = triangleNormal; return true; } @@ -142,6 +159,12 @@ bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmm if(!collision || d < minDistance) { collision = true; minDistance = d; + + if(normal) { + vmml::vec3f p = m + move*d; + + *normal = (p - projectToEdge(p, t.getVertex(i), t.getVertex((i+1)%3)))/r; + } } } } @@ -160,6 +183,12 @@ bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmm collision = true; minDistance = d; } + + if(normal) { + vmml::vec3f p = m + move*d; + + *normal = (p - t.getVertex(i))/r; + } } } diff --git a/src/Collision.h b/src/Collision.h index ba987b9..2688435 100644 --- a/src/Collision.h +++ b/src/Collision.h @@ -27,11 +27,13 @@ namespace Zoom { class Collision { public: static bool test(const Triangle &t, const MathUtil::Ray &ray, float *distance = 0); - static bool test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance = 0); + static bool test(const Triangle &t, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance = 0, vmml::vec3f *normal = 0); private: Collision(); + static vmml::vec3f projectToEdge(const vmml::vec3f& p, const vmml::vec3f& v1, const vmml::vec3f& v2); + static bool testEdge(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance); static bool testVertex(const vmml::vec3f &v, const vmml::vec3f &m, float r, const vmml::vec3f &move, float *distance); }; diff --git a/src/Game.cpp b/src/Game.cpp index aea829f..d13a262 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -136,43 +136,32 @@ void Game::run(int delta) { while(collision) { collision = false; - MathUtil::Plane nearestPlane; float nearestDistance; + vmml::vec3f nearestNormal; for(std::vector::iterator t = triangles.begin(); t != triangles.end(); ++t) { - if(Collision::test(t->getTriangle(), playerPos, PLAYER_RADIUS, playerMove)) { - vmml::vec3f normal = t->getTriangle().computeNormal(); + float distance; + vmml::vec3f normal; + + if(Collision::test(t->getTriangle(), playerPos, PLAYER_RADIUS, playerMove, &distance, &normal)) { + normal.y() = 0; + if(normal.dot(playerMove) >= 0) continue; - MathUtil::Plane p(normal, vmml::dot(normal, t->getTriangle().getVertex(0)+PLAYER_RADIUS*normal)); - if(p.isInFront(playerPos) || p.contains(playerPos)) { - vmml::vec3f intersection = p.intersection(MathUtil::Ray(playerPos, playerMove)); - float distance = intersection.squared_distance(playerPos); - - if(!collision || distance < nearestDistance) { - collision = true; - - nearestPlane = p; - nearestDistance = distance; - } - } - else { - // TODO Edge collision + if(!collision || distance < nearestDistance) { + collision = true; + nearestDistance = distance; + nearestNormal = normal; } } } if(collision) { - vmml::vec3f move; + vmml::vec3f move = playerMove*nearestDistance; - if(playerMove.dot(nearestPlane.getNormal()) == 0) - move = playerMove; - else - move = nearestPlane.intersection(MathUtil::Ray(playerPos, playerMove)) - playerPos; - - if(move.dot(origMove) <= 0 && move.squared_length() > MathUtil::EPSILON) { + if(move.dot(origMove) <= 0 && move.squared_length() > 0) { return; } @@ -182,7 +171,8 @@ void Game::run(int delta) { playerPos += move; vmml::vec3f restMove = playerMove - move; - playerMove = restMove - nearestPlane.getNormal() * (nearestPlane.getNormal().dot(restMove)); + + playerMove = restMove - nearestNormal * (nearestNormal.dot(restMove)); } } From a30ae7d0fb13b9a00a17e621463c186fb6ac5ada Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 6 Jan 2010 06:12:58 +0100 Subject: [PATCH 08/10] Optimized triangle normal handling --- src/Collision.cpp | 2 +- src/Level.cpp | 18 +++++++----------- src/MathUtil.h | 2 +- src/Renderer.cpp | 2 +- src/Triangle.h | 33 ++++++++++++++++++++++----------- 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/Collision.cpp b/src/Collision.cpp index 21ef083..81bc89d 100644 --- a/src/Collision.cpp +++ b/src/Collision.cpp @@ -136,7 +136,7 @@ bool Collision::test(const Triangle &t, const vmml::vec3f &m, float r, const vmm float d; - vmml::vec3f triangleNormal = t.computeNormal(); + vmml::vec3f triangleNormal = t.getNormal(); if(test(t, MathUtil::Ray(m - r*triangleNormal, move), &d) && d > -MathUtil::EPSILON) { if(d < 1) { if(distance) diff --git a/src/Level.cpp b/src/Level.cpp index 9b2aa78..c6ba915 100644 --- a/src/Level.cpp +++ b/src/Level.cpp @@ -172,13 +172,13 @@ TriangleRecord Level::loadWall(xmlNodePtr wallNode) { if(++vertexNum > 2) break; - wall.getTriangle().setVertex(vertexNum, loadVector(node)); + wall.getTriangle().setVertex(vertexNum, loadVector(node), false); } else if(!xmlStrcmp(node->name, (xmlChar*)"normal")) { if(vertexNum < 0) continue; - wall.getTriangle().setNormal(vertexNum, loadVector(node)); + wall.getTriangle().setVertexNormal(vertexNum, loadVector(node)); } else if(!xmlStrcmp(node->name, (xmlChar*)"texcoords")) { if(vertexNum < 0) continue; @@ -197,18 +197,14 @@ TriangleRecord Level::loadWall(xmlNodePtr wallNode) { } } - vmml::vec3f normal = wall.getTriangle().computeNormal(); + wall.getTriangle().updateNormal(); + vmml::vec3f normal = wall.getTriangle().getNormal(); - if(normal.squared_length() > 0) { - normal.normalize(); - - for(int i = 0; i < 3; ++i) { - if(wall.getTriangle().getNormal(i).squared_length() == 0) - wall.getTriangle().setNormal(i, normal); - } + for(int i = 0; i < 3; ++i) { + if(wall.getTriangle().getVertexNormal(i).squared_length() == 0) + wall.getTriangle().setVertexNormal(i, normal); } - return wall; } diff --git a/src/MathUtil.h b/src/MathUtil.h index 3f7ba90..639336a 100644 --- a/src/MathUtil.h +++ b/src/MathUtil.h @@ -51,7 +51,7 @@ class MathUtil { 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)) {} + Plane(const Triangle &t) : normal(t.getNormal()), d(t.getVertex(0).dot(normal)) {} bool contains(const vmml::vec3f &v) const { return (fabsf(normal.dot(v) - d) < EPSILON); diff --git a/src/Renderer.cpp b/src/Renderer.cpp index 5d86565..512883d 100644 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -53,7 +53,7 @@ void Renderer::renderTriangle(const Triangle &t) { for(int i = 0; i < 3; ++i) { glTexCoord2fv(t.getTexCoords(i).array); - glNormal3fv(t.getNormal(i).array); + glNormal3fv(t.getVertexNormal(i).array); glVertex3fv(t.getVertex(i).array); } } diff --git a/src/Triangle.h b/src/Triangle.h index 2b34c3f..e13574c 100644 --- a/src/Triangle.h +++ b/src/Triangle.h @@ -30,30 +30,44 @@ class Triangle { 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; + normal = 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) { + Triangle(const vmml::vec3f &v1, const vmml::vec3f &v2, const vmml::vec3f &v3, const vmml::vec4f &color0, bool update = true) : 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; + + if(update) + updateNormal(); + else + normal = vmml::vec3f::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) { + void setVertex(int i, vmml::vec3f v, bool update = true) { vertices[i] = v; + + if(update) + updateNormal(); } - 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) { + void updateNormal() { + normal = vertices[0].compute_normal(vertices[1], vertices[2]); + } + + const vmml::vec3f& getVertexNormal(int i) const {return normals[i];} + vmml::vec3f& getVertexNormal(int i) {return normals[i];} + void setVertexNormal(int i, vmml::vec3f n) { normals[i] = n; } + const vmml::vec3f& getNormal() const {return normal;} + 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) { @@ -73,12 +87,8 @@ class Triangle { color = c; } - vmml::vec3f computeNormal() const { - return vertices[0].compute_normal(vertices[1], vertices[2]); - } - bool isDegenerate() const { - return (computeNormal().squared_length() == 0); + return (normal.squared_length() == 0); } void transform(const vmml::mat4f &matrix) { @@ -94,6 +104,7 @@ class Triangle { private: vmml::vec3f vertices[3]; vmml::vec3f normals[3]; + vmml::vec3f normal; vmml::vec2f texcoords[3]; vmml::vec4f color; unsigned texture; From 05bc72eeb33ea42012da2eba26dcaedfafb2f3a2 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 7 Jan 2010 16:25:42 +0100 Subject: [PATCH 09/10] GLX: Wait for MapNotify --- src/zoom.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/zoom.cpp b/src/zoom.cpp index aa085bf..84c303c 100644 --- a/src/zoom.cpp +++ b/src/zoom.cpp @@ -233,6 +233,10 @@ bool XIInit(Display *disp, int *opcode) { return true; } +static Bool WaitForMapNotify(Display*, XEvent *event, XPointer arg) { + return (event->type == MapNotify && event->xmap.window == (Window)arg); +} + bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, int *xi_opcode, int *pointer) { static const int msAttributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, @@ -305,7 +309,9 @@ bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, int *xi_o XFreePixmap(disp, pixmap); XMapWindow(disp, *wnd); - XSync(disp, False); + + XEvent event; + XIfEvent(disp, &event, WaitForMapNotify, (XPointer)*wnd); XIGetClientPointer(disp, *wnd, pointer); From 09d8936f0e640ae863861a92f6d16f8c35c93501 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 27 Nov 2012 13:15:52 +0100 Subject: [PATCH 10/10] Some fixes for recent changes in GCC, libX11, etc... --- CMakeLists.txt | 3 ++- src/CMakeLists.txt | 2 +- src/zoom.cpp | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af00fd4..eeeb3ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,10 +9,11 @@ IF (NOT OPENGL_FOUND) MESSAGE(FATAL_ERROR "Could not find OpenGL") ENDIF (NOT OPENGL_FOUND) +find_package(X11 REQUIRED) find_package(GLEW REQUIRED) find_package(GLPng REQUIRED) find_package(LibXml2 REQUIRED) -include_directories(${Boost_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${GLPNG_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) +include_directories(${Boost_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${GLPNG_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR} ${X11_X11_INCLUDE_PATH} ${X11_Xi_INCLUDE_PATH}) add_subdirectory(src) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8718ba7..d5fefb2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,4 +14,4 @@ add_executable(zoom TriangleRecord.h zoom.cpp ) -target_link_libraries(zoom ${Boost_LIBRARIES} ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY} ${GLPNG_LIBRARY} ${LIBXML2_LIBRARIES}) +target_link_libraries(zoom ${Boost_LIBRARIES} ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY} ${GLPNG_LIBRARY} ${LIBXML2_LIBRARIES} ${X11_LIBRARIES} ${X11_Xi_LIB}) diff --git a/src/zoom.cpp b/src/zoom.cpp index 84c303c..78e5389 100644 --- a/src/zoom.cpp +++ b/src/zoom.cpp @@ -26,6 +26,7 @@ #else #include #include +#include #include #include #include @@ -390,7 +391,7 @@ int main() { break; case KeyPress: - switch(XKeycodeToKeysym(disp, event.xkey.keycode, 0)) { + switch(XkbKeycodeToKeysym(disp, event.xkey.keycode, 0, 0)) { case XK_Up: case XK_w: input |= Zoom::Game::FORWARD; break; case XK_Down: case XK_s: input |= Zoom::Game::BACKWARD; break; case XK_Left: case XK_a: input |= Zoom::Game::LEFT; break; @@ -400,7 +401,7 @@ int main() { break; case KeyRelease: - switch(XKeycodeToKeysym(disp, event.xkey.keycode, 0)) { + switch(XkbKeycodeToKeysym(disp, event.xkey.keycode, 0, 0)) { case XK_Up: case XK_w: input &= ~Zoom::Game::FORWARD; break; case XK_Down: case XK_s: input &= ~Zoom::Game::BACKWARD; break; case XK_Left: case XK_a: input &= ~Zoom::Game::LEFT; break;