1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** @file matrix.cc
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Implements simple matrix manipulation functions.
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//-----------------------------------------------------------------------------
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <stdlib.h>
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string.h>
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "matrix.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define deg_to_rad(x) (x * (M_PI / 180.0f))
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void glhFrustumf2(Matrix_t mat,
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  GLfloat left,
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  GLfloat right,
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  GLfloat bottom,
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  GLfloat top,
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  GLfloat znear,
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  GLfloat zfar) {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  float temp, temp2, temp3, temp4;
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  temp = 2.0f * znear;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  temp2 = right - left;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  temp3 = top - bottom;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  temp4 = zfar - znear;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[0] = temp / temp2;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[1] = 0.0f;
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[2] = 0.0f;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[3] = 0.0f;
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[4] = 0.0f;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[5] = temp / temp3;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[6] = 0.0f;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[7] = 0.0f;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[8] = (right + left) / temp2;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[9] = (top + bottom) / temp3;
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[10] = (-zfar - znear) / temp4;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[11] = -1.0f;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[12] = 0.0f;
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[13] = 0.0f;
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[14] = (-temp * zfar) / temp4;
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[15] = 0.0f;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void glhPerspectivef2(Matrix_t mat,
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      GLfloat fovyInDegrees,
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      GLfloat aspectRatio,
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      GLfloat znear,
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      GLfloat zfar) {
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  float ymax, xmax;
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ymax = znear * tanf(fovyInDegrees * 3.14f / 360.0f);
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  xmax = ymax * aspectRatio;
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  glhFrustumf2(mat, -xmax, xmax, -ymax, ymax, znear, zfar);
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void identity_matrix(Matrix_t mat) {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(mat, 0, sizeof(Matrix_t));
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[0] = 1.0;
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[5] = 1.0;
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[10] = 1.0;
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[15] = 1.0;
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void multiply_matrix(const Matrix_t a, const Matrix_t b, Matrix_t mat) {
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Generate to a temporary first in case the output matrix and input
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // matrix are the same.
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Matrix_t out;
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memcpy(mat, out, sizeof(Matrix_t));
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void rotate_x_matrix(GLfloat x_rad, Matrix_t mat) {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  identity_matrix(mat);
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[5] = cosf(x_rad);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[6] = -sinf(x_rad);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[9] = -mat[6];
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[10] = mat[5];
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void rotate_y_matrix(GLfloat y_rad, Matrix_t mat) {
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  identity_matrix(mat);
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[0] = cosf(y_rad);
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[2] = sinf(y_rad);
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[8] = -mat[2];
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[10] = mat[0];
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void rotate_z_matrix(GLfloat z_rad, Matrix_t mat) {
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  identity_matrix(mat);
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[0] = cosf(z_rad);
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[1] = sinf(z_rad);
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[4] = -mat[1];
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[5] = mat[0];
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void rotate_matrix(GLfloat x_deg, GLfloat y_deg, GLfloat z_deg, Matrix_t mat) {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GLfloat x_rad = (GLfloat) deg_to_rad(x_deg);
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GLfloat y_rad = (GLfloat) deg_to_rad(y_deg);
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GLfloat z_rad = (GLfloat) deg_to_rad(z_deg);
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Matrix_t x_matrix;
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Matrix_t y_matrix;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Matrix_t z_matrix;
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotate_x_matrix(x_rad, x_matrix);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotate_y_matrix(y_rad, y_matrix);
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotate_z_matrix(z_rad, z_matrix);
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Matrix_t xy_matrix;
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  multiply_matrix(y_matrix, x_matrix, xy_matrix);
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  multiply_matrix(z_matrix, xy_matrix, mat);
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void translate_matrix(GLfloat x, GLfloat y, GLfloat z, Matrix_t mat) {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  identity_matrix(mat);
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[12] += x;
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[13] += y;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mat[14] += z;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
140