//////////////////////////////////////////////////////////////////////////////// // Scorched3D (c) 2000-2004 // // This file is part of Scorched3D. // // Scorched3D is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // Scorched3D 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Scorched3D; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// #include <3dsparse/Model.h> #include <3dsparse/ModelMaths.h> #include Model::Model() : startFrame_(0), totalFrames_(0) { } Model::~Model() { while (!meshes_.empty()) { Mesh *mesh = meshes_.back(); meshes_.pop_back(); delete mesh; } while (!bones_.empty()) { Bone *bone = bones_.back(); bones_.pop_back(); delete bone; } while (!baseBoneTypes_.empty()) { BoneType *boneType = baseBoneTypes_.back(); baseBoneTypes_.pop_back(); delete boneType; } } void Model::centre() { max_ = meshes_.front()->getMax(); min_ = meshes_.front()->getMin(); DIALOG_ASSERT(!meshes_.empty()); std::vector::iterator itor; for (itor = meshes_.begin(); itor != meshes_.end(); itor++) { max_[0] = MAX(max_[0], (*itor)->getMax()[0]); max_[1] = MAX(max_[1], (*itor)->getMax()[1]); max_[2] = MAX(max_[2], (*itor)->getMax()[2]); min_[0] = MIN(min_[0], (*itor)->getMin()[0]); min_[1] = MIN(min_[1], (*itor)->getMin()[1]); min_[2] = MIN(min_[2], (*itor)->getMin()[2]); } Vector centre = (max_ + min_) / -2.0f; for (itor = meshes_.begin(); itor != meshes_.end(); itor++) { (*itor)->move(centre); } min_ += centre; max_ += centre; } int Model::getNumberTriangles() { int tris = 0; std::vector::iterator itor; for (itor = meshes_.begin(); itor != meshes_.end(); itor++) { Mesh *mesh = *itor; tris += (int) mesh->getFaces().size(); } return tris; } void Model::setup() { centre(); setupBones(); setupColor(); } void Model::setupColor() { Vector lightpos(-0.3f, -0.2f, 1.0f); lightpos.StoreNormalize(); std::vector::iterator itor; for (itor = meshes_.begin(); itor != meshes_.end(); itor++) { Mesh *mesh = (*itor); std::vector::iterator itor; for (itor = mesh->getFaces().begin(); itor != mesh->getFaces().end(); itor++) { Face *face = *itor; for (int i=0; i<3; i++) { Vertex *vertex = mesh->getVertex(face->v[i]); Vector &normal = face->normal[i]; const float ambientLight = 0.2f; const float diffuseLight = 0.8f; float diffuseLightMult = (((lightpos.dotP(normal.Normalize())) / 2.0f) + 0.5f); float intense = diffuseLightMult * diffuseLight + ambientLight; if (intense > 1.0f) intense = 1.0f; vertex->lightintense[0] = intense; vertex->lightintense[1] = intense; vertex->lightintense[2] = intense; } } } } void Model::setupBones() { for (unsigned int b=0; bgetParentName(), parent->getName())) { type->parent_ = p; break; } } // Set rotation and position Vector rot; rot[0] = bone->getRotation()[0] * 180.0f / PI; rot[1] = bone->getRotation()[1] * 180.0f / PI; rot[2] = bone->getRotation()[2] * 180.0f / PI; ModelMaths::angleMatrix(rot, type->relative_); type->relative_[0][3] = bone->getPosition()[0]; type->relative_[1][3] = bone->getPosition()[1]; type->relative_[2][3] = bone->getPosition()[2]; // Setup child relations if (type->parent_ != -1) { BoneType *parent = baseBoneTypes_[type->parent_]; ModelMaths::concatTransforms(parent->absolute_, type->relative_, type->absolute_); memcpy(type->final_, type->absolute_, sizeof(BoneMatrixType)); } else // No parent { memcpy(type->absolute_, type->relative_, sizeof(BoneMatrixType)); memcpy(type->final_, type->relative_, sizeof(BoneMatrixType)); } } // Move vertexes to align with the bones for (unsigned int i=0; igetVertexes().size(); j++) { Vertex *vertex = mesh->getVertex(j); if (vertex->boneIndex != -1) { BoneType *type = baseBoneTypes_[vertex->boneIndex]; mesh->getReferencesBones() = true; // Note: Translation of MS to S3D coords // Translation vertex->position[0] -= type->absolute_[0][3]; vertex->position[1] -= type->absolute_[2][3]; vertex->position[2] -= type->absolute_[1][3]; // Rotation Vector tmpPos; tmpPos[0] = vertex->position[0]; tmpPos[1] = vertex->position[2]; tmpPos[2] = vertex->position[1]; Vector tmp; ModelMaths::vectorIRotate(tmpPos, type->absolute_, tmp); vertex->position[0] = tmp[0]; vertex->position[1] = tmp[2]; vertex->position[2] = tmp[1]; } } } }