xoreos  0.0.5
trxfile.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 #include "src/common/scopedptr.h"
26 #include "src/common/error.h"
27 #include "src/common/readstream.h"
28 #include "src/common/encoding.h"
29 #include "src/common/ustring.h"
30 #include "src/common/strutil.h"
31 
32 #include "src/aurora/resman.h"
33 
34 #include "src/graphics/graphics.h"
37 
39 
41 
42 namespace Engines {
43 
44 namespace NWN2 {
45 
46 TRXFile::TRXFile(const Common::UString &resRef) : _visible(false) {
47  try {
49  if (!trx)
50  throw Common::Exception("No such TRX");
51 
52  load(*trx);
53 
54  } catch (Common::Exception &e) {
55  e.add("Failed to load TRX \"%s\"", resRef.c_str());
56  throw e;
57  }
58 }
59 
61  hide();
62 }
63 
64 void TRXFile::show() {
65  if (_visible)
66  return;
67 
68  GfxMan.lockFrame();
69 
70  for (ObjectList::iterator t = _terrain.begin(); t != _terrain.end(); ++t)
71  (*t)->show();
72  for (ObjectList::iterator w = _water.begin(); w != _water.end(); ++w)
73  (*w)->show();
74 
75  _visible = true;
76 
77  GfxMan.unlockFrame();
78 }
79 
80 void TRXFile::hide() {
81  if (!_visible)
82  return;
83 
84  GfxMan.lockFrame();
85 
86  for (ObjectList::iterator t = _terrain.begin(); t != _terrain.end(); ++t)
87  (*t)->hide();
88  for (ObjectList::iterator w = _water.begin(); w != _water.end(); ++w)
89  (*w)->hide();
90 
91  _visible = false;
92 
93  GfxMan.unlockFrame();
94 }
95 
97  uint32 magic = trx.readUint32BE();
98  if (magic != MKTAG('N', 'W', 'N', '2'))
99  throw Common::Exception("Invalid magic %s", Common::debugTag(magic).c_str());
100 
101  uint16 versionMajor = trx.readUint16LE();
102  uint16 versionMinor = trx.readUint16LE();
103  if ((versionMajor != 2) || (versionMinor != 3))
104  throw Common::Exception("Invalid version %d.%d", versionMajor, versionMinor);
105 
106  uint32 packetCount = trx.readUint32LE();
107  if ((trx.size() - trx.pos()) < (packetCount * 8))
108  throw Common::Exception("TRX won't fit the packet packets");
109 
110  std::vector<Packet> packets;
111  packets.resize(packetCount);
112 
113  loadDirectory(trx, packets);
114  loadPackets(trx, packets);
115 }
116 
117 void TRXFile::loadDirectory(Common::SeekableReadStream &trx, std::vector<Packet> &packets) {
118  for (std::vector<Packet>::iterator p = packets.begin(); p != packets.end(); ++p) {
119  p->type = trx.readUint32BE();
120  p->offset = trx.readUint32LE();
121 
122  if (p->offset >= trx.size())
123  throw Common::Exception("Offset of 0x%08X packet too big (%d)", p->type, p->offset);
124  }
125 }
126 
127 void TRXFile::loadPackets(Common::SeekableReadStream &trx, std::vector<Packet> &packets) {
128  for (std::vector<Packet>::iterator p = packets.begin(); p != packets.end(); ++p) {
129  trx.seek(p->offset);
130 
131  uint32 type = trx.readUint32BE();
132  if (type != p->type)
133  throw Common::Exception("Packet type mismatch (0x%08X vs 0x%08X)", type, p->type);
134 
135  p->size = trx.readUint32LE();
136  if ((trx.size() - trx.pos()) < p->size)
137  throw Common::Exception("Size of 0x%8X packet too big (%d)", p->type, p->size);
138 
139  loadPacket(trx, *p);
140  }
141 }
142 
144  if (packet.type == MKTAG('T', 'R', 'W', 'H'))
145  loadTRWH(trx, packet);
146  else if (packet.type == MKTAG('T', 'R', 'R', 'N'))
147  loadTRRN(trx, packet);
148  else if (packet.type == MKTAG('W', 'A', 'T', 'R'))
149  loadWATR(trx, packet);
150  else if (packet.type == MKTAG('A', 'S', 'W', 'M'))
151  loadASWM(trx, packet);
152  else
153  throw Common::Exception("Unknown packet type %s", Common::debugTag(packet.type).c_str());
154 }
155 
157  if (packet.size != 12)
158  throw Common::Exception("Invalid TRWH size (%d)", packet.size);
159 
160  _width = trx.readUint32LE();
161  _height = trx.readUint32LE();
162 
163  // trx.readUint32LE(); // Unknown
164 }
165 
167  Common::SeekableSubReadStream ttrn(&trx, trx.pos(), trx.pos() + packet.size);
168 
170 
171  Common::UString textures[6];
172  for (int i = 0; i < 6; i++)
173  textures[i] = Common::readStringFixed(ttrn, Common::kEncodingASCII, 32);
174 
175  float textureColors[6][3];
176  for (int i = 0; i < 6; i++)
177  for (int j = 0; j < 3; j++)
178  textureColors[i][j] = ttrn.readIEEEFloatLE();
179 
180  const uint32 vCount = ttrn.readUint32LE();
181  const uint32 fCount = ttrn.readUint32LE();
182 
183  Graphics::VertexDecl vertexDecl;
184 
185  vertexDecl.push_back(Graphics::VertexAttrib(Graphics::VPOSITION, 3, GL_FLOAT));
186  vertexDecl.push_back(Graphics::VertexAttrib(Graphics::VNORMAL , 3, GL_FLOAT));
187  vertexDecl.push_back(Graphics::VertexAttrib(Graphics::VCOLOR , 4, GL_FLOAT));
188 
190  vBuf.setVertexDeclInterleave(vCount, vertexDecl);
191 
192  float *v = reinterpret_cast<float *>(vBuf.getData());
193  for (uint32 i = 0; i < vCount; i++) {
194  *v++ = ttrn.readIEEEFloatLE();
195  *v++ = ttrn.readIEEEFloatLE();
196  *v++ = ttrn.readIEEEFloatLE();
197 
198  *v++ = ttrn.readIEEEFloatLE();
199  *v++ = ttrn.readIEEEFloatLE();
200  *v++ = ttrn.readIEEEFloatLE();
201 
202  for (int j = 0; j < 3; j++) {
203  int vals = 1;
204  float rgb = ttrn.readByte() / 255.0f;
205 
206  for (int k = 0; k < 6; k++) {
207  if (!textures[k].empty()) {
208  rgb += textureColors[k][j];
209  vals++;
210  }
211  }
212 
213  rgb /= vals;
214 
215  *v++ = rgb;
216  }
217 
218  *v++ = ttrn.readByte() / 255.0f;
219 
220  ttrn.skip(16); // Some texture coordinates?
221  }
222 
224  iBuf.setSize(fCount * 3, sizeof(uint16), GL_UNSIGNED_SHORT);
225 
226  uint16 *f = reinterpret_cast<uint16 *>(iBuf.getData());
227  for (uint32 i = 0; i < fCount; i++) {
228  *f++ = ttrn.readUint16LE();
229  *f++ = ttrn.readUint16LE();
230  *f++ = ttrn.readUint16LE();
231  }
232 
233  /* TODO:
234  * - uint32 dds1Size
235  * - byte *dds1
236  * - uint32 dds2Size
237  * - byte *dds2
238  * - uint32 grassCount
239  * - Grass grass
240  */
241 
242  _terrain.push_back(new Graphics::Aurora::GeometryObject(vBuf, iBuf));
243 }
244 
246  Common::SeekableSubReadStream watr(&trx, trx.pos(), trx.pos() + packet.size);
247 
249 
250  float color[3];
251  color[0] = watr.readIEEEFloatLE();
252  color[1] = watr.readIEEEFloatLE();
253  color[2] = watr.readIEEEFloatLE();
254 
255  watr.skip(4); // float rippleX
256  watr.skip(4); // float rippleY
257  watr.skip(4); // float smoothness
258  watr.skip(4); // float refBias
259  watr.skip(4); // float refPower
260  watr.skip(4); // Unknown
261  watr.skip(4); // Unknown
262 
263  Common::UString textures[3];
264  for (int i = 0; i < 3; i++) {
265  textures[i] = Common::readStringFixed(watr, Common::kEncodingASCII, 32);
266 
267  watr.skip(4); // float dirX
268  watr.skip(4); // float dirY
269  watr.skip(4); // float rate
270  watr.skip(4); // float angle
271  }
272 
273  watr.skip(4); // float offsetX
274  watr.skip(4); // float offsetY
275 
276  uint32 vCount = watr.readUint32LE();
277  uint32 fCount = watr.readUint32LE();
278 
279  Graphics::VertexDecl vertexDecl;
280 
281  vertexDecl.push_back(Graphics::VertexAttrib(Graphics::VPOSITION, 3, GL_FLOAT));
282  vertexDecl.push_back(Graphics::VertexAttrib(Graphics::VCOLOR , 3, GL_FLOAT));
283 
285  vBuf.setVertexDeclInterleave(vCount, vertexDecl);
286 
287  float *v = reinterpret_cast<float *>(vBuf.getData());
288  for (uint32 i = 0; i < vCount; i++) {
289  *v++ = watr.readIEEEFloatLE();
290  *v++ = watr.readIEEEFloatLE();
291  *v++ = watr.readIEEEFloatLE();
292 
293  *v++ = color[0];
294  *v++ = color[1];
295  *v++ = color[2];
296 
297  watr.skip(16); // texture coordinates?
298  }
299 
301  iBuf.setSize(fCount * 3, sizeof(uint16), GL_UNSIGNED_SHORT);
302 
303  uint16 *f = reinterpret_cast<uint16 *>(iBuf.getData());
304  for (uint32 i = 0; i < fCount; i++) {
305  *f++ = watr.readUint16LE();
306  *f++ = watr.readUint16LE();
307  *f++ = watr.readUint16LE();
308  }
309 
310  /* TODO:
311  * - uint32 ddsSize
312  * - byte *dds
313  * - uint32 flags[vCount]
314  * - uint32 tileX
315  * - uint32 tileY
316  */
317 
318  _water.push_back(new Graphics::Aurora::GeometryObject(vBuf, iBuf));
319 }
320 
322 }
323 
324 } // End of namespace NWN2
325 
326 } // End of namespace Engines
#define ResMan
Shortcut for accessing the sound manager.
Definition: resman.h:557
GLvoid * getData()
Access buffer data.
Definition: indexbuffer.cpp:78
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like &#39;DATA&#39;, to ensure portability.
Definition: endianness.h:140
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
uint32 type
Type of the packet (TRWH, TRRN, WATR, ASWM).
Definition: trxfile.h:77
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
The global graphics manager.
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
void loadPackets(Common::SeekableReadStream &trx, std::vector< Packet > &packets)
Load the packets.
Definition: trxfile.cpp:127
A class holding an UTF-8 string.
Definition: ustring.h:48
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
Vertex position.
Definition: vertexbuffer.h:36
uint32 size
Size of the packet.
Definition: trxfile.h:79
Vertex color.
Definition: vertexbuffer.h:38
void setVertexDeclInterleave(uint32 vertCount, VertexDecl &decl)
Set the interleaved vertex declaration for this buffer.
std::vector< VertexAttrib > VertexDecl
Vertex data layout.
Definition: vertexbuffer.h:63
A index buffer.
Utility templates and functions for working with strings and streams.
Exception that provides a stack of explanations.
Definition: error.h:36
A simple scoped smart pointer template.
Vertex normal.
Definition: vertexbuffer.h:37
Basic exceptions to throw.
void loadTRWH(Common::SeekableReadStream &trx, Packet &packet)
Load TRWH (size information) packets.
Definition: trxfile.cpp:156
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
uint16_t uint16
Definition: types.h:202
#define UNUSED(x)
Definition: system.h:170
void loadASWM(Common::SeekableReadStream &trx, Packet &packet)
Load ASWM (walk mesh) packets.
Definition: trxfile.cpp:321
void loadTRRN(Common::SeekableReadStream &trx, Packet &packet)
Load TRRN (terrain tile) packets.
Definition: trxfile.cpp:166
ObjectList _terrain
Definition: trxfile.h:90
Utility functions for working with differing string encodings.
Buffer containing vertex data.
Definition: vertexbuffer.h:68
StackException Exception
Definition: error.h:59
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
Basic reading stream interfaces.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
A packet within a TRX file.
Definition: trxfile.h:76
uint32 readUint32BE()
Read an unsigned 32-bit word stored in big endian (MSB first) order from the stream and return it...
Definition: readstream.h:166
Unicode string handling.
void loadWATR(Common::SeekableReadStream &trx, Packet &packet)
Load WATR (water tile) packets.
Definition: trxfile.cpp:245
TRXFile(const Common::UString &resRef)
Definition: trxfile.cpp:46
Plain, unextended ASCII (7bit clean).
Definition: encoding.h:40
void loadPacket(Common::SeekableReadStream &trx, Packet &packet)
Load one packets.
Definition: trxfile.cpp:143
uint32_t uint32
Definition: types.h:204
UString debugTag(uint32 tag, bool trim)
Create an elaborate string from an integer tag, for debugging purposes.
Definition: strutil.cpp:117
GLvoid * getData()
Access buffer data.
void load(Common::SeekableReadStream &trx)
Definition: trxfile.cpp:96
ObjectList _water
Definition: trxfile.h:91
void loadDirectory(Common::SeekableReadStream &trx, std::vector< Packet > &packets)
Load the packets directory.
Definition: trxfile.cpp:117
Buffer containing indices data.
Definition: indexbuffer.h:33
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
A simple 3D object.
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Definition: readstream.h:359
Loader for Neverwinter Nights 2 baked terrain files (TRX).
Generic vertex attribute data.
Definition: vertexbuffer.h:43
Interface for a seekable & readable data stream.
Definition: readstream.h:265
A vertex buffer.
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
void setSize(uint32 indexCount, uint32 indexSize, GLenum indexType)
Change buffer size.
Definition: indexbuffer.cpp:65
The global resource manager for Aurora resources.