scummvm/engines/grim/model.cpp

642 lines
18 KiB
C++
Raw Normal View History

2009-05-26 14:13:08 +00:00
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
2011-04-16 12:12:44 +00:00
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
2006-04-02 14:20:45 +00:00
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
2003-08-15 18:00:22 +00:00
#include "common/endian.h"
2009-06-18 11:52:26 +00:00
#include "engines/grim/grim.h"
#include "engines/grim/model.h"
#include "engines/grim/actor.h"
#include "engines/grim/material.h"
#include "engines/grim/textsplit.h"
#include "engines/grim/gfx_base.h"
2011-04-10 09:24:03 +00:00
#include "engines/grim/lipsync.h"
2011-05-14 00:55:14 +00:00
#include "engines/grim/resource.h"
2005-01-01 12:27:57 +00:00
2009-05-25 06:49:57 +00:00
namespace Grim {
2011-05-15 13:47:09 +00:00
void Sprite::draw() const {
if (!_visible)
return;
_material->select();
g_driver->drawSprite(this);
}
Model::Model(const Common::String &filename, const char *data, int len, CMap *cmap, Model *parent) :
Object(), _parent(parent), _numMaterials(0), _numGeosets(0), _cmap(cmap) {
2009-06-26 16:13:11 +00:00
_fname = filename;
if (g_grim->getGameType() == GType_MONKEY4) {
Common::MemoryReadStream ms((const byte *)data, len);
loadEMI(ms);
} else if (len >= 4 && READ_BE_UINT32(data) == MKTAG('L','D','O','M'))
loadBinary(data, cmap);
else {
TextSplitter ts(data, len);
2009-06-26 16:13:11 +00:00
loadText(&ts, cmap);
}
2003-08-15 18:00:22 +00:00
}
void Model::reload(CMap *cmap) {
// Load the new colormap
for (int i = 0; i < _numMaterials; i++) {
loadMaterial(i, cmap);
}
for (int i = 0; i < _numGeosets; i++)
_geosets[i].changeMaterials(_materials);
}
void Model::loadEMI(Common::MemoryReadStream &ms) {
char name[64];
int nameLength = ms.readUint32LE();
assert(nameLength < 64);
ms.read(name, nameLength);
// skip over some unkown floats
ms.seek(48, SEEK_CUR);
_numMaterials = ms.readUint32LE();
_materials = new Material*[_numMaterials];
_materialNames = new char[_numMaterials][32];
for (int i = 0; i < _numMaterials; i++) {
nameLength = ms.readUint32LE();
assert(nameLength < 32);
ms.read(_materialNames[i], nameLength);
// I'm not sure what specialty mateials are, but they are handled differently.
if (memcmp(_materialNames[i], "specialty", 9) == 0) {
_materials[i] = 0;
} else {
loadMaterial(i, 0);
}
ms.seek(4, SEEK_CUR);
}
ms.seek(4, SEEK_CUR);
}
void Model::loadBinary(const char *&data, CMap *cmap) {
2004-12-09 23:55:43 +00:00
_numMaterials = READ_LE_UINT32(data + 4);
data += 8;
_materials = new Material*[_numMaterials];
_materialNames = new char[_numMaterials][32];
_materialsShared = new bool[_numMaterials];
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numMaterials; i++) {
strcpy(_materialNames[i], data);
_materialsShared[i] = false;
_materials[i] = NULL;
loadMaterial(i, cmap);
data += 32;
}
data += 32; // skip name
2004-12-09 23:55:43 +00:00
_numGeosets = READ_LE_UINT32(data + 4);
data += 8;
2004-12-09 23:55:43 +00:00
_geosets = new Geoset[_numGeosets];
for (int i = 0; i < _numGeosets; i++)
_geosets[i].loadBinary(data, _materials);
2004-12-09 23:55:43 +00:00
_numHierNodes = READ_LE_UINT32(data + 4);
data += 8;
2004-12-09 23:55:43 +00:00
_rootHierNode = new HierNode[_numHierNodes];
2011-07-18 20:23:18 +00:00
for (int i = 0; i < _numHierNodes; i++) {
_rootHierNode[i].loadBinary(data, _rootHierNode, &_geosets[0]);
}
2004-12-09 23:55:43 +00:00
_radius = get_float(data);
_insertOffset = Graphics::get_vector3d(data + 40);
2003-08-15 18:00:22 +00:00
}
Model::~Model() {
2004-12-09 23:55:43 +00:00
delete[] _materials;
delete[] _materialNames;
2004-12-09 23:55:43 +00:00
delete[] _geosets;
delete[] _rootHierNode;
g_resourceloader->uncacheModel(this);
2003-08-15 18:00:22 +00:00
}
void Model::Geoset::loadBinary(const char *&data, Material *materials[]) {
2004-12-09 23:55:43 +00:00
_numMeshes = READ_LE_UINT32(data);
data += 4;
2004-12-09 23:55:43 +00:00
_meshes = new Mesh[_numMeshes];
for (int i = 0; i < _numMeshes; i++)
_meshes[i].loadBinary(data, materials);
2003-08-15 18:00:22 +00:00
}
Model::Geoset::~Geoset() {
2004-12-09 23:55:43 +00:00
delete[] _meshes;
2003-08-15 18:00:22 +00:00
}
void Model::Mesh::loadBinary(const char *&data, Material *materials[]) {
2004-12-09 23:55:43 +00:00
memcpy(_name, data, 32);
_geometryMode = READ_LE_UINT32(data + 36);
_lightingMode = READ_LE_UINT32(data + 40);
_textureMode = READ_LE_UINT32(data + 44);
_numVertices = READ_LE_UINT32(data + 48);
_numTextureVerts = READ_LE_UINT32(data + 52);
_numFaces = READ_LE_UINT32(data + 56);
_vertices = new float[3 * _numVertices];
_verticesI = new float[_numVertices];
_vertNormals = new float[3 * _numVertices];
_textureVerts = new float[2 * _numTextureVerts];
2011-05-09 19:53:41 +00:00
_faces = new Face[_numFaces];
_materialid = new int[_numFaces];
data += 60;
2004-12-09 23:55:43 +00:00
for (int i = 0; i < 3 * _numVertices; i++) {
_vertices[i] = get_float(data);
data += 4;
}
2004-12-09 23:55:43 +00:00
for (int i = 0; i < 2 * _numTextureVerts; i++) {
_textureVerts[i] = get_float(data);
data += 4;
}
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numVertices; i++) {
_verticesI[i] = get_float(data);
data += 4;
}
2004-12-09 23:55:43 +00:00
data += _numVertices * 4;
for (int i = 0; i < _numFaces; i++)
_materialid[i] = _faces[i].loadBinary(data, materials);
2004-12-09 23:55:43 +00:00
for (int i = 0; i < 3 * _numVertices; i++) {
_vertNormals[i] = get_float(data);
data += 4;
}
2004-12-09 23:55:43 +00:00
_shadow = READ_LE_UINT32(data);
_radius = get_float(data + 8);
data += 36;
2003-08-15 18:00:22 +00:00
}
Model::Mesh::~Mesh() {
2004-12-09 23:55:43 +00:00
delete[] _vertices;
delete[] _verticesI;
delete[] _vertNormals;
delete[] _textureVerts;
delete[] _faces;
delete[] _materialid;
2003-08-15 18:00:22 +00:00
}
2003-08-31 13:20:28 +00:00
void Model::Mesh::update() {
}
2009-06-26 16:13:11 +00:00
void Model::Face::changeMaterial(Material *material) {
_material = material;
}
int Model::Face::loadBinary(const char *&data, Material *materials[]) {
2004-12-09 23:55:43 +00:00
_type = READ_LE_UINT32(data + 4);
_geo = READ_LE_UINT32(data + 8);
_light = READ_LE_UINT32(data + 12);
_tex = READ_LE_UINT32(data + 16);
_numVertices = READ_LE_UINT32(data + 20);
int texPtr = READ_LE_UINT32(data + 28);
int materialPtr = READ_LE_UINT32(data + 32);
2004-12-09 23:55:43 +00:00
_extraLight = get_float(data + 48);
_normal = Graphics::get_vector3d(data + 64);
data += 76;
2004-12-09 23:55:43 +00:00
_vertices = new int[_numVertices];
for (int i = 0; i < _numVertices; i++) {
_vertices[i] = READ_LE_UINT32(data);
data += 4;
}
2005-01-12 23:28:47 +00:00
if (texPtr == 0)
2004-12-09 23:55:43 +00:00
_texVertices = NULL;
else {
2004-12-09 23:55:43 +00:00
_texVertices = new int[_numVertices];
for (int i = 0; i < _numVertices; i++) {
_texVertices[i] = READ_LE_UINT32(data);
data += 4;
}
}
if (materialPtr == 0)
2004-12-09 23:55:43 +00:00
_material = 0;
else {
_material = materials[READ_LE_UINT32(data)];
materialPtr = READ_LE_UINT32(data);
data += 4;
}
return materialPtr;
2003-08-15 18:00:22 +00:00
}
Model::Face::~Face() {
2004-12-09 23:55:43 +00:00
delete[] _vertices;
delete[] _texVertices;
2003-08-15 18:00:22 +00:00
}
Model::HierNode::~HierNode() {
HierNode *child = _child;
while (child) {
child->_parent = NULL;
child = child->_sibling;
}
}
2009-06-26 16:13:11 +00:00
void Model::HierNode::loadBinary(const char *&data, Model::HierNode *hierNodes, const Geoset *g) {
2004-12-09 23:55:43 +00:00
memcpy(_name, data, 64);
_flags = READ_LE_UINT32(data + 64);
_type = READ_LE_UINT32(data + 72);
2004-04-19 09:56:34 +00:00
int meshNum = READ_LE_UINT32(data + 76);
if (meshNum < 0)
2004-12-09 23:55:43 +00:00
_mesh = NULL;
2004-04-19 09:56:34 +00:00
else
2009-06-26 16:13:11 +00:00
_mesh = g->_meshes + meshNum;
2004-12-09 23:55:43 +00:00
_depth = READ_LE_UINT32(data + 80);
2004-04-19 09:56:34 +00:00
int parentPtr = READ_LE_UINT32(data + 84);
2004-12-09 23:55:43 +00:00
_numChildren = READ_LE_UINT32(data + 88);
2004-04-19 09:56:34 +00:00
int childPtr = READ_LE_UINT32(data + 92);
int siblingPtr = READ_LE_UINT32(data + 96);
_pivot = Graphics::get_vector3d(data + 100);
_pos = Graphics::get_vector3d(data + 112);
2004-12-09 23:55:43 +00:00
_pitch = get_float(data + 124);
_yaw = get_float(data + 128);
_roll = get_float(data + 132);
_animPos.set(0,0,0);
_animPitch = 0;
_animYaw = 0;
_animRoll = 0;
2011-05-15 13:47:09 +00:00
_sprite = NULL;
2004-04-19 09:56:34 +00:00
data += 184;
if (parentPtr != 0) {
2004-12-09 23:55:43 +00:00
_parent = hierNodes + READ_LE_UINT32(data);
2004-04-19 09:56:34 +00:00
data += 4;
} else
2004-12-09 23:55:43 +00:00
_parent = NULL;
2004-04-19 09:56:34 +00:00
if (childPtr != 0) {
2004-12-09 23:55:43 +00:00
_child = hierNodes + READ_LE_UINT32(data);
2004-04-19 09:56:34 +00:00
data += 4;
} else
2004-12-09 23:55:43 +00:00
_child = NULL;
2004-04-19 09:56:34 +00:00
if (siblingPtr != 0) {
2004-12-09 23:55:43 +00:00
_sibling = hierNodes + READ_LE_UINT32(data);
2004-04-19 09:56:34 +00:00
data += 4;
} else
2004-12-09 23:55:43 +00:00
_sibling = NULL;
2004-12-09 23:55:43 +00:00
_meshVisible = true;
_hierVisible = true;
_initialized = true;
2004-04-19 09:56:34 +00:00
}
2003-08-15 18:00:22 +00:00
void Model::draw() const {
2004-12-09 23:55:43 +00:00
_rootHierNode->draw();
2003-08-15 18:00:22 +00:00
}
Model::HierNode *Model::copyHierarchy() {
2004-12-09 23:55:43 +00:00
HierNode *result = new HierNode[_numHierNodes];
2009-05-10 16:43:41 +00:00
memcpy(result, _rootHierNode, _numHierNodes * sizeof(HierNode));
// Now adjust pointers
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numHierNodes; i++) {
2008-09-10 11:16:57 +00:00
if (result[i]._parent)
2009-06-26 16:13:11 +00:00
result[i]._parent = &result[(_rootHierNode[i]._parent - _rootHierNode)];
2008-09-10 11:16:57 +00:00
if (result[i]._child)
2009-06-26 16:13:11 +00:00
result[i]._child = &result[(_rootHierNode[i]._child - _rootHierNode)];
2008-09-10 11:16:57 +00:00
if (result[i]._sibling)
2009-06-26 16:13:11 +00:00
result[i]._sibling = &result[(_rootHierNode[i]._sibling - _rootHierNode)];
}
return result;
2003-08-15 18:00:22 +00:00
}
void Model::loadText(TextSplitter *ts, CMap *cmap) {
2009-06-26 16:13:11 +00:00
ts->expectString("section: header");
int major, minor;
2009-06-26 16:13:11 +00:00
ts->scanString("3do %d.%d", 2, &major, &minor);
ts->expectString("section: modelresource");
ts->scanString("materials %d", 1, &_numMaterials);
_materials = new Material*[_numMaterials];
_materialNames = new char[_numMaterials][32];
_materialsShared = new bool[_numMaterials];
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numMaterials; i++) {
char materialName[32];
int num;
_materialsShared[i] = false;
_materials[i] = NULL;
2008-07-30 07:04:32 +00:00
2009-06-26 16:13:11 +00:00
ts->scanString("%d: %32s", 2, &num, materialName);
strcpy(_materialNames[num], materialName);
loadMaterial(num, cmap);
}
2009-06-26 16:13:11 +00:00
ts->expectString("section: geometrydef");
ts->scanString("radius %f", 1, &_radius);
ts->scanString("insert offset %f %f %f", 3, &_insertOffset.x(), &_insertOffset.y(), &_insertOffset.z());
ts->scanString("geosets %d", 1, &_numGeosets);
2004-12-09 23:55:43 +00:00
_geosets = new Geoset[_numGeosets];
for (int i = 0; i < _numGeosets; i++) {
int num;
2009-06-26 16:13:11 +00:00
ts->scanString("geoset %d", 1, &num);
_geosets[num].loadText(ts, _materials);
}
2009-06-26 16:13:11 +00:00
ts->expectString("section: hierarchydef");
ts->scanString("hierarchy nodes %d", 1, &_numHierNodes);
2004-12-09 23:55:43 +00:00
_rootHierNode = new HierNode[_numHierNodes];
for (int i = 0; i < _numHierNodes; i++) {
2009-06-07 14:34:48 +00:00
int num, mesh, parent, child, sibling, numChildren;
unsigned int flags, type;
float x, y, z, pitch, yaw, roll, pivotx, pivoty, pivotz;
char name[64];
2009-06-26 16:13:11 +00:00
ts->scanString(" %d: %x %x %d %d %d %d %d %f %f %f %f %f %f %f %f %f %64s",
18, &num, &flags, &type, &mesh, &parent, &child, &sibling,
2004-12-09 23:55:43 +00:00
&numChildren, &x, &y, &z, &pitch, &yaw, &roll, &pivotx, &pivoty, &pivotz, name);
2009-06-07 14:34:48 +00:00
_rootHierNode[num]._flags = (int)flags;
_rootHierNode[num]._type = (int)type;
if (mesh < 0)
2004-12-09 23:55:43 +00:00
_rootHierNode[num]._mesh = NULL;
else
2009-06-26 16:13:11 +00:00
_rootHierNode[num]._mesh = &_geosets[0]._meshes[mesh];
if (parent >= 0) {
2009-06-26 16:13:11 +00:00
_rootHierNode[num]._parent = &_rootHierNode[parent];
2004-12-09 23:55:43 +00:00
_rootHierNode[num]._depth = _rootHierNode[parent]._depth + 1;
} else {
2004-12-09 23:55:43 +00:00
_rootHierNode[num]._parent = NULL;
_rootHierNode[num]._depth = 0;
}
if (child >= 0)
2009-06-26 16:13:11 +00:00
_rootHierNode[num]._child = &_rootHierNode[child];
else
2004-12-09 23:55:43 +00:00
_rootHierNode[num]._child = NULL;
if (sibling >= 0)
2009-06-26 16:13:11 +00:00
_rootHierNode[num]._sibling = &_rootHierNode[sibling];
else
2004-12-09 23:55:43 +00:00
_rootHierNode[num]._sibling = NULL;
_rootHierNode[num]._numChildren = numChildren;
_rootHierNode[num]._pos = Graphics::Vector3d(x, y, z);
2004-12-09 23:55:43 +00:00
_rootHierNode[num]._pitch = pitch;
_rootHierNode[num]._yaw = yaw;
_rootHierNode[num]._roll = roll;
_rootHierNode[num]._pivot = Graphics::Vector3d(pivotx, pivoty, pivotz);
2004-12-09 23:55:43 +00:00
_rootHierNode[num]._meshVisible = true;
_rootHierNode[num]._hierVisible = true;
_rootHierNode[num]._sprite = NULL;
}
2004-04-19 09:56:34 +00:00
2011-05-05 09:56:36 +00:00
if (!ts->isEof() && (gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL))
warning("Unexpected junk at end of model text");
2003-08-15 18:00:22 +00:00
}
void Model::loadMaterial(int index, CMap *cmap) {
if (!_materialsShared[index]) {
delete _materials[index];
_materials[index] = NULL;
}
if (_parent) {
_materials[index] = _parent->findMaterial(_materialNames[index]);
_materialsShared[index] = true;
}
if (!_materials[index]) {
_materials[index] = g_resourceloader->loadMaterial(_materialNames[index], cmap);
_materialsShared[index] = false;
}
}
Material *Model::findMaterial(const char *name) const {
for (int i = 0; i < _numMaterials; ++i) {
if (scumm_stricmp(name, _materialNames[i]) == 0) {
return _materials[i];
}
}
return NULL;
}
void Model::Geoset::changeMaterials(Material *materials[]) {
for (int i = 0; i < _numMeshes; i++)
_meshes[i].changeMaterials(materials);
}
void Model::Geoset::loadText(TextSplitter *ts, Material *materials[]) {
2009-06-26 16:13:11 +00:00
ts->scanString("meshes %d", 1, &_numMeshes);
2004-12-09 23:55:43 +00:00
_meshes = new Mesh[_numMeshes];
for (int i = 0; i < _numMeshes; i++) {
int num;
2009-06-26 16:13:11 +00:00
ts->scanString("mesh %d", 1, &num);
2004-12-09 23:55:43 +00:00
_meshes[num].loadText(ts, materials);
}
2003-08-15 18:00:22 +00:00
}
void Model::Mesh::changeMaterials(Material *materials[]) {
for (int i = 0; i < _numFaces; i++)
_faces[i].changeMaterial(materials[_materialid[i]]);
}
void Model::Mesh::loadText(TextSplitter *ts, Material* materials[]) {
2009-06-26 16:13:11 +00:00
ts->scanString("name %32s", 1, _name);
ts->scanString("radius %f", 1, &_radius);
// In data001/rope_scale.3do, the shadow line is missing
2011-05-05 09:56:36 +00:00
if (sscanf(ts->getCurrentLine(), "shadow %d", &_shadow) < 1) {
2004-12-09 23:55:43 +00:00
_shadow = 0;
} else
2009-06-26 16:13:11 +00:00
ts->nextLine();
ts->scanString("geometrymode %d", 1, &_geometryMode);
ts->scanString("lightingmode %d", 1, &_lightingMode);
ts->scanString("texturemode %d", 1, &_textureMode);
ts->scanString("vertices %d", 1, &_numVertices);
2004-12-09 23:55:43 +00:00
_vertices = new float[3 * _numVertices];
_verticesI = new float[_numVertices];
_vertNormals = new float[3 * _numVertices];
for (int i = 0; i < _numVertices; i++) {
int num;
float x, y, z, ival;
2009-06-26 16:13:11 +00:00
ts->scanString(" %d: %f %f %f %f", 5, &num, &x, &y, &z, &ival);
2004-12-09 23:55:43 +00:00
_vertices[3 * num] = x;
_vertices[3 * num + 1] = y;
_vertices[3 * num + 2] = z;
_verticesI[num] = ival;
}
2009-06-26 16:13:11 +00:00
ts->scanString("texture vertices %d", 1, &_numTextureVerts);
2004-12-09 23:55:43 +00:00
_textureVerts = new float[2 * _numTextureVerts];
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numTextureVerts; i++) {
int num;
float x, y;
2009-06-26 16:13:11 +00:00
ts->scanString(" %d: %f %f", 3, &num, &x, &y);
2004-12-09 23:55:43 +00:00
_textureVerts[2 * num] = x;
_textureVerts[2 * num + 1] = y;
}
2009-06-26 16:13:11 +00:00
ts->expectString("vertex normals");
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numVertices; i++) {
int num;
float x, y, z;
2009-06-26 16:13:11 +00:00
ts->scanString(" %d: %f %f %f", 4, &num, &x, &y, &z);
2004-12-09 23:55:43 +00:00
_vertNormals[3 * num] = x;
_vertNormals[3 * num + 1] = y;
_vertNormals[3 * num + 2] = z;
}
2009-06-26 16:13:11 +00:00
ts->scanString("faces %d", 1, &_numFaces);
2004-12-09 23:55:43 +00:00
_faces = new Face[_numFaces];
_materialid = new int[_numFaces];
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numFaces; i++) {
2009-06-07 14:34:48 +00:00
int num, materialid, geo, light, tex, verts;
unsigned int type;
float extralight;
int readlen;
2004-12-09 23:55:43 +00:00
2011-05-05 09:56:36 +00:00
if (ts->isEof())
error("Expected face data, got EOF");
2004-12-09 23:55:43 +00:00
2011-05-05 09:56:36 +00:00
if (sscanf(ts->getCurrentLine(), " %d: %d %x %d %d %d %f %d%n", &num, &materialid, &type, &geo, &light, &tex, &extralight, &verts, &readlen) < 8)
error("Expected face data, got '%s'", ts->getCurrentLine());
2004-12-09 23:55:43 +00:00
assert(materialid != -1);
_materialid[num] = materialid;
_faces[num]._material = materials[materialid];
2009-06-07 14:34:48 +00:00
_faces[num]._type = (int)type;
2004-12-09 23:55:43 +00:00
_faces[num]._geo = geo;
_faces[num]._light = light;
_faces[num]._tex = tex;
_faces[num]._extraLight = extralight;
_faces[num]._numVertices = verts;
_faces[num]._vertices = new int[verts];
_faces[num]._texVertices = new int[verts];
for (int j = 0; j < verts; j++) {
int readlen2;
2004-12-09 23:55:43 +00:00
2011-05-05 09:56:36 +00:00
if (sscanf(ts->getCurrentLine() + readlen, " %d, %d%n", &_faces[num]._vertices[j], &_faces[num]._texVertices[j], &readlen2) < 2)
error("Could not read vertex indices in line '%s'",
2004-12-09 23:55:43 +00:00
2011-05-05 09:56:36 +00:00
ts->getCurrentLine());
readlen += readlen2;
}
2009-06-26 16:13:11 +00:00
ts->nextLine();
}
2009-06-26 16:13:11 +00:00
ts->expectString("face normals");
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numFaces; i++) {
int num;
float x, y, z;
2009-06-26 16:13:11 +00:00
ts->scanString(" %d: %f %f %f", 4, &num, &x, &y, &z);
_faces[num]._normal = Graphics::Vector3d(x, y, z);
}
2003-08-15 18:00:22 +00:00
}
void Model::HierNode::draw() const {
2004-04-19 09:56:34 +00:00
g_driver->drawHierachyNode(this);
2003-08-15 18:00:22 +00:00
}
void Model::HierNode::addChild(HierNode *child) {
2004-12-09 23:55:43 +00:00
HierNode **childPos = &_child;
2008-07-30 07:04:32 +00:00
while (*childPos)
2004-12-09 23:55:43 +00:00
childPos = &(*childPos)->_sibling;
*childPos = child;
2004-12-09 23:55:43 +00:00
child->_parent = this;
2003-08-15 18:00:22 +00:00
}
void Model::HierNode::removeChild(HierNode *child) {
2004-12-09 23:55:43 +00:00
HierNode **childPos = &_child;
2008-07-30 07:04:32 +00:00
while (*childPos && *childPos != child)
2004-12-09 23:55:43 +00:00
childPos = &(*childPos)->_sibling;
2008-07-30 07:04:32 +00:00
if (*childPos) {
2004-12-09 23:55:43 +00:00
*childPos = child->_sibling;
child->_parent = NULL;
}
2003-08-15 18:00:22 +00:00
}
void Model::HierNode::setMatrix(Graphics::Matrix4 matrix) {
2004-12-09 23:55:43 +00:00
_matrix = matrix;
}
void Model::HierNode::update() {
if (!_initialized)
return;
2009-05-09 17:47:28 +00:00
Graphics::Vector3d animPos = _pos + _animPos;
float animPitch = _pitch + _animPitch;
float animYaw = _yaw + _animYaw;
float animRoll = _roll + _animRoll;
_localMatrix._pos.set(animPos.x(), animPos.y(), animPos.z());
_localMatrix._rot.buildFromPitchYawRoll(animPitch, animYaw, animRoll);
2004-12-09 23:55:43 +00:00
_matrix *= _localMatrix;
2004-12-09 23:55:43 +00:00
_pivotMatrix = _matrix;
2005-01-11 19:46:47 +00:00
_pivotMatrix.translate(_pivot.x(), _pivot.y(), _pivot.z());
2008-07-30 07:04:32 +00:00
if (_mesh) {
2005-01-11 19:46:47 +00:00
_mesh->_matrix = _pivotMatrix;
}
HierNode *child = _child;
while (child) {
child->setMatrix(_matrix);
child->update();
child = child->_sibling;
2005-01-11 19:46:47 +00:00
}
}
2011-05-15 13:47:09 +00:00
void Model::HierNode::addSprite(Sprite *sprite) {
sprite->_next = _sprite;
_sprite = sprite;
}
void Model::HierNode::removeSprite(Sprite *sprite) {
2011-05-25 20:01:25 +00:00
Sprite* curr = _sprite;
Sprite* prev = NULL;
while (curr) {
if (curr == sprite) {
if (prev)
prev->_next = curr->_next;
else
_sprite = curr->_next;
2011-05-15 13:47:09 +00:00
}
2011-05-25 20:01:25 +00:00
prev = curr;
curr = curr->_next;
2011-05-15 13:47:09 +00:00
}
}
2003-08-15 18:00:22 +00:00
void Model::Mesh::draw() const {
int winX1, winY1, winX2, winY2;
g_driver->getBoundingBoxPos(this, &winX1, &winY1, &winX2, &winY2);
2008-09-26 17:48:46 +00:00
if (winX1 != -1 && winY1 != -1 && winX2 != -1 && winY2 != -1) {
g_winX1 = MIN(g_winX1, winX1);
g_winY1 = MIN(g_winY1, winY1);
g_winX2 = MAX(g_winX2, winX2);
g_winY2 = MAX(g_winY2, winY2);
}
if (_lightingMode == 0)
g_driver->disableLights();
2004-12-09 23:55:43 +00:00
for (int i = 0; i < _numFaces; i++)
_faces[i].draw(_vertices, _vertNormals, _textureVerts);
if (_lightingMode == 0)
g_driver->enableLights();
2004-04-19 09:56:34 +00:00
}
2003-08-15 18:00:22 +00:00
void Model::Face::draw(float *vertices, float *vertNormals, float *textureVerts) const {
2004-12-09 23:55:43 +00:00
_material->select();
2004-04-19 09:56:34 +00:00
g_driver->drawModelFace(this, vertices, vertNormals, textureVerts);
2003-08-15 18:00:22 +00:00
}
2009-05-25 06:49:57 +00:00
} // end of namespace Grim