xoreos  0.0.5
model_nwn.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 /* Based on the binary MDL specs by Torlack.
26  *
27  * Torlack's own site is down, but our docs repository hosts a
28  * a mirror (<https://github.com/xoreos/xoreos-docs>).
29  */
30 
31 #include <cassert>
32 
33 #include <boost/unordered_set.hpp>
34 
35 #include "glm/glm.hpp"
36 
37 #include "src/common/system.h"
38 #include "src/common/error.h"
39 #include "src/common/maths.h"
40 #include "src/common/debug.h"
41 #include "src/common/readstream.h"
42 #include "src/common/strutil.h"
43 #include "src/common/encoding.h"
45 
46 #include "src/aurora/types.h"
47 #include "src/aurora/resman.h"
48 
53 
56 
57 // Disable the "unused variable" warnings while most stuff is still stubbed
59 
61 
62 static const int kNodeFlagHasHeader = 0x00000001;
63 static const int kNodeFlagHasLight = 0x00000002;
64 static const int kNodeFlagHasEmitter = 0x00000004;
65 static const int kNodeFlagHasReference = 0x00000010;
66 static const int kNodeFlagHasMesh = 0x00000020;
67 static const int kNodeFlagHasSkin = 0x00000040;
68 static const int kNodeFlagHasAnim = 0x00000080;
69 static const int kNodeFlagHasDangly = 0x00000100;
70 static const int kNodeFlagHasAABB = 0x00000200;
71 
74 static const uint16 kControllerTypeScale = 36;
75 static const uint16 kControllerTypeColor = 76;
76 static const uint16 kControllerTypeRadius = 88;
79 static const uint16 kControllerTypeMultiplier = 140;
80 static const uint16 kControllerTypeAlphaEnd = 80;
82 static const uint16 kControllerTypeBirthRate = 88;
83 static const uint16 kControllerTypeBounce_Co = 92;
84 static const uint16 kControllerTypeColorEnd = 96;
85 static const uint16 kControllerTypeColorStart = 108;
87 static const uint16 kControllerTypeDrag = 124;
88 static const uint16 kControllerTypeFPS = 128;
89 static const uint16 kControllerTypeFrameEnd = 132;
90 static const uint16 kControllerTypeFrameStart = 136;
91 static const uint16 kControllerTypeGrav = 140;
92 static const uint16 kControllerTypeLifeExp = 144;
93 static const uint16 kControllerTypeMass = 148;
97 static const uint16 kControllerTypeRandVel = 164;
98 static const uint16 kControllerTypeSizeStart = 168;
99 static const uint16 kControllerTypeSizeEnd = 172;
101 static const uint16 kControllerTypeSizeEnd_Y = 180;
102 static const uint16 kControllerTypeSpread = 184;
103 static const uint16 kControllerTypeThreshold = 188;
104 static const uint16 kControllerTypeVelocity = 192;
105 static const uint16 kControllerTypeXSize = 196;
106 static const uint16 kControllerTypeYSize = 200;
111 static const uint16 kControllerTypeDetonate = 228;
112 static const uint16 kControllerTypeAlphaMid = 464;
113 static const uint16 kControllerTypeColorMid = 468;
117 static const uint16 kControllerTypeSizeMid = 484;
118 static const uint16 kControllerTypeSizeMid_Y = 488;
120 static const uint16 kControllerTypeAlpha = 128;
121 
122 namespace Graphics {
123 
124 namespace Aurora {
125 
127  const Common::UString &t) :
128  mdl(0), state(0), texture(t) {
129 
130  mdl = ResMan.getResource(name, ::Aurora::kFileTypeMDL);
131  if (!mdl)
132  throw Common::Exception("No such MDL \"%s\"", name.c_str());
133 
134  mdl->seek(0);
135  isASCII = mdl->readUint32LE() != 0;
136 
137  if (isASCII) {
139 
140  tokenize->addSeparator(' ');
141  tokenize->addChunkEnd('\n');
142  tokenize->addIgnore('\r');
143  } else
144  tokenize = 0;
145 }
146 
148  delete tokenize;
149  delete mdl;
150 
151  clear();
152 }
153 
155  for (std::list<ModelNode *>::iterator n = nodes.begin(); n != nodes.end(); ++n)
156  delete *n;
157  nodes.clear();
158 
159  delete state;
160  state = 0;
161 }
162 
164  ModelNode *&node) const {
165 
166  node = 0;
167 
168  if (name.empty() || (name == "NULL"))
169  return true;
170 
171  for (std::list<ModelNode *>::const_iterator n = nodes.begin();
172  n != nodes.end(); ++n) {
173 
174  if ((*n)->getName() == name) {
175  node = *n;
176  return true;
177  }
178  }
179 
180  return false;
181 }
182 
183 
185  const Common::UString &texture, ModelCache *modelCache) :
186  Model(type) {
187 
188  if (_type == kModelTypeGUIFront) {
189  // NWN GUI objects use 0.01 units / pixel
190  _scale[0] = _scale[1] = 100.0f;
191  _scale[2] = 1.0f;
192  }
193 
194  _fileName = name;
195 
196  ParserContext ctx(name, texture);
197 
198  if (ctx.isASCII)
199  loadASCII(ctx);
200  else
201  loadBinary(ctx);
202 
203  loadSuperModel(modelCache);
204 
205  // These are usually inherited from a supermodel
207 
208  finalize();
209 }
210 
212 }
213 
215  ctx.mdl->seek(4);
216 
217  uint32 sizeModelData = ctx.mdl->readUint32LE();
218  uint32 sizeRawData = ctx.mdl->readUint32LE();
219 
220  ctx.offModelData = 12;
221  ctx.offRawData = ctx.offModelData + sizeModelData;
222 
223  ctx.mdl->skip(8); // Function pointers
224 
226  debugC(kDebugGraphics, 4, "Loading NWN binary model \"%s\": \"%s\"", _fileName.c_str(),
227  _name.c_str());
228  ctx.mdlName = _name;
229 
230  uint32 nodeHeadPointer = ctx.mdl->readUint32LE();
231  uint32 nodeCount = ctx.mdl->readUint32LE();
232 
233  ctx.mdl->skip(24 + 4); // Unknown + Reference count
234 
235  uint8 type = ctx.mdl->readByte();
236 
237  ctx.mdl->skip(3 + 2); // Padding + Unknown
238 
239  uint8 classification = ctx.mdl->readByte();
240  uint8 fogged = ctx.mdl->readByte();
241 
242  ctx.mdl->skip(4); // Unknown
243 
244  uint32 animOffset, animCount;
245  readArrayDef(*ctx.mdl, animOffset, animCount);
246 
247  ctx.mdl->skip(4); // Parent model pointer
248 
249  float boundingMin[3], boundingMax[3];
250 
251  boundingMin[0] = ctx.mdl->readIEEEFloatLE();
252  boundingMin[1] = ctx.mdl->readIEEEFloatLE();
253  boundingMin[2] = ctx.mdl->readIEEEFloatLE();
254 
255  boundingMax[0] = ctx.mdl->readIEEEFloatLE();
256  boundingMax[1] = ctx.mdl->readIEEEFloatLE();
257  boundingMax[2] = ctx.mdl->readIEEEFloatLE();
258 
259  float radius = ctx.mdl->readIEEEFloatLE();
260 
262 
264 
265  newState(ctx);
266 
267  ModelNode_NWN_Binary *rootNode = new ModelNode_NWN_Binary(*this);
268  ctx.nodes.push_back(rootNode);
269 
270  ctx.mdl->seek(ctx.offModelData + nodeHeadPointer);
271  rootNode->load(ctx);
272 
273  addState(ctx);
274 
275  std::vector<uint32> animOffsets;
276  readArray(*ctx.mdl, ctx.offModelData + animOffset, animCount, animOffsets);
277 
278  for (std::vector<uint32>::const_iterator offset = animOffsets.begin(); offset != animOffsets.end(); ++offset) {
279  newState(ctx);
280 
281  readAnimBinary(ctx, ctx.offModelData + *offset);
282 
283  addState(ctx);
284  }
285 }
286 
288  ctx.mdl->seek(0);
289 
290  newState(ctx);
291 
292  while (!ctx.mdl->eos()) {
293  std::vector<Common::UString> line;
294 
295  size_t count = ctx.tokenize->getTokens(*ctx.mdl, line, 3);
296 
297  ctx.tokenize->nextChunk(*ctx.mdl);
298 
299  // Ignore empty lines and comments
300  if ((count == 0) || line[0].empty() || (*line[0].begin() == '#'))
301  continue;
302 
303  line[0].makeLower();
304 
305  if (line[0] == "newmodel") {
306  if (!_name.empty())
307  warning("Model_NWN_ASCII::load(): More than one model definition");
308 
309  debugC(kDebugGraphics, 4, "Loading NWN ASCII model \"%s\": \"%s\"", _fileName.c_str(),
310  _name.c_str());
311 
312  _name = line[1];
313  ctx.mdlName = _name;
314  } else if (line[0] == "setsupermodel") {
315  if (line[1] != _name)
316  warning("Model_NWN_ASCII::load(): setsupermodel: \"%s\" != \"%s\"",
317  line[1].c_str(), _name.c_str());
318 
319  if (!line[2].empty() && (line[2] != "NULL"))
320  _superModelName = line[2];
321 
322  } else if (line[0] == "beginmodelgeom") {
323  if (line[1] != _name)
324  warning("Model_NWN_ASCII::load(): beginmodelgeom: \"%s\" != \"%s\"",
325  line[1].c_str(), _name.c_str());
326  } else if (line[0] == "setanimationscale") {
328  } else if (line[0] == "node") {
329 
330  ModelNode_NWN_ASCII *newNode = new ModelNode_NWN_ASCII(*this);
331  ctx.nodes.push_back(newNode);
332 
333  newNode->load(ctx, line[1], line[2]);
334 
335  } else if (line[0] == "newanim") {
336  ctx.anims.push_back(ctx.mdl->pos());
337  skipAnimASCII(ctx);
338  } else if (line[0] == "donemodel") {
339  break;
340  } else {
341  // warning("Unknown MDL command \"%s\"", line[0].c_str());
342  }
343  }
344 
345  addState(ctx);
346 
347  for (std::vector<uint32>::iterator a = ctx.anims.begin(); a != ctx.anims.end(); ++a) {
348  ctx.mdl->seek(*a);
349  readAnimASCII(ctx);
350  }
351 }
353  ctx.clear();
354 
355  ctx.hasPosition = false;
356  ctx.hasOrientation = false;
357  ctx.state = new State;
358 }
359 
361  bool end = false;
362 
363  while (!ctx.mdl->eos()) {
364  std::vector<Common::UString> line;
365 
366  size_t count = ctx.tokenize->getTokens(*ctx.mdl, line, 1);
367 
368  ctx.tokenize->nextChunk(*ctx.mdl);
369 
370  // Ignore empty lines and comments
371  if ((count == 0) || line[0].empty() || (*line[0].begin() == '#'))
372  continue;
373 
374  line[0].makeLower();
375 
376  if (line[0] == "doneanim") {
377  end = true;
378  break;
379  }
380  }
381 
382  if (!end)
383  throw Common::Exception("anim without doneanim");
384 }
385 
387  // TODO: Model_NWN_ASCII::readAnimASCII
388  // read in the animation name
389  // there should be a list of animations
390  // each with a bunch of animnodes
391  // each animnode targets a model node
392  // and has a list of position, orientation keyframes
393  // (at time t, position, orientation = x)
394 }
395 
397  if (!ctx.state || ctx.nodes.empty()) {
398  ctx.clear();
399  return;
400  }
401 
402  for (std::list<ModelNode *>::iterator n = ctx.nodes.begin();
403  n != ctx.nodes.end(); ++n) {
404 
405  ctx.state->nodeList.push_back(*n);
406  ctx.state->nodeMap.insert(std::make_pair((*n)->getName(), *n));
407 
408  if (!(*n)->getParent())
409  ctx.state->rootNodes.push_back(*n);
410  }
411 
412  _stateList.push_back(ctx.state);
413  _stateMap.insert(std::make_pair(ctx.state->name, ctx.state));
414 
415  if (!_currentState)
416  _currentState = ctx.state;
417 
418  ctx.state = 0;
419 
420  ctx.nodes.clear();
421 }
422 
424  ctx.mdl->seek(offset);
425 
426  ctx.mdl->skip(8); // Function pointers
427 
429 
430  uint32 nodeHeadPointer = ctx.mdl->readUint32LE();
431  uint32 nodeCount = ctx.mdl->readUint32LE();
432 
433  ctx.mdl->skip(24 + 4); // Unknown + Reference count
434 
435  uint8 type = ctx.mdl->readByte();
436 
437  ctx.mdl->skip(3); // Padding
438 
439  float animLength = ctx.mdl->readIEEEFloatLE();
440  float transTime = ctx.mdl->readIEEEFloatLE();
441 
443 
444  uint32 eventOffset, eventCount;
445  readArrayDef(*ctx.mdl, eventOffset, eventCount);
446 
447  // Associated events
448  // TODO: Save in array, then pass to animation class
449  ctx.mdl->seek(ctx.offModelData + eventOffset);
450  for (uint32 i = 0; i < eventCount; i++) {
451  float after = ctx.mdl->readIEEEFloatLE();
452 
454  }
455 
456  ModelNode_NWN_Binary *rootNode = new ModelNode_NWN_Binary(*this);
457  ctx.nodes.push_back(rootNode);
458 
459  ctx.mdl->seek(ctx.offModelData + nodeHeadPointer);
460  rootNode->load(ctx);
461 
462  // We read this in, but what do we do with it??
463  // Ah, we call addState, interesting
464  // Need to look at interaction with placeable states?
465  Animation *anim = new Animation();
466  anim->setName(ctx.state->name);
467  anim->setLength(animLength);
468  anim->setTransTime(transTime);
469  _animationMap.insert(std::make_pair(ctx.state->name, anim));
470  debugC(kDebugGraphics, 4, "Loaded animation \"%s\" in model \"%s\"", ctx.state->name.c_str(), _name.c_str());
471 
472  for (std::list<ModelNode *>::iterator n = ctx.nodes.begin();
473  n != ctx.nodes.end(); ++n) {
474  AnimNode *animnode = new AnimNode(*n);
475  anim->addAnimNode(animnode);
476  }
477 
478 }
479 
481  if (!_superModelName.empty() && _superModelName != "NULL") {
482  bool foundInCache = false;
483 
484  if (modelCache) {
485  ModelCache::iterator super = modelCache->find(_superModelName);
486  if (super != modelCache->end()) {
487  _superModel = super->second;
488 
489  foundInCache = true;
490  }
491  }
492 
493  if (!_superModel)
494  _superModel = new Model_NWN(_superModelName, _type, "", modelCache);
495 
496  if (modelCache && !foundInCache)
497  modelCache->insert(std::make_pair(_superModelName, _superModel));
498  }
499 }
500 
501 struct DefaultAnim {
502  const char *name;
504 };
505 
506 static const DefaultAnim kDefaultAnims[] = {
507  {"pausesh" , 5},
508  {"pausebrd", 5},
509  {"hturnl" , 5},
510  {"hturnr" , 5},
511  {"pause1" , 100},
512  {"pause2" , 100},
513  {"chturnl" , 5},
514  {"chturnr" , 5},
515  {"cpause1" , 100}
516 };
517 
519  for (size_t i = 0; i < ARRAYSIZE(kDefaultAnims); i++) {
520  Animation *anim = getAnimation(kDefaultAnims[i].name);
521  if (!anim)
522  continue;
523 
524  addDefaultAnimation(kDefaultAnims[i].name, kDefaultAnims[i].probability);
525  }
526 }
527 
528 
530 }
531 
533 }
534 
536  size_t pos = ctx.mdl->pos();
537 
538  ctx.mdl->skip(32); // Function pointers, inherit color flag, part number
539 
541 
542  ctx.mdl->seek(pos);
543 
544  return name;
545 }
546 
548  ctx.mdl->skip(24); // Function pointers
549 
550  uint32 inheritColorFlag = ctx.mdl->readUint32LE();
551 
552  _nodeNumber = ctx.mdl->readUint32LE();
553 
555 
556  debugC(kDebugGraphics, 5, "Node \"%s\" in state \"%s\"", _name.c_str(),
557  ctx.state->name.c_str());
558 
559  ctx.mdl->skip(8); // Parent pointers
560 
561  uint32 childrenOffset, childrenCount;
562  Model::readArrayDef(*ctx.mdl, childrenOffset, childrenCount);
563 
564  std::vector<uint32> children;
565  Model::readArray(*ctx.mdl, ctx.offModelData + childrenOffset, childrenCount, children);
566 
567  uint32 controllerKeyOffset, controllerKeyCount;
568  Model::readArrayDef(*ctx.mdl, controllerKeyOffset, controllerKeyCount);
569 
570  uint32 controllerDataOffset, controllerDataCount;
571  Model::readArrayDef(*ctx.mdl, controllerDataOffset, controllerDataCount);
572 
573  std::vector<float> controllerData;
574  Model::readArray(*ctx.mdl, ctx.offModelData + controllerDataOffset,
575  controllerDataCount, controllerData);
576 
577  uint32 flags = ctx.mdl->readUint32LE();
578 
579  if ((flags & 0xFFFFFC00) != 0)
580  throw Common::Exception("Unknown model node flags %08X", flags);
581 
582  if (flags & kNodeFlagHasLight) {
583  // TODO: Light
584  ctx.mdl->skip(0x5C);
585  }
586 
587  if (flags & kNodeFlagHasEmitter) {
588  // TODO: Emitter
589  ctx.mdl->skip(0xD8);
590  }
591 
592  if (flags & kNodeFlagHasReference) {
593  // TODO: Reference
594  ctx.mdl->skip(0x44);
595  }
596 
597  if (flags & kNodeFlagHasMesh) {
598  readMesh(ctx);
599  }
600 
601  if (flags & kNodeFlagHasSkin) {
602  // TODO: Skin
603  ctx.mdl->skip(0x64);
604  }
605 
606  if (flags & kNodeFlagHasAnim) {
607  readAnim(ctx);
608  }
609 
610  if (flags & kNodeFlagHasDangly) {
611  // TODO: Dangly
612  ctx.mdl->skip(0x18);
613  }
614 
615  if (flags & kNodeFlagHasAABB) {
616  // TODO: AABB
617  ctx.mdl->skip(0x4);
618  }
619 
620  readNodeControllers(ctx, ctx.offModelData + controllerKeyOffset,
621  controllerKeyCount, controllerData);
622 
623  // If the node has no own position controller, inherit the position from the root state
624  if (!ctx.hasPosition) {
625  ModelNode *node = _model->getNode(_name);
626  if (node)
627  node->inheritPosition(*this);
628  }
629 
630  if (!ctx.hasOrientation) {
631  ModelNode *node = _model->getNode(_name);
632  if (node)
633  node->inheritOrientation(*this);
634  }
635 
636 
637  for (std::vector<uint32>::const_iterator child = children.begin(); child != children.end(); ++child) {
638  ctx.mdl->seek(ctx.offModelData + *child);
639 
640  ctx.hasPosition = false;
641  ctx.hasOrientation = false;
642 
644  ctx.nodes.push_back(childNode);
645 
646  childNode->setParent(this);
647 
648  checkDuplicateNode(ctx, childNode);
649 
650  childNode->load(ctx);
651  }
652 
653 }
654 
656  // Read the node's name and check if a node with that name already exists
658 
659  ModelNode_NWN_Binary *oldChildNode = 0;
660  for (std::list<ModelNode *>::iterator n = ctx.nodes.begin(); n != ctx.nodes.end(); ++n) {
661  if ((*n)->getName().equalsIgnoreCase(name)) {
662  oldChildNode = dynamic_cast<ModelNode_NWN_Binary *>(*n);
663  break;
664  }
665  }
666 
667  // If there isn't, we're done
668  if (!oldChildNode)
669  return;
670 
671  // If it there, reparent its children, remove it from its parent and delete it
672 
673  warning("Duplicate node \"%s\" in state \"%s\" in model \"%s\"",
674  name.c_str(), ctx.state->name.c_str(), _model->getName().c_str());
675 
676  for (std::list<ModelNode *>::const_iterator c = oldChildNode->getChildren().begin();
677  c != oldChildNode->getChildren().end(); ++c) {
678 
679  (*c)->setParent(newNode);
680  }
681 
682  if (oldChildNode->getParent())
683  oldChildNode->getParent()->getChildren().remove(oldChildNode);
684 
685  ctx.nodes.remove(oldChildNode);
686  delete oldChildNode;
687 }
688 
689 struct Face {
690  float normal[3];
691 
693 
695 };
696 
697 static bool fuzzyEqual(const float *a, const float *b) {
698  return fabs(a[0] - b[0]) < 1E-4 &&
699  fabs(a[1] - b[1]) < 1E-4 &&
700  fabs(a[2] - b[2]) < 1E-4;
701 }
702 
704  ctx.mdl->skip(8); // Function pointers
705 
706  uint32 facesOffset, facesCount;
707  Model::readArrayDef(*ctx.mdl, facesOffset, facesCount);
708 
709  _mesh = new Mesh();
710 
711  float boundingMin[3], boundingMax[3];
712 
713  boundingMin[0] = ctx.mdl->readIEEEFloatLE();
714  boundingMin[1] = ctx.mdl->readIEEEFloatLE();
715  boundingMin[2] = ctx.mdl->readIEEEFloatLE();
716 
717  boundingMax[0] = ctx.mdl->readIEEEFloatLE();
718  boundingMax[1] = ctx.mdl->readIEEEFloatLE();
719  boundingMax[2] = ctx.mdl->readIEEEFloatLE();
720 
721  float radius = ctx.mdl->readIEEEFloatLE();
722 
723  float pointsAverage[3];
724  pointsAverage[0] = ctx.mdl->readIEEEFloatLE();
725  pointsAverage[1] = ctx.mdl->readIEEEFloatLE();
726  pointsAverage[2] = ctx.mdl->readIEEEFloatLE();
727 
728  _mesh->ambient[0] = ctx.mdl->readIEEEFloatLE();
729  _mesh->ambient[1] = ctx.mdl->readIEEEFloatLE();
730  _mesh->ambient[2] = ctx.mdl->readIEEEFloatLE();
731 
732  _mesh->diffuse[0] = ctx.mdl->readIEEEFloatLE();
733  _mesh->diffuse[1] = ctx.mdl->readIEEEFloatLE();
734  _mesh->diffuse[2] = ctx.mdl->readIEEEFloatLE();
735 
736  _mesh->specular[0] = ctx.mdl->readIEEEFloatLE();
737  _mesh->specular[1] = ctx.mdl->readIEEEFloatLE();
738  _mesh->specular[2] = ctx.mdl->readIEEEFloatLE();
739 
741 
742  _mesh->shadow = ctx.mdl->readUint32LE() == 1;
743  _mesh->beaming = ctx.mdl->readUint32LE() == 1;
744  _mesh->render = ctx.mdl->readUint32LE() == 1;
745 
746  _mesh->hasTransparencyHint = true;
747  _mesh->transparencyHint = ctx.mdl->readUint32LE() == 1;
748 
749  ctx.mdl->skip(4); // Unknown
750 
751  std::vector<Common::UString> textures;
752  textures.push_back(Common::readStringFixed(*ctx.mdl, Common::kEncodingASCII, 64));
753  textures.push_back(Common::readStringFixed(*ctx.mdl, Common::kEncodingASCII, 64));
754  textures.push_back(Common::readStringFixed(*ctx.mdl, Common::kEncodingASCII, 64));
755  textures.push_back(Common::readStringFixed(*ctx.mdl, Common::kEncodingASCII, 64));
756 
757  _mesh->tilefade = ctx.mdl->readUint32LE();
758 
759  ctx.mdl->skip(12); // Vertex indices
760  ctx.mdl->skip(12); // Left over faces
761 
762  ctx.mdl->skip(12); // Vertex indices counts
763  ctx.mdl->skip(12); // Vertex indices offsets
764 
765  ctx.mdl->skip(8); // Unknown
766 
767  byte triangleMode = ctx.mdl->readByte(); // 3 - Triangle, 4 - TriStrip
768 
769  ctx.mdl->skip(3 + 4); // Padding + Unknown
770 
771  uint32 vertexOffset = ctx.mdl->readUint32LE();
772  uint16 vertexCount = ctx.mdl->readUint16LE();
773  uint16 textureCount = ctx.mdl->readUint16LE();
774 
775  uint32 textureVertexOffset[4];
776  textureVertexOffset[0] = ctx.mdl->readUint32LE();
777  textureVertexOffset[1] = ctx.mdl->readUint32LE();
778  textureVertexOffset[2] = ctx.mdl->readUint32LE();
779  textureVertexOffset[3] = ctx.mdl->readUint32LE();
780 
781  uint32 normalOffset = ctx.mdl->readUint32LE(); // Vertex normals
782  uint32 colorOffset = ctx.mdl->readUint32LE(); // Vertex RGBA colors
783 
784  uint32 textureAnimOffset[6]; // Texture animation data
785  for (uint32 i = 0; i < 6; i++)
786  textureAnimOffset[i] = ctx.mdl->readUint32LE();
787 
788  bool lightMapped = ctx.mdl->readByte() == 1;
789 
790  _mesh->rotatetexture = ctx.mdl->readByte() == 1;
791 
792  ctx.mdl->skip(2); // Padding
793 
794  ctx.mdl->skip(4); // Normal sum / 2
795 
796  ctx.mdl->skip(4); // Unknown
797 
798  if ((vertexCount == 0) || (facesCount == 0) || (facesOffset == 0))
799  return;
800 
801  if (textureCount > 4) {
802  warning("ModelNode_NWN_Binary::readMesh(): textureCount > 4 (%d)", textureCount);
803  textureCount = 4;
804  }
805 
806  if ((textureCount > 0) && !ctx.texture.empty())
807  textures[0] = ctx.texture;
808 
809  _render = _mesh->render;
810  _mesh->data = new MeshData();
812 
813  textures.resize(textureCount);
814  loadTextures(textures);
815 
816  size_t endPos = ctx.mdl->pos();
817 
818 
819  // Read vertices
820 
821  std::vector<float> vertices;
822  vertices.resize(vertexCount * 3);
823 
824  assert (vertexOffset != 0xFFFFFFFF);
825  ctx.mdl->seek(ctx.offRawData + vertexOffset);
826  for (std::vector<float>::iterator v = vertices.begin(); v != vertices.end(); ++v)
827  *v = ctx.mdl->readIEEEFloatLE();
828 
829  // Read faces
830 
831  std::vector<Face> faces;
832  faces.resize(facesCount);
833 
834  std::vector< std::list<Face *> > vFaces;
835  vFaces.resize(vertexCount);
836 
837  assert (facesOffset != 0xFFFFFFFF);
838  ctx.mdl->seek(ctx.offModelData + facesOffset);
839  for (std::vector<Face>::iterator f = faces.begin(); f != faces.end(); ++f) {
840  f->normal[0] = ctx.mdl->readIEEEFloatLE();
841  f->normal[1] = ctx.mdl->readIEEEFloatLE();
842  f->normal[2] = ctx.mdl->readIEEEFloatLE();
843 
844  ctx.mdl->skip(4); // Plane distance
845 
846  f->smooth = ctx.mdl->readUint32LE();
847 
848  ctx.mdl->skip(3 * 2); // Adjacent face number or -1
849 
850  f->index[0] = ctx.mdl->readUint16LE();
851  f->index[1] = ctx.mdl->readUint16LE();
852  f->index[2] = ctx.mdl->readUint16LE();
853 
854  // Assign this face to all vertices belonging to this face
855  for (int i = 0; i < 3; i++) {
856  assert((size_t)(f->index[i] * 3) < vertices.size());
857 
858  const float *fV = &vertices[f->index[i] * 3];
859 
860  for (uint32 j = 0; j < vertices.size() / 3; j++)
861  if (fuzzyEqual(fV, &vertices[j * 3]))
862  vFaces[j].push_back(&*f);
863  }
864  }
865 
866  // Read texture coordinates
867 
868  std::vector<float> texCoords;
869  texCoords.resize(textureCount * vertexCount * 2);
870 
871  for (uint16 t = 0; t < textureCount; t++) {
872  const bool hasTexture = textureVertexOffset[t] != 0xFFFFFFFF;
873  if (hasTexture)
874  ctx.mdl->seek(ctx.offRawData + textureVertexOffset[t]);
875 
876  float *v = &texCoords[t * vertexCount * 2];
877  for (uint32 i = 0; i < vertexCount; i++) {
878  *v++ = hasTexture ? ctx.mdl->readIEEEFloatLE() : 0.0f;
879  *v++ = hasTexture ? ctx.mdl->readIEEEFloatLE() : 0.0f;
880  }
881  }
882 
883  // Create vertex buffer
884 
885  VertexDecl vertexDecl;
886 
887  vertexDecl.push_back(VertexAttrib(VPOSITION, 3, GL_FLOAT));
888  vertexDecl.push_back(VertexAttrib(VNORMAL , 3, GL_FLOAT));
889  for (uint t = 0; t < textureCount; t++)
890  vertexDecl.push_back(VertexAttrib(VTCOORD + t, 2, GL_FLOAT));
891 
892  _mesh->data->rawMesh->getVertexBuffer()->setVertexDeclInterleave(facesCount * 3, vertexDecl);
893 
894  float *v = reinterpret_cast<float *>(_mesh->data->rawMesh->getVertexBuffer()->getData());
895  for (uint32 i = 0; i < facesCount; i++) {
896  const Face &face = faces[i];
897 
898  for (uint32 j = 0; j < 3; j++) {
899  const uint16 index = face.index[j];
900  assert((size_t)(index * 3) < vertices.size());
901 
902  // Vertices
903  *v++ = vertices[index * 3 + 0];
904  *v++ = vertices[index * 3 + 1];
905  *v++ = vertices[index * 3 + 2];
906 
907  // Normals, smoothed
908  glm::vec3 normal(0.0f, 0.0f, 0.0f);
909  uint32 n = 0;
910 
911  for (std::list<Face *>::const_iterator vF = vFaces[index].begin(); vF != vFaces[index].end(); ++vF) {
912  if (face.smooth != (*vF)->smooth)
913  continue;
914 
915  normal += glm::vec3((*vF)->normal[0], (*vF)->normal[1], (*vF)->normal[2]);
916  n++;
917  }
918 
919  if (n > 0) {
920  normal /= (float) n;
921  normal = glm::normalize(normal);
922  }
923 
924  *v++ = normal[0];
925  *v++ = normal[1];
926  *v++ = normal[2];
927 
928  // Texture coordinates
929  for (uint32 t = 0; t < textureCount; t++) {
930  *v++ = texCoords[t * vertexCount * 2 + index * 2 + 0];
931  *v++ = texCoords[t * vertexCount * 2 + index * 2 + 1];
932  }
933  }
934  }
935 
936  // Create index buffer
937 
938  _mesh->data->rawMesh->getIndexBuffer()->setSize(facesCount * 3, sizeof(uint16), GL_UNSIGNED_SHORT);
939 
940  uint16 *f = reinterpret_cast<uint16 *>(_mesh->data->rawMesh->getIndexBuffer()->getData());
941  for (uint16 i = 0; i < facesCount * 3; i++)
942  *f++ = i;
943 
944  createBound();
945 
946  ctx.mdl->seek(endPos);
947 
948  Common::UString meshName = ctx.mdlName;
949  meshName += ".";
950  if (ctx.state->name.size() != 0) {
951  meshName += ctx.state->name;
952  } else {
953  meshName += "xoreos.default";
954  }
955  meshName += ".";
956  meshName += _name;
957 
958  Graphics::Mesh::Mesh *checkMesh = MeshMan.getMesh(meshName);
959  if (checkMesh) {
960  delete _mesh->data->rawMesh;
961  _mesh->data->rawMesh = checkMesh;
962  } else {
963  _mesh->data->rawMesh->setName(meshName);
964  _mesh->data->rawMesh->init();
965  MeshMan.addMesh(_mesh->data->rawMesh);
966  }
967 
968  if (GfxMan.isRendererExperimental())
969  buildMaterial();
970 }
971 
973  float samplePeriod = ctx.mdl->readIEEEFloatLE();
974 
975  uint32 a0S, a0C;
976  Model::readArrayDef(*ctx.mdl, a0S, a0C);
977 
978  uint32 a1S, a1C;
979  Model::readArrayDef(*ctx.mdl, a1S, a1C);
980 
981  uint32 a2S, a2C;
982  Model::readArrayDef(*ctx.mdl, a2S, a2C);
983 
984  uint32 offAnimVertices = ctx.mdl->readUint32LE();
985  uint32 offAnimTextureVertices = ctx.mdl->readUint32LE();
986 
987  uint32 verticesCount = ctx.mdl->readUint32LE();
988  uint32 textureVerticesCount = ctx.mdl->readUint32LE();
989 }
990 
992  uint32 offset, uint32 count, std::vector<float> &data) {
993 
994  uint32 pos = ctx.mdl->seek(offset);
995 
996  // TODO: readNodeControllers: Implement this properly :P
997 
998  for (uint32 i = 0; i < count; i++) {
999  uint32 type = ctx.mdl->readUint32LE();
1000  uint16 rowCount = ctx.mdl->readUint16LE();
1001  uint16 timeIndex = ctx.mdl->readUint16LE();
1002  uint16 dataIndex = ctx.mdl->readUint16LE();
1003  uint8 columnCount = ctx.mdl->readByte();
1004  ctx.mdl->skip(1);
1005 
1006  if (rowCount == 0xFFFF)
1007  // TODO: Controller row count = 0xFFFF
1008  continue;
1009 
1010  if (type == kControllerTypePosition) {
1011  if (columnCount != 3)
1012  throw Common::Exception("Position controller with %d values", columnCount);
1013  for (int r = 0; r < rowCount; r++) {
1014  PositionKeyFrame p;
1015  p.time = data[timeIndex + r];
1016  p.x = data[dataIndex + (r * columnCount) + 0];
1017  p.y = data[dataIndex + (r * columnCount) + 1];
1018  p.z = data[dataIndex + (r * columnCount) + 2];
1019  _positionFrames.push_back(p);
1020 
1021  // Starting position
1022  if (p.time == 0.0f) {
1023  _position[0] = p.x;
1024  _position[1] = p.y;
1025  _position[2] = p.z;
1026  _positionBuffer[0] = _position[0];
1027  _positionBuffer[1] = _position[1];
1028  _positionBuffer[2] = _position[2];
1029  ctx.hasPosition = true;
1030  }
1031  }
1032 
1033  } else if (type == kControllerTypeOrientation) {
1034  if (columnCount != 4)
1035  throw Common::Exception("Orientation controller with %d values", columnCount);
1036 
1037  for (int r = 0; r < rowCount; r++) {
1039  q.time = data[timeIndex + r];
1040  q.x = data[dataIndex + (r * columnCount) + 0];
1041  q.y = data[dataIndex + (r * columnCount) + 1];
1042  q.z = data[dataIndex + (r * columnCount) + 2];
1043  q.q = data[dataIndex + (r * columnCount) + 3];
1044  _orientationFrames.push_back(q);
1045  // Starting orientation
1046  // TODO: Handle animation orientation correctly
1047  if (data[timeIndex + 0] == 0.0f) {
1048  _orientation[0] = data[dataIndex + 0];
1049  _orientation[1] = data[dataIndex + 1];
1050  _orientation[2] = data[dataIndex + 2];
1051  _orientation[3] = Common::rad2deg(acos(data[dataIndex + 3]) * 2.0);
1056 
1057  ctx.hasOrientation = true;
1058  }
1059  }
1060 
1061  } else if (type == kControllerTypeAlpha) {
1062  if (columnCount != 1)
1063  throw Common::Exception("Alpha controller with %d values", columnCount);
1064 
1065  // Starting alpha
1066  if (data[timeIndex + 0] == 0.0f)
1067  if (data[dataIndex + 0] == 0.0f)
1068  // TODO: Just disabled rendering if alpha == 0.0 for now
1069  _render = false;
1070  }
1071 
1072  }
1073 
1074  ctx.mdl->seek(pos);
1075 }
1076 
1077 
1078 ModelNode_NWN_ASCII::Mesh::Mesh() : vCount(0), tCount(0), faceCount(0) {
1079 }
1080 
1081 
1083 }
1084 
1086 }
1087 
1089  const Common::UString &type, const Common::UString &name) {
1090 
1091  bool end = false;
1092  bool skipNode = false;
1093 
1094  _name = name;
1095 
1096  debugC(kDebugGraphics, 5, "Node \"%s\" in state \"%s\"", _name.c_str(),
1097  ctx.state->name.c_str());
1098 
1099  if ((type == "trimesh") || (type == "danglymesh") || (type == "skin")) {
1100  _mesh = new ModelNode::Mesh();
1101  _mesh->hasTransparencyHint = true;
1102  _mesh->render = true;
1103  if (type == "danglymesh")
1104  _mesh->dangly = new Dangly();
1105  }
1106 
1107  if ((type == "emitter") || (type == "reference") || (type == "aabb")) {
1108  // warning("TODO: Node type %s", type.c_str());
1109  skipNode = true;
1110  }
1111 
1113 
1114  while (!ctx.mdl->eos()) {
1115  std::vector<Common::UString> line;
1116 
1117  size_t count = ctx.tokenize->getTokens(*ctx.mdl, line, 5);
1118 
1119  ctx.tokenize->nextChunk(*ctx.mdl);
1120 
1121  // Ignore empty lines and comments
1122  if ((count == 0) || line[0].empty() || (*line[0].begin() == '#'))
1123  continue;
1124 
1125  line[0].makeLower();
1126 
1127  if (line[0] == "endnode") {
1128  end = true;
1129  break;
1130  } else if (skipNode) {
1131  continue;
1132  } else if (line[0] == "parent") {
1133  ModelNode *parent = 0;
1134 
1135  if (!ctx.findNode(line[1], parent))
1136  warning("ModelNode_NWN_ASCII::load(): Non-existent parent node \"%s\"",
1137  line[1].c_str());
1138 
1139  setParent(parent);
1140 
1141  } else if (line[0] == "position") {
1142  readFloats(line, _position, 3, 1);
1143  } else if (line[0] == "orientation") {
1144  readFloats(line, _orientation, 4, 1);
1145 
1147  } else if (line[0] == "render") {
1148  Common::parseString(line[1], _mesh->render);
1149  } else if (line[0] == "transparencyhint") {
1150  Common::parseString(line[1], _mesh->transparencyHint);
1151  } else if (line[0] == "danglymesh") {
1152  } else if (line[0] == "constraints") {
1153  uint32 n;
1154 
1155  Common::parseString(line[1], n);
1156  readConstraints(ctx, n);
1157  } else if (line[0] == "weights") {
1158  uint32 n;
1159 
1160  Common::parseString(line[1], n);
1161  readWeights(ctx, n);
1162  } else if (line[0] == "bitmap") {
1163  mesh.textures.push_back(line[1]);
1164  } else if (line[0] == "verts") {
1165  Common::parseString(line[1], mesh.vCount);
1166 
1167  readVCoords(ctx, mesh);
1168  } else if (line[0] == "tverts") {
1169  if (mesh.tCount != 0)
1170  warning("ModelNode_NWN_ASCII::load(): Multiple texture coordinates!");
1171 
1172  Common::parseString(line[1], mesh.tCount);
1173 
1174  readTCoords(ctx, mesh);
1175  } else if (line[0] == "faces") {
1176  Common::parseString(line[1], mesh.faceCount);
1177 
1178  readFaces(ctx, mesh);
1179  } else {
1180  // warning("Unknown MDL node command \"%s\"", line[0].c_str());
1181  }
1182  }
1183 
1184  if (!end)
1185  throw Common::Exception("ModelNode_NWN_ASCII::load(): node without endnode");
1186 
1187  if (!mesh.textures.empty() && !ctx.texture.empty())
1188  mesh.textures[0] = ctx.texture;
1189 
1190  processMesh(mesh);
1191 
1192  Common::UString meshName = ctx.mdlName;
1193  meshName += ".";
1194  if (ctx.state->name.size() != 0) {
1195  meshName += ctx.state->name;
1196  } else {
1197  meshName += "xoreos.default";
1198  }
1199  meshName += ".";
1200  meshName += _name;
1201 
1202  if (!_mesh) {
1203  return;
1204  }
1205 
1206  if (!_mesh->data) {
1207  return;
1208  }
1209 
1210  if (!_mesh->data->rawMesh) {
1211  return;
1212  }
1213 
1214  _mesh->data->rawMesh->setName(meshName);
1215  _mesh->data->rawMesh->init();
1216  if (MeshMan.getMesh(meshName)) {
1217  warning("Warning: probable mesh duplication of: %s", meshName.c_str());
1218  }
1219  MeshMan.addMesh(_mesh->data->rawMesh);
1220 
1221  if (GfxMan.isRendererExperimental())
1222  buildMaterial();
1223 }
1224 
1226  for (uint32 i = 0; i < n; ) {
1227  std::vector<Common::UString> line;
1228 
1229  size_t count = ctx.tokenize->getTokens(*ctx.mdl, line, 1);
1230 
1231  ctx.tokenize->nextChunk(*ctx.mdl);
1232 
1233  // Ignore empty lines and comments
1234  if ((count == 0) || line[0].empty() || (*line[0].begin() == '#'))
1235  continue;
1236 
1237  i++;
1238  }
1239 }
1240 
1242  for (uint32 i = 0; i < n; ) {
1243  std::vector<Common::UString> line;
1244 
1245  size_t count = ctx.tokenize->getTokens(*ctx.mdl, line, 1);
1246 
1247  ctx.tokenize->nextChunk(*ctx.mdl);
1248 
1249  // Ignore empty lines and comments
1250  if ((count == 0) || line[0].empty() || (*line[0].begin() == '#'))
1251  continue;
1252 
1253  i++;
1254  }
1255 }
1256 
1257 void ModelNode_NWN_ASCII::readFloats(const std::vector<Common::UString> &strings,
1258  float *floats, uint32 n, uint32 start) {
1259 
1260  if (strings.size() < (start + n))
1261  throw Common::Exception("Missing tokens");
1262 
1263  for (uint32 i = 0; i < n; i++)
1264  Common::parseString(strings[start + i], floats[i]);
1265 }
1266 
1268  mesh.vX.resize(mesh.vCount);
1269  mesh.vY.resize(mesh.vCount);
1270  mesh.vZ.resize(mesh.vCount);
1271 
1272  for (uint32 i = 0; i < mesh.vCount; ) {
1273  std::vector<Common::UString> line;
1274 
1275  size_t count = ctx.tokenize->getTokens(*ctx.mdl, line, 3);
1276 
1277  ctx.tokenize->nextChunk(*ctx.mdl);
1278 
1279  // Ignore empty lines and comments
1280  if ((count == 0) || line[0].empty() || (*line[0].begin() == '#'))
1281  continue;
1282 
1283  Common::parseString(line[0], mesh.vX[i]);
1284  Common::parseString(line[1], mesh.vY[i]);
1285  Common::parseString(line[2], mesh.vZ[i]);
1286 
1287  i++;
1288  }
1289 }
1290 
1292  mesh.tX.resize(mesh.tCount);
1293  mesh.tY.resize(mesh.tCount);
1294 
1295  for (uint32 i = 0; i < mesh.tCount; ) {
1296  std::vector<Common::UString> line;
1297 
1298  size_t count = ctx.tokenize->getTokens(*ctx.mdl, line, 2);
1299 
1300  ctx.tokenize->nextChunk(*ctx.mdl);
1301 
1302  // Ignore empty lines and comments
1303  if ((count == 0) || line[0].empty() || (*line[0].begin() == '#'))
1304  continue;
1305 
1306  Common::parseString(line[0], mesh.tX[i]);
1307  Common::parseString(line[1], mesh.tY[i]);
1308 
1309  i++;
1310  }
1311 }
1312 
1314  mesh.vIA.resize(mesh.faceCount);
1315  mesh.vIB.resize(mesh.faceCount);
1316  mesh.vIC.resize(mesh.faceCount);
1317 
1318  mesh.tIA.resize(mesh.faceCount);
1319  mesh.tIB.resize(mesh.faceCount);
1320  mesh.tIC.resize(mesh.faceCount);
1321 
1322  mesh.smooth.resize(mesh.faceCount);
1323  mesh.mat.resize(mesh.faceCount);
1324 
1325  for (uint32 i = 0; i < mesh.faceCount; ) {
1326  std::vector<Common::UString> line;
1327 
1328  size_t count = ctx.tokenize->getTokens(*ctx.mdl, line, 8);
1329 
1330  ctx.tokenize->nextChunk(*ctx.mdl);
1331 
1332  // Ignore empty lines and comments
1333  if ((count == 0) || line[0].empty() || (*line[0].begin() == '#'))
1334  continue;
1335 
1336  Common::parseString(line[0], mesh.vIA[i]);
1337  Common::parseString(line[1], mesh.vIB[i]);
1338  Common::parseString(line[2], mesh.vIC[i]);
1339 
1340  Common::parseString(line[3], mesh.smooth[i]);
1341 
1342  Common::parseString(line[4], mesh.tIA[i]);
1343  Common::parseString(line[5], mesh.tIB[i]);
1344  Common::parseString(line[6], mesh.tIC[i]);
1345 
1346  Common::parseString(line[7], mesh.mat[i]);
1347 
1348  i++;
1349  }
1350 }
1351 
1352 typedef glm::vec3 Vec3;
1353 
1354 struct FaceVert {
1355  uint32 p, t; // position, texture coord indices
1356  uint32 i; // unique vertex id
1357  Vec3 n; // normal vector
1358 };
1359 
1360 bool operator == (const FaceVert &a, const FaceVert &b) {
1361  return (a.p == b.p) && (a.t == b.t) && fuzzyEqual(&a.n[0], &b.n[0]);
1362 }
1363 
1364 std::size_t hash_value(const FaceVert &b) {
1365  std::size_t seed = 0;
1366  boost::hash_combine(seed, b.p);
1367  boost::hash_combine(seed, b.t);
1368  boost::hash_combine(seed, uint32(b.n[0] * 1E4));
1369  boost::hash_combine(seed, uint32(b.n[1] * 1E4));
1370  boost::hash_combine(seed, uint32(b.n[2] * 1E4));
1371  return seed;
1372 }
1373 
1375  if ((mesh.vCount == 0) || (mesh.tCount == 0) || (mesh.faceCount == 0))
1376  return;
1377 
1378  _render = _mesh->render;
1379  _mesh->data = new MeshData();
1380  _mesh->data->rawMesh = new Graphics::Mesh::Mesh();
1381 
1382  loadTextures(mesh.textures);
1383 
1384  const size_t textureCount = mesh.textures.size();
1385  if (textureCount > 1)
1386  warning("ModelNode_NWN_ASCII::processMesh(): textureCount == %u", (uint)textureCount);
1387 
1388 
1389  // Read faces
1390 
1391  uint32 facesCount = mesh.faceCount;
1392  _mesh->data->rawMesh->getIndexBuffer()->setSize(facesCount * 3, sizeof(uint32), GL_UNSIGNED_INT);
1393 
1394  boost::unordered_set<FaceVert> verts;
1395  typedef boost::unordered_set<FaceVert>::iterator verts_set_it;
1396 
1397  uint32 vertexCount = 0;
1398  uint32 *f = reinterpret_cast<uint32 *>(_mesh->data->rawMesh->getIndexBuffer()->getData());
1399  for (uint32 i = 0; i < facesCount; i++) {
1400  const uint32 v[3] = {mesh.vIA[i], mesh.vIB[i], mesh.vIC[i]};
1401  const uint32 t[3] = {mesh.tIA[i], mesh.tIB[i], mesh.tIC[i]};
1402 
1403  // Face normal
1404  const Vec3 p1(mesh.vX[v[0]], mesh.vY[v[0]], mesh.vZ[v[0]]);
1405  const Vec3 p2(mesh.vX[v[1]], mesh.vY[v[1]], mesh.vZ[v[1]]);
1406  const Vec3 p3(mesh.vX[v[2]], mesh.vY[v[2]], mesh.vZ[v[2]]);
1407  const Vec3 n = glm::normalize(glm::cross(p2 - p1, p3 - p2));
1408 
1409  for (uint32 j = 0; j < 3; j++) {
1410  FaceVert fv;
1411  fv.i = vertexCount;
1412  fv.p = v[j];
1413  fv.t = t[j];
1414  fv.n = n;
1415 
1416  std::pair<verts_set_it, bool> it = verts.insert(fv);
1417  if (it.second)
1418  vertexCount++;
1419 
1420  *f++ = it.first->i;
1421  }
1422  }
1423 
1424 
1425  // Read vertices (interleaved)
1426 
1427  VertexDecl vertexDecl;
1428 
1429  vertexDecl.push_back(VertexAttrib(VPOSITION, 3, GL_FLOAT));
1430  vertexDecl.push_back(VertexAttrib(VNORMAL , 3, GL_FLOAT));
1431  for (uint t = 0; t < textureCount; t++)
1432  vertexDecl.push_back(VertexAttrib(VTCOORD + t, 2, GL_FLOAT));
1433 
1434  _mesh->data->rawMesh->getVertexBuffer()->setVertexDeclInterleave(vertexCount, vertexDecl);
1435 
1436  for (verts_set_it i = verts.begin(); i != verts.end(); ++i) {
1437  byte *vData = reinterpret_cast<byte *>(_mesh->data->rawMesh->getVertexBuffer()->getData()) + i->i * _mesh->data->rawMesh->getVertexBuffer()->getSize();
1438  float *v = reinterpret_cast<float *>(vData);
1439 
1440  // Position
1441  *v++ = mesh.vX[i->p];
1442  *v++ = mesh.vY[i->p];
1443  *v++ = mesh.vZ[i->p];
1444 
1445  // Normal
1446  *v++ = i->n[0];
1447  *v++ = i->n[1];
1448  *v++ = i->n[2];
1449 
1450  // TexCoord
1451  if (i->t < mesh.tCount) {
1452  *v++ = mesh.tX[i->t];
1453  *v++ = mesh.tY[i->t];
1454  } else {
1455  *v++ = 0.0f;
1456  *v++ = 0.0f;
1457  }
1458  for (uint16 t = 1; t < textureCount; t++) {
1459  *v++ = 0.0f;
1460  *v++ = 0.0f;
1461  }
1462  }
1463 
1464  createBound();
1465 }
1466 
1467 } // End of namespace Aurora
1468 
1469 } // End of namespace Graphics
static const uint16 kControllerTypeSelfIllumColor
Definition: model_nwn.cpp:119
Model_NWN(const Common::UString &name, ModelType type=kModelTypeObject, const Common::UString &texture="", ModelCache *modelCache=0)
Definition: model_nwn.cpp:184
#define ResMan
Shortcut for accessing the sound manager.
Definition: resman.h:557
GLvoid * getData()
Access buffer data.
Definition: indexbuffer.cpp:78
bool operator==(const FaceVert &a, const FaceVert &b)
Definition: model_nwn.cpp:1360
A node within an animation.
static const uint16 kControllerTypeColorMid
Definition: model_nwn.cpp:113
static const uint16 kControllerTypeSizeEnd_Y
Definition: model_nwn.cpp:101
void loadSuperModel(ModelCache *modelCache)
Definition: model_nwn.cpp:480
uint16 readUint16LE()
Read an unsigned 16-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:122
NodeMap nodeMap
The nodes within the state, indexed by name.
Definition: model.h:207
void loadBinary(ParserContext &ctx)
Definition: model_nwn.cpp:214
Vertex texture coordinates, VTCOORDi = VTCOORD + i.
Definition: vertexbuffer.h:39
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:133
static const int kNodeFlagHasDangly
Definition: model_nwn.cpp:69
An element of the front GUI.
Definition: types.h:53
void debugC(Common::DebugChannel channel, uint32 level, const char *s,...)
Definition: debug.cpp:34
static const uint16 kControllerTypeLifeExp
Definition: model_nwn.cpp:92
friend class ModelNode_NWN_Binary
Definition: model_nwn.h:96
A class holding an UTF-8 string.
Definition: ustring.h:48
static const uint16 kControllerTypeP2P_Bezier3
Definition: model_nwn.cpp:95
Geometry, BioWare model.
Definition: types.h:73
static const uint16 kControllerTypeVelocity
Definition: model_nwn.cpp:104
void setLength(float length)
Definition: animation.cpp:62
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
void readFaces(Model_NWN::ParserContext &ctx, Mesh &mesh)
Definition: model_nwn.cpp:1313
An animation to be applied to a model.
friend class Animation
Definition: model.h:307
Vertex position.
Definition: vertexbuffer.h:36
VertexBuffer * getVertexBuffer()
Definition: mesh.cpp:39
Utility functions for debug output.
static const uint16 kControllerTypeDrag
Definition: model_nwn.cpp:87
std::vector< Common::UString > textures
Definition: model_nwn.h:133
static const uint16 kControllerTypeThreshold
Definition: model_nwn.cpp:103
static const int kNodeFlagHasSkin
Definition: model_nwn.cpp:67
void loadTextures(const std::vector< Common::UString > &textures)
Definition: modelnode.cpp:340
uint8_t uint8
Definition: types.h:200
virtual bool eos() const =0
Returns true if a read failed because the stream has been reached.
void init()
General mesh initialisation, queuing the mesh for GL resource creation.
Definition: mesh.cpp:71
static const uint16 kControllerTypeRadius
Definition: model_nwn.cpp:76
static const uint16 kControllerTypeDetonate
Definition: model_nwn.cpp:111
std::list< ModelNode * > & getChildren()
Get the node&#39;s children.
Definition: modelnode.cpp:152
bool render
Render this mesh?
Definition: modelnode.h:183
Common::UString name
The state&#39;s name.
Definition: model.h:204
Mathematical helpers.
Tokenizes a stream.
static const uint16 kControllerTypeLightningRadius
Definition: model_nwn.cpp:109
NodeList rootNodes
The nodes in the state without a parent.
Definition: model.h:209
static const uint16 kControllerTypeXSize
Definition: model_nwn.cpp:105
void readWeights(Model_NWN::ParserContext &ctx, uint32 n)
Definition: model_nwn.cpp:1241
void setParent(ModelNode *parent)
Set the node&#39;s parent.
Definition: modelnode.cpp:143
void setVertexDeclInterleave(uint32 vertCount, VertexDecl &decl)
Set the interleaved vertex declaration for this buffer.
State * _currentState
The current state.
Definition: model.h:227
void addChunkEnd(uint32 c)
Add a character marking the end of a chunk.
static const uint16 kControllerTypeSizeStart
Definition: model_nwn.cpp:98
#define ARRAYSIZE(x)
Macro which determines the number of entries in a fixed size array.
Definition: util.h:131
bool _render
Render the node?
Definition: modelnode.h:235
void readConstraints(Model_NWN::ParserContext &ctx, uint32 n)
Definition: model_nwn.cpp:1225
static const uint16 kControllerTypeSizeMid
Definition: model_nwn.cpp:117
const Common::UString & getName() const
Get the model&#39;s name.
Definition: model.cpp:125
void readAnimBinary(ParserContext &ctx, uint32 offset)
Definition: model_nwn.cpp:423
static const uint16 kControllerTypeBounce_Co
Definition: model_nwn.cpp:83
Common::UString _fileName
The model&#39;s file name.
Definition: model.h:218
static bool fuzzyEqual(const float *a, const float *b)
Definition: model_nwn.cpp:697
std::vector< VertexAttrib > VertexDecl
Vertex data layout.
Definition: vertexbuffer.h:63
static const int kNodeFlagHasMesh
Definition: model_nwn.cpp:66
#define IGNORE_UNUSED_VARIABLES
Definition: system.h:423
static const uint16 kControllerTypeAlphaEnd
Definition: model_nwn.cpp:80
static const uint16 kControllerTypeFrameEnd
Definition: model_nwn.cpp:89
Utility templates and functions for working with strings and streams.
static const uint16 kControllerTypeParticleRot
Definition: model_nwn.cpp:96
void processMesh(ModelNode_NWN_ASCII::Mesh &mesh)
Definition: model_nwn.cpp:1374
static const int kNodeFlagHasAnim
Definition: model_nwn.cpp:68
static const uint16 kControllerTypeColorEnd
Definition: model_nwn.cpp:84
Model * _model
The model this node belongs to.
Definition: modelnode.h:207
void readNodeControllers(Model_NWN::ParserContext &ctx, uint32 offset, uint32 count, std::vector< float > &data)
Definition: model_nwn.cpp:991
static const int kNodeFlagHasAABB
Definition: model_nwn.cpp:70
void load(Model_NWN::ParserContext &ctx, const Common::UString &type, const Common::UString &name)
Definition: model_nwn.cpp:1088
void readTCoords(Model_NWN::ParserContext &ctx, Mesh &mesh)
Definition: model_nwn.cpp:1291
Common::UString _name
The model&#39;s name.
Definition: model.h:220
Vertex normal.
Definition: vertexbuffer.h:37
void addState(ParserContext &ctx)
Definition: model_nwn.cpp:396
Basic exceptions to throw.
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
AnimationMap _animationMap
Map of all animations in this model.
Definition: model.h:231
ModelType
The display type of a model.
Definition: types.h:51
ModelType _type
The model&#39;s type.
Definition: model.h:216
uint16_t uint16
Definition: types.h:202
#define UNUSED(x)
Definition: system.h:170
static const uint16 kControllerTypeScale
Definition: model_nwn.cpp:74
static const uint16 kControllerTypeVerticalDisplacement
Definition: model_nwn.cpp:78
void setTransTime(float transtime)
Definition: animation.cpp:70
static const uint16 kControllerTypeColor
Definition: model_nwn.cpp:75
void newState(ParserContext &ctx)
Definition: model_nwn.cpp:352
static const int kNodeFlagHasReference
Definition: model_nwn.cpp:65
static const uint16 kControllerTypeBlurLength
Definition: model_nwn.cpp:107
"GGraphics", global, non-engine graphics.
Definition: debugman.h:42
virtual void buildMaterial()
Definition: modelnode.cpp:1008
void readAnim(Model_NWN::ParserContext &ctx)
Definition: model_nwn.cpp:972
static const DefaultAnim kDefaultAnims[]
Definition: model_nwn.cpp:506
static void readArray(Common::SeekableReadStream &stream, uint32 offset, uint32 count, std::vector< T > &values)
Definition: model.cpp:902
virtual size_t skip(ptrdiff_t offset)
Skip the specified number of bytes, adding that offset to the current position in the stream...
Definition: readstream.h:317
void load(Model_NWN::ParserContext &ctx)
Definition: model_nwn.cpp:547
static const uint16 kControllerTypePosition
Definition: model_nwn.cpp:72
Loading MDL files found in Neverwinter Nights.
float ambient[3]
Ambient color.
Definition: modelnode.h:173
Utility functions for working with differing string encodings.
The global shader material manager.
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
The global shader surface manager.
static const uint16 kControllerTypeMass
Definition: model_nwn.cpp:93
float specular[3]
Specular color.
Definition: modelnode.h:175
static const uint16 kControllerTypeColorStart
Definition: model_nwn.cpp:85
void checkDuplicateNode(Model_NWN::ParserContext &ctx, ModelNode_NWN_Binary *newNode)
Definition: model_nwn.cpp:655
std::size_t hash_value(const FaceVert &b)
Definition: model_nwn.cpp:1364
StackException Exception
Definition: error.h:59
std::vector< QuaternionKeyFrame > _orientationFrames
Keyframes for orientation animation.
Definition: modelnode.h:229
static const uint16 kControllerTypePercentMid
Definition: model_nwn.cpp:115
static const uint16 kControllerTypeYSize
Definition: model_nwn.cpp:106
void addIgnore(uint32 c)
Add a character to ignore.
float _position[3]
Position of the node.
Definition: modelnode.h:221
NodeList nodeList
The nodes within the state.
Definition: model.h:206
static Common::UString loadName(Model_NWN::ParserContext &ctx)
Definition: model_nwn.cpp:535
void warning(const char *s,...)
Definition: util.cpp:33
StateMap _stateMap
All states within this model, index by name.
Definition: model.h:226
std::list< ModelNode * > nodes
Definition: model_nwn.h:60
Basic reading stream interfaces.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
Common::StreamTokenizer * tokenize
Definition: model_nwn.h:70
ParserContext(const Common::UString &name, const Common::UString &t)
Definition: model_nwn.cpp:126
void readMesh(Model_NWN::ParserContext &ctx)
Definition: model_nwn.cpp:703
float _scale[3]
Model&#39;s scale.
Definition: model.h:237
static const uint16 kControllerTypeLightningDelay
Definition: model_nwn.cpp:108
static const uint16 kControllerTypeSizeMid_Y
Definition: model_nwn.cpp:118
void readVCoords(Model_NWN::ParserContext &ctx, Mesh &mesh)
Definition: model_nwn.cpp:1267
bool findNode(const Common::UString &name, ModelNode *&node) const
Definition: model_nwn.cpp:163
void skipAnimASCII(ParserContext &ctx)
Definition: model_nwn.cpp:360
FORCEINLINE float readIEEEFloatLE()
Read a 32-bit IEEE float stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:230
#define MeshMan
Shortcut for accessing the shader manager.
Definition: meshman.h:74
static const uint16 kControllerTypePercentEnd
Definition: model_nwn.cpp:116
Basic type definitions to handle files used in BioWare&#39;s Aurora engine.
Plain, unextended ASCII (7bit clean).
Definition: encoding.h:40
static const uint16 kControllerTypeMultiplier
Definition: model_nwn.cpp:79
static const uint16 kControllerTypeCombineTime
Definition: model_nwn.cpp:86
static const int kNodeFlagHasLight
Definition: model_nwn.cpp:63
size_t getTokens(SeekableReadStream &stream, std::vector< UString > &list, size_t min=0, size_t max=SIZE_MAX, const UString &def="")
Parse tokens out of the stream.
Graphics::Mesh::Mesh * rawMesh
Node raw mesh data.
Definition: modelnode.h:159
void inheritPosition(ModelNode &node) const
Definition: modelnode.cpp:262
Common::UString _name
The node&#39;s name.
Definition: modelnode.h:216
size_t size() const
Return the size of the string, in characters.
Definition: ustring.cpp:241
static const int kNodeFlagHasHeader
Definition: model_nwn.cpp:62
void loadASCII(ParserContext &ctx)
Definition: model_nwn.cpp:287
static const uint16 kControllerTypeRandVel
Definition: model_nwn.cpp:97
bool shadow
Does the node have a shadow?
Definition: modelnode.h:184
uint32_t uint32
Definition: types.h:204
static const uint16 kControllerTypeAlpha
Definition: model_nwn.cpp:120
static const uint16 kControllerTypeBirthRate
Definition: model_nwn.cpp:82
Parse tokens out of a stream.
static void readArrayDef(Common::SeekableReadStream &stream, uint32 &offset, uint32 &count)
Definition: model.cpp:886
GLvoid * getData()
Access buffer data.
void nextChunk(SeekableReadStream &stream)
Skip past end of chunk characters.
Ignore all repeated separators.
friend class ModelNode_NWN_ASCII
Definition: model_nwn.h:97
Low-level detection of architecture/system properties.
float diffuse[3]
Diffuse color.
Definition: modelnode.h:174
void setName(Common::UString &name)
Definition: animation.cpp:58
float _orientation[4]
Orientation of the node.
Definition: modelnode.h:223
Model * _superModel
The actual super model.
Definition: model.h:223
static const uint16 kControllerTypeGrav
Definition: model_nwn.cpp:91
static const uint16 kControllerTypeAlphaMid
Definition: model_nwn.cpp:112
void addAnimNode(AnimNode *node)
Definition: animation.cpp:100
static const uint16 kControllerTypeSpread
Definition: model_nwn.cpp:102
static float rad2deg(float rad)
Definition: maths.h:93
void finalize()
Finalize the loading procedure.
Definition: model.cpp:807
void addDefaultAnimation(const Common::UString &anim, uint8 probability)
Definition: model.cpp:550
UString readStringFixed(SeekableReadStream &stream, Encoding encoding, size_t length)
Read length bytes as a string with the given encoding out of a stream.
Definition: encoding.cpp:297
void setName(const Common::UString &name)
Definition: mesh.cpp:47
Animation * getAnimation(const Common::UString &anim)
Get the animation from its name.
Definition: model.cpp:496
static const uint16 kControllerTypeOrientation
Definition: model_nwn.cpp:73
static const int kNodeFlagHasEmitter
Definition: model_nwn.cpp:64
std::vector< PositionKeyFrame > _positionFrames
Keyframes for position animation.
Definition: modelnode.h:228
Animation channel.
void addSeparator(uint32 c)
Add a character on where to split tokens.
void readFloats(const std::vector< Common::UString > &strings, float *floats, uint32 n, uint32 start)
Definition: model_nwn.cpp:1257
ModelNode * getParent()
Get the node&#39;s parent.
Definition: modelnode.cpp:135
static const uint16 kControllerTypeAlphaStart
Definition: model_nwn.cpp:81
ModelNode * getNode(const Common::UString &node)
Get the specified node, from the current state.
Definition: model.cpp:379
StateList _stateList
All states within this model.
Definition: model.h:225
static const uint16 kControllerTypePercentStart
Definition: model_nwn.cpp:114
float _animationScale
The scale of the animation.
Definition: model.h:235
void readAnimASCII(ParserContext &ctx)
Definition: model_nwn.cpp:386
Common::UString _superModelName
Name of the super model.
Definition: model.h:222
Generic vertex attribute data.
Definition: vertexbuffer.h:43
static const uint16 kControllerTypeFPS
Definition: model_nwn.cpp:88
static const uint16 kControllerTypeLightningScale
Definition: model_nwn.cpp:110
byte readByte()
Read an unsigned byte from the stream and return it.
Definition: readstream.h:92
IndexBuffer * getIndexBuffer()
Definition: mesh.cpp:43
static const uint16 kControllerTypeP2P_Bezier2
Definition: model_nwn.cpp:94
static const uint16 kControllerTypeFrameStart
Definition: model_nwn.cpp:90
void parseString(const UString &str, T &value, bool allowEmpty)
Parse a string into any POD integer, float/double or bool type.
Definition: strutil.cpp:215
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
static const uint16 kControllerTypeSizeStart_Y
Definition: model_nwn.cpp:100
void setSize(uint32 indexCount, uint32 indexSize, GLenum indexType)
Change buffer size.
Definition: indexbuffer.cpp:65
The global resource manager for Aurora resources.
uint8 byte
Definition: types.h:209
static const uint16 kControllerTypeShadowRadius
Definition: model_nwn.cpp:77
unsigned int uint
Definition: types.h:211
void inheritOrientation(ModelNode &node) const
Definition: modelnode.cpp:268
Common::SeekableReadStream * mdl
Definition: model_nwn.h:52
static const uint16 kControllerTypeSizeEnd
Definition: model_nwn.cpp:99