Add a new OpenGL pyramid sample
This sample shows the use of modern OpenGL (3.2). Closes #16910.
This commit is contained in:
committed by
Vadim Zeitlin
parent
bdc95f5766
commit
d6fb44e158
268
samples/opengl/pyramid/mathstuff.cpp
Normal file
268
samples/opengl/pyramid/mathstuff.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: mathstuff.cpp
|
||||
// Purpose: Some maths used for pyramid sample
|
||||
// Author: Manuel Martin
|
||||
// Created: 2015/01/31
|
||||
// Copyright: (c) 2015 Manuel Martin
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "mathstuff.h"
|
||||
|
||||
// Overload of "-" operator
|
||||
myVec3 operator- (const myVec3& v1, const myVec3& v2)
|
||||
{
|
||||
return myVec3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
|
||||
}
|
||||
|
||||
// Vector normalization
|
||||
myVec3 MyNormalize(const myVec3& v)
|
||||
{
|
||||
double mo = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
if ( mo > 1E-20 )
|
||||
return myVec3(v.x / mo, v.y / mo, v.z / mo);
|
||||
else
|
||||
return myVec3();
|
||||
}
|
||||
|
||||
// Dot product
|
||||
double MyDot(const myVec3& v1, const myVec3& v2)
|
||||
{
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z ;
|
||||
}
|
||||
|
||||
// Cross product
|
||||
myVec3 MyCross(const myVec3& v1, const myVec3& v2)
|
||||
{
|
||||
return myVec3( v1.y * v2.z - v2.y * v1.z,
|
||||
v1.z * v2.x - v2.z * v1.x,
|
||||
v1.x * v2.y - v2.x * v1.y );
|
||||
}
|
||||
|
||||
// Distance between two points
|
||||
double MyDistance(const myVec3& v1, const myVec3& v2)
|
||||
{
|
||||
double rx = v1.x -v2.x;
|
||||
double ry = v1.y -v2.y;
|
||||
double rz = v1.z -v2.z;
|
||||
|
||||
return sqrt(rx*rx + ry*ry + rz*rz);
|
||||
}
|
||||
|
||||
// Angle between two normalized vectors, in radians
|
||||
double AngleBetween(myVec3 v1, myVec3 v2)
|
||||
{
|
||||
double angle = MyDot(v1, v2);
|
||||
// Prevent issues due to numerical precision
|
||||
if (angle > 1.0)
|
||||
angle = 1.0;
|
||||
if (angle < -1.0)
|
||||
angle = -1.0;
|
||||
|
||||
return acos(angle);
|
||||
}
|
||||
|
||||
// Matrix 4x4 by 4x1 multiplication
|
||||
// Attention: No bounds check!
|
||||
myVec4 MyMatMul4x1(const float *m1, const myVec4& v)
|
||||
{
|
||||
myVec4 mmv;
|
||||
mmv.x = (double) m1[0] * v.x + m1[4] * v.y + m1[8] * v.z + m1[12] * v.w ;
|
||||
mmv.y = (double) m1[1] * v.x + m1[5] * v.y + m1[9] * v.z + m1[13] * v.w ;
|
||||
mmv.z = (double) m1[2] * v.x + m1[6] * v.y + m1[10] * v.z + m1[14] * v.w ;
|
||||
mmv.w = (double) m1[3] * v.x + m1[7] * v.y + m1[11] * v.z + m1[15] * v.w ;
|
||||
|
||||
return mmv;
|
||||
}
|
||||
|
||||
// Matrix 4x4 multiplication
|
||||
// Attention: No bounds check!
|
||||
void MyMatMul4x4(const float *m1, const float *m2, float* mm)
|
||||
{
|
||||
mm[0] = (double) m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3] ;
|
||||
mm[1] = (double) m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3] ;
|
||||
mm[2] = (double) m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3] ;
|
||||
mm[3] = (double) m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3] ;
|
||||
mm[4] = (double) m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7] ;
|
||||
mm[5] = (double) m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7] ;
|
||||
mm[6] = (double) m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7] ;
|
||||
mm[7] = (double) m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7] ;
|
||||
mm[8] = (double) m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11] ;
|
||||
mm[9] = (double) m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11] ;
|
||||
mm[10] = (double) m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11] ;
|
||||
mm[11] = (double) m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11] ;
|
||||
mm[12] = (double) m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15] ;
|
||||
mm[13] = (double) m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15] ;
|
||||
mm[14] = (double) m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15] ;
|
||||
mm[15] = (double) m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15] ;
|
||||
}
|
||||
|
||||
// Matrix 4x4 inverse. Returns the determinant.
|
||||
// Attention: No bounds check!
|
||||
// Method used is "adjugate matrix" with "cofactors".
|
||||
// A faster method, such as "LU decomposition", isn't much faster than this code.
|
||||
double MyMatInverse(const float *m, float *minv)
|
||||
{
|
||||
double det;
|
||||
double cof[16], sdt[19];
|
||||
|
||||
// The 2x2 determinants used for cofactors
|
||||
sdt[0] = (double) m[10] * m[15] - m[14] * m[11] ;
|
||||
sdt[1] = (double) m[9] * m[15] - m[13] * m[11] ;
|
||||
sdt[2] = (double) m[9] * m[14] - m[13] * m[10] ;
|
||||
sdt[3] = (double) m[8] * m[15] - m[12] * m[11] ;
|
||||
sdt[4] = (double) m[8] * m[14] - m[12] * m[10] ;
|
||||
sdt[5] = (double) m[8] * m[13] - m[12] * m[9] ;
|
||||
sdt[6] = (double) m[6] * m[15] - m[14] * m[7] ;
|
||||
sdt[7] = (double) m[5] * m[15] - m[13] * m[7] ;
|
||||
sdt[8] = (double) m[5] * m[14] - m[13] * m[6] ;
|
||||
sdt[9] = (double) m[4] * m[15] - m[12] * m[7] ;
|
||||
sdt[10] = (double) m[4] * m[14] - m[12] * m[6] ;
|
||||
sdt[11] = (double) m[5] * m[15] - m[13] * m[7] ;
|
||||
sdt[12] = (double) m[4] * m[13] - m[12] * m[5] ;
|
||||
sdt[13] = (double) m[6] * m[11] - m[10] * m[7] ;
|
||||
sdt[14] = (double) m[5] * m[11] - m[9] * m[7] ;
|
||||
sdt[15] = (double) m[5] * m[10] - m[9] * m[6] ;
|
||||
sdt[16] = (double) m[4] * m[11] - m[8] * m[7] ;
|
||||
sdt[17] = (double) m[4] * m[10] - m[8] * m[6] ;
|
||||
sdt[18] = (double) m[4] * m[9] - m[8] * m[5] ;
|
||||
// The cofactors, transposed
|
||||
cof[0] = m[5] * sdt[0] - m[6] * sdt[1] + m[7] * sdt[2] ;
|
||||
cof[1] = - m[1] * sdt[0] + m[2] * sdt[1] - m[3] * sdt[2] ;
|
||||
cof[2] = m[1] * sdt[6] - m[2] * sdt[7] + m[3] * sdt[8] ;
|
||||
cof[3] = - m[1] * sdt[13] + m[2] * sdt[14] - m[3] * sdt[15] ;
|
||||
cof[4] = - m[4] * sdt[0] + m[6] * sdt[3] - m[7] * sdt[4] ;
|
||||
cof[5] = m[0] * sdt[0] - m[2] * sdt[3] + m[3] * sdt[4] ;
|
||||
cof[6] = - m[0] * sdt[6] + m[2] * sdt[9] - m[3] * sdt[10] ;
|
||||
cof[7] = m[0] * sdt[13] - m[2] * sdt[16] + m[3] * sdt[17] ;
|
||||
cof[8] = m[4] * sdt[1] - m[5] * sdt[3] + m[7] * sdt[5] ;
|
||||
cof[9] = - m[0] * sdt[1] + m[1] * sdt[3] - m[3] * sdt[5] ;
|
||||
cof[10] = m[0] * sdt[11] - m[1] * sdt[9] + m[3] * sdt[12] ;
|
||||
cof[11] = - m[0] * sdt[14] + m[1] * sdt[16] - m[3] * sdt[18] ;
|
||||
cof[12] = - m[4] * sdt[2] + m[5] * sdt[4] - m[6] * sdt[5] ;
|
||||
cof[13] = m[0] * sdt[2] - m[1] * sdt[4] + m[2] * sdt[5] ;
|
||||
cof[14] = - m[0] * sdt[8] + m[1] * sdt[10] - m[2] * sdt[12] ;
|
||||
cof[15] = m[0] * sdt[15] - m[1] * sdt[17] + m[2] * sdt[18] ;
|
||||
|
||||
det = m[0] * cof[0] + m[1] * cof[4] + m[2] * cof[8] + m[3] * cof[12] ;
|
||||
|
||||
if ( fabs(det) > 10E-9 ) // Some precision value
|
||||
{
|
||||
double invdet = 1.0 / det;
|
||||
for (int i = 0; i < 16; ++i)
|
||||
minv[i] = cof[i] * invdet;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable comparison with 0
|
||||
det = 0.0;
|
||||
}
|
||||
|
||||
return det;
|
||||
}
|
||||
|
||||
// Matrix of rotation around an axis in the origin.
|
||||
// angle is positive if follows axis (right-hand rule)
|
||||
// Attention: No bounds check!
|
||||
void MyRotate(const myVec3& axis, double angle, float *mrot)
|
||||
{
|
||||
double c = cos(angle);
|
||||
double s = sin(angle);
|
||||
double t = 1.0 - c;
|
||||
|
||||
// Normalize the axis vector
|
||||
myVec3 uv = MyNormalize(axis);
|
||||
|
||||
// Store the matrix in column order
|
||||
mrot[0] = t * uv.x * uv.x + c ;
|
||||
mrot[1] = t * uv.x * uv.y + s * uv.z ;
|
||||
mrot[2] = t * uv.x * uv.z - s * uv.y ;
|
||||
mrot[3] = 0.0 ;
|
||||
mrot[4] = t * uv.y * uv.x - s * uv.z ;
|
||||
mrot[5] = t * uv.y * uv.y + c ;
|
||||
mrot[6] = t * uv.y * uv.z + s * uv.x ;
|
||||
mrot[7] = 0.0 ;
|
||||
mrot[8] = t * uv.z * uv.x + s * uv.y ;
|
||||
mrot[9] = t * uv.z * uv.y - s * uv.x ;
|
||||
mrot[10] = t * uv.z * uv.z + c ;
|
||||
mrot[11] = 0.0 ;
|
||||
mrot[12] = mrot[13] = mrot[14] = 0.0 ;
|
||||
mrot[15] = 1.0 ;
|
||||
}
|
||||
|
||||
// Matrix for defining the viewing transformation
|
||||
// Attention: No bounds check!
|
||||
// Unchecked conditions:
|
||||
// camPos != targ && camUp != {0,0,0}
|
||||
// camUo can't be parallel to camPos - targ
|
||||
void MyLookAt(const myVec3& camPos, const myVec3& camUp, const myVec3& targ, float *mt)
|
||||
{
|
||||
myVec3 tc = MyNormalize(targ - camPos);
|
||||
myVec3 up = MyNormalize(camUp);
|
||||
// Normalize tc x up for the case where up is not perpendicular to tc
|
||||
myVec3 s = MyNormalize(MyCross(tc, up));
|
||||
myVec3 u = MyNormalize(MyCross(s, tc)); //Normalize to improve accuracy
|
||||
|
||||
// Store the matrix in column order
|
||||
mt[0] = s.x ;
|
||||
mt[1] = u.x ;
|
||||
mt[2] = - tc.x ;
|
||||
mt[3] = 0.0 ;
|
||||
mt[4] = s.y ;
|
||||
mt[5] = u.y ;
|
||||
mt[6] = - tc.y ;
|
||||
mt[7] = 0.0 ;
|
||||
mt[8] = s.z ;
|
||||
mt[9] = u.z ;
|
||||
mt[10] = - tc.z ;
|
||||
mt[11] = 0.0 ;
|
||||
mt[12] = - MyDot(s, camPos) ;
|
||||
mt[13] = - MyDot(u, camPos) ;
|
||||
mt[14] = MyDot(tc, camPos) ;
|
||||
mt[15] = 1.0 ;
|
||||
}
|
||||
|
||||
// Matrix for defining the perspective projection with symmetric frustum
|
||||
// From camera coordinates to canonical (2x2x2 cube) coordinates.
|
||||
// Attention: No bounds check!
|
||||
// Unchecked conditions: fov > 0 && zNear > 0 && zFar > zNear && aspect > 0
|
||||
void MyPerspective(double fov, double aspect, double zNear, double zFar, float *mp)
|
||||
{
|
||||
double f = 1.0 / tan(fov / 2.0);
|
||||
|
||||
// Store the matrix in column order
|
||||
mp[0] = f / aspect ;
|
||||
mp[1] = mp[2] = mp[3] = 0.0 ;
|
||||
mp[4] = 0.0 ;
|
||||
mp[5] = f ;
|
||||
mp[6] = mp[7] = 0.0 ;
|
||||
mp[8] = mp[9] = 0.0 ;
|
||||
mp[10] = (zNear + zFar) / (zNear - zFar) ;
|
||||
mp[11] = -1.0 ;
|
||||
mp[12] = mp[13] = 0.0 ;
|
||||
mp[14] = 2.0 * zNear * zFar / (zNear - zFar) ;
|
||||
mp[15] = 0.0 ;
|
||||
}
|
||||
|
||||
// Matrix for defining the orthogonal projection with symmetric frustum
|
||||
// From camera coordinates to canonical (2x2x2 cube) coordinates.
|
||||
// Attention: No bounds check!
|
||||
// Unchecked conditions: left != right && bottom != top && zNear != zFar
|
||||
void MyOrtho(double left, double right, double bottom, double top,
|
||||
double zNear, double zFar, float *mo)
|
||||
{
|
||||
// Store the matrix in column order
|
||||
mo[0] = 2.0 / (right - left) ;
|
||||
mo[1] = mo[2] = mo[3] = mo[4] = 0.0 ;
|
||||
mo[5] = 2.0 / (top - bottom) ;
|
||||
mo[6] = mo[7] = mo[8] = mo[9] = 0.0 ;
|
||||
mo[10] = 2.0 / (zNear - zFar) ;
|
||||
mo[11] = 0.0 ;
|
||||
mo[12] = -(right + left) / (right - left) ;
|
||||
mo[13] = -(top + bottom) / (top - bottom) ;
|
||||
mo[14] = (zNear + zFar) / (zNear - zFar) ;
|
||||
mo[15] = 1.0 ;
|
||||
}
|
||||
|
Reference in New Issue
Block a user