Subversion Repositories spk

Rev

Rev 1 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
#include "bod_bob_parser.h"
2
#include "../common/strutils.h"
3
//---------------------------------------------------------------------------------
4
bool bod_bob_parser::compile(token_stream& is, bob_dom_obinaryfilestream& os, bool bEmbedded)
5
{
6
	bob_dom_bob *bob=new bob_dom_bob(m_settings);
7
	bob=loadBOB(is, bEmbedded);
8
	if(bob)
9
		bob->toFile(os);
10
	delete bob;
11
	return bob!=NULL;
12
}
13
//---------------------------------------------------------------------------------
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)
18
{
19
	token *t;
20
	bob_dom_bob *bob=new bob_dom_bob(m_settings);
21
	bool abort=false;
22
 
23
	while((t=is.tok()) && t->type==token::t_hdrinfo){
24
		if(bob->info.text()!=0)
25
			error(is.tok(), S_Warning, "Header info already defined, last value will be used");
26
		bob->info.text(t->text);
27
		++is;
28
	}
29
 
30
	// first load material definitions, break on first numeric token
31
	while((t=is.tok()) && t->type!=token::t_closeBracket){
32
		if(t->type!=token::t_text){
33
			error(t, S_Error, "Unexpected here: '%s'", t->getText());
34
			abort=true; break;
35
		}
36
		if(isinteger(t->text)) break;
37
 
38
		//if(strcmp(t->text, "MATERIAL5")==0 || strcmp(t->text, "MATERIAL3")==0 || strcmp(t->text, "MATERIAL")==0){
39
		if(ISMATERIAL(t->text)){
40
			if(!loadMaterial(bob, is)){
41
				abort=true; break;
42
			}
43
		}
44
		else{
45
			error(t, S_Error, "Unexpected here '%s'", t->getText());
46
			abort=true; break;
47
		}
48
	}
49
 
50
	// now load the body definition: body size, points, parts
51
	if(!abort){
52
		m_materials=&(bob->materials);
53
		do{
54
			if(abort=(loadBody(bob, is)==false)) break;
55
 
56
			if(bEmbedded){
57
				if(is.tok()==NULL){
58
					error(is.previous(), S_Error, "Unexpected end of document found while loading embedded BOB - do you miss the '}'?");
59
					abort=true; break;
60
				}
61
				else if(is.tok()->type==token::t_closeBracket)
62
					break;
63
			}
64
			else if(is.eof())
65
				break;
66
		}
67
		while(1); // while what? while '}' if embedded or while eof if standalone
68
	}
69
 
70
	if(abort){
71
		delete bob;
72
		bob=NULL;
73
	}
74
 
75
	++is; // advance past the close bracket (if embedded)
76
 
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;
95
}
96
//---------------------------------------------------------------------------------
97
bool bod_bob_parser::loadMatRGB(token_stream& is, bob_dom_material5::rgb& rgb)
98
{
99
	int vals[3];
100
	token *t;
101
	for(int i=0; i < 3; i++){
102
		t=loadValue(is);
103
		if(t==NULL) return false;
104
		if(!isinteger(t->text)){
105
			error(t, S_Error, "Expected integer value at position %d in RBG", i);
106
			return false;
107
		}
108
		vals[i]=atoi(t->text);
109
	}
110
	rgb.r=vals[0];
111
	rgb.g=vals[1];
112
	rgb.b=vals[2];
113
	return true;
114
}
115
//---------------------------------------------------------------------------------
116
bool bod_bob_parser::loadMatPair(token_stream& is, bob_dom_material5::pair& pair)
117
{
118
	int vals[2];
119
 
120
	for(int i=0; i < 2; i++){
121
		if(!loadIntValue(is, vals + i))
122
			return false;
123
 
124
	}
125
	pair.value=vals[0];
126
	pair.strength=vals[1];
127
	return true;
128
}
129
//---------------------------------------------------------------------------------
130
bool bod_bob_parser::loadMatPair(token_stream& is, bob_dom_material6::Small::pair& pair)
131
{
132
	int i;
133
	if((pair.texture=loadString(is, "texture name"))==0) return false;
134
	if(strcmp(pair.texture, "NULL")==0){
135
		delete pair.texture; pair.texture=0;
136
	}
137
	if(loadIntValue(is, &i, "texture strength")==false) return false;
138
	pair.strength=i;
139
	return true;
140
}
141
//---------------------------------------------------------------------------------
142
bool bod_bob_parser::checkImmediatePlacement(const bod_bob_parser::token *token1, const bod_bob_parser::token *token2)
143
{
144
	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());
146
		return false;
147
	}
148
	else
149
		return true;
150
}
151
//---------------------------------------------------------------------------------
152
bool bod_bob_parser::loadMat(bob_dom_material5 *mat, token_stream &is)
153
{
154
	do{
155
		int i; 
156
		bob_dom_material5::rgb rgb;
157
		bob_dom_material5::pair pair;
158
 
159
		if(!loadIntValue(is, &i)) break;
160
		mat->index=i;
161
		if(!loadIntValue(is, &i)) break;
162
		mat->textureID=i;
163
		if(!loadMatRGB(is, rgb)) break;
164
		mat->ambient=rgb;
165
		if(!loadMatRGB(is, rgb)) break;
166
		mat->diffuse=rgb;
167
		if(!loadMatRGB(is, rgb)) break;
168
		mat->specular=rgb;
169
		if(mat->type!=bob_dom_material::mat1) {
170
			if(!loadIntValue(is, &i)) break;
171
			mat->transparency=i;
172
			if(!loadIntValue(is, &i)) break;
173
			mat->selfIllumination=i;
174
			if(!loadMatPair(is, pair)) break;
175
			mat->shininess=pair;
176
			if(!loadIntValue(is, &i)) break;
177
			mat->destinationBlend=i!=0;
178
			if(!loadIntValue(is, &i)) break;
179
			mat->twoSided=i!=0;
180
			if(!loadIntValue(is, &i)) break;
181
			mat->wireframe=i!=0;
182
			if(!loadIntValue(is, &i)) break;
183
			mat->textureValue=i;
184
			if(!loadMatPair(is, pair)) break;
185
			mat->enviromentMap=pair;
186
			if(!loadMatPair(is, pair)) break;
187
			mat->bumpMap=pair;
188
 
189
			if(mat->type==bob_dom_material::mat5){
190
				if(!loadMatPair(is, pair)) break;
191
				mat->lightMap=pair;
192
			}
193
		}
194
		return true;
195
	}
196
	while(false);
197
	return false;
198
}
199
//---------------------------------------------------------------------------------
200
bool bod_bob_parser::loadMat(bob_dom_material6 *mat, token_stream &is)
201
{
202
	int i; bool bRes=false;
203
	do{
204
		if(!loadIntValue(is, &i)) break;
205
			mat->index=i;
206
 
207
		if(!loadIntValue(is, &i)) break;
208
			mat->flags=i;
209
 
210
		if(mat->flags==bob_dom_material6::Big::flag)
211
			bRes=loadMaterial6Big(mat, is);
212
		else
213
			bRes=loadMaterial6Small(mat, is);
214
	}
215
	while(false);
216
 
217
	return bRes;
218
}
219
//---------------------------------------------------------------------------------
220
bool bod_bob_parser::loadMaterial6Small(bob_dom_material6 *mat, token_stream &is)
221
{
222
	int i;
223
	bob_dom_material1::rgb rgb;
224
	bob_dom_material1::pair int_pair;
225
	bob_dom_material6::Small::pair pair;
226
 
227
	mat->small=new bob_dom_material6::Small();
228
	do{
229
		if((mat->small->textureFile=loadString(is, "texture name: "))==0) break;
230
		if(strcmp(mat->small->textureFile, "NULL")==0) 
231
			{ delete[] mat->small->textureFile; mat->small->textureFile=0; }
232
		if(!loadMatRGB(is, rgb)) break;
233
		mat->small->ambient=rgb;
234
		if(!loadMatRGB(is, rgb)) break;
235
		mat->small->diffuse=rgb;
236
		if(!loadMatRGB(is, rgb)) break;
237
		mat->small->specular=rgb;
238
		if(!loadIntValue(is, &i)) break;
239
		mat->small->transparency=i;
240
		if(!loadIntValue(is, &i)) break;
241
		mat->small->selfIllumination=i;
242
		if(!loadMatPair(is, int_pair)) break;
243
		mat->small->shininess=int_pair;
244
		if(!loadIntValue(is, &i)) break;
245
		mat->small->destinationBlend=i!=0;
246
		if(!loadIntValue(is, &i)) break;
247
		mat->small->twoSided=i!=0;
248
		if(!loadIntValue(is, &i)) break;
249
		mat->small->wireframe=i!=0;
250
		if(!loadIntValue(is, &i)) break;
251
		mat->small->textureValue=i;
252
		if(!loadMatPair(is, pair)) break;
253
		mat->small->enviromentMap=pair;
254
		if(!loadMatPair(is, pair)) break;
255
		mat->small->bumpMap=pair;
256
 
257
		if(!loadMatPair(is, pair)) break;
258
		mat->small->lightMap=pair;
259
 
260
		if(!loadMatPair(is, pair)) break;
261
		mat->small->map4=pair;
262
		if(!loadMatPair(is, pair)) break;
263
		mat->small->map5=pair;
264
 
265
		short flags=0;
266
		if(mat->small->destinationBlend) flags&=0x2;
267
		if(mat->small->twoSided) flags&=0x10;
268
		if(mat->small->wireframe) flags&=0x8;
269
		mat->flags=flags;
270
 
271
		return true;
272
	}
273
	while(false);
274
	return false;
275
}
276
//---------------------------------------------------------------------------------
277
bool bod_bob_parser::loadMaterial6Big(bob_dom_material6 *mat, token_stream &is)
278
{
279
	int count,i;
280
 
281
	bob_dom_material6::Big *big=new bob_dom_material6::Big();
282
	mat->big=big;
283
 
284
	if(!loadIntValue(is, &i, "Technique idx: ")) return false;
285
	big->technique=i;
286
 
287
	if((big->effect=loadString(is, "Effect name: "))==0) return false;
288
 
289
	material6_value *val;
290
	if(!loadIntValue(is, &count, "Value count: ")) return false;
291
	for(i=0; i < count; i++){
292
		if((val=loadMat6Value(is))==0) return false;
293
		big->values.push_back(val);
294
	}
295
 
296
	return true;
297
}
298
//---------------------------------------------------------------------------------
299
material6_value * bod_bob_parser::loadMat6Value(token_stream& is)
300
{
301
	bool bRes=false;
302
	// name, type, value
303
	char *name, *strtype;
304
 
305
	material6_value *val=new material6_value();
306
 
307
	token_stream::token *typepos;
308
 
309
	do{
310
		if((name=loadString(is, "Property name: "))==0) break;
311
		if(name[0]==0) {
312
			error(is.tok(), S_Error, "Empty property name");
313
			return false;
314
		}
315
		if((strtype=loadString(is, "Property type: "))==0) break;
316
		typepos=is.tok();
317
 
318
		int type=-1;
319
 
320
		for(int i=0; i < material6_value::typeNameCount(); i++){
321
			if(strcmp(strtype, material6_value::typeName(i))==0) {
322
				if(strtype[0]!=0)
323
					type=i;
324
				break;
325
			}
326
		}
327
 
328
		if(type==-1){
329
			error(typepos, S_Error, "Unknown property type: \"%s\"", strtype);
330
			break;
331
		}
332
		val->type=(material6_value::Type)type;
333
		val->name=name; 
334
		name=0;
335
 
336
		double d;
337
		switch(val->type){
338
			case material6_value::typeBool: // nobreak
339
			case material6_value::typeLong:
340
				bRes=loadIntValue(is, &val->val.i, "Property value: ");
341
				break;
342
			case material6_value::typeString:
343
				bRes=((val->val.psz=loadString(is, "Property value: "))!=0);
344
				break;
345
			case material6_value::typeFloat:
346
				bRes=loadDoubleValue(is, &d, "Property value: ");
347
				val->val.f=(float)d;
348
				break;
349
			case material6_value::typeFloat4:
350
				for(int i=0; i < 4; i++){
351
					if((bRes=loadDoubleValue(is, &d, "Property value"))==false) break;
352
					val->val.f4.f[i]=(float)d;
353
				}
354
				break;
355
			default:
356
				error(0, S_Error, "Don't know how to output type \"%s\"", strtype);
357
				bRes=false;
358
		}
359
		if(bRes==false)
360
			break;
361
 
362
		bRes=true;
363
	}
364
	while(0);
365
 
366
	delete[] name; delete[] strtype;
367
 
368
	if(bRes==false) {
369
		delete val;
370
		val=0;
371
	}
372
 
373
	return val;
374
}
375
//---------------------------------------------------------------------------------
376
bool bod_bob_parser::loadMaterial(bob_dom_bob *bob, token_stream& is)
377
{
378
	bob_dom_material5::materialType type;
379
 
380
	token *t=is.tok();
381
 
382
	if(t){
383
		if(strcmp(t->getText(), "MATERIAL6")==0)
384
			type=bob_dom_material::mat6;
385
		else if(strcmp(t->getText(), "MATERIAL5")==0)
386
			type=bob_dom_material::mat5;
387
		else if(strcmp(t->getText(), "MATERIAL3")==0)
388
			type=bob_dom_material::mat3;
389
		else if(strcmp(t->getText(), "MATERIAL")==0)
390
			type=bob_dom_material5::mat1;
391
	}
392
 
393
	if(t==NULL || t->type!=token::t_text){
394
		error(t ? t : is.previous(), S_Error, "Expected material header (MATERIAL, MATERIAL3, MATERIAL5 or MATERIAL6)");
395
		return NULL;
396
	}
397
	t=(++is).tok();
398
	if(t==NULL || t->type!=token::t_colon){
399
		error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->getText());
400
		return NULL;
401
	}
402
	if(!checkImmediatePlacement(is.previous(), is.tok()))
403
		return NULL;
404
 
405
	++is;
406
 
407
	bool bRes;
408
	bob_dom_material *mat;
409
	switch(type) {
410
		case bob_dom_material::mat6:
411
			mat=new bob_dom_material6();
412
			bRes=loadMat((bob_dom_material6*)mat, is);
413
			break;
414
		default: // always mat5 because lower mats are not supported in binary form
415
			mat=new bob_dom_material5();
416
			mat->type=type;
417
			bRes=loadMat((bob_dom_material5*)mat, is);
418
			break;
419
	}
420
 
421
	if(bRes==false)
422
		delete mat;
423
	else
424
		bob->materials.push_back(mat);
425
 
426
	return bRes;
427
}
428
//---------------------------------------------------------------------------------
429
bool bod_bob_parser::loadBody(bob_dom_bob *bob, token_stream& is)
430
{
431
	static const char *context="Body: ";
432
	bob_dom_body *body=bob->bodies.createChild();
433
	PointList list;
434
 
435
	deleteTempData();
436
 
437
	loadIntValue(is, &(body->bodySize), context);
438
 
439
	if(!loadBones(body, is)){
440
		bob->bodies.removeChild(--bob->bodies.end());
441
		return false;
442
	}
443
	if(!loadPoints(body, is, list)) {
444
		bob->bodies.removeChild(--bob->bodies.end());
445
		return false;
446
	}
447
 
448
	if(!loadWeights(body, is)){
449
		bob->bodies.removeChild(--bob->bodies.end());
450
		return false;
451
	}
452
 
453
	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());
455
		bob->bodies.removeChild(--bob->bodies.end());
456
		return false;
457
	}
458
 
459
	// move the points to array so we can access them with index
460
	m_points.resize(list.size());
461
	int i=0;
462
	for(PointList::iterator &it=list.begin(); it!=list.end(); ++it, ++i){
463
		m_points[i]=*it;
464
	}
465
	list.clear();
466
 
467
	int endval;
468
	do{
469
		if(!loadPart(body, is)) {
470
			bob->bodies.removeChild(--bob->bodies.end());
471
			return false;
472
		}
473
 
474
		loadIntValue(is, &endval);
475
		if(endval!=-99)
476
			ungetValue(is);
477
	}
478
	while(is.good() && endval!=-99); // -99 means end of body
479
 
480
	if(endval!=-99){
481
		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());
483
		return false;
484
	}
485
	if(!flagsFromString(is, body->bodyFlags)){
486
		bob->bodies.removeChild(--bob->bodies.end());
487
		return false;
488
	}
489
 
490
	return true;
491
}
492
//---------------------------------------------------------------------------------
493
bool bod_bob_parser::loadPoints(bob_dom_body *body, token_stream& is, PointList& points)
494
{
495
	bool bEnd;
496
	int x, y, z;
497
	static const char *context="Point: ";
498
 
499
	do{
500
		loadIntValue(is, &x, context);
501
		loadIntValue(is, &y, context);
502
		if(!loadIntValue(is, &z, context)) return false;
503
 
504
		if(x==-1 && y==-1 && z==-1) { 
505
			bEnd=true; 
506
			break; 
507
		}
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;
520
			fistp z
521
		}
522
		points.push_back(new point_t(x, y, z));
523
	}
524
	while(is.good());
525
 
526
	if(!bEnd){
527
		error(is.previous(), S_Error, "Unexpected end of document found while loading Points. Do you miss the '-1;-1;-1;'?");
528
		return false;
529
	}
530
 
531
	return true;
532
}
533
//---------------------------------------------------------------------------------
534
// load part - bunch of faces/uv's
535
bool bod_bob_parser::loadPart(bob_dom_body *body, token_stream& is)
536
{
537
	int matIdx;
538
	bool bRes=true;
539
	static const char *context="Parts: ";
540
	bool secUV=false;
541
 
542
	bob_dom_part *part=new bob_dom_part();
543
 
544
	loadIntValue(is, &matIdx, context);
545
	do{
546
		if(matIdx < 0)
547
			{ error(is.previous(), S_Error, "%sMaterial index must be >= 0", context); bRes=false; break; }
548
		if(matIdx!=0 && ((size_t)matIdx > m_materials->size() - 1))
549
			error(is.previous(), S_Warning, "%sMaterial index out of range: %d", context, matIdx);
550
 
551
		if((bRes=loadFace(matIdx, *body, *part, is))==false)
552
			break;
553
 
554
		if(is.tok() && is.tok()->type==token::t_openInstrBlock) {
555
			secUV=true;
556
 
557
			if((bRes=loadX3PartValues(++is, *part))==false)
558
				break;
559
 
560
			if((bRes=loadSecondaryUVs(is, *part))==false) 
561
				break;
562
		}
563
 
564
		loadIntValue(is, &matIdx, context);
565
	}
566
	while(matIdx!=-99 && is.good()); // -99 means end of part
567
 
568
	if(bRes && matIdx!=-99){
569
		error(is.previous(), S_Error, "Unexpected end of document found while loading Part. Do you miss the '-99'?");
570
		bRes=false;
571
	}
572
 
573
	if(bRes)
574
		bRes=flagsFromString(is, part->flags);
575
 
576
	if(secUV)
577
		part->flags|=bob_dom_part::x3flag;
578
 
579
	if(bRes)
580
		body->parts.push_back(part);
581
	else
582
		delete part;
583
 
584
	return bRes;
585
};
586
//---------------------------------------------------------------------------------
587
bool bod_bob_parser::flagsFromString(token_stream& is, int& flags)
588
{
589
	bool bRes;
590
	token *t=loadValue(is);
591
 
592
	flags=0;
593
	if(bRes=(t!=NULL)){
594
		int len=(int)strlen(t->text);
595
		int val=1;
596
		for(int i=len-1; i >= 0; i--, val<<=1 ){
597
			switch(t->text[i]){
598
				case '0':
599
					break;
600
				case '1':
601
					flags|=val;
602
					break;
603
				default:
604
					error(is.previous(), S_Error, "Invalid flags definition. Expected binary number");
605
					bRes=false;
606
					break;
607
			}
608
			if(bRes==false) break;
609
		}
610
	}
611
	return bRes;
612
}
613
//---------------------------------------------------------------------------------
614
// 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)
616
{
617
	int indexes[3];
618
	int magic;
619
	int lastPntVal;
620
	double dtexX, dtexY;
621
	int texX, texY;
622
	static const char *context="Part: ";
623
 
624
	for(int i=0; i < 3; i++){
625
		if(loadIntValue(is, indexes + i, context)){
626
			if(indexes[i] < 0 || (size_t)indexes[i] >= m_points.size()){
627
				error(is.previous(), S_Error, "Point index out of range: point %d, index %d", i, indexes[i]);
628
				return false;
629
			}
630
		}
631
		else
632
			return false;
633
	}
634
 
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);
640
	if(magic!=-9 && magic!=-1)
641
		bRes&=loadIntValue(is, &lastPntVal, context);
642
	else
643
		lastPntVal=0;
644
 
645
	if(bRes==false) return false;
646
 
647
	bob_dom_point *point;
648
	bob_dom_face *face=new bob_dom_face();
649
 
650
	bob_dom_point *points_ar[3];
651
	int  magic_ar[3];
652
 
653
	for(int i=0; i < 3; i++){
654
		if(magic!=-17 && magic!=-1){
655
			loadDoubleValue(is, &dtexX, context);
656
			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
		}
669
		else{
670
			texX=0;
671
			texY=0;
672
		}
673
 
674
		texture_coords_t *coords;
675
		texture_coord_t *coord=0;
676
 
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){
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();
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;
696
 
697
			point->values.push_back(lastPntVal);
698
 
699
			coord->index=(int)body.points.new_points.size();
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
 
704
			// now insert the appropriate weight
705
			if(m_weights.size())
706
				body.weights.new_weights.push_back(new bob_dom_weight(*m_weights[indexes[i]]));
707
		}
708
		else
709
			points_ar[i]=NULL;
710
 
711
		magic_ar[i]=magic;
712
		face->values[i]=coord->index;
713
	}
714
	face->values[3]=1;
715
	part.facelist(matIdx)->push_back(face);
716
 
717
 
718
	return loadSpecialValues(points_ar, magic_ar, is);
719
}
720
//---------------------------------------------------------------------------------
721
// 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; } !/
723
bool bod_bob_parser::loadSpecialValues(bob_dom_point *points[3], int magic[3], token_stream& is)
724
{
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;
729
	dummy_pnt.values.push_back(1);
730
 
731
	token *t=is.tok();
732
 
733
	if(t && t->type==token::t_openInstrBlock){
734
		++is;
735
		for(int i=0; i < 3; i++){
736
			// if thte point was already loaded it is null, but we must still consume the values
737
			// and check errors so I load them to dummy point
738
			if(points[i]!=NULL){
739
				if(!loadSpecialPointValues(is, points[i]))
740
					return false;
741
			}
742
			else{
743
				if(!loadSpecialPointValues(is, &dummy_pnt))
744
					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
			}
749
		}
750
		t=is.tok();
751
		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());
753
			return false;
754
		}
755
		++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
	}
778
	return true;
779
}
780
//---------------------------------------------------------------------------------
781
// load one block from extra info in instruction block 
782
// example: { 1; 2; 3; }
783
bool bod_bob_parser::loadSpecialPointValues(token_stream& is, bob_dom_point *point)
784
{
785
	double d;
786
	int v;
787
	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
 
793
	token *t=is.tok();
794
	if(t==NULL || t->type!=token::t_openBracket){
795
		error(t ? t : is.previous(), S_Error, "Expected beginning of block after '%s'", is.previous()->getText());
796
		return false;
797
	}
798
	++is;
799
	while((t=is.tok())!=NULL && !(t->type==token::t_closeBracket || t->type==token::t_closeInstrBlock)){
800
		if(!loadDoubleValue(is, &d, context))
801
			return false;
802
 
803
		__asm{
804
			fld d
805
			fdiv bob_dom_part::multiplier
806
			fistp v
807
		}
808
 
809
		point->values.insert(last, v);
810
	}
811
	if(t==NULL || t->type!=token::t_closeBracket){
812
		if(t==NULL)
813
			error(is.previous(), S_Error, "Unexpected end of document found while loading extra point info. Do you miss the '}'?");
814
		else
815
			error(t, S_Error, "Unexpected '%s' found while loading extra point info", t->getText());
816
		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
	}
833
	++is;
834
 
835
	return true;
836
}
837
//---------------------------------------------------------------------------------
838
bool bod_bob_parser::loadBones(bob_dom_body *body, token_stream& is)
839
{
840
	const token *t=is.tok();
841
	static const char *context2="Bones: ";
842
	static const char *context="Bone: ";
843
 
844
	if(!(t && t->type==token::t_text && strcmp(t->text, "BONES")==0))
845
		return true;
846
 
847
	t=(++is).tok();
848
	if(t==NULL || t->type!=token::t_colon){
849
		error(t ? t : is.previous(), S_Error, "Expected ':' after '%s'", is.previous()->getText());
850
		return false;
851
	}
852
	if(!checkImmediatePlacement(is.previous(), t))
853
		return false;
854
 
855
	int count;
856
	if(!loadIntValue(++is, &count, context2))
857
		return false;
858
 
859
	char *name;
860
	for(int i=0; i < count; i++){
861
		name=loadString(is, context);
862
		if(name==NULL) return false;
863
		body->bones.push_back(name);
864
	}
865
 
866
	return !is.fail();
867
}
868
//---------------------------------------------------------------------------------
869
// 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)
871
{
872
	const token *t=is.tok();
873
	static const char *context="Weight: ";
874
	static const char *context2="Weights: ";
875
 
876
	if(!(t && t->type==token::t_text && strcmp(t->text, "WEIGHTS")==0))
877
		return true;
878
 
879
	int count;
880
	if(!loadIntValue(++is, &count, context2))
881
		return false;
882
 
883
	bool bRes=true;
884
	int v; double d;
885
	bob_dom_weight *w;
886
 
887
	m_weights.resize(count, 0);
888
 
889
	for(int i=0; i < count; i++){
890
		w=new bob_dom_weight();
891
		do{
892
			if(!loadIntValue(is, &v, context)) 
893
				{ bRes=false; break; }
894
			if(v==-1) 
895
				break;
896
 
897
			if(v < 0 || (size_t)v >= body->bones.size()){
898
				error(is.previous(), S_Error, "Weight: Bone index out of range (%d)", v);
899
				{ bRes=false; break; }
900
			}
901
 
902
			if(!loadDoubleValue(is, &d, context)) 
903
				{ bRes=false; break; }
904
 
905
			bob_dom_weight::value val;
906
			val.boneIdx=v;
907
 
908
			__asm{
909
				// val.boneCoefficient = bob_dom_weight::value::multiplier * d
910
				fild bob_dom_weight::value::multiplier
911
				fmul d
912
				fistp val.boneCoefficient
913
			}
914
			w->values.push_back(val);
915
		}
916
		while(!is.fail());
917
		if(is.fail()){
918
			error(is.previous(), S_Error, "Unexpected end of document found while loading Weights. Do you miss the '-1'?");
919
			bRes=false;
920
		}
921
		if(bRes==false){
922
			delete w;
923
			break;
924
		}
925
		m_weights[i]=w;
926
	}
927
	if(bRes){
928
		if(!loadIntValue(is, &v, context2)) 
929
			bRes=false;
930
		else if(v!=-1){
931
			error(is.previous(), S_Error, "Expected '-1' after end of Weights");
932
			bRes=false;
933
		}
934
	}
935
	return bRes;
936
}
937
//---------------------------------------------------------------------------------
938
bool bod_bob_parser::loadSecondaryUVs(token_stream& is, bob_dom_part& part)
939
{
940
	bool bRes;
941
	do{
942
		if((bRes=loadSecondaryUVRecord(is, part))==false) break;
943
	}
944
	while(is.tok() && is.tok()->type!=token::t_closeInstrBlock);
945
 
946
	if(bRes){
947
		bRes=(is.tok() && is.tok()->type==token::t_closeInstrBlock);
948
		if(bRes==false)
949
			error(is.tok() ? is.tok() : is.previous(), S_Error, "Unexpected end of document found while loading secondary UV's. Do you miss the '!/'?");
950
		else
951
			++is;
952
	}
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
 
964
	do{
965
		if(!loadIntValue(is, &matIdx, "")) break;
966
		if(!loadIntValue(is, &pointIdx, "")) break;
967
		for(int i=0; i < 6; i++){
968
			if((bRes=loadDoubleValue(is, &d, ""))==false) break;
969
			uv->values[i]=(float) d;
970
		}
971
		uv->idx=pointIdx;
972
 
973
		faces=part[matIdx];
974
		if(faces==NULL){
975
			error(is.tok(), S_Error, "Secondary UVs: Face list with material idx %d not found", matIdx);
976
			break;
977
		}
978
		faces->x3uvlist.push_back(uv);
979
 
980
		bRes=true;
981
	}
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
 
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;
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
}
1015
//---------------------------------------------------------------------------------