1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2011
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 ////////////////////////////////////////////////////////////////////////////////
20
21 #include <3dsparse/Model.h>
22 #include <3dsparse/ModelMaths.h>
23 #include <common/Defines.h>
24
Model()25 Model::Model() :
26 startFrame_(0), totalFrames_(0),
27 noTriangles_(0),
28 texturesUsed_(false)
29 {
30 }
31
~Model()32 Model::~Model()
33 {
34 while (!meshes_.empty())
35 {
36 Mesh *mesh = meshes_.back();
37 meshes_.pop_back();
38 delete mesh;
39 }
40 while (!bones_.empty())
41 {
42 Bone *bone = bones_.back();
43 bones_.pop_back();
44 delete bone;
45 }
46 while (!baseBoneTypes_.empty())
47 {
48 BoneType *boneType = baseBoneTypes_.back();
49 baseBoneTypes_.pop_back();
50 delete boneType;
51 }
52 }
53
centre()54 void Model::centre()
55 {
56 max_ = meshes_.front()->getMax();
57 min_ = meshes_.front()->getMin();
58 DIALOG_ASSERT(!meshes_.empty());
59
60 std::vector<Mesh *>::iterator itor;
61 for (itor = meshes_.begin();
62 itor != meshes_.end();
63 ++itor)
64 {
65 max_[0] = MAX(max_[0], (*itor)->getMax()[0]);
66 max_[1] = MAX(max_[1], (*itor)->getMax()[1]);
67 max_[2] = MAX(max_[2], (*itor)->getMax()[2]);
68
69 min_[0] = MIN(min_[0], (*itor)->getMin()[0]);
70 min_[1] = MIN(min_[1], (*itor)->getMin()[1]);
71 min_[2] = MIN(min_[2], (*itor)->getMin()[2]);
72 }
73
74 FixedVector centre = (max_ + min_) / -2;
75 for (itor = meshes_.begin();
76 itor != meshes_.end();
77 ++itor)
78 {
79 (*itor)->move(centre);
80 }
81 min_ += centre;
82 max_ += centre;
83 }
84
setup()85 void Model::setup()
86 {
87 centre();
88 setupBones();
89 setupColor();
90 countTextures();
91 }
92
countTextures()93 void Model::countTextures()
94 {
95 unsigned int texturesUsed = 0;
96 std::vector<Mesh *>::iterator itor;
97 for (itor = meshes_.begin();
98 itor != meshes_.end();
99 ++itor)
100 {
101 Mesh *mesh = *itor;
102 if (mesh->getTextureName()[0])
103 {
104 texturesUsed++;
105 }
106 noTriangles_ += (int) mesh->getFaces().size();
107 }
108 //DIALOG_ASSERT(texturesUsed == meshes_.size());
109 texturesUsed_ = (texturesUsed > 0);
110 }
111
setupColor()112 void Model::setupColor()
113 {
114 FixedVector lightpos(fixed(true, -3000), fixed(true, -2000), 1);
115 lightpos.StoreNormalize();
116
117 std::vector<Mesh *>::iterator itor;
118 for (itor = meshes_.begin();
119 itor != meshes_.end();
120 ++itor)
121 {
122 Mesh *mesh = (*itor);
123
124 std::vector<Face *>::iterator itor;
125 for (itor = mesh->getFaces().begin();
126 itor != mesh->getFaces().end();
127 ++itor)
128 {
129 Face *face = *itor;
130 for (int i=0; i<3; i++)
131 {
132 Vertex *vertex = mesh->getVertex(face->v[i]);
133 FixedVector &normal = face->normal[i];
134
135 const fixed ambientLight = fixed(true, 2000);
136 const fixed diffuseLight = fixed(true, 8000);
137 fixed diffuseLightMult =
138 (((lightpos.dotP(normal.Normalize())) / 2) + fixed(true, 5000));
139 fixed intense = diffuseLightMult * diffuseLight + ambientLight;
140 if (intense > 1) intense = 1;
141 vertex->lightintense[0] = intense;
142 vertex->lightintense[1] = intense;
143 vertex->lightintense[2] = intense;
144 }
145 }
146 }
147 }
148
setupBones()149 void Model::setupBones()
150 {
151 for (unsigned int b=0; b<bones_.size(); b++)
152 {
153 baseBoneTypes_.push_back(new BoneType());
154 }
155
156 for (unsigned int b=0; b<bones_.size(); b++)
157 {
158 Bone *bone = bones_[b];
159 BoneType *type = baseBoneTypes_[b];
160
161 // Find the parent bone
162 for (unsigned int p=0; p<bones_.size(); p++)
163 {
164 Bone *parent = bones_[p];
165 if (0 == strcmp(bone->getParentName(), parent->getName()))
166 {
167 type->parent_ = p;
168 break;
169 }
170 }
171
172 // Set rotation and position
173 FixedVector rot;
174 rot[0] = bone->getRotation()[0] * 180 / fixed::XPI;
175 rot[1] = bone->getRotation()[1] * 180 / fixed::XPI;
176 rot[2] = bone->getRotation()[2] * 180 / fixed::XPI;
177
178 ModelMaths::angleMatrix(rot, type->relative_);
179 type->relative_[0][3] = bone->getPosition()[0];
180 type->relative_[1][3] = bone->getPosition()[1];
181 type->relative_[2][3] = bone->getPosition()[2];
182
183 // Setup child relations
184 if (type->parent_ != -1)
185 {
186 BoneType *parent = baseBoneTypes_[type->parent_];
187
188 ModelMaths::concatTransforms(parent->absolute_, type->relative_, type->absolute_);
189 memcpy(type->final_, type->absolute_, sizeof(BoneMatrixType));
190 }
191 else // No parent
192 {
193 memcpy(type->absolute_, type->relative_, sizeof(BoneMatrixType));
194 memcpy(type->final_, type->relative_, sizeof(BoneMatrixType));
195 }
196 }
197
198 // Move vertexes to align with the bones
199 bool referenceBones = false;
200 for (unsigned int i=0; i<meshes_.size(); i++)
201 {
202 Mesh *mesh = meshes_[i];
203 for (unsigned int j=0; j<mesh->getVertexes().size(); j++)
204 {
205 Vertex *vertex = mesh->getVertex(j);
206 if (vertex->boneIndex != -1)
207 {
208 DIALOG_ASSERT(vertex->boneIndex < int(bones_.size()));
209
210 BoneType *type = baseBoneTypes_[vertex->boneIndex];
211 referenceBones = true;
212
213 // Note: Translation of MS to S3D coords
214
215 // Translation
216 vertex->position[0] -= type->absolute_[0][3];
217 vertex->position[1] -= type->absolute_[2][3];
218 vertex->position[2] -= type->absolute_[1][3];
219
220 // Rotation
221 FixedVector tmpPos;
222 tmpPos[0] = vertex->position[0];
223 tmpPos[1] = vertex->position[2];
224 tmpPos[2] = vertex->position[1];
225
226 FixedVector tmp;
227 ModelMaths::vectorIRotate(tmpPos, type->absolute_, tmp);
228 vertex->position[0] = tmp[0];
229 vertex->position[1] = tmp[2];
230 vertex->position[2] = tmp[1];
231 }
232 }
233 }
234
235 if (!referenceBones) totalFrames_ = 1;
236 }
237