blob: b931c8de9684bf5dd72b19319dfa79346b5ad935 [file] [log] [blame]
// 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 <math.h>
#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;
}