1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program 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 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program 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 this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include <cassert>
24 #include <cmath>
25 #include <cstdio>
26 #include <cstdlib>
27 #include <iostream>
28 #include <fstream>
29 #include <vector>
30 #include <sstream>
31 #include "tools/lab.h"
32
33 using namespace std;
34
35 enum SectorType {
36 NoneType = 0,
37 WalkType = 0x1000,
38 FunnelType = 0x1100,
39 CameraType = 0x2000,
40 SpecialType = 0x4000,
41 HotType = 0x8000
42 };
43
44
45 enum LightType {
46 OmniType = 1,
47 SpotType = 2,
48 DirectType = 3,
49 AmbientType = 4
50 };
51
52 class Data {
53 public:
54 Data(const char *data);
55 float GetFloat();
56 int GetInt();
57 bool GetBool();
58 string GetString(int length);
59 string GetNullTerminatedString();
60 void Skip(int val);
61 private:
62 const char *buf;
63 };
64
Data(const char * data)65 Data::Data(const char *data) {
66 buf = data;
67 }
68
GetFloat()69 float Data::GetFloat() {
70 float retVal = *(float *) buf;
71 buf += 4;
72 return retVal;
73 }
74
GetInt()75 int Data::GetInt() {
76 int retVal = *(int *) buf;
77 buf += 4;
78 return retVal;
79 }
80
GetBool()81 bool Data::GetBool() {
82 bool retVal = *(bool *) buf;
83 buf += 1;
84 return retVal;
85 }
86
GetString(int length)87 string Data::GetString(int length) {
88 //kind of a hack
89 string s = string(buf);
90 buf += length;
91 return s;
92 }
93
GetNullTerminatedString()94 string Data::GetNullTerminatedString() {
95 string s = string(buf);
96 buf += s.length() + 1;
97 return s;
98 }
99
Skip(int val)100 void Data::Skip(int val) {
101 buf += val;
102 }
103
104 struct Section {
105 public:
106 Section(Data *data);
~SectionSection107 virtual ~Section() {};
108 //virtual uint32 load() = 0;
109 virtual string ToString() = 0;
110 protected:
111 Data *section_data;
112 };
113
Section(Data * data)114 Section::Section(Data *data) {
115 this->section_data = data;
116 }
117
118 class Sector : public Section {
119 public:
120 Sector(Data *data);
121
122 virtual string ToString();
123 private:
124 string name;
125 int ID; // byte;
126 SectorType type;
127 float height;
128 int numVertices; // byte;
129 float *vertices; // 3 * numVertices.
130 float normal[3];
131 bool visible;
132 int numSortPlanes;
133 int *sortPlanes;
134 };
135
Sector(Data * data)136 Sector::Sector(Data *data) : Section(data) {
137 numVertices = data->GetInt();
138 vertices = new float[3 * numVertices];
139 for (int i = 0; i < numVertices; i++) {
140 vertices[0 + 3 * i] = data->GetFloat();
141 vertices[1 + 3 * i] = data->GetFloat();
142 vertices[2 + 3 * i] = data->GetFloat();
143 }
144 int nameLength = data->GetInt();
145
146 name = data->GetString(nameLength);
147 ID = data->GetInt();
148 visible = data->GetBool();
149 type = (SectorType)data->GetInt();
150 numSortPlanes = data->GetInt();
151 sortPlanes = new int[numSortPlanes];
152 for (int i = 0; i < numSortPlanes; ++i)
153 sortPlanes[i] = data->GetInt();
154 height = data->GetFloat();
155
156 float cross1[3], cross2[3];
157 cross1[0] = vertices[3] - vertices[0];
158 cross1[1] = vertices[4] - vertices[1];
159 cross1[2] = vertices[5] - vertices[2];
160
161 int x = 3 * (numVertices - 1);
162 cross2[0] = vertices[x + 0] - vertices[0];
163 cross2[1] = vertices[x + 1] - vertices[1];
164 cross2[2] = vertices[x + 2] - vertices[2];
165
166 float &nx = normal[0];
167 float &ny = normal[1];
168 float &nz = normal[2];
169 nx = cross1[1] * cross2[2] - cross2[1] * cross1[2];
170 ny = cross1[0] * cross2[2] - cross2[0] * cross1[2];
171 nz = cross1[0] * cross2[1] - cross2[0] * cross1[1];
172
173 float norm = nx * nx + ny * ny + nz * nz;
174 norm = ::sqrt(norm);
175 nx /= norm;
176 ny /= norm;
177 nz /= norm;
178 }
179
ToString()180 string Sector::ToString() {
181 stringstream ss;
182 ss.precision(6);
183 ss.setf(ios::fixed, ios::floatfield);
184 ss << "\tsector\t" << name << endl;
185 ss << "\tID\t" << ID << endl;
186 ss << "\ttype\t";
187 switch (type) {
188 case WalkType:
189 ss << "walk";
190 break;
191 case FunnelType:
192 ss << "funnel";
193 break;
194 case CameraType:
195 ss << "camera";
196 break;
197 case SpecialType:
198 ss << "special";
199 break;
200 case HotType:
201 ss << "hot";
202 break;
203 case NoneType:
204 ss << "unknown";
205 break;
206 };
207 ss << endl;
208 ss << "\tdefault visibility\t";
209 if (visible) {
210 ss << "visible";
211 } else {
212 ss << "invisible";
213 }
214 ss << endl;
215 ss << "\theight\t" << height << endl;
216 ss << "\tnumvertices\t" << numVertices << endl;
217 ss << "\tsortplanes\t" << numSortPlanes << "\t";
218 for (int i = 0; i < numSortPlanes; ++i) {
219 if (i != 0)
220 ss << ",";
221 ss << sortPlanes[i];
222 }
223 ss << endl;
224 ss << "\tnormal\t\t\t" << normal[0] << "\t" << normal[1] << "\t" << normal[2] << endl;
225 ss << "\tvertices:\t\t";
226 for (int i = 0; i < numVertices * 3; i += 3) {
227 if (i != 0) {
228 ss << "\t\t\t\t";
229 }
230 ss << vertices[i] << "\t" << vertices[i + 1] << "\t" << vertices[i + 2] << endl;
231 }
232
233 return ss.str();
234 }
235
236 class Setup : public Section {
237 public:
238 Setup(Data *data);
239
240 virtual string ToString();
241 private:
242 string name;
243 string tile;
244 string background;
245 string zbuffer;
246 float *position;
247 float *rotationQuat;
248 float fov;
249 float nclip;
250 float fclip;
251 };
252
Setup(Data * data)253 Setup::Setup(Data *data) : Section(data) {
254 name = data->GetString(128); // Parse a string really
255
256 // Skip an unknown number
257 data->GetInt();
258
259 tile = data->GetNullTerminatedString();
260
261 position = new float[3];
262
263 position[0] = data->GetFloat();
264 position[1] = data->GetFloat();
265 position[2] = data->GetFloat();
266
267 rotationQuat = new float[4];
268
269 rotationQuat[0] = data->GetFloat();
270 rotationQuat[1] = data->GetFloat();
271 rotationQuat[2] = data->GetFloat();
272 rotationQuat[3] = data->GetFloat();
273
274 fov = data->GetFloat();
275 nclip = data->GetFloat();
276 fclip = data->GetFloat();
277 }
278
ToString()279 string Setup::ToString() {
280 stringstream ss;
281 ss.precision(6);
282 ss.setf(ios::fixed, ios::floatfield);
283 ss << "\tname\t" << name << endl;
284 // background
285 // zbuffer
286 ss << "\tposition\t" << position[0] << "\t" << position[1] << "\t" << position[2] << endl;
287 ss << "\trotationQuat\tX: " << rotationQuat[0] << "\tY: " << rotationQuat[1] << "\tZ: " << rotationQuat[2] << "\tW: " << rotationQuat[3] << "\t" << endl;
288 ss << "\tfov\t" << fov << endl;
289 ss << "\tnclip\t" << nclip << endl;
290 ss << "\tfclip\t" << fclip << endl;
291
292 return ss.str();
293 }
294
295 class Light : public Section {
296 public:
297 Light(Data *data);
298 virtual string ToString();
299
300 private:
301 string name;
302 LightType type;
303 float *position;
304 float *direction;
305 float intensity;
306 int *color; // Byte
307 float umbraangle;
308 float penumbraangle;
309 float focusdistance;
310 float spreaddistance;
311
312 };
313
Light(Data * data)314 Light::Light(Data *data) : Section(data) {
315 name = data->GetString(32); // 0x00
316
317 position = new float[3]; // 0x20
318 position[0] = data->GetFloat(); // X
319 position[1] = data->GetFloat(); // Y
320 position[2] = data->GetFloat(); // Z
321
322 direction = new float[3]; // 0x2C
323 direction[0] = data->GetFloat(); // X
324 direction[1] = data->GetFloat(); // Y
325 direction[2] = data->GetFloat(); // Z
326
327 intensity = data->GetFloat(); // 0x38
328
329 // Need to check the light type
330 type = (LightType)data->GetInt(); // 0x3C
331
332 data->GetFloat(); // 0x40 // Unknown, definitely float
333 int j = data->GetInt(); // 0x44
334 if (j != 0) {
335 cout << "Warning j != 0!" << endl;
336 }
337
338 // Light color
339 color = new int[3];
340 color[0] = data->GetInt(); // R // 0x48
341 color[1] = data->GetInt(); // G // 0x4C
342 color[2] = data->GetInt(); // B // 0x50
343
344 // Not 100% on these names
345 focusdistance = data->GetFloat(); // 0x54
346 spreaddistance = data->GetFloat(); // 0x58
347 umbraangle = data->GetFloat(); // 0x5C // In radians
348 penumbraangle = data->GetFloat(); // 0x60 // In radians
349 }
350
ToString()351 string Light::ToString() {
352 stringstream ss;
353 ss.precision(6);
354 ss.setf(ios::fixed, ios::floatfield);
355 ss << "\tlight\t" << name << endl;
356 ss << "\ttype\t";
357 switch (type) {
358 case OmniType:
359 ss << "omni";
360 break;
361 case SpotType:
362 ss << "spot";
363 break;
364 case DirectType:
365 ss << "direct";
366 break;
367 case AmbientType:
368 ss << "ambient";
369 break;
370 default:
371 ss << "unknown: " << type;
372 break;
373 }
374 ss << endl;
375 ss << "\tposition\t" << position[0] << "\t" << position[1] << "\t" << position[2] << endl;
376 ss << "\tdirection\t" << direction[0] << "\t" << direction[1] << "\t" << direction[2] << endl;
377 ss << "\tintensity\t" << intensity << endl;
378 ss << "\tcolor\t" << color[0] << " " << color[1] << " " << color[2] << endl;
379 ss << "\tumbraangle\t" << umbraangle << endl;
380 ss << "\tpenumbraangle\t" << penumbraangle << endl;
381 return ss.str();
382 }
383
384 class Set {
385 public:
386 virtual string ToString();
387 Set(Data *data);
~Set()388 virtual ~Set() {}
389 private:
390 string setName;
391 uint32 numSetups;
392 uint32 numLights;
393 uint32 numSectors;
394 vector<Section *> setups;
395 vector<string> colormaps;
396 vector<Section *> lights;
397 vector<Section *> sectors;
398 };
399
Set(Data * data)400 Set::Set(Data *data) {
401 numSetups = data->GetInt();
402 setups.reserve(numSetups);
403 for (uint32 i = 0; i < numSetups; i++) {
404 setups.push_back(new Setup(data));
405 }
406
407 numLights = data->GetInt();
408 lights.reserve(numLights);
409 for (uint32 i = 0; i < numLights; i++) {
410 lights.push_back(new Light(data));
411 }
412
413 numSectors = data->GetInt();
414 sectors.reserve(numSectors);
415 for (uint32 i = 0; i < numSectors; i++) {
416 sectors.push_back(new Sector(data));
417 }
418 }
ToString()419 string Set::ToString() {
420 stringstream ss;
421 // colormaps
422 ss << "section: colormaps" << endl; // we don't have any.
423 // setups
424 ss << "section: setups" << endl;
425 ss << "\tnumsetups " << setups.size() << endl;
426 for (vector<Section *>::iterator it = setups.begin(); it != setups.end(); ++it) {
427 ss << (*it)->ToString() << endl << endl;
428 }
429 // lights
430 ss << "section: lights" << endl;
431 ss << "\tnumlights " << lights.size() << endl;
432 for (vector<Section *>::iterator it = lights.begin(); it != lights.end(); it++) {
433 ss << (*it)->ToString() << endl << endl;
434 }
435 // sectors
436 ss << "section: sectors\n";
437 ss << "\tnumsectors " << sectors.size() << endl;
438 for (vector<Section *>::iterator it = sectors.begin(); it != sectors.end(); it++) {
439 ss << (*it)->ToString() << endl << endl;
440 }
441 return ss.str();
442 }
443
main(int argc,char ** argv)444 int main(int argc, char **argv) {
445 if (argc < 2) {
446 return 0;
447 }
448 Lab *lab = NULL;
449 std::string filename;
450 int length = 0;
451
452 if (argc > 2) {
453 lab = new Lab(argv[1]);
454 filename = argv[2];
455 } else {
456 filename = argv[1];
457 }
458
459 std::istream *file = getFile(filename, lab, length);
460
461 if (!file) {
462 std::cout << "Could not open file" << std::endl;
463 return 0;
464 }
465
466 char *buf = new char[length];
467 file->read(buf, length);
468 delete file;
469
470 Data *data = new Data(buf);
471 Set *ourSet = new Set(data);
472 delete data;
473 delete buf;
474 cout << ourSet->ToString();
475 }
476