00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <wx/filename.h>
00013 #include <wx/wfstream.h>
00014 #include <wx/tokenzr.h>
00015 #include <wx/event.h>
00016 #include "fhsparser.h"
00017 #include "../../geometrynode.h"
00018
00019
00020 using namespace VRUT;
00021
00022
00023 FHSParser::FHSParser(wxInputStream * _inputStream, SCENE_ID _sceneID, const wxString _scenePath, Module * _module)
00024 : module(_module)
00025 {
00026 textParser = new TextParser(_inputStream, 10000, 1000);
00027 wxFileName filename(_scenePath);
00028 scenePath = filename.GetPath() + filename.GetPathSeparator();
00029 sceneID = _sceneID;
00030 nodesImported = nodesGeomImported = materialsImported = texturesImported = lightsImported = 0;
00031 }
00032
00033
00034 FHSParser::~FHSParser()
00035 {
00036 delete textParser;
00037 }
00038
00039
00040 bool FHSParser::logErrorMsg(ERROR_MSG msg, const wxString & line, const wxChar * expected)
00041 {
00042 if (module->TestExit())
00043 return false;
00044
00045 switch (msg)
00046 {
00047 case EXPECTED:
00048 if (expected)
00049 {
00050 LOGERROR(wxT("<FHSParser>Expected '") + wxString(expected) + wxT("' before '") + line + wxT("'"));
00051 break;
00052 }
00053 case UNEXPECTED:
00054 if (wxString(line).Trim().IsEmpty())
00055 LOGERROR(wxT("<FHSParser>Unexpected end of file"));
00056 else
00057 LOGERROR(wxT("<FHSParser>Unexpected token: '" + line + wxT("'")));
00058 break;
00059 case VECTOR:
00060 LOGERROR(wxT("<FHSParser>Vector parse error, invalid dimension or format: '" + line + wxT("'")));
00061 break;
00062 case MATERIAL:
00063 LOGERROR(wxT("<FHSParser>Material not defined: '" + line + wxT("'")));
00064 break;
00065 }
00066 return false;
00067 }
00068
00069
00070 const wxString FHSParser::getUniqueUid(const wxString & uid)
00071 {
00072
00073 wxString unqUid = CloneWxString(uid);
00074 unsigned cnt = 0;
00075 while (nodeUidsList.find(unqUid) != nodeUidsList.end())
00076 unqUid = wxString::Format(wxT("%s_%i"), uid.c_str(), cnt++);
00077 nodeUidsList.insert(NodeUidsList::value_type(unqUid, false));
00078 return unqUid;
00079 }
00080
00081
00082 bool FHSParser::parseScale(const wxString & nodeUid)
00083 {
00085 if (textParser->NextCharIs('('))
00086 {
00087 VECTOR3 v;
00088 if (textParser->ParseVector(v._v, 3) != 3)
00089 return false;
00090 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORM(sceneID, nodeUid, MATRIX::ScaleMat(v));
00091 module->PostToKernel(ev);
00092 }
00094 else
00095 {
00096 float val = 0;
00097 if (textParser->ParseFloat(&val))
00098 {
00099 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORM(sceneID, nodeUid, MATRIX::ScaleMat(VECTOR3(val, val, val)));
00100 module->PostToKernel(ev);
00101 }
00102 else
00103 return logErrorMsg(EXPECTED, textParser->GetWxLine(), wxT("<number>"));
00104 }
00105 return true;
00106 }
00107
00108
00109 bool FHSParser::parseRotate(const wxString & nodeUid)
00110 {
00111 float angle;
00113 if (textParser->NextCharIs('('))
00114 {
00115 VECTOR3 axis;
00116 if ((textParser->ParseVector(axis._v, 3) != 3) || (!textParser->ParseFloat(&angle)))
00117 return false;
00118 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORM(sceneID, nodeUid, MATRIX::RotationAxis(axis, angle / 180.0 * 3.14159));
00119 module->PostToKernel(ev);
00120 }
00122 else
00123 {
00124 const char *keywords[] = {"XAXIS", "YAXIS", "ZAXIS", ""};
00125 while (!textParser->NextCharIs('}'))
00126 {
00127 switch (textParser->KeywordsSwitch(keywords))
00128 {
00129 case 0:
00130 {
00131 if (!textParser->ParseFloat(&angle))
00132 return false;
00133 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORM(sceneID, nodeUid, MATRIX::RotationX(angle / 180.0 * 3.14159));
00134 module->PostToKernel(ev);
00135 }
00136 break;
00137 case 1:
00138 {
00139 if (!textParser->ParseFloat(&angle))
00140 return false;
00141 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORM(sceneID, nodeUid, MATRIX::RotationY(angle / 180.0 * 3.14159));
00142 module->PostToKernel(ev);
00143 }
00144 break;
00145 case 2:
00146 {
00147 if (!textParser->ParseFloat(&angle))
00148 return false;
00149 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORM(sceneID, nodeUid, MATRIX::RotationZ(angle / 180.0 * 3.14159));
00150 module->PostToKernel(ev);
00151 }
00152 break;
00153 default:
00154 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00155 }
00156 }
00157 }
00158 return true;
00159 }
00160
00161
00162 bool FHSParser::parseIndices(std::vector<GeometryTriangles::Indice> * indices, size_t maxInd)
00163 {
00164 if (textParser->GetChar() != '{')
00165 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00166
00167
00168 while (!textParser->NextCharIs('}', "TNIC= \t\n\r"))
00169 {
00170 long val;
00171 if (!textParser->ParseLong(&val, NULL, false) || (val < 0) || (val > long(maxInd)))
00172 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00173 indices->push_back((GeometryTriangles::Indice)val);
00174 }
00175 if (textParser->GetChar() != '}')
00176 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00177 return true;
00178 }
00179
00180 bool FHSParser::parsePolyPool(GeometryTriangles * geometry)
00181 {
00182 wxASSERT_MSG(geometry->type == Geometry::GEOMETRY_TRIANGLE, wxT("Cannot parse polygon pool for non-triangulated geometry"));
00183 if (textParser->GetChar() != '{')
00184 return logErrorMsg(EXPECTED, textParser->GetWxLine(), wxT("{"));
00185 std::vector<VECTOR3> * verts = &(geometry->vertices);
00186 std::vector<VECTOR3> * normals = &(geometry->normals);
00187 std::vector<GeometryTriangles::TexCoord> * texCoords = &(geometry->texCoords);
00188 bool cycle = true;
00189 while (cycle)
00190 {
00191 switch (textParser->CharsSwitch("PNTC}", " \t\n\r="))
00192 {
00193 case 0:
00194 {
00195 VECTOR3 vert;
00196 if (textParser->ParseVector(vert._v, 3, false, "= ") != 3)
00197 return false;
00198 verts->push_back(vert);
00199 }
00200 break;
00201 case 1:
00202 {
00203 VECTOR3 norm;
00204 if (textParser->ParseVector(norm._v, 3, false, "= ") != 3)
00205 return false;
00206 for (size_t i=verts->size()-normals->size()-1; i>0; i--)
00207 normals->push_back(VECTOR3());
00208 normals->push_back(norm);
00209 }
00210 break;
00211 case 2:
00212 {
00213 GeometryTriangles::TexCoord texCoord;
00214 if (textParser->ParseVector(texCoord._v, 2, false, "= ") != 2)
00215 return false;
00216 for (size_t i=verts->size()-texCoords->size()-1; i>0; i--)
00217 texCoords->push_back(GeometryTriangles::TexCoord());
00218 texCoords->push_back(texCoord);
00219 }
00220 break;
00221 case 3:
00222 {
00223 VECTOR3 c;
00224 if (textParser->ParseVector(c._v, 3, false, "= ") != 3)
00225 return false;
00226
00227 }
00228 break;
00229 case 4:
00230 cycle = false;
00231 break;
00232 default:
00233 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00234 }
00235 }
00236 return true;
00237 }
00238
00239
00240 bool FHSParser::parsePolyBox(GeometryTriangles * geometry)
00241 {
00242 float box[6];
00243 if (!textParser->ParseVector(box, 6))
00244 return false;
00245 vector3 position(box), size(box + 3);
00246 geometry->AddBox(position, size - position);
00247 return true;
00248 }
00249
00250
00251 bool FHSParser::parseMaterialAttribs(Material * material)
00252 {
00253 if (textParser->GetChar() != '{')
00254 return logErrorMsg(EXPECTED, textParser->GetWxLine(), wxT("{"));
00255 const char *keywords[] = {"AMBIENT", "DIFFUSE", "SPECULAR", "EMISSION", "SHININESS", "TEXTURE", "TEXWRAP", "TEXFILTER", "TEXQUALITY", "TEXBLEND", "TRANSPARENCY", "MATX", "COLOR", "UNLIT", "}", ""};
00256 vector3 color(1, 1, 1);
00257 bool cycle = true;
00258 while (cycle)
00259 {
00260 switch (textParser->KeywordsSwitch(keywords))
00261 {
00262 case 0:
00263 if (textParser->ParseVector(material->ambient._v, 3) != 3)
00264 return false;
00265 break;
00266 case 1:
00267 if (textParser->NextCharIs('('))
00268 {
00269 if (textParser->ParseVector(material->diffuse._v, 3) != 3)
00270 return false;
00271 }
00272 else
00273 {
00274 float diffuse;
00275 if (!textParser->ParseFloat(&diffuse))
00276 return false;
00277 material->diffuse = VECTOR4(color * diffuse, 1);
00278 }
00279 break;
00280 case 2:
00281 if (textParser->NextCharIs('('))
00282 {
00283 if (textParser->ParseVector(material->specular._v, 3) != 3)
00284 return false;
00285 }
00286 else
00287 {
00288 float specular;
00289 if (!textParser->ParseFloat(&specular))
00290 return false;
00291 material->specular = VECTOR4(color * specular, 1);
00292 }
00293 break;
00294 case 3:
00295 if (textParser->ParseVector(material->emission._v, 3) != 3)
00296 return false;
00297 break;
00298 case 4:
00299 if (!textParser->ParseFloat(&material->shininess))
00300 return false;
00301 break;
00302 case 5:
00303 {
00304 wxString texPath = scenePath + textParser->GetWxString();
00305 wxCommandEvent texEvt = Event::GET_EVT_SCENE_IMAGE_ADD(texPath);
00306 module->PostToKernel(texEvt);
00307 material->imageName = texPath;
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 texturesImported++;
00319 }
00320 break;
00321 case 6:
00322 {
00323 const char *texwraps[] = {"REPEAT", "CLAMP", ""};
00324 material->texFlags |= ( textParser->KeywordsSwitch(texwraps) ? Material::TEX_UWRAP_CLAMP : Material::TEX_UWRAP_REPEAT );
00325 material->texFlags |= ( textParser->KeywordsSwitch(texwraps) ? Material::TEX_VWRAP_CLAMP : Material::TEX_VWRAP_REPEAT );
00326 }
00327 break;
00328 case 7:
00329 {
00330 const char *texfilters[] = {"POINT", "LINEAR", "MIPMAP", ""};
00331 int minFilter = textParser->KeywordsSwitch(texfilters);
00332 switch (minFilter)
00333 {
00334 case 0:
00335 material->texFlags |= Material::TEX_MIN_FILTER_POINT;
00336 break;
00337 case 1:
00338 material->texFlags |= Material::TEX_MIN_FILTER_LINEAR;
00339 break;
00340 default:
00341 material->texFlags |= Material::TEX_MIN_FILTER_MIPMAP;
00342 break;
00343 }
00344 int maxFilter = textParser->KeywordsSwitch(texfilters);
00345 switch (maxFilter)
00346 {
00347 case 0:
00348 material->texFlags |= Material::TEX_MAG_FILTER_POINT;
00349 break;
00350 default:
00351 material->texFlags |= Material::TEX_MAG_FILTER_LINEAR;
00352 break;
00353 }
00354 }
00355 break;
00356 case 8:
00357 {
00358 wxString texquality(textParser->GetWxString());
00359
00360 }
00361 break;
00362 case 9:
00363 {
00364 const char *texblend[] = {"MODULATE", "REPLACE", "DECAL", "BLEND", ""};
00365 int texBlend = textParser->KeywordsSwitch(texblend);
00366 switch (texBlend)
00367 {
00368 case 0:
00369 material->texFlags |= Material::TEX_ENV_MODULATE;
00370 break;
00371 case 1:
00372 material->texFlags |= Material::TEX_ENV_REPLACE;
00373 break;
00374 case 2:
00375 material->texFlags |= Material::TEX_ENV_DECAL;
00376 break;
00377 case 3:
00378 material->texFlags |= Material::TEX_ENV_BLEND;
00379 break;
00380 }
00381 }
00382 break;
00383 case 10:
00384 if (!textParser->ParseFloat(&material->diffuse.w))
00385 return false;
00386 material->diffuse.w = 1.0 - material->diffuse.w;
00387 material->flags |= Material::BLENDED;
00388 break;
00389 case 11:
00390 {
00391 TextParser tmpParser(textParser->GetString().c_str());
00392 const char *envKeywords[] = {"DEPTHTEST", "DEPTHMASK", "DEPTHFUNC", "UID", "DSIDED", "GENFUNC", "INVERTALPHA", "IGNORECOLORS", "CLEARCOAT",
00393 "SHADERENABLE", "SHADERPROG", "SHADERPARAM", "MIXTEXTURE", "BLENDFUNC", "ACTIVATE", "DEACTIVATE", "CUBETEX", "LINEWIDTH", ""
00394 };
00395 switch (tmpParser.KeywordsSwitch(envKeywords))
00396 {
00397 case 0:
00398 {
00399 int depthtest;
00400 if (!tmpParser.ParseInt(&depthtest))
00401 return false;
00402 if (depthtest == 0)
00403 material->flags |= Material::DEPTH_TEST_DISABLE;
00404 }
00405 break;
00406 case 1:
00407 {
00408 int depthmask;
00409 if (!tmpParser.ParseInt(&depthmask))
00410 return false;
00411 if (depthmask == 0)
00412 material->flags |= Material::DEPTH_MASK_DISABLE;
00413 }
00414 break;
00415 case 2:
00416 {
00417 int dfunc;
00418 if (!tmpParser.ParseInt(&dfunc))
00419 return false;
00420 material->depthFunc = dfunc;
00421 }
00422 break;
00423 case 3:
00424 material->uid = tmpParser.GetWxString();
00425 break;
00426 case 4:
00427 {
00428 int dsided;
00429 if (!tmpParser.ParseInt(&dsided))
00430 return false;
00431 if (dsided)
00432 material->flags |= Material::DOUBLE_SIDED;
00433 }
00434 break;
00435 case 5:
00436 {
00437 bool scoord = tmpParser.GetWxString().IsSameAs('s', false);
00438 wxString type(tmpParser.GetWxString());
00439 if (type.Matches(wxT("*Eye*")))
00440 {
00441 if (scoord)
00442 material->texFlags |= Material::TEX_GEN_FUNC_U_EYE;
00443 else
00444 material->texFlags |= Material::TEX_GEN_FUNC_V_EYE;
00445 }
00446 else if (type.Matches(wxT("*Object*")))
00447 {
00448 if (scoord)
00449 material->texFlags |= Material::TEX_GEN_FUNC_U_OBJECT;
00450 else
00451 material->texFlags |= Material::TEX_GEN_FUNC_V_OBJECT;
00452 }
00453 else if (type.IsSameAs(wxT("Sphere")))
00454 {
00455 if (scoord)
00456 material->texFlags |= Material::TEX_GEN_FUNC_U_SPHERE;
00457 else
00458 material->texFlags |= Material::TEX_GEN_FUNC_V_SPHERE;
00459 }
00460 }
00461 break;
00462 case 6:
00463 material->flags |= Material::INVERT_ALPHA;
00464 break;
00465 case 7:
00466 material->texFlags |= Material::TEX_IGNORE_COLORS;
00467 break;
00468 case 8:
00469 {
00470 float clearcoat[3];
00471 if (tmpParser.ParseVector(clearcoat, 3, true) != 3)
00472 return false;
00473 }
00474 break;
00475 case 9:
00476 {
00477 int shaderenable;
00478 if (!tmpParser.ParseInt(&shaderenable))
00479 return false;
00480 material->shader = new ShaderProgram;
00481 }
00482 break;
00483 case 10:
00484 {
00485 if (!material->shader)
00486 {
00487 LOGERROR(wxT("<FHSParser>Shader defined but not enabled"));
00488 material->shader = new ShaderProgram;
00489
00490 }
00491 const char *keywords[] = {"GLSL", "OPENRT", ""};
00492 switch (tmpParser.KeywordsSwitch(keywords))
00493 {
00494 case 0:
00495 {
00496 material->shader->type = ShaderProgram::LANG_GLSL;
00497 wxString * target = (wxString *)NULL;
00498 wxString * targetFileName = (wxString *)NULL;
00499 const char *envKeywords[] = {"FS", "VS", ""};
00500 switch (tmpParser.KeywordsSwitch(envKeywords))
00501 {
00502 case 0:
00503 target = &material->shader->fsSource;
00504 targetFileName = &material->shader->fsFileName;
00505 break;
00506 case 1:
00507 target = &material->shader->vsSource;
00508 targetFileName = &material->shader->vsFileName;
00509 break;
00510 default:
00511 logErrorMsg(UNEXPECTED, tmpParser.GetWxLine());
00512 }
00513 wxString shaderfilename(tmpParser.GetWxString().AfterFirst('\'').BeforeLast('\''));
00514 if (target && wxFileName::FileExists(scenePath + shaderfilename))
00515 {
00516 *targetFileName = scenePath + shaderfilename;
00517 wxFileInputStream fin(scenePath + shaderfilename);
00518 wxStringOutputStream ss(target);
00519 fin.Read(ss);
00520 }
00521 }
00522 break;
00523 case 1:
00524 {
00525 material->shader->type = ShaderProgram::LANG_OPENRT;
00526
00527 }
00528 break;
00529 default:
00530 logErrorMsg(UNEXPECTED, tmpParser.GetWxLine());
00531 }
00532 }
00533 break;
00534 case 11:
00535 {
00536 if (!material->shader)
00537 {
00538 LOGERROR(wxT("<FHSParser>Shader not enabled"));
00539 return false;
00540 }
00541 ShaderParam param;
00542 const char *typeKeywords[] = {"GLSL", "OPENRT", ""};
00543 if (tmpParser.KeywordsSwitch(typeKeywords) != 0)
00544 break;
00545
00546 param.name = tmpParser.GetWxString();
00547 const char *keywords[] = {"FLOAT", "FLOAT3", "FLOAT4", "COLOR", "BOOL", "SAMPLERCUBE", "SAMPLER2D", ""};
00548 switch (tmpParser.KeywordsSwitch(keywords))
00549 {
00550 case 0:
00551 {
00552 size_t n = tmpParser.ParseVector(param.fVals, 0, true);
00553 if (n == 0)
00554 return false;
00555 param.type = ShaderParam::PARAM_TYPE(ShaderParam::FLOAT1);
00556 }
00557 break;
00558 case 1:
00559 case 2:
00560 case 3:
00561 case 4:
00562 {
00563 size_t n = tmpParser.ParseVector(param.fVals, 0, true);
00564 if (n == 0)
00565 return false;
00566 param.type = ShaderParam::PARAM_TYPE(ShaderParam::FLOAT1 + n - 1);
00567 }
00568 break;
00569 case 5:
00570 case 6:
00571 {
00572 param.type = ShaderParam::SAMPLER;
00573 wxString texPath = scenePath + tmpParser.GetWxLine().AfterFirst('\'').BeforeLast('\'');
00574 wxCommandEvent texEvt = Event::GET_EVT_SCENE_IMAGE_ADD(texPath);
00575 module->PostToKernel(texEvt);
00576 param.imageName = texPath;
00577 texturesImported++;
00578 }
00579 break;
00580 default:
00581 logErrorMsg(UNEXPECTED, tmpParser.GetWxLine());
00582 }
00583 material->shader->paramList.push_back(param);
00584 }
00585 break;
00586 case 12:
00587 {
00588 if (!tmpParser.ParseFloat(&material->textureMix))
00589 return false;
00590 }
00591 break;
00592 case 13:
00593 {
00594 const char *envKeywords[] = {"None", "Zero", "One", "SrcColor", "OneMinusSrcColor", "DstColor", "OneMinusDstColor", "SrcAlpha", "OneMinusSrcAlpha", "DstAlpha", ""};
00595 const GLuint values[] = {GL_ZERO, GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA};
00596 GLuint * funcTgt = &material->texBlendSrc;
00597 for (int i = 0; i < 2; i++)
00598 {
00599 int index = tmpParser.KeywordsSwitch(envKeywords);
00600 if (i >= 0)
00601 *funcTgt = values[index];
00602 else
00603 logErrorMsg(UNEXPECTED, tmpParser.GetWxLine());
00604 funcTgt = &material->texBlendDst;
00605 }
00606 material->flags |= Material::BLENDED;
00607 }
00608 break;
00609 case 14:
00610 {
00611 wxString activate(tmpParser.GetWxLine());
00612 }
00613 break;
00614 case 15:
00615 {
00616 wxString deactivate(tmpParser.GetWxLine());
00617 }
00618 break;
00619 case 16:
00620 {
00621 int cubetexindex;
00622 if (!tmpParser.ParseInt(&cubetexindex))
00623 return false;
00624 wxString cubetexname(tmpParser.GetWxLine());
00625 }
00626 break;
00627 case 17:
00628 {
00629 float linewidth;
00630 if (!tmpParser.ParseFloat(&linewidth))
00631 return false;
00632 }
00633 break;
00634 default:
00635 logErrorMsg(UNEXPECTED, tmpParser.GetWxLine());
00636 }
00637 }
00638 break;
00639 case 12:
00640 if (!textParser->ParseVector(color._v, 3))
00641 return false;
00642 break;
00643 case 13:
00644 material->flags |= Material::UNLIT;
00645 break;
00646 case 14:
00647 cycle = false;
00648 break;
00649 default:
00650 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00651 }
00652 }
00653 return true;
00654 }
00655
00656
00657 bool FHSParser::parseMaterial()
00658 {
00659 wxString matName = textParser->GetWxString();
00660 Material * material = new Material(matName);
00661 if (parseMaterialAttribs(material))
00662 {
00663 wxCommandEvent ev = Event::GET_EVT_SCENE_MATERIAL_ADD(sceneID, material);
00664 module->PostToKernel(ev);
00665 materialsImported++;
00666 return true;
00667 }
00668 else
00669 {
00670 SAFE_DELETE(material);
00671 LOGERROR(wxT("<FHSParser>Failed parsing material '") + matName + wxT("'"));
00672 return false;
00673 }
00674 }
00675
00676
00677 bool FHSParser::parseEnvironmentBody(const wxString & nodeUid)
00678 {
00679
00680 if (textParser->GetChar() != '{')
00681 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00682 const char *keywords[] = {"BACKGROUND", "AMBIENT", "ENVX", "}", ""};
00683 bool cycle = true;
00684 while (cycle)
00685 {
00686 switch (textParser->KeywordsSwitch(keywords))
00687 {
00688 case 0:
00689 {
00690 VECTOR3 background;
00691 if (textParser->ParseVector(background._v, 3) != 3)
00692 return false;
00693 }
00694 break;
00695 case 1:
00696 {
00697 VECTOR3 ambient;
00698 if (textParser->ParseVector(ambient._v, 3) != 3)
00699 return false;
00700 }
00701 break;
00702 case 2:
00703 {
00704
00705 TextParser tmpParser(textParser->GetString().c_str());
00706 const char *envKeywords[] = {"FOGDENSITY", "FOGCOLOR", ""};
00707 switch (tmpParser.KeywordsSwitch(envKeywords))
00708 {
00709 case 0:
00710 {
00711 float fogdensity;
00712 if (!tmpParser.ParseFloat(&fogdensity))
00713 return false;
00714 }
00715 break;
00716 case 1:
00717 {
00718 float fogcolor[4];
00719 if (tmpParser.ParseVector(fogcolor, 4) != 4)
00720 return false;
00721 }
00722 break;
00723 default:
00724 logErrorMsg(UNEXPECTED, tmpParser.GetWxLine());
00725 }
00726 }
00727 break;
00728 case 3:
00729 cycle = false;
00730 break;
00731 default:
00732 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00733 }
00734 }
00735 return true;
00736 }
00737
00738
00739 bool FHSParser::parseEnvironmentAttribs(wxString &nodeUid)
00740 {
00741 if (!parseCommonAttribs(nodeUid))
00742 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00743 return true;
00744 }
00745
00746
00747 bool FHSParser::parseEnvironment(const wxString & parentUid)
00748 {
00749
00751 wxString nodeName = textParser->GetWxString();
00752 wxString nodeUid = getUniqueUid(nodeName);
00753
00754
00755
00756
00757
00758
00759 if (!parseEnvironmentAttribs(nodeUid) || !parseEnvironmentBody(nodeUid))
00760 {
00761 LOGERROR(wxT("<FHSParser>Failed parsing environment '") + nodeUid + wxT("'"));
00762 return false;
00763 }
00764 LOGWARNING(wxT("Environment not implemented"));
00765 return true;
00766 }
00767
00768
00769 bool FHSParser::parseLightBody(Light * light)
00770 {
00771 if (textParser->GetChar() != '{')
00772 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00773 const char *keywords[] = {"COLOR", "DIRECTION", "POSITION", "SPOTLIGHT", "LIGHTX", "}", ""};
00774 bool cycle = true;
00775 while (cycle)
00776 {
00777 switch (textParser->KeywordsSwitch(keywords))
00778 {
00779 case 0:
00780 if (textParser->ParseVector(light->diffuse._v, 3) != 3)
00781 return false;
00782 break;
00783 case 1:
00784 if (textParser->ParseVector(light->direction._v, 3) != 3)
00785 return false;
00786 switch (light->type)
00787 {
00788 case Light::UNKNOWN:
00789 case Light::DIRECTIONAL:
00790 light->type = Light::DIRECTIONAL;
00791 break;
00792 case Light::OMNI:
00793 case Light::SPOTLIGHT:
00794 light->type = Light::SPOTLIGHT;
00795 break;
00796 }
00797 break;
00798 case 2:
00799 if (textParser->ParseVector(light->position._v, 3) != 3)
00800 return false;
00801 switch (light->type)
00802 {
00803 case Light::UNKNOWN:
00804 case Light::OMNI:
00805 light->type = Light::OMNI;
00806 break;
00807 case Light::DIRECTIONAL:
00808 case Light::SPOTLIGHT:
00809 light->type = Light::SPOTLIGHT;
00810 break;
00811 }
00812 break;
00813 case 3:
00814 {
00815 float spotlight[2];
00816 if (textParser->ParseVector(spotlight, 2) != 2)
00817 return false;
00818 light->angle = spotlight[0];
00819 light->exponent = spotlight[1];
00820 light->type = Light::SPOTLIGHT;
00821 }
00822 break;
00823 case 4:
00824 textParser->GetWxString();
00825 break;
00826 case 5:
00827 cycle = false;
00828 break;
00829 default:
00830 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00831 }
00832 }
00833 return true;
00834 }
00835
00836
00837 bool FHSParser::parseLightAttribs(wxString &nodeUid)
00838 {
00839 if (!parseCommonAttribs(nodeUid))
00840 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00841 return true;
00842 }
00843
00844
00845 bool FHSParser::parseLight(const wxString & parentUid)
00846 {
00848 wxString nodeName = textParser->GetWxString();
00849 wxString nodeUid = getUniqueUid(nodeName);
00850 LightNode * node = new LightNode(nodeUid, nodeName);
00851 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_INSERT(sceneID, node, parentUid);
00852 module->PostToKernel(ev);
00853 nodesImported++;
00854
00855 Light * light = new Light;
00856
00857 if (!parseLightAttribs(nodeUid) || !parseLightBody(light))
00858 {
00859 LOGERROR(wxT("<FHSParser>Failed parsing light '") + nodeUid + wxT("'"));
00860 SAFE_DELETE(light);
00861 return false;
00862 }
00863
00864 wxCommandEvent ev2 = Event::GET_EVT_SCENE_NODE_LIGHT_SET(sceneID, nodeUid, light);
00865 module->PostToKernel(ev2);
00866 lightsImported++;
00867
00868 return true;
00869 }
00870
00871
00872 bool FHSParser::parseGeometryBody(const wxString & nodeUid, GeometryTriangles * geometry, bool &valid)
00873 {
00874 valid = true;
00875 if (textParser->GetChar() != '{')
00876 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00877 std::vector<GeometryTriangles::Indice> * indices = &(geometry->indices);
00878 GeometryTriangles::TriDescList * triDescList = &geometry->triDescList;
00879 const char *keywords[] = {"TRIANGLES", "TRIANGLE_STRIP", "TRIFAN", "POLYGON", "LINES", "LINE_STRIP", "POINTS", "QUADS", "PRIMX", "USEMAT", "BOX", "}", ""};
00880 bool cycle = true;
00881 while (cycle)
00882 {
00883 switch (textParser->KeywordsSwitch(keywords))
00884 {
00885 case 0:
00886 if (triDescList->empty() || triDescList->back().second != GeometryTriangles::TRI_LIST)
00887 {
00888 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::TRI_LIST);
00889 triDescList->push_back(indType);
00890 }
00891 if (!parseIndices(indices, geometry->vertices.size()))
00892 return false;
00893 break;
00894 case 1:
00895 {
00896 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::TRI_STRIP);
00897 triDescList->push_back(indType);
00898 if (!parseIndices(indices, geometry->vertices.size()))
00899 return false;
00900 }
00901 break;
00902 case 2:
00903 {
00904 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::TRI_FAN);
00905 triDescList->push_back(indType);
00906 }
00907 if (!parseIndices(indices, geometry->vertices.size()))
00908 return false;
00909 break;
00910 case 3:
00911 {
00912 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::POLYGON);
00913 triDescList->push_back(indType);
00914 }
00915 if (!parseIndices(indices, geometry->vertices.size()))
00916 return false;
00917 break;
00918 case 4:
00919 if (triDescList->empty() || triDescList->back().second != GeometryTriangles::LINES)
00920 {
00921 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::LINES);
00922 triDescList->push_back(indType);
00923 }
00924 if (!parseIndices(indices, geometry->vertices.size()))
00925 return false;
00926 break;
00927 case 5:
00928 {
00929 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::LINE_STRIP);
00930 triDescList->push_back(indType);
00931 }
00932 if (!parseIndices(indices, geometry->vertices.size()))
00933 return false;
00934 break;
00935 case 6:
00936 if (triDescList->empty() || triDescList->back().second != GeometryTriangles::POINTS)
00937 {
00938 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::POINTS);
00939 triDescList->push_back(indType);
00940 }
00941 if (!parseIndices(indices, geometry->vertices.size()))
00942 return false;
00943 break;
00944 case 7:
00945 if (triDescList->empty() || triDescList->back().second != GeometryTriangles::QUADS)
00946 {
00947 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::QUADS);
00948 triDescList->push_back(indType);
00949 }
00950 if (!parseIndices(indices, geometry->vertices.size()))
00951 return false;
00952 break;
00953 case 8:
00954 {
00955
00956 TextParser txtParser(textParser->GetWxString());
00957 const char *keywords[] = {"FROM", ""};
00958 switch (txtParser.KeywordsSwitch(keywords))
00959 {
00960 case 0:
00961 {
00962 wxCommandEvent ev3 = Event::GET_EVT_SCENE_NODE_GEOMETRY_SET(sceneID, nodeUid, txtParser.GetWxString());
00963 module->PostToKernel(ev3);
00964 SAFE_DELETE(geometry);
00965 valid = false;
00966 size_t brackCount = 1;
00967 while (brackCount > 0)
00968 {
00969 switch (textParser->GetChar())
00970 {
00971 case '{':
00972 brackCount++;
00973 break;
00974 case '}':
00975 brackCount--;
00976 break;
00977 }
00978 }
00979 return true;
00980 }
00981 default:
00982 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
00983 break;
00984 }
00985 }
00986 break;
00987 case 9:
00988 {
00989
00990 wxString matName(textParser->GetWxString());
00991 }
00992 break;
00993 case 10:
00994 if (!parsePolyBox(geometry))
00995 return false;
00996 break;
00997 case 11:
00998 cycle = false;
00999 break;
01000 default:
01001 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01002 }
01003 }
01004 return true;
01005 }
01006
01007 bool FHSParser::parseCommonAttribs(wxString &nodeUid)
01008 {
01009 const char *keywords[] = {"DESCX", "MATRIX", "TRANSLATE", "SCALE", "ROTATE", ""};
01010 while (!textParser->NextCharIs('{'))
01011 {
01012 if (module->TestExit())
01013 textParser->ForceEmpty();
01014
01015 switch (textParser->KeywordsSwitch(keywords))
01016 {
01017 case 0:
01018 {
01019
01020 TextParser tmpParser(textParser->GetString().c_str());
01021 const char *envKeywords[] = {"UID", "SIZES", "TEXTURE_ATTRIBUTES", "LODTYPE", "UNUSED", "MIRROR", "OPENRTBINARY", ""};
01022 switch (tmpParser.KeywordsSwitch(envKeywords))
01023 {
01024 case 0:
01025 {
01026 wxString newUid(getUniqueUid(tmpParser.GetWxString()));
01027 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_UID_SET(sceneID, nodeUid, newUid);
01028 module->PostToKernel(ev);
01029 nodeUid = newUid;
01030 }
01031 break;
01032 case 1:
01033 {
01034 int sizes[3];
01035 if (!tmpParser.ParseInt(&sizes[0]))
01036 return false;
01037 if (!tmpParser.ParseInt(&sizes[1]))
01038 return false;
01039 if (!tmpParser.ParseInt(&sizes[2]))
01040 return false;
01041 }
01042 break;
01043 case 2:
01044 {
01045 const char *envKeywords[] = {"flip_textureS", "flip_textureT", "planar_scaleS", "planar_scaleT", "planar_translationS", "planar_translationT", ""};
01046 int index;
01047 while ((index = tmpParser.KeywordsSwitch(envKeywords)) >= 0)
01048 {
01049 switch (index)
01050 {
01051 case 0:
01052 {
01053 int flip_textureS;
01054 if (!tmpParser.ParseInt(&flip_textureS))
01055 return false;
01056 }
01057 break;
01058 case 1:
01059 {
01060 int flip_textureT;
01061 if (!tmpParser.ParseInt(&flip_textureT))
01062 return false;
01063 }
01064 break;
01065 case 2:
01066 {
01067 float planar_scaleS;
01068 if (!tmpParser.ParseFloat(&planar_scaleS))
01069 return false;
01070 }
01071 break;
01072 case 3:
01073 {
01074 float planar_scaleT;
01075 if (!tmpParser.ParseFloat(&planar_scaleT))
01076 return false;
01077 }
01078 break;
01079 case 4:
01080 {
01081 float planar_translationS;
01082 if (!tmpParser.ParseFloat(&planar_translationS))
01083 return false;
01084 }
01085 break;
01086 case 5:
01087 {
01088 float planar_translationT;
01089 if (!tmpParser.ParseFloat(&planar_translationT))
01090 return false;
01091 }
01092 break;
01093 case 6:
01094 {
01095 float planar_translationS;
01096 if (!tmpParser.ParseFloat(&planar_translationS))
01097 return false;
01098 }
01099 break;
01100 default:
01101 wxString textureattributes(tmpParser.GetWxLine());
01102
01103 }
01104 }
01105 }
01106 break;
01107 case 3:
01108 {
01109 wxString lodtype(tmpParser.GetWxString());
01110 }
01111 break;
01112 case 4:
01113 break;
01114 case 5:
01115 break;
01116 case 6:
01117 {
01118 wxString openrtbinary(tmpParser.GetWxLine());
01119 }
01120 break;
01121 default:
01122 logErrorMsg(UNEXPECTED, tmpParser.GetWxLine());
01123 }
01124 }
01125 break;
01126 case 1:
01127 {
01128 MATRIX mat;
01129 if (textParser->ParseVector(mat._m, 16) != 16)
01130 return false;
01131 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORM(sceneID, nodeUid, mat);
01132 module->PostToKernel(ev);
01133 }
01134 break;
01135 case 2:
01136 {
01137 VECTOR3 v;
01138 if (textParser->ParseVector(v._v, 3) != 3)
01139 return false;
01140 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_TRANSFORM(sceneID, nodeUid, MATRIX::Translation(v));
01141 module->PostToKernel(ev);
01142 }
01143 break;
01144 case 3:
01145 if (!parseScale(nodeUid))
01146 return false;
01147 break;
01148 case 4:
01149 if (!parseRotate(nodeUid))
01150 return false;
01151 break;
01152 default:
01153 return false;
01154 }
01155 }
01156 return true;
01157 }
01158
01159
01160 bool FHSParser::parseCommonBody(const wxString & nodeUid)
01161 {
01162 const char *keywords[] = {"ASSEMBLY", "GEOMETRY", "LODASSEMBLY", "LOD", "LIGHT", "ENVIRONMENT", "BILLBOARD", "SWITCH", ""};
01163 while (!textParser->NextCharIs('}'))
01164 {
01165 if (module->TestExit())
01166 textParser->ForceEmpty();
01167
01168 switch (textParser->KeywordsSwitch(keywords))
01169 {
01170 case 0:
01171 if (!parseAssembly(nodeUid))
01172 return false;
01173 break;
01174 case 1:
01175 if (!parseGeometry(nodeUid))
01176 return false;
01177 break;
01178 case 2:
01179 if (!parseLODAssembly(nodeUid))
01180 return false;
01181 break;
01182 case 3:
01183 if (!parseAssembly(nodeUid))
01184 return false;
01185 break;
01186 case 4:
01187 if (!parseLight(nodeUid))
01188 return false;
01189 break;
01190 case 5:
01191 if (!parseEnvironment(nodeUid))
01192 return false;
01193 break;
01194 case 6:
01195 if (!parseBillboard(nodeUid))
01196 return false;
01197 break;
01198 case 7:
01199 if (!parseSwitch(nodeUid))
01200 return false;
01201 break;
01202 default:
01203 return false;
01204 }
01205 }
01206 return true;
01207 }
01208
01209
01210 bool FHSParser::parseGeometryAttribs(wxString &nodeUid, GeometryTriangles * geometry)
01211 {
01212 const char *keywords[] = {"USEMAT", "POLYPOOL", "RESOLUTION", ""};
01213 while (!textParser->NextCharIs('{'))
01214 {
01215 if (!parseCommonAttribs(nodeUid))
01216 {
01217 switch (textParser->KeywordsSwitch(keywords))
01218 {
01219 case 0:
01220 {
01221
01222 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_MATERIAL_SET(sceneID, nodeUid, textParser->GetWxString());
01223 module->PostToKernel(ev);
01224 }
01225 break;
01226 case 1:
01227 if (!parsePolyPool(geometry))
01228 return false;
01229 if (!geometry->texCoords.empty() && ( geometry->texCoords.size() != geometry->vertices.size() ))
01230 {
01231 LOGWARNING(wxT("<FHSParser>Texture coords count and vertices count mismatch"));
01232 for (size_t i=geometry->vertices.size()-geometry->texCoords.size(); i>0; i--)
01233 geometry->texCoords.push_back(GeometryTriangles::TexCoord());
01234 }
01235 if (!geometry->normals.empty() && ( geometry->normals.size() != geometry->vertices.size() ))
01236 {
01237 LOGWARNING(wxT("<FHSParser>Normals count and vertices count mismatch"));
01238 for (size_t i=geometry->vertices.size()-geometry->normals.size(); i>0; i--)
01239 geometry->normals.push_back(VECTOR3());
01240 }
01241 break;
01242 case 2:
01243 {
01244 wxString resolution(textParser->GetWxString());
01245 }
01246 break;
01247 default:
01248 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01249 }
01250 }
01251 }
01252 return true;
01253 }
01254
01255
01256 bool FHSParser::parseGeometry(const wxString & parentUid)
01257 {
01259 wxString nodeName = textParser->GetWxString();
01260 wxString nodeUid = getUniqueUid(nodeName);
01261 GeometryNode *node = new GeometryNode(nodeUid, nodeName);
01262 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_INSERT(sceneID, node, parentUid);
01263 module->PostToKernel(ev);
01264 nodesImported++;
01265 nodesGeomImported++;
01267
01268 GeometryTriangles *geometry = new GeometryTriangles(nodeUid);
01269
01271 bool valid;
01272 if (!parseGeometryAttribs(nodeUid, geometry) || !parseGeometryBody(nodeUid, geometry, valid))
01273 {
01274 SAFE_DELETE(geometry);
01275 LOGERROR(wxT("<FHSParser>Failed parsing geometry '") + nodeUid + wxT("'"));
01276 return false;
01277 }
01278
01279
01280 if (valid)
01281 {
01283 wxCommandEvent ev2 = Event::GET_EVT_SCENE_GEOMETRY_ADD(sceneID, geometry);
01284 module->PostToKernel(ev2);
01286 wxCommandEvent ev3 = Event::GET_EVT_SCENE_NODE_GEOMETRY_SET(sceneID, nodeUid, geometry->GetName());
01287 module->PostToKernel(ev3);
01288 }
01289 return true;
01290 }
01291
01292
01293 bool FHSParser::parseSwitchAttribs(wxString &nodeUid)
01294 {
01295 const char *keywords[] = {"USEMAT", "WHICHCHILD", ""};
01296 while (!textParser->NextCharIs('{'))
01297 {
01298 if (!parseCommonAttribs(nodeUid))
01299 {
01300 switch (textParser->KeywordsSwitch(keywords))
01301 {
01302 case 0:
01303 {
01304
01305 wxString matName(textParser->GetWxString());
01306 }
01307 break;
01308 case 1:
01309 {
01310
01311 wxString whichchild(textParser->GetWxString());
01312 }
01313 break;
01314 default:
01315 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01316 }
01317 }
01318 }
01319 return true;
01320 }
01321
01322
01323 bool FHSParser::parseSwitch(const wxString & parentUid)
01324 {
01326 wxString nodeName = textParser->GetWxString();
01327 wxString nodeUid = getUniqueUid(nodeName);
01328 SceneNode * node = new SceneNode(nodeUid, nodeName, SceneNode::ASSEMBLY);
01329 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_INSERT(sceneID, node, parentUid);
01330 module->PostToKernel(ev);
01331 nodesImported++;
01332 LOGWARNING(wxT("Swithch not implemented"));
01333 return parseSwitchAttribs(nodeUid) && parseAssemblyBody(nodeUid);
01334 }
01335
01336
01337 bool FHSParser::parseBillboardAttribs(wxString &nodeUid)
01338 {
01339 const char *keywords[] = {"USEMAT", "AXIS", "XAXIS", "YAXIS", "ZAXIS", ""};
01340 VECTOR3 axis;
01341 while (!textParser->NextCharIs('{'))
01342 {
01343 if (!parseCommonAttribs(nodeUid))
01344 {
01345 switch (textParser->KeywordsSwitch(keywords))
01346 {
01347 case 0:
01348 {
01349
01350 wxString matName(textParser->GetWxString());
01351 }
01352 break;
01353 case 1:
01354 if (textParser->ParseVector(axis._v, 3) != 3)
01355 return false;
01356 break;
01357 case 2:
01358 axis = vector3(1, 0, 0);
01359 break;
01360 case 3:
01361 axis = vector3(0, 1, 0);
01362 break;
01363 case 4:
01364 axis = vector3(0, 0, 1);
01365 break;
01366 default:
01367 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01368 }
01369 }
01370 }
01371 return true;
01372 }
01373
01374
01375 bool FHSParser::parseBillboard(const wxString & parentUid)
01376 {
01378 wxString nodeName = textParser->GetWxString();
01379 wxString nodeUid = getUniqueUid(nodeName);
01380 SceneNode * node = new SceneNode(nodeUid, nodeName, SceneNode::ASSEMBLY);
01381 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_INSERT(sceneID, node, parentUid);
01382 module->PostToKernel(ev);
01383 nodesImported++;
01384 LOGWARNING(wxT("Billboard not implemented"));
01385 return parseBillboardAttribs(nodeUid) && parseAssemblyBody(nodeUid);
01386 }
01387
01388
01389 bool FHSParser::parseLOD(const wxString & parentUid, const bool active)
01390 {
01392 wxString nodeName = textParser->GetWxString();
01393 wxString nodeUid = getUniqueUid(nodeName);
01394 SceneNode * node = new SceneNode(nodeUid, nodeName, SceneNode::ASSEMBLY);
01395 node->SetActive(active);
01396 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_INSERT(sceneID, node, parentUid);
01397 module->PostToKernel(ev);
01398 nodesImported++;
01399
01400 return parseAssemblyAttribs(nodeUid) && parseAssemblyBody(nodeUid);
01401 }
01402
01403
01404 bool FHSParser::parseLODAssemblyBody(const wxString & nodeUid)
01405 {
01406 if (textParser->GetChar() != '{')
01407 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01408 const char *keywords[] = {"LOD", ""};
01409 bool active=true;
01410 while (!textParser->NextCharIs('}'))
01411 {
01412 if (module->TestExit())
01413 textParser->ForceEmpty();
01414
01415 switch (textParser->KeywordsSwitch(keywords))
01416 {
01417 case 0:
01418 if (!parseLOD(nodeUid, active))
01419 return false;
01420 active=false;
01421 break;
01422 default:
01423 return false;
01424 }
01425 }
01426 if (textParser->GetChar() != '}')
01427 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01428 return true;
01429 }
01430
01431
01432 bool FHSParser::parseLODAssembly(const wxString & parentUid)
01433 {
01435 wxString nodeName = textParser->GetWxString();
01436 wxString nodeUid = getUniqueUid(nodeName);
01437 SceneNode * node = new SceneNode(nodeUid, nodeName, SceneNode::ASSEMBLY);
01438 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_INSERT(sceneID, node, parentUid);
01439 module->PostToKernel(ev);
01440 nodesImported++;
01441 LOGWARNING(wxT("LODAssembly not implemented"));
01442 return parseAssemblyAttribs(nodeUid) && parseLODAssemblyBody(nodeUid);
01443 }
01444
01445
01446 bool FHSParser::parseAssemblyBody(const wxString & nodeUid)
01447 {
01448 if (textParser->GetChar() != '{')
01449 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01450 if (!parseCommonBody(nodeUid))
01451 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01452 if (textParser->GetChar() != '}')
01453 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01454 return true;
01455 }
01456
01457
01458 bool FHSParser::parseAssemblyAttribs(wxString &nodeUid)
01459 {
01460 const char *keywords[] = {"USEMAT", ""};
01461 while (!textParser->NextCharIs('{'))
01462 {
01463 if (!parseCommonAttribs(nodeUid))
01464 {
01465 switch (textParser->KeywordsSwitch(keywords))
01466 {
01467 case 0:
01468 {
01469
01470 wxString matName(textParser->GetWxString());
01471 }
01472 break;
01473 default:
01474 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01475 }
01476 }
01477 }
01478 return true;
01479 }
01480
01481
01482 bool FHSParser::parseAssembly(const wxString & parentUid)
01483 {
01485 wxString nodeName = textParser->GetWxString();
01486 wxString nodeUid = getUniqueUid(nodeName);
01487 SceneNode * node = new SceneNode(nodeUid, nodeName, SceneNode::ASSEMBLY);
01488 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_INSERT(sceneID, node, parentUid);
01489 module->PostToKernel(ev);
01490 nodesImported++;
01491
01492 return parseAssemblyAttribs(nodeUid) && parseAssemblyBody(nodeUid);
01493 }
01494
01495
01496 bool FHSParser::parseModelAttribs(const wxString & nodeUid)
01497 {
01498 const char *keywords[] = {"FHSVERSION", "POINTORDER", "DEFMAT", "CIRCLE", ""};
01499 while (!textParser->IsEmpty())
01500 {
01501 if (!parseCommonBody(nodeUid))
01502 {
01503 switch (textParser->KeywordsSwitch(keywords))
01504 {
01505 case 0:
01506 if (!textParser->NextKeywordIs("1100"))
01507 LOGWARNING(wxT("<FHSParser>Unknown FHSVERSION") + textParser->GetWxLine());
01508 break;
01509 case 1:
01510 if (!textParser->NextKeywordIs("COUNTERCLOCKWISE"))
01511 return logErrorMsg(UNEXPECTED, wxT("POINTORDER ") + textParser->GetWxLine());
01512 break;
01513 case 2:
01514 if (!parseMaterial())
01515 return false;
01516 break;
01517 case 3:
01518 {
01519
01520 GeometryNode *node = new GeometryNode(nodeUid+wxT("Geometry"), nodeUid+wxT("Geometry"));
01521 wxCommandEvent ev3(Event::GET_EVT_SCENE_NODE_INSERT(sceneID, node, nodeUid));
01522 module->PostToKernel(ev3);
01523
01524
01525 wxCommandEvent ev4(Event::GET_EVT_SCENE_NODE_MATERIAL_SET(sceneID, nodeUid+wxT("Geometry"), wxT("CIRCLE")));
01526 module->PostToKernel(ev4);
01527
01528
01529 GeometryTriangles *geometry = new GeometryTriangles(nodeUid+wxT("Geometry"));
01530 std::vector<VECTOR3> * verts = &(geometry->vertices);
01531 std::vector<VECTOR3> * normals = &(geometry->normals);
01532 std::vector<GeometryTriangles::TexCoord> * texCoords = &(geometry->texCoords);
01533 std::vector<GeometryTriangles::Indice> * indices = &(geometry->indices);
01534 GeometryTriangles::TriDescList * triDescList = &geometry->triDescList;
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType((GeometryTriangles::Indice)indices->size(), GeometryTriangles::TRI_STRIP);
01564 triDescList->push_back(indType);
01565 float anglestep=360.0f/10800.0f;
01566 float ih=0.0f, oh=0.0f;
01567 for (float angle=0.0f; angle<360.0f; angle+=anglestep)
01568 {
01569 float ca=cos(angle/180*3.14159);
01570 float sa=sin(angle/180*3.14159);
01571 ih=(float)rand()/RAND_MAX*50;
01572 oh=(float)rand()/RAND_MAX*50;
01573 verts->push_back(VECTOR3(170000*sa, 170000*ca-175000,0));
01574 verts->push_back(VECTOR3(174000*sa, 174000*ca-175000,ih));
01575 LOG(wxString::Format(wxT("%g\t%g"), -175000*sa, 175000*ca-175000));
01576 verts->push_back(VECTOR3(176000*sa, 176000*ca-175000,oh));
01577 verts->push_back(VECTOR3(180000*sa, 180000*ca-175000,0));
01578 normals->push_back(VECTOR3(0,0,1));
01579 normals->push_back(VECTOR3(0,0,1));
01580 normals->push_back(VECTOR3(0,0,1));
01581 normals->push_back(VECTOR3(0,0,1));
01582 texCoords->push_back(GeometryTriangles::TexCoord(angle/360.0f, 0));
01583 texCoords->push_back(GeometryTriangles::TexCoord(angle/360.0f, 0.4));
01584 texCoords->push_back(GeometryTriangles::TexCoord(angle/360.0f, 0.6));
01585 texCoords->push_back(GeometryTriangles::TexCoord(angle/360.0f, 1));
01586
01587 indices->push_back((GeometryTriangles::Indice)verts->size()-3);
01588 indices->push_back((GeometryTriangles::Indice)verts->size()-4);
01589 }
01590
01591 verts->push_back(verts->at(0));
01592 verts->push_back(verts->at(1));
01593 verts->push_back(verts->at(2));
01594 verts->push_back(verts->at(3));
01595 normals->push_back(VECTOR3(0,0,1));
01596 normals->push_back(VECTOR3(0,0,1));
01597 normals->push_back(VECTOR3(0,0,1));
01598 normals->push_back(VECTOR3(0,0,1));
01599 texCoords->push_back(GeometryTriangles::TexCoord(1, 0));
01600 texCoords->push_back(GeometryTriangles::TexCoord(1, 0.4));
01601 texCoords->push_back(GeometryTriangles::TexCoord(1, 0.6));
01602 texCoords->push_back(GeometryTriangles::TexCoord(1, 1));
01603
01604 indices->push_back((GeometryTriangles::Indice)verts->size()-3);
01605 indices->push_back((GeometryTriangles::Indice)verts->size()-4);
01606
01607 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType2((GeometryTriangles::Indice)indices->size(), GeometryTriangles::TRI_STRIP);
01608 triDescList->push_back(indType2);
01609 for (GeometryTriangles::Indice index=1; index<verts->size(); index+=4)
01610 {
01611 indices->push_back(index+1);
01612 indices->push_back(index);
01613 }
01614
01615 std::pair<GeometryTriangles::Indice, GeometryTriangles::PRIMITIVE_TYPE> indType3((GeometryTriangles::Indice)indices->size(), GeometryTriangles::TRI_STRIP);
01616 triDescList->push_back(indType3);
01617 for (GeometryTriangles::Indice index=2; index<verts->size(); index+=4)
01618 {
01619 indices->push_back(index+1);
01620 indices->push_back(index);
01621 }
01622
01624 wxCommandEvent ev5(Event::GET_EVT_SCENE_GEOMETRY_ADD(sceneID, geometry));
01625 module->PostToKernel(ev5);
01627 wxCommandEvent ev6(Event::GET_EVT_SCENE_NODE_GEOMETRY_SET(sceneID, nodeUid+wxT("Geometry"), geometry->GetName()));
01628 module->PostToKernel(ev6);
01629 }
01630 default:
01631 if (textParser->IsEmpty())
01632 return true;
01633 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01634 }
01635 }
01636 else if (!textParser->IsEmpty())
01637 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01638 }
01639 return true;
01640 }
01641
01642
01643 bool FHSParser::parseModel(const wxString & nodeUid)
01644 {
01645 if (textParser->NextKeywordIs("MODEL"))
01646 {
01648 wxCommandEvent ev = Event::GET_EVT_SCENE_NODE_NAME_SET(sceneID, nodeUid, textParser->GetWxString());
01649 module->PostToKernel(ev);
01650 return parseModelAttribs(nodeUid);
01651 }
01652 else
01653 return logErrorMsg(UNEXPECTED, textParser->GetWxLine());
01654 }
01655
01656
01657 bool FHSParser::Parse(const wxString & rootUid)
01658 {
01659 if (!parseModel(rootUid))
01660 {
01661 LOGERROR(wxT("<FHSParser>Scene not parsed properly"));
01662 return false;
01663 }
01664 LOG(wxString::Format(
01665 wxT("<FHSParser>Nodes parsed: %i (%i geometry nodes, %i light nodes)"),
01666 nodesImported, nodesGeomImported, lightsImported));
01667 LOG(wxString::Format(
01668 wxT("<FHSParser>Materials parsed: %i\tTextures parsed: %i "),
01669 materialsImported, texturesImported));
01670
01671 return true;
01672 }