Files
android_development/ndk/sources/android/helper/vecmath.h
Hak Matsuda 5d1c91fb75 cleaned code, added pinch gesture detector, better opengl context handling, fixed issues
Change-Id: I26a28374ae74391204586b4584d03cf0c58772c2
2013-10-28 11:41:58 +08:00

1052 lines
22 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.
*/
#ifndef VECMATH_H_
#define VECMATH_H_
#include <math.h>
#include "JNIHelper.h"
/******************************************************************
* Helper class for vector math operations
* Currently all implementations are in pure C++.
* Each class is an opaque class so caller does not have a direct access
* to each element. This is for an ease of future optimization to use vector operations.
*
*/
class vec2;
class vec3;
class vec4;
class mat4;
/******************************************************************
* 2 elements vector class
*
*/
class vec2
{
private:
float x,y;
public:
friend class vec3;
friend class vec4;
friend class mat4;
friend class quaternion;
vec2()
{
x = y = 0.f;
}
vec2(const float fX, const float fY)
{
x = fX; y = fY;
}
vec2(const vec2& vec)
{
x = vec.x;
y = vec.y;
}
vec2(const float* pVec)
{
x = (*pVec++); y = (*pVec++);
}
//Operators
vec2 operator*(const vec2& rhs) const
{
vec2 ret;
ret.x = x*rhs.x;
ret.y = y*rhs.y;
return ret;
}
vec2 operator/(const vec2& rhs) const
{
vec2 ret;
ret.x = x/rhs.x;
ret.y = y/rhs.y;
return ret;
}
vec2 operator+(const vec2& rhs) const
{
vec2 ret;
ret.x = x + rhs.x;
ret.y = y + rhs.y;
return ret;
}
vec2 operator-(const vec2& rhs) const
{
vec2 ret;
ret.x = x - rhs.x;
ret.y = y - rhs.y;
return ret;
}
vec2& operator+=(const vec2& rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
}
vec2& operator-=(const vec2& rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
vec2& operator*=(const vec2& rhs)
{
x *= rhs.x;
y *= rhs.y;
return *this;
}
vec2& operator/=(const vec2& rhs)
{
x /= rhs.x;
y /= rhs.y;
return *this;
}
//External operators
friend vec2 operator-(const vec2& rhs) { return vec2(rhs) *= -1; }
friend vec2 operator*(const float lhs, const vec2& rhs)
{
vec2 ret;
ret.x = lhs * rhs.x;
ret.y = lhs * rhs.y;
return ret;
}
friend vec2 operator/(const float lhs, const vec2& rhs)
{
vec2 ret;
ret.x = lhs / rhs.x;
ret.y = lhs / rhs.y;
return ret;
}
//Operators with float
vec2 operator*(const float& rhs) const
{
vec2 ret;
ret.x = x * rhs;
ret.y = y * rhs;
return ret;
}
vec2& operator*=(const float& rhs)
{
x = x * rhs;
y = y * rhs;
return *this;
}
vec2 operator/(const float& rhs) const
{
vec2 ret;
ret.x = x / rhs;
ret.y = y / rhs;
return ret;
}
vec2& operator/=(const float& rhs)
{
x = x / rhs;
y = y / rhs;
return *this;
}
//Compare
bool operator==(const vec2& rhs) const
{
if(x != rhs.x || y != rhs.y ) return false;
return true;
}
bool operator!=(const vec2& rhs) const
{
if(x == rhs.x)
return false;
return true;
}
float length() const
{
return sqrtf(x*x + y*y);
}
vec2 normalize()
{
float len = length();
x = x / len;
y = y / len;
return *this;
}
float dot(const vec2& rhs)
{
return x * rhs.x + y*rhs.y;
}
bool validate()
{
if( isnan( x ) || isnan( y ) )
return false;
return true;
}
void value(float& fX, float& fY)
{
fX = x;
fY = y;
}
void dump()
{
LOGI("vec2 %f %f", x, y);
}
};
/******************************************************************
* 3 elements vector class
*
*/
class vec3
{
private:
float x,y,z;
public:
friend class vec4;
friend class mat4;
friend class quaternion;
vec3()
{
x = y = z = 0.f;
}
vec3(const float fX, const float fY, const float fZ)
{
x = fX; y = fY; z = fZ;
}
vec3(const vec3& vec)
{
x = vec.x;
y = vec.y;
z = vec.z;
}
vec3(const float* pVec)
{
x = (*pVec++); y = (*pVec++); z = *pVec;
}
vec3(const vec2& vec, float f )
{
x = vec.x;
y = vec.y;
z = f;
}
vec3(const vec4& vec );
//Operators
vec3 operator*(const vec3& rhs) const
{
vec3 ret;
ret.x = x*rhs.x;
ret.y = y*rhs.y;
ret.z = z*rhs.z;
return ret;
}
vec3 operator/(const vec3& rhs) const
{
vec3 ret;
ret.x = x/rhs.x;
ret.y = y/rhs.y;
ret.z = z/rhs.z;
return ret;
}
vec3 operator+(const vec3& rhs) const
{
vec3 ret;
ret.x = x + rhs.x;
ret.y = y + rhs.y;
ret.z = z + rhs.z;
return ret;
}
vec3 operator-(const vec3& rhs) const
{
vec3 ret;
ret.x = x - rhs.x;
ret.y = y - rhs.y;
ret.z = z - rhs.z;
return ret;
}
vec3& operator+=(const vec3& rhs)
{
x += rhs.x;
y += rhs.y;
z += rhs.z;
return *this;
}
vec3& operator-=(const vec3& rhs)
{
x -= rhs.x;
y -= rhs.y;
z -= rhs.z;
return *this;
}
vec3& operator*=(const vec3& rhs)
{
x *= rhs.x;
y *= rhs.y;
z *= rhs.z;
return *this;
}
vec3& operator/=(const vec3& rhs)
{
x /= rhs.x;
y /= rhs.y;
z /= rhs.z;
return *this;
}
//External operators
friend vec3 operator-(const vec3& rhs) { return vec3(rhs) *= -1; }
friend vec3 operator*(const float lhs, const vec3& rhs)
{
vec3 ret;
ret.x = lhs * rhs.x;
ret.y = lhs * rhs.y;
ret.z = lhs * rhs.z;
return ret;
}
friend vec3 operator/(const float lhs, const vec3& rhs)
{
vec3 ret;
ret.x = lhs / rhs.x;
ret.y = lhs / rhs.y;
ret.z = lhs / rhs.z;
return ret;
}
//Operators with float
vec3 operator*(const float& rhs) const
{
vec3 ret;
ret.x = x * rhs;
ret.y = y * rhs;
ret.z = z * rhs;
return ret;
}
vec3& operator*=(const float& rhs)
{
x = x * rhs;
y = y * rhs;
z = z * rhs;
return *this;
}
vec3 operator/(const float& rhs) const
{
vec3 ret;
ret.x = x / rhs;
ret.y = y / rhs;
ret.z = z / rhs;
return ret;
}
vec3& operator/=(const float& rhs)
{
x = x / rhs;
y = y / rhs;
z = z / rhs;
return *this;
}
//Compare
bool operator==(const vec3& rhs) const
{
if(x != rhs.x || y != rhs.y || z != rhs.z) return false;
return true;
}
bool operator!=(const vec3& rhs) const
{
if(x == rhs.x)
return false;
return true;
}
float length() const
{
return sqrtf(x*x + y*y + z*z);
}
vec3 normalize()
{
float len = length();
x = x / len;
y = y / len;
z = z / len;
return *this;
}
float dot(const vec3& rhs)
{
return x * rhs.x + y*rhs.y + z*rhs.z;
}
vec3 cross(const vec3& rhs)
{
vec3 ret;
ret.x = y*rhs.z - z*rhs.y;
ret.y = z*rhs.x - x*rhs.z;
ret.z = x*rhs.y - y*rhs.x;
return ret;
}
bool validate()
{
if( isnan( x ) || isnan( y ) || isnan( z ) )
return false;
return true;
}
void value(float& fX, float& fY, float& fZ)
{
fX = x;
fY = y;
fZ = z;
}
void dump()
{
LOGI("vec3 %f %f %f", x, y, z);
}
};
/******************************************************************
* 4 elements vector class
*
*/
class vec4
{
private:
float x,y,z,w;
public:
friend class vec3;
friend class mat4;
friend class quaternion;
vec4()
{
x = y = z = w = 0.f;
}
vec4(const float fX, const float fY, const float fZ, const float fW )
{
x = fX; y = fY; z = fZ; w = fW;
}
vec4(const vec4& vec)
{
x = vec.x;
y = vec.y;
z = vec.z;
w = vec.w;
}
vec4(const vec3& vec, const float fW )
{
x = vec.x; y = vec.y; z = vec.z; w = fW;
}
vec4(const float* pVec)
{
x = (*pVec++); y = (*pVec++); z = *pVec; w = *pVec;
}
//Operators
vec4 operator*(const vec4& rhs) const
{
vec4 ret;
ret.x = x*rhs.x;
ret.y = y*rhs.y;
ret.z = z*rhs.z;
ret.w = z*rhs.w;
return ret;
}
vec4 operator/(const vec4& rhs) const
{
vec4 ret;
ret.x = x/rhs.x;
ret.y = y/rhs.y;
ret.z = z/rhs.z;
ret.w = z/rhs.w;
return ret;
}
vec4 operator+(const vec4& rhs) const
{
vec4 ret;
ret.x = x+rhs.x;
ret.y = y+rhs.y;
ret.z = z+rhs.z;
ret.w = z+rhs.w;
return ret;
}
vec4 operator-(const vec4& rhs) const
{
vec4 ret;
ret.x = x-rhs.x;
ret.y = y-rhs.y;
ret.z = z-rhs.z;
ret.w = z-rhs.w;
return ret;
}
vec4& operator+=(const vec4& rhs)
{
x += rhs.x;
y += rhs.y;
z += rhs.z;
w += rhs.w;
return *this;
}
vec4& operator-=(const vec4& rhs)
{
x -= rhs.x;
y -= rhs.y;
z -= rhs.z;
w -= rhs.w;
return *this;
}
vec4& operator*=(const vec4& rhs)
{
x *= rhs.x;
y *= rhs.y;
z *= rhs.z;
w *= rhs.w;
return *this;
}
vec4& operator/=(const vec4& rhs)
{
x /= rhs.x;
y /= rhs.y;
z /= rhs.z;
w /= rhs.w;
return *this;
}
//External operators
friend vec4 operator-(const vec4& rhs) { return vec4(rhs) *= -1; }
friend vec4 operator*(const float lhs, const vec4& rhs)
{
vec4 ret;
ret.x = lhs * rhs.x;
ret.y = lhs * rhs.y;
ret.z = lhs * rhs.z;
ret.w = lhs * rhs.w;
return ret;
}
friend vec4 operator/(const float lhs, const vec4& rhs)
{
vec4 ret;
ret.x = lhs / rhs.x;
ret.y = lhs / rhs.y;
ret.z = lhs / rhs.z;
ret.w = lhs / rhs.w;
return ret;
}
//Operators with float
vec4 operator*(const float& rhs) const
{
vec4 ret;
ret.x = x * rhs;
ret.y = y * rhs;
ret.z = z * rhs;
ret.w = w * rhs;
return ret;
}
vec4& operator*=(const float& rhs)
{
x = x * rhs;
y = y * rhs;
z = z * rhs;
w = w * rhs;
return *this;
}
vec4 operator/(const float& rhs) const
{
vec4 ret;
ret.x = x / rhs;
ret.y = y / rhs;
ret.z = z /rhs;
ret.w = w /rhs;
return ret;
}
vec4& operator/=(const float& rhs)
{
x = x / rhs;
y = y / rhs;
z = z / rhs;
w = w / rhs;
return *this;
}
//Compare
bool operator==(const vec4& rhs) const
{
if(x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w) return false;
return true;
}
bool operator!=(const vec4& rhs) const
{
if(x == rhs.x)
return false;
return true;
}
vec4 operator*(const mat4& rhs) const;
float length() const
{
return sqrtf(x*x + y*y + z*z + w*w);
}
vec4 normalize()
{
float len = length();
x = x / len;
y = y / len;
z = z / len;
w = w / len;
return *this;
}
float dot(const vec3& rhs)
{
return x * rhs.x + y*rhs.y + z*rhs.z;
}
vec3 cross(const vec3& rhs)
{
vec3 ret;
ret.x = y*rhs.z - z*rhs.y;
ret.y = z*rhs.x - x*rhs.z;
ret.z = x*rhs.y - y*rhs.x;
return ret;
}
bool validate()
{
if( isnan( x ) || isnan( y ) || isnan( z ) || isnan( w ))
return false;
return true;
}
void value(float& fX, float& fY, float& fZ, float& fW)
{
fX = x;
fY = y;
fZ = z;
fW = w;
}
};
/******************************************************************
* 4x4 matrix
*
*/
class mat4
{
private:
float f[16];
public:
friend class vec3;
friend class vec4;
friend class quaternion;
mat4();
mat4(const float*);
mat4 operator*(const mat4& rhs) const;
vec4 operator*(const vec4& rhs) const;
mat4 operator+(const mat4& rhs) const
{
mat4 ret;
for(int32_t i=0; i < 16; ++i)
{
ret.f[i] = f[i] + rhs.f[i];
}
return ret;
}
mat4 operator-(const mat4& rhs) const
{
mat4 ret;
for(int32_t i=0; i < 16; ++i)
{
ret.f[i] = f[i] - rhs.f[i];
}
return ret;
}
mat4& operator+=(const mat4& rhs)
{
for(int32_t i=0; i < 16; ++i)
{
f[i] += rhs.f[i];
}
return *this;
}
mat4& operator-=(const mat4& rhs)
{
for(int32_t i=0; i < 16; ++i)
{
f[i] -= rhs.f[i];
}
return *this;
}
mat4& operator*=(const mat4& rhs)
{
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];
*this = ret;
return *this;
}
mat4 operator*(const float rhs)
{
mat4 ret;
for(int32_t i=0; i < 16; ++i)
{
ret.f[i] = f[i] * rhs;
}
return ret;
}
mat4& operator*=(const float rhs)
{
for(int32_t i=0; i < 16; ++i)
{
f[i] *= rhs;
}
return *this;
}
mat4& operator=(const mat4& rhs)
{
for(int32_t i=0; i < 16; ++i)
{
f[i] = rhs.f[i];
}
return *this;
}
mat4 inverse();
mat4 transpose()
{
mat4 ret;
ret.f[0] = f[0]; ret.f[1] = f[4]; ret.f[2] = f[8]; ret.f[3] = f[12];
ret.f[4] = f[1]; ret.f[5] = f[5]; ret.f[6] = f[9]; ret.f[7] = f[13];
ret.f[8] = f[2]; ret.f[9] = f[6]; ret.f[10] = f[10]; ret.f[11] = f[14];
ret.f[12] = f[3]; ret.f[13] = f[7]; ret.f[14] = f[11]; ret.f[15] = f[15];
*this = ret;
return *this;
}
mat4& postTranslate(float tx, float ty, float tz)
{
f[12] += (tx*f[0])+(ty*f[4])+(tz*f[8]);
f[13] += (tx*f[1])+(ty*f[5])+(tz*f[9]);
f[14] += (tx*f[2])+(ty*f[6])+(tz*f[10]);
f[15] += (tx*f[3])+(ty*f[7])+(tz*f[11]);
return *this;
}
float* ptr() {
return f;
}
//--------------------------------------------------------------------------------
// Misc
//--------------------------------------------------------------------------------
static mat4 perspective(
float width,
float height,
float nearPlane, float farPlane);
static mat4 lookAt(const vec3& vEye, const vec3& vAt, const vec3& vUp);
static mat4 translation(
const float fX,
const float fY,
const float fZ);
static mat4 translation(
const vec3 vec);
static mat4 rotationX(
const float fAngle);
static mat4 rotationY(const float fAngle);
static mat4 rotationZ(const float fAngle);
static mat4 identity()
{
mat4 ret;
ret.f[0] = 1.f; ret.f[1] = 0; ret.f[2] = 0; ret.f[3] = 0;
ret.f[4] = 0; ret.f[5] = 1.f; ret.f[6] = 0; ret.f[7] = 0;
ret.f[8] = 0; ret.f[9] = 0; ret.f[10] = 1.f;ret.f[11] = 0;
ret.f[12] = 0; ret.f[13] = 0; ret.f[14] = 0; ret.f[15] = 1.f;
return ret;
}
void dump()
{
LOGI("%f %f %f %f", f[0], f[1], f[2], f[3]);
LOGI("%f %f %f %f", f[4], f[5], f[6], f[7]);
LOGI("%f %f %f %f", f[8], f[9], f[10], f[11]);
LOGI("%f %f %f %f", f[12], f[13], f[14], f[15]);
}
};
/******************************************************************
* quaternion class
*
*/
class quaternion
{
private:
float x,y,z,w;
public:
friend class vec3;
friend class vec4;
friend class mat4;
quaternion()
{
x = 0.f;
y = 0.f;
z = 0.f;
w = 1.f;
}
quaternion(const float fX, const float fY, const float fZ, const float fW)
{
x = fX;
y = fY;
z = fZ;
w = fW;
}
quaternion(const vec3 vec, const float fW)
{
x = vec.x;
y = vec.y;
z = vec.z;
w = fW;
}
quaternion(const float* p)
{
x = *p++;
y = *p++;
z = *p++;
w = *p++;
}
quaternion operator*(const quaternion rhs)
{
quaternion ret;
ret.x = x * rhs.w + y * rhs.z - z * rhs.y + w * rhs.x;
ret.y = -x * rhs.z + y * rhs.w + z * rhs.x + w * rhs.y;
ret.z = x * rhs.y - y * rhs.x + z * rhs.w + w * rhs.z;
ret.w = -x * rhs.x - y * rhs.y - z * rhs.z + w * rhs.w;
return ret;
}
quaternion& operator*=(const quaternion rhs)
{
quaternion ret;
ret.x = x * rhs.w + y * rhs.z - z * rhs.y + w * rhs.x;
ret.y = -x * rhs.z + y * rhs.w + z * rhs.x + w * rhs.y;
ret.z = x * rhs.y - y * rhs.x + z * rhs.w + w * rhs.z;
ret.w = -x * rhs.x - y * rhs.y - z * rhs.z + w * rhs.w;
*this = ret;
return *this;
}
quaternion conjugate()
{
x = -x;
y = -y;
z = -z;
return *this;
}
//Non destuctive version
quaternion conjugated()
{
quaternion ret;
ret.x = -x;
ret.y = -y;
ret.z = -z;
ret.w = w;
return ret;
}
void toMatrix(mat4& mat)
{
float x2 = x * x * 2.0f;
float y2 = y * y * 2.0f;
float z2 = z * z * 2.0f;
float xy = x * y * 2.0f;
float yz = y * z * 2.0f;
float zx = z * x * 2.0f;
float xw = x * w * 2.0f;
float yw = y * w * 2.0f;
float zw = z * w * 2.0f;
mat.f[0] = 1.0f - y2 - z2;
mat.f[1] = xy + zw;
mat.f[2] = zx - yw;
mat.f[4] = xy - zw;
mat.f[5] = 1.0f - z2 - x2;
mat.f[6] = yz + xw;
mat.f[8] = zx + yw;
mat.f[9] = yz - xw;
mat.f[10] = 1.0f - x2 - y2;
mat.f[3] = mat.f[7] = mat.f[11] = mat.f[12] = mat.f[13] = mat.f[14] = 0.0f;
mat.f[15] = 1.0f;
}
void toMatrixPreserveTranslate(mat4& mat)
{
float x2 = x * x * 2.0f;
float y2 = y * y * 2.0f;
float z2 = z * z * 2.0f;
float xy = x * y * 2.0f;
float yz = y * z * 2.0f;
float zx = z * x * 2.0f;
float xw = x * w * 2.0f;
float yw = y * w * 2.0f;
float zw = z * w * 2.0f;
mat.f[0] = 1.0f - y2 - z2;
mat.f[1] = xy + zw;
mat.f[2] = zx - yw;
mat.f[4] = xy - zw;
mat.f[5] = 1.0f - z2 - x2;
mat.f[6] = yz + xw;
mat.f[8] = zx + yw;
mat.f[9] = yz - xw;
mat.f[10] = 1.0f - x2 - y2;
mat.f[3] = mat.f[7] = mat.f[11] = 0.0f;
mat.f[15] = 1.0f;
}
static quaternion rotationAxis(const vec3 axis, const float angle )
{
quaternion ret;
float s = sinf(angle / 2);
ret.x = s * axis.x;
ret.y = s * axis.y;
ret.z = s * axis.z;
ret.w = cosf( angle / 2 );
return ret;
}
void value(float& fX, float& fY, float& fZ, float& fW)
{
fX = x;
fY = y;
fZ = z;
fW = w;
}
};
#endif /* VECMATH_H_ */