ACLoader.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (ASSIMP)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2008, ASSIMP Development Team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the ASSIMP team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the ASSIMP Development Team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file Implementation of the AC3D importer class */
  35. #include "AssimpPCH.h"
  36. #ifndef AI_BUILD_NO_AC_IMPORTER
  37. // internal headers
  38. #include "ACLoader.h"
  39. #include "ParsingUtils.h"
  40. #include "fast_atof.h"
  41. using namespace Assimp;
  42. // ------------------------------------------------------------------------------------------------
  43. // skip to the next token
  44. #define AI_AC_SKIP_TO_NEXT_TOKEN() \
  45. if (!SkipSpaces(&buffer)) \
  46. { \
  47. DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \
  48. continue; \
  49. }
  50. // ------------------------------------------------------------------------------------------------
  51. // read a string (may be enclosed in double quotation marks). buffer must point to "
  52. #define AI_AC_GET_STRING(out) \
  53. ++buffer; \
  54. const char* sz = buffer; \
  55. while ('\"' != *buffer) \
  56. { \
  57. if (IsLineEnd( *buffer )) \
  58. { \
  59. DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \
  60. out = "ERROR"; \
  61. break; \
  62. } \
  63. ++buffer; \
  64. } \
  65. if (IsLineEnd( *buffer ))continue; \
  66. out = std::string(sz,(unsigned int)(buffer-sz)); \
  67. ++buffer;
  68. // ------------------------------------------------------------------------------------------------
  69. // read 1 to n floats prefixed with an optional predefined identifier
  70. #define AI_AC_CHECKED_LOAD_FLOAT_ARRAY(name,name_length,num,out) \
  71. AI_AC_SKIP_TO_NEXT_TOKEN(); \
  72. if (name_length) \
  73. { \
  74. if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \
  75. { \
  76. DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \
  77. continue; \
  78. } \
  79. buffer += name_length+1; \
  80. } \
  81. for (unsigned int i = 0; i < num;++i) \
  82. { \
  83. AI_AC_SKIP_TO_NEXT_TOKEN(); \
  84. buffer = fast_atof_move(buffer,((float*)out)[i]); \
  85. }
  86. // ------------------------------------------------------------------------------------------------
  87. // Constructor to be privately used by Importer
  88. AC3DImporter::AC3DImporter()
  89. {
  90. }
  91. // ------------------------------------------------------------------------------------------------
  92. // Destructor, private as well
  93. AC3DImporter::~AC3DImporter()
  94. {
  95. }
  96. // ------------------------------------------------------------------------------------------------
  97. // Returns whether the class can handle the format of the given file.
  98. bool AC3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
  99. {
  100. // simple check of file extension is enough for the moment
  101. std::string::size_type pos = pFile.find_last_of('.');
  102. // no file extension - can't read
  103. if( pos == std::string::npos)return false;
  104. std::string extension = pFile.substr( pos);
  105. for( std::string::iterator it = extension.begin(); it != extension.end(); ++it)
  106. *it = tolower( *it);
  107. if( extension == ".ac" || extension == "ac")
  108. return true;
  109. return false;
  110. }
  111. // ------------------------------------------------------------------------------------------------
  112. // Get a pointer to the next line from the file
  113. bool AC3DImporter::GetNextLine( )
  114. {
  115. SkipLine(&buffer);
  116. return SkipSpaces(&buffer);
  117. }
  118. // ------------------------------------------------------------------------------------------------
  119. // Parse an object section in an AC file
  120. void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
  121. {
  122. if (!TokenMatch(buffer,"OBJECT",6))
  123. return;
  124. SkipSpaces(&buffer);
  125. ++mNumMeshes;
  126. objects.push_back(Object());
  127. Object& obj = objects.back();
  128. aiLight* light = NULL;
  129. if (!ASSIMP_stricmp(buffer,"light"))
  130. {
  131. // This is a light source. Add it to the list
  132. mLights->push_back(light = new aiLight());
  133. // Return a point light with no attenuation
  134. light->mType = aiLightSource_POINT;
  135. light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f,1.f,1.f);
  136. light->mAttenuationConstant = 1.f;
  137. // Generate a default name for both the light source and the node
  138. light->mName.length = ::sprintf(light->mName.data,"ACLight_%i",mLights->size()-1);
  139. obj.name = std::string( light->mName.data );
  140. }
  141. while (GetNextLine())
  142. {
  143. if (TokenMatch(buffer,"kids",4))
  144. {
  145. SkipSpaces(&buffer);
  146. unsigned int num = strtol10(buffer,&buffer);
  147. GetNextLine();
  148. if (num)
  149. {
  150. // load the children of this object recursively
  151. obj.children.reserve(num);
  152. for (unsigned int i = 0; i < num; ++i)
  153. LoadObjectSection(obj.children);
  154. }
  155. return;
  156. }
  157. else if (TokenMatch(buffer,"name",4))
  158. {
  159. SkipSpaces(&buffer);
  160. AI_AC_GET_STRING(obj.name);
  161. // If this is a light source, we'll also need to store
  162. // the name of the node in it.
  163. if (light)
  164. {
  165. light->mName.Set(obj.name);
  166. }
  167. }
  168. else if (TokenMatch(buffer,"texture",7))
  169. {
  170. SkipSpaces(&buffer);
  171. AI_AC_GET_STRING(obj.texture);
  172. }
  173. else if (TokenMatch(buffer,"texrep",6))
  174. {
  175. SkipSpaces(&buffer);
  176. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texRepeat);
  177. }
  178. else if (TokenMatch(buffer,"rot",3))
  179. {
  180. SkipSpaces(&buffer);
  181. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,9,&obj.rotation);
  182. }
  183. else if (TokenMatch(buffer,"loc",3))
  184. {
  185. SkipSpaces(&buffer);
  186. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&obj.translation);
  187. }
  188. else if (TokenMatch(buffer,"numvert",7))
  189. {
  190. SkipSpaces(&buffer);
  191. unsigned int t = strtol10(buffer,&buffer);
  192. obj.vertices.reserve(t);
  193. for (unsigned int i = 0; i < t;++i)
  194. {
  195. if (!GetNextLine())
  196. {
  197. DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet");
  198. break;
  199. }
  200. else if (!IsNumeric(*buffer))
  201. {
  202. DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet");
  203. --buffer; // make sure the line is processed a second time
  204. break;
  205. }
  206. obj.vertices.push_back(aiVector3D());
  207. aiVector3D& v = obj.vertices.back();
  208. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x);
  209. }
  210. }
  211. else if (TokenMatch(buffer,"numsurf",7))
  212. {
  213. SkipSpaces(&buffer);
  214. bool Q3DWorkAround = false;
  215. const unsigned int t = strtol10(buffer,&buffer);
  216. obj.surfaces.reserve(t);
  217. for (unsigned int i = 0; i < t;++i)
  218. {
  219. GetNextLine();
  220. if (!TokenMatch(buffer,"SURF",4))
  221. {
  222. // FIX: this can occur for some files - Quick 3D for
  223. // example writes no surf chunks
  224. if (!Q3DWorkAround)
  225. {
  226. DefaultLogger::get()->warn("AC3D: SURF token was expected");
  227. DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled");
  228. }
  229. --buffer; // make sure the line is processed a second time
  230. // break; --- see fix notes above
  231. Q3DWorkAround = true;
  232. }
  233. SkipSpaces(&buffer);
  234. obj.surfaces.push_back(Surface());
  235. Surface& surf = obj.surfaces.back();
  236. surf.flags = strtol_cppstyle(buffer);
  237. while (1)
  238. {
  239. if(!GetNextLine())
  240. {
  241. DefaultLogger::get()->error("AC3D: Unexpected EOF: surface is incomplete");
  242. break;
  243. }
  244. if (TokenMatch(buffer,"mat",3))
  245. {
  246. SkipSpaces(&buffer);
  247. surf.mat = strtol10(buffer);
  248. }
  249. else if (TokenMatch(buffer,"refs",4))
  250. {
  251. // --- see fix notes above
  252. if (Q3DWorkAround)
  253. {
  254. if (!surf.entries.empty())
  255. {
  256. buffer -= 6;
  257. break;
  258. }
  259. }
  260. SkipSpaces(&buffer);
  261. const unsigned int m = strtol10(buffer);
  262. surf.entries.reserve(m);
  263. obj.numRefs += m;
  264. for (unsigned int k = 0; k < m; ++k)
  265. {
  266. if(!GetNextLine())
  267. {
  268. DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete");
  269. break;
  270. }
  271. surf.entries.push_back(Surface::SurfaceEntry());
  272. Surface::SurfaceEntry& entry = surf.entries.back();
  273. entry.first = strtol10(buffer,&buffer);
  274. SkipSpaces(&buffer);
  275. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&entry.second);
  276. }
  277. }
  278. else
  279. {
  280. --buffer; // make sure the line is processed a second time
  281. break;
  282. }
  283. }
  284. }
  285. }
  286. }
  287. DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected");
  288. }
  289. // ------------------------------------------------------------------------------------------------
  290. // Convert a material from AC3DImporter::Material to aiMaterial
  291. void AC3DImporter::ConvertMaterial(const Object& object,
  292. const Material& matSrc,
  293. MaterialHelper& matDest)
  294. {
  295. aiString s;
  296. if (matSrc.name.length())
  297. {
  298. s.Set(matSrc.name);
  299. matDest.AddProperty(&s,AI_MATKEY_NAME);
  300. }
  301. if (object.texture.length())
  302. {
  303. s.Set(object.texture);
  304. matDest.AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
  305. }
  306. matDest.AddProperty<aiColor3D>(&matSrc.rgb,1, AI_MATKEY_COLOR_DIFFUSE);
  307. matDest.AddProperty<aiColor3D>(&matSrc.amb,1, AI_MATKEY_COLOR_AMBIENT);
  308. matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE);
  309. matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR);
  310. int n;
  311. if (matSrc.shin)
  312. {
  313. n = aiShadingMode_Phong;
  314. matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS);
  315. }
  316. else n = aiShadingMode_Gouraud;
  317. matDest.AddProperty<int>(&n,1,AI_MATKEY_SHADING_MODEL);
  318. float f = 1.f - matSrc.trans;
  319. matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
  320. }
  321. // ------------------------------------------------------------------------------------------------
  322. // Converts the loaded data to the internal verbose representation
  323. aiNode* AC3DImporter::ConvertObjectSection(Object& object,
  324. std::vector<aiMesh*>& meshes,
  325. std::vector<MaterialHelper*>& outMaterials,
  326. const std::vector<Material>& materials)
  327. {
  328. aiNode* node = new aiNode();
  329. if (object.vertices.size())
  330. {
  331. if (!object.surfaces.size() || !object.numRefs)
  332. {
  333. /* " An object with 7 vertices (no surfaces, no materials defined).
  334. This is a good way of getting point data into AC3D.
  335. The Vertex->create convex-surface/object can be used on these
  336. vertices to 'wrap' a 3d shape around them "
  337. (http://www.opencity.info/html/ac3dfileformat.html)
  338. therefore: if no surfaces are defined return point data only
  339. */
  340. DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, "
  341. "a point list is returned");
  342. meshes.push_back(new aiMesh());
  343. aiMesh* mesh = meshes.back();
  344. mesh->mNumFaces = mesh->mNumVertices = (unsigned int)object.vertices.size();
  345. aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
  346. aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
  347. for (unsigned int i = 0; i < mesh->mNumVertices;++i,++faces,++verts)
  348. {
  349. *verts = object.vertices[i];
  350. faces->mNumIndices = 1;
  351. faces->mIndices = new unsigned int[1];
  352. faces->mIndices[0] = i;
  353. }
  354. // use the primary material in this case. this should be the
  355. // default material if all objects of the file contain points
  356. // and no faces.
  357. mesh->mMaterialIndex = 0;
  358. outMaterials.push_back(new MaterialHelper());
  359. ConvertMaterial(object, materials[0], *outMaterials.back());
  360. }
  361. else
  362. {
  363. // need to generate one or more meshes for this object.
  364. // find out how many different materials we have
  365. typedef std::pair< unsigned int, unsigned int > IntPair;
  366. typedef std::vector< IntPair > MatTable;
  367. MatTable needMat(materials.size(),IntPair(0,0));
  368. std::vector<Surface>::iterator it,end = object.surfaces.end();
  369. std::vector<Surface::SurfaceEntry>::iterator it2,end2;
  370. for (it = object.surfaces.begin(); it != end; ++it)
  371. {
  372. register unsigned int idx = (*it).mat;
  373. if (idx >= needMat.size())
  374. {
  375. DefaultLogger::get()->error("AC3D: material index os out of range");
  376. idx = 0;
  377. }
  378. if ((*it).entries.empty())
  379. {
  380. DefaultLogger::get()->warn("AC3D: surface her zero vertex references");
  381. }
  382. // validate all vertex indices to make sure we won't crash here
  383. for (it2 = (*it).entries.begin(),
  384. end2 = (*it).entries.end(); it2 != end2; ++it2)
  385. {
  386. if ((*it2).first >= object.vertices.size())
  387. {
  388. DefaultLogger::get()->warn("AC3D: Invalid vertex reference");
  389. (*it2).first = 0;
  390. }
  391. }
  392. if (!needMat[idx].first)++node->mNumMeshes;
  393. switch ((*it).flags & 0xf)
  394. {
  395. // closed line
  396. case 0x1:
  397. needMat[idx].first += (unsigned int)(*it).entries.size();
  398. needMat[idx].second += (unsigned int)(*it).entries.size()<<1u;
  399. break;
  400. // unclosed line
  401. case 0x2:
  402. needMat[idx].first += (unsigned int)(*it).entries.size()-1;
  403. needMat[idx].second += ((unsigned int)(*it).entries.size()-1)<<1u;
  404. break;
  405. // 0 == polygon, else unknown
  406. default:
  407. if ((*it).flags & 0xf)
  408. {
  409. DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown");
  410. (*it).flags &= ~(0xf);
  411. }
  412. // the number of faces increments by one, the number
  413. // of vertices by surface.numref.
  414. needMat[idx].first++;
  415. needMat[idx].second += (unsigned int)(*it).entries.size();
  416. };
  417. }
  418. unsigned int* pip = node->mMeshes = new unsigned int[node->mNumMeshes];
  419. unsigned int mat = 0;
  420. for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end();
  421. cit != cend; ++cit, ++mat)
  422. {
  423. if (!(*cit).first)continue;
  424. // allocate a new aiMesh object
  425. *pip++ = (unsigned int)meshes.size();
  426. aiMesh* mesh = new aiMesh();
  427. meshes.push_back(mesh);
  428. mesh->mMaterialIndex = (unsigned int)outMaterials.size();
  429. outMaterials.push_back(new MaterialHelper());
  430. ConvertMaterial(object, materials[mat], *outMaterials.back());
  431. // allocate storage for vertices and normals
  432. mesh->mNumFaces = (*cit).first;
  433. aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
  434. mesh->mNumVertices = (*cit).second;
  435. aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
  436. unsigned int cur = 0;
  437. // allocate UV coordinates, but only if the texture name for the
  438. // surface is not empty
  439. aiVector3D* uv = NULL;
  440. if(object.texture.length())
  441. {
  442. uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
  443. mesh->mNumUVComponents[0] = 2;
  444. }
  445. for (it = object.surfaces.begin(); it != end; ++it)
  446. {
  447. if (mat == (*it).mat)
  448. {
  449. const Surface& src = *it;
  450. // closed polygon
  451. unsigned int type = (*it).flags & 0xf;
  452. if (!type)
  453. {
  454. aiFace& face = *faces++;
  455. if((face.mNumIndices = (unsigned int)src.entries.size()))
  456. {
  457. face.mIndices = new unsigned int[face.mNumIndices];
  458. for (unsigned int i = 0; i < face.mNumIndices;++i,++vertices)
  459. {
  460. const Surface::SurfaceEntry& entry = src.entries[i];
  461. face.mIndices[i] = cur++;
  462. // copy vertex positions
  463. *vertices = object.vertices[entry.first];
  464. // copy texture coordinates (apply the UV offset)
  465. if (uv)
  466. {
  467. uv->x = entry.second.x * object.texRepeat.x;
  468. uv->y = entry.second.y * object.texRepeat.y;
  469. ++uv;
  470. }
  471. }
  472. }
  473. }
  474. else
  475. {
  476. it2 = (*it).entries.begin();
  477. // either a closed or an unclosed line
  478. register unsigned int tmp = (unsigned int)(*it).entries.size();
  479. if (0x2 == type)--tmp;
  480. for (unsigned int m = 0; m < tmp;++m)
  481. {
  482. aiFace& face = *faces++;
  483. face.mNumIndices = 2;
  484. face.mIndices = new unsigned int[2];
  485. face.mIndices[0] = cur++;
  486. face.mIndices[1] = cur++;
  487. // copy vertex positions
  488. *vertices++ = object.vertices[(*it2).first];
  489. // copy texture coordinates (apply the UV offset)
  490. if (uv)
  491. {
  492. uv->x = (*it2).second.x * object.texRepeat.x;
  493. uv->y = (*it2).second.y * object.texRepeat.y;
  494. ++uv;
  495. }
  496. if (0x1 == type && tmp-1 == m)
  497. {
  498. // if this is a closed line repeat its beginning now
  499. it2 = (*it).entries.begin();
  500. }
  501. else ++it2;
  502. // second point
  503. *vertices++ = object.vertices[(*it2).first];
  504. if (uv)
  505. {
  506. uv->x = (*it2).second.x * object.texRepeat.x;
  507. uv->y = (*it2).second.y * object.texRepeat.y;
  508. ++uv;
  509. }
  510. }
  511. }
  512. }
  513. }
  514. }
  515. }
  516. }
  517. // add children to the object
  518. if (object.children.size())
  519. {
  520. node->mNumChildren = (unsigned int)object.children.size();
  521. node->mChildren = new aiNode*[node->mNumChildren];
  522. for (unsigned int i = 0; i < node->mNumChildren;++i)
  523. {
  524. node->mChildren[i] = ConvertObjectSection(object.children[i],meshes,outMaterials,materials);
  525. node->mChildren[i]->mParent = node;
  526. }
  527. }
  528. node->mName.Set(object.name);
  529. // setup the local transformation matrix of the object
  530. node->mTransformation = aiMatrix4x4 ( object.rotation );
  531. node->mTransformation.a4 = object.translation.x;
  532. node->mTransformation.b4 = -object.translation.y;
  533. node->mTransformation.c4 = object.translation.z;
  534. return node;
  535. }
  536. // ------------------------------------------------------------------------------------------------
  537. void AC3DImporter::SetupProperties(const Importer* pImp)
  538. {
  539. configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL,1) ? true : false;
  540. }
  541. // ------------------------------------------------------------------------------------------------
  542. // Imports the given file into the given scene structure.
  543. void AC3DImporter::InternReadFile( const std::string& pFile,
  544. aiScene* pScene, IOSystem* pIOHandler)
  545. {
  546. boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
  547. // Check whether we can read from the file
  548. if( file.get() == NULL)
  549. throw new ImportErrorException( "Failed to open AC3D file " + pFile + ".");
  550. const unsigned int fileSize = (unsigned int)file->FileSize();
  551. // allocate storage and copy the contents of the file to a memory buffer
  552. std::vector<char> mBuffer2(fileSize+1);
  553. file->Read(&mBuffer2[0], 1, fileSize);
  554. mBuffer2[fileSize] = '\0';
  555. buffer = &mBuffer2[0];
  556. mNumMeshes = 0;
  557. if (::strncmp(buffer,"AC3D",4))
  558. throw new ImportErrorException("AC3D: No valid AC3D file, magic sequence not found");
  559. // print the file format version to the console
  560. unsigned int version = HexDigitToDecimal( buffer[4] );
  561. char msg[3];
  562. itoa10(msg,3,version);
  563. DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg);
  564. std::vector<Material> materials;
  565. materials.reserve(5);
  566. std::vector<Object> rootObjects;
  567. rootObjects.reserve(5);
  568. std::vector<aiLight*> lights;
  569. mLights = & lights;
  570. while (GetNextLine())
  571. {
  572. if (TokenMatch(buffer,"MATERIAL",8))
  573. {
  574. materials.push_back(Material());
  575. Material& mat = materials.back();
  576. // manually parse the material ... sscanf would use the buldin atof ...
  577. // Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f
  578. AI_AC_SKIP_TO_NEXT_TOKEN();
  579. if ('\"' == *buffer)
  580. {
  581. AI_AC_GET_STRING(mat.name);
  582. AI_AC_SKIP_TO_NEXT_TOKEN();
  583. }
  584. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb);
  585. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb);
  586. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis);
  587. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.spec);
  588. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin);
  589. AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans);
  590. }
  591. LoadObjectSection(rootObjects);
  592. }
  593. if (rootObjects.empty() || !mNumMeshes)
  594. {
  595. throw new ImportErrorException("AC3D: No meshes have been loaded");
  596. }
  597. if (materials.empty())
  598. {
  599. DefaultLogger::get()->warn("AC3D: No material has been found");
  600. materials.push_back(Material());
  601. }
  602. mNumMeshes += (mNumMeshes>>2u) + 1;
  603. std::vector<aiMesh*> meshes;
  604. meshes.reserve(mNumMeshes);
  605. std::vector<MaterialHelper*> omaterials;
  606. materials.reserve(mNumMeshes);
  607. // generate a dummy root if there are multiple objects on the top layer
  608. Object* root;
  609. if (1 == rootObjects.size())
  610. root = &rootObjects[0];
  611. else
  612. {
  613. root = new Object();
  614. }
  615. // now convert the imported stuff to our output data structure
  616. pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials);
  617. if (1 != rootObjects.size())delete root;
  618. if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4))
  619. pScene->mRootNode->mName.Set("<AC3DWorld>");
  620. // build output arrays
  621. if (meshes.empty())
  622. {
  623. throw new ImportErrorException("An unknown error occured during converting");
  624. }
  625. pScene->mNumMeshes = (unsigned int)meshes.size();
  626. pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
  627. ::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
  628. pScene->mNumMaterials = (unsigned int)omaterials.size();
  629. pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
  630. ::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*));
  631. pScene->mNumLights = (unsigned int)lights.size();
  632. if (lights.size())
  633. {
  634. pScene->mLights = new aiLight*[lights.size()];
  635. ::memcpy(pScene->mLights,&lights[0],lights.size()*sizeof(void*));
  636. }
  637. }
  638. #endif //!defined AI_BUILD_NO_AC_IMPORTER