// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "matrixop.h" #include #define PI 3.1415926535897932384626433832795f void Matrix4x4_Copy(Matrix4x4 dst, Matrix4x4 src) { int i; for (i = 0; i < 16; ++i) dst[i] = src[i]; } void Matrix4x4_Multiply(Matrix4x4 result, Matrix4x4 mat1, Matrix4x4 mat2) { Matrix4x4 tmp; int i, j, k; for (i = 0; i < 4; i++) { for (j = 0; j < 4; ++j) { tmp[i*4 + j] = 0; for (k = 0; k < 4; ++k) tmp[i*4 + j] += mat1[i*4 + k] * mat2[k*4 + j]; } } Matrix4x4_Copy(result, tmp); } void Matrix4x4_LoadIdentity(Matrix4x4 mat) { int i; for (i = 0; i < 16; ++i) mat[i] = 0; for (i = 0; i < 4; ++i) mat[i*4 + i] = 1.f; } void Matrix4x4_Scale(Matrix4x4 mat, float sx, float sy, float sz) { int i; for (i = 0; i < 4; ++i) { mat[0*4 + i] *= sx; mat[1*4 + i] *= sy; mat[2*4 + i] *= sz; } } void Matrix4x4_Translate(Matrix4x4 mat, float tx, float ty, float tz) { int i; for (i = 0; i < 4; ++i) mat[3*4 + i] += mat[0*4 + i] * tx + mat[1*4 + i] * ty + mat[2*4 + i] * tz; } static float normalize(float *ax, float *ay, float *az) { float norm = sqrtf((*ax) * (*ax) + (*ay) * (*ay) + (*az) * (*az)); if (norm > 0) { *ax /= norm; *ay /= norm; *az /= norm; } return norm; } void Matrix4x4_Rotate(Matrix4x4 mat, float angle, float ax, float ay, float az) { Matrix4x4 rot; float r = angle * PI / 180.f; float s = sinf(r); float c = cosf(r); float one_c = 1.f - c; float xx, yy, zz, xy, yz, xz, xs, ys, zs; float norm = normalize(&ax, &ay, &az); if (norm == 0 || angle == 0) return; xx = ax * ax; yy = ay * ay; zz = az * az; xy = ax * ay; yz = ay * az; xz = ax * az; xs = ax * s; ys = ay * s; zs = az * s; rot[0*4 + 0] = xx + (1.f - xx) * c; rot[1*4 + 0] = xy * one_c - zs; rot[2*4 + 0] = xz * one_c + ys; rot[3*4 + 0] = 0.f; rot[0*4 + 1] = xy * one_c + zs; rot[1*4 + 1] = yy + (1.f - yy) * c; rot[2*4 + 1] = yz * one_c - xs; rot[3*4 + 1] = 0.f; rot[0*4 + 2] = xz * one_c - ys; rot[1*4 + 2] = yz * one_c + xs; rot[2*4 + 2] = zz + (1.f - zz) * c; rot[3*4 + 2] = 0.f; rot[0*4 + 3] = 0.f; rot[1*4 + 3] = 0.f; rot[2*4 + 3] = 0.f; rot[3*4 + 3] = 1.f; Matrix4x4_Multiply(mat, rot, mat); } void Matrix4x4_Frustum(Matrix4x4 mat, float left, float right, float bottom, float top, float near, float far) { float dx = right - left; float dy = top - bottom; float dz = far - near; Matrix4x4 frust; if (near <= 0.f || far <= 0.f || dx <= 0.f || dy <= 0.f || dz <= 0.f) return; frust[0*4 + 0] = 2.f * near / dx; frust[0*4 + 1] = 0.f; frust[0*4 + 2] = 0.f; frust[0*4 + 3] = 0.f; frust[1*4 + 0] = 0.f; frust[1*4 + 1] = 2.f * near / dy; frust[1*4 + 2] = 0.f; frust[1*4 + 3] = 0.f; frust[2*4 + 0] = (right + left) / dx; frust[2*4 + 1] = (top + bottom) / dy; frust[2*4 + 2] = -(near + far) / dz; frust[2*4 + 3] = -1.f; frust[3*4 + 0] = 0.f; frust[3*4 + 1] = 0.f; frust[3*4 + 2] = -2.f * near * far / dz; frust[3*4 + 3] = 0.f; Matrix4x4_Multiply(mat, frust, mat); } void Matrix4x4_Perspective(Matrix4x4 mat, float fovy, float aspect, float nearZ, float farZ) { float frustumW, frustumH; frustumH = tanf(fovy / 360.f * PI) * nearZ; frustumW = frustumH * aspect; Matrix4x4_Frustum(mat, -frustumW, frustumW, -frustumH, frustumH, nearZ, farZ); } void Matrix4x4_Transform(Matrix4x4 mat, float *x, float *y, float *z) { float tx = mat[0*4 + 0] * (*x) + mat[1*4 + 0] * (*y) + mat[2*4 + 0] * (*z); float ty = mat[0*4 + 1] * (*x) + mat[1*4 + 1] * (*y) + mat[2*4 + 1] * (*z); float tz = mat[0*4 + 2] * (*x) + mat[1*4 + 2] * (*y) + mat[2*4 + 2] * (*z); *x = tx; *y = ty; *z = tz; }