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