/* * 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; }