| 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 | //---------------------------------------------------------------------------------
 |