rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 Open Asset Import Library (assimp)
|
nuclear@0
|
3 ----------------------------------------------------------------------
|
nuclear@0
|
4
|
nuclear@0
|
5 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
6 All rights reserved.
|
nuclear@0
|
7
|
nuclear@0
|
8 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
9 with or without modification, are permitted provided that the
|
nuclear@0
|
10 following conditions are met:
|
nuclear@0
|
11
|
nuclear@0
|
12 * Redistributions of source code must retain the above
|
nuclear@0
|
13 copyright notice, this list of conditions and the
|
nuclear@0
|
14 following disclaimer.
|
nuclear@0
|
15
|
nuclear@0
|
16 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
17 copyright notice, this list of conditions and the
|
nuclear@0
|
18 following disclaimer in the documentation and/or other
|
nuclear@0
|
19 materials provided with the distribution.
|
nuclear@0
|
20
|
nuclear@0
|
21 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
22 contributors may be used to endorse or promote products
|
nuclear@0
|
23 derived from this software without specific prior
|
nuclear@0
|
24 written permission of the assimp team.
|
nuclear@0
|
25
|
nuclear@0
|
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
37
|
nuclear@0
|
38 ----------------------------------------------------------------------
|
nuclear@0
|
39 */
|
nuclear@0
|
40
|
nuclear@0
|
41 /** @file COBLoader.cpp
|
nuclear@0
|
42 * @brief Implementation of the TrueSpace COB/SCN importer class.
|
nuclear@0
|
43 */
|
nuclear@0
|
44 #include "AssimpPCH.h"
|
nuclear@0
|
45
|
nuclear@0
|
46 #ifndef ASSIMP_BUILD_NO_COB_IMPORTER
|
nuclear@0
|
47 #include "COBLoader.h"
|
nuclear@0
|
48 #include "COBScene.h"
|
nuclear@0
|
49
|
nuclear@0
|
50 #include "StreamReader.h"
|
nuclear@0
|
51 #include "ParsingUtils.h"
|
nuclear@0
|
52 #include "fast_atof.h"
|
nuclear@0
|
53
|
nuclear@0
|
54 #include "LineSplitter.h"
|
nuclear@0
|
55 #include "TinyFormatter.h"
|
nuclear@0
|
56
|
nuclear@0
|
57 using namespace Assimp;
|
nuclear@0
|
58 using namespace Assimp::COB;
|
nuclear@0
|
59 using namespace Assimp::Formatter;
|
nuclear@0
|
60
|
nuclear@0
|
61 #define for_each BOOST_FOREACH
|
nuclear@0
|
62
|
nuclear@0
|
63
|
nuclear@0
|
64 static const float units[] = {
|
nuclear@0
|
65 1000.f,
|
nuclear@0
|
66 100.f,
|
nuclear@0
|
67 1.f,
|
nuclear@0
|
68 0.001f,
|
nuclear@0
|
69 1.f/0.0254f,
|
nuclear@0
|
70 1.f/0.3048f,
|
nuclear@0
|
71 1.f/0.9144f,
|
nuclear@0
|
72 1.f/1609.344f
|
nuclear@0
|
73 };
|
nuclear@0
|
74
|
nuclear@0
|
75 static const aiImporterDesc desc = {
|
nuclear@0
|
76 "TrueSpace Object Importer",
|
nuclear@0
|
77 "",
|
nuclear@0
|
78 "",
|
nuclear@0
|
79 "little-endian files only",
|
nuclear@0
|
80 aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
|
nuclear@0
|
81 0,
|
nuclear@0
|
82 0,
|
nuclear@0
|
83 0,
|
nuclear@0
|
84 0,
|
nuclear@0
|
85 "cob scn"
|
nuclear@0
|
86 };
|
nuclear@0
|
87
|
nuclear@0
|
88
|
nuclear@0
|
89 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
90 // Constructor to be privately used by Importer
|
nuclear@0
|
91 COBImporter::COBImporter()
|
nuclear@0
|
92 {}
|
nuclear@0
|
93
|
nuclear@0
|
94 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
95 // Destructor, private as well
|
nuclear@0
|
96 COBImporter::~COBImporter()
|
nuclear@0
|
97 {}
|
nuclear@0
|
98
|
nuclear@0
|
99 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
100 // Returns whether the class can handle the format of the given file.
|
nuclear@0
|
101 bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
nuclear@0
|
102 {
|
nuclear@0
|
103 const std::string& extension = GetExtension(pFile);
|
nuclear@0
|
104 if (extension == "cob" || extension == "scn") {
|
nuclear@0
|
105 return true;
|
nuclear@0
|
106 }
|
nuclear@0
|
107
|
nuclear@0
|
108 else if ((!extension.length() || checkSig) && pIOHandler) {
|
nuclear@0
|
109 const char* tokens[] = {"Caligary"};
|
nuclear@0
|
110 return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
nuclear@0
|
111 }
|
nuclear@0
|
112 return false;
|
nuclear@0
|
113 }
|
nuclear@0
|
114
|
nuclear@0
|
115 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
116 // Loader meta information
|
nuclear@0
|
117 const aiImporterDesc* COBImporter::GetInfo () const
|
nuclear@0
|
118 {
|
nuclear@0
|
119 return &desc;
|
nuclear@0
|
120 }
|
nuclear@0
|
121
|
nuclear@0
|
122 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
123 // Setup configuration properties for the loader
|
nuclear@0
|
124 void COBImporter::SetupProperties(const Importer* /*pImp*/)
|
nuclear@0
|
125 {
|
nuclear@0
|
126 // nothing to be done for the moment
|
nuclear@0
|
127 }
|
nuclear@0
|
128
|
nuclear@0
|
129 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
130 /*static*/ void COBImporter::ThrowException(const std::string& msg)
|
nuclear@0
|
131 {
|
nuclear@0
|
132 throw DeadlyImportError("COB: "+msg);
|
nuclear@0
|
133 }
|
nuclear@0
|
134
|
nuclear@0
|
135 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
136 // Imports the given file into the given scene structure.
|
nuclear@0
|
137 void COBImporter::InternReadFile( const std::string& pFile,
|
nuclear@0
|
138 aiScene* pScene, IOSystem* pIOHandler)
|
nuclear@0
|
139 {
|
nuclear@0
|
140 COB::Scene scene;
|
nuclear@0
|
141 boost::scoped_ptr<StreamReaderLE> stream(new StreamReaderLE( pIOHandler->Open(pFile,"rb")) );
|
nuclear@0
|
142
|
nuclear@0
|
143 // check header
|
nuclear@0
|
144 char head[32];
|
nuclear@0
|
145 stream->CopyAndAdvance(head,32);
|
nuclear@0
|
146 if (strncmp(head,"Caligari ",9)) {
|
nuclear@0
|
147 ThrowException("Could not found magic id: `Caligari`");
|
nuclear@0
|
148 }
|
nuclear@0
|
149
|
nuclear@0
|
150 DefaultLogger::get()->info("File format tag: "+std::string(head+9,6));
|
nuclear@0
|
151 void (COBImporter::* load)(Scene&,StreamReaderLE*)= head[15]=='A'?&COBImporter::ReadAsciiFile:&COBImporter::ReadBinaryFile;
|
nuclear@0
|
152 if (head[16]!='L') {
|
nuclear@0
|
153 ThrowException("File is big-endian, which is not supported");
|
nuclear@0
|
154 }
|
nuclear@0
|
155
|
nuclear@0
|
156 // load data into intermediate structures
|
nuclear@0
|
157 (this->*load)(scene,stream.get());
|
nuclear@0
|
158 if(scene.nodes.empty()) {
|
nuclear@0
|
159 ThrowException("No nodes loaded");
|
nuclear@0
|
160 }
|
nuclear@0
|
161
|
nuclear@0
|
162 // sort faces by material indices
|
nuclear@0
|
163 for_each(boost::shared_ptr< Node >& n,scene.nodes) {
|
nuclear@0
|
164 if (n->type == Node::TYPE_MESH) {
|
nuclear@0
|
165 Mesh& mesh = (Mesh&)(*n.get());
|
nuclear@0
|
166 for_each(Face& f,mesh.faces) {
|
nuclear@0
|
167 mesh.temp_map[f.material].push_back(&f);
|
nuclear@0
|
168 }
|
nuclear@0
|
169 }
|
nuclear@0
|
170 }
|
nuclear@0
|
171
|
nuclear@0
|
172 // count meshes
|
nuclear@0
|
173 for_each(boost::shared_ptr< Node >& n,scene.nodes) {
|
nuclear@0
|
174 if (n->type == Node::TYPE_MESH) {
|
nuclear@0
|
175 Mesh& mesh = (Mesh&)(*n.get());
|
nuclear@0
|
176 if (mesh.vertex_positions.size() && mesh.texture_coords.size()) {
|
nuclear@0
|
177 pScene->mNumMeshes += mesh.temp_map.size();
|
nuclear@0
|
178 }
|
nuclear@0
|
179 }
|
nuclear@0
|
180 }
|
nuclear@0
|
181 pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
|
nuclear@0
|
182 pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes]();
|
nuclear@0
|
183 pScene->mNumMeshes = 0;
|
nuclear@0
|
184
|
nuclear@0
|
185 // count lights and cameras
|
nuclear@0
|
186 for_each(boost::shared_ptr< Node >& n,scene.nodes) {
|
nuclear@0
|
187 if (n->type == Node::TYPE_LIGHT) {
|
nuclear@0
|
188 ++pScene->mNumLights;
|
nuclear@0
|
189 }
|
nuclear@0
|
190 else if (n->type == Node::TYPE_CAMERA) {
|
nuclear@0
|
191 ++pScene->mNumCameras;
|
nuclear@0
|
192 }
|
nuclear@0
|
193 }
|
nuclear@0
|
194
|
nuclear@0
|
195 if (pScene->mNumLights) {
|
nuclear@0
|
196 pScene->mLights = new aiLight*[pScene->mNumLights]();
|
nuclear@0
|
197 }
|
nuclear@0
|
198 if (pScene->mNumCameras) {
|
nuclear@0
|
199 pScene->mCameras = new aiCamera*[pScene->mNumCameras]();
|
nuclear@0
|
200 }
|
nuclear@0
|
201 pScene->mNumLights = pScene->mNumCameras = 0;
|
nuclear@0
|
202
|
nuclear@0
|
203 // resolve parents by their IDs and build the output graph
|
nuclear@0
|
204 boost::scoped_ptr<Node> root(new Group());
|
nuclear@0
|
205 for(size_t n = 0; n < scene.nodes.size(); ++n) {
|
nuclear@0
|
206 const Node& nn = *scene.nodes[n].get();
|
nuclear@0
|
207 if(nn.parent_id==0) {
|
nuclear@0
|
208 root->temp_children.push_back(&nn);
|
nuclear@0
|
209 }
|
nuclear@0
|
210
|
nuclear@0
|
211 for(size_t m = n; m < scene.nodes.size(); ++m) {
|
nuclear@0
|
212 const Node& mm = *scene.nodes[m].get();
|
nuclear@0
|
213 if (mm.parent_id == nn.id) {
|
nuclear@0
|
214 nn.temp_children.push_back(&mm);
|
nuclear@0
|
215 }
|
nuclear@0
|
216 }
|
nuclear@0
|
217 }
|
nuclear@0
|
218
|
nuclear@0
|
219 pScene->mRootNode = BuildNodes(*root.get(),scene,pScene);
|
nuclear@0
|
220 }
|
nuclear@0
|
221
|
nuclear@0
|
222 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
223 void ConvertTexture(boost::shared_ptr< Texture > tex, aiMaterial* out, aiTextureType type)
|
nuclear@0
|
224 {
|
nuclear@0
|
225 const aiString path( tex->path );
|
nuclear@0
|
226 out->AddProperty(&path,AI_MATKEY_TEXTURE(type,0));
|
nuclear@0
|
227 out->AddProperty(&tex->transform,1,AI_MATKEY_UVTRANSFORM(type,0));
|
nuclear@0
|
228 }
|
nuclear@0
|
229
|
nuclear@0
|
230 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
231 aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill)
|
nuclear@0
|
232 {
|
nuclear@0
|
233 aiNode* nd = new aiNode();
|
nuclear@0
|
234 nd->mName.Set(root.name);
|
nuclear@0
|
235 nd->mTransformation = root.transform;
|
nuclear@0
|
236
|
nuclear@0
|
237 // Note to everybody believing Voodoo is appropriate here:
|
nuclear@0
|
238 // I know polymorphism, run as fast as you can ;-)
|
nuclear@0
|
239 if (Node::TYPE_MESH == root.type) {
|
nuclear@0
|
240 const Mesh& ndmesh = (const Mesh&)(root);
|
nuclear@0
|
241 if (ndmesh.vertex_positions.size() && ndmesh.texture_coords.size()) {
|
nuclear@0
|
242
|
nuclear@0
|
243 typedef std::pair<unsigned int,Mesh::FaceRefList> Entry;
|
nuclear@0
|
244 for_each(const Entry& reflist,ndmesh.temp_map) {
|
nuclear@0
|
245 { // create mesh
|
nuclear@0
|
246 size_t n = 0;
|
nuclear@0
|
247 for_each(Face* f, reflist.second) {
|
nuclear@0
|
248 n += f->indices.size();
|
nuclear@0
|
249 }
|
nuclear@0
|
250 if (!n) {
|
nuclear@0
|
251 continue;
|
nuclear@0
|
252 }
|
nuclear@0
|
253 aiMesh* outmesh = fill->mMeshes[fill->mNumMeshes++] = new aiMesh();
|
nuclear@0
|
254 ++nd->mNumMeshes;
|
nuclear@0
|
255
|
nuclear@0
|
256 outmesh->mVertices = new aiVector3D[n];
|
nuclear@0
|
257 outmesh->mTextureCoords[0] = new aiVector3D[n];
|
nuclear@0
|
258
|
nuclear@0
|
259 outmesh->mFaces = new aiFace[reflist.second.size()]();
|
nuclear@0
|
260 for_each(Face* f, reflist.second) {
|
nuclear@0
|
261 if (f->indices.empty()) {
|
nuclear@0
|
262 continue;
|
nuclear@0
|
263 }
|
nuclear@0
|
264
|
nuclear@0
|
265 aiFace& fout = outmesh->mFaces[outmesh->mNumFaces++];
|
nuclear@0
|
266 fout.mIndices = new unsigned int[f->indices.size()];
|
nuclear@0
|
267
|
nuclear@0
|
268 for_each(VertexIndex& v, f->indices) {
|
nuclear@0
|
269 if (v.pos_idx >= ndmesh.vertex_positions.size()) {
|
nuclear@0
|
270 ThrowException("Position index out of range");
|
nuclear@0
|
271 }
|
nuclear@0
|
272 if (v.uv_idx >= ndmesh.texture_coords.size()) {
|
nuclear@0
|
273 ThrowException("UV index out of range");
|
nuclear@0
|
274 }
|
nuclear@0
|
275 outmesh->mVertices[outmesh->mNumVertices] = ndmesh.vertex_positions[ v.pos_idx ];
|
nuclear@0
|
276 outmesh->mTextureCoords[0][outmesh->mNumVertices] = aiVector3D(
|
nuclear@0
|
277 ndmesh.texture_coords[ v.uv_idx ].x,
|
nuclear@0
|
278 ndmesh.texture_coords[ v.uv_idx ].y,
|
nuclear@0
|
279 0.f
|
nuclear@0
|
280 );
|
nuclear@0
|
281
|
nuclear@0
|
282 fout.mIndices[fout.mNumIndices++] = outmesh->mNumVertices++;
|
nuclear@0
|
283 }
|
nuclear@0
|
284 }
|
nuclear@0
|
285 outmesh->mMaterialIndex = fill->mNumMaterials;
|
nuclear@0
|
286 }{ // create material
|
nuclear@0
|
287 const Material* min = NULL;
|
nuclear@0
|
288 for_each(const Material& m, scin.materials) {
|
nuclear@0
|
289 if (m.parent_id == ndmesh.id && m.matnum == reflist.first) {
|
nuclear@0
|
290 min = &m;
|
nuclear@0
|
291 break;
|
nuclear@0
|
292 }
|
nuclear@0
|
293 }
|
nuclear@0
|
294 boost::scoped_ptr<const Material> defmat;
|
nuclear@0
|
295 if(!min) {
|
nuclear@0
|
296 DefaultLogger::get()->debug(format()<<"Could not resolve material index "
|
nuclear@0
|
297 <<reflist.first<<" - creating default material for this slot");
|
nuclear@0
|
298
|
nuclear@0
|
299 defmat.reset(min=new Material());
|
nuclear@0
|
300 }
|
nuclear@0
|
301
|
nuclear@0
|
302 aiMaterial* mat = new aiMaterial();
|
nuclear@0
|
303 fill->mMaterials[fill->mNumMaterials++] = mat;
|
nuclear@0
|
304
|
nuclear@0
|
305 const aiString s(format("#mat_")<<fill->mNumMeshes<<"_"<<min->matnum);
|
nuclear@0
|
306 mat->AddProperty(&s,AI_MATKEY_NAME);
|
nuclear@0
|
307
|
nuclear@0
|
308 if(int tmp = ndmesh.draw_flags & Mesh::WIRED ? 1 : 0) {
|
nuclear@0
|
309 mat->AddProperty(&tmp,1,AI_MATKEY_ENABLE_WIREFRAME);
|
nuclear@0
|
310 }
|
nuclear@0
|
311
|
nuclear@0
|
312 { int shader;
|
nuclear@0
|
313 switch(min->shader)
|
nuclear@0
|
314 {
|
nuclear@0
|
315 case Material::FLAT:
|
nuclear@0
|
316 shader = aiShadingMode_Gouraud;
|
nuclear@0
|
317 break;
|
nuclear@0
|
318
|
nuclear@0
|
319 case Material::PHONG:
|
nuclear@0
|
320 shader = aiShadingMode_Phong;
|
nuclear@0
|
321 break;
|
nuclear@0
|
322
|
nuclear@0
|
323 case Material::METAL:
|
nuclear@0
|
324 shader = aiShadingMode_CookTorrance;
|
nuclear@0
|
325 break;
|
nuclear@0
|
326
|
nuclear@0
|
327 default:
|
nuclear@0
|
328 ai_assert(false); // shouldn't be here
|
nuclear@0
|
329 }
|
nuclear@0
|
330 mat->AddProperty(&shader,1,AI_MATKEY_SHADING_MODEL);
|
nuclear@0
|
331 if(shader != aiShadingMode_Gouraud) {
|
nuclear@0
|
332 mat->AddProperty(&min->exp,1,AI_MATKEY_SHININESS);
|
nuclear@0
|
333 }
|
nuclear@0
|
334 }
|
nuclear@0
|
335
|
nuclear@0
|
336 mat->AddProperty(&min->ior,1,AI_MATKEY_REFRACTI);
|
nuclear@0
|
337 mat->AddProperty(&min->rgb,1,AI_MATKEY_COLOR_DIFFUSE);
|
nuclear@0
|
338
|
nuclear@0
|
339 aiColor3D c = aiColor3D(min->rgb)*min->ks;
|
nuclear@0
|
340 mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
|
nuclear@0
|
341
|
nuclear@0
|
342 c = aiColor3D(min->rgb)*min->ka;
|
nuclear@0
|
343 mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT);
|
nuclear@0
|
344
|
nuclear@0
|
345 // convert textures if some exist.
|
nuclear@0
|
346 if(min->tex_color) {
|
nuclear@0
|
347 ConvertTexture(min->tex_color,mat,aiTextureType_DIFFUSE);
|
nuclear@0
|
348 }
|
nuclear@0
|
349 if(min->tex_env) {
|
nuclear@0
|
350 ConvertTexture(min->tex_env ,mat,aiTextureType_UNKNOWN);
|
nuclear@0
|
351 }
|
nuclear@0
|
352 if(min->tex_bump) {
|
nuclear@0
|
353 ConvertTexture(min->tex_bump ,mat,aiTextureType_HEIGHT);
|
nuclear@0
|
354 }
|
nuclear@0
|
355 }
|
nuclear@0
|
356 }
|
nuclear@0
|
357 }
|
nuclear@0
|
358 }
|
nuclear@0
|
359 else if (Node::TYPE_LIGHT == root.type) {
|
nuclear@0
|
360 const Light& ndlight = (const Light&)(root);
|
nuclear@0
|
361 aiLight* outlight = fill->mLights[fill->mNumLights++] = new aiLight();
|
nuclear@0
|
362
|
nuclear@0
|
363 outlight->mName.Set(ndlight.name);
|
nuclear@0
|
364 outlight->mColorDiffuse = outlight->mColorAmbient = outlight->mColorSpecular = ndlight.color;
|
nuclear@0
|
365
|
nuclear@0
|
366 outlight->mAngleOuterCone = AI_DEG_TO_RAD(ndlight.angle);
|
nuclear@0
|
367 outlight->mAngleInnerCone = AI_DEG_TO_RAD(ndlight.inner_angle);
|
nuclear@0
|
368
|
nuclear@0
|
369 // XXX
|
nuclear@0
|
370 outlight->mType = ndlight.ltype==Light::SPOT ? aiLightSource_SPOT : aiLightSource_DIRECTIONAL;
|
nuclear@0
|
371 }
|
nuclear@0
|
372 else if (Node::TYPE_CAMERA == root.type) {
|
nuclear@0
|
373 const Camera& ndcam = (const Camera&)(root);
|
nuclear@0
|
374 aiCamera* outcam = fill->mCameras[fill->mNumCameras++] = new aiCamera();
|
nuclear@0
|
375
|
nuclear@0
|
376 outcam->mName.Set(ndcam.name);
|
nuclear@0
|
377 }
|
nuclear@0
|
378
|
nuclear@0
|
379 // add meshes
|
nuclear@0
|
380 if (nd->mNumMeshes) { // mMeshes must be NULL if count is 0
|
nuclear@0
|
381 nd->mMeshes = new unsigned int[nd->mNumMeshes];
|
nuclear@0
|
382 for(unsigned int i = 0; i < nd->mNumMeshes;++i) {
|
nuclear@0
|
383 nd->mMeshes[i] = fill->mNumMeshes-i-1;
|
nuclear@0
|
384 }
|
nuclear@0
|
385 }
|
nuclear@0
|
386
|
nuclear@0
|
387 // add children recursively
|
nuclear@0
|
388 nd->mChildren = new aiNode*[root.temp_children.size()]();
|
nuclear@0
|
389 for_each(const Node* n, root.temp_children) {
|
nuclear@0
|
390 (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n,scin,fill))->mParent = nd;
|
nuclear@0
|
391 }
|
nuclear@0
|
392
|
nuclear@0
|
393 return nd;
|
nuclear@0
|
394 }
|
nuclear@0
|
395
|
nuclear@0
|
396 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
397 // Read an ASCII file into the given scene data structure
|
nuclear@0
|
398 void COBImporter::ReadAsciiFile(Scene& out, StreamReaderLE* stream)
|
nuclear@0
|
399 {
|
nuclear@0
|
400 ChunkInfo ci;
|
nuclear@0
|
401 for(LineSplitter splitter(*stream);splitter;++splitter) {
|
nuclear@0
|
402
|
nuclear@0
|
403 // add all chunks to be recognized here. /else ../ omitted intentionally.
|
nuclear@0
|
404 if (splitter.match_start("PolH ")) {
|
nuclear@0
|
405 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
406 ReadPolH_Ascii(out,splitter,ci);
|
nuclear@0
|
407 }
|
nuclear@0
|
408 if (splitter.match_start("BitM ")) {
|
nuclear@0
|
409 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
410 ReadBitM_Ascii(out,splitter,ci);
|
nuclear@0
|
411 }
|
nuclear@0
|
412 if (splitter.match_start("Mat1 ")) {
|
nuclear@0
|
413 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
414 ReadMat1_Ascii(out,splitter,ci);
|
nuclear@0
|
415 }
|
nuclear@0
|
416 if (splitter.match_start("Grou ")) {
|
nuclear@0
|
417 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
418 ReadGrou_Ascii(out,splitter,ci);
|
nuclear@0
|
419 }
|
nuclear@0
|
420 if (splitter.match_start("Lght ")) {
|
nuclear@0
|
421 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
422 ReadLght_Ascii(out,splitter,ci);
|
nuclear@0
|
423 }
|
nuclear@0
|
424 if (splitter.match_start("Came ")) {
|
nuclear@0
|
425 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
426 ReadCame_Ascii(out,splitter,ci);
|
nuclear@0
|
427 }
|
nuclear@0
|
428 if (splitter.match_start("Bone ")) {
|
nuclear@0
|
429 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
430 ReadBone_Ascii(out,splitter,ci);
|
nuclear@0
|
431 }
|
nuclear@0
|
432 if (splitter.match_start("Chan ")) {
|
nuclear@0
|
433 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
434 ReadChan_Ascii(out,splitter,ci);
|
nuclear@0
|
435 }
|
nuclear@0
|
436 if (splitter.match_start("Unit ")) {
|
nuclear@0
|
437 ReadChunkInfo_Ascii(ci,splitter);
|
nuclear@0
|
438 ReadUnit_Ascii(out,splitter,ci);
|
nuclear@0
|
439 }
|
nuclear@0
|
440 if (splitter.match_start("END ")) {
|
nuclear@0
|
441 // we don't need this, but I guess there is a reason this
|
nuclear@0
|
442 // chunk has been implemented into COB for.
|
nuclear@0
|
443 return;
|
nuclear@0
|
444 }
|
nuclear@0
|
445 }
|
nuclear@0
|
446 }
|
nuclear@0
|
447
|
nuclear@0
|
448 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
449 void COBImporter::ReadChunkInfo_Ascii(ChunkInfo& out, const LineSplitter& splitter)
|
nuclear@0
|
450 {
|
nuclear@0
|
451 const char* all_tokens[8];
|
nuclear@0
|
452 splitter.get_tokens(all_tokens);
|
nuclear@0
|
453
|
nuclear@0
|
454 out.version = (all_tokens[1][1]-'0')*100+(all_tokens[1][3]-'0')*10+(all_tokens[1][4]-'0');
|
nuclear@0
|
455 out.id = strtoul10(all_tokens[3]);
|
nuclear@0
|
456 out.parent_id = strtoul10(all_tokens[5]);
|
nuclear@0
|
457 out.size = strtol10(all_tokens[7]);
|
nuclear@0
|
458 }
|
nuclear@0
|
459
|
nuclear@0
|
460 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
461 void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo& nfo, const char* name)
|
nuclear@0
|
462 {
|
nuclear@0
|
463 const std::string error = format("Encountered unsupported chunk: ") << name <<
|
nuclear@0
|
464 " [version: "<<nfo.version<<", size: "<<nfo.size<<"]";
|
nuclear@0
|
465
|
nuclear@0
|
466 // we can recover if the chunk size was specified.
|
nuclear@0
|
467 if(nfo.size != static_cast<unsigned int>(-1)) {
|
nuclear@0
|
468 DefaultLogger::get()->error(error);
|
nuclear@0
|
469
|
nuclear@0
|
470 // (HACK) - our current position in the stream is the beginning of the
|
nuclear@0
|
471 // head line of the next chunk. That's fine, but the caller is going
|
nuclear@0
|
472 // to call ++ on `splitter`, which we need to swallow to avoid
|
nuclear@0
|
473 // missing the next line.
|
nuclear@0
|
474 splitter.get_stream().IncPtr(nfo.size);
|
nuclear@0
|
475 splitter.swallow_next_increment();
|
nuclear@0
|
476 }
|
nuclear@0
|
477 else ThrowException(error);
|
nuclear@0
|
478 }
|
nuclear@0
|
479
|
nuclear@0
|
480 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
481 void COBImporter::LogWarn_Ascii(const LineSplitter& splitter, const format& message) {
|
nuclear@0
|
482 LogWarn_Ascii(message << " [at line "<< splitter.get_index()<<"]");
|
nuclear@0
|
483 }
|
nuclear@0
|
484
|
nuclear@0
|
485 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
486 void COBImporter::LogError_Ascii(const LineSplitter& splitter, const format& message) {
|
nuclear@0
|
487 LogError_Ascii(message << " [at line "<< splitter.get_index()<<"]");
|
nuclear@0
|
488 }
|
nuclear@0
|
489
|
nuclear@0
|
490 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
491 void COBImporter::LogInfo_Ascii(const LineSplitter& splitter, const format& message) {
|
nuclear@0
|
492 LogInfo_Ascii(message << " [at line "<< splitter.get_index()<<"]");
|
nuclear@0
|
493 }
|
nuclear@0
|
494
|
nuclear@0
|
495 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
496 void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message) {
|
nuclear@0
|
497 LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]");
|
nuclear@0
|
498 }
|
nuclear@0
|
499
|
nuclear@0
|
500 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
501 void COBImporter::LogWarn_Ascii(const Formatter::format& message) {
|
nuclear@0
|
502 DefaultLogger::get()->warn(std::string("COB: ")+=message);
|
nuclear@0
|
503 }
|
nuclear@0
|
504
|
nuclear@0
|
505 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
506 void COBImporter::LogError_Ascii(const Formatter::format& message) {
|
nuclear@0
|
507 DefaultLogger::get()->error(std::string("COB: ")+=message);
|
nuclear@0
|
508 }
|
nuclear@0
|
509
|
nuclear@0
|
510 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
511 void COBImporter::LogInfo_Ascii(const Formatter::format& message) {
|
nuclear@0
|
512 DefaultLogger::get()->info(std::string("COB: ")+=message);
|
nuclear@0
|
513 }
|
nuclear@0
|
514
|
nuclear@0
|
515 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
516 void COBImporter::LogDebug_Ascii(const Formatter::format& message) {
|
nuclear@0
|
517 DefaultLogger::get()->debug(std::string("COB: ")+=message);
|
nuclear@0
|
518 }
|
nuclear@0
|
519
|
nuclear@0
|
520 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
521 void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& /*nfo*/)
|
nuclear@0
|
522 {
|
nuclear@0
|
523 for(;splitter;++splitter) {
|
nuclear@0
|
524 if (splitter.match_start("Name")) {
|
nuclear@0
|
525 msh.name = std::string(splitter[1]);
|
nuclear@0
|
526
|
nuclear@0
|
527 // make nice names by merging the dupe count
|
nuclear@0
|
528 std::replace(msh.name.begin(),msh.name.end(),
|
nuclear@0
|
529 ',','_');
|
nuclear@0
|
530 }
|
nuclear@0
|
531 else if (splitter.match_start("Transform")) {
|
nuclear@0
|
532 for(unsigned int y = 0; y < 4 && ++splitter; ++y) {
|
nuclear@0
|
533 const char* s = splitter->c_str();
|
nuclear@0
|
534 for(unsigned int x = 0; x < 4; ++x) {
|
nuclear@0
|
535 SkipSpaces(&s);
|
nuclear@0
|
536 msh.transform[y][x] = fast_atof(&s);
|
nuclear@0
|
537 }
|
nuclear@0
|
538 }
|
nuclear@0
|
539 // we need the transform chunk, so we won't return until we have it.
|
nuclear@0
|
540 return;
|
nuclear@0
|
541 }
|
nuclear@0
|
542 }
|
nuclear@0
|
543 }
|
nuclear@0
|
544
|
nuclear@0
|
545 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
546 template <typename T>
|
nuclear@0
|
547 void COBImporter::ReadFloat3Tuple_Ascii(T& fill, const char** in)
|
nuclear@0
|
548 {
|
nuclear@0
|
549 const char* rgb = *in;
|
nuclear@0
|
550 for(unsigned int i = 0; i < 3; ++i) {
|
nuclear@0
|
551 SkipSpaces(&rgb);
|
nuclear@0
|
552 if (*rgb == ',')++rgb;
|
nuclear@0
|
553 SkipSpaces(&rgb);
|
nuclear@0
|
554
|
nuclear@0
|
555 fill[i] = fast_atof(&rgb);
|
nuclear@0
|
556 }
|
nuclear@0
|
557 *in = rgb;
|
nuclear@0
|
558 }
|
nuclear@0
|
559
|
nuclear@0
|
560 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
561 void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
562 {
|
nuclear@0
|
563 if(nfo.version > 8) {
|
nuclear@0
|
564 return UnsupportedChunk_Ascii(splitter,nfo,"Mat1");
|
nuclear@0
|
565 }
|
nuclear@0
|
566
|
nuclear@0
|
567 ++splitter;
|
nuclear@0
|
568 if (!splitter.match_start("mat# ")) {
|
nuclear@0
|
569 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
570 "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
|
nuclear@0
|
571 return;
|
nuclear@0
|
572 }
|
nuclear@0
|
573
|
nuclear@0
|
574 out.materials.push_back(Material());
|
nuclear@0
|
575 Material& mat = out.materials.back();
|
nuclear@0
|
576 mat = nfo;
|
nuclear@0
|
577
|
nuclear@0
|
578 mat.matnum = strtoul10(splitter[1]);
|
nuclear@0
|
579 ++splitter;
|
nuclear@0
|
580
|
nuclear@0
|
581 if (!splitter.match_start("shader: ")) {
|
nuclear@0
|
582 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
583 "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
|
nuclear@0
|
584 return;
|
nuclear@0
|
585 }
|
nuclear@0
|
586 std::string shader = std::string(splitter[1]);
|
nuclear@0
|
587 shader = shader.substr(0,shader.find_first_of(" \t"));
|
nuclear@0
|
588
|
nuclear@0
|
589 if (shader == "metal") {
|
nuclear@0
|
590 mat.shader = Material::METAL;
|
nuclear@0
|
591 }
|
nuclear@0
|
592 else if (shader == "phong") {
|
nuclear@0
|
593 mat.shader = Material::PHONG;
|
nuclear@0
|
594 }
|
nuclear@0
|
595 else if (shader != "flat") {
|
nuclear@0
|
596 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
597 "Unknown value for `shader` in `Mat1` chunk "<<nfo.id);
|
nuclear@0
|
598 }
|
nuclear@0
|
599
|
nuclear@0
|
600 ++splitter;
|
nuclear@0
|
601 if (!splitter.match_start("rgb ")) {
|
nuclear@0
|
602 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
603 "Expected `rgb` line in `Mat1` chunk "<<nfo.id);
|
nuclear@0
|
604 }
|
nuclear@0
|
605
|
nuclear@0
|
606 const char* rgb = splitter[1];
|
nuclear@0
|
607 ReadFloat3Tuple_Ascii(mat.rgb,&rgb);
|
nuclear@0
|
608
|
nuclear@0
|
609 ++splitter;
|
nuclear@0
|
610 if (!splitter.match_start("alpha ")) {
|
nuclear@0
|
611 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
612 "Expected `alpha` line in `Mat1` chunk "<<nfo.id);
|
nuclear@0
|
613 }
|
nuclear@0
|
614
|
nuclear@0
|
615 const char* tokens[10];
|
nuclear@0
|
616 splitter.get_tokens(tokens);
|
nuclear@0
|
617
|
nuclear@0
|
618 mat.alpha = fast_atof( tokens[1] );
|
nuclear@0
|
619 mat.ka = fast_atof( tokens[3] );
|
nuclear@0
|
620 mat.ks = fast_atof( tokens[5] );
|
nuclear@0
|
621 mat.exp = fast_atof( tokens[7] );
|
nuclear@0
|
622 mat.ior = fast_atof( tokens[9] );
|
nuclear@0
|
623 }
|
nuclear@0
|
624
|
nuclear@0
|
625 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
626 void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
627 {
|
nuclear@0
|
628 if(nfo.version > 1) {
|
nuclear@0
|
629 return UnsupportedChunk_Ascii(splitter,nfo,"Unit");
|
nuclear@0
|
630 }
|
nuclear@0
|
631 ++splitter;
|
nuclear@0
|
632 if (!splitter.match_start("Units ")) {
|
nuclear@0
|
633 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
634 "Expected `Units` line in `Unit` chunk "<<nfo.id);
|
nuclear@0
|
635 return;
|
nuclear@0
|
636 }
|
nuclear@0
|
637
|
nuclear@0
|
638 // parent chunks preceede their childs, so we should have the
|
nuclear@0
|
639 // corresponding chunk already.
|
nuclear@0
|
640 for_each(boost::shared_ptr< Node >& nd, out.nodes) {
|
nuclear@0
|
641 if (nd->id == nfo.parent_id) {
|
nuclear@0
|
642 const unsigned int t=strtoul10(splitter[1]);
|
nuclear@0
|
643
|
nuclear@0
|
644 nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
|
nuclear@0
|
645 LogWarn_Ascii(splitter,format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
|
nuclear@0
|
646 ,1.f):units[t];
|
nuclear@0
|
647 return;
|
nuclear@0
|
648 }
|
nuclear@0
|
649 }
|
nuclear@0
|
650 LogWarn_Ascii(splitter,format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
|
nuclear@0
|
651 <<nfo.parent_id<<" which does not exist");
|
nuclear@0
|
652 }
|
nuclear@0
|
653
|
nuclear@0
|
654 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
655 void COBImporter::ReadChan_Ascii(Scene& /*out*/, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
656 {
|
nuclear@0
|
657 if(nfo.version > 8) {
|
nuclear@0
|
658 return UnsupportedChunk_Ascii(splitter,nfo,"Chan");
|
nuclear@0
|
659 }
|
nuclear@0
|
660 }
|
nuclear@0
|
661
|
nuclear@0
|
662 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
663 void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
664 {
|
nuclear@0
|
665 if(nfo.version > 8) {
|
nuclear@0
|
666 return UnsupportedChunk_Ascii(splitter,nfo,"Lght");
|
nuclear@0
|
667 }
|
nuclear@0
|
668
|
nuclear@0
|
669 out.nodes.push_back(boost::shared_ptr<Light>(new Light()));
|
nuclear@0
|
670 Light& msh = (Light&)(*out.nodes.back().get());
|
nuclear@0
|
671 msh = nfo;
|
nuclear@0
|
672
|
nuclear@0
|
673 ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
|
nuclear@0
|
674
|
nuclear@0
|
675 if (splitter.match_start("Infinite ")) {
|
nuclear@0
|
676 msh.ltype = Light::INFINITE;
|
nuclear@0
|
677 }
|
nuclear@0
|
678 else if (splitter.match_start("Local ")) {
|
nuclear@0
|
679 msh.ltype = Light::LOCAL;
|
nuclear@0
|
680 }
|
nuclear@0
|
681 else if (splitter.match_start("Spot ")) {
|
nuclear@0
|
682 msh.ltype = Light::SPOT;
|
nuclear@0
|
683 }
|
nuclear@0
|
684 else {
|
nuclear@0
|
685 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
686 "Unknown kind of light source in `Lght` chunk "<<nfo.id<<" : "<<*splitter);
|
nuclear@0
|
687 msh.ltype = Light::SPOT;
|
nuclear@0
|
688 }
|
nuclear@0
|
689
|
nuclear@0
|
690 ++splitter;
|
nuclear@0
|
691 if (!splitter.match_start("color ")) {
|
nuclear@0
|
692 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
693 "Expected `color` line in `Lght` chunk "<<nfo.id);
|
nuclear@0
|
694 }
|
nuclear@0
|
695
|
nuclear@0
|
696 const char* rgb = splitter[1];
|
nuclear@0
|
697 ReadFloat3Tuple_Ascii(msh.color ,&rgb);
|
nuclear@0
|
698
|
nuclear@0
|
699 SkipSpaces(&rgb);
|
nuclear@0
|
700 if (strncmp(rgb,"cone angle",10)) {
|
nuclear@0
|
701 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
702 "Expected `cone angle` entity in `color` line in `Lght` chunk "<<nfo.id);
|
nuclear@0
|
703 }
|
nuclear@0
|
704 SkipSpaces(rgb+10,&rgb);
|
nuclear@0
|
705 msh.angle = fast_atof(&rgb);
|
nuclear@0
|
706
|
nuclear@0
|
707 SkipSpaces(&rgb);
|
nuclear@0
|
708 if (strncmp(rgb,"inner angle",11)) {
|
nuclear@0
|
709 LogWarn_Ascii(splitter,format()<<
|
nuclear@0
|
710 "Expected `inner angle` entity in `color` line in `Lght` chunk "<<nfo.id);
|
nuclear@0
|
711 }
|
nuclear@0
|
712 SkipSpaces(rgb+11,&rgb);
|
nuclear@0
|
713 msh.inner_angle = fast_atof(&rgb);
|
nuclear@0
|
714
|
nuclear@0
|
715 // skip the rest for we can't handle this kind of physically-based lighting information.
|
nuclear@0
|
716 }
|
nuclear@0
|
717
|
nuclear@0
|
718 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
719 void COBImporter::ReadCame_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
720 {
|
nuclear@0
|
721 if(nfo.version > 2) {
|
nuclear@0
|
722 return UnsupportedChunk_Ascii(splitter,nfo,"Came");
|
nuclear@0
|
723 }
|
nuclear@0
|
724
|
nuclear@0
|
725 out.nodes.push_back(boost::shared_ptr<Camera>(new Camera()));
|
nuclear@0
|
726 Camera& msh = (Camera&)(*out.nodes.back().get());
|
nuclear@0
|
727 msh = nfo;
|
nuclear@0
|
728
|
nuclear@0
|
729 ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
|
nuclear@0
|
730
|
nuclear@0
|
731 // skip the next line, we don't know this differenciation between a
|
nuclear@0
|
732 // standard camera and a panoramic camera.
|
nuclear@0
|
733 ++splitter;
|
nuclear@0
|
734 }
|
nuclear@0
|
735
|
nuclear@0
|
736 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
737 void COBImporter::ReadBone_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
738 {
|
nuclear@0
|
739 if(nfo.version > 5) {
|
nuclear@0
|
740 return UnsupportedChunk_Ascii(splitter,nfo,"Bone");
|
nuclear@0
|
741 }
|
nuclear@0
|
742
|
nuclear@0
|
743 out.nodes.push_back(boost::shared_ptr<Bone>(new Bone()));
|
nuclear@0
|
744 Bone& msh = (Bone&)(*out.nodes.back().get());
|
nuclear@0
|
745 msh = nfo;
|
nuclear@0
|
746
|
nuclear@0
|
747 ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
|
nuclear@0
|
748
|
nuclear@0
|
749 // TODO
|
nuclear@0
|
750 }
|
nuclear@0
|
751
|
nuclear@0
|
752 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
753 void COBImporter::ReadGrou_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
754 {
|
nuclear@0
|
755 if(nfo.version > 1) {
|
nuclear@0
|
756 return UnsupportedChunk_Ascii(splitter,nfo,"Grou");
|
nuclear@0
|
757 }
|
nuclear@0
|
758
|
nuclear@0
|
759 out.nodes.push_back(boost::shared_ptr<Group>(new Group()));
|
nuclear@0
|
760 Group& msh = (Group&)(*out.nodes.back().get());
|
nuclear@0
|
761 msh = nfo;
|
nuclear@0
|
762
|
nuclear@0
|
763 ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
|
nuclear@0
|
764 }
|
nuclear@0
|
765
|
nuclear@0
|
766 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
767 void COBImporter::ReadPolH_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
768 {
|
nuclear@0
|
769 if(nfo.version > 8) {
|
nuclear@0
|
770 return UnsupportedChunk_Ascii(splitter,nfo,"PolH");
|
nuclear@0
|
771 }
|
nuclear@0
|
772
|
nuclear@0
|
773 out.nodes.push_back(boost::shared_ptr<Mesh>(new Mesh()));
|
nuclear@0
|
774 Mesh& msh = (Mesh&)(*out.nodes.back().get());
|
nuclear@0
|
775 msh = nfo;
|
nuclear@0
|
776
|
nuclear@0
|
777 ReadBasicNodeInfo_Ascii(msh,++splitter,nfo);
|
nuclear@0
|
778
|
nuclear@0
|
779 // the chunk has a fixed order of components, but some are not interesting of us so
|
nuclear@0
|
780 // we're just looking for keywords in arbitrary order. The end of the chunk is
|
nuclear@0
|
781 // either the last `Face` or the `DrawFlags` attribute, depending on the format ver.
|
nuclear@0
|
782 for(;splitter;++splitter) {
|
nuclear@0
|
783 if (splitter.match_start("World Vertices")) {
|
nuclear@0
|
784 const unsigned int cnt = strtoul10(splitter[2]);
|
nuclear@0
|
785 msh.vertex_positions.resize(cnt);
|
nuclear@0
|
786
|
nuclear@0
|
787 for(unsigned int cur = 0;cur < cnt && ++splitter;++cur) {
|
nuclear@0
|
788 const char* s = splitter->c_str();
|
nuclear@0
|
789
|
nuclear@0
|
790 aiVector3D& v = msh.vertex_positions[cur];
|
nuclear@0
|
791
|
nuclear@0
|
792 SkipSpaces(&s);
|
nuclear@0
|
793 v.x = fast_atof(&s);
|
nuclear@0
|
794 SkipSpaces(&s);
|
nuclear@0
|
795 v.y = fast_atof(&s);
|
nuclear@0
|
796 SkipSpaces(&s);
|
nuclear@0
|
797 v.z = fast_atof(&s);
|
nuclear@0
|
798 }
|
nuclear@0
|
799 }
|
nuclear@0
|
800 else if (splitter.match_start("Texture Vertices")) {
|
nuclear@0
|
801 const unsigned int cnt = strtoul10(splitter[2]);
|
nuclear@0
|
802 msh.texture_coords.resize(cnt);
|
nuclear@0
|
803
|
nuclear@0
|
804 for(unsigned int cur = 0;cur < cnt && ++splitter;++cur) {
|
nuclear@0
|
805 const char* s = splitter->c_str();
|
nuclear@0
|
806
|
nuclear@0
|
807 aiVector2D& v = msh.texture_coords[cur];
|
nuclear@0
|
808
|
nuclear@0
|
809 SkipSpaces(&s);
|
nuclear@0
|
810 v.x = fast_atof(&s);
|
nuclear@0
|
811 SkipSpaces(&s);
|
nuclear@0
|
812 v.y = fast_atof(&s);
|
nuclear@0
|
813 }
|
nuclear@0
|
814 }
|
nuclear@0
|
815 else if (splitter.match_start("Faces")) {
|
nuclear@0
|
816 const unsigned int cnt = strtoul10(splitter[1]);
|
nuclear@0
|
817 msh.faces.reserve(cnt);
|
nuclear@0
|
818
|
nuclear@0
|
819 for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) {
|
nuclear@0
|
820 if (splitter.match_start("Hole")) {
|
nuclear@0
|
821 LogWarn_Ascii(splitter,"Skipping unsupported `Hole` line");
|
nuclear@0
|
822 continue;
|
nuclear@0
|
823 }
|
nuclear@0
|
824
|
nuclear@0
|
825 if (!splitter.match_start("Face")) {
|
nuclear@0
|
826 ThrowException("Expected Face line");
|
nuclear@0
|
827 }
|
nuclear@0
|
828
|
nuclear@0
|
829 msh.faces.push_back(Face());
|
nuclear@0
|
830 Face& face = msh.faces.back();
|
nuclear@0
|
831
|
nuclear@0
|
832 face.indices.resize(strtoul10(splitter[2]));
|
nuclear@0
|
833 face.flags = strtoul10(splitter[4]);
|
nuclear@0
|
834 face.material = strtoul10(splitter[6]);
|
nuclear@0
|
835
|
nuclear@0
|
836 const char* s = (++splitter)->c_str();
|
nuclear@0
|
837 for(size_t i = 0; i < face.indices.size(); ++i) {
|
nuclear@0
|
838 if(!SkipSpaces(&s)) {
|
nuclear@0
|
839 ThrowException("Expected EOL token in Face entry");
|
nuclear@0
|
840 }
|
nuclear@0
|
841 if ('<' != *s++) {
|
nuclear@0
|
842 ThrowException("Expected < token in Face entry");
|
nuclear@0
|
843 }
|
nuclear@0
|
844 face.indices[i].pos_idx = strtoul10(s,&s);
|
nuclear@0
|
845 if (',' != *s++) {
|
nuclear@0
|
846 ThrowException("Expected , token in Face entry");
|
nuclear@0
|
847 }
|
nuclear@0
|
848 face.indices[i].uv_idx = strtoul10(s,&s);
|
nuclear@0
|
849 if ('>' != *s++) {
|
nuclear@0
|
850 ThrowException("Expected < token in Face entry");
|
nuclear@0
|
851 }
|
nuclear@0
|
852 }
|
nuclear@0
|
853 }
|
nuclear@0
|
854 if (nfo.version <= 4) {
|
nuclear@0
|
855 break;
|
nuclear@0
|
856 }
|
nuclear@0
|
857 }
|
nuclear@0
|
858 else if (splitter.match_start("DrawFlags")) {
|
nuclear@0
|
859 msh.draw_flags = strtoul10(splitter[1]);
|
nuclear@0
|
860 break;
|
nuclear@0
|
861 }
|
nuclear@0
|
862 }
|
nuclear@0
|
863 }
|
nuclear@0
|
864
|
nuclear@0
|
865 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
866 void COBImporter::ReadBitM_Ascii(Scene& /*out*/, LineSplitter& splitter, const ChunkInfo& nfo)
|
nuclear@0
|
867 {
|
nuclear@0
|
868 if(nfo.version > 1) {
|
nuclear@0
|
869 return UnsupportedChunk_Ascii(splitter,nfo,"BitM");
|
nuclear@0
|
870 }
|
nuclear@0
|
871 /*
|
nuclear@0
|
872 "\nThumbNailHdrSize %ld"
|
nuclear@0
|
873 "\nThumbHeader: %02hx 02hx %02hx "
|
nuclear@0
|
874 "\nColorBufSize %ld"
|
nuclear@0
|
875 "\nColorBufZipSize %ld"
|
nuclear@0
|
876 "\nZippedThumbnail: %02hx 02hx %02hx "
|
nuclear@0
|
877 */
|
nuclear@0
|
878
|
nuclear@0
|
879 const unsigned int head = strtoul10((++splitter)[1]);
|
nuclear@0
|
880 if (head != sizeof(Bitmap::BitmapHeader)) {
|
nuclear@0
|
881 LogWarn_Ascii(splitter,"Unexpected ThumbNailHdrSize, skipping this chunk");
|
nuclear@0
|
882 return;
|
nuclear@0
|
883 }
|
nuclear@0
|
884
|
nuclear@0
|
885 /*union {
|
nuclear@0
|
886 Bitmap::BitmapHeader data;
|
nuclear@0
|
887 char opaq[sizeof Bitmap::BitmapHeader()];
|
nuclear@0
|
888 };*/
|
nuclear@0
|
889 // ReadHexOctets(opaq,head,(++splitter)[1]);
|
nuclear@0
|
890 }
|
nuclear@0
|
891
|
nuclear@0
|
892 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
893 void COBImporter::ReadString_Binary(std::string& out, StreamReaderLE& reader)
|
nuclear@0
|
894 {
|
nuclear@0
|
895 out.resize( reader.GetI2());
|
nuclear@0
|
896 for_each(char& c,out) {
|
nuclear@0
|
897 c = reader.GetI1();
|
nuclear@0
|
898 }
|
nuclear@0
|
899 }
|
nuclear@0
|
900
|
nuclear@0
|
901 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
902 void COBImporter::ReadBasicNodeInfo_Binary(Node& msh, StreamReaderLE& reader, const ChunkInfo& /*nfo*/)
|
nuclear@0
|
903 {
|
nuclear@0
|
904 const unsigned int dupes = reader.GetI2();
|
nuclear@0
|
905 ReadString_Binary(msh.name,reader);
|
nuclear@0
|
906
|
nuclear@0
|
907 msh.name = format(msh.name)<<'_'<<dupes;
|
nuclear@0
|
908
|
nuclear@0
|
909 // skip local axes for the moment
|
nuclear@0
|
910 reader.IncPtr(48);
|
nuclear@0
|
911
|
nuclear@0
|
912 msh.transform = aiMatrix4x4();
|
nuclear@0
|
913 for(unsigned int y = 0; y < 3; ++y) {
|
nuclear@0
|
914 for(unsigned int x =0; x < 4; ++x) {
|
nuclear@0
|
915 msh.transform[y][x] = reader.GetF4();
|
nuclear@0
|
916 }
|
nuclear@0
|
917 }
|
nuclear@0
|
918 }
|
nuclear@0
|
919
|
nuclear@0
|
920 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
921 void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkInfo& nfo, const char* name)
|
nuclear@0
|
922 {
|
nuclear@0
|
923 const std::string error = format("Encountered unsupported chunk: ") << name <<
|
nuclear@0
|
924 " [version: "<<nfo.version<<", size: "<<nfo.size<<"]";
|
nuclear@0
|
925
|
nuclear@0
|
926 // we can recover if the chunk size was specified.
|
nuclear@0
|
927 if(nfo.size != static_cast<unsigned int>(-1)) {
|
nuclear@0
|
928 DefaultLogger::get()->error(error);
|
nuclear@0
|
929 reader.IncPtr(nfo.size);
|
nuclear@0
|
930 }
|
nuclear@0
|
931 else ThrowException(error);
|
nuclear@0
|
932 }
|
nuclear@0
|
933
|
nuclear@0
|
934 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
935 // tiny utility guard to aid me at staying within chunk boundaries.
|
nuclear@0
|
936 class chunk_guard {
|
nuclear@0
|
937
|
nuclear@0
|
938 public:
|
nuclear@0
|
939
|
nuclear@0
|
940 chunk_guard(const COB::ChunkInfo& nfo, StreamReaderLE& reader)
|
nuclear@0
|
941 : nfo(nfo)
|
nuclear@0
|
942 , reader(reader)
|
nuclear@0
|
943 , cur(reader.GetCurrentPos())
|
nuclear@0
|
944 {
|
nuclear@0
|
945 }
|
nuclear@0
|
946
|
nuclear@0
|
947 ~chunk_guard() {
|
nuclear@0
|
948 // don't do anything if the size is not given
|
nuclear@0
|
949 if(nfo.size != static_cast<unsigned int>(-1)) {
|
nuclear@0
|
950 reader.IncPtr(static_cast<int>(nfo.size)-reader.GetCurrentPos()+cur);
|
nuclear@0
|
951 }
|
nuclear@0
|
952 }
|
nuclear@0
|
953
|
nuclear@0
|
954 private:
|
nuclear@0
|
955
|
nuclear@0
|
956 const COB::ChunkInfo& nfo;
|
nuclear@0
|
957 StreamReaderLE& reader;
|
nuclear@0
|
958 long cur;
|
nuclear@0
|
959 };
|
nuclear@0
|
960
|
nuclear@0
|
961 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
962 void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader)
|
nuclear@0
|
963 {
|
nuclear@0
|
964 while(1) {
|
nuclear@0
|
965 std::string type;
|
nuclear@0
|
966 type += reader -> GetI1()
|
nuclear@0
|
967 ,type += reader -> GetI1()
|
nuclear@0
|
968 ,type += reader -> GetI1()
|
nuclear@0
|
969 ,type += reader -> GetI1()
|
nuclear@0
|
970 ;
|
nuclear@0
|
971
|
nuclear@0
|
972 ChunkInfo nfo;
|
nuclear@0
|
973 nfo.version = reader -> GetI2()*10;
|
nuclear@0
|
974 nfo.version += reader -> GetI2();
|
nuclear@0
|
975
|
nuclear@0
|
976 nfo.id = reader->GetI4();
|
nuclear@0
|
977 nfo.parent_id = reader->GetI4();
|
nuclear@0
|
978 nfo.size = reader->GetI4();
|
nuclear@0
|
979
|
nuclear@0
|
980 if (type == "PolH") {
|
nuclear@0
|
981 ReadPolH_Binary(out,*reader,nfo);
|
nuclear@0
|
982 }
|
nuclear@0
|
983 else if (type == "BitM") {
|
nuclear@0
|
984 ReadBitM_Binary(out,*reader,nfo);
|
nuclear@0
|
985 }
|
nuclear@0
|
986 else if (type == "Grou") {
|
nuclear@0
|
987 ReadGrou_Binary(out,*reader,nfo);
|
nuclear@0
|
988 }
|
nuclear@0
|
989 else if (type == "Lght") {
|
nuclear@0
|
990 ReadLght_Binary(out,*reader,nfo);
|
nuclear@0
|
991 }
|
nuclear@0
|
992 else if (type == "Came") {
|
nuclear@0
|
993 ReadCame_Binary(out,*reader,nfo);
|
nuclear@0
|
994 }
|
nuclear@0
|
995 else if (type == "Mat1") {
|
nuclear@0
|
996 ReadMat1_Binary(out,*reader,nfo);
|
nuclear@0
|
997 }
|
nuclear@0
|
998 /* else if (type == "Bone") {
|
nuclear@0
|
999 ReadBone_Binary(out,*reader,nfo);
|
nuclear@0
|
1000 }
|
nuclear@0
|
1001 else if (type == "Chan") {
|
nuclear@0
|
1002 ReadChan_Binary(out,*reader,nfo);
|
nuclear@0
|
1003 }*/
|
nuclear@0
|
1004 else if (type == "Unit") {
|
nuclear@0
|
1005 ReadUnit_Binary(out,*reader,nfo);
|
nuclear@0
|
1006 }
|
nuclear@0
|
1007 else if (type == "OLay") {
|
nuclear@0
|
1008 // ignore layer index silently.
|
nuclear@0
|
1009 if(nfo.size != static_cast<unsigned int>(-1) ) {
|
nuclear@0
|
1010 reader->IncPtr(nfo.size);
|
nuclear@0
|
1011 }
|
nuclear@0
|
1012 else return UnsupportedChunk_Binary(*reader,nfo,type.c_str());
|
nuclear@0
|
1013 }
|
nuclear@0
|
1014 else if (type == "END ") {
|
nuclear@0
|
1015 return;
|
nuclear@0
|
1016 }
|
nuclear@0
|
1017 else UnsupportedChunk_Binary(*reader,nfo,type.c_str());
|
nuclear@0
|
1018 }
|
nuclear@0
|
1019 }
|
nuclear@0
|
1020
|
nuclear@0
|
1021 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1022 void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
|
nuclear@0
|
1023 {
|
nuclear@0
|
1024 if(nfo.version > 8) {
|
nuclear@0
|
1025 return UnsupportedChunk_Binary(reader,nfo,"PolH");
|
nuclear@0
|
1026 }
|
nuclear@0
|
1027 const chunk_guard cn(nfo,reader);
|
nuclear@0
|
1028
|
nuclear@0
|
1029 out.nodes.push_back(boost::shared_ptr<Mesh>(new Mesh()));
|
nuclear@0
|
1030 Mesh& msh = (Mesh&)(*out.nodes.back().get());
|
nuclear@0
|
1031 msh = nfo;
|
nuclear@0
|
1032
|
nuclear@0
|
1033 ReadBasicNodeInfo_Binary(msh,reader,nfo);
|
nuclear@0
|
1034
|
nuclear@0
|
1035 msh.vertex_positions.resize(reader.GetI4());
|
nuclear@0
|
1036 for_each(aiVector3D& v,msh.vertex_positions) {
|
nuclear@0
|
1037 v.x = reader.GetF4();
|
nuclear@0
|
1038 v.y = reader.GetF4();
|
nuclear@0
|
1039 v.z = reader.GetF4();
|
nuclear@0
|
1040 }
|
nuclear@0
|
1041
|
nuclear@0
|
1042 msh.texture_coords.resize(reader.GetI4());
|
nuclear@0
|
1043 for_each(aiVector2D& v,msh.texture_coords) {
|
nuclear@0
|
1044 v.x = reader.GetF4();
|
nuclear@0
|
1045 v.y = reader.GetF4();
|
nuclear@0
|
1046 }
|
nuclear@0
|
1047
|
nuclear@0
|
1048 const size_t numf = reader.GetI4();
|
nuclear@0
|
1049 msh.faces.reserve(numf);
|
nuclear@0
|
1050 for(size_t i = 0; i < numf; ++i) {
|
nuclear@0
|
1051 // XXX backface culling flag is 0x10 in flags
|
nuclear@0
|
1052
|
nuclear@0
|
1053 // hole?
|
nuclear@0
|
1054 bool hole;
|
nuclear@0
|
1055 if ((hole = (reader.GetI1() & 0x08) != 0)) {
|
nuclear@0
|
1056 // XXX Basically this should just work fine - then triangulator
|
nuclear@0
|
1057 // should output properly triangulated data even for polygons
|
nuclear@0
|
1058 // with holes. Test data specific to COB is needed to confirm it.
|
nuclear@0
|
1059 if (msh.faces.empty()) {
|
nuclear@0
|
1060 ThrowException(format("A hole is the first entity in the `PolH` chunk with id ") << nfo.id);
|
nuclear@0
|
1061 }
|
nuclear@0
|
1062 }
|
nuclear@0
|
1063 else msh.faces.push_back(Face());
|
nuclear@0
|
1064 Face& f = msh.faces.back();
|
nuclear@0
|
1065
|
nuclear@0
|
1066 const size_t num = reader.GetI2();
|
nuclear@0
|
1067 f.indices.reserve(f.indices.size() + num);
|
nuclear@0
|
1068
|
nuclear@0
|
1069 if(!hole) {
|
nuclear@0
|
1070 f.material = reader.GetI2();
|
nuclear@0
|
1071 f.flags = 0;
|
nuclear@0
|
1072 }
|
nuclear@0
|
1073
|
nuclear@0
|
1074 for(size_t x = 0; x < num; ++x) {
|
nuclear@0
|
1075 f.indices.push_back(VertexIndex());
|
nuclear@0
|
1076
|
nuclear@0
|
1077 VertexIndex& v = f.indices.back();
|
nuclear@0
|
1078 v.pos_idx = reader.GetI4();
|
nuclear@0
|
1079 v.uv_idx = reader.GetI4();
|
nuclear@0
|
1080 }
|
nuclear@0
|
1081
|
nuclear@0
|
1082 if(hole) {
|
nuclear@0
|
1083 std::reverse(f.indices.rbegin(),f.indices.rbegin()+num);
|
nuclear@0
|
1084 }
|
nuclear@0
|
1085 }
|
nuclear@0
|
1086 if (nfo.version>4) {
|
nuclear@0
|
1087 msh.draw_flags = reader.GetI4();
|
nuclear@0
|
1088 }
|
nuclear@0
|
1089 nfo.version>5 && nfo.version<8 ? reader.GetI4() : 0;
|
nuclear@0
|
1090 }
|
nuclear@0
|
1091
|
nuclear@0
|
1092 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1093 void COBImporter::ReadBitM_Binary(COB::Scene& /*out*/, StreamReaderLE& reader, const ChunkInfo& nfo)
|
nuclear@0
|
1094 {
|
nuclear@0
|
1095 if(nfo.version > 1) {
|
nuclear@0
|
1096 return UnsupportedChunk_Binary(reader,nfo,"BitM");
|
nuclear@0
|
1097 }
|
nuclear@0
|
1098
|
nuclear@0
|
1099 const chunk_guard cn(nfo,reader);
|
nuclear@0
|
1100
|
nuclear@0
|
1101 const uint32_t len = reader.GetI4();
|
nuclear@0
|
1102 reader.IncPtr(len);
|
nuclear@0
|
1103
|
nuclear@0
|
1104 reader.GetI4();
|
nuclear@0
|
1105 reader.IncPtr(reader.GetI4());
|
nuclear@0
|
1106 }
|
nuclear@0
|
1107
|
nuclear@0
|
1108 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1109 void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
|
nuclear@0
|
1110 {
|
nuclear@0
|
1111 if(nfo.version > 8) {
|
nuclear@0
|
1112 return UnsupportedChunk_Binary(reader,nfo,"Mat1");
|
nuclear@0
|
1113 }
|
nuclear@0
|
1114
|
nuclear@0
|
1115 const chunk_guard cn(nfo,reader);
|
nuclear@0
|
1116
|
nuclear@0
|
1117 out.materials.push_back(Material());
|
nuclear@0
|
1118 Material& mat = out.materials.back();
|
nuclear@0
|
1119 mat = nfo;
|
nuclear@0
|
1120
|
nuclear@0
|
1121 mat.matnum = reader.GetI2();
|
nuclear@0
|
1122 switch(reader.GetI1()) {
|
nuclear@0
|
1123 case 'f':
|
nuclear@0
|
1124 mat.type = Material::FLAT;
|
nuclear@0
|
1125 break;
|
nuclear@0
|
1126 case 'p':
|
nuclear@0
|
1127 mat.type = Material::PHONG;
|
nuclear@0
|
1128 break;
|
nuclear@0
|
1129 case 'm':
|
nuclear@0
|
1130 mat.type = Material::METAL;
|
nuclear@0
|
1131 break;
|
nuclear@0
|
1132 default:
|
nuclear@0
|
1133 LogError_Ascii(format("Unrecognized shader type in `Mat1` chunk with id ")<<nfo.id);
|
nuclear@0
|
1134 mat.type = Material::FLAT;
|
nuclear@0
|
1135 }
|
nuclear@0
|
1136
|
nuclear@0
|
1137 switch(reader.GetI1()) {
|
nuclear@0
|
1138 case 'f':
|
nuclear@0
|
1139 mat.autofacet = Material::FACETED;
|
nuclear@0
|
1140 break;
|
nuclear@0
|
1141 case 'a':
|
nuclear@0
|
1142 mat.autofacet = Material::AUTOFACETED;
|
nuclear@0
|
1143 break;
|
nuclear@0
|
1144 case 's':
|
nuclear@0
|
1145 mat.autofacet = Material::SMOOTH;
|
nuclear@0
|
1146 break;
|
nuclear@0
|
1147 default:
|
nuclear@0
|
1148 LogError_Ascii(format("Unrecognized faceting mode in `Mat1` chunk with id ")<<nfo.id);
|
nuclear@0
|
1149 mat.autofacet = Material::FACETED;
|
nuclear@0
|
1150 }
|
nuclear@0
|
1151 mat.autofacet_angle = static_cast<float>(reader.GetI1());
|
nuclear@0
|
1152
|
nuclear@0
|
1153 mat.rgb.r = reader.GetF4();
|
nuclear@0
|
1154 mat.rgb.g = reader.GetF4();
|
nuclear@0
|
1155 mat.rgb.b = reader.GetF4();
|
nuclear@0
|
1156
|
nuclear@0
|
1157 mat.alpha = reader.GetF4();
|
nuclear@0
|
1158 mat.ka = reader.GetF4();
|
nuclear@0
|
1159 mat.ks = reader.GetF4();
|
nuclear@0
|
1160 mat.exp = reader.GetF4();
|
nuclear@0
|
1161 mat.ior = reader.GetF4();
|
nuclear@0
|
1162
|
nuclear@0
|
1163 char id[2];
|
nuclear@0
|
1164 id[0] = reader.GetI1(),id[1] = reader.GetI1();
|
nuclear@0
|
1165
|
nuclear@0
|
1166 if (id[0] == 'e' && id[1] == ':') {
|
nuclear@0
|
1167 mat.tex_env.reset(new Texture());
|
nuclear@0
|
1168
|
nuclear@0
|
1169 reader.GetI1();
|
nuclear@0
|
1170 ReadString_Binary(mat.tex_env->path,reader);
|
nuclear@0
|
1171
|
nuclear@0
|
1172 // advance to next texture-id
|
nuclear@0
|
1173 id[0] = reader.GetI1(),id[1] = reader.GetI1();
|
nuclear@0
|
1174 }
|
nuclear@0
|
1175
|
nuclear@0
|
1176 if (id[0] == 't' && id[1] == ':') {
|
nuclear@0
|
1177 mat.tex_color.reset(new Texture());
|
nuclear@0
|
1178
|
nuclear@0
|
1179 reader.GetI1();
|
nuclear@0
|
1180 ReadString_Binary(mat.tex_color->path,reader);
|
nuclear@0
|
1181
|
nuclear@0
|
1182 mat.tex_color->transform.mTranslation.x = reader.GetF4();
|
nuclear@0
|
1183 mat.tex_color->transform.mTranslation.y = reader.GetF4();
|
nuclear@0
|
1184
|
nuclear@0
|
1185 mat.tex_color->transform.mScaling.x = reader.GetF4();
|
nuclear@0
|
1186 mat.tex_color->transform.mScaling.y = reader.GetF4();
|
nuclear@0
|
1187
|
nuclear@0
|
1188 // advance to next texture-id
|
nuclear@0
|
1189 id[0] = reader.GetI1(),id[1] = reader.GetI1();
|
nuclear@0
|
1190 }
|
nuclear@0
|
1191
|
nuclear@0
|
1192 if (id[0] == 'b' && id[1] == ':') {
|
nuclear@0
|
1193 mat.tex_bump.reset(new Texture());
|
nuclear@0
|
1194
|
nuclear@0
|
1195 reader.GetI1();
|
nuclear@0
|
1196 ReadString_Binary(mat.tex_bump->path,reader);
|
nuclear@0
|
1197
|
nuclear@0
|
1198 mat.tex_bump->transform.mTranslation.x = reader.GetF4();
|
nuclear@0
|
1199 mat.tex_bump->transform.mTranslation.y = reader.GetF4();
|
nuclear@0
|
1200
|
nuclear@0
|
1201 mat.tex_bump->transform.mScaling.x = reader.GetF4();
|
nuclear@0
|
1202 mat.tex_bump->transform.mScaling.y = reader.GetF4();
|
nuclear@0
|
1203
|
nuclear@0
|
1204 // skip amplitude for I don't know its purpose.
|
nuclear@0
|
1205 reader.GetF4();
|
nuclear@0
|
1206 }
|
nuclear@0
|
1207 reader.IncPtr(-2);
|
nuclear@0
|
1208 }
|
nuclear@0
|
1209
|
nuclear@0
|
1210 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1211 void COBImporter::ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
|
nuclear@0
|
1212 {
|
nuclear@0
|
1213 if(nfo.version > 2) {
|
nuclear@0
|
1214 return UnsupportedChunk_Binary(reader,nfo,"Came");
|
nuclear@0
|
1215 }
|
nuclear@0
|
1216
|
nuclear@0
|
1217 const chunk_guard cn(nfo,reader);
|
nuclear@0
|
1218
|
nuclear@0
|
1219 out.nodes.push_back(boost::shared_ptr<Camera>(new Camera()));
|
nuclear@0
|
1220 Camera& msh = (Camera&)(*out.nodes.back().get());
|
nuclear@0
|
1221 msh = nfo;
|
nuclear@0
|
1222
|
nuclear@0
|
1223 ReadBasicNodeInfo_Binary(msh,reader,nfo);
|
nuclear@0
|
1224
|
nuclear@0
|
1225 // the rest is not interesting for us, so we skip over it.
|
nuclear@0
|
1226 if(nfo.version > 1) {
|
nuclear@0
|
1227 if (reader.GetI2()==512) {
|
nuclear@0
|
1228 reader.IncPtr(42);
|
nuclear@0
|
1229 }
|
nuclear@0
|
1230 }
|
nuclear@0
|
1231 }
|
nuclear@0
|
1232
|
nuclear@0
|
1233 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1234 void COBImporter::ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
|
nuclear@0
|
1235 {
|
nuclear@0
|
1236 if(nfo.version > 2) {
|
nuclear@0
|
1237 return UnsupportedChunk_Binary(reader,nfo,"Lght");
|
nuclear@0
|
1238 }
|
nuclear@0
|
1239
|
nuclear@0
|
1240 const chunk_guard cn(nfo,reader);
|
nuclear@0
|
1241
|
nuclear@0
|
1242 out.nodes.push_back(boost::shared_ptr<Light>(new Light()));
|
nuclear@0
|
1243 Light& msh = (Light&)(*out.nodes.back().get());
|
nuclear@0
|
1244 msh = nfo;
|
nuclear@0
|
1245
|
nuclear@0
|
1246 ReadBasicNodeInfo_Binary(msh,reader,nfo);
|
nuclear@0
|
1247 }
|
nuclear@0
|
1248
|
nuclear@0
|
1249 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1250 void COBImporter::ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
|
nuclear@0
|
1251 {
|
nuclear@0
|
1252 if(nfo.version > 2) {
|
nuclear@0
|
1253 return UnsupportedChunk_Binary(reader,nfo,"Grou");
|
nuclear@0
|
1254 }
|
nuclear@0
|
1255
|
nuclear@0
|
1256 const chunk_guard cn(nfo,reader);
|
nuclear@0
|
1257
|
nuclear@0
|
1258 out.nodes.push_back(boost::shared_ptr<Group>(new Group()));
|
nuclear@0
|
1259 Group& msh = (Group&)(*out.nodes.back().get());
|
nuclear@0
|
1260 msh = nfo;
|
nuclear@0
|
1261
|
nuclear@0
|
1262 ReadBasicNodeInfo_Binary(msh,reader,nfo);
|
nuclear@0
|
1263 }
|
nuclear@0
|
1264
|
nuclear@0
|
1265 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
1266 void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo)
|
nuclear@0
|
1267 {
|
nuclear@0
|
1268 if(nfo.version > 1) {
|
nuclear@0
|
1269 return UnsupportedChunk_Binary(reader,nfo,"Unit");
|
nuclear@0
|
1270 }
|
nuclear@0
|
1271
|
nuclear@0
|
1272 const chunk_guard cn(nfo,reader);
|
nuclear@0
|
1273
|
nuclear@0
|
1274 // parent chunks preceede their childs, so we should have the
|
nuclear@0
|
1275 // corresponding chunk already.
|
nuclear@0
|
1276 for_each(boost::shared_ptr< Node >& nd, out.nodes) {
|
nuclear@0
|
1277 if (nd->id == nfo.parent_id) {
|
nuclear@0
|
1278 const unsigned int t=reader.GetI2();
|
nuclear@0
|
1279 nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
|
nuclear@0
|
1280 LogWarn_Ascii(format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
|
nuclear@0
|
1281 ,1.f):units[t];
|
nuclear@0
|
1282
|
nuclear@0
|
1283 return;
|
nuclear@0
|
1284 }
|
nuclear@0
|
1285 }
|
nuclear@0
|
1286 LogWarn_Ascii(format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
|
nuclear@0
|
1287 <<nfo.parent_id<<" which does not exist");
|
nuclear@0
|
1288 }
|
nuclear@0
|
1289
|
nuclear@0
|
1290
|
nuclear@0
|
1291 #endif
|