Subversion Repositories spk

Rev

Rev 1 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1 Rev 114
Line 1... Line 1...
1
#include "bod_bob_parser.h"
1
#include "bod_bob_parser.h"
2
#include "../common/strutils.h"
2
#include "../common/strutils.h"
-
 
3
 
-
 
4
#define ISMATERIAL(text) ((strcmp(text, "MATERIAL6")==0 || strcmp(text, "MATERIAL5")==0 || \
-
 
5
                          strcmp(text, "MATERIAL3")==0 || strcmp(text, "MATERIAL")==0))
-
 
6
 
-
 
7
//---------------------------------------------------------------------------------
-
 
8
 
-
 
9
geometry::point2d<double> bod_bob_parser::uv_coord::NULL_COORDS(123456, 78910);
3
//---------------------------------------------------------------------------------
10
//---------------------------------------------------------------------------------
4
bool bod_bob_parser::compile(token_stream& is, bob_dom_obinaryfilestream& os, bool bEmbedded)
11
bool bod_bob_parser::compile(token_stream& is, obinaryfilestream& os, bool bEmbedded)
5
{
12
{
6
	bob_dom_bob *bob=new bob_dom_bob(m_settings);
-
 
7
	bob=loadBOB(is, bEmbedded);
13
	bob_dom_bob *bob=loadBOB(is, bEmbedded);
8
	if(bob)
14
	if(bob)
9
		bob->toFile(os);
15
		bob->toFile(os);
10
	delete bob;
16
	delete bob;
11
	return bob!=NULL;
17
	return bob!=NULL;
12
}
18
}
13
//---------------------------------------------------------------------------------
19
//---------------------------------------------------------------------------------
14
#define ISMATERIAL(text) ((strcmp(text, "MATERIAL6")==0 || strcmp(text, "MATERIAL5")==0 || \
-
 
15
                          strcmp(text, "MATERIAL3")==0 || strcmp(text, "MATERIAL")==0))
-
 
16
 
-
 
17
bob_dom_bob * bod_bob_parser::loadBOB(token_stream& is, bool bEmbedded)
20
bob_dom_bob * bod_bob_parser::loadBOB(token_stream& is, bool bEmbedded)
18
{
21
{
19
	token *t;
22
	token *t;
20
	bob_dom_bob *bob=new bob_dom_bob(m_settings);
23
	bob_dom_bob *bob=new bob_dom_bob(m_settings);
21
	bool abort=false;
24
	bool abort=false;
22
	
25
 
23
	while((t=is.tok()) && t->type==token::t_hdrinfo){
26
	while((t=is.tok()) && t->type==token::t_hdrinfo){
24
		if(bob->info.text()!=0)
27
		if(bob->info.text()!=0)
25
			error(is.tok(), S_Warning, "Header info already defined, last value will be used");
28
			error(is.tok(), S_Warning, "Header info already defined, last value will be used");
26
		bob->info.text(t->text);
29
		bob->info.text(t->text);
27
		++is;
30
		++is;
28
	}
31
	}
29
	
32
 
30
	// first load material definitions, break on first numeric token
33
	// first load material definitions, break on first numeric token
31
	while((t=is.tok()) && t->type!=token::t_closeBracket){
34
	while((t=is.tok()) && t->type!=token::t_closeCrBracket){
32
		if(t->type!=token::t_text){
35
		if(t->type!=token::t_text){
33
			error(t, S_Error, "Unexpected here: '%s'", t->getText());
36
			error(t, S_Error, "Unexpected here: '%s'", t->getText());
34
			abort=true; break;
37
			abort=true; break;
35
		}
38
		}
36
		if(isinteger(t->text)) break;
39
		if(isinteger(t->text)) break;
37
		
40
 
38
		//if(strcmp(t->text, "MATERIAL5")==0 || strcmp(t->text, "MATERIAL3")==0 || strcmp(t->text, "MATERIAL")==0){
-
 
39
		if(ISMATERIAL(t->text)){
41
		if(ISMATERIAL(t->text)){
40
			if(!loadMaterial(bob, is)){
42
			if(!loadMaterial(bob, is)){
41
				abort=true; break;
43
				abort=true; break;
42
			}
44
			}
43
		}
45
		}
44
		else{
46
		else{
45
			error(t, S_Error, "Unexpected here '%s'", t->getText());
47
			error(t, S_Error, "Unexpected here '%s'", t->getText());
46
			abort=true; break;
48
			abort=true; break;
47
		}
49
		}
48
	}
50
	}
49
	
51
 
50
	// now load the body definition: body size, points, parts
52
	// now load the body definition: body size, points, parts
51
	if(!abort){
53
	if(!abort){
52
		m_materials=&(bob->materials);
54
		m_materials=&(bob->materials);
53
		do{
55
		do{
54
			if(abort=(loadBody(bob, is)==false)) break;
56
			if(abort=(loadBody(bob, is)==false)) break;
55
			
57
 
56
			if(bEmbedded){
58
			if(bEmbedded){
57
				if(is.tok()==NULL){
59
				if(is.tok()==NULL){
58
					error(is.previous(), S_Error, "Unexpected end of document found while loading embedded BOB - do you miss the '}'?");
60
					error(is.previous(), S_Error, "Unexpected end of document found while loading embedded BOB - do you miss the '}'?");
59
					abort=true; break;
61
					abort=true; break;
60
				}
62
				}
61
				else if(is.tok()->type==token::t_closeBracket)
63
				else if(is.tok()->type==token::t_closeCrBracket)
62
					break;
64
					break;
63
			}
65
			}
64
			else if(is.eof())
66
			else if(is.eof())
65
				break;
67
				break;
66
		}
68
		}
67
		while(1); // while what? while '}' if embedded or while eof if standalone
69
		while(1); // while what? while '}' if embedded or while eof if standalone
68
	}
70
	}
69
	
71
 
70
	if(abort){
72
	if(abort){
71
		delete bob;
73
		delete bob;
72
		bob=NULL;
74
		bob=NULL;
73
	}
75
	}
74
	
76
 
75
	++is; // advance past the close bracket (if embedded)
77
	++is; // advance past the close bracket (if embedded)
76
	
78
 
77
	// set the bob type (setting from Settings takes precedence)
-
 
78
	/*if(bob){
-
 
79
		switch(m_settings->X3BOB()){
-
 
80
			case Settings::on:
-
 
81
				bob->bobType=bobX3;
-
 
82
				break;
-
 
83
			case Settings::off:
-
 
84
				bob->bobType=bobX2;
-
 
85
				break;
-
 
86
			default:
-
 
87
				if(bob->materials.size() && bob->materials.front()->type==bob_dom_material::mat6)
-
 
88
					bob->bobType=bobX3;
-
 
89
				else
-
 
90
					bob->bobType=bobX2;
-
 
91
		}	
-
 
92
	}*/
-
 
93
	
-
 
94
	return bob;
79
	return bob;
95
}
80
}
96
//---------------------------------------------------------------------------------
81
//---------------------------------------------------------------------------------
97
bool bod_bob_parser::loadMatRGB(token_stream& is, bob_dom_material5::rgb& rgb)
82
bool bod_bob_parser::loadMatRGB(token_stream& is, bob_material5::rgb& rgb)
98
{
83
{
99
	int vals[3];
84
	int vals[3];
100
	token *t;
85
	token *t;
101
	for(int i=0; i < 3; i++){
86
	for(int i=0; i < 3; i++){
102
		t=loadValue(is);
87
		t=loadValue(is);
Line 111... Line 96...
111
	rgb.g=vals[1];
96
	rgb.g=vals[1];
112
	rgb.b=vals[2];
97
	rgb.b=vals[2];
113
	return true;
98
	return true;
114
}
99
}
115
//---------------------------------------------------------------------------------
100
//---------------------------------------------------------------------------------
116
bool bod_bob_parser::loadMatPair(token_stream& is, bob_dom_material5::pair& pair)
101
bool bod_bob_parser::loadMatPair(token_stream& is, bob_material5::pair& pair)
117
{
102
{
118
	int vals[2];
103
	int vals[2];
119
	
104
 
120
	for(int i=0; i < 2; i++){
105
	for(int i=0; i < 2; i++){
121
		if(!loadIntValue(is, vals + i))
106
		if(!loadIntValue(is, vals + i))
122
			return false;
107
			return false;
123
		
108
 
124
	}
109
	}
125
	pair.value=vals[0];
110
	pair.value=vals[0];
126
	pair.strength=vals[1];
111
	pair.strength=vals[1];
127
	return true;
112
	return true;
128
}
113
}
129
//---------------------------------------------------------------------------------
114
//---------------------------------------------------------------------------------
130
bool bod_bob_parser::loadMatPair(token_stream& is, bob_dom_material6::Small::pair& pair)
115
bool bod_bob_parser::loadMatPair(token_stream& is, bob_material6::Small::pair& pair)
131
{
116
{
132
	int i;
117
	int i;
133
	if((pair.texture=loadString(is, "texture name"))==0) return false;
118
	if((pair.texture=loadString(is, "texture name"))==0) return false;
134
	if(strcmp(pair.texture, "NULL")==0){
119
	if(strcmp(pair.texture, "NULL")==0){
135
		delete pair.texture; pair.texture=0;
120
		delete pair.texture; pair.texture=0;
Line 142... Line 127...
142
bool bod_bob_parser::checkImmediatePlacement(const bod_bob_parser::token *token1, const bod_bob_parser::token *token2)
127
bool bod_bob_parser::checkImmediatePlacement(const bod_bob_parser::token *token1, const bod_bob_parser::token *token2)
143
{
128
{
144
	if(token1->line!=token2->line || (token1->col + strlen(token1->getText())!=token2->col)){
129
	if(token1->line!=token2->line || (token1->col + strlen(token1->getText())!=token2->col)){
145
		error(token2, S_Error, "'%s' must be placed directly after '%s'", token2->getText(), token1->getText());
130
		error(token2, S_Error, "'%s' must be placed directly after '%s'", token2->getText(), token1->getText());
146
		return false;
131
		return false;
147
	}
132
	}
148
	else
133
	else
149
		return true;
134
		return true;
150
}
135
}
151
//---------------------------------------------------------------------------------
136
//---------------------------------------------------------------------------------
152
bool bod_bob_parser::loadMat(bob_dom_material5 *mat, token_stream &is)
137
bool bod_bob_parser::loadMat(bob_material5 *mat, token_stream &is)
153
{
138
{
154
	do{
139
	do{
155
		int i; 
140
		int i;
156
		bob_dom_material5::rgb rgb;
141
		bob_material5::rgb rgb;
157
		bob_dom_material5::pair pair;
142
		bob_material5::pair pair;
158
		
143
 
159
		if(!loadIntValue(is, &i)) break;
144
		if(!loadIntValue(is, &i)) break;
160
		mat->index=i;
145
		mat->index=i;
161
		if(!loadIntValue(is, &i)) break;
146
		if(!loadIntValue(is, &i)) break;
162
		mat->textureID=i;
147
		mat->textureID=i;
163
		if(!loadMatRGB(is, rgb)) break;
148
		if(!loadMatRGB(is, rgb)) break;
164
		mat->ambient=rgb;
149
		mat->ambient=rgb;
165
		if(!loadMatRGB(is, rgb)) break;
150
		if(!loadMatRGB(is, rgb)) break;
166
		mat->diffuse=rgb;
151
		mat->diffuse=rgb;
167
		if(!loadMatRGB(is, rgb)) break;
152
		if(!loadMatRGB(is, rgb)) break;
168
		mat->specular=rgb;
153
		mat->specular=rgb;
169
		if(mat->type!=bob_dom_material::mat1) {
154
		if(mat->type!=bob_material::mat1) {
170
			if(!loadIntValue(is, &i)) break;
155
			if(!loadIntValue(is, &i)) break;
171
			mat->transparency=i;
156
			mat->transparency=i;
172
			if(!loadIntValue(is, &i)) break;
157
			if(!loadIntValue(is, &i)) break;
173
			mat->selfIllumination=i;
158
			mat->selfIllumination=i;
174
			if(!loadMatPair(is, pair)) break;
159
			if(!loadMatPair(is, pair)) break;
Line 183... Line 168...
183
			mat->textureValue=i;
168
			mat->textureValue=i;
184
			if(!loadMatPair(is, pair)) break;
169
			if(!loadMatPair(is, pair)) break;
185
			mat->enviromentMap=pair;
170
			mat->enviromentMap=pair;
186
			if(!loadMatPair(is, pair)) break;
171
			if(!loadMatPair(is, pair)) break;
187
			mat->bumpMap=pair;
172
			mat->bumpMap=pair;
188
			
173
 
189
			if(mat->type==bob_dom_material::mat5){
174
			if(mat->type==bob_material::mat5){
190
				if(!loadMatPair(is, pair)) break;
175
				if(!loadMatPair(is, pair)) break;
191
				mat->lightMap=pair;
176
				mat->lightMap=pair;
192
			}
177
			}
193
		}
178
		}
194
		return true;
179
		return true;
195
	}
180
	}
196
	while(false);
181
	while(false);
197
	return false;
182
	return false;
198
}
183
}
199
//---------------------------------------------------------------------------------
184
//---------------------------------------------------------------------------------
200
bool bod_bob_parser::loadMat(bob_dom_material6 *mat, token_stream &is)
185
bool bod_bob_parser::loadMat(bob_material6 *mat, token_stream &is)
201
{
186
{
202
	int i; bool bRes=false;
187
	int i; bool bRes=false;
203
	do{
188
	do{
204
		if(!loadIntValue(is, &i)) break;
189
		if(!loadIntValue(is, &i)) break;
205
			mat->index=i;
190
			mat->index=i;
206
		
191
 
207
		if(!loadIntValue(is, &i)) break;
192
		if(!loadIntValue(is, &i)) break;
208
			mat->flags=i;
193
			mat->flags=i;
209
			
194
 
210
		if(mat->flags==bob_dom_material6::Big::flag)
195
		if(mat->flags==bob_material6::Big::flag)
211
			bRes=loadMaterial6Big(mat, is);
196
			bRes=loadMaterial6Big(mat, is);
212
		else
197
		else
213
			bRes=loadMaterial6Small(mat, is);
198
			bRes=loadMaterial6Small(mat, is);
214
	}
199
	}
215
	while(false);
200
	while(false);
216
	
201
 
217
	return bRes;
202
	return bRes;
218
}
203
}
219
//---------------------------------------------------------------------------------
204
//---------------------------------------------------------------------------------
220
bool bod_bob_parser::loadMaterial6Small(bob_dom_material6 *mat, token_stream &is)
205
bool bod_bob_parser::loadMaterial6Small(bob_material6 *mat, token_stream &is)
221
{
206
{
222
	int i;
207
	int i;
223
	bob_dom_material1::rgb rgb;
208
	bob_material1::rgb rgb;
224
	bob_dom_material1::pair int_pair;
209
	bob_material1::pair int_pair;
225
	bob_dom_material6::Small::pair pair;
210
	bob_material6::Small::pair pair;
226
	
211
 
227
	mat->small=new bob_dom_material6::Small();
212
	mat->small=new bob_material6::Small();
228
	do{
213
	do{
229
		if((mat->small->textureFile=loadString(is, "texture name: "))==0) break;
214
		if((mat->small->textureFile=loadString(is, "texture name: "))==0) break;
230
		if(strcmp(mat->small->textureFile, "NULL")==0) 
215
		if(strcmp(mat->small->textureFile, "NULL")==0)
231
			{ delete[] mat->small->textureFile; mat->small->textureFile=0; }
216
			{ delete[] mat->small->textureFile; mat->small->textureFile=0; }
232
		if(!loadMatRGB(is, rgb)) break;
217
		if(!loadMatRGB(is, rgb)) break;
233
		mat->small->ambient=rgb;
218
		mat->small->ambient=rgb;
234
		if(!loadMatRGB(is, rgb)) break;
219
		if(!loadMatRGB(is, rgb)) break;
235
		mat->small->diffuse=rgb;
220
		mat->small->diffuse=rgb;
236
		if(!loadMatRGB(is, rgb)) break;
221
		if(!loadMatRGB(is, rgb)) break;
237
		mat->small->specular=rgb;
222
		mat->small->specular=rgb;
Line 259... Line 244...
259
 
244
 
260
		if(!loadMatPair(is, pair)) break;
245
		if(!loadMatPair(is, pair)) break;
261
		mat->small->map4=pair;
246
		mat->small->map4=pair;
262
		if(!loadMatPair(is, pair)) break;
247
		if(!loadMatPair(is, pair)) break;
263
		mat->small->map5=pair;
248
		mat->small->map5=pair;
264
		
249
 
265
		short flags=0;
250
		short flags=0;
266
		if(mat->small->destinationBlend) flags&=0x2;
251
		if(mat->small->destinationBlend) flags&=0x2;
267
		if(mat->small->twoSided) flags&=0x10;
252
		if(mat->small->twoSided) flags&=0x10;
268
		if(mat->small->wireframe) flags&=0x8;
253
		if(mat->small->wireframe) flags&=0x8;
269
		mat->flags=flags;
254
		mat->flags=flags;
270
	
255
 
271
		return true;
256
		return true;
272
	}
257
	}
273
	while(false);
258
	while(false);
274
	return false;
259
	return false;
275
}
260
}
276
//---------------------------------------------------------------------------------
261
//---------------------------------------------------------------------------------
277
bool bod_bob_parser::loadMaterial6Big(bob_dom_material6 *mat, token_stream &is)
262
bool bod_bob_parser::loadMaterial6Big(bob_material6 *mat, token_stream &is)
278
{
263
{
279
	int count,i;
264
	int count,i;
280
	
265
 
281
	bob_dom_material6::Big *big=new bob_dom_material6::Big();
266
	bob_material6::Big *big=new bob_material6::Big();
282
	mat->big=big;
267
	mat->big=big;
283
	
268
 
284
	if(!loadIntValue(is, &i, "Technique idx: ")) return false;
269
	if(!loadIntValue(is, &i, "Technique idx: ")) return false;
285
	big->technique=i;
270
	big->technique=i;
286
	
271
 
287
	if((big->effect=loadString(is, "Effect name: "))==0) return false;
272
	if((big->effect=loadString(is, "Effect name: "))==0) return false;
288
	
273
 
289
	material6_value *val;
274
	material6_value *val;
290
	if(!loadIntValue(is, &count, "Value count: ")) return false;
275
	if(!loadIntValue(is, &count, "Value count: ")) return false;
291
	for(i=0; i < count; i++){
276
	for(i=0; i < count; i++){
292
		if((val=loadMat6Value(is))==0) return false;
277
		if((val=loadMat6Value(is))==0) return false;
293
		big->values.push_back(val);
278
		big->values.push_back(val);
294
	}
279
	}
295
	
280
 
296
	return true;
281
	return true;
297
}
282
}
298
//---------------------------------------------------------------------------------
283
//---------------------------------------------------------------------------------
299
material6_value * bod_bob_parser::loadMat6Value(token_stream& is)
284
material6_value * bod_bob_parser::loadMat6Value(token_stream& is)
300
{
285
{
301
	bool bRes=false;
286
	bool bRes=false;
302
	// name, type, value
287
	// name, type, value
303
	char *name, *strtype;
288
	char *name, *strtype;
304
	
289
 
305
	material6_value *val=new material6_value();
290
	material6_value *val=new material6_value();
306
	
291
 
307
	token_stream::token *typepos;
292
	token_stream::token *typepos;
308
	
293
 
309
	do{
294
	do{
310
		if((name=loadString(is, "Property name: "))==0) break;
295
		if((name=loadString(is, "Property name: "))==0) break;
311
		if(name[0]==0) {
296
		if(name[0]==0) {
312
			error(is.tok(), S_Error, "Empty property name");
297
			error(is.tok(), S_Error, "Empty property name");
313
			return false;
298
			return false;
314
		}
299
		}
315
		if((strtype=loadString(is, "Property type: "))==0) break;
300
		if((strtype=loadString(is, "Property type: "))==0) break;
316
		typepos=is.tok();
301
		typepos=is.tok();
317
		
302
 
318
		int type=-1;
303
		int type=-1;
319
		
304
 
320
		for(int i=0; i < material6_value::typeNameCount(); i++){
305
		for(int i=0; i < material6_value::typeNameCount(); i++){
321
			if(strcmp(strtype, material6_value::typeName(i))==0) {
306
			if(strcmp(strtype, material6_value::typeName(i))==0) {
322
				if(strtype[0]!=0)
307
				if(strtype[0]!=0)
323
					type=i;
308
					type=i;
324
				break;
309
				break;
325
			}
310
			}
326
		}
311
		}
327
		
312
 
328
		if(type==-1){
313
		if(type==-1){
329
			error(typepos, S_Error, "Unknown property type: \"%s\"", strtype);
314
			error(typepos, S_Error, "Unknown property type: \"%s\"", strtype);
330
			break;
315
			break;
331
		}
316
		}
332
		val->type=(material6_value::Type)type;
317
		val->type=(material6_value::Type)type;
333
		val->name=name; 
318
		val->name=name;
334
		name=0;
319
		name=0;
335
		
320
 
336
		double d;
321
		double d;
337
		switch(val->type){
322
		switch(val->type){
338
			case material6_value::typeBool: // nobreak
323
			case material6_value::typeBool: // nobreak
339
			case material6_value::typeLong:
324
			case material6_value::typeLong:
340
				bRes=loadIntValue(is, &val->val.i, "Property value: ");
325
				bRes=loadIntValue(is, &val->val.i, "Property value: ");
Line 356... Line 341...
356
				error(0, S_Error, "Don't know how to output type \"%s\"", strtype);
341
				error(0, S_Error, "Don't know how to output type \"%s\"", strtype);
357
				bRes=false;
342
				bRes=false;
358
		}
343
		}
359
		if(bRes==false)
344
		if(bRes==false)
360
			break;
345
			break;
361
			
346
 
362
		bRes=true;
347
		bRes=true;
363
	}
348
	}
364
	while(0);
349
	while(0);
365
	
350
 
366
	delete[] name; delete[] strtype;
351
	delete[] name; delete[] strtype;
367
	
352
 
368
	if(bRes==false) {
353
	if(bRes==false) {
369
		delete val;
354
		delete val;
370
		val=0;
355
		val=0;
371
	}
356
	}
372
	
357
 
373
	return val;
358
	return val;
374
}
359
}
375
//---------------------------------------------------------------------------------
360
//---------------------------------------------------------------------------------
376
bool bod_bob_parser::loadMaterial(bob_dom_bob *bob, token_stream& is)
361
bool bod_bob_parser::loadMaterial(bob_dom_bob *bob, token_stream& is)
377
{
362
{
378
	bob_dom_material5::materialType type;
363
	bob_material5::materialType type;
379
	
364
 
380
	token *t=is.tok();
365
	token *t=is.tok();
381
	
366
 
382
	if(t){
367
	if(t){
383
		if(strcmp(t->getText(), "MATERIAL6")==0)
368
		if(strcmp(t->getText(), "MATERIAL6")==0)
384
			type=bob_dom_material::mat6;
369
			type=bob_material::mat6;
385
		else if(strcmp(t->getText(), "MATERIAL5")==0)
370
		else if(strcmp(t->getText(), "MATERIAL5")==0)
386
			type=bob_dom_material::mat5;
371
			type=bob_material::mat5;
387
		else if(strcmp(t->getText(), "MATERIAL3")==0)
372
		else if(strcmp(t->getText(), "MATERIAL3")==0)
388
			type=bob_dom_material::mat3;
373
			type=bob_material::mat3;
389
		else if(strcmp(t->getText(), "MATERIAL")==0)
374
		else if(strcmp(t->getText(), "MATERIAL")==0)
390
			type=bob_dom_material5::mat1;
375
			type=bob_material5::mat1;
391
	}
376
	}
392
	
377
 
393
	if(t==NULL || t->type!=token::t_text){
378
	if(t==NULL || t->type!=token::t_text){
394
		error(t ? t : is.previous(), S_Error, "Expected material header (MATERIAL, MATERIAL3, MATERIAL5 or MATERIAL6)");
379
		error(t ? t : is.previous(), S_Error, "Expected material header (MATERIAL, MATERIAL3, MATERIAL5 or MATERIAL6)");
395
		return NULL;
380
		return NULL;
396
	}
381
	}
397
	t=(++is).tok();
382
	t=(++is).tok();
398
	if(t==NULL || t->type!=token::t_colon){
383
	if(t==NULL || t->type!=token::t_colon){
399
		error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->getText());
384
		error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->getText());
400
		return NULL;
385
		return NULL;
401
	}
386
	}
402
	if(!checkImmediatePlacement(is.previous(), is.tok()))
387
	if(!checkImmediatePlacement(is.previous(), is.tok()))
403
		return NULL;
388
		return NULL;
404
	
389
 
405
	++is;
390
	++is;
406
	
391
 
407
	bool bRes;
392
	bool bRes;
408
	bob_dom_material *mat;
393
	bob_material *mat;
409
	switch(type) {
394
	switch(type) {
410
		case bob_dom_material::mat6:
395
		case bob_material::mat6:
411
			mat=new bob_dom_material6();
396
			mat=new bob_material6();
412
			bRes=loadMat((bob_dom_material6*)mat, is);
397
			bRes=loadMat((bob_material6*)mat, is);
413
			break;
398
			break;
414
		default: // always mat5 because lower mats are not supported in binary form
399
		default: // always mat5 because lower mats are not supported in binary form
415
			mat=new bob_dom_material5();
400
			mat=new bob_material5();
416
			mat->type=type;
401
			mat->type=type;
417
			bRes=loadMat((bob_dom_material5*)mat, is);
402
			bRes=loadMat((bob_material5*)mat, is);
418
			break;
403
			break;
419
	}
404
	}
420
	
405
 
421
	if(bRes==false)
406
	if(bRes==false)
422
		delete mat;
407
		delete mat;
423
	else
408
	else
424
		bob->materials.push_back(mat);
409
		bob->materials.push_back(mat);
425
		
410
 
426
	return bRes;
411
	return bRes;
427
}
412
}
428
//---------------------------------------------------------------------------------
413
//---------------------------------------------------------------------------------
429
bool bod_bob_parser::loadBody(bob_dom_bob *bob, token_stream& is)
414
bool bod_bob_parser::loadBody(bob_dom_bob *bob, token_stream& is)
430
{
415
{
431
	static const char *context="Body: ";
416
	static const char *context="Body: ";
432
	bob_dom_body *body=bob->bodies.createChild();
417
	bob_body *body=bob->bodies.createChild();
433
	PointList list;
418
	VertexList list;
434
	
419
 
435
	deleteTempData();
420
	deleteTempData();
436
	
421
 
437
	loadIntValue(is, &(body->bodySize), context);
422
	loadIntValue(is, &(body->bodySize), context);
438
	
423
 
439
	if(!loadBones(body, is)){
424
	if(!loadBones(body, is)){
440
		bob->bodies.removeChild(--bob->bodies.end());
425
		bob->bodies.removeChild(--bob->bodies.end());
441
		return false;
426
		return false;
442
	}
427
	}
443
	if(!loadPoints(body, is, list)) {
428
	if(!loadVertices(body, is, list)) {
444
		bob->bodies.removeChild(--bob->bodies.end());
429
		bob->bodies.removeChild(--bob->bodies.end());
445
		return false;
430
		return false;
446
	}
431
	}
447
	
432
 
448
	if(!loadWeights(body, is)){
433
	if(!loadWeights(body, is)){
449
		bob->bodies.removeChild(--bob->bodies.end());
434
		bob->bodies.removeChild(--bob->bodies.end());
450
		return false;
435
		return false;
451
	}
436
	}
452
	
437
 
453
	if(m_weights.size() && m_weights.size()!=list.size()){
438
	if(m_weights.size() && m_weights.size()!=list.size()){
454
		error(0, S_Error, "Number of Weights (%d) does not match number of Points (%d)", m_weights.size(), list.size());
439
		error(0, S_Error, "Number of Weights (%d) does not match number of Points (%d)", m_weights.size(), list.size());
455
		bob->bodies.removeChild(--bob->bodies.end());
440
		bob->bodies.removeChild(--bob->bodies.end());
456
		return false;
441
		return false;
457
	}
442
	}
458
	
443
 
459
	// move the points to array so we can access them with index
444
	// move the points to array so we can access them with index
460
	m_points.resize(list.size());
445
	m_vertices.resize(list.size());
461
	int i=0;
446
	int i=0;
462
	for(PointList::iterator &it=list.begin(); it!=list.end(); ++it, ++i){
447
	for(VertexList::iterator &it=list.begin(); it!=list.end(); ++it, ++i){
463
		m_points[i]=*it;
448
		m_vertices[i]=*it;
464
	}
449
	}
465
	list.clear();
450
	list.clear();
-
 
451
 
-
 
452
	// reserve space in the vertex array (some of the vertices will be duplicated)
-
 
453
	body->vertices.new_vertices.reserve((size_t)(m_vertices.size() * 2));
-
 
454
	body->vertices.new_vertices.growby((size_t)(m_vertices.size() * 0.25));
466
	
455
 
467
	int endval;
456
	int endval;
468
	do{
457
	do{
469
		if(!loadPart(body, is)) {
458
		if(!loadPart(body, is)) {
470
			bob->bodies.removeChild(--bob->bodies.end());
459
			bob->bodies.removeChild(--bob->bodies.end());
471
			return false;
460
			return false;
472
		}
461
		}
473
		
462
 
474
		loadIntValue(is, &endval);
463
		loadIntValue(is, &endval);
475
		if(endval!=-99)
464
		if(endval!=-99)
476
			ungetValue(is);
465
			ungetValue(is);
477
	}
466
	}
478
	while(is.good() && endval!=-99); // -99 means end of body
467
	while(is.good() && endval!=-99); // -99 means end of body
479
	
468
 
480
	if(endval!=-99){
469
	if(endval!=-99){
481
		error(is.previous(), S_Error, "Unexpected end of document found while loading Body. Do you miss the '-99'?");
470
		error(is.previous(), S_Error, "Unexpected end of document found while loading Body. Do you miss the '-99'?");
482
		bob->bodies.removeChild(--bob->bodies.end());
471
		bob->bodies.removeChild(--bob->bodies.end());
483
		return false;
472
		return false;
484
	}
473
	}
485
	if(!flagsFromString(is, body->bodyFlags)){
474
	if(!flagsFromString(is, body->bodyFlags)){
486
		bob->bodies.removeChild(--bob->bodies.end());
475
		bob->bodies.removeChild(--bob->bodies.end());
487
		return false;
476
		return false;
488
	}
477
	}
-
 
478
 
-
 
479
	computeVertexTangents(*body);
489
	
480
 
490
	return true;
481
	return true;
491
}
482
}
492
//---------------------------------------------------------------------------------
483
//---------------------------------------------------------------------------------
493
bool bod_bob_parser::loadPoints(bob_dom_body *body, token_stream& is, PointList& points)
484
bool bod_bob_parser::loadVertices(bob_body *body, token_stream& is, VertexList& points)
494
{
485
{
495
	bool bEnd;
486
	bool bEnd;
496
	int x, y, z;
487
	int x, y, z;
497
	static const char *context="Point: ";
488
	static const char *context="Vertex: ";
498
	
489
 
499
	do{
490
	do{
500
		loadIntValue(is, &x, context);
491
		loadIntValue(is, &x, context);
501
		loadIntValue(is, &y, context);
492
		loadIntValue(is, &y, context);
502
		if(!loadIntValue(is, &z, context)) return false;
493
		if(!loadIntValue(is, &z, context)) return false;
503
		
494
 
504
		if(x==-1 && y==-1 && z==-1) { 
495
		if(x==-1 && y==-1 && z==-1) {
505
			bEnd=true; 
496
			bEnd=true;
506
			break; 
497
			break;
507
		}
498
		}
508
		
-
 
509
		__asm {
-
 
510
			fild x
-
 
511
			fdiv bob_dom_point::multiplier;
-
 
512
			fistp x
-
 
513
			
-
 
514
			fild y
-
 
515
			fdiv bob_dom_point::multiplier;
-
 
516
			fistp y
-
 
517
			
-
 
518
			fild z
-
 
519
			fdiv bob_dom_point::multiplier;
499
		/* SameVertices will take care of translating the BOD coords to BOB format */
520
			fistp z
-
 
521
		}
-
 
522
		points.push_back(new point_t(x, y, z));
500
		points.push_back(new SameVertices(x, y, z));
523
	}
501
	}
524
	while(is.good());
502
	while(is.good());
525
	
503
 
526
	if(!bEnd){
504
	if(!bEnd){
527
		error(is.previous(), S_Error, "Unexpected end of document found while loading Points. Do you miss the '-1;-1;-1;'?");
505
		error(is.previous(), S_Error, "Unexpected end of document found while loading Points. Do you miss the '-1;-1;-1;'?");
528
		return false;
506
		return false;
529
	}
507
	}
530
	
508
 
531
	return true;
509
	return true;
532
}
510
}
533
//---------------------------------------------------------------------------------
511
//---------------------------------------------------------------------------------
534
// load part - bunch of faces/uv's
512
// load part - bunch of faces/uv's
535
bool bod_bob_parser::loadPart(bob_dom_body *body, token_stream& is)
513
bool bod_bob_parser::loadPart(bob_body *body, token_stream& is)
536
{
514
{
537
	int matIdx;
515
	int matIdx;
538
	bool bRes=true;
516
	bool bRes=true;
539
	static const char *context="Parts: ";
517
	static const char *context="Parts: ";
540
	bool secUV=false;
518
	bool x3data=false;
541
	
519
 
542
	bob_dom_part *part=new bob_dom_part();
520
	bob_part *part=new bob_part();
543
	
521
 
544
	loadIntValue(is, &matIdx, context);
522
	loadIntValue(is, &matIdx, context);
545
	do{
523
	do{
-
 
524
		// no longer truth - negative number is direct texture ID of animated texture
546
		if(matIdx < 0)
525
		/*if(matIdx < 0)
547
			{ error(is.previous(), S_Error, "%sMaterial index must be >= 0", context); bRes=false; break; }
526
			{ error(is.previous(), S_Error, "%sMaterial index must be >= 0", context); bRes=false; break; }
-
 
527
		*/
548
		if(matIdx!=0 && ((size_t)matIdx > m_materials->size() - 1))
528
		if(matIdx > 0 && ((size_t)matIdx > m_materials->size() - 1))
549
			error(is.previous(), S_Warning, "%sMaterial index out of range: %d", context, matIdx);
529
			error(is.previous(), S_Warning, "%sMaterial index out of range: %d", context, matIdx);
550
			
530
 
551
		if((bRes=loadFace(matIdx, *body, *part, is))==false)
531
		if((bRes=loadFace(matIdx, *body, *part, is))==false)
552
			break;
532
			break;
553
		
533
 
554
		if(is.tok() && is.tok()->type==token::t_openInstrBlock) {
534
		if(is.tok() && is.tok()->type==token::t_openInstrBlock) {
555
			secUV=true;
535
			x3data = true;
556
			
536
 
557
			if((bRes=loadX3PartValues(++is, *part))==false)
537
			if((bRes = loadCollisionBoxData(++is, *part)) == false)
558
				break;
-
 
559
			
-
 
560
			if((bRes=loadSecondaryUVs(is, *part))==false) 
-
 
561
				break;
538
				break;
562
		}
539
		}
563
		
540
 
564
		loadIntValue(is, &matIdx, context);
541
		loadIntValue(is, &matIdx, context);
565
	}
542
	}
566
	while(matIdx!=-99 && is.good()); // -99 means end of part
543
	while(matIdx!=-99 && is.good()); // -99 means end of part
567
	
544
 
568
	if(bRes && matIdx!=-99){
545
	if(bRes && matIdx != -99){
569
		error(is.previous(), S_Error, "Unexpected end of document found while loading Part. Do you miss the '-99'?");
546
		error(is.previous(), S_Error, "Unexpected end of document found while loading Part. Do you miss the '-99'?");
570
		bRes=false;
547
		bRes = false;
571
	}
548
	}
572
	
549
 
573
	if(bRes)
550
	if(bRes)
574
		bRes=flagsFromString(is, part->flags);
551
		bRes = flagsFromString(is, part->flags);
575
		
552
 
-
 
553
	// set x3 flag if either we loaded x3 part values or settings::writeX3Data is set
576
	if(secUV)
554
	if(x3data || m_settings->writeX3Data())
577
		part->flags|=bob_dom_part::x3flag;
555
		part->flags|=bob_part::FLAG_X3;
578
		
556
 
579
	if(bRes)
557
	if(bRes)
580
		body->parts.push_back(part);
558
		body->parts.push_back(part);
581
	else
559
	else
582
		delete part;
560
		delete part;
583
		
561
 
584
	return bRes;
562
	return bRes;
585
};
563
};
586
//---------------------------------------------------------------------------------
564
//---------------------------------------------------------------------------------
587
bool bod_bob_parser::flagsFromString(token_stream& is, int& flags)
565
bool bod_bob_parser::flagsFromString(token_stream& is, int& flags)
588
{
566
{
589
	bool bRes;
567
	bool bRes;
590
	token *t=loadValue(is);
568
	token *t=loadValue(is);
591
	
569
 
592
	flags=0;
570
	flags=0;
593
	if(bRes=(t!=NULL)){
571
	if(bRes=(t!=NULL)){
594
		int len=(int)strlen(t->text);
572
		int len=(int)strlen(t->text);
595
		int val=1;
573
		int val=1;
596
		for(int i=len-1; i >= 0; i--, val<<=1 ){
574
		for(int i=len-1; i >= 0; i--, val<<=1 ){
Line 602... Line 580...
602
					break;
580
					break;
603
				default:
581
				default:
604
					error(is.previous(), S_Error, "Invalid flags definition. Expected binary number");
582
					error(is.previous(), S_Error, "Invalid flags definition. Expected binary number");
605
					bRes=false;
583
					bRes=false;
606
					break;
584
					break;
607
			}
585
			}
608
			if(bRes==false) break;
586
			if(bRes==false) break;
609
		}
587
		}
610
	}
588
	}
611
	return bRes;
589
	return bRes;
612
}
590
}
613
//---------------------------------------------------------------------------------
591
//---------------------------------------------------------------------------------
614
// load face - actual face and its uv's
592
// load face - actual face and its uv's
615
bool bod_bob_parser::loadFace(int matIdx, bob_dom_body& body, bob_dom_part& part, token_stream& is)
593
bool bod_bob_parser::loadFace(int matIdx, bob_body& body, bob_part& part, token_stream& is)
616
{
594
{
617
	int indexes[3];
595
	int indexes[3];
618
	int magic;
596
	int magic;
619
	int lastPntVal;
597
	int sgbits;
620
	double dtexX, dtexY;
598
	double dtexX, dtexY;
621
	int texX, texY;
-
 
622
	static const char *context="Part: ";
599
	static const char *context="Part: ";
623
	
600
 
624
	for(int i=0; i < 3; i++){
601
	for(int i=0; i < 3; i++){
625
		if(loadIntValue(is, indexes + i, context)){
602
		if(loadIntValue(is, indexes + i, context)){
626
			if(indexes[i] < 0 || (size_t)indexes[i] >= m_points.size()){
603
			if(indexes[i] < 0 || (size_t)indexes[i] >= m_vertices.size()){
627
				error(is.previous(), S_Error, "Point index out of range: point %d, index %d", i, indexes[i]);
604
				error(is.previous(), S_Error, "Point index out of range: point %d, index %d", i, indexes[i]);
628
				return false;
605
				return false;
629
			}
606
			}
630
		}
607
		}
631
		else
608
		else
632
			return false;
609
			return false;
633
	}
610
	}
-
 
611
 
-
 
612
	bool bRes=true;
-
 
613
 
-
 
614
	/*
-
 
615
		original (old) meaning of the 'magic' number (now I'm using flags)
-
 
616
		magic: -1 means no smoothing and no uv, -9 means no smoothing and uv
-
 
617
		        -17 means smoothing and no uv, -25 means smoothing and uv
-
 
618
	*/
634
	
619
	
635
	bool bRes=true;
-
 
636
	
-
 
637
	// magic: -1 means no smoothing and no uv, -9 means no smoothing and uv
-
 
638
	//        -17 means smoothing and no uv, -25 means smoothing and uv
-
 
639
	bRes&=loadIntValue(is, &magic, context);
620
	bRes&=loadIntValue(is, &magic, context);
-
 
621
 
640
	if(magic!=-9 &amp;&; magic!=-1)
622
	if(magic &gt;= 0){
-
 
623
		error(is.tok(), S_Error, "Faces are written using polygons not triangles - cannot continue");
-
 
624
		return false;
-
 
625
	}
-
 
626
 
-
 
627
	magic*=-1;
-
 
628
 
-
 
629
	if(magic & bob_part::BOD_FLAG_SGBITS)
641
		bRes&=loadIntValue(is, &lastPntVal, context);
630
		bRes&=loadIntValue(is, &sgbits, context);
642
	else
631
	else
643
		lastPntVal=0;
632
		sgbits=0;
644
	
633
 
645
	if(bRes==false) return false;
634
	if(bRes==false) return false;
646
	
635
 
647
	bob_dom_point *point;
636
	bob_vertex *vertex;
648
	bob_dom_face *face=new bob_dom_face();
637
	bob_face *face=new bob_face();
649
	
-
 
650
	bob_dom_point *points_ar[3];
638
	bob_vertex *points_ar[3];
651
	int  magic_ar[3];
-
 
652
	
639
 
653
	for(int i=0; i < 3; i++){
640
	for(int i=0; i < 3; i++){
654
		if(magic!=-17 && magic!=-1){
641
		if(magic & bob_part::BOD_FLAG_UV){
655
			loadDoubleValue(is, &dtexX, context);
642
			loadDoubleValue(is, &dtexX, context);
656
			bRes&=loadDoubleValue(is, &dtexY, context);
643
			bRes&=loadDoubleValue(is, &dtexY, context);
657
			
-
 
658
			// this is like texX=(int)(dtexX / bob_dom_part::multiplier) with rounding 'to nearest'
-
 
659
			__asm {
-
 
660
				fld dtexX
-
 
661
				fdiv bob_dom_part::multiplier
-
 
662
				fistp texX
-
 
663
				
-
 
664
				fld dtexY
-
 
665
				fdiv bob_dom_part::multiplier
-
 
666
				fistp texY
-
 
667
			}
-
 
668
		}
644
		}
669
		else{
645
		else{
670
			texX=0;
646
			dtexX=dtexY=0;
-
 
647
		}
-
 
648
 
671
			texY=0;
649
		/*
-
 
650
			look (or create) for vertex with same coords and same sgbits
672
		}
651
		*/
-
 
652
		SameSG_UVs *SGgroup=m_vertices[indexes[i]]->findTextureCoords(sgbits);
-
 
653
		uv_coord *uv=NULL;
673
		
654
		
-
 
655
		/*
-
 
656
			look for the same UV coords or use anything if no UV is specified
-
 
657
		*/
-
 
658
		if(magic & bob_part::BOD_FLAG_UV)
674
		texture_coords_t *coords;
659
			uv=SGgroup->findUV(dtexX, dtexY);
-
 
660
		else 
675
		texture_coord_t *coord=0;
661
			uv=SGgroup->findNullUV();
676
		
662
		
677
		coords=m_points[indexes[i]]->findTextureCoords(lastPntVal);
-
 
678
		
-
 
679
		// I can't remember why -9 is duplicated - it is because it does not have smoothing?
-
 
680
		// should -1 be also here?
-
 
681
		if(magic!=-9 /*&& magic!=-1 ?? */){
-
 
682
			coord=coords->findCoords(texX, texY);
-
 
683
		}
-
 
684
		if(coord==NULL){
663
		if(uv==NULL){
685
			coord=new texture_coord_t();
-
 
686
			coord->x=texX;
-
 
687
			coord->y=texY;
-
 
688
			coords->push_back(coord);
-
 
689
			
-
 
690
			point=new bob_dom_point();
664
			if(magic &; bob_part::BOD_FLAG_UV)
691
			point->x=m_points[indexes[i]]->x;
-
 
692
			point->y=m_points[indexes[i]]->y;
-
 
693
			point->z=m_points[indexes[i]]->z;
-
 
694
			point->textureCoords.left=texX;
-
 
695
			point->textureCoords.right=texY;
665
				uv=SGgroup->createUV(dtexX, dtexY);
696
			
666
			else
697
			point->values.push_back(lastPntVal);
667
				uv=SGgroup->createNullUV();
698
			
668
				
699
			coord->index=(int)body.points.new_points.size();
669
			vertex=uv->createBOBVertex();
700
			body.points.new_points.push_back(point);
-
 
701
			
-
 
702
			points_ar[i]=point; // this will be used to fetch values found in intruction block
-
 
703
			
670
			
-
 
671
			uv->vertexIndex=(int)body.vertices.new_vertices.size();
-
 
672
			body.vertices.new_vertices.push_back(vertex);
-
 
673
 
-
 
674
			points_ar[i]=vertex; // this will be used to fetch values found in intruction block
-
 
675
 
704
			// now insert the appropriate weight
676
			// now insert the appropriate weight
705
			if(m_weights.size())
677
			if(m_weights.size())
706
				body.weights.new_weights.push_back(new bob_dom_weight(*m_weights[indexes[i]]));
678
				body.weights.new_weights.push_back(new bob_weight(*m_weights[indexes[i]]));
707
		}
679
		}
708
		else
680
		else
709
			points_ar[i]=NULL;
681
			points_ar[i]=NULL;
710
		
682
 
711
		magic_ar[i]=magic;
-
 
712
		face->values[i]=coord->index;
683
		face->values[i]=uv->vertexIndex;
713
	}
684
	}
714
	face->values[3]=1;
685
	face->flags=1; // always 1 (or 0)
-
 
686
	
715
	part.facelist(matIdx)->push_back(face);
687
	part.facelist(matIdx)->push_back(face);
716
	
688
 
-
 
689
	bRes = loadSpecialValues(points_ar, is);
717
	
690
	
718
	return loadSpecialValues(points_ar, magic_ar, is);
691
	return bRes;
719
}
692
}
720
//---------------------------------------------------------------------------------
693
//---------------------------------------------------------------------------------
721
// load special values which may be "hidden" in instruction block after standard part definition
694
// load special values which may be "hidden" in instruction block after standard part definition
722
// example: /! { 1;2;3; } { 4;5;6; } { 7;8;9; } !/
695
// example: /! { 1;2;3; } { 4;5;6; } { 7;8;9; } !/
723
bool bod_bob_parser::loadSpecialValues(bob_dom_point *points[3], int magic[3], token_stream& is)
696
bool bod_bob_parser::loadSpecialValues(bob_vertex *points[3], token_stream& is)
724
{
697
{
725
	// we must now fill the special coordinates to the points
-
 
726
	// they will be either specified in instruction block or we will use default values
-
 
727
	
-
 
728
	bob_dom_point dummy_pnt;
698
	bob_vertex dummy_pnt;
729
	dummy_pnt.values.push_back(1);
-
 
730
	
699
 
731
	token *t=is.tok();
700
	token *t=is.tok();
732
	
701
 
733
	if(t && t->type==token::t_openInstrBlock){
702
	if(t && t->type==token::t_openInstrBlock){
734
		++is;
703
		++is;
-
 
704
		
735
		for(int i=0; i < 3; i++){
705
		t=is.tok();
736
			// if thte point was already loaded it is null, but we must still consume the values
706
		while(t != NULL && t->type != token::t_closeInstrBlock){
737
			// and check errors so I load them to dummy point
707
			if(t == NULL || t->type != token::t_text){
-
 
708
				error(t ? t : is.previous(), S_Error, "Expected identifier in instruction block.");
-
 
709
				return false;
-
 
710
			}
-
 
711
			
738
			if(points[i]!=NULL){
712
			if(strcmp(t->text, "N") == 0){
739
				if(!loadSpecialPointValues(is, points[i]))
713
				if(!loadFaceNormal(is, points))
-
 
714
					return false;
-
 
715
			}
-
 
716
			else if(strcmp(t->text, "XPINFO") == 0){
-
 
717
				t = (++is).tok();
-
 
718
				if(t == NULL || t->type != token::t_colon){
-
 
719
					error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->getText());
740
					return false;
720
					return false;
-
 
721
				}	
-
 
722
				++is;
-
 
723
				for(int i = 0; i < 3; i++){
-
 
724
					if(!loadSpecialPointValues(is, points[i]))
-
 
725
						return false;
-
 
726
				}
741
			}
727
			}
742
			else{
728
			else {
743
				if(!loadSpecialPointValues(is, &amp;dummy_pnt))
729
				error(t, S_Error, "Unexpected identifier in instruction block: '%s'&quot;, t);
744
					return false;
730
				return false;
745
				dummy_pnt.values.clear();
-
 
746
				// the "last value" must be there otherwise loadSpecialPointValues would fail
-
 
747
				dummy_pnt.values.push_back(1); 
-
 
748
			}
731
			}
-
 
732
			t=is.tok();
749
		}
733
		}
750
		t=is.tok();
-
 
751
		if(t==NULL || t->type!=token::t_closeInstrBlock){
734
		if(t==NULL || t->type!=token::t_closeInstrBlock){
752
			error(t ? t : is.previous(), S_Error, "Expected end of instruction block '!/' after '%s'", is.previous());
735
			error(t ? t : is.previous(), S_Error, "Expected end of instruction block '!/' after '%s'", is.previous());
753
			return false;
736
			return false;
754
		}
737
		}
755
		++is;
738
		++is;
756
	}
-
 
757
	// use default values
-
 
758
	else{
-
 
759
		int count;
-
 
760
		for(int i=0; i < 3; i++){
-
 
761
			if(points[i]==NULL) continue;
-
 
762
			bob_dom_point::iterator last=--points[i]->values.end();
-
 
763
			
-
 
764
			// megic ==-17 means we are not using mateial so we can use the smallest point type 0x19
-
 
765
			if(magic[i]==-17){
-
 
766
				points[i]->type=0x19;
-
 
767
				count=1;
-
 
768
			}
-
 
769
			else{
-
 
770
				points[i]->type=0x1B;
-
 
771
				count=3;
-
 
772
			}
-
 
773
			for(int j=0; j < count; j++){
-
 
774
				points[i]->values.insert(last, 0);
-
 
775
			}
-
 
776
		}
-
 
777
	}
739
	}
778
	return true;
740
	return true;
779
}
741
}
780
//---------------------------------------------------------------------------------
742
//---------------------------------------------------------------------------------
781
// load one block from extra info in instruction block 
743
// load one block from extra info in instruction block
782
// example: { 1; 2; 3; }
744
// example: { 1; 2; 3; }
-
 
745
 
-
 
746
// point can be null!
783
bool bod_bob_parser::loadSpecialPointValues(token_stream& is, bob_dom_point *point)
747
bool bod_bob_parser::loadSpecialPointValues(token_stream& is, bob_vertex *point)
784
{
748
{
785
	double d;
-
 
786
	int v;
-
 
787
	static const char *context="Part - Extra point info: ";
749
	static const char *context="Part - Extra point info: ";
788
	
-
 
789
	// point already has the "last point value" pushed into list, so we must
-
 
790
	// push new values before it
-
 
791
	bob_dom_point::iterator &last=--point->values.end();
-
 
792
	
750
 
793
	token *t=is.tok();
751
	token *t=is.tok();
794
	if(t==NULL || t->type!=token::t_openBracket){
752
	if(t==NULL || t->type!=token::t_openCrBracket){
795
		error(t ? t : is.previous(), S_Error, "Expected beginning of block after '%s'", is.previous()->getText());
753
		error(t ? t : is.previous(), S_Error, "Expected beginning of block after '%s'", is.previous()->getText());
796
		return false;
754
		return false;
797
	}
755
	}
798
	++is;
756
	++is;
-
 
757
	
-
 
758
	double x, y;
-
 
759
	
799
	while((t=is.tok())!=NULL && !(t->type==token::t_closeBracket || t-&gt;type==token::t_closeInstrBlock)){
760
	if(!loadDoubleValue(is, &amp;x, context))
-
 
761
		return false;
800
		if(!loadDoubleValue(is, &d, context))
762
	if(!loadDoubleValue(is, &y, context))
801
			return false;
763
		return false;
-
 
764
 
-
 
765
	if(point != NULL){
-
 
766
		point->weirdCoords.x = x;
-
 
767
		point->weirdCoords.y = y;
802
		
768
		
803
		__asm{
-
 
804
			fld d
-
 
805
			fdiv bob_dom_part::multiplier
-
 
806
			fistp v
-
 
807
		}
-
 
808
		
-
 
809
		point->values.insert(last, v);
769
		point->flags|=bob_vertex::FLAG_WEIRD_STUFF;
810
	}
770
	}
-
 
771
 
811
	if(t==NULL || t->type!=token::t_closeBracket){
772
	if(is.tok()==NULL || is.tok()->type!=token::t_closeCrBracket){
812
		if(t==NULL)
773
		if(is.tok()==NULL)
813
			error(is.previous(), S_Error, "Unexpected end of document found while loading extra point info. Do you miss the '}'?");
774
			error(is.previous(), S_Error, "Unexpected end of document found while loading extra point info. Do you miss the '}'?");
814
		else
775
		else
815
			error(t, S_Error, "Unexpected '%s' found while loading extra point info", t->getText());
776
			error(t, S_Error, "Unexpected '%s' found while loading extra point info", t->getText());
816
		return false;
777
		return false;
817
	}
-
 
818
	
-
 
819
	switch(point->values.size()){
-
 
820
		case 2:
-
 
821
			point->type=0x19;
-
 
822
			break;
-
 
823
		case 4:
-
 
824
			point->type=0x1B;
-
 
825
			break;
-
 
826
		case 6:
-
 
827
			point->type=0x1F;
-
 
828
			break;
-
 
829
		default:
-
 
830
			error(t, S_Error, "Invalid number of values in extra point info block (%d) must be 1, 3 or 5", point->values.size() - 1);
-
 
831
			return false;
-
 
832
	}
778
	}
-
 
779
 
833
	++is;
780
	++is;
834
	
781
 
835
	return true;
782
	return true;
836
}
783
}
837
//---------------------------------------------------------------------------------
784
//---------------------------------------------------------------------------------
838
bool bod_bob_parser::loadBones(bob_dom_body *body, token_stream& is)
785
bool bod_bob_parser::loadBones(bob_body *body, token_stream& is)
839
{
786
{
840
	const token *t=is.tok();
787
	const token *t=is.tok();
841
	static const char *context2="Bones: ";
788
	static const char *context2="Bones: ";
842
	static const char *context="Bone: ";
789
	static const char *context="Bone: ";
843
	
790
 
844
	if(!(t && t->type==token::t_text && strcmp(t->text, "BONES")==0))
791
	if(!(t && t->type==token::t_text && strcmp(t->text, "BONES")==0))
845
		return true;
792
		return true;
846
		
793
 
847
	t=(++is).tok();
794
	t=(++is).tok();
848
	if(t==NULL || t->type!=token::t_colon){
795
	if(t==NULL || t->type!=token::t_colon){
849
		error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->getText());
796
		error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->getText());
850
		return false;
797
		return false;
851
	}
798
	}
852
	if(!checkImmediatePlacement(is.previous(), t))
799
	if(!checkImmediatePlacement(is.previous(), t))
853
		return false;
800
		return false;
854
	
801
 
855
	int count;
802
	int count;
856
	if(!loadIntValue(++is, &count, context2))
803
	if(!loadIntValue(++is, &count, context2))
857
		return false;
804
		return false;
858
	
805
 
859
	char *name;
806
	char *name;
860
	for(int i=0; i < count; i++){
807
	for(int i=0; i < count; i++){
861
		name=loadString(is, context);
808
		name=loadString(is, context);
862
		if(name==NULL) return false;
809
		if(name==NULL) return false;
863
		body->bones.push_back(name);
810
		body->bones.push_back(name);
864
	}
811
	}
865
	
812
 
866
	return !is.fail();
813
	return !is.fail();
867
}
814
}
868
//---------------------------------------------------------------------------------
815
//---------------------------------------------------------------------------------
869
// load the weights to temporary array. Weights from this array will then be inflated and added to body
816
// load the weights to temporary array. Weights from this array will then be inflated and added to body
870
bool bod_bob_parser::loadWeights(bob_dom_body *body, token_stream& is)
817
bool bod_bob_parser::loadWeights(bob_body *body, token_stream& is)
871
{
818
{
872
	const token *t=is.tok();
819
	const token *t=is.tok();
873
	static const char *context="Weight: ";
820
	static const char *context="Weight: ";
874
	static const char *context2="Weights: ";
821
	static const char *context2="Weights: ";
875
	
822
 
876
	if(!(t && t->type==token::t_text && strcmp(t->text, "WEIGHTS")==0))
823
	if(!(t && t->type==token::t_text && strcmp(t->text, "WEIGHTS")==0))
877
		return true;
824
		return true;
878
		
825
 
879
	int count;
826
	int count;
880
	if(!loadIntValue(++is, &count, context2))
827
	if(!loadIntValue(++is, &count, context2))
881
		return false;
828
		return false;
882
	
829
 
883
	bool bRes=true;
830
	bool bRes=true;
884
	int v; double d;
831
	int v; double d;
885
	bob_dom_weight *w;
832
	bob_weight *w;
886
	
833
 
887
	m_weights.resize(count, 0);
834
	m_weights.resize(count, 0);
888
	
835
 
889
	for(int i=0; i < count; i++){
836
	for(int i=0; i < count; i++){
890
		w=new bob_dom_weight();
837
		w=new bob_weight();
891
		do{
838
		do{
892
			if(!loadIntValue(is, &v, context)) 
839
			if(!loadIntValue(is, &v, context))
893
				{ bRes=false; break; }
840
				{ bRes=false; break; }
894
			if(v==-1) 
841
			if(v==-1)
895
				break;
842
				break;
896
				
843
 
897
			if(v < 0 || (size_t)v >= body->bones.size()){
844
			if(v < 0 || (size_t)v >= body->bones.size()){
898
				error(is.previous(), S_Error, "Weight: Bone index out of range (%d)", v);
845
				error(is.previous(), S_Error, "Weight: Bone index out of range (%d)", v);
899
				{ bRes=false; break; }
846
				{ bRes=false; break; }
900
			}
847
			}
901
			
848
 
902
			if(!loadDoubleValue(is, &d, context)) 
849
			if(!loadDoubleValue(is, &d, context))
903
				{ bRes=false; break; }
850
				{ bRes=false; break; }
904
			
851
 
905
			bob_dom_weight::value val;
852
			bob_weight::value val;
906
			val.boneIdx=v;
853
			val.boneIdx=v;
907
			
854
 
908
			__asm{
855
			__asm{
-
 
856
				/* 
909
				// val.boneCoefficient = bob_dom_weight::value::multiplier * d
857
					val.boneCoefficient = bob_weight::value::multiplier * d 
-
 
858
				*/
910
				fild bob_dom_weight::value::multiplier
859
				fild bob_weight::value::MULTIPLIER
911
				fmul d
860
				fmul d
912
				fistp val.boneCoefficient
861
				fistp val.boneCoefficient
913
			}
862
			}
914
			w->values.push_back(val);
863
			w->values.push_back(val);
915
		}
864
		}
916
		while(!is.fail());
865
		while(!is.fail());
917
		if(is.fail()){
866
		if(is.fail()){
918
			error(is.previous(), S_Error, "Unexpected end of document found while loading Weights. Do you miss the '-1'?");
867
			error(is.previous(), S_Error, "Unexpected end of document found while loading Weights. Do you miss the '-1'?");
919
			bRes=false;
868
			bRes=false;
920
		}
869
		}
921
		if(bRes==false){
870
		if(bRes==false){
922
			delete w;
871
			delete w;
923
			break;
872
			break;
924
		}
873
		}
925
		m_weights[i]=w;
874
		m_weights[i]=w;
926
	}
875
	}
927
	if(bRes){
876
	if(bRes){
928
		if(!loadIntValue(is, &v, context2)) 
877
		if(!loadIntValue(is, &v, context2))
929
			bRes=false;
878
			bRes=false;
930
		else if(v!=-1){
879
		else if(v!=-1){
931
			error(is.previous(), S_Error, "Expected '-1' after end of Weights");
880
			error(is.previous(), S_Error, "Expected '-1' after end of Weights");
932
			bRes=false;
881
			bRes=false;
933
		}
882
		}
934
	}
883
	}
935
	return bRes;
884
	return bRes;
936
}
885
}
937
//---------------------------------------------------------------------------------
886
//---------------------------------------------------------------------------------
938
bool bod_bob_parser::loadSecondaryUVs(token_stream& is, bob_dom_part& part)
887
bool bod_bob_parser::loadCollisionBoxData(token_stream& is, bob_part& part)
-
 
888
{
-
 
889
	static char *context="Collision box: ";
-
 
890
	static char *HDR="COLLISION_BOX";
-
 
891
 
-
 
892
	if(is.tok()==NULL || is.tok()->type!=token::t_text || strcmp(is.tok()->text, HDR)!=0) {
-
 
893
		error(is.tok() ? is.tok() : is.previous(), S_Error, "Expected '%s' here", HDR);
-
 
894
		return false;
-
 
895
	}
-
 
896
	if((++is).tok()==NULL || is.tok()->type!=token::t_colon){
-
 
897
		error(is.tok() ? is.tok() : is.previous(), S_Error, "Expected ':' after '%s'", HDR);
-
 
898
		return false;
-
 
899
	}
-
 
900
 
-
 
901
	++is;
-
 
902
 
-
 
903
	loadDoubleValue(is, &part.collisionBox.boxOffset.x, "Box offset");
-
 
904
	loadDoubleValue(is, &part.collisionBox.boxOffset.y, "Box offset");
-
 
905
	if(!loadDoubleValue(is, &part.collisionBox.boxOffset.z, "Box offset"))
-
 
906
		return false;
-
 
907
		
-
 
908
	if(!loadDoubleValue(is, &part.collisionBox.sphereDiameter, "Sphere diameter"))
-
 
909
		return false;
-
 
910
		
-
 
911
	loadDoubleValue(is, &part.collisionBox.boxSize.x, "Box size");
-
 
912
	loadDoubleValue(is, &part.collisionBox.boxSize.y, "Box size");
-
 
913
	if(!loadDoubleValue(is, &part.collisionBox.boxSize.z, "Box size"))
-
 
914
		return false;
-
 
915
	
-
 
916
	part.collisionBox.sphereOffset = part.collisionBox.boxOffset;
-
 
917
	
-
 
918
	if(is.tok()==NULL || is.tok()->type!=token::t_closeInstrBlock){
-
 
919
		error(is.tok() ? is.tok() : is.previous(), S_Error, "Expected '!/' after end of Collision box");
-
 
920
		return false;
-
 
921
	}
-
 
922
	++is;
-
 
923
	return true;
-
 
924
}
-
 
925
//---------------------------------------------------------------------------------
-
 
926
bool bod_bob_parser::loadFaceNormal(token_stream& is, bob_vertex *points[3])
-
 
927
{
-
 
928
	token *t;
-
 
929
	t=is.tok();
-
 
930
	if(t==NULL || t->type!=token::t_text || *t->text!='N'){
-
 
931
		error(t, S_Error, "Error loading face normal: expecting 'N:'");
-
 
932
		return false;
-
 
933
	}
-
 
934
	t=(++is).tok();
-
 
935
	if(t==NULL || t->type!=token::t_colon){
-
 
936
		error(t, S_Error, "Expecting ':' after '%'", is.previous()->getText());
-
 
937
		return false;
-
 
938
	}
-
 
939
	++is;
-
 
940
 
-
 
941
	t = is.tok();
-
 
942
	if(t == NULL || t->type != token::t_openCrBracket){
-
 
943
		error(t ? t : is.previous(), S_Error, "Expected beginning of block after '%s'", is.previous()->getText());
-
 
944
		return false;
-
 
945
	}
-
 
946
	
-
 
947
	++is;
-
 
948
	
-
 
949
	// buffer for normals - contains either 1 or 3 records
-
 
950
	normal_vector normals[3];
-
 
951
	
-
 
952
	int i;
-
 
953
	// for each vertex
-
 
954
	for(i = 0; i < 3; i++){
-
 
955
		double d[3];
-
 
956
		
-
 
957
		// load the vertex normal
-
 
958
		for(int j=0; j < 3; j++){
-
 
959
			if(!loadDoubleValue(is, d + j, "Face normal: "))
-
 
960
				return false;
-
 
961
		}
-
 
962
		normals[i] = normal_vector(d[0], d[1], d[2]);
-
 
963
		
-
 
964
		t = is.tok();
-
 
965
		// bail out if end of block was reached - case of short (3 numbers) normal block
-
 
966
		if(i == 0 && t && t->type == token::t_closeCrBracket)
-
 
967
			break;
-
 
968
	}	
-
 
969
	int max = i > 0 ? 2 : 0;
-
 
970
	for(i = 0; i < 3; i++){
-
 
971
		if(points[i]!=NULL)
-
 
972
			points[i]->normalVector = normals[__min(i, max)];
-
 
973
	}
-
 
974
	
-
 
975
	if(t == NULL || t->type != token::t_closeCrBracket){
-
 
976
		error(t ? t : is.previous(), S_Error, "Expected end of block after '%s'", is.previous()->getText());
-
 
977
		return false;
-
 
978
	}
-
 
979
	++is;
-
 
980
	
-
 
981
	return true;
-
 
982
}
-
 
983
//---------------------------------------------------------------------------------
-
 
984
/*
-
 
985
	computation taken from C4 3D engine (http://www.terathon.com/code/tangent.php)
-
 
986
*/
-
 
987
void bod_bob_parser::computeVertexTangents(bob_body& body)
939
{
988
{
-
 
989
	typedef ext::array<bob_vertex*> vertex_array;
940
	bool bRes;
990
	
-
 
991
	bob_vertices::VertexArray &vertices=body.vertices.new_vertices;
941
	do{
992
	
-
 
993
	// stuff for the computation
-
 
994
	vertex v1, v2, v3; // vertices
942
		if((bRes=loadSecondaryUVRecord(is, part))==false) break;
995
	geometry::point2d<;double> w1, w2, w3; // uv coords
-
 
996
	int i1, i2, i3; // vertex indexes
943
	}
997
	
944
	while(is.tok() && is.tok()->type!=token::t_closeInstrBlock);
998
	vector *tmp_tangents=new vector[vertices.size()];
945
	
999
	
-
 
1000
	// every part in body
-
 
1001
	for(bob_parts::iterator &part_it=body.parts.begin(); part_it!=body.parts.end(); part_it++){
-
 
1002
		// every face list in a part
-
 
1003
		for(bob_part::iterator &facelist_it=part_it->begin(); facelist_it!=part_it->end(); facelist_it++){
-
 
1004
			// every face in face list
-
 
1005
			for(bob_face_list::iterator &face_it=facelist_it->begin(); face_it!=facelist_it->end(); ++face_it){
-
 
1006
				i1=face_it->values[0]; i2=face_it->values[1]; i3=face_it->values[2];
946
	if(bRes){
1007
				
947
		bRes=(is.tok() && is.tok()->;type==token::t_closeInstrBlock);
1008
				v1=*vertices[i1]; v2=*vertices[i2]; v3=*vertices[i3];
-
 
1009
				w1=vertices[i1]->textureCoords; w2=vertices[i2]->textureCoords; w3=vertices[i3]->textureCoords;
-
 
1010
				
-
 
1011
				double x1 = v2.x - v1.x;
-
 
1012
				double x2 = v3.x - v1.x;
-
 
1013
				double y1 = v2.y - v1.y;
-
 
1014
				double y2 = v3.y - v1.y;
-
 
1015
				double z1 = v2.z - v1.z;
-
 
1016
				double z2 = v3.z - v1.z;
-
 
1017
		    
-
 
1018
				double s1 = w2.x - w1.x;
-
 
1019
				double s2 = w3.x - w1.x;
-
 
1020
				double t1 = w2.y - w1.y;
-
 
1021
				double t2 = w3.y - w1.y;
-
 
1022
		    
-
 
1023
				double cp=s1 * t2 - s2 * t1;
-
 
1024
		    
948
		if(bRes==false)
1025
				if(cp!=0) {
-
 
1026
					double r = 1.0 / cp;
949
			error(is.tok() ? is.tok() : is.previous(), S_Error, "Unexpected end of document found while loading secondary UV's. Do you miss the '!/'?");
1027
					vector sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
-
 
1028
									(t2 * z1 - t1 * z2) * r);
950
		else
1029
					
-
 
1030
					tmp_tangents[i1] += sdir;
-
 
1031
					tmp_tangents[i2] += sdir;
-
 
1032
					tmp_tangents[i3] += sdir;
951
			++is;
1033
				}
-
 
1034
			}
-
 
1035
		}
952
	}
1036
	}
953
	return bRes;
-
 
954
}
-
 
955
//---------------------------------------------------------------------------------
-
 
956
bool bod_bob_parser::loadSecondaryUVRecord(token_stream& is, bob_dom_part& part)
-
 
957
{
-
 
958
	int matIdx, pointIdx;
-
 
959
	bool bRes=false;
-
 
960
	double d;
-
 
961
	bob_face_list *faces;
-
 
962
	bob_x3uv *uv=new bob_x3uv();
-
 
963
	
1037
	
964
	do{
-
 
965
		if(!loadIntValue(is, &matIdx, "")) break;
-
 
966
		if(!loadIntValue(is, &pointIdx, "")) break;
-
 
967
		for(int i=0; i < 6; i++){
1038
	for(vertex_array::size_type i=0; i < vertices.size(); i++){
968
			if((bRes=loadDoubleValue(is, &d, "&quot;))==false) break;
1039
		const vector& n=vertices[(vertex_array::difference_type)i]-&gt;normalVector;
969
			uv-&gt;values[i]=(float) d;
1040
		const vector&amp; t=tmp_tangents[i];
970
		}
-
 
971
		uv->idx=pointIdx;
-
 
972
		
1041
		
973
		faces=part[matIdx];
1042
		if(!t.isZero()){
974
		if(faces==NULL){
1043
			// Gram-Schmidt orthogonalize
975
			error(is.tok(), S_Error, "Secondary UVs: Face list with material idx %d not found&quot;, matIdx);
1044
			vertices[(vertex_array::difference_type)i]-&gt;tangentVector = (t - n * n.dot(t)).normalize();
976
			break;
-
 
977
		}
1045
		}
978
		faces->x3uvlist.push_back(uv);
-
 
979
		
-
 
980
		bRes=true;
-
 
981
	}
1046
	}
982
	while(0);
-
 
983
	if(bRes==false)
-
 
984
		delete uv;
-
 
985
		
-
 
986
	return bRes;
-
 
987
}
-
 
988
//---------------------------------------------------------------------------------
-
 
989
bool bod_bob_parser::loadX3PartValues(token_stream& is, bob_dom_part& part)
-
 
990
{
-
 
991
	static char *context="X3 part values: ";
-
 
992
	static char *hdr="PART_VALUES_RAW";
-
 
993
	
1047
	
994
	if(is.tok()==NULL || is.tok()->type!=token::t_text || strcmp(is.tok()->text, "PART_VALUES_RAW")!=0) {
-
 
995
		error(is.tok() ? is.tok() : is.previous(), S_Error, "Expected '%s' here", hdr);
-
 
996
		return false;
-
 
997
	}
-
 
998
	if((++is).tok()==NULL || is.tok()->type!=token::t_colon){
-
 
999
		error(is.tok() ? is.tok() : is.previous(), S_Error, "Expected ':' after '%s'", hdr);
-
 
1000
		return false;
1048
	delete[] tmp_tangents;
1001
	}
-
 
1002
	
-
 
1003
	++is;
-
 
1004
	
-
 
1005
	int v;
-
 
1006
	bool bRes;
-
 
1007
	
-
 
1008
	for(int i=0; i < 10; i++){
-
 
1009
		if((bRes=loadIntValue(is, &v, context))==false) 
-
 
1010
			break;
-
 
1011
		part.values[i]=v;
-
 
1012
	}
-
 
1013
	return bRes;
-
 
1014
}
1049
}
1015
//---------------------------------------------------------------------------------
1050
//---------------------------------------------------------------------------------