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 RawLoader.cpp
|
nuclear@0
|
43 * @brief Implementation of the RAW importer class
|
nuclear@0
|
44 */
|
nuclear@0
|
45
|
nuclear@0
|
46 #include "AssimpPCH.h"
|
nuclear@0
|
47 #ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
|
nuclear@0
|
48
|
nuclear@0
|
49 // internal headers
|
nuclear@0
|
50 #include "RawLoader.h"
|
nuclear@0
|
51 #include "ParsingUtils.h"
|
nuclear@0
|
52 #include "fast_atof.h"
|
nuclear@0
|
53
|
nuclear@0
|
54 using namespace Assimp;
|
nuclear@0
|
55
|
nuclear@0
|
56 static const aiImporterDesc desc = {
|
nuclear@0
|
57 "Raw Importer",
|
nuclear@0
|
58 "",
|
nuclear@0
|
59 "",
|
nuclear@0
|
60 "",
|
nuclear@0
|
61 aiImporterFlags_SupportTextFlavour,
|
nuclear@0
|
62 0,
|
nuclear@0
|
63 0,
|
nuclear@0
|
64 0,
|
nuclear@0
|
65 0,
|
nuclear@0
|
66 "raw"
|
nuclear@0
|
67 };
|
nuclear@0
|
68
|
nuclear@0
|
69 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
70 // Constructor to be privately used by Importer
|
nuclear@0
|
71 RAWImporter::RAWImporter()
|
nuclear@0
|
72 {}
|
nuclear@0
|
73
|
nuclear@0
|
74 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
75 // Destructor, private as well
|
nuclear@0
|
76 RAWImporter::~RAWImporter()
|
nuclear@0
|
77 {}
|
nuclear@0
|
78
|
nuclear@0
|
79 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
80 // Returns whether the class can handle the format of the given file.
|
nuclear@0
|
81 bool RAWImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
|
nuclear@0
|
82 {
|
nuclear@0
|
83 return SimpleExtensionCheck(pFile,"raw");
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@0
|
86 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
87 const aiImporterDesc* RAWImporter::GetInfo () const
|
nuclear@0
|
88 {
|
nuclear@0
|
89 return &desc;
|
nuclear@0
|
90 }
|
nuclear@0
|
91
|
nuclear@0
|
92 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
93 // Imports the given file into the given scene structure.
|
nuclear@0
|
94 void RAWImporter::InternReadFile( const std::string& pFile,
|
nuclear@0
|
95 aiScene* pScene, IOSystem* pIOHandler)
|
nuclear@0
|
96 {
|
nuclear@0
|
97 boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
|
nuclear@0
|
98
|
nuclear@0
|
99 // Check whether we can read from the file
|
nuclear@0
|
100 if( file.get() == NULL) {
|
nuclear@0
|
101 throw DeadlyImportError( "Failed to open RAW file " + pFile + ".");
|
nuclear@0
|
102 }
|
nuclear@0
|
103
|
nuclear@0
|
104 // allocate storage and copy the contents of the file to a memory buffer
|
nuclear@0
|
105 // (terminate it with zero)
|
nuclear@0
|
106 std::vector<char> mBuffer2;
|
nuclear@0
|
107 TextFileToBuffer(file.get(),mBuffer2);
|
nuclear@0
|
108 const char* buffer = &mBuffer2[0];
|
nuclear@0
|
109
|
nuclear@0
|
110 // list of groups loaded from the file
|
nuclear@0
|
111 std::vector< GroupInformation > outGroups(1,GroupInformation("<default>"));
|
nuclear@0
|
112 std::vector< GroupInformation >::iterator curGroup = outGroups.begin();
|
nuclear@0
|
113
|
nuclear@0
|
114 // now read all lines
|
nuclear@0
|
115 char line[4096];
|
nuclear@0
|
116 while (GetNextLine(buffer,line))
|
nuclear@0
|
117 {
|
nuclear@0
|
118 // if the line starts with a non-numeric identifier, it marks
|
nuclear@0
|
119 // the beginning of a new group
|
nuclear@0
|
120 const char* sz = line;SkipSpaces(&sz);
|
nuclear@0
|
121 if (IsLineEnd(*sz))continue;
|
nuclear@0
|
122 if (!IsNumeric(*sz))
|
nuclear@0
|
123 {
|
nuclear@0
|
124 const char* sz2 = sz;
|
nuclear@0
|
125 while (!IsSpaceOrNewLine(*sz2))++sz2;
|
nuclear@0
|
126 const unsigned int length = (unsigned int)(sz2-sz);
|
nuclear@0
|
127
|
nuclear@0
|
128 // find an existing group with this name
|
nuclear@0
|
129 for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
|
nuclear@0
|
130 it != end;++it)
|
nuclear@0
|
131 {
|
nuclear@0
|
132 if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str()))
|
nuclear@0
|
133 {
|
nuclear@0
|
134 curGroup = it;sz2 = NULL;
|
nuclear@0
|
135 break;
|
nuclear@0
|
136 }
|
nuclear@0
|
137 }
|
nuclear@0
|
138 if (sz2)
|
nuclear@0
|
139 {
|
nuclear@0
|
140 outGroups.push_back(GroupInformation(std::string(sz,length)));
|
nuclear@0
|
141 curGroup = outGroups.end()-1;
|
nuclear@0
|
142 }
|
nuclear@0
|
143 }
|
nuclear@0
|
144 else
|
nuclear@0
|
145 {
|
nuclear@0
|
146 // there can be maximally 12 floats plus an extra texture file name
|
nuclear@0
|
147 float data[12];
|
nuclear@0
|
148 unsigned int num;
|
nuclear@0
|
149 for (num = 0; num < 12;++num)
|
nuclear@0
|
150 {
|
nuclear@0
|
151 if(!SkipSpaces(&sz) || !IsNumeric(*sz))break;
|
nuclear@0
|
152 sz = fast_atoreal_move<float>(sz,data[num]);
|
nuclear@0
|
153 }
|
nuclear@0
|
154 if (num != 12 && num != 9)
|
nuclear@0
|
155 {
|
nuclear@0
|
156 DefaultLogger::get()->error("A line may have either 9 or 12 floats and an optional texture");
|
nuclear@0
|
157 continue;
|
nuclear@0
|
158 }
|
nuclear@0
|
159
|
nuclear@0
|
160 MeshInformation* output = NULL;
|
nuclear@0
|
161
|
nuclear@0
|
162 const char* sz2 = sz;
|
nuclear@0
|
163 unsigned int length;
|
nuclear@0
|
164 if (!IsLineEnd(*sz))
|
nuclear@0
|
165 {
|
nuclear@0
|
166 while (!IsSpaceOrNewLine(*sz2))++sz2;
|
nuclear@0
|
167 length = (unsigned int)(sz2-sz);
|
nuclear@0
|
168 }
|
nuclear@0
|
169 else if (9 == num)
|
nuclear@0
|
170 {
|
nuclear@0
|
171 sz = "%default%";
|
nuclear@0
|
172 length = 9;
|
nuclear@0
|
173 }
|
nuclear@0
|
174 else
|
nuclear@0
|
175 {
|
nuclear@0
|
176 sz = "";
|
nuclear@0
|
177 length = 0;
|
nuclear@0
|
178 }
|
nuclear@0
|
179
|
nuclear@0
|
180 // search in the list of meshes whether we have one with this texture
|
nuclear@0
|
181 for (std::vector< MeshInformation >::iterator it = (*curGroup).meshes.begin(),
|
nuclear@0
|
182 end = (*curGroup).meshes.end(); it != end; ++it)
|
nuclear@0
|
183 {
|
nuclear@0
|
184 if (length == (*it).name.length() && (length ? !::strcmp(sz,(*it).name.c_str()) : true))
|
nuclear@0
|
185 {
|
nuclear@0
|
186 output = &(*it);
|
nuclear@0
|
187 break;
|
nuclear@0
|
188 }
|
nuclear@0
|
189 }
|
nuclear@0
|
190 // if we don't have the mesh, create it
|
nuclear@0
|
191 if (!output)
|
nuclear@0
|
192 {
|
nuclear@0
|
193 (*curGroup).meshes.push_back(MeshInformation(std::string(sz,length)));
|
nuclear@0
|
194 output = &((*curGroup).meshes.back());
|
nuclear@0
|
195 }
|
nuclear@0
|
196 if (12 == num)
|
nuclear@0
|
197 {
|
nuclear@0
|
198 aiColor4D v(data[0],data[1],data[2],1.0f);
|
nuclear@0
|
199 output->colors.push_back(v);
|
nuclear@0
|
200 output->colors.push_back(v);
|
nuclear@0
|
201 output->colors.push_back(v);
|
nuclear@0
|
202
|
nuclear@0
|
203 output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
|
nuclear@0
|
204 output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
|
nuclear@0
|
205 output->vertices.push_back(aiVector3D(data[9],data[10],data[11]));
|
nuclear@0
|
206 }
|
nuclear@0
|
207 else
|
nuclear@0
|
208 {
|
nuclear@0
|
209 output->vertices.push_back(aiVector3D(data[0],data[1],data[2]));
|
nuclear@0
|
210 output->vertices.push_back(aiVector3D(data[3],data[4],data[5]));
|
nuclear@0
|
211 output->vertices.push_back(aiVector3D(data[6],data[7],data[8]));
|
nuclear@0
|
212 }
|
nuclear@0
|
213 }
|
nuclear@0
|
214 }
|
nuclear@0
|
215
|
nuclear@0
|
216 pScene->mRootNode = new aiNode();
|
nuclear@0
|
217 pScene->mRootNode->mName.Set("<RawRoot>");
|
nuclear@0
|
218
|
nuclear@0
|
219 // count the number of valid groups
|
nuclear@0
|
220 // (meshes can't be empty)
|
nuclear@0
|
221 for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
|
nuclear@0
|
222 it != end;++it)
|
nuclear@0
|
223 {
|
nuclear@0
|
224 if (!(*it).meshes.empty())
|
nuclear@0
|
225 {
|
nuclear@0
|
226 ++pScene->mRootNode->mNumChildren;
|
nuclear@0
|
227 pScene->mNumMeshes += (unsigned int)(*it).meshes.size();
|
nuclear@0
|
228 }
|
nuclear@0
|
229 }
|
nuclear@0
|
230
|
nuclear@0
|
231 if (!pScene->mNumMeshes)
|
nuclear@0
|
232 {
|
nuclear@0
|
233 throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty.");
|
nuclear@0
|
234 }
|
nuclear@0
|
235
|
nuclear@0
|
236 pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
nuclear@0
|
237 aiNode** cc;
|
nuclear@0
|
238 if (1 == pScene->mRootNode->mNumChildren)
|
nuclear@0
|
239 {
|
nuclear@0
|
240 cc = &pScene->mRootNode;
|
nuclear@0
|
241 pScene->mRootNode->mNumChildren = 0;
|
nuclear@0
|
242 }
|
nuclear@0
|
243 else cc = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
|
nuclear@0
|
244
|
nuclear@0
|
245 pScene->mNumMaterials = pScene->mNumMeshes;
|
nuclear@0
|
246 aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
|
nuclear@0
|
247
|
nuclear@0
|
248 unsigned int meshIdx = 0;
|
nuclear@0
|
249 for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end();
|
nuclear@0
|
250 it != end;++it)
|
nuclear@0
|
251 {
|
nuclear@0
|
252 if ((*it).meshes.empty())continue;
|
nuclear@0
|
253
|
nuclear@0
|
254 aiNode* node;
|
nuclear@0
|
255 if (pScene->mRootNode->mNumChildren)
|
nuclear@0
|
256 {
|
nuclear@0
|
257 node = *cc = new aiNode();
|
nuclear@0
|
258 node->mParent = pScene->mRootNode;
|
nuclear@0
|
259 }
|
nuclear@0
|
260 else node = *cc;++cc;
|
nuclear@0
|
261 node->mName.Set((*it).name);
|
nuclear@0
|
262
|
nuclear@0
|
263 // add all meshes
|
nuclear@0
|
264 node->mNumMeshes = (unsigned int)(*it).meshes.size();
|
nuclear@0
|
265 unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ];
|
nuclear@0
|
266 for (std::vector< MeshInformation >::iterator it2 = (*it).meshes.begin(),
|
nuclear@0
|
267 end2 = (*it).meshes.end(); it2 != end2; ++it2)
|
nuclear@0
|
268 {
|
nuclear@0
|
269 ai_assert(!(*it2).vertices.empty());
|
nuclear@0
|
270
|
nuclear@0
|
271 // allocate the mesh
|
nuclear@0
|
272 *pi++ = meshIdx;
|
nuclear@0
|
273 aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh();
|
nuclear@0
|
274 mesh->mMaterialIndex = meshIdx++;
|
nuclear@0
|
275
|
nuclear@0
|
276 mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
nuclear@0
|
277
|
nuclear@0
|
278 // allocate storage for the vertex components and copy them
|
nuclear@0
|
279 mesh->mNumVertices = (unsigned int)(*it2).vertices.size();
|
nuclear@0
|
280 mesh->mVertices = new aiVector3D[ mesh->mNumVertices ];
|
nuclear@0
|
281 ::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices);
|
nuclear@0
|
282
|
nuclear@0
|
283 if ((*it2).colors.size())
|
nuclear@0
|
284 {
|
nuclear@0
|
285 ai_assert((*it2).colors.size() == mesh->mNumVertices);
|
nuclear@0
|
286
|
nuclear@0
|
287 mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ];
|
nuclear@0
|
288 ::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices);
|
nuclear@0
|
289 }
|
nuclear@0
|
290
|
nuclear@0
|
291 // generate triangles
|
nuclear@0
|
292 ai_assert(0 == mesh->mNumVertices % 3);
|
nuclear@0
|
293 aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ];
|
nuclear@0
|
294 aiFace* const fcEnd = fc + mesh->mNumFaces;
|
nuclear@0
|
295 unsigned int n = 0;
|
nuclear@0
|
296 while (fc != fcEnd)
|
nuclear@0
|
297 {
|
nuclear@0
|
298 aiFace& f = *fc++;
|
nuclear@0
|
299 f.mIndices = new unsigned int[f.mNumIndices = 3];
|
nuclear@0
|
300 for (unsigned int m = 0; m < 3;++m)
|
nuclear@0
|
301 f.mIndices[m] = n++;
|
nuclear@0
|
302 }
|
nuclear@0
|
303
|
nuclear@0
|
304 // generate a material for the mesh
|
nuclear@0
|
305 aiMaterial* mat = new aiMaterial();
|
nuclear@0
|
306
|
nuclear@0
|
307 aiColor4D clr(1.0f,1.0f,1.0f,1.0f);
|
nuclear@0
|
308 if ("%default%" == (*it2).name) // a gray default material
|
nuclear@0
|
309 {
|
nuclear@0
|
310 clr.r = clr.g = clr.b = 0.6f;
|
nuclear@0
|
311 }
|
nuclear@0
|
312 else if ((*it2).name.length() > 0) // a texture
|
nuclear@0
|
313 {
|
nuclear@0
|
314 aiString s;
|
nuclear@0
|
315 s.Set((*it2).name);
|
nuclear@0
|
316 mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
nuclear@0
|
317 }
|
nuclear@0
|
318 mat->AddProperty<aiColor4D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
|
nuclear@0
|
319 *mats++ = mat;
|
nuclear@0
|
320 }
|
nuclear@0
|
321 }
|
nuclear@0
|
322 }
|
nuclear@0
|
323
|
nuclear@0
|
324 #endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER
|