ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

model.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/model/model.h"
00024 
00025 #include "engines/stark/services/archiveloader.h"
00026 #include "engines/stark/model/animhandler.h"
00027 #include "engines/stark/gfx/texture.h"
00028 
00029 #include "math/aabb.h"
00030 
00031 namespace Stark {
00032 
00033 Model::Model() :
00034         _u1(0),
00035         _u2(0.0) {
00036 
00037 }
00038 
00039 Model::~Model() {
00040     for (Common::Array<VertNode *>::iterator it = _vertices.begin(); it != _vertices.end(); ++it)
00041         delete *it;
00042 
00043     for (Common::Array<Material *>::iterator it = _materials.begin(); it != _materials.end(); ++it)
00044         delete *it;
00045 
00046     for (Common::Array<Face *>::iterator it = _faces.begin(); it != _faces.end(); ++it)
00047         delete *it;
00048 
00049     for (Common::Array<BoneNode *>::iterator it = _bones.begin(); it != _bones.end(); ++it)
00050         delete *it;
00051 }
00052 
00053 void Model::readFromStream(ArchiveReadStream *stream) {
00054     uint32 id = stream->readUint32LE();
00055     if (id != 4) {
00056         error("Wrong magic 1 while reading actor '%d'", id);
00057     }
00058 
00059     uint32 format = stream->readUint32LE();
00060     if (format == 256) {
00061         _u1 = stream->readUint32LE();
00062     } else if (format == 16) {
00063         _u1 = 0;
00064     } else {
00065         error("Wrong format while reading actor '%d'", format);
00066     }
00067 
00068     uint32 id2 = stream->readUint32LE();
00069     if (id2 != 0xDEADBABE) {
00070         error("Wrong magic 2 while reading actor '%d'", id2);
00071     }
00072 
00073     _u2 = stream->readFloat();
00074 
00075     uint32 numMaterials = stream->readUint32LE();
00076 
00077     for (uint i = 0; i < numMaterials; ++i) {
00078         Material *node = new Material();
00079         node->name = stream->readString();
00080         stream->readUint32LE(); // CHECKME: Unknown data
00081         node->texture = stream->readString();
00082         node->r = stream->readFloat();
00083         node->g = stream->readFloat();
00084         node->b = stream->readFloat();
00085         _materials.push_back(node);
00086     }
00087 
00088     uint32 numUnknowns = stream->readUint32LE();
00089     if (numUnknowns != 0) {
00090         error("Found a mesh with numUnknowns != 0");
00091     }
00092 
00093     readBones(stream);
00094 
00095     uint32 numMeshes = stream->readUint32LE();
00096     if (numMeshes != 1) {
00097         error("Found a mesh with numMeshes != 1 (%d)", numMeshes);
00098     }
00099 
00100     _name = stream->readString();
00101 
00102     uint32 numFaces = stream->readUint32LE();
00103     for (uint32 j = 0; j < numFaces; ++j) {
00104         uint faceVertexIndexOffset = _vertices.size();
00105 
00106         Face *face = new Face();
00107         face->materialId = stream->readUint32LE();
00108 
00109         uint32 numVertices = stream->readUint32LE();
00110         for (uint32 k = 0; k < numVertices; ++k) {
00111             VertNode *vert = new VertNode();
00112             vert->_pos1 = stream->readVector3();
00113             vert->_pos2 = stream->readVector3();
00114             vert->_normal = stream->readVector3();
00115             vert->_texS = stream->readFloat();
00116             vert->_texT = stream->readFloat();
00117             vert->_bone1 = stream->readUint32LE();
00118             vert->_bone2 = stream->readUint32LE();
00119             vert->_boneWeight = stream->readFloat();
00120             _vertices.push_back(vert);
00121         }
00122 
00123         uint32 numTriangles = stream->readUint32LE();
00124         face->vertexIndices.resize(numTriangles * 3); // 3 vertex indices per triangle
00125         for (uint32 k = 0; k < numTriangles; ++k) {
00126             face->vertexIndices[k * 3 + 0] = stream->readUint32LE() + faceVertexIndexOffset;
00127             face->vertexIndices[k * 3 + 1] = stream->readUint32LE() + faceVertexIndexOffset;
00128             face->vertexIndices[k * 3 + 2] = stream->readUint32LE() + faceVertexIndexOffset;
00129         }
00130 
00131         _faces.push_back(face);
00132     }
00133 
00134     buildBonesBoundingBoxes();
00135 }
00136 
00137 void Model::readBones(ArchiveReadStream *stream) {
00138     uint32 numBones = stream->readUint32LE();
00139     for (uint32 i = 0; i < numBones; ++i) {
00140         BoneNode *node = new BoneNode();
00141         node->_name = stream->readString();
00142         node->_u1 = stream->readFloat();
00143 
00144         uint32 len = stream->readUint32LE();
00145         for (uint32 j = 0; j < len; ++j)
00146             node->_children.push_back(stream->readUint32LE());
00147 
00148         node->_idx = _bones.size();
00149         _bones.push_back(node);
00150     }
00151 
00152     for (uint32 i = 0; i < numBones; ++i) {
00153         BoneNode *node = _bones[i];
00154         for (uint j = 0; j < node->_children.size(); ++j) {
00155             _bones[node->_children[j]]->_parent = i;
00156         }
00157     }
00158 }
00159 
00160 void Model::buildBonesBoundingBoxes() {
00161     for (uint i = 0; i < _bones.size(); i++) {
00162         buildBoneBoundingBox(_bones[i]);
00163     }
00164 }
00165 
00166 void Model::buildBoneBoundingBox(BoneNode *bone) const {
00167     bone->_boundingBox.reset();
00168 
00169     // Add all the vertices with a non zero weight for the bone to the bone's bounding box
00170     for (uint k = 0; k < _vertices.size(); k++) {
00171         VertNode *vert = _vertices[k];
00172 
00173         if (vert->_bone1 == bone->_idx) {
00174             bone->_boundingBox.expand(vert->_pos1);
00175         }
00176 
00177         if (vert->_bone2 == bone->_idx) {
00178             bone->_boundingBox.expand(vert->_pos2);
00179         }
00180     }
00181 }
00182 
00183 bool Model::intersectRay(const Math::Ray &ray) const {
00184     for (uint i = 0; i < _bones.size(); i++) {
00185         if (_bones[i]->intersectRay(ray)) {
00186             return true;
00187         }
00188     }
00189 
00190     return false;
00191 }
00192 
00193 void Model::updateBoundingBox() {
00194     _boundingBox.reset();
00195     for (uint i = 0; i < _bones.size(); i++) {
00196         _bones[i]->expandModelSpaceBB(_boundingBox);
00197     }
00198 }
00199 
00200 Math::AABB Model::getBoundingBox() const {
00201     return _boundingBox;
00202 }
00203 
00204 bool BoneNode::intersectRay(const Math::Ray &ray) const {
00205     Math::Ray localRay = ray;
00206     localRay.translate(-_animPos);
00207     localRay.rotate(_animRot.inverse());
00208 
00209     return localRay.intersectAABB(_boundingBox);
00210 }
00211 
00212 void BoneNode::expandModelSpaceBB(Math::AABB &aabb) const {
00213     // Transform the bounding box
00214     Math::Vector3d min = _boundingBox.getMin();
00215     Math::Vector3d max = _boundingBox.getMax();
00216 
00217     Math::Vector3d verts[8];
00218     verts[0].set(min.x(), min.y(), min.z());
00219     verts[1].set(max.x(), min.y(), min.z());
00220     verts[2].set(min.x(), max.y(), min.z());
00221     verts[3].set(min.x(), min.y(), max.z());
00222     verts[4].set(max.x(), max.y(), min.z());
00223     verts[5].set(max.x(), min.y(), max.z());
00224     verts[6].set(min.x(), max.y(), max.z());
00225     verts[7].set(max.x(), max.y(), max.z());
00226 
00227     for (int i = 0; i < 8; ++i) {
00228         _animRot.transform(verts[i]);
00229         verts[i] += _animPos;
00230         aabb.expand(verts[i]);
00231     }
00232 }
00233 
00234 } // End of namespace Stark


Generated on Sat Oct 12 2019 05:00:51 for ResidualVM by doxygen 1.7.1
curved edge   curved edge