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