From db6c0ee85cd8445c454b12f7899b07606f1a0ec5 Mon Sep 17 00:00:00 2001 From: Themaister Date: Thu, 9 Aug 2012 08:56:35 +0200 Subject: [PATCH] Use custom matrix calculation routines. Aims for more compatibility with modern OpenGL. --- Makefile | 2 +- Makefile.win | 2 +- gfx/context/sdl_ctx.c | 22 ++++++-- gfx/math/matrix.c | 113 ++++++++++++++++++++++++++++++++++++++++++ gfx/math/matrix.h | 43 ++++++++++++++++ 5 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 gfx/math/matrix.c create mode 100644 gfx/math/matrix.h diff --git a/Makefile b/Makefile index 392593d13f..c4905ede83 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ ifeq ($(HAVE_X11), 1) endif ifeq ($(HAVE_OPENGL), 1) - OBJ += gfx/gl.o gfx/fonts/freetype.o + OBJ += gfx/gl.o gfx/fonts/freetype.o gfx/math/matrix.o ifeq ($(OSX),1) LIBS += -framework OpenGL else diff --git a/Makefile.win b/Makefile.win index f02a6d15ca..b8fdd29db0 100644 --- a/Makefile.win +++ b/Makefile.win @@ -61,7 +61,7 @@ ifeq ($(TDM_GCC),) endif ifeq ($(HAVE_SDL), 1) - OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/fonts/freetype.o gfx/context/sdl_ctx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o + OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/math/matrix.o gfx/fonts/freetype.o gfx/context/sdl_ctx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o LIBS += -lSDL DEFINES += -ISDL -DHAVE_SDL endif diff --git a/gfx/context/sdl_ctx.c b/gfx/context/sdl_ctx.c index 51ba0e641e..a8466f7d39 100644 --- a/gfx/context/sdl_ctx.c +++ b/gfx/context/sdl_ctx.c @@ -26,6 +26,7 @@ #endif #include "sdl_ctx.h" +#include "../math/matrix.h" // SDL 1.2 is portable, sure, but you still need some platform specific workarounds ;) // Hopefully SDL 1.3 will solve this more cleanly :D @@ -441,13 +442,28 @@ void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) #ifdef HAVE_OPENGL void gfx_ctx_set_projection(gl_t *gl, const struct gl_ortho *ortho, bool allow_rotate) { + // TODO: Explicitly setting matrix modes is not used for GLES 2.0. glMatrixMode(GL_PROJECTION); - glLoadIdentity(); + + // Calculate projection. + math_matrix proj; + matrix_ortho(&proj, ortho->left, ortho->right, + ortho->bottom, ortho->top, ortho->znear, ortho->zfar); if (allow_rotate) - glRotatef(gl->rotation, 0, 0, 1); + { + math_matrix rot; + matrix_rotate_z(&rot, M_PI * gl->rotation / 180.0f); + matrix_multiply(&proj, &rot, &proj); + } - glOrtho(ortho->left, ortho->right, ortho->bottom, ortho->top, ortho->znear, ortho->zfar); + // Load matrix directly into GL. + // TODO: For GLES 2.0 or similar, we should keep this matrix + // somewhere and pass it directly to the shader. + // It should probably be part of gl_t ... + glLoadMatrixf(proj.data); + + // TODO: Explicitly setting matrix modes is not used for GLES 2.0. glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } diff --git a/gfx/math/matrix.c b/gfx/math/matrix.c new file mode 100644 index 0000000000..d7e358fe91 --- /dev/null +++ b/gfx/math/matrix.c @@ -0,0 +1,113 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "matrix.h" +#include +#include + +void matrix_identity(math_matrix *mat) +{ + memset(mat, 0, sizeof(*mat)); + for (unsigned i = 0; i < 4; i++) + MAT_ELEM(*mat, i, i) = 1.0f; +} + +void matrix_transpose(math_matrix *out, const math_matrix *in) +{ + math_matrix mat; + for (unsigned i = 0; i < 4; i++) + for (unsigned j = 0; j < 4; j++) + MAT_ELEM(mat, j, i) = MAT_ELEM(*in, i, j); + + *out = mat; +} + +void matrix_rotate_x(math_matrix *mat, float rad) +{ + float cosine = cosf(rad); + float sine = sinf(rad); + + matrix_identity(mat); + + MAT_ELEM(*mat, 1, 1) = cosine; + MAT_ELEM(*mat, 2, 2) = cosine; + MAT_ELEM(*mat, 1, 2) = -sine; + MAT_ELEM(*mat, 2, 1) = sine; +} + +void matrix_rotate_y(math_matrix *mat, float rad) +{ + float cosine = cosf(rad); + float sine = sinf(rad); + + matrix_identity(mat); + + MAT_ELEM(*mat, 0, 0) = cosine; + MAT_ELEM(*mat, 2, 2) = cosine; + MAT_ELEM(*mat, 0, 2) = -sine; + MAT_ELEM(*mat, 2, 0) = sine; +} + +void matrix_rotate_z(math_matrix *mat, float rad) +{ + float cosine = cosf(rad); + float sine = sinf(rad); + + matrix_identity(mat); + + MAT_ELEM(*mat, 0, 0) = cosine; + MAT_ELEM(*mat, 1, 1) = cosine; + MAT_ELEM(*mat, 0, 1) = -sine; + MAT_ELEM(*mat, 1, 0) = sine; +} + +void matrix_ortho(math_matrix *mat, + float left, float right, + float bottom, float top, + float znear, float zfar) +{ + matrix_identity(mat); + + float tx = -(right + left) / (right - left); + float ty = -(top + bottom) / (top - bottom); + float tz = -(zfar + znear) / (zfar - znear); + + MAT_ELEM(*mat, 0, 0) = 2.0f / (right - left); + MAT_ELEM(*mat, 1, 1) = 2.0f / (top - bottom); + MAT_ELEM(*mat, 2, 2) = -2.0f / (zfar - znear); + MAT_ELEM(*mat, 0, 3) = tx; + MAT_ELEM(*mat, 1, 3) = ty; + MAT_ELEM(*mat, 2, 3) = tz; +} + +void matrix_multiply(math_matrix *out, + const math_matrix *a, const math_matrix *b) +{ + math_matrix mat; + + for (unsigned r = 0; r < 4; r++) + { + for (unsigned c = 0; c < 4; c++) + { + float dot = 0.0f; + for (unsigned k = 0; k < 4; k++) + dot += MAT_ELEM(*a, r, k) * MAT_ELEM(*b, k, c); + MAT_ELEM(mat, r, c) = dot; + } + } + + *out = mat; +} + diff --git a/gfx/math/matrix.h b/gfx/math/matrix.h new file mode 100644 index 0000000000..9fc2624287 --- /dev/null +++ b/gfx/math/matrix.h @@ -0,0 +1,43 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef MATH_MATRIX_H__ +#define MATH_MATRIX_H__ + +// Colunm-major matrix (OpenGL-style). +// Reimplements functionality from FF OpenGL pipeline to be able to work on GLES 2.0 and modern GL variants. +typedef struct math_matrix +{ + float data[16]; +} math_matrix; + +#define MAT_ELEM(mat, r, c) ((mat).data[4 * (c) + (r)]) + +void matrix_load_identity(math_matrix *mat); +void matrix_transpose(math_matrix *out, const math_matrix *in); + +void matrix_rotate_x(math_matrix *mat, float rad); +void matrix_rotate_y(math_matrix *mat, float rad); +void matrix_rotate_z(math_matrix *mat, float rad); + +void matrix_ortho(math_matrix *mat, + float left, float right, + float bottom, float top, + float znear, float zfar); + +void matrix_multiply(math_matrix *out, const math_matrix *a, const math_matrix *b); + +#endif +