00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include "Parser.h"
00014 #include "spectral.h"
00015 #include "vuColourRGBa.h"
00016 #include "vuColour31a.h"
00017 #include "vuColour7a.h"
00018 #include "vuColour9a.h"
00019 #include "vuColourXYZa.h"
00020 #include "Util.h"
00021
00022 namespace ns_vu1112112 {
00023 using namespace ns_vu1112112;
00024
00025
00026 Parser::Parser()
00027 {
00028 m_Buffer = 0;
00029 m_Pos = 0;
00030 m_ReadAmbient = false;
00031 }
00032
00033
00034 Parser::~Parser()
00035 {
00036 if (m_Buffer)
00037 delete [] m_Buffer;
00038 }
00039
00040
00041
00042 bool Parser::Parse(const char* filename, vu1112112& scene)
00043 {
00044 FILE* ifp;
00045
00046 ifp = fopen(filename, "rb");
00047 if (ifp)
00048 {
00049 int stats[5] = {0,0,0,0,0};
00050 int length;
00051
00052
00053
00054 fseek(ifp, 0, SEEK_END);
00055 length = ftell(ifp);
00056 fseek(ifp, 0, SEEK_SET);
00057 m_Buffer = new char[length+1];
00058 fread(m_Buffer, 1, length, ifp);
00059 m_Buffer[length] = 0;
00060 fclose(ifp);
00061
00062
00063 do
00064 {
00065 stats[4] = 0;
00066 if (!stats[0] && ReadGeneral(scene)){
00067 stats[0] = 1; stats[4]++;
00068 }
00069 if (!stats[1] && ReadTarga(scene)){
00070 stats[1] = 1; stats[4]++;
00071 }
00072 if (!stats[2] && ReadMaterial(scene)){
00073
00074 stats[4]++;
00075 }
00076 if (!stats[3] && ReadLight(scene)){
00077
00078 stats[4]++;
00079 }
00080 }while(stats[4]);
00081
00082 CheckError();
00083 }
00084
00085 return true;
00086 }
00087
00088
00089 bool Parser::ReadGeneral(vu1112112& s)
00090 {
00091 int stats[7] = {0,0,0,0,0,0,0};
00092 ColourType c;
00093 vuVector v;
00094 float n;
00095
00096 if (ReadString(" general {"))
00097 {
00098 Material mat;
00099 do
00100 {
00101 stats[6] = 0;
00102 if (!stats[0] && ReadColourType(" background", c, cColour)){
00103 stats[0] = 1; stats[6]++; s.Background = c;
00104 }
00105 if (!stats[1] && ReadNumber(" brightness", n)){
00106 stats[1] = 1; stats[6]++; s.brightness = n;
00107 }
00108 if (!stats[2] && ReadVector3(" light_dir", v)){
00109 stats[2] = 1; stats[6]++; s.m_LightDir = v.normalize();
00110 }
00111 if (!stats[3] && ReadNumber(" diffuse", n)){
00112 stats[3] = 1; stats[6]++; s.diffuse = n;
00113 }
00114 if (!stats[4] && ReadNumber(" light_scale", n)){
00115 stats[4] = 1; stats[6]++; s.light_scale = n;
00116 }
00117 if (ReadString(" }")){
00118 stats[6]++; break;
00119 }
00120 }while(stats[6]);
00121
00122 if (stats[6])
00123 return true;
00124 }
00125 return false;
00126 }
00127
00128
00129
00130
00131 void Parser::CheckError(void)
00132 {
00133 int pos = m_Pos;
00134
00135
00136 ReadString(" ");
00137
00138
00139
00140 if (m_Buffer[m_Pos])
00141 {
00142 char error[1024];
00143 char last=0;
00144 int line=1;
00145 int i=0;
00146
00147
00148 while(i < pos)
00149 {
00150 if (m_Buffer[i]==10)
00151 {
00152 if (last==13)
00153 {
00154 last = 0;
00155 ++i;
00156 }
00157 else
00158 {
00159 ++line;
00160 last = m_Buffer[i++];
00161 }
00162 }
00163 else if (m_Buffer[i]==13)
00164 {
00165 if (last==10)
00166 {
00167 last = 0;
00168 ++i;
00169 }
00170 else
00171 {
00172 ++line;
00173 last = m_Buffer[i++];
00174 }
00175 }
00176 else
00177 last = m_Buffer[i++];
00178 }
00179
00180
00181 while((i>0) && (m_Buffer[i]!=10) && (m_Buffer[i]!=13))
00182 --i;
00183 pos -= i;
00184 if ((pos==0) && (line>1))
00185 ++line;
00186
00187 sprintf(error, "PARSER - Parsed successfully to line %i, character %i.", line, pos);
00188 throw error;
00189 }
00190 }
00191
00192
00193 bool Parser::ReadString(char* s)
00194 {
00195 char str[1024];
00196 int ret, len=0;
00197 strcpy(str, s);
00198 strcat(str, "%n");
00199 ret = sscanf(&m_Buffer[m_Pos], str, &len);
00200 if ((ret!=EOF) && (len!=0))
00201 {
00202 m_Pos += len;
00203 return true;
00204 }
00205 return false;
00206 }
00207
00208
00209 bool Parser::ReadString(char* prefix, char* s)
00210 {
00211 char str[1024];
00212 int i=0;
00213 strcpy(str, prefix);
00214 strcat(str, " \"");
00215 if (ReadString(str))
00216 {
00217 while((m_Buffer[m_Pos]!='"') && m_Buffer[m_Pos])
00218 s[i++] = m_Buffer[m_Pos++];
00219 s[i] = 0;
00220 if (m_Buffer[m_Pos]=='"')
00221 {
00222 ++m_Pos;
00223 return true;
00224 }
00225 }
00226 return false;
00227 }
00228
00229
00230 bool Parser::ReadNumber(char* prefix, float& t)
00231 {
00232 char str[1024];
00233 int ret, len=0;
00234 strcpy(str, prefix);
00235 strcat(str, " %f%n");
00236 ret = sscanf(&m_Buffer[m_Pos], str, (float*)&t, &len);
00237 if ((ret == 1) && (len!=0))
00238 {
00239 m_Pos += len;
00240 return true;
00241 }
00242 return false;
00243 }
00244
00245
00246
00247 bool Parser::ReadVector3(char* prefix, vuVector& v)
00248 {
00249 char str[1024];
00250 int pos;
00251
00252 pos = m_Pos;
00253 strcpy(str, prefix);
00254 strcat(str, " <");
00255 if (ReadNumber(str, v[0]))
00256 if (ReadNumber(" ,", v[1]))
00257 if (ReadNumber(" ,", v[2]))
00258 if (ReadString(" >"))
00259 return true;
00260 m_Pos = pos;
00261 return false;
00262 }
00263
00264
00265
00266 bool Parser::ReadvuVector(char* prefix, vuVector& v)
00267 {
00268 char str[1024];
00269 int pos;
00270
00271 pos = m_Pos;
00272 strcpy(str, prefix);
00273 strcat(str, " <");
00274 if (ReadNumber(str, v[0]))
00275 if (ReadNumber(" ,", v[1]))
00276 if (ReadNumber(" ,", v[2]))
00277 if (ReadNumber(" ,", v[3]))
00278 if (ReadString(" >"))
00279 return true;
00280 m_Pos = pos;
00281 return false;
00282 }
00283
00284
00285
00286 bool Parser::ReadRGB(char* prefix, vuColourRGBa& r)
00287 {
00288 char str[1024];
00289 int pos;
00290
00291 pos = m_Pos;
00292 strcpy(str, prefix);
00293 strcat(str, " <");
00294 if (ReadNumber(str, r[0]))
00295 if (ReadNumber(" ,", r[1]))
00296 if (ReadNumber(" ,", r[2]))
00297 if (ReadString(" >"))
00298 return true;
00299 m_Pos = pos;
00300 return false;
00301 }
00302
00303
00304
00305 bool Parser::ReadvuColourRGBa(char* prefix, vuColourRGBa& r)
00306 {
00307 char str[1024];
00308 int pos;
00309
00310 pos = m_Pos;
00311 strcpy(str, prefix);
00312 strcat(str, " <");
00313 if (ReadNumber(str, r[0]))
00314 if (ReadNumber(" ,", r[1]))
00315 if (ReadNumber(" ,", r[2]))
00316 if (ReadNumber(" ,", r[3]))
00317 if (ReadString(" >"))
00318 return true;
00319 m_Pos = pos;
00320 return false;
00321 }
00322
00323
00324
00325 bool Parser::ReadSpectrum31(char* prefix, vuColour31a& s)
00326 {
00327 char str[1024];
00328 bool good;
00329 int pos;
00330 int i;
00331
00332 pos = m_Pos;
00333 strcpy(str, prefix);
00334 strcat(str, " <");
00335 if (ReadNumber(str, s[0]))
00336 {
00337 good = true;
00338 for(i=1;(i<31)&&good;++i)
00339 good = ReadNumber(" ,", s[i]);
00340 if (good && ReadString(" >"))
00341 return true;
00342 }
00343 m_Pos = pos;
00344 return false;
00345 }
00346
00347
00348
00349 bool Parser::ReadvuColour31a(char* prefix, vuColour31a& s)
00350 {
00351 char str[1024];
00352 bool good;
00353 int pos;
00354 int i;
00355
00356 pos = m_Pos;
00357 strcpy(str, prefix);
00358 strcat(str, " <");
00359 if (ReadNumber(str, s[0]))
00360 {
00361 good = true;
00362 for(i=1;(i<32)&&good;++i)
00363 good = ReadNumber(" ,", s[i]);
00364 if (good && ReadString(" >"))
00365 return true;
00366 }
00367 m_Pos = pos;
00368 return false;
00369 }
00370
00371
00372
00373 bool Parser::ReadSpectrum7(char* prefix, vuColour7a& s)
00374 {
00375 char str[1024];
00376 bool good;
00377 int pos;
00378 int i;
00379
00380 pos = m_Pos;
00381 strcpy(str, prefix);
00382 strcat(str, " <");
00383 if (ReadNumber(str, s[0]))
00384 {
00385 good = true;
00386 for(i=1;(i<7)&&good;++i)
00387 good = ReadNumber(" ,", s[i]);
00388 if (good && ReadString(" >"))
00389 return true;
00390 }
00391 m_Pos = pos;
00392 return false;
00393 }
00394
00395
00396
00397 bool Parser::ReadvuColour7a(char* prefix, vuColour7a& s)
00398 {
00399 char str[1024];
00400 bool good;
00401 int pos;
00402 int i;
00403
00404 pos = m_Pos;
00405 strcpy(str, prefix);
00406 strcat(str, " <");
00407 if (ReadNumber(str, s[0]))
00408 {
00409 good = true;
00410 for(i=1;(i<8)&&good;++i)
00411 good = ReadNumber(" ,", s[i]);
00412 if (good && ReadString(" >"))
00413 return true;
00414 }
00415 m_Pos = pos;
00416 return false;
00417 }
00418
00419
00420
00421 bool Parser::ReadSpectrum9(char* prefix, vuColour9a& s)
00422 {
00423 char str[1024];
00424 bool good;
00425 int pos;
00426 int i;
00427
00428 pos = m_Pos;
00429 strcpy(str, prefix);
00430 strcat(str, " <");
00431 if (ReadNumber(str, s[0]))
00432 {
00433 good = true;
00434 for(i=1;(i<9)&&good;++i)
00435 good = ReadNumber(" ,", s[i]);
00436 if (good && ReadString(" >"))
00437 return true;
00438 }
00439 m_Pos = pos;
00440 return false;
00441 }
00442
00443
00444
00445 bool Parser::ReadvuColour9a(char* prefix, vuColour9a& s)
00446 {
00447 char str[1024];
00448 bool good;
00449 int pos;
00450 int i;
00451
00452 pos = m_Pos;
00453 strcpy(str, prefix);
00454 strcat(str, " <");
00455 if (ReadNumber(str, s[0]))
00456 {
00457 good = true;
00458 for(i=1;(i<10)&&good;++i)
00459 good = ReadNumber(" ,", s[i]);
00460 if (good && ReadString(" >"))
00461 return true;
00462 }
00463 m_Pos = pos;
00464 return false;
00465 }
00466
00467
00468
00469 bool Parser::ReadColourType(char* prefix,
00470 ColourType& c,
00471 ColourUsage u)
00472 {
00473 #if defined USE_vuColourRGBa
00474 if (u == cColour)
00475 {
00476 if (ReadvuColourRGBa(prefix, c))
00477 {
00478 return true;
00479 }
00480 else
00481 {
00482 vuColour31a s;
00483 vuColourXYZa x;
00484 if (ReadvuColour31a(prefix, s))
00485 {
00486 if (m_ReadAmbient)
00487 s *= m_Ambient;
00488 x.From(s);
00489 if (m_ReadAmbient)
00490 x.SetNormalSpectrum(m_Ambient);
00491 x.Normalize();
00492 c.From(x);
00493 c.ClampTo1();
00494 return true;
00495 }
00496 }
00497 }
00498 else if (u == cLight || u == cAmbient || u == cBackground)
00499 {
00500 if (ReadRGB(prefix, c))
00501 {
00502 return true;
00503 }
00504 else
00505 {
00506 vuColour31a s;
00507 vuColourXYZa x;
00508 if (ReadSpectrum31(prefix, s))
00509 {
00510 if (u == cAmbient)
00511 {
00512 m_Ambient = s;
00513 m_ReadAmbient = true;
00514 }
00515 if (m_ReadAmbient && u == cBackground)
00516 s *= m_Ambient;
00517 x.From(s);
00518 if (m_ReadAmbient)
00519 x.SetNormalSpectrum(m_Ambient);
00520 x.Normalize();
00521 c.From(x);
00522 c.ClampTo1();
00523 return true;
00524 }
00525 }
00526 }
00527 return false;
00528 #elif defined USE_SPECTRUM31A
00529 if (u == cColour)
00530 return ReadvuColour31a(prefix, c);
00531 return ReadSpectrum31(prefix, c);
00532 #elif defined USE_SPECTRUM7A
00533 if (u == cColour)
00534 {
00535 if (ReadvuColour7a(prefix, c))
00536 {
00537 return true;
00538 }
00539 else
00540 {
00541 vuColour31a s;
00542 if (ReadvuColour31a(prefix, s))
00543 {
00544 c.from(s);
00545 return true;
00546 }
00547 }
00548 }
00549 else if (u == cLight)
00550 {
00551 if (ReadSpectrum7(prefix, c))
00552 {
00553 return true;
00554 }
00555 else
00556 {
00557 vuColour31a s;
00558 if (ReadSpectrum31(prefix, s))
00559 {
00560 c.from(s);
00561 return true;
00562 }
00563 }
00564 }
00565 return false;
00566 #elif defined USE_SPECTRUM9A
00567 if (u == cColour)
00568 {
00569 if (ReadvuColour9a(prefix, c))
00570 {
00571 return true;
00572 }
00573 else
00574 {
00575 vuColour31a s;
00576 if (ReadvuColour31a(prefix, s))
00577 {
00578 c.from(s);
00579 return true;
00580 }
00581 }
00582 }
00583 else if (u == cLight)
00584 {
00585 if (ReadSpectrum9(prefix, c))
00586 {
00587 return true;
00588 }
00589 else
00590 {
00591 vuColour31a s;
00592 if (ReadSpectrum31(prefix, s))
00593 {
00594 c.from(s);
00595 return true;
00596 }
00597 }
00598 }
00599 return false;
00600 #endif
00601 }
00602
00603
00604 bool Parser::ReadMaterial(vu1112112 &r)
00605 {
00606 int stats[8] = {0,0,0,0,0,0,0,0};
00607 ColourType c;
00608 float n;
00609 if (ReadString(" material {"))
00610 {
00611 Material m;
00612 m.scattering=1;
00613 m.absorption=1;
00614 do
00615 {
00616 stats[7] = 0;
00617 if (!stats[0] && ReadColourType(" colour", c, cColour)){
00618 stats[0] = 1; stats[7]++; m.scattering = c;
00619 }
00620 if (!stats[1] && ReadColourType(" absorption", c, cColour)){
00621 stats[1] = 1; stats[7]++; m.absorption = c;
00622 }
00623 if (!stats[2] && ReadNumber(" low_th", n)){
00624 stats[2] = 1; stats[7]++; m.low_th = (int)n;
00625 }
00626 if (!stats[3] && ReadNumber(" high_th", n)){
00627 stats[3] = 1; stats[7]++; m.high_th = (int)n;
00628 }
00629 if (!stats[4] && ReadNumber(" xray", n)){
00630 stats[4] = 1; stats[7]++; m.xray = (n == 1);
00631 }
00632 if (ReadString(" }")){
00633 stats[7]++; break;
00634 }
00635 }while(stats[7]);
00636
00637 if (stats[7])
00638 {
00639 m.check_absorption();
00640 r.add_material(m);
00641 return true;
00642 }
00643 }
00644 return false;
00645 }
00646
00647
00648 bool Parser::ReadTarga(vu1112112& s)
00649 {
00650 int stats[4] = {0,0,0,0};
00651 char c[64];
00652 float n;
00653
00654 if (ReadString(" image {"))
00655 {
00656 do
00657 {
00658 stats[3] = 0;
00659 if (!stats[0] && ReadString(" name", c)){
00660 FixName(c);
00661 stats[0] = 1; stats[3]++;
00662 }
00663 if (!stats[1] && ReadNumber(" width", n)){
00664 stats[1] = 1; stats[3]++;
00665 s.m_Camera->setWidth((int)n);
00666 }
00667 if (!stats[2] && ReadNumber(" height", n)){
00668 stats[2] = 1; stats[3]++;
00669 s.m_Camera->setHeight((int)n);
00670 }
00671 if (ReadString(" }")){
00672 stats[3]++; break;
00673 }
00674 }while(stats[3]);
00675
00676 if (stats[3])
00677 return true;
00678 }
00679 return false;
00680 }
00681
00682
00683 bool Parser::ReadLight(vu1112112& scene)
00684 {
00685 int stats[4] = {0,0,0,0};
00686 vuVector v;
00687 ColourType c;
00688
00689 if (ReadString(" light {"))
00690 {
00691 do
00692 {
00693 stats[3] = 0;
00694 if (!stats[1] && ReadColourType(" colour", c, cLight)){
00695 stats[1] = 1; stats[3]++; scene.add_light(c);
00696 }
00697 if (ReadString(" }")){
00698 stats[3]++; break;
00699 }
00700 }while(stats[3]);
00701
00702 if (stats[3])
00703 {
00704 return true;
00705 }
00706 }
00707 return false;
00708 }
00709
00710 void Parser::FixName(char* str)
00711 {
00712 char ext[32];
00713 int i=0;
00714
00715 while(str[i] != '.' && str[i])
00716 ++i;
00717 strcpy(ext, &str[i]);
00718 str[i] = 0;
00719 #if defined USE_vuColourRGBa
00720 strcat(str, "_rgb");
00721 #elif defined USE_SPECTRUM31A
00722 strcat(str, "_31");
00723 #elif defined USE_SPECTRUM7A
00724 strcat(str, "_7");
00725 #elif defined USE_SPECTRUM9A
00726 strcat(str, "_9");
00727 #endif
00728 strcat(str, ext);
00729 }
00730
00731 }