summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/graphics/common/device.h23
-rw-r--r--src/graphics/opengl/gldevice.cpp82
-rw-r--r--src/graphics/opengl/gldevice.h1
4 files changed, 108 insertions, 3 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fc3cfe3..9430da6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,6 +5,8 @@
# Configure options
option(DEBUG "Enable debug output" ON)
+set(PLATFORM_LIBS "")
+
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(PLATFORM_WINDOWS 1)
set(PLATFORM_LINUX 0)
@@ -13,6 +15,8 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(PLATFORM_WINDOWS 0)
set(PLATFORM_LINUX 1)
set(PLATFORM_OTHER 0)
+ # for clock_gettime
+ set(PLATFORM_LIBS "-lrt")
else()
set(PLATFORM_WINDOWS 0)
set(PLATFORM_LINUX 0)
@@ -154,6 +158,7 @@ ${SDLIMAGE_LIBRARY}
${OPENGL_LIBRARY}
${PNG_LIBRARIES}
#CBot -- not yet WinAPI-independent
+${PLATFORM_LIBS}
)
include_directories(. ${CMAKE_CURRENT_BINARY_DIR}
diff --git a/src/graphics/common/device.h b/src/graphics/common/device.h
index 6a71a8a..ceaf67a 100644
--- a/src/graphics/common/device.h
+++ b/src/graphics/common/device.h
@@ -181,6 +181,24 @@ enum PrimitiveType
PRIMITIVE_TRIANGLE_STRIP
};
+/**
+ \enum IntersectPlane
+ \brief Intersection plane of projection volume
+
+ These flags can be OR'd together. */
+enum IntersectPlane
+{
+ INTERSECT_PLANE_LEFT = 0x01,
+ INTERSECT_PLANE_RIGHT = 0x02,
+ INTERSECT_PLANE_TOP = 0x04,
+ INTERSECT_PLANE_BOTTOM = 0x08,
+ INTERSECT_PLANE_FRONT = 0x10,
+ INTERSECT_PLANE_BACK = 0x20,
+ INTERSECT_PLANE_ALL = INTERSECT_PLANE_LEFT | INTERSECT_PLANE_RIGHT |
+ INTERSECT_PLANE_TOP | INTERSECT_PLANE_BOTTOM |
+ INTERSECT_PLANE_FRONT | INTERSECT_PLANE_BACK
+};
+
/*
Notes for rewriting DirectX code:
@@ -324,9 +342,8 @@ public:
//! Renders primitive composed of vertices with multitexturing (2 textures)
virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexTex2 *vertices, int vertexCount) = 0;
- // TODO:
- // virtual void ComputeSphereVisibility() = 0;
-
+ //! Tests whether a sphere intersects the 6 clipping planes of projection volume
+ virtual int ComputeSphereVisibility(Math::Vector center, float radius) = 0;
//! Enables/disables the given render state
virtual void SetRenderState(Gfx::RenderState state, bool enabled) = 0;
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index b8f3bed..19a9cff 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -18,6 +18,7 @@
#include "common/image.h"
#include "graphics/opengl/gldevice.h"
+#include "math/geometry.h"
#define GL_GLEXT_PROTOTYPES
@@ -732,6 +733,87 @@ void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, VertexTex2 *vertices
glEnd();
}
+bool InPlane(Math::Vector normal, float originPlane, Math::Vector center, float radius)
+{
+ float distance = (originPlane + Math::DotProduct(normal, center)) / normal.Length();
+
+ if (distance < -radius)
+ return true;
+
+ return false;
+}
+
+/*
+ The implementation of ComputeSphereVisibility is taken from libwine's device.c
+ Copyright of the WINE team, licensed under GNU LGPL v 2.1
+ */
+
+// TODO: testing
+int Gfx::CGLDevice::ComputeSphereVisibility(Math::Vector center, float radius)
+{
+ Math::Matrix m;
+ m.LoadIdentity();
+ m = Math::MultiplyMatrices(m, m_worldMat);
+ m = Math::MultiplyMatrices(m, m_viewMat);
+ m = Math::MultiplyMatrices(m, m_projectionMat);
+
+ Math::Vector vec[6];
+ float originPlane[6];
+
+ // Left plane
+ vec[0].x = m.Get(4, 1) + m.Get(1, 1);
+ vec[0].y = m.Get(4, 2) + m.Get(1, 2);
+ vec[0].z = m.Get(4, 3) + m.Get(1, 3);
+ originPlane[0] = m.Get(4, 4) + m.Get(1, 4);
+
+ // Right plane
+ vec[1].x = m.Get(4, 1) - m.Get(1, 1);
+ vec[1].y = m.Get(4, 2) - m.Get(1, 2);
+ vec[1].z = m.Get(4, 3) - m.Get(1, 3);
+ originPlane[1] = m.Get(4, 4) - m.Get(1, 4);
+
+ // Top plane
+ vec[2].x = m.Get(4, 1) - m.Get(2, 1);
+ vec[2].y = m.Get(4, 2) - m.Get(2, 2);
+ vec[2].z = m.Get(4, 3) - m.Get(2, 3);
+ originPlane[2] = m.Get(4, 4) - m.Get(2, 4);
+
+ // Bottom plane
+ vec[3].x = m.Get(4, 1) + m.Get(2, 1);
+ vec[3].y = m.Get(4, 2) + m.Get(2, 2);
+ vec[3].z = m.Get(4, 3) + m.Get(2, 3);
+ originPlane[3] = m.Get(4, 4) + m.Get(2, 4);
+
+ // Front plane
+ vec[4].x = m.Get(3, 1);
+ vec[4].y = m.Get(3, 2);
+ vec[4].z = m.Get(3, 3);
+ originPlane[4] = m.Get(3, 4);
+
+ // Back plane
+ vec[5].x = m.Get(4, 1) - m.Get(3, 1);
+ vec[5].y = m.Get(4, 2) - m.Get(3, 2);
+ vec[5].z = m.Get(4, 3) - m.Get(3, 3);
+ originPlane[5] = m.Get(4, 4) - m.Get(3, 4);
+
+ int result = 0;
+
+ if (InPlane(vec[0], originPlane[0], center, radius))
+ result |= Gfx::INTERSECT_PLANE_LEFT;
+ if (InPlane(vec[1], originPlane[1], center, radius))
+ result |= Gfx::INTERSECT_PLANE_RIGHT;
+ if (InPlane(vec[2], originPlane[2], center, radius))
+ result |= Gfx::INTERSECT_PLANE_TOP;
+ if (InPlane(vec[3], originPlane[3], center, radius))
+ result |= Gfx::INTERSECT_PLANE_BOTTOM;
+ if (InPlane(vec[4], originPlane[4], center, radius))
+ result |= Gfx::INTERSECT_PLANE_FRONT;
+ if (InPlane(vec[5], originPlane[5], center, radius))
+ result |= Gfx::INTERSECT_PLANE_BACK;
+
+ return result;
+}
+
void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
{
if (state == RENDER_STATE_DEPTH_WRITE)
diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h
index 2b1b05d..56ea2c0 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -117,6 +117,7 @@ public:
virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexCol *vertices, int vertexCount);
virtual void DrawPrimitive(Gfx::PrimitiveType type, VertexTex2 *vertices, int vertexCount);
+ virtual int ComputeSphereVisibility(Math::Vector center, float radius);
virtual void SetRenderState(Gfx::RenderState state, bool enabled);
virtual bool GetRenderState(Gfx::RenderState state);