rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file NDOLoader.cpp
|
nuclear@0
|
43 * Implementation of the NDO importer class.
|
nuclear@0
|
44 */
|
nuclear@0
|
45
|
nuclear@0
|
46 #include "AssimpPCH.h"
|
nuclear@0
|
47 #ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
|
nuclear@0
|
48 #include "NDOLoader.h"
|
nuclear@0
|
49
|
nuclear@0
|
50 using namespace Assimp;
|
nuclear@0
|
51 #define for_each BOOST_FOREACH
|
nuclear@0
|
52
|
nuclear@0
|
53 static const aiImporterDesc desc = {
|
nuclear@0
|
54 "Nendo Mesh Importer",
|
nuclear@0
|
55 "",
|
nuclear@0
|
56 "",
|
nuclear@0
|
57 "http://www.izware.com/nendo/index.htm",
|
nuclear@0
|
58 aiImporterFlags_SupportBinaryFlavour,
|
nuclear@0
|
59 0,
|
nuclear@0
|
60 0,
|
nuclear@0
|
61 0,
|
nuclear@0
|
62 0,
|
nuclear@0
|
63 "ndo"
|
nuclear@0
|
64 };
|
nuclear@0
|
65
|
nuclear@0
|
66 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
67 // Constructor to be privately used by Importer
|
nuclear@0
|
68 NDOImporter::NDOImporter()
|
nuclear@0
|
69 {}
|
nuclear@0
|
70
|
nuclear@0
|
71 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
72 // Destructor, private as well
|
nuclear@0
|
73 NDOImporter::~NDOImporter()
|
nuclear@0
|
74 {}
|
nuclear@0
|
75
|
nuclear@0
|
76 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
77 // Returns whether the class can handle the format of the given file.
|
nuclear@0
|
78 bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
nuclear@0
|
79 {
|
nuclear@0
|
80 // check file extension
|
nuclear@0
|
81 const std::string extension = GetExtension(pFile);
|
nuclear@0
|
82
|
nuclear@0
|
83 if( extension == "ndo")
|
nuclear@0
|
84 return true;
|
nuclear@0
|
85
|
nuclear@0
|
86 if ((checkSig || !extension.length()) && pIOHandler) {
|
nuclear@0
|
87 const char* tokens[] = {"nendo"};
|
nuclear@0
|
88 return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,5);
|
nuclear@0
|
89 }
|
nuclear@0
|
90 return false;
|
nuclear@0
|
91 }
|
nuclear@0
|
92
|
nuclear@0
|
93 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
94 // Build a string of all file extensions supported
|
nuclear@0
|
95 const aiImporterDesc* NDOImporter::GetInfo () const
|
nuclear@0
|
96 {
|
nuclear@0
|
97 return &desc;
|
nuclear@0
|
98 }
|
nuclear@0
|
99
|
nuclear@0
|
100 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
101 // Setup configuration properties for the loader
|
nuclear@0
|
102 void NDOImporter::SetupProperties(const Importer* /*pImp*/)
|
nuclear@0
|
103 {
|
nuclear@0
|
104 // nothing to be done for the moment
|
nuclear@0
|
105 }
|
nuclear@0
|
106
|
nuclear@0
|
107 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
108 // Imports the given file into the given scene structure.
|
nuclear@0
|
109 void NDOImporter::InternReadFile( const std::string& pFile,
|
nuclear@0
|
110 aiScene* pScene, IOSystem* pIOHandler)
|
nuclear@0
|
111 {
|
nuclear@0
|
112 StreamReaderBE reader(pIOHandler->Open( pFile, "rb"));
|
nuclear@0
|
113
|
nuclear@0
|
114 // first 9 bytes are nendo file format ("nendo 1.n")
|
nuclear@0
|
115 const char* head = (const char*)reader.GetPtr();
|
nuclear@0
|
116 reader.IncPtr(9);
|
nuclear@0
|
117
|
nuclear@0
|
118 if (strncmp("nendo ",head,6)) {
|
nuclear@0
|
119 throw DeadlyImportError("Not a Nendo file; magic signature missing");
|
nuclear@0
|
120 }
|
nuclear@0
|
121 // check if this is a supported version. if not, continue, too -- users,
|
nuclear@0
|
122 // please don't complain if it doesn't work then ...
|
nuclear@0
|
123 unsigned int file_format = 12;
|
nuclear@0
|
124 if (!strncmp("1.0",head+6,3)) {
|
nuclear@0
|
125 file_format = 10;
|
nuclear@0
|
126 DefaultLogger::get()->info("NDO file format is 1.0");
|
nuclear@0
|
127 }
|
nuclear@0
|
128 else if (!strncmp("1.1",head+6,3)) {
|
nuclear@0
|
129 file_format = 11;
|
nuclear@0
|
130 DefaultLogger::get()->info("NDO file format is 1.1");
|
nuclear@0
|
131 }
|
nuclear@0
|
132 else if (!strncmp("1.2",head+6,3)) {
|
nuclear@0
|
133 file_format = 12;
|
nuclear@0
|
134 DefaultLogger::get()->info("NDO file format is 1.2");
|
nuclear@0
|
135 }
|
nuclear@0
|
136 else {
|
nuclear@0
|
137 DefaultLogger::get()->warn(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6));
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140 reader.IncPtr(2); /* skip flags */
|
nuclear@0
|
141 if (file_format >= 12) {
|
nuclear@0
|
142 reader.IncPtr(2);
|
nuclear@0
|
143 }
|
nuclear@0
|
144 unsigned int temp = reader.GetU1();
|
nuclear@0
|
145
|
nuclear@0
|
146 std::vector<Object> objects(temp); /* buffer to store all the loaded objects in */
|
nuclear@0
|
147
|
nuclear@0
|
148 // read all objects
|
nuclear@0
|
149 for (unsigned int o = 0; o < objects.size(); ++o) {
|
nuclear@0
|
150
|
nuclear@0
|
151 // if (file_format < 12) {
|
nuclear@0
|
152 if (!reader.GetI1()) {
|
nuclear@0
|
153 continue; /* skip over empty object */
|
nuclear@0
|
154 }
|
nuclear@0
|
155 // reader.GetI2();
|
nuclear@0
|
156 // }
|
nuclear@0
|
157 Object& obj = objects[o];
|
nuclear@0
|
158
|
nuclear@0
|
159 temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
160 head = (const char*)reader.GetPtr();
|
nuclear@0
|
161 reader.IncPtr(temp + 76); /* skip unknown stuff */
|
nuclear@0
|
162
|
nuclear@0
|
163 obj.name = std::string(head, temp);
|
nuclear@0
|
164
|
nuclear@0
|
165 // read edge table
|
nuclear@0
|
166 temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
167 obj.edges.reserve(temp);
|
nuclear@0
|
168 for (unsigned int e = 0; e < temp; ++e) {
|
nuclear@0
|
169
|
nuclear@0
|
170 obj.edges.push_back(Edge());
|
nuclear@0
|
171 Edge& edge = obj.edges.back();
|
nuclear@0
|
172
|
nuclear@0
|
173 for (unsigned int i = 0; i< 8; ++i) {
|
nuclear@0
|
174 edge.edge[i] = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
175 }
|
nuclear@0
|
176 edge.hard = file_format >= 11 ? reader.GetU1() : 0;
|
nuclear@0
|
177 for (unsigned int i = 0; i< 8; ++i) {
|
nuclear@0
|
178 edge.color[i] = reader.GetU1();
|
nuclear@0
|
179 }
|
nuclear@0
|
180 }
|
nuclear@0
|
181
|
nuclear@0
|
182 // read face table
|
nuclear@0
|
183 temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
184 obj.faces.reserve(temp);
|
nuclear@0
|
185 for (unsigned int e = 0; e < temp; ++e) {
|
nuclear@0
|
186
|
nuclear@0
|
187 obj.faces.push_back(Face());
|
nuclear@0
|
188 Face& face = obj.faces.back();
|
nuclear@0
|
189
|
nuclear@0
|
190 face.elem = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
191 }
|
nuclear@0
|
192
|
nuclear@0
|
193 // read vertex table
|
nuclear@0
|
194 temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
195 obj.vertices.reserve(temp);
|
nuclear@0
|
196 for (unsigned int e = 0; e < temp; ++e) {
|
nuclear@0
|
197
|
nuclear@0
|
198 obj.vertices.push_back(Vertex());
|
nuclear@0
|
199 Vertex& v = obj.vertices.back();
|
nuclear@0
|
200
|
nuclear@0
|
201 v.num = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
202 v.val.x = reader.GetF4();
|
nuclear@0
|
203 v.val.y = reader.GetF4();
|
nuclear@0
|
204 v.val.z = reader.GetF4();
|
nuclear@0
|
205 }
|
nuclear@0
|
206
|
nuclear@0
|
207 // read UVs
|
nuclear@0
|
208 temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
209 for (unsigned int e = 0; e < temp; ++e) {
|
nuclear@0
|
210 file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
211 }
|
nuclear@0
|
212
|
nuclear@0
|
213 temp = file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
214 for (unsigned int e = 0; e < temp; ++e) {
|
nuclear@0
|
215 file_format >= 12 ? reader.GetU4() : reader.GetU2();
|
nuclear@0
|
216 }
|
nuclear@0
|
217
|
nuclear@0
|
218 if (reader.GetU1()) {
|
nuclear@0
|
219 const unsigned int x = reader.GetU2(), y = reader.GetU2();
|
nuclear@0
|
220 temp = 0;
|
nuclear@0
|
221 while (temp < x*y) {
|
nuclear@0
|
222 unsigned int repeat = reader.GetU1();
|
nuclear@0
|
223 reader.GetU1();
|
nuclear@0
|
224 reader.GetU1();
|
nuclear@0
|
225 reader.GetU1();
|
nuclear@0
|
226 temp += repeat;
|
nuclear@0
|
227 }
|
nuclear@0
|
228 }
|
nuclear@0
|
229 }
|
nuclear@0
|
230
|
nuclear@0
|
231 // construct a dummy node graph and add all named objects as child nodes
|
nuclear@0
|
232 aiNode* root = pScene->mRootNode = new aiNode("$NDODummyRoot");
|
nuclear@0
|
233 aiNode** cc = root->mChildren = new aiNode* [ root->mNumChildren = static_cast<unsigned int>( objects.size()) ] ();
|
nuclear@0
|
234 pScene->mMeshes = new aiMesh* [ root->mNumChildren] ();
|
nuclear@0
|
235
|
nuclear@0
|
236 std::vector<aiVector3D> vertices;
|
nuclear@0
|
237 std::vector<unsigned int> indices;
|
nuclear@0
|
238
|
nuclear@0
|
239 for_each(const Object& obj,objects) {
|
nuclear@0
|
240 aiNode* nd = *cc++ = new aiNode(obj.name);
|
nuclear@0
|
241 nd->mParent = root;
|
nuclear@0
|
242
|
nuclear@0
|
243 // translated from a python dict() - a vector might be sufficient as well
|
nuclear@0
|
244 typedef std::map<unsigned int, unsigned int> FaceTable;
|
nuclear@0
|
245 FaceTable face_table;
|
nuclear@0
|
246
|
nuclear@0
|
247 unsigned int n = 0;
|
nuclear@0
|
248 for_each(const Edge& edge, obj.edges) {
|
nuclear@0
|
249
|
nuclear@0
|
250 face_table[edge.edge[2]] = n;
|
nuclear@0
|
251 face_table[edge.edge[3]] = n;
|
nuclear@0
|
252
|
nuclear@0
|
253 ++n;
|
nuclear@0
|
254 }
|
nuclear@0
|
255
|
nuclear@0
|
256 aiMesh* mesh = new aiMesh();
|
nuclear@0
|
257 aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces=face_table.size()];
|
nuclear@0
|
258
|
nuclear@0
|
259 vertices.clear();
|
nuclear@0
|
260 vertices.reserve(4 * face_table.size()); // arbitrarily choosen
|
nuclear@0
|
261 for_each(FaceTable::value_type& v, face_table) {
|
nuclear@0
|
262 indices.clear();
|
nuclear@0
|
263
|
nuclear@0
|
264 aiFace& f = *faces++;
|
nuclear@0
|
265
|
nuclear@0
|
266 const unsigned int key = v.first;
|
nuclear@0
|
267 unsigned int cur_edge = v.second;
|
nuclear@0
|
268 while (1) {
|
nuclear@0
|
269 unsigned int next_edge, next_vert;
|
nuclear@0
|
270 if (key == obj.edges[cur_edge].edge[3]) {
|
nuclear@0
|
271 next_edge = obj.edges[cur_edge].edge[5];
|
nuclear@0
|
272 next_vert = obj.edges[cur_edge].edge[1];
|
nuclear@0
|
273 }
|
nuclear@0
|
274 else {
|
nuclear@0
|
275 next_edge = obj.edges[cur_edge].edge[4];
|
nuclear@0
|
276 next_vert = obj.edges[cur_edge].edge[0];
|
nuclear@0
|
277 }
|
nuclear@0
|
278 indices.push_back( vertices.size() );
|
nuclear@0
|
279 vertices.push_back(obj.vertices[ next_vert ].val);
|
nuclear@0
|
280
|
nuclear@0
|
281 cur_edge = next_edge;
|
nuclear@0
|
282 if (cur_edge == v.second) {
|
nuclear@0
|
283 break;
|
nuclear@0
|
284 }
|
nuclear@0
|
285 }
|
nuclear@0
|
286
|
nuclear@0
|
287 f.mIndices = new unsigned int[f.mNumIndices = indices.size()];
|
nuclear@0
|
288 std::copy(indices.begin(),indices.end(),f.mIndices);
|
nuclear@0
|
289 }
|
nuclear@0
|
290
|
nuclear@0
|
291 mesh->mVertices = new aiVector3D[mesh->mNumVertices = vertices.size()];
|
nuclear@0
|
292 std::copy(vertices.begin(),vertices.end(),mesh->mVertices);
|
nuclear@0
|
293
|
nuclear@0
|
294 if (mesh->mNumVertices) {
|
nuclear@0
|
295 pScene->mMeshes[pScene->mNumMeshes] = mesh;
|
nuclear@0
|
296
|
nuclear@0
|
297 (nd->mMeshes = new unsigned int[nd->mNumMeshes=1])[0]=pScene->mNumMeshes++;
|
nuclear@0
|
298 }
|
nuclear@0
|
299 }
|
nuclear@0
|
300 }
|
nuclear@0
|
301
|
nuclear@0
|
302 #endif
|