266 lines
9.1 KiB
C++
266 lines
9.1 KiB
C++
/*
|
|
* Copyright 2013 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// vecmath.cpp
|
|
//--------------------------------------------------------------------------------
|
|
|
|
#include "vecmath.h"
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// vec3
|
|
//--------------------------------------------------------------------------------
|
|
vec3::vec3(const vec4& vec)
|
|
{
|
|
x = vec.x; y = vec.y; z = vec.z;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// vec4
|
|
//--------------------------------------------------------------------------------
|
|
vec4 vec4::operator*(const mat4& rhs) const
|
|
{
|
|
vec4 out;
|
|
out.x = x * rhs.f[0] + y * rhs.f[1] + z * rhs.f[2] + w * rhs.f[3];
|
|
out.y = x * rhs.f[4] + y * rhs.f[5] + z * rhs.f[6] + w * rhs.f[7];
|
|
out.z = x * rhs.f[8] + y * rhs.f[9] + z * rhs.f[10] + w * rhs.f[11];
|
|
out.w = x * rhs.f[12] + y * rhs.f[13] + z * rhs.f[14] + w * rhs.f[15];
|
|
return out;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// mat4
|
|
//--------------------------------------------------------------------------------
|
|
mat4::mat4()
|
|
{
|
|
for(int32_t i = 0; i < 16; ++i)
|
|
f[i] = 0.f;
|
|
}
|
|
|
|
mat4::mat4(const float* mIn )
|
|
{
|
|
for(int32_t i = 0; i < 16; ++i)
|
|
f[i] = mIn[i];
|
|
}
|
|
|
|
mat4 mat4::operator*(const mat4& rhs) const
|
|
{
|
|
mat4 ret;
|
|
ret.f[0] = f[0]*rhs.f[0] + f[4]*rhs.f[1] + f[8]*rhs.f[2] + f[12]*rhs.f[3];
|
|
ret.f[1] = f[1]*rhs.f[0] + f[5]*rhs.f[1] + f[9]*rhs.f[2] + f[13]*rhs.f[3];
|
|
ret.f[2] = f[2]*rhs.f[0] + f[6]*rhs.f[1] + f[10]*rhs.f[2] + f[14]*rhs.f[3];
|
|
ret.f[3] = f[3]*rhs.f[0] + f[7]*rhs.f[1] + f[11]*rhs.f[2] + f[15]*rhs.f[3];
|
|
|
|
ret.f[4] = f[0]*rhs.f[4] + f[4]*rhs.f[5] + f[8]*rhs.f[6] + f[12]*rhs.f[7];
|
|
ret.f[5] = f[1]*rhs.f[4] + f[5]*rhs.f[5] + f[9]*rhs.f[6] + f[13]*rhs.f[7];
|
|
ret.f[6] = f[2]*rhs.f[4] + f[6]*rhs.f[5] + f[10]*rhs.f[6] + f[14]*rhs.f[7];
|
|
ret.f[7] = f[3]*rhs.f[4] + f[7]*rhs.f[5] + f[11]*rhs.f[6] + f[15]*rhs.f[7];
|
|
|
|
ret.f[8] = f[0]*rhs.f[8] + f[4]*rhs.f[9] + f[8]*rhs.f[10] + f[12]*rhs.f[11];
|
|
ret.f[9] = f[1]*rhs.f[8] + f[5]*rhs.f[9] + f[9]*rhs.f[10] + f[13]*rhs.f[11];
|
|
ret.f[10] = f[2]*rhs.f[8] + f[6]*rhs.f[9] + f[10]*rhs.f[10] + f[14]*rhs.f[11];
|
|
ret.f[11] = f[3]*rhs.f[8] + f[7]*rhs.f[9] + f[11]*rhs.f[10] + f[15]*rhs.f[11];
|
|
|
|
ret.f[12] = f[0]*rhs.f[12] + f[4]*rhs.f[13] + f[8]*rhs.f[14] + f[12]*rhs.f[15];
|
|
ret.f[13] = f[1]*rhs.f[12] + f[5]*rhs.f[13] + f[9]*rhs.f[14] + f[13]*rhs.f[15];
|
|
ret.f[14] = f[2]*rhs.f[12] + f[6]*rhs.f[13] + f[10]*rhs.f[14] + f[14]*rhs.f[15];
|
|
ret.f[15] = f[3]*rhs.f[12] + f[7]*rhs.f[13] + f[11]*rhs.f[14] + f[15]*rhs.f[15];
|
|
|
|
return ret;
|
|
}
|
|
|
|
vec4 mat4::operator*(const vec4& rhs) const
|
|
{
|
|
vec4 ret;
|
|
ret.x = rhs.x*f[0] + rhs.y*f[4] + rhs.z*f[8] + rhs.w*f[12];
|
|
ret.y = rhs.x*f[1] + rhs.y*f[5] + rhs.z*f[9] + rhs.w*f[13];
|
|
ret.z = rhs.x*f[2] + rhs.y*f[6] + rhs.z*f[10] + rhs.w*f[14];
|
|
ret.w = rhs.x*f[3] + rhs.y*f[7] + rhs.z*f[11] + rhs.w*f[15];
|
|
return ret;
|
|
}
|
|
|
|
mat4 mat4::inverse()
|
|
{
|
|
mat4 ret;
|
|
float det_1;
|
|
float pos = 0;
|
|
float neg = 0;
|
|
float temp;
|
|
|
|
temp = f[0] * f[5] * f[10];
|
|
if (temp >= 0) pos += temp; else neg += temp;
|
|
temp = f[4] * f[9] * f[2];
|
|
if (temp >= 0) pos += temp; else neg += temp;
|
|
temp = f[8] * f[1] * f[6];
|
|
if (temp >= 0) pos += temp; else neg += temp;
|
|
temp = -f[8] * f[5] * f[2];
|
|
if (temp >= 0) pos += temp; else neg += temp;
|
|
temp = -f[4] * f[1] * f[10];
|
|
if (temp >= 0) pos += temp; else neg += temp;
|
|
temp = -f[0] * f[9] * f[6];
|
|
if (temp >= 0) pos += temp; else neg += temp;
|
|
det_1 = pos + neg;
|
|
|
|
if (det_1 == 0.0)
|
|
{
|
|
//Error
|
|
}
|
|
else
|
|
{
|
|
det_1 = 1.0f / det_1;
|
|
ret.f[0] = ( f[ 5] * f[10] - f[ 9] * f[ 6] ) * det_1;
|
|
ret.f[1] = -( f[ 1] * f[10] - f[ 9] * f[ 2] ) * det_1;
|
|
ret.f[2] = ( f[ 1] * f[ 6] - f[ 5] * f[ 2] ) * det_1;
|
|
ret.f[4] = -( f[ 4] * f[10] - f[ 8] * f[ 6] ) * det_1;
|
|
ret.f[5] = ( f[ 0] * f[10] - f[ 8] * f[ 2] ) * det_1;
|
|
ret.f[6] = -( f[ 0] * f[ 6] - f[ 4] * f[ 2] ) * det_1;
|
|
ret.f[8] = ( f[ 4] * f[ 9] - f[ 8] * f[ 5] ) * det_1;
|
|
ret.f[9] = -( f[ 0] * f[ 9] - f[ 8] * f[ 1] ) * det_1;
|
|
ret.f[10] = ( f[ 0] * f[ 5] - f[ 4] * f[ 1] ) * det_1;
|
|
|
|
/* Calculate -C * inverse(A) */
|
|
ret.f[12] = - ( f[12] *ret.f[0] + f[13] * ret.f[4] + f[14] *ret.f[8] );
|
|
ret.f[13] = - ( f[12] * ret.f[1] + f[13] * ret.f[5] + f[14] * ret.f[9] );
|
|
ret.f[14] = - ( f[12] * ret.f[2] + f[13] * ret.f[6] + f[14] * ret.f[10] );
|
|
|
|
ret.f[ 3] = 0.0f;
|
|
ret.f[ 7] = 0.0f;
|
|
ret.f[11] = 0.0f;
|
|
ret.f[15] = 1.0f;
|
|
}
|
|
|
|
*this = ret;
|
|
return *this;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// Misc
|
|
//--------------------------------------------------------------------------------
|
|
mat4 mat4::rotationX(
|
|
const float fAngle)
|
|
{
|
|
mat4 ret;
|
|
float fCosine, fSine;
|
|
|
|
fCosine = cosf(fAngle);
|
|
fSine = sinf(fAngle);
|
|
|
|
ret.f[ 0]=1.0f; ret.f[ 4]=0.0f; ret.f[ 8]=0.0f; ret.f[12]=0.0f;
|
|
ret.f[ 1]=0.0f; ret.f[ 5]=fCosine; ret.f[ 9]=fSine; ret.f[13]=0.0f;
|
|
ret.f[ 2]=0.0f; ret.f[ 6]=-fSine; ret.f[10]=fCosine; ret.f[14]=0.0f;
|
|
ret.f[ 3]=0.0f; ret.f[ 7]=0.0f; ret.f[11]=0.0f; ret.f[15]=1.0f;
|
|
return ret;
|
|
}
|
|
|
|
mat4 mat4::rotationY(
|
|
const float fAngle)
|
|
{
|
|
mat4 ret;
|
|
float fCosine, fSine;
|
|
|
|
fCosine = cosf(fAngle);
|
|
fSine = sinf(fAngle);
|
|
|
|
ret.f[ 0]=fCosine; ret.f[ 4]=0.0f; ret.f[ 8]=-fSine; ret.f[12]=0.0f;
|
|
ret.f[ 1]=0.0f; ret.f[ 5]=1.0f; ret.f[ 9]=0.0f; ret.f[13]=0.0f;
|
|
ret.f[ 2]=fSine; ret.f[ 6]=0.0f; ret.f[10]=fCosine; ret.f[14]=0.0f;
|
|
ret.f[ 3]=0.0f; ret.f[ 7]=0.0f; ret.f[11]=0.0f; ret.f[15]=1.0f;
|
|
return ret;
|
|
|
|
}
|
|
|
|
mat4 mat4::rotationZ(
|
|
const float fAngle)
|
|
{
|
|
mat4 ret;
|
|
float fCosine, fSine;
|
|
|
|
fCosine = cosf(fAngle);
|
|
fSine = sinf(fAngle);
|
|
|
|
ret.f[ 0]=fCosine; ret.f[ 4]=fSine; ret.f[ 8]=0.0f; ret.f[12]=0.0f;
|
|
ret.f[ 1]=-fSine; ret.f[ 5]=fCosine; ret.f[ 9]=0.0f; ret.f[13]=0.0f;
|
|
ret.f[ 2]=0.0f; ret.f[ 6]=0.0f; ret.f[10]=1.0f; ret.f[14]=0.0f;
|
|
ret.f[ 3]=0.0f; ret.f[ 7]=0.0f; ret.f[11]=0.0f; ret.f[15]=1.0f;
|
|
return ret;
|
|
}
|
|
|
|
mat4 mat4::translation(
|
|
const float fX,
|
|
const float fY,
|
|
const float fZ)
|
|
{
|
|
mat4 ret;
|
|
ret.f[ 0]=1.0f; ret.f[ 4]=0.0f; ret.f[ 8]=0.0f; ret.f[12]=fX;
|
|
ret.f[ 1]=0.0f; ret.f[ 5]=1.0f; ret.f[ 9]=0.0f; ret.f[13]=fY;
|
|
ret.f[ 2]=0.0f; ret.f[ 6]=0.0f; ret.f[10]=1.0f; ret.f[14]=fZ;
|
|
ret.f[ 3]=0.0f; ret.f[ 7]=0.0f; ret.f[11]=0.0f; ret.f[15]=1.0f;
|
|
return ret;
|
|
}
|
|
|
|
mat4 mat4::translation(
|
|
const vec3 vec)
|
|
{
|
|
mat4 ret;
|
|
ret.f[ 0]=1.0f; ret.f[ 4]=0.0f; ret.f[ 8]=0.0f; ret.f[12]=vec.x;
|
|
ret.f[ 1]=0.0f; ret.f[ 5]=1.0f; ret.f[ 9]=0.0f; ret.f[13]=vec.y;
|
|
ret.f[ 2]=0.0f; ret.f[ 6]=0.0f; ret.f[10]=1.0f; ret.f[14]=vec.z;
|
|
ret.f[ 3]=0.0f; ret.f[ 7]=0.0f; ret.f[11]=0.0f; ret.f[15]=1.0f;
|
|
return ret;
|
|
}
|
|
|
|
mat4 mat4::perspective(
|
|
float width,
|
|
float height,
|
|
float nearPlane, float farPlane)
|
|
{
|
|
float n2 = 2.0f * nearPlane;
|
|
float rcpnmf = 1.f/(nearPlane - farPlane);
|
|
|
|
mat4 result;
|
|
result.f[0] = n2 / width; result.f[4] = 0; result.f[8] = 0; result.f[12] = 0;
|
|
result.f[1] = 0; result.f[5] = n2 / height; result.f[9] = 0; result.f[13] = 0;
|
|
result.f[2] = 0; result.f[6] = 0; result.f[10] = (farPlane+nearPlane)*rcpnmf; result.f[14] = farPlane*rcpnmf*n2;
|
|
result.f[3] = 0; result.f[7] = 0; result.f[11] = -1.0; result.f[15]=0;
|
|
|
|
return result;
|
|
}
|
|
|
|
mat4 mat4::lookAt(const vec3& vEye, const vec3& vAt, const vec3& vUp)
|
|
{
|
|
vec3 vForward, vUpNorm, vSide;
|
|
mat4 result;
|
|
|
|
vForward.x = vEye.x - vAt.x;
|
|
vForward.y = vEye.y - vAt.y;
|
|
vForward.z = vEye.z - vAt.z;
|
|
|
|
vForward.normalize();
|
|
vUpNorm = vUp;
|
|
vUpNorm.normalize();
|
|
vSide = vUpNorm.cross( vForward);
|
|
vUpNorm = vForward.cross(vSide);
|
|
|
|
result.f[0]=vSide.x; result.f[4]=vSide.y; result.f[8]=vSide.z; result.f[12]=0;
|
|
result.f[1]=vUpNorm.x; result.f[5]=vUpNorm.y; result.f[9]=vUpNorm.z; result.f[13]=0;
|
|
result.f[2]=vForward.x; result.f[6]=vForward.y; result.f[10]=vForward.z; result.f[14]=0;
|
|
result.f[3]=0; result.f[7]=0; result.f[11]=0; result.f[15]=1.0;
|
|
|
|
result.postTranslate(-vEye.x, -vEye.y, -vEye.z);
|
|
return result;
|
|
}
|
|
|