|
From: Lasse Kärkkäi. <tr...@us...> - 2011-03-12 20:40:34
|
Author: Lasse Karkkainen <tro...@tr...>
Date: Sat Mar 12 21:39:29 2011 +0100
Fix view/projection transforms (instrument perspective)
---
game/guitargraph.cc | 7 +------
game/video_driver.cc | 32 +++++++++++++++++++++++++-------
game/video_driver.hh | 10 ++++++++++
3 files changed, 36 insertions(+), 13 deletions(-)
diff --git a/game/guitargraph.cc b/game/guitargraph.cc
index 62518f4..7395222 100644
--- a/game/guitargraph.cc
+++ b/game/guitargraph.cc
@@ -796,12 +796,7 @@ void GuitarGraph::draw(double time) {
{ // Translate, rotate and scale to place
using namespace glmath;
double frac = 0.75; // Adjustable: 1.0 means fully separated, 0.0 means fully attached
- /*
- glutil::PushMatrixMode pmm(GL_PROJECTION);
- glTranslatef(frac * offsetX, 0.0f, 0.0f);
- glutil::PushMatrixMode pmb(GL_MODELVIEW);
- glTranslatef((1.0 - frac) * offsetX, 0.0f, 0.0f);
- */
+ ViewTrans view(offsetX, 0.0, frac);
mat4 m = translate(vec3(0.0f, dimensions.y2(), 0.0f)) * rotate(g_angle, vec3(1.0f, 0.0f, 0.0f)) * scale(dimensions.w() / 5.0f);
// Do some jumping for drums
if (m_drums) {
diff --git a/game/video_driver.cc b/game/video_driver.cc
index 5d96406..eeddf08 100644
--- a/game/video_driver.cc
+++ b/game/video_driver.cc
@@ -148,13 +148,7 @@ void Window::updateStereo(float sepFactor) {
}
void Window::updateTransforms() {
- // Setup the projection matrix for 2D translates
using namespace glmath;
- {
- float h = virtH();
- const float f = near_ / z0;
- g_projection = frustum(-0.5f * f, 0.5f * f, 0.5f * h * f, -0.5f * h * f, near_, far_);
- }
mat4 position = g_projection * g_modelview;
mat3 normal(g_modelview);
for (ShaderMap::iterator it = m_shaders.begin(); it != m_shaders.end(); ++it) {
@@ -169,7 +163,7 @@ void Window::updateTransforms() {
void Window::render(boost::function<void (void)> drawFunc) {
glutil::GLErrorChecker glerror("Window::render");
- updateTransforms();
+ ViewTrans trans; // Default frustum
if (s_width < screen->w || s_height < screen->h) glClear(GL_COLOR_BUFFER_BIT); // Black bars
bool stereo = config["graphic/stereo3d"].b();
int type = config["graphic/stereo3dtype"].i();
@@ -318,6 +312,30 @@ void Window::resize() {
if (s_height > 0.8f * s_width) s_height = round(0.8f * s_width);
}
+ViewTrans::ViewTrans(double offsetX, double offsetY, double frac): m_old(g_projection) {
+ // Setup the projection matrix for 2D translates
+ using namespace glmath;
+ double h = virtH();
+ const double f = near_ / z0; // z0 to nearplane conversion factor
+ // Corners of the screen at z0
+ double x1 = -0.5, x2 = 0.5;
+ double y1 = 0.5 * h, y2 = -0.5 * h;
+ // Move the perspective point by frac of offset (i.e. move the image)
+ double persX = frac * offsetX, persY = frac * offsetY;
+ x1 -= persX; x2 -= persX;
+ y1 -= persY; y2 -= persY;
+ // Perspective projection + the rest of the offset in eye (world) space
+ g_projection = frustum(f * x1, f * x2, f * y1, f * y2, near_, far_)
+ * translate(vec3(offsetX - persX, offsetY - persY, 0.0));
+ ScreenManager::getSingletonPtr()->window().updateTransforms();
+}
+
+ViewTrans::~ViewTrans() {
+ g_projection = m_old;
+ ScreenManager::getSingletonPtr()->window().updateTransforms();
+}
+
+
Transform::Transform(glmath::mat4 const& m): m_old(g_modelview) {
g_modelview = g_modelview * m;
ScreenManager::getSingletonPtr()->window().updateTransforms();
diff --git a/game/video_driver.hh b/game/video_driver.hh
index c493035..eafd93d 100644
--- a/game/video_driver.hh
+++ b/game/video_driver.hh
@@ -12,6 +12,7 @@ static inline float virtH() { return float(screenH()) / screenW(); }
struct SDL_Surface;
+/// Apply a transform to current modelview stack
class Transform {
public:
Transform(glmath::mat4 const& m);
@@ -20,6 +21,15 @@ private:
glmath::mat4 m_old;
};
+/// Apply a subviewport with different perspective projection
+class ViewTrans {
+public:
+ ViewTrans(double offsetX = 0.0, double offsetY = 0.0, double frac = 1.0);
+ ~ViewTrans();
+private:
+ glmath::mat4 m_old;
+};
+
/// Performs a GL transform for displaying background image at far distance
glmath::mat4 farTransform();
|