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