2003-01-22 00:45:36 +08:00
|
|
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
|
|
|
|
*
|
|
|
|
* This library is open source and may be redistributed and/or modified under
|
|
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* OpenSceneGraph Public License for more details.
|
|
|
|
*/
|
2001-09-20 05:08:56 +08:00
|
|
|
#include <osg/Matrix>
|
2001-09-22 10:42:08 +08:00
|
|
|
#include <osg/Quat>
|
2001-09-20 05:08:56 +08:00
|
|
|
#include <osg/Notify>
|
2001-10-15 23:50:55 +08:00
|
|
|
#include <osg/Math>
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2001-09-27 17:44:55 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
using namespace osg;
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
#define SET_ROW(row, v1, v2, v3, v4 ) \
|
|
|
|
_mat[(row)][0] = (v1); \
|
|
|
|
_mat[(row)][1] = (v2); \
|
|
|
|
_mat[(row)][2] = (v3); \
|
|
|
|
_mat[(row)][3] = (v4);
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
#define INNER_PRODUCT(a,b,r,c) \
|
|
|
|
((a)._mat[r][0] * (b)._mat[0][c]) \
|
|
|
|
+((a)._mat[r][1] * (b)._mat[1][c]) \
|
|
|
|
+((a)._mat[r][2] * (b)._mat[2][c]) \
|
|
|
|
+((a)._mat[r][3] * (b)._mat[3][c])
|
2001-01-11 00:32:10 +08:00
|
|
|
|
|
|
|
|
2002-02-07 09:15:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2003-01-10 17:25:42 +08:00
|
|
|
Matrix::Matrix()
|
2002-02-06 05:51:06 +08:00
|
|
|
{
|
|
|
|
makeIdentity();
|
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2003-01-10 17:25:42 +08:00
|
|
|
Matrix::Matrix( const Matrix& other)
|
2001-09-20 05:08:56 +08:00
|
|
|
{
|
2001-10-15 23:50:55 +08:00
|
|
|
set( (const float *) other._mat );
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
|
|
|
|
2002-03-19 05:56:00 +08:00
|
|
|
Matrix::Matrix( const float * const def )
|
2001-09-22 10:42:08 +08:00
|
|
|
{
|
|
|
|
set( def );
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
Matrix::Matrix( float a00, float a01, float a02, float a03,
|
|
|
|
float a10, float a11, float a12, float a13,
|
|
|
|
float a20, float a21, float a22, float a23,
|
|
|
|
float a30, float a31, float a32, float a33)
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
SET_ROW(0, a00, a01, a02, a03 )
|
|
|
|
SET_ROW(1, a10, a11, a12, a13 )
|
|
|
|
SET_ROW(2, a20, a21, a22, a23 )
|
|
|
|
SET_ROW(3, a30, a31, a32, a33 )
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
void Matrix::set( float a00, float a01, float a02, float a03,
|
|
|
|
float a10, float a11, float a12, float a13,
|
|
|
|
float a20, float a21, float a22, float a23,
|
|
|
|
float a30, float a31, float a32, float a33)
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
SET_ROW(0, a00, a01, a02, a03 )
|
|
|
|
SET_ROW(1, a10, a11, a12, a13 )
|
|
|
|
SET_ROW(2, a20, a21, a22, a23 )
|
|
|
|
SET_ROW(3, a30, a31, a32, a33 )
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
void Matrix::setTrans( float tx, float ty, float tz )
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
|
|
|
_mat[3][0] = tx;
|
|
|
|
_mat[3][1] = ty;
|
|
|
|
_mat[3][2] = tz;
|
|
|
|
}
|
|
|
|
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
void Matrix::setTrans( const Vec3& v )
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
_mat[3][0] = v[0];
|
|
|
|
_mat[3][1] = v[1];
|
|
|
|
_mat[3][2] = v[2];
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-12-16 00:56:39 +08:00
|
|
|
void Matrix::makeIdentity()
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
SET_ROW(0, 1, 0, 0, 0 )
|
|
|
|
SET_ROW(1, 0, 1, 0, 0 )
|
|
|
|
SET_ROW(2, 0, 0, 1, 0 )
|
|
|
|
SET_ROW(3, 0, 0, 0, 1 )
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
void Matrix::makeScale( const Vec3& v )
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
makeScale(v[0], v[1], v[2] );
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
void Matrix::makeScale( float x, float y, float z )
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
SET_ROW(0, x, 0, 0, 0 )
|
|
|
|
SET_ROW(1, 0, y, 0, 0 )
|
|
|
|
SET_ROW(2, 0, 0, z, 0 )
|
|
|
|
SET_ROW(3, 0, 0, 0, 1 )
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-12-13 04:29:10 +08:00
|
|
|
void Matrix::makeTranslate( const Vec3& v )
|
2001-09-20 05:08:56 +08:00
|
|
|
{
|
2001-12-13 04:29:10 +08:00
|
|
|
makeTranslate( v[0], v[1], v[2] );
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
|
|
|
|
2001-12-13 04:29:10 +08:00
|
|
|
void Matrix::makeTranslate( float x, float y, float z )
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
SET_ROW(0, 1, 0, 0, 0 )
|
|
|
|
SET_ROW(1, 0, 1, 0, 0 )
|
|
|
|
SET_ROW(2, 0, 0, 1, 0 )
|
|
|
|
SET_ROW(3, x, y, z, 1 )
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-12-13 04:29:10 +08:00
|
|
|
void Matrix::makeRotate( const Vec3& from, const Vec3& to )
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-12-12 23:09:11 +08:00
|
|
|
Quat quat;
|
2001-12-13 04:29:10 +08:00
|
|
|
quat.makeRotate(from,to);
|
2001-12-12 23:09:11 +08:00
|
|
|
quat.get(*this);
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-12-13 04:29:10 +08:00
|
|
|
void Matrix::makeRotate( float angle, const Vec3& axis )
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-12-12 23:09:11 +08:00
|
|
|
Quat quat;
|
2001-12-13 04:29:10 +08:00
|
|
|
quat.makeRotate( angle, axis);
|
2001-12-12 23:09:11 +08:00
|
|
|
quat.get(*this);
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-12-13 04:29:10 +08:00
|
|
|
void Matrix::makeRotate( float angle, float x, float y, float z )
|
2001-12-12 01:00:29 +08:00
|
|
|
{
|
2001-12-12 23:09:11 +08:00
|
|
|
Quat quat;
|
2001-12-13 04:29:10 +08:00
|
|
|
quat.makeRotate( angle, x, y, z);
|
2001-12-12 23:09:11 +08:00
|
|
|
quat.get(*this);
|
2001-09-22 10:42:08 +08:00
|
|
|
}
|
|
|
|
|
2001-12-13 04:29:10 +08:00
|
|
|
void Matrix::makeRotate( const Quat& q )
|
2001-12-12 23:09:11 +08:00
|
|
|
{
|
|
|
|
q.get(*this);
|
2001-09-22 10:42:08 +08:00
|
|
|
}
|
|
|
|
|
Added DOFTransform, MatrixTransform and PositionAttitudeTransform to NodeVisitor.
Added osg::Matrix/Quat::makeRotate(angle1,axis1,angle2,axis2,angle3,axis3) and
osg::Matrix::rotate(angle1,axis1,angle2,axis2,angle3,axis3) method.
Made osg::Matrix/Quat::makeRotate(heading,pitch,roll) and
osg::Matrix::rotate(heading,pitch,roll) all deprecated API.
Fixed the Quat*Quat & Quat*=Quat multiplication methods so that they multiplied
in the correct order - they were reversed originally due to the Quat code being
based on code example which used the v' = M v ordering, rather than the OSG's
v' = v M ordering.
2002-08-18 22:42:43 +08:00
|
|
|
void Matrix::makeRotate( float angle1, const Vec3& axis1,
|
|
|
|
float angle2, const Vec3& axis2,
|
|
|
|
float angle3, const Vec3& axis3)
|
|
|
|
{
|
|
|
|
Quat quat;
|
|
|
|
quat.makeRotate(angle1, axis1,
|
|
|
|
angle2, axis2,
|
|
|
|
angle3, axis3);
|
|
|
|
quat.get(*this);
|
|
|
|
}
|
2001-09-22 10:42:08 +08:00
|
|
|
|
|
|
|
void Matrix::mult( const Matrix& lhs, const Matrix& rhs )
|
2002-02-06 05:51:06 +08:00
|
|
|
{
|
2002-02-07 09:15:15 +08:00
|
|
|
if (&lhs==this)
|
|
|
|
{
|
|
|
|
postMult(rhs);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (&rhs==this)
|
|
|
|
{
|
|
|
|
preMult(lhs);
|
2002-07-26 05:58:53 +08:00
|
|
|
return;
|
2002-02-07 09:15:15 +08:00
|
|
|
}
|
2002-02-06 05:51:06 +08:00
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
// PRECONDITION: We assume neither &lhs nor &rhs == this
|
|
|
|
// if it did, use preMult or postMult instead
|
|
|
|
_mat[0][0] = INNER_PRODUCT(lhs, rhs, 0, 0);
|
|
|
|
_mat[0][1] = INNER_PRODUCT(lhs, rhs, 0, 1);
|
|
|
|
_mat[0][2] = INNER_PRODUCT(lhs, rhs, 0, 2);
|
|
|
|
_mat[0][3] = INNER_PRODUCT(lhs, rhs, 0, 3);
|
|
|
|
_mat[1][0] = INNER_PRODUCT(lhs, rhs, 1, 0);
|
|
|
|
_mat[1][1] = INNER_PRODUCT(lhs, rhs, 1, 1);
|
|
|
|
_mat[1][2] = INNER_PRODUCT(lhs, rhs, 1, 2);
|
|
|
|
_mat[1][3] = INNER_PRODUCT(lhs, rhs, 1, 3);
|
|
|
|
_mat[2][0] = INNER_PRODUCT(lhs, rhs, 2, 0);
|
|
|
|
_mat[2][1] = INNER_PRODUCT(lhs, rhs, 2, 1);
|
|
|
|
_mat[2][2] = INNER_PRODUCT(lhs, rhs, 2, 2);
|
|
|
|
_mat[2][3] = INNER_PRODUCT(lhs, rhs, 2, 3);
|
|
|
|
_mat[3][0] = INNER_PRODUCT(lhs, rhs, 3, 0);
|
|
|
|
_mat[3][1] = INNER_PRODUCT(lhs, rhs, 3, 1);
|
|
|
|
_mat[3][2] = INNER_PRODUCT(lhs, rhs, 3, 2);
|
|
|
|
_mat[3][3] = INNER_PRODUCT(lhs, rhs, 3, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Matrix::preMult( const Matrix& other )
|
|
|
|
{
|
|
|
|
// brute force method requiring a copy
|
|
|
|
//Matrix tmp(other* *this);
|
|
|
|
// *this = tmp;
|
|
|
|
|
|
|
|
// more efficient method just use a float[4] for temporary storage.
|
|
|
|
float t[4];
|
|
|
|
for(int col=0; col<4; ++col) {
|
|
|
|
t[0] = INNER_PRODUCT( other, *this, 0, col );
|
|
|
|
t[1] = INNER_PRODUCT( other, *this, 1, col );
|
|
|
|
t[2] = INNER_PRODUCT( other, *this, 2, col );
|
|
|
|
t[3] = INNER_PRODUCT( other, *this, 3, col );
|
|
|
|
_mat[0][col] = t[0];
|
|
|
|
_mat[1][col] = t[1];
|
|
|
|
_mat[2][col] = t[2];
|
|
|
|
_mat[3][col] = t[3];
|
|
|
|
}
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
void Matrix::postMult( const Matrix& other )
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
// brute force method requiring a copy
|
|
|
|
//Matrix tmp(*this * other);
|
|
|
|
// *this = tmp;
|
|
|
|
|
|
|
|
// more efficient method just use a float[4] for temporary storage.
|
|
|
|
float t[4];
|
|
|
|
for(int row=0; row<4; ++row)
|
2001-09-20 05:08:56 +08:00
|
|
|
{
|
2001-09-22 10:42:08 +08:00
|
|
|
t[0] = INNER_PRODUCT( *this, other, row, 0 );
|
|
|
|
t[1] = INNER_PRODUCT( *this, other, row, 1 );
|
|
|
|
t[2] = INNER_PRODUCT( *this, other, row, 2 );
|
|
|
|
t[3] = INNER_PRODUCT( *this, other, row, 3 );
|
|
|
|
SET_ROW(row, t[0], t[1], t[2], t[3] )
|
2001-09-20 05:08:56 +08:00
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2001-09-22 10:42:08 +08:00
|
|
|
#undef INNER_PRODUCT
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-02-12 07:24:23 +08:00
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline T SGL_ABS(T a)
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2002-02-12 07:24:23 +08:00
|
|
|
return (a >= 0 ? a : -a);
|
|
|
|
}
|
2001-09-20 05:08:56 +08:00
|
|
|
|
2002-02-12 07:24:23 +08:00
|
|
|
#ifndef SGL_SWAP
|
|
|
|
#define SGL_SWAP(a,b,temp) ((temp)=(a),(a)=(b),(b)=(temp))
|
|
|
|
#endif
|
2002-02-07 09:15:15 +08:00
|
|
|
|
2002-02-12 07:24:23 +08:00
|
|
|
bool Matrix::invert( const Matrix& mat )
|
|
|
|
{
|
|
|
|
if (&mat==this) {
|
|
|
|
Matrix tm(mat);
|
|
|
|
return invert(tm);
|
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-02-12 07:24:23 +08:00
|
|
|
unsigned int indxc[4], indxr[4], ipiv[4];
|
|
|
|
unsigned int i,j,k,l,ll;
|
|
|
|
unsigned int icol = 0;
|
|
|
|
unsigned int irow = 0;
|
2003-04-29 22:24:11 +08:00
|
|
|
double temp, pivinv, dum, big;
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-02-12 07:24:23 +08:00
|
|
|
// copy in place this may be unnecessary
|
|
|
|
*this = mat;
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-02-12 07:24:23 +08:00
|
|
|
for (j=0; j<4; j++) ipiv[j]=0;
|
2001-01-11 00:32:10 +08:00
|
|
|
|
2002-02-12 07:24:23 +08:00
|
|
|
for(i=0;i<4;i++)
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2002-02-12 07:24:23 +08:00
|
|
|
big=(float)0.0;
|
|
|
|
for (j=0; j<4; j++)
|
|
|
|
if (ipiv[j] != 1)
|
|
|
|
for (k=0; k<4; k++)
|
|
|
|
{
|
|
|
|
if (ipiv[k] == 0)
|
2001-01-11 00:32:10 +08:00
|
|
|
{
|
2002-02-12 07:24:23 +08:00
|
|
|
if (SGL_ABS(operator()(j,k)) >= big)
|
|
|
|
{
|
|
|
|
big = SGL_ABS(operator()(j,k));
|
|
|
|
irow=j;
|
|
|
|
icol=k;
|
|
|
|
}
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
2002-02-12 07:24:23 +08:00
|
|
|
else if (ipiv[k] > 1)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
++(ipiv[icol]);
|
|
|
|
if (irow != icol)
|
|
|
|
for (l=0; l<4; l++) SGL_SWAP(operator()(irow,l),
|
|
|
|
operator()(icol,l),
|
|
|
|
temp);
|
|
|
|
|
|
|
|
indxr[i]=irow;
|
|
|
|
indxc[i]=icol;
|
|
|
|
if (operator()(icol,icol) == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
pivinv = 1.0/operator()(icol,icol);
|
|
|
|
operator()(icol,icol) = 1;
|
|
|
|
for (l=0; l<4; l++) operator()(icol,l) *= pivinv;
|
|
|
|
for (ll=0; ll<4; ll++)
|
|
|
|
if (ll != icol)
|
|
|
|
{
|
|
|
|
dum=operator()(ll,icol);
|
|
|
|
operator()(ll,icol) = 0;
|
|
|
|
for (l=0; l<4; l++) operator()(ll,l) -= operator()(icol,l)*dum;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int lx=4; lx>0; --lx)
|
|
|
|
{
|
|
|
|
if (indxr[lx-1] != indxc[lx-1])
|
|
|
|
for (k=0; k<4; k++) SGL_SWAP(operator()(k,indxr[lx-1]),
|
|
|
|
operator()(k,indxc[lx-1]),temp);
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
|
|
|
|
2002-02-12 07:24:23 +08:00
|
|
|
return true;
|
2001-01-11 00:32:10 +08:00
|
|
|
}
|
2001-09-22 10:42:08 +08:00
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
void Matrix::makeOrtho(double left, double right,
|
|
|
|
double bottom, double top,
|
|
|
|
double zNear, double zFar)
|
2001-09-22 10:42:08 +08:00
|
|
|
{
|
2002-04-10 00:09:19 +08:00
|
|
|
// note transpose of Matrix wr.t OpenGL documentation, since the OSG use post multiplication rather than pre.
|
|
|
|
double tx = -(right+left)/(right-left);
|
|
|
|
double ty = -(top+bottom)/(top-bottom);
|
|
|
|
double tz = -(zFar+zNear)/(zFar-zNear);
|
|
|
|
SET_ROW(0, 2.0f/(right-left), 0.0f, 0.0f, 0.0f )
|
|
|
|
SET_ROW(1, 0.0f, 2.0f/(top-bottom), 0.0f, 0.0f )
|
|
|
|
SET_ROW(2, 0.0f, 0.0f, -2.0f/(zFar-zNear), 0.0f )
|
|
|
|
SET_ROW(3, tx, ty, tz, 1.0f )
|
|
|
|
}
|
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
void Matrix::makeFrustum(double left, double right,
|
|
|
|
double bottom, double top,
|
|
|
|
double zNear, double zFar)
|
2002-04-10 00:09:19 +08:00
|
|
|
{
|
|
|
|
// note transpose of Matrix wr.t OpenGL documentation, since the OSG use post multiplication rather than pre.
|
|
|
|
double A = (right+left)/(right-left);
|
|
|
|
double B = (top+bottom)/(top-bottom);
|
|
|
|
double C = -(zFar+zNear)/(zFar-zNear);
|
|
|
|
double D = -2.0*zFar*zNear/(zFar-zNear);
|
|
|
|
SET_ROW(0, 2.0f*zNear/(right-left), 0.0f, 0.0f, 0.0f )
|
|
|
|
SET_ROW(1, 0.0f, 2.0f*zNear/(top-bottom), 0.0f, 0.0f )
|
|
|
|
SET_ROW(2, A, B, C, -1.0f )
|
|
|
|
SET_ROW(3, 0.0f, 0.0f, D, 0.0f )
|
|
|
|
}
|
2001-09-22 10:42:08 +08:00
|
|
|
|
2002-04-10 00:09:19 +08:00
|
|
|
|
2002-09-02 20:31:35 +08:00
|
|
|
void Matrix::makePerspective(double fovy,double aspectRatio,
|
|
|
|
double zNear, double zFar)
|
2002-04-10 00:09:19 +08:00
|
|
|
{
|
|
|
|
// calculate the appropriate left, right etc.
|
|
|
|
double tan_fovy = tan(DegreesToRadians(fovy*0.5));
|
|
|
|
double right = tan_fovy * aspectRatio * zNear;
|
|
|
|
double left = -right;
|
|
|
|
double top = tan_fovy * zNear;
|
|
|
|
double bottom = -top;
|
|
|
|
makeFrustum(left,right,bottom,top,zNear,zFar);
|
2001-09-22 10:42:08 +08:00
|
|
|
}
|
|
|
|
|
2002-04-10 00:09:19 +08:00
|
|
|
|
|
|
|
void Matrix::makeLookAt(const Vec3& eye,const Vec3& center,const Vec3& up)
|
|
|
|
{
|
2002-04-16 19:41:32 +08:00
|
|
|
Vec3 f(center-eye);
|
|
|
|
f.normalize();
|
|
|
|
Vec3 s(f^up);
|
|
|
|
s.normalize();
|
|
|
|
Vec3 u(s^f);
|
|
|
|
u.normalize();
|
|
|
|
|
|
|
|
set(
|
|
|
|
s[0], u[0], -f[0], 0.0f,
|
|
|
|
s[1], u[1], -f[1], 0.0f,
|
|
|
|
s[2], u[2], -f[2], 0.0f,
|
|
|
|
0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
preMult(Matrix::translate(-eye));
|
2002-04-10 00:09:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef SET_ROW
|