vrshoot

annotate libs/assimp/NDOLoader.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
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