Implemented the basic matrix system in the models.

Now we can know the position of each node/polygon/point of the animated model before it's even drawn on screen.
We can also know the position of the points on screen (and the depth of those points).
The dirty box of the models is now computed (in a debug fashion).
Somehow, models head are still bugged but it's probably due to the fact that they are not animated (and not initialised).

The debug display is left activated to let Endy see the results and implement a better zbuffer refresh system
This commit is contained in:
Vincent Hamm 2003-08-28 01:55:48 +00:00
parent 05c0f90ab2
commit f615a07c35
13 changed files with 576 additions and 9 deletions

View file

@ -210,13 +210,16 @@ void Actor::update() {
pos_ += dir * walkAmt;
}
for (std::list<Costume *>::iterator i = costumeStack_.begin();
i != costumeStack_.end(); i++)
{
(*i)->setPosRotate( pos_, pitch_, yaw_, roll_ );
(*i)->update();
}
if (lookingMode_) {
float lookAtAmt = Engine::instance()->perSecond(lookAtRate_);
}
for (std::list<Costume *>::iterator i = costumeStack_.begin();
i != costumeStack_.end(); i++)
(*i)->update();
}
void Actor::draw() {

View file

@ -108,6 +108,7 @@ public:
void update();
void reset();
void setColormap(Colormap *c);
void setMatrix(Matrix4 matrix) { matrix_ = matrix; };
~ModelComponent();
Model::HierNode *hierarchy() { return hier_; }
@ -118,6 +119,7 @@ protected:
ResPtr<Model> obj_;
ResPtr<Colormap> cmap_;
Model::HierNode *hier_;
Matrix4 matrix_;
};
class MainModelComponent : public ModelComponent {
@ -143,14 +145,18 @@ public:
const char *name);
void init();
void setKey(int val);
void update();
void reset();
~MeshComponent() { }
void setMatrix(Matrix4 matrix) { matrix_ = matrix; };
Model::HierNode *node() { return node_; }
private:
int num_;
Model::HierNode *node_;
Matrix4 matrix_;
};
BitmapComponent::BitmapComponent(Costume::Component *parent, int parentID,
@ -420,6 +426,11 @@ void MeshComponent::reset() {
node_->meshVisible_ = true;
}
void MeshComponent::update() {
node_->setMatrix( matrix_ );
node_->update();
}
class LuaVarComponent : public Costume::Component {
public:
LuaVarComponent(Costume::Component *parent, int parentID,
@ -744,8 +755,11 @@ void Costume::update() {
chores_[i].update();
for (int i = 0; i < numComponents_; i++)
if (components_[i] != NULL)
{
components_[i]->setMatrix( matrix_ );
components_[i]->update();
}
}
void Costume::setHead( int joint1, int joint2, int joint3, float maxRoll, float maxPitch, float maxYaw )
{
@ -756,3 +770,9 @@ void Costume::setHead( int joint1, int joint2, int joint3, float maxRoll, float
head_.maxPitch = maxPitch;
head_.maxYaw = maxYaw;
}
void Costume::setPosRotate( Vector3d pos_, float pitch_, float yaw_, float roll_ )
{
matrix_.pos_ = pos_;
matrix_.rot_.buildFromPitchYawRoll( pitch_, yaw_, roll_ );
}

View file

@ -19,6 +19,7 @@
#define COSTUME_H
#include <string>
#include "matrix4.h"
#define MAX_TALK_CHORES 10
class TextSplitter;
@ -49,10 +50,13 @@ public:
void update();
void draw();
void setPosRotate( Vector3d pos_, float pitch_, float yaw_, float roll_ );
class Component {
public:
Component(Component *parent, int parentID);
virtual void setMatrix( Matrix4 matrix ) { };
virtual void init() { }
virtual void setKey(int /* val */) { }
virtual void update() { }
@ -63,6 +67,7 @@ public:
protected:
int parentID_;
Component *parent_, *child_, *sibling_;
Matrix4 matrix_;
void setParent(Component *newParent);
friend class Costume;
@ -124,6 +129,7 @@ private:
int numChores_;
Chore *chores_;
int talkChores_[MAX_TALK_CHORES];
Matrix4 matrix_;
};
#endif

View file

@ -204,4 +204,6 @@ void KeyframeAnim::KeyframeNode::animate(Model::HierNode &node,
node.animYaw_ += yaw;
node.animRoll_ += roll;
}
// node
}

View file

@ -36,7 +36,7 @@ static void saveRegistry() {
int main(int /* argc */, char ** /* argv */) {
char GLDriver[1024];
if (SDL_Init(SDL_INIT_VIDEO) < 0)
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
return 1;
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);

177
matrix3.cpp Normal file
View file

@ -0,0 +1,177 @@
#include <math.h>
#include "matrix3.h"
Matrix3::setAsIdentity( void )
{
right_.set(1.f, 0.f, 0.f);
up_.set(0.f, 1.f, 0.f);
at_.set(0.f, 0.f, 0.f);
}
Matrix3::buildFromPitchYawRoll( float pitch, float yaw, float roll )
{
Matrix3 temp1, temp2;
temp1.constructAroundPitch( pitch );
constructAroundRoll( roll );
(*this) *= temp1;
temp2.constructAroundYaw( yaw );
(*this) *= temp2;
}
#define MYPI 3.141592654
#define DEGTORAD(a) (a*MYPI/180.0)
#define RADTODEG(a) (a*180.0/MYPI)
float RadianToDegree( float rad )
{
return RADTODEG(rad);
}
float DegreeToRadian( float degrees )
{
return DEGTORAD(degrees);
}
// right
Matrix3::constructAroundPitch( float pitch )
{
float cosa;
float sina;
cosa = (float)cos( DegreeToRadian(pitch) );
sina = (float)sin( DegreeToRadian(pitch) );
right_.set( 1.f, 0.f, 0.f );
up_.set( 0.f, cosa, -sina );
at_.set( 0.f, sina, cosa );
}
// up
Matrix3::constructAroundYaw( float yaw )
{
float cosa;
float sina;
cosa = (float)cos( DegreeToRadian(yaw) );
sina = (float)sin( DegreeToRadian(yaw) );
right_.set( cosa, 0.f, sina );
up_.set( 0.f, 1.f, 0.f );
at_.set( -sina, 0.f, cosa );
}
// at
Matrix3::constructAroundRoll( float roll )
{
float cosa;
float sina;
cosa = (float)cos( DegreeToRadian(roll) );
sina = (float)sin( DegreeToRadian(roll) );
right_.set( cosa, -sina, 0.f );
up_.set( sina, cosa, 0.f );
at_.set( 0.f, 0.f, 1.f );
}
/*
0 1 2 3
4 5 6 7
8 9 10 11
*/
// WARNING: Still buggy in some occasions.
void Matrix3::getPitchYawRoll( float* pPitch, float* pYaw, float* pRoll )
{
float D;
float C;
float ftrx;
float ftry;
float angle_x;
float angle_y;
float angle_z;
angle_y = D = asin( right_.z() ); /* Calculate Y-axis angle */
C = cos( angle_y );
angle_y = RadianToDegree( angle_y );
if ( fabs( C ) > 0.005 ) /* Gimball lock? */
{
ftrx = at_.z() / C; /* No, so get X-axis angle */
ftry = -up_.z() / C;
angle_x = RadianToDegree(atan2( ftry, ftrx ));
ftrx = right_.x() / C; /* Get Z-axis angle */
ftry = -right_.y() / C;
angle_z = RadianToDegree(atan2( ftry, ftrx ));
}
else /* Gimball lock has occurred */
{
angle_x = 0; /* Set X-axis angle to zqero */
ftrx = up_.y(); /* And calculate Z-axis angle */
ftry = up_.x();
angle_z = RadianToDegree(atan2( ftry, ftrx ));
}
/* return only positive angles in [0,360] */
if (angle_x < 0) angle_x += 360;
if (angle_y < 0) angle_y += 360;
if (angle_z < 0) angle_z += 360;
if( pPitch)
*pPitch = angle_x;
if( pYaw )
*pYaw = angle_y;
if( pRoll )
*pRoll = angle_z;
}
float Matrix3::getPitch()
{
float pitch;
getPitchYawRoll( &pitch, 0, 0);
return pitch;
}
float Matrix3::getYaw()
{
float yaw;
getPitchYawRoll( 0, &yaw, 0);
return yaw;
}
float Matrix3::getRoll()
{
float roll;
getPitchYawRoll( 0, 0, &roll);
return roll;
}
void Matrix3::transform( Vector3d v )
{
float x;
float y;
float z;
x = v.dotProduct( right_.x(), up_.x(), at_.x() );
y = v.dotProduct( right_.x(), up_.x(), at_.x() );
z = v.dotProduct( right_.x(), up_.x(), at_.x() );
v.set( x, y, z );
}

82
matrix3.h Normal file
View file

@ -0,0 +1,82 @@
// Residual - Virtual machine to run LucasArts' 3D adventure games
// Copyright (C) 2003 The ScummVM-Residual Team (www.scummvm.org)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef MATRIX3_HH
#define MATRIX3_HH
#include "vector3d.h"
// matrix 3 is a rotation matrix
class Matrix3{
public:
Vector3d right_;
Vector3d up_;
Vector3d at_;
buildFromPitchYawRoll( float pitch, float yaw, float roll );
setAsIdentity(void);
constructAroundPitch( float pitch );
constructAroundYaw( float pitch );
constructAroundRoll( float pitch );
void getPitchYawRoll( float* pPitch, float* pYaw, float* pRoll );
float getPitch();
float getYaw();
float getRoll();
void transform( Vector3d v );
// operators
Matrix3& operator *=(const Matrix3& s)
{
float x, y, z;
x = right_.dotProduct( s.right_.x(), s.up_.x(), s.at_.x() );
y = right_.dotProduct( s.right_.y(), s.up_.y(), s.at_.y() );
z = right_.dotProduct( s.right_.z(), s.up_.z(), s.at_.z() );
right_.set( x, y, z );
x = up_.dotProduct( s.right_.x(), s.up_.x(), s.at_.x() );
y = up_.dotProduct( s.right_.y(), s.up_.y(), s.at_.y() );
z = up_.dotProduct( s.right_.z(), s.up_.z(), s.at_.z() );
up_.set( x, y, z );
x = at_.dotProduct( s.right_.x(), s.up_.x(), s.at_.x() );
y = at_.dotProduct( s.right_.y(), s.up_.y(), s.at_.y() );
z = at_.dotProduct( s.right_.z(), s.up_.z(), s.at_.z() );
at_.set( x, y, z );
return *this;
}
Matrix3& operator =(const Matrix3& s)
{
right_ = s.right_;
up_ = s.up_;
at_ = s.at_;
return *this;
}
private:
};
#endif // MATRIX_HH

18
matrix4.cpp Normal file
View file

@ -0,0 +1,18 @@
#include "matrix4.h"
Matrix4::Matrix4( void )
{
pos_.set( 0.f, 0.f, 0.f );
rot_.setAsIdentity();
}
void Matrix4::translate( float x, float y, float z )
{
Vector3d v;
v.set( x, y, z );
rot_.transform( v );
pos_ += v;
}

59
matrix4.h Normal file
View file

@ -0,0 +1,59 @@
// Residual - Virtual machine to run LucasArts' 3D adventure games
// Copyright (C) 2003 The ScummVM-Residual Team (www.scummvm.org)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef MATRIX4_HH
#define MATRIX4_HH
#include "vector3d.h"
#include "matrix3.h"
// matrix 4 is a rotation matrix + position
class Matrix4{
public:
Matrix3 rot_;
Vector3d pos_;
Matrix4( void );
Matrix4& operator =(const Matrix4& s)
{
pos_ = s.pos_;
rot_ = s.rot_;
return *this;
}
Matrix4& operator *=(const Matrix4& s)
{
Vector3d v;
v = s.pos_;
rot_.transform( v );
pos_+=v;
rot_ *= s.rot_;
return *this;
}
void translate( float x, float y, float z );
private:
};
#endif // MATRIX_HH

173
model.cpp
View file

@ -455,9 +455,182 @@ void Model::HierNode::removeChild(HierNode *child) {
}
}
void Model::HierNode::setMatrix(Matrix4 matrix) {
matrix_ = matrix;
}
void Model::HierNode::update() {
localMatrix_.pos_.set( animPos_.x() / totalWeight_, animPos_.y() / totalWeight_, animPos_.z() / totalWeight_ );
localMatrix_.rot_.buildFromPitchYawRoll( animPitch_ / totalWeight_, animYaw_ / totalWeight_, animRoll_ / totalWeight_);
matrix_ *= localMatrix_;
pivotMatrix = matrix_;
pivotMatrix.translate( pivot_.x(), pivot_.y(), pivot_.z() );
if( mesh_ != NULL )
{
mesh_->matrix_ = pivotMatrix;
}
if( child_ != NULL )
{
child_->setMatrix( matrix_ );
child_->update();
}
}
void Model::Mesh::draw() const {
for (int i = 0; i < numFaces_; i++)
faces_[i].draw(vertices_, vertNormals_, textureVerts_);
// Yaz: debug
// this draw the model node in red
glPushMatrix();
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glPointSize( 3.f );
glColor4f( 1.f, 0.f, 0.f, 1.f );
glDisable(GL_TEXTURE_2D );
glBegin( GL_POINTS );
glVertex3f( matrix_.pos_.x(), matrix_.pos_.y(), matrix_.pos_.z() );
glEnd();
glEnable(GL_DEPTH_TEST);
glPopMatrix();
glEnable(GL_TEXTURE_2D );
// Yaz: debug
// this draw the poly points
glPushMatrix();
glLoadIdentity();
glPointSize( 3.f );
glColor4f( 0.f, 1.f, 0.f, 1.f );
glDisable(GL_TEXTURE_2D );
glBegin( GL_POINTS );
for (int i = 0; i < numFaces_; i++)
{
Vector3d v;
Matrix4 tempMatrix = matrix_;
float* pVertices;
int j;
for( j =0; j< faces_[i].numVertices_; j++ )
{
pVertices = vertices_ + 3 * faces_[i].vertices_[j];
v.set( *(pVertices), *(pVertices+1), *(pVertices+2) );
tempMatrix.rot_.transform( v );
v+= tempMatrix.pos_;
glVertex3f( v.x(), v.y(), v.z() );
}
}
glEnd();
glEnable(GL_DEPTH_TEST);
glPopMatrix();
glEnable(GL_TEXTURE_2D );
// Yaz: debug
// this compute the dirty rect for the mesh
glPushMatrix();
glLoadIdentity();
GLdouble modelView[500];
GLdouble projection[500];
GLint viewPort[500];
glGetDoublev( GL_MODELVIEW_MATRIX, modelView );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewPort);
GLdouble top = 1000;
GLdouble right = -1000;
GLdouble left = 1000;
GLdouble bottom = -1000;
for (int i = 0; i < numFaces_; i++)
{
Vector3d v;
Matrix4 tempMatrix = matrix_;
float* pVertices;
int j;
for( j =0; j< faces_[i].numVertices_; j++ )
{
pVertices = vertices_ + 3 * faces_[i].vertices_[j];
v.set( *(pVertices), *(pVertices+1), *(pVertices+2) );
tempMatrix.rot_.transform( v );
v+= tempMatrix.pos_;
GLdouble winX;
GLdouble winY;
GLdouble winZ;
gluProject( v.x(), v.y(), v.z(), modelView, projection, viewPort, &winX, &winY, &winZ);
if( winX > right )
right = winX;
if( winX < left )
left = winX;
if( winY < top )
top = winY;
if( winY > bottom )
bottom = winY;
}
}
glDisable(GL_DEPTH_TEST);
glPointSize( 3.f );
glColor4f( 1.f, 1.f, 0.f, 1.f );
glDisable(GL_TEXTURE_2D );
glBegin(GL_LINES);
GLdouble objx;
GLdouble objy;
GLdouble objz;
// top
gluUnProject( left, top, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
glVertex3f( objx, objy, objz );
gluUnProject( right, top, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
glVertex3f( objx, objy, objz );
// bottom
gluUnProject( left, bottom, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
glVertex3f( objx, objy, objz );
gluUnProject( right, bottom, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
glVertex3f( objx, objy, objz );
// left
gluUnProject( left, top, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
glVertex3f( objx, objy, objz );
gluUnProject( left, bottom, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
glVertex3f( objx, objy, objz );
// right
gluUnProject( right, top, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
glVertex3f( objx, objy, objz );
gluUnProject( right, bottom, 1.f, modelView, projection, viewPort, &objx, &objy, &objz );
glVertex3f( objx, objy, objz );
glEnd();
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D );
glPopMatrix();
}
void Model::Face::draw(float *vertices, float *vertNormals,

View file

@ -19,6 +19,7 @@
#define MODEL_H
#include "vector3d.h"
#include "matrix4.h"
#include "resource.h"
#include <cstring>
@ -44,6 +45,8 @@ public:
void draw() const;
void addChild(HierNode *child);
void removeChild(HierNode *child);
void setMatrix(Matrix4 matrix);
void update();
char name_[64];
Mesh *mesh_;
@ -56,6 +59,9 @@ public:
float animPitch_, animYaw_, animRoll_;
bool meshVisible_, hierVisible_;
int priority_, totalWeight_;
Matrix4 matrix_;
Matrix4 localMatrix_;
Matrix4 pivotMatrix;
};
HierNode *copyHierarchy();
@ -95,6 +101,7 @@ private:
int numFaces_;
Face *faces_;
Matrix4 matrix_;
};
struct Geoset {

View file

@ -236,15 +236,31 @@
<File
RelativePath="textsplit.h">
</File>
<File
RelativePath="vector3d.h">
</File>
<File
RelativePath="walkplane.cpp">
</File>
<File
RelativePath="walkplane.h">
</File>
<Filter
Name="3DEngine"
Filter="">
<File
RelativePath="matrix3.cpp">
</File>
<File
RelativePath="matrix3.h">
</File>
<File
RelativePath="matrix4.cpp">
</File>
<File
RelativePath="matrix4.h">
</File>
<File
RelativePath="vector3d.h">
</File>
</Filter>
</Filter>
<Filter
Name="Resource Files"

View file

@ -81,6 +81,10 @@ public:
return std::sqrt(x() * x() + y() * y() + z() * z());
}
float dotProduct( float sx, float sy, float sz ) {
return x()*sx + y()*sy + z()*sz;
}
bool isZero() {
if(x() == 0.f && y() == 0.f && z() == 0.f)
return true;