Lephisto/src/static_rigid_body.cpp

179 lines
5.4 KiB
C++

#include "libs.h"
#include "static_rigid_body.h"
#include "space.h"
#include "matrix4x4.h"
#include "frame.h"
#include "l3d.h"
#include "world_view.h"
StaticRigidBody::StaticRigidBody(void): Body() {
m_geom = 0;
sbreCollMesh = 0;
triMeshLastMatrixIndex = 0;
}
StaticRigidBody::~StaticRigidBody(void) {
if(sbreCollMesh) {
free(sbreCollMesh->pVertex);
free(sbreCollMesh->pIndex);
free(sbreCollMesh->pFlag);
free(sbreCollMesh);
}
dGeomDestroy(m_geom);
}
void StaticRigidBody::SetGeomSphere(double radius) {
assert(!m_geom);
m_geom = dCreateSphere(0, radius);
}
void StaticRigidBody::SetGeomFromSBREModel(int sbreModel, ObjParams* params) {
assert(!m_geom);
assert(sbreCollMesh == 0);
sbreCollMesh = (CollMesh*)calloc(1, sizeof(CollMesh));
sbreGenCollMesh(sbreCollMesh, sbreModel, params);
/* TODO: Flip Z & X because SBRE is in magicspace. */
for(int i = 0; i < 3*sbreCollMesh->nv; i += 3) {
sbreCollMesh->pVertex[i] = -sbreCollMesh->pVertex[i];
sbreCollMesh->pVertex[i+2] = -sbreCollMesh->pVertex[i+2];
}
/* Make normals. */
meshNormals = new float[sbreCollMesh->ni];
for(int i = 0; i < sbreCollMesh->ni; i += 3) {
float* vtx1 = sbreCollMesh->pVertex + 3*sbreCollMesh->pIndex[i];
float* vtx2 = sbreCollMesh->pVertex + 3*sbreCollMesh->pIndex[i+1];
float* vtx3 = sbreCollMesh->pVertex + 3*sbreCollMesh->pIndex[i+2];
vector3f v1(vtx1[0], vtx1[1], vtx1[2]);
vector3f v2(vtx2[0], vtx2[1], vtx2[2]);
vector3f v3(vtx3[0], vtx3[1], vtx3[2]);
vector3f n = vector3f::Cross(v1-v2, v1-v3);
n.Normalize();
meshNormals[i] = n.x;
meshNormals[i+1] = n.y;
meshNormals[i+2] = n.z;
}
dTriMeshDataID triMeshDataID = dGeomTriMeshDataCreate();
dGeomTriMeshDataBuildSingle1(triMeshDataID, (void*)sbreCollMesh->pVertex,
3*sizeof(float), sbreCollMesh->nv, (void*)sbreCollMesh->pIndex,
sbreCollMesh->ni, 3*sizeof(int), NULL/*meshNormals*/);
/* TODO: Leaking StaticRigidBody m_geom. */
m_geom = dCreateTriMesh(0, triMeshDataID, NULL, NULL, NULL);
dGeomSetData(m_geom, static_cast<Body*>(this));
}
void StaticRigidBody::SetPosition(vector3d p) {
dGeomSetPosition(m_geom, p.x, p.y, p.z);
}
void StaticRigidBody::SetVelocity(vector3d v) {
assert(0);
}
vector3d StaticRigidBody::GetPosition(void) {
const dReal* pos = dGeomGetPosition(m_geom);
return vector3d(pos[0], pos[1], pos[2]);
}
void StaticRigidBody::GetRotMatrix(matrix4x4d& m) {
m.LoadFromOdeMatrix(dGeomGetRotation(m_geom));
}
void StaticRigidBody::ViewingRotation(void) {
matrix4x4d m;
GetRotMatrix(m);
m = m.InverseOf();
glMultMatrixd(&m[0]);
}
void StaticRigidBody::TransformCameraTo(void) {
const dReal* p = dGeomGetPosition(m_geom);
matrix4x4d m;
GetRotMatrix(m);
m = m.InverseOf();
glMultMatrixd(&m[0]);
glTranslated(-p[0], -p[1], -p[2]);
}
void StaticRigidBody::TransformToModelCoords(const Frame* camFrame) {
vector3d fpos = GetPositionRelTo(camFrame);
const dReal* r = dGeomGetRotation(m_geom);
matrix4x4d m;
m[ 0] = r[ 0]; m[ 1] = r[ 4]; m[ 2] = r[ 8]; m[ 3] = 0;
m[ 4] = r[ 1]; m[ 5] = r[ 5]; m[ 6] = r[ 9]; m[ 7] = 0;
m[ 8] = r[ 2]; m[ 9] = r[ 6]; m[10] = r[10]; m[11] = 0;
m[12] = fpos.x; m[13] = fpos.y; m[14] = fpos.z; m[15] = 1;
glMultMatrixd(&m[0]);
}
void StaticRigidBody::SetFrame(Frame* f) {
if(GetFrame()) GetFrame()->RemoveGeom(m_geom);
Body::SetFrame(f);
if(f) f->AddGeom(m_geom);
}
void StaticRigidBody::TriMeshUpdateLastPos(void) {
/* ODE tri mesh likes to know our old position. */
const dReal* r = dGeomGetRotation(m_geom);
vector3d pos = GetPosition();
dReal* t = triMeshTrans + 16*triMeshLastMatrixIndex;
t[ 0] = r[0]; t[1] = r[1]; t[ 2] = r[ 2]; t[ 3] = 0;
t[ 4] = r[4]; t[5] = r[5]; t[ 6] = r[ 6]; t[ 7] = 0;
t[ 8] = r[8]; t[9] = r[9]; t[10] = r[10]; t[11] = 0;
t[12] = pos.x; t[13] = pos.y; t[14] = pos.z; t[15] = 1;
triMeshLastMatrixIndex = !triMeshLastMatrixIndex;
dGeomTriMeshSetLastTransform(m_geom, *(dMatrix4*)(triMeshTrans + 16*triMeshLastMatrixIndex));
}
void StaticRigidBody::RenderSbreModel(const Frame* camFrame, int model, ObjParams* params) {
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
/* TODO Reduce. */
glPushAttrib(GL_ALL_ATTRIB_BITS);
{
/* TODO Need to use correct starlight colour. */
float lightCol[3] = { 1,1,1 };
float lightDir[3];
vector3d _lightDir = Frame::GetFramePosRelativeToOther(Space::GetRootFrame(), camFrame);
matrix4x4d poo = L3D::world_view->viewingRotation;
poo[2] = -poo[2];
poo[6] = -poo[6];
poo[8] = -poo[8];
poo[9] = -poo[9];
_lightDir = poo*_lightDir;
lightDir[0] = _lightDir.x;
lightDir[1] = _lightDir.y;
lightDir[2] = _lightDir.z;
sbreSetDirLight(lightCol, lightDir);
}
sbreSetViewport(L3D::GetScrWidth(), L3D::GetScrHeight(), L3D::GetScrWidth()
*0.5, 5.0f, 100000.0f, 0.0f, 1.0f);
vector3d pos = GetPositionRelTo(camFrame);
pos = L3D::world_view->viewingRotation*pos;
Vector p; p.x = pos.x; p.y = pos.y; p.z = -pos.z;
matrix4x4d rot;
rot.LoadFromOdeMatrix(dGeomGetRotation(m_geom));
rot = L3D::world_view->viewingRotation * rot;
Matrix m;
m.x1 = rot[0]; m.x2 = rot[4]; m.x3 = -rot[8];
m.y1 = rot[1]; m.y2 = rot[5]; m.y3 = -rot[9];
m.z1 = -rot[2]; m.z2 = -rot[6]; m.z3 = rot[10];
sbreRenderModel(&p, &m, model, params);
glPopAttrib();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}