00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <wx/filename.h>
00011 #include <wx/utils.h>
00012 #include <wx/datetime.h>
00013 #include <math.h>
00014 #include "vrmlwriter.h"
00015
00016 using namespace VRUT;
00017
00018
00019
00020
00021
00022 #define CTL_CHARS 31
00023 #define SINGLE_QUOTE 39
00024
00025 static char* VRMLName(const char* name)
00026 {
00027 static char buffer[256];
00028 int seqnum = 0;
00029 char* cPtr;
00030 int firstCharacter = 1;
00031
00032 strncpy(buffer, name, 256);
00033 cPtr = buffer;
00034 while(*cPtr) {
00035 if( *cPtr <= CTL_CHARS ||
00036 *cPtr == ' ' ||
00037 *cPtr == SINGLE_QUOTE ||
00038 *cPtr == '"' ||
00039 *cPtr == '\\' ||
00040 *cPtr == '{' ||
00041 *cPtr == '}' ||
00042 *cPtr == ',' ||
00043 *cPtr == '.' ||
00044 *cPtr == '[' ||
00045 *cPtr == ']' ||
00046 *cPtr == '-' ||
00047 *cPtr == '#' ||
00048 *cPtr >= 127 ||
00049 (firstCharacter && (*cPtr >= '0' && *cPtr <= '9'))) *cPtr = '_';
00050 firstCharacter = 0;
00051 cPtr++;
00052 }
00053
00054 return buffer;
00055 }
00056
00057 static char* VRMLName(const wxString& string)
00058 {
00059 return VRMLName((const char*)string.mb_str(wxConvUTF8));
00060 }
00061
00062
00063
00064
00065 VRMLWriter::VRMLWriter(wxBufferedOutputStream * _outputStream, const Scene * _scene, const wxString & _fname)
00066 : scene(_scene), outputStream(_outputStream), fname(_fname)
00067 {
00068 tw = new TextWriter(outputStream);
00069 maxBoundDistance = 0.0f;
00070 mode = 1;
00071 ccw = true;
00072 extraCams = false;
00073 }
00074
00075
00076 VRMLWriter::~VRMLWriter()
00077 {
00078 delete tw;
00080 }
00081
00082
00083 void VRMLWriter::Write(bool hFlag, bool _extraCams)
00084 {
00085 if(hFlag) mode = 1;
00086 else mode = 0;
00087 extraCams = _extraCams;
00088
00089 ccw = true;
00090 wxString tabs = wxT("");
00091
00092 tw->SetOutputStream(outputStream);
00093 LOGVERBOSE(wxT("<VRMLWriter>Inside VRMLWriter::Write."));
00094
00095 if (!scene->GetBVH())
00096 {
00097 LOGERROR(wxT("<VRMLWriter>Cannot initialize BVH, maxBoundDistance = 10000 forced."));
00098 maxBoundDistance = 10000;
00099 }
00100 else
00101 {
00102 VECTOR3 maxbound = scene->GetBVH()->GetRoot()->GetAABB()->MaxBound;
00103 VECTOR3 minbound = scene->GetBVH()->GetRoot()->GetAABB()->MinBound;
00104 maxBoundDistance = sqrt((maxbound.x-minbound.x)*(maxbound.x-minbound.x) +
00105 (maxbound.y-minbound.y)*(maxbound.y-minbound.y) + (maxbound.z-minbound.z)*(maxbound.z-minbound.z));
00106 }
00107
00108
00109 ExportFileInfo();
00110 ExportWorldInfo();
00111
00112
00113 const SceneNode::NodeIDList *children = scene->GetNode(scene->GetRootID())->GetChildren();
00114 for (SceneNode::NodeIDList::const_iterator it = children->begin() ; it != children->end(); it++)
00115 {
00116 const SceneNode * child = scene->GetNode(*it);
00117
00118 ExportNode1(child, &tabs);
00119 }
00120
00121 if(extraCams)
00122 {
00123 ExportCameras();
00124 }
00125
00126 for (SceneNode::NodeIDList::const_iterator it = children->begin() ; it != children->end(); it++)
00127 {
00128 const SceneNode * child = scene->GetNode(*it);
00129
00130 ExportNode2(child, &tabs, true);
00131 }
00132 outputStream->Sync();
00133 }
00134
00135
00136 void VRMLWriter::ExportFileInfo()
00137 {
00138 if(mode == 0) tw->Write("#VRML V2.0 utf8\n\n");
00139 else tw->Write("#VRML V2.0 utf8 VRUTexporter\n\n");
00140 tw->Write("#Produced by VRUT VRML97 exporter\n");
00141 tw->Write("#Date: ")->Write(wxDateTime::Now().FormatDate())->Write("\n\n");
00142 }
00143
00144
00145 void VRMLWriter::ExportWorldInfo()
00146 {
00147 tw->Write("WorldInfo {\n");
00148 tw->Write("\ttitle \"\"\n");
00149 tw->Write("\tinfo \"\"\n");
00150 tw->Write("}\n\n");
00151
00152 tw->Write("#file ")->Write(fname)->Write("\n\n");
00153 }
00154
00155
00156 void VRMLWriter::ExportNode1(const SceneNode * node, wxString * tabs)
00157 {
00158 if (node->IsOfType(SceneNode::ASSEMBLY))
00159 {
00160
00161 }
00162 else if (node->IsOfType(SceneNode::GEOMETRY))
00163 {
00164
00165 }
00166 else if (node->IsOfType(SceneNode::CAMERA))
00167 {
00168
00169 ExportCamera(node, tabs);
00170 }
00171 else if (node->IsOfType(SceneNode::LIGHT))
00172 {
00173
00174 ExportGeneralLight(node, tabs);
00175 }
00176 else
00177 {
00178 LOGERROR(wxT("<VRMLWriter>Unknown node type"));
00179 return;
00180 }
00181
00182 const SceneNode::NodeIDList *children = node->GetChildren();
00183 for (SceneNode::NodeIDList::const_iterator it = children->begin() ; it != children->end(); it++)
00184 {
00185 const SceneNode * child = scene->GetNode(*it);
00186 ExportNode1(child, tabs);
00187 }
00188 }
00189
00190
00191 void VRMLWriter::ExportNode2(const SceneNode * node, wxString * tabs, bool det)
00192 {
00193 const SceneNode::NodeIDList *children = node->GetChildren();
00194 if(!children)
00195 {
00196 return;
00197 }
00198 bool hasChildren = !children->empty();
00199
00200
00201 if ((node->IsOfType(SceneNode::CAMERA) || node->IsOfType(SceneNode::LIGHT)) && !hasChildren)
00202 {
00203 return;
00204 }
00205
00206
00207 tw->Write(*tabs)->Write("DEF ");
00208 if(node->GetName().size() > 0)
00209 tw->Write(VRMLName(node->GetName()));
00210 else tw->Write(node->GetID());
00211 tw->Write(" Transform {\n");
00212
00213 tabs->Append(wxT("\t"));
00214
00215
00216 bool det1 = ExportTransform(node, tabs, det);
00217
00218
00219 tw->Write(*tabs)->Write("children [\n");
00220
00221 tabs->Append(wxT("\t"));
00222
00223
00224
00225 if (node->IsOfType(SceneNode::GEOMETRY))
00226 {
00227
00228 ExportGeometry(node, tabs, det);
00229 }
00230
00231 for (SceneNode::NodeIDList::const_iterator it = children->begin() ; it != children->end(); it++)
00232 {
00233 const SceneNode * child = scene->GetNode(*it);
00234 ExportNode2(child, tabs, det1);
00235 }
00236
00237 tabs->RemoveLast();
00238 tw->Write(*tabs)->Write("]\n");
00239 tabs->RemoveLast();
00240 tw->Write(*tabs)->Write("}\n");
00241 }
00242
00243
00244 void VRMLWriter::ExportGeometry(const SceneNode * node, wxString * tabs, bool det)
00245 {
00246 const GeometryNode * geomNode = (const GeometryNode *)node;
00247 const Geometry * geom = scene->GetGeometry(geomNode->GetGeometryID());
00248 const GeometryTriangles * geometry = (GeometryTriangles *)geom;
00249 GeometryTriangles::TriDescList::const_iterator indPrimType = geometry->triDescList.begin();
00250
00251 tw->Write(*tabs)->Write("Shape {\n");
00252
00253 tabs->Append(wxT("\t"));
00254
00255 bool outputTexCoord = ExportAppearance(node, tabs);
00256
00257 if(indPrimType == geometry->triDescList.end())
00258 {
00259 tabs->RemoveLast();
00260 tw->Write(*tabs)->Write("}\n");
00261 return;
00262 }
00263 switch (indPrimType->second)
00264 {
00265 case GeometryTriangles::POLYGON:
00266 case GeometryTriangles::QUADS:
00267 case GeometryTriangles::TRI_FAN:
00268 case GeometryTriangles::TRI_LIST:
00269 case GeometryTriangles::TRI_STRIP:
00270 ExportIndexedFaceSet(node, tabs, det, outputTexCoord);
00271 break;
00272 case GeometryTriangles::LINE_STRIP:
00273 case GeometryTriangles::LINES:
00274 ExportIndexedLineSet(node, tabs);
00275 break;
00276 case GeometryTriangles::POINTS:
00277 ExportPointSet(node, tabs);
00278 break;
00279 default:
00280 LOGERROR(wxT("<VRMLWriter>Unknown node type"));
00281 }
00282
00283 tabs->RemoveLast();
00284 tw->Write(*tabs)->Write("}\n");
00285 }
00286
00287
00288 void VRMLWriter::ExportIndexedFaceSet(const SceneNode * node, wxString * tabs, bool det, bool outputTexCoord)
00289 {
00290 const GeometryNode * geomNode = (const GeometryNode *)node;
00291 const Geometry * geom = scene->GetGeometry(geomNode->GetGeometryID());
00292 const Material * material = scene->GetMaterial(geomNode->GetMaterialID());
00293
00294 if (!geom || geom->type != Geometry::GEOMETRY_TRIANGLE)
00295 {
00296 return;
00297 }
00298
00299
00300 const GeometryTriangles * geometry = (GeometryTriangles *)geom;
00301 const std::vector<VECTOR3> * vertices = &geometry->vertices;
00302 const std::vector<VECTOR3> * normals = &geometry->normals;
00303 const std::vector<GeometryTriangles::TexCoord> * texCoords = &geometry->texCoords;
00304 const std::vector<GeometryTriangles::Indice> * indices = &geometry->indices;
00305
00306 std::vector<int> indicesToWrite;
00307 size_t texCoordsCount = texCoords->size();
00308 size_t indSize = geometry->indices.size();
00309 size_t indiceIndex = 0;
00310 int modTabs = 0;
00311
00312 tw->Write(*tabs)->Write("geometry ");
00313
00314
00315
00316 tw->Write(" IndexedFaceSet {\n");
00317
00318 tabs->Append(wxT("\t"));
00319
00320 if(det == true)
00321 {
00322 tw->Write(*tabs)->Write("ccw TRUE\n");
00323 if (material && (material->flags & Material::DOUBLE_SIDED))
00324 tw->Write(*tabs)->Write("solid FALSE\n");
00325 else tw->Write(*tabs)->Write("solid TRUE\n");
00326 }
00327 else {
00328
00329
00330
00331 tw->Write(*tabs)->Write("ccw FALSE\n");
00332 if (material && (material->flags & Material::DOUBLE_SIDED))
00333 tw->Write(*tabs)->Write("solid FALSE\n");
00334 else tw->Write(*tabs)->Write("solid TRUE\n");
00335 }
00336 tw->Write(*tabs)->Write("convex TRUE\n");
00337
00338
00339
00340
00341
00342
00343
00344
00345 tw->Write(*tabs)->Write("coord ");
00346
00347
00348
00349 tw->Write(" Coordinate {\n");
00350
00351 tabs->Append(wxT("\t"));
00352
00353 tw->Write(*tabs)->Write("point [");
00354
00355 tabs->Append(wxT("\t"));
00356
00357 for (size_t i=0; i<vertices->size()-1; i++)
00358 {
00359 if((i%8) == 0)
00360 tw->Write("\n")->Write(*tabs);
00361 #ifdef MIRROR_BY_VERTICES
00362 vector3 tmp;
00363 if(det) tmp = vertices->at(i);
00364 else tmp = -vertices->at(i);
00365 #else
00366 vector3 tmp = vertices->at(i);
00367 #endif
00368 tw->Write(tmp._v, 3, " ")->Write(", ");
00369 }
00370 if (vertices->size()>0)
00371 {
00372 #ifdef MIRROR_BY_VERTICES
00373 vector3 tmp;
00374 if(det) tmp = vertices->at(vertices->size()-1);
00375 else tmp = -vertices->at(vertices->size()-1);
00376 #else
00377 vector3 tmp = vertices->at(vertices->size()-1);
00378 #endif
00379 tw->Write(tmp._v, 3, " ")->Write("\n");
00380 }
00381
00382 tabs->RemoveLast();
00383 tw->Write(*tabs)->Write("]\n");
00384
00385 tabs->RemoveLast();
00386 tw->Write(*tabs)->Write("}\n");
00387
00388 tw->Write(*tabs)->Write("coordIndex [");
00389 tabs->Append(wxT("\t"));
00390
00391 bool ccw_ts = true;
00392 bool comma = false;
00393 for (GeometryTriangles::TriDescList::const_iterator indPrimType = geometry->triDescList.begin();
00394 indPrimType != geometry->triDescList.end(); indPrimType++)
00395 {
00396 GeometryTriangles::TriDescList::const_iterator endIndPrimType = indPrimType + 1;
00397 size_t endInd = ( endIndPrimType == geometry->triDescList.end() ? indSize : endIndPrimType->first );
00398 endInd = __min( endInd, indSize );
00399 modTabs = 0;
00400 ccw_ts = true;
00401 if(comma == false) comma = true;
00402 else {
00403 tw->Write(", ");
00404 }
00405 switch (indPrimType->second)
00406 {
00407 case GeometryTriangles::TRI_LIST:
00408
00409 if(indiceIndex+2 >= endInd)
00410 {
00411 comma = false;
00412 break;
00413 }
00414 if(mode == 1)
00415 {
00416 tw->Write("\n")->Write(*tabs)->Write("#TL");
00417 }
00418 while (indiceIndex+2 < endInd)
00419 {
00420 if((modTabs++)%4 == 0)
00421 {
00422 tw->Write("\n")->Write(*tabs);
00423 }
00424 GeometryTriangles::Indice indice = indices->at(indiceIndex++);
00425 indicesToWrite.push_back(indice);
00426 tw->Write(indice)->Write(", ");
00427 indice = indices->at(indiceIndex++);
00428 indicesToWrite.push_back(indice);
00429 tw->Write(indice)->Write(", ");
00430 indice = indices->at(indiceIndex++);
00431 indicesToWrite.push_back(indice);
00432 tw->Write(indice);
00433 if (indiceIndex < endInd)
00434 tw->Write(", -1, ");
00435 else tw->Write(", -1");
00436 indicesToWrite.push_back(-1);
00437 }
00438 break;
00439 case GeometryTriangles::QUADS:
00440
00441 if(indiceIndex+3 >= endInd)
00442 {
00443 comma = false;
00444 break;
00445 }
00446 if(mode == 1)
00447 {
00448 tw->Write("\n")->Write(*tabs)->Write("#QU");
00449 }
00450 while (indiceIndex+3 < endInd)
00451 {
00452 if((modTabs++)%4 == 0)
00453 {
00454 tw->Write("\n")->Write(*tabs);
00455 }
00456 GeometryTriangles::Indice indice = indices->at(indiceIndex++);
00457 indicesToWrite.push_back(indice);
00458 tw->Write(indice)->Write(", ");
00459 indice = indices->at(indiceIndex++);
00460 indicesToWrite.push_back(indice);
00461 tw->Write(indice)->Write(", ");
00462 indice = indices->at(indiceIndex++);
00463 indicesToWrite.push_back(indice);
00464 tw->Write(indice)->Write(", ");
00465 indice = indices->at(indiceIndex++);
00466 indicesToWrite.push_back(indice);
00467 tw->Write(indice);
00468 if (indiceIndex < endInd)
00469 tw->Write(", -1, ");
00470 else tw->Write(", -1");
00471 indicesToWrite.push_back(-1);
00472 }
00473 break;
00474 case GeometryTriangles::POLYGON:
00475
00476 if(indiceIndex >= endInd)
00477 {
00478 comma = false;
00479 break;
00480 }
00481 if(mode == 1)
00482 {
00483 tw->Write("\n")->Write(*tabs)->Write("#PO");
00484 }
00485 while (indiceIndex < endInd)
00486 {
00487 if((modTabs++)%4 == 0)
00488 {
00489 tw->Write("\n")->Write(*tabs);
00490 }
00491 GeometryTriangles::Indice indice = indices->at(indiceIndex++);
00492 indicesToWrite.push_back(indice);
00493 tw->Write(indice)->Write(", ");
00494 }
00495 tw->Write("-1");
00496 indicesToWrite.push_back(-1);
00497 break;
00498 case GeometryTriangles::TRI_FAN:
00499
00500 if (indiceIndex > endInd-1)
00501 {
00502 comma = false;
00503 break;
00504 }{
00505 if(mode == 1)
00506 {
00507 tw->Write("\n")->Write(*tabs)->Write("#TF");
00508 }
00509 GeometryTriangles::Indice indice0 = indices->at(indiceIndex++);
00510 indiceIndex++;
00511 while (indiceIndex < endInd)
00512 {
00513 indiceIndex--;
00514 if((modTabs++)%4 == 0)
00515 {
00516 tw->Write("\n")->Write(*tabs);
00517 }
00518 indicesToWrite.push_back(indice0);
00519 tw->Write(indice0)->Write(", ");
00520 GeometryTriangles::Indice indice = indices->at(indiceIndex++);
00521 indicesToWrite.push_back(indice);
00522 tw->Write(indice)->Write(", ");
00523 indice = indices->at(indiceIndex++);
00524 indicesToWrite.push_back(indice);
00525 tw->Write(indice);
00526 if (indiceIndex < endInd)
00527 tw->Write(", -1, ");
00528 else tw->Write(", -1");
00529 indicesToWrite.push_back(-1);
00530 }
00531 }
00532 break;
00533 case GeometryTriangles::TRI_STRIP:
00534
00535 if (indiceIndex > endInd-2)
00536 {
00537 comma = false;
00538 break;
00539 }
00540 if(mode == 1)
00541 {
00542 tw->Write("\n")->Write(*tabs)->Write("#TS");
00543 }
00544 indiceIndex += 2;
00545 while (indiceIndex < endInd)
00546 {
00547 if(ccw_ts)
00548 {
00549 indiceIndex -= 2;
00550 if((modTabs++)%4 == 0)
00551 {
00552 tw->Write("\n")->Write(*tabs);
00553 }
00554 GeometryTriangles::Indice indice = indices->at(indiceIndex++);
00555 indicesToWrite.push_back(indice);
00556 tw->Write(indice)->Write(", ");
00557 indice = indices->at(indiceIndex++);
00558 indicesToWrite.push_back(indice);
00559 tw->Write(indice)->Write(", ");
00560 indice = indices->at(indiceIndex++);
00561 indicesToWrite.push_back(indice);
00562 tw->Write(indice);
00563 if (indiceIndex < endInd)
00564 tw->Write(", -1, ");
00565 else tw->Write(", -1");
00566 indicesToWrite.push_back(-1);
00567 ccw_ts = false;
00568 } else {
00569 indiceIndex -= 1;
00570 if((modTabs++)%4 == 0)
00571 {
00572 tw->Write("\n")->Write(*tabs);
00573 }
00574 GeometryTriangles::Indice indice = indices->at(indiceIndex--);
00575 indicesToWrite.push_back(indice);
00576 tw->Write(indice)->Write(", ");
00577 indice = indices->at(indiceIndex++);
00578 indiceIndex++;
00579 indicesToWrite.push_back(indice);
00580 tw->Write(indice)->Write(", ");
00581 indice = indices->at(indiceIndex++);
00582 indicesToWrite.push_back(indice);
00583 tw->Write(indice);
00584 if (indiceIndex < endInd)
00585 tw->Write(", -1, ");
00586 else tw->Write(", -1");
00587 indicesToWrite.push_back(-1);
00588 ccw_ts = true;
00589 }
00590 }
00591 break;
00592 case GeometryTriangles::LINES:
00593 LOGERROR(wxT("<VRMLWriter>Line type within face primitive type"));
00594 break;
00595 case GeometryTriangles::LINE_STRIP:
00596 LOGERROR(wxT("<VRMLWriter>Line type within face primitive type"));
00597 break;
00598 case GeometryTriangles::POINTS:
00599 LOGERROR(wxT("<VRMLWriter>Point type within face primitive type"));
00600 break;
00601 default:
00602 LOGERROR(wxT("<VRMLWriter>Unknown node type"));
00603 }
00604 }
00605
00606
00607 tabs->RemoveLast();
00608
00609 tw->Write("\n")->Write(*tabs)->Write("]\n");
00610
00611
00612
00613 if (texCoords->size()>0 && outputTexCoord)
00614 {
00615 tw->Write(*tabs)->Write("texCoord ");
00616
00617
00618
00619 tw->Write(" TextureCoordinate {\n");
00620
00621 tabs->Append(wxT("\t"));
00622 tw->Write(*tabs)->Write("point [");
00623 tabs->Append(wxT("\t"));
00624
00625 for (size_t i=0; i<texCoords->size()-1; i++)
00626 {
00627 if((i%12) == 0)
00628 tw->Write("\n")->Write(*tabs);
00629 tw->Write(texCoords->at(i)._v, 2, " ")->Write(", ");
00630 }
00631 if (texCoords->size()>0)
00632 tw->Write(texCoords->at(texCoords->size()-1)._v, 2, " ")->Write("\n");
00633
00634 tabs->RemoveLast();
00635 tw->Write(*tabs)->Write("]\n");
00636 tabs->RemoveLast();
00637 tw->Write(*tabs)->Write("}\n");
00638 tw->Write(*tabs)->Write("texCoordIndex [");
00639
00640 tabs->Append(wxT("\t"));
00641
00642 if(indicesToWrite.size()>0 && texCoordsCount>0)
00643 tw->Write(indicesToWrite.at(0));
00644 size_t endInd = __min(texCoordsCount, indicesToWrite.size());
00645 for(size_t it = 1; it < endInd; it++)
00646 {
00647 tw->Write(", ");
00648 if((it%24) == 0)
00649 tw->Write("\n")->Write(*tabs);
00650 tw->Write(indicesToWrite.at(it));
00651 }
00652
00653 tabs->RemoveLast();
00654 tw->Write("\n")->Write(*tabs)->Write("]\n");
00655 }
00656
00657
00658
00659
00660 tw->Write(*tabs)->Write("normalPerVertex TRUE\n");
00661
00662 size_t normalsCount = normals->size();
00663
00664 if (normalsCount > 0)
00665 {
00666 tw->Write(*tabs)->Write("normal ");
00667
00668
00669
00670 tw->Write(" Normal {\n");
00671
00672 tabs->Append(wxT("\t"));
00673 tw->Write(*tabs)->Write("vector [");
00674 tabs->Append(wxT("\t"));
00675
00676 for (size_t i=0; i<normalsCount-1; i++)
00677 {
00678 if((i%8) == 0)
00679 tw->Write("\n")->Write(*tabs);
00680 tw->Write(normals->at(i)._v, 3, " ")->Write(", ");
00681 }
00682 tw->Write(normals->at(normalsCount-1)._v, 3, " ")->Write("\n");
00683
00684 tabs->RemoveLast();
00685 tw->Write(*tabs)->Write("]\n");
00686 tabs->RemoveLast();
00687 tw->Write(*tabs)->Write("}\n");
00688 tw->Write(*tabs)->Write("normalIndex [");
00689
00690 tabs->Append(wxT("\t"));
00691 modTabs = 0;
00692 indiceIndex = 0;
00693
00694 if(indicesToWrite.size()>0)
00695 tw->Write(indicesToWrite.at(0));
00696 for(size_t it = 1; it < indicesToWrite.size(); it++)
00697 {
00698 tw->Write(", ");
00699 if((it%24) == 0)
00700 tw->Write("\n")->Write(*tabs);
00701 tw->Write(indicesToWrite.at(it));
00702 }
00703
00704 tabs->RemoveLast();
00705 tw->Write("\n")->Write(*tabs)->Write("]\n");
00706 }
00707
00708
00709 tabs->RemoveLast();
00710 tw->Write(*tabs)->Write("}\n");
00711
00712 }
00713
00714
00715 void VRMLWriter::ExportIndexedLineSet(const SceneNode * node, wxString * tabs)
00716 {
00717 const GeometryNode * geomNode = (const GeometryNode *)node;
00718 const Geometry * geom = scene->GetGeometry(geomNode->GetGeometryID());
00719 const Material * material = scene->GetMaterial(geomNode->GetMaterialID());
00720 if (!geom || geom->type != Geometry::GEOMETRY_TRIANGLE)
00721 {
00722 return;
00723 }
00724
00725 const GeometryTriangles * geometry = (GeometryTriangles *)geom;
00726 const std::vector<VECTOR3> * vertices = &geometry->vertices;
00727 const std::vector<GeometryTriangles::Indice> * indices = &geometry->indices;
00728
00729
00730 size_t indSize = geometry->indices.size();
00731 size_t indiceIndex = 0;
00732 int modTabs = 0;
00733
00734 tw->Write(*tabs)->Write("geometry ");
00735
00736
00737
00738 tw->Write(" IndexedLineSet {\n");
00739 tabs->Append(wxT("\t"));
00740
00741
00742 tw->Write(*tabs)->Write("coord ");
00743
00744
00745
00746 tw->Write(" Coordinate {\n");
00747
00748 tabs->Append(wxT("\t"));
00749 tw->Write(*tabs)->Write("point [");
00750 tabs->Append(wxT("\t"));
00751
00752 for (size_t i=0; i<vertices->size()-1; i++)
00753 {
00754 if((i%8) == 0)
00755 tw->Write("\n")->Write(*tabs);
00756 tw->Write(vertices->at(i)._v, 3, " ")->Write(", ");
00757 }
00758 if (vertices->size()>0)
00759 tw->Write(vertices->at(vertices->size()-1)._v, 3, " ")->Write("\n");
00760
00761 tabs->RemoveLast();
00762 tw->Write(*tabs)->Write("]\n");
00763
00764 tabs->RemoveLast();
00765 tw->Write(*tabs)->Write("}\n");
00766 tw->Write(*tabs)->Write("coordIndex [\n");
00767
00768 tabs->Append(wxT("\t"));
00769 bool ccw_ts = true;
00770 bool comma = false;
00771 for (GeometryTriangles::TriDescList::const_iterator indPrimType = geometry->triDescList.begin();
00772 indPrimType != geometry->triDescList.end(); indPrimType++)
00773 {
00774 GeometryTriangles::TriDescList::const_iterator endIndPrimType = indPrimType + 1;
00775 size_t endInd = ( endIndPrimType == geometry->triDescList.end() ? indSize : endIndPrimType->first );
00776 endInd = __min( endInd, indSize );
00777 modTabs = 0;
00778 ccw_ts = true;
00779 if(comma == false) comma = true;
00780 else {
00781 tw->Write(", ");
00782 }
00783 switch (indPrimType->second)
00784 {
00785 case GeometryTriangles::TRI_LIST:
00786 case GeometryTriangles::QUADS:
00787 case GeometryTriangles::POLYGON:
00788 case GeometryTriangles::TRI_FAN:
00789 case GeometryTriangles::TRI_STRIP:
00790 LOGERROR(wxT("<VRMLWriter>Face type within line primitive type"));
00791 break;
00792 case GeometryTriangles::LINES:
00793 if(indiceIndex+1 >= endInd)
00794 {
00795 comma = false;
00796 break;
00797 }
00798 if(mode == 1)
00799 {
00800 tw->Write("\n")->Write(*tabs)->Write("#LI");
00801 }
00802 while (indiceIndex+1 < endInd)
00803 {
00804 if((modTabs++)%8 == 0)
00805 {
00806 tw->Write("\n")->Write(*tabs);
00807 }
00808 GeometryTriangles::Indice indice = indices->at(indiceIndex++);
00809 tw->Write(indice)->Write(", ");
00810 indice = indices->at(indiceIndex++);
00811 tw->Write(indice);
00812 if (indiceIndex < endInd)
00813 tw->Write(", -1, ");
00814 else tw->Write(", -1");
00815 }
00816 break;
00817 case GeometryTriangles::LINE_STRIP:
00818 if(indiceIndex+1 >= endInd)
00819 {
00820 comma = false;
00821 break;
00822 }
00823 if(mode == 1)
00824 {
00825 tw->Write("\n")->Write(*tabs)->Write("#LS");
00826 }
00827 while (indiceIndex < endInd)
00828 {
00829 if((modTabs++)%16 == 0)
00830 {
00831 tw->Write("\n")->Write(*tabs);
00832 }
00833 GeometryTriangles::Indice indice = indices->at(indiceIndex++);
00834 tw->Write(indice)->Write(", ");
00835 }
00836 tw->Write("-1");
00837 break;
00838 case GeometryTriangles::POINTS:
00839 LOGERROR(wxT("<VRMLWriter>Point type within line primitive type"));
00840 break;
00841 default:
00842 LOGERROR(wxT("<VRMLWriter>Unknown node type"));
00843 }
00844 }
00845
00846
00847 tabs->RemoveLast();
00848 tw->Write("\n")->Write(*tabs)->Write("]\n");
00849
00850
00851 tabs->RemoveLast();
00852 tw->Write(*tabs)->Write("}\n");
00853 }
00854
00855
00856 void VRMLWriter::ExportPointSet(const SceneNode * node, wxString * tabs)
00857 {
00858 const GeometryNode * geomNode = (const GeometryNode *)node;
00859 const Geometry * geom = scene->GetGeometry(geomNode->GetGeometryID());
00860 const Material * material = scene->GetMaterial(geomNode->GetMaterialID());
00861 if (!geom || geom->type != Geometry::GEOMETRY_TRIANGLE)
00862 {
00863 return;
00864 }
00865
00866 const GeometryTriangles * geometry = (GeometryTriangles *)geom;
00867 const std::vector<VECTOR3> * vertices = &geometry->vertices;
00868 const std::vector<GeometryTriangles::Indice> * indices = &geometry->indices;
00869
00870
00871 size_t indSize = geometry->indices.size();
00872 size_t indiceIndex = 0;
00873 int modTabs = 0;
00874
00875 tw->Write(*tabs)->Write("geometry ");
00876
00877
00878
00879 tw->Write(" PointSet {\n");
00880
00881 tabs->Append(wxT("\t"));
00882
00883
00884
00885
00886 tw->Write(" Coordinate {\n");
00887
00888 tabs->Append(wxT("\t"));
00889 tw->Write(*tabs)->Write("point [");
00890 tabs->Append(wxT("\t"));
00891
00892 for (size_t i=0; i<vertices->size()-1; i++)
00893 {
00894 if((i%8) == 0)
00895 tw->Write("\n")->Write(*tabs);
00896 tw->Write(vertices->at(i)._v, 3, " ")->Write(", ");
00897 }
00898 if (vertices->size()>0)
00899 tw->Write(vertices->at(vertices->size()-1)._v, 3, " ")->Write("\n");
00900
00901 tabs->RemoveLast();
00902 tw->Write(*tabs)->Write("]\n");
00903
00904 tabs->RemoveLast();
00905 tw->Write(*tabs)->Write("}\n");
00906
00907
00908
00909 tabs->RemoveLast();
00910 tw->Write(*tabs)->Write("}\n");
00911 }
00912
00913
00914 bool VRMLWriter::ExportAppearance(const SceneNode * node, wxString * tabs)
00915 {
00916 bool outputTexCoord = true;
00917 const GeometryNode * geomNode = (const GeometryNode *)node;
00918 const Geometry * geom = scene->GetGeometry(geomNode->GetGeometryID());
00919 const Material * material = scene->GetMaterial(geomNode->GetMaterialID());
00920
00921 if(!material) return false;
00922
00923 tw->Write(*tabs)->Write("appearance ");
00924
00925
00926
00927 tw->Write(" Appearance {\n");
00928
00929 tabs->Append(wxT("\t"));
00930
00931 tw->Write(*tabs)->Write("material ");
00932
00933
00934
00935 tw->Write(" Material {\n");
00936
00937
00938 if (material)
00939 {
00940 tabs->Append(wxT("\t"));
00941
00942 vector3 diffuseColor = vector3(material->diffuse.x, material->diffuse.y, material->diffuse.z);
00943 vector3 specularColor = vector3(material->specular.x, material->specular.y, material->specular.z);
00944 vector3 emissiveColor = vector3(material->emission.x, material->emission.y, material->emission.z);
00945 tw->Write(*tabs)->Write("diffuseColor ")->Write(diffuseColor._v, 3, " ")->Write("\n");
00946 tw->Write(*tabs)->Write("ambientIntensity 0.2\n");
00947 tw->Write(*tabs)->Write("specularColor ")->Write(specularColor._v, 3, " ")->Write("\n");
00948 tw->Write(*tabs)->Write("emissiveColor ")->Write(emissiveColor._v, 3, " ")->Write("\n");
00949 tw->Write(*tabs)->Write("shininess ")->Write(material->shininess)->Write("\n");
00950 if (material->flags & Material::BLENDED)
00951 {
00952 tw->Write(*tabs)->Write("transparency ")->Write(1 - material->diffuse.w)->Write("\n");
00953 }
00954 tabs->RemoveLast();
00955 }
00956
00957
00958 tw->Write(*tabs)->Write("}\n");
00959
00961
00962 if (material->imageName.size())
00963 {
00964 tw->Write(*tabs)->Write("texture ");
00965
00966
00967
00968 tw->Write(" ImageTexture {\n");
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 wxString texName = material->imageName;
00984
00985
00986 texName = texName.After(wxFileName(texName).GetPathSeparator());
00988
00989 wxString VRMLPath = fname;
00990 wxString texturePath = wxString();
00991
00992 const wxChar * dot = new wxChar('.');
00993
00994
00995 const wxChar * slash = new wxChar('/');
00996 const wxChar * pathSep = new wxChar(wxFileName(texName).GetPathSeparator());
00997 size_t rep1 = texName.Replace(wxString(*slash),wxString(*pathSep));
00998 size_t rep2 = VRMLPath.Replace(wxString(*slash),wxString(*pathSep));
00999
01000
01001 if(texName.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01002 {
01003 texName = texName.AfterFirst(wxFileName(texName).GetPathSeparator());
01004 while(texName.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01005 {
01006 texName = texName.AfterFirst(wxFileName(texName).GetPathSeparator());
01007 }
01008 }
01009
01010 else if(texName.find_first_of(*dot) == 0)
01011 {
01012 texName = texName.AfterFirst(*dot);
01013 if(texName.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01014 {
01015 texName = texName.AfterFirst(wxFileName(texName).GetPathSeparator());
01016 while(texName.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01017 {
01018 texName = texName.AfterFirst(wxFileName(texName).GetPathSeparator());
01019 }
01020 }
01021 }
01022
01023 if(VRMLPath.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01024 {
01025 VRMLPath = VRMLPath.AfterFirst(wxFileName(texName).GetPathSeparator());
01026 while(VRMLPath.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01027 {
01028 VRMLPath = VRMLPath.AfterFirst(wxFileName(texName).GetPathSeparator());
01029 }
01030 }
01031
01032 else if(VRMLPath.find_first_of(*dot) == 0)
01033 {
01034 VRMLPath = VRMLPath.After(*dot);
01035 if(VRMLPath.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01036 {
01037 VRMLPath = VRMLPath.After(wxFileName(texName).GetPathSeparator());
01038 while(VRMLPath.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01039 {
01040 VRMLPath = VRMLPath.After(wxFileName(texName).GetPathSeparator());
01041 }
01042 }
01043 }
01044
01045
01046 if(texName.find_last_of(wxFileName(texName).GetPathSeparator()) > 0)
01047 {
01048 texturePath = texName.BeforeLast(wxFileName(texName).GetPathSeparator());
01049 }
01050
01051 if(VRMLPath.find_last_of(wxFileName(VRMLPath).GetPathSeparator()) > 0)
01052 {
01053 VRMLPath = VRMLPath.BeforeLast(wxFileName(VRMLPath).GetPathSeparator());
01054 } else {
01055 VRMLPath = wxString();
01056 }
01057
01058
01059 wxString texFileName;
01060 if(VRMLPath.empty())
01061 {
01062
01063 texFileName = texturePath;
01064 texFileName = texFileName.Append(wxString(*pathSep));
01065 texFileName = texFileName.Append(wxFileName(texName).GetFullName());
01066 } else {
01067 if(VRMLPath == texturePath)
01068 {
01069
01070 texFileName = wxFileName(texName).GetFullName();
01071 } else if(texturePath.Contains(VRMLPath))
01072 {
01073
01074 texFileName = VRMLPath.BeforeFirst(texturePath.at(texturePath.First(VRMLPath)));
01075 texFileName = texFileName.append(texturePath.substr(texturePath.First(VRMLPath)+(int)VRMLPath.Len()));
01076 if(texFileName.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01077 {
01078 texFileName = texFileName.AfterFirst(wxFileName(texName).GetPathSeparator());
01079 }
01080 texFileName = texFileName.Append(wxString(*pathSep));
01081 texFileName = texFileName.Append(wxFileName(texName).GetFullName());
01082 } else if(VRMLPath.Contains(texturePath))
01083 {
01084
01085 wxString temp = VRMLPath.substr(VRMLPath.First(texturePath)+(int)texturePath.Len());
01086 if(temp.find_first_of(wxFileName(texName).GetPathSeparator()) == 0)
01087 {
01088 temp = temp.AfterFirst(wxFileName(texName).GetPathSeparator());
01089 }
01090 int num = (int)temp.Replace(wxString(*pathSep),wxString(*pathSep));
01091 if(!temp.IsEmpty())
01092 {
01093 texFileName = texFileName.Append(wxString::FromAscii(".."));
01094 texFileName = texFileName.Append(wxString(*pathSep));
01095 }
01096 for(int i = 0; i < num; i++) {
01097 texFileName = texFileName.Append(wxString::FromAscii(".."));
01098 texFileName = texFileName.Append(wxString(*pathSep));
01099 }
01100 texFileName = texFileName.Append(wxFileName(texName).GetFullName());
01101 }
01102 else {
01103
01104 int size = (int)VRMLPath.length();
01105 int pos = 0;
01106 if((int)texturePath.length() < size) size = (int)texturePath.length();
01107 for(int i = 0; i < size; i++) {
01108 if(VRMLPath.at(i) != texturePath.at(i))
01109 {
01110 pos = i;
01111 break;
01112 }
01113 }
01114 wxString tempVRMLPath = VRMLPath.substr(pos);
01115 wxString tempTexturePath = texturePath.substr(pos);
01116 int num = (int)tempVRMLPath.Replace(wxString(*pathSep),wxString(*pathSep));
01117 if(!tempVRMLPath.IsEmpty())
01118 {
01119 texFileName = texFileName.Append(wxString::FromAscii(".."));
01120 texFileName = texFileName.Append(wxString(*pathSep));
01121 }
01122 for(int i = 0; i < num; i++) {
01123 texFileName = texFileName.Append(wxString::FromAscii(".."));
01124 texFileName = texFileName.Append(wxString(*pathSep));
01125 }
01126 texFileName = texFileName.Append(tempTexturePath);
01127 texFileName = texFileName.Append(wxString(*pathSep));
01128 texFileName = texFileName.Append(wxFileName(texName).GetFullName());
01129 }
01130 }
01131
01132
01133
01134
01135 tw->Write(*tabs)->Write("\turl \"")->Write(texFileName)->Write("\"\n");
01136
01137
01138
01139 tw->Write(*tabs)->Write("\trepeatS ");
01140
01141 tw->Write(" TRUE\n");
01142
01143
01144 tw->Write(*tabs)->Write("\trepeatT ");
01145
01146 tw->Write(" TRUE\n");
01147
01148
01149 tw->Write(*tabs)->Write("}\n");
01150
01151 if ((material->texFlags & Material::TEX_GEN_FUNC_U_SPHERE) || (material->texFlags & Material::TEX_GEN_FUNC_V_SPHERE))
01152 outputTexCoord = false;
01153 }
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 tabs->RemoveLast();
01168 tw->Write(*tabs)->Write("}\n");
01169
01170 return outputTexCoord;
01171 }
01172
01173
01174 void VRMLWriter::ExportCamera(const SceneNode * node, wxString * tabs)
01175 {
01176 scene->UpdateTransformation(node->GetID());
01177 const MATRIX * m = node->GetWorldTransMatrix();
01178 vector3 position = m->ExtractTranslation();
01179 AffineParts parts;
01180 Quat q;
01181 float ang;
01182 vector3 axis;
01183 vector4 rotation;
01184 float matToDecomp[4][4];
01185 for(int i=0,j=0; i<3; i++)
01186 {
01187 matToDecomp[0][i] = m->_m[j++];
01188 matToDecomp[1][i] = m->_m[j++];
01189 matToDecomp[2][i] = m->_m[j++];
01190 matToDecomp[3][i] = m->_m[j++];
01191 }
01192
01193 decomp_affine(matToDecomp, &parts);
01194
01195 q = parts.q;
01196 AngAxisFromQa(q, &ang, axis);
01197 rotation = vector4(axis.x, axis.y, axis.z, ang);
01198
01199 Camera * camera = (Camera *) node;
01200 float FOV = (camera->GetFOV()*M_PI)/180;
01201 tw->Write("DEF VIEWPOINT");
01202 if(node->GetName().size() > 0)
01203 tw->Write(VRMLName(node->GetName()));
01204 tw->Write(node->GetID());
01205 tw->Write(" Viewpoint {\n");
01206 tw->Write("\tposition ")->Write(position._v, 3, " ");
01207 tw->Write("\n\torientation ")->Write(rotation._v, 4, " ");
01208 tw->Write("\n\tfieldOfView ")->Write(FOV);
01209 tw->Write("\n\tdescription \"")->Write(node->GetID())->Write("\"");
01210 tw->Write("\n}\n\n");
01211 }
01212
01213
01214 void VRMLWriter::ExportCameras()
01215 {
01216 if (!scene->GetBVH())
01217 {
01218 LOGERROR(wxT("<VRMLWriter>Cannot initialize BVH, extra cameras not created."));
01219 return;
01220 }
01221 VECTOR3 minBound = scene->GetBVH()->GetRoot()->GetAABB()->MinBound;
01222 VECTOR3 maxBound = scene->GetBVH()->GetRoot()->GetAABB()->MaxBound;
01223 VECTOR3 tmpMin = minBound;
01224 VECTOR3 tmpMax = maxBound;
01225 float tmpDist1 = 0.0f;
01226 float tmpDist2 = 0.0f;
01227 float FOV = (45.0f*M_PI)/180;
01228 VECTOR3 position;
01229 VECTOR4 rotation;
01230
01231
01232 tmpMin.z = maxBound.z;
01233 tmpDist1 = sqrtf((tmpMax.x-tmpMin.x)*(tmpMax.x-tmpMin.x) + (tmpMax.y-tmpMin.y)*(tmpMax.y-tmpMin.y));
01234 tmpDist2 = (tmpDist1/2)*tan((45.0f*M_PI)/180)*1.5f;
01235 position = VECTOR3(((tmpMax.x-tmpMin.x)/2)+tmpMin.x, ((tmpMax.y-tmpMin.y)/2)+tmpMin.y, tmpMax.z+tmpDist2);
01236 tw->Write("DEF VIEWPOINT_ZDIR");
01237 tw->Write(" Viewpoint {\n");
01238 tw->Write("\tposition ")->Write(position._v, 3, " ");
01239 tw->Write("\n\tfieldOfView ")->Write(FOV);
01240 tw->Write("\n\tdescription \"ZDIR\"");
01241 tw->Write("\n}\n\n");
01242
01243
01244 tmpMin = minBound;
01245 tmpMax = maxBound;
01246 tmpMin.x = tmpMax.x;
01247 tmpDist1 = sqrtf((tmpMax.z-tmpMin.z)*(tmpMax.z-tmpMin.z) + (tmpMax.y-tmpMin.y)*(tmpMax.y-tmpMin.y));
01248 tmpDist2 = (tmpDist1/2)*tan((45.0f*M_PI)/180)*1.5f;
01249 position.x = tmpMax.x+tmpDist2;
01250 position.y = ((tmpMax.y-tmpMin.y)/2)+tmpMin.y;
01251 position.z = ((tmpMax.z-tmpMin.z)/2)+tmpMin.z;
01252 rotation = VECTOR4(0.0f, 1.0f, 0.0f, M_PI/2);
01253 tw->Write("DEF VIEWPOINT_XDIR");
01254 tw->Write(" Viewpoint {\n");
01255 tw->Write("\tposition ")->Write(position._v, 3, " ");
01256 tw->Write("\n\torientation ")->Write(rotation._v, 4, " ");
01257 tw->Write("\n\tfieldOfView ")->Write(FOV);
01258 tw->Write("\n\tdescription \"XDIR\"");
01259 tw->Write("\n}\n\n");
01260
01261
01262 tmpMin = minBound;
01263 tmpMax = maxBound;
01264 tmpMin.y = tmpMax.y;
01265 tmpDist1 = sqrtf((tmpMax.z-tmpMin.z)*(tmpMax.z-tmpMin.z) + (tmpMax.x-tmpMin.x)*(tmpMax.x-tmpMin.x));
01266 tmpDist2 = (tmpDist1/2)*tan((45.0f*M_PI)/180)*1.5f;
01267 position.x = ((tmpMax.x-tmpMin.x)/2)+tmpMin.x;
01268 position.y = tmpMax.y+tmpDist2;
01269 position.z = ((tmpMax.z-tmpMin.z)/2)+tmpMin.z;
01270 rotation = VECTOR4(-1.0f, 0.0f, 0.0f, M_PI/2);
01271 tw->Write("DEF VIEWPOINT_YDIR");
01272 tw->Write(" Viewpoint {\n");
01273 tw->Write("\tposition ")->Write(position._v, 3, " ");
01274 tw->Write("\n\torientation ")->Write(rotation._v, 4, " ");
01275 tw->Write("\n\tfieldOfView ")->Write(FOV);
01276 tw->Write("\n\tdescription \"YDIR\"");
01277 tw->Write("\n}\n\n");
01278
01279
01280 tmpMin = minBound;
01281 tmpMax = maxBound;
01282 tmpMax.z = tmpMin.z;
01283 tmpDist1 = sqrtf((tmpMax.x-tmpMin.x)*(tmpMax.x-tmpMin.x) + (tmpMax.y-tmpMin.y)*(tmpMax.y-tmpMin.y));
01284 tmpDist2 = (tmpDist1/2)*tan((45.0f*M_PI)/180)*1.5f;
01285 position.x = ((tmpMax.x-tmpMin.x)/2)+tmpMin.x;
01286 position.y = ((tmpMax.y-tmpMin.y)/2)+tmpMin.y;
01287 position.z = tmpMax.z-tmpDist2;
01288 rotation = VECTOR4(0.0f, 1.0f, 0.0f, M_PI);
01289 tw->Write("DEF VIEWPOINT__ZDIR");
01290 tw->Write(" Viewpoint {\n");
01291 tw->Write("\tposition ")->Write(position._v, 3, " ");
01292 tw->Write("\n\torientation ")->Write(rotation._v, 4, " ");
01293 tw->Write("\n\tfieldOfView ")->Write(FOV);
01294 tw->Write("\n\tdescription \"_ZDIR\"");
01295 tw->Write("\n}\n\n");
01296
01297
01298 tmpMin = minBound;
01299 tmpMax = maxBound;
01300 tmpMax.x = tmpMin.x;
01301 tmpDist1 = sqrtf((tmpMax.z-tmpMin.z)*(tmpMax.z-tmpMin.z) + (tmpMax.y-tmpMin.y)*(tmpMax.y-tmpMin.y));
01302 tmpDist2 = (tmpDist1/2)*tan((45.0f*M_PI)/180)*1.5f;
01303 position.x = tmpMax.x-tmpDist2;
01304 position.y = ((tmpMax.y-tmpMin.y)/2)+tmpMin.y;
01305 position.z = ((tmpMax.z-tmpMin.z)/2)+tmpMin.z;
01306 rotation = VECTOR4(0.0f, -1.0f, 0.0f, M_PI/2);
01307 tw->Write("DEF VIEWPOINT__XDIR");
01308 tw->Write(" Viewpoint {\n");
01309 tw->Write("\tposition ")->Write(position._v, 3, " ");
01310 tw->Write("\n\torientation ")->Write(rotation._v, 4, " ");
01311 tw->Write("\n\tfieldOfView ")->Write(FOV);
01312 tw->Write("\n\tdescription \"_XDIR\"");
01313 tw->Write("\n}\n\n");
01314
01315
01316 tmpMin = minBound;
01317 tmpMax = maxBound;
01318 tmpMax.y = tmpMin.y;
01319 tmpDist1 = sqrtf((tmpMax.z-tmpMin.z)*(tmpMax.z-tmpMin.z) + (tmpMax.x-tmpMin.x)*(tmpMax.x-tmpMin.x));
01320 tmpDist2 = (tmpDist1/2)*tan((45.0f*M_PI)/180)*1.5f;
01321 position.x = ((tmpMax.x-tmpMin.x)/2)+tmpMin.x;
01322 position.y = tmpMax.y-tmpDist2;
01323 position.z = ((tmpMax.z-tmpMin.z)/2)+tmpMin.z;
01324 rotation = VECTOR4(1.0f, 0.0f, 0.0f, M_PI/2);
01325 tw->Write("DEF VIEWPOINT__YDIR");
01326 tw->Write(" Viewpoint {\n");
01327 tw->Write("\tposition ")->Write(position._v, 3, " ");
01328 tw->Write("\n\torientation ")->Write(rotation._v, 4, " ");
01329 tw->Write("\n\tfieldOfView ")->Write(FOV);
01330 tw->Write("\n\tdescription \"_YDIR\"");
01331 tw->Write("\n}\n\n");
01332
01333 }
01334
01335
01336 void VRMLWriter::ExportGeneralLight(const SceneNode * node, wxString * tabs)
01337 {
01338 scene->UpdateTransformation(node->GetID());
01339 const Light * light = ((LightNode *) node)->GetLight();
01340 switch(light->type) {
01341 case Light::OMNI:
01342 ExportOmniLight(light, node, tabs);
01343 break;
01344 case Light::DIRECTIONAL:
01345 ExportDirectionalLight(light, node, tabs);
01346 break;
01347 case Light::SPOTLIGHT:
01348 ExportSpotLight(light, node, tabs);
01349 break;
01350 case Light::UNKNOWN:
01351 LOGERROR(wxT("<VRMLWriter>Unknown light type"));
01352 break;
01353 default:
01354 LOGERROR(wxT("<VRMLWriter>Unexpected light type"));
01355 return;
01356 }
01357 }
01358
01359
01360
01361 void VRMLWriter::ExportOmniLight(const Light * light, const SceneNode * node, wxString * tabs)
01362 {
01363 tw->Write("DEF ");
01364 if(node->GetName().size() > 0)
01365 tw->Write(VRMLName(node->GetName()));
01366 else tw->Write(node->GetID());
01367 tw->Write(" PointLight {\n");
01368 tw->Write("\ton TRUE\n\tintensity ")->Write(1);
01369 vector3 diffuse_light = vector3(light->diffuse.x, light->diffuse.y, light->diffuse.z);
01370 tw->Write("\n\tcolor ")->Write(diffuse_light._v, 3, " ");
01371 tw->Write("\n\tlocation ")->Write(light->position._v, 3, " ");
01372 tw->Write("\n\tradius ")->Write(maxBoundDistance);
01373 tw->Write("\n\tattenuation 1 0 0\n");
01374 tw->Write("}\n\n");
01375 }
01376
01377
01378 void VRMLWriter::ExportDirectionalLight(const Light * light, const SceneNode * node, wxString * tabs)
01379 {
01380 tw->Write("DEF ");
01381 if(node->GetName().size() > 0)
01382 tw->Write(VRMLName(node->GetName()));
01383 else tw->Write(node->GetID());
01384 tw->Write(" DirectionalLight {\n");
01385 tw->Write("\ton TRUE\n\tintensity ")->Write(1);
01386 vector3 diffuse_light = vector3(light->diffuse.x, light->diffuse.y, light->diffuse.z);
01387 tw->Write("\n\tcolor ")->Write(diffuse_light._v, 3, " ");
01388 tw->Write("\n\tdirection ")->Write(light->direction._v, 3, " ");
01389 tw->Write("\n}\n\n");
01390 }
01391
01392
01393 void VRMLWriter::ExportSpotLight(const Light * light, const SceneNode * node, wxString * tabs)
01394 {
01395 tw->Write("DEF ");
01396 if(node->GetName().size() > 0)
01397 tw->Write(VRMLName(node->GetName()));
01398 else tw->Write(node->GetID());
01399 tw->Write(" SpotLight {\n");
01400 tw->Write("\ton TRUE\n");
01401 tw->Write("\tintensity ")->Write(1);
01402 vector3 diffuse_light = vector3(light->diffuse.x, light->diffuse.y, light->diffuse.z);
01403 tw->Write("\n\tcolor ")->Write(diffuse_light._v, 3, " ");
01404 tw->Write("\n\tlocation ")->Write(light->position._v, 3, " ");
01405 tw->Write("\n\tdirection ")->Write(light->direction._v, 3, " ");
01406
01407
01408
01409
01410 tw->Write("\n\tradius ")->Write(maxBoundDistance);
01411 tw->Write("\n\tattenuation 1 0 0\n");
01412 tw->Write("}\n\n");
01413 }
01414
01415
01416 bool VRMLWriter::ExportTransform(const SceneNode * node, wxString * tabs, bool det)
01417 {
01418
01419 scene->UpdateTransformation(node->GetID());
01420
01421 const MATRIX * m = node->GetLocalTransMatrix();
01422
01423 AffineParts parts;
01424 Quat q;
01425 float ang;
01426 vector3 axis, scale;
01427 vector4 scaleOrientation, rotation;
01428 float matToDecomp[4][4];
01429
01430
01431
01432
01433
01434
01435
01436
01437 for(int i=0,j=0; i<4; i++)
01438 {
01439 matToDecomp[0][i] = m->_m[j++];
01440 matToDecomp[1][i] = m->_m[j++];
01441 matToDecomp[2][i] = m->_m[j++];
01442 matToDecomp[3][i] = m->_m[j++];
01443 }
01444
01445 decomp_affine(matToDecomp, &parts);
01446
01447 vector3 translation = vector3(parts.t.x, parts.t.y, parts.t.z);
01448 q = parts.q;
01449 AngAxisFromQa(q, &ang, axis);
01450 rotation = vector4(axis.x, axis.y, axis.z, ang);
01451
01452 q = parts.u;
01453 AngAxisFromQa(q, &ang, axis);
01454 scale = vector3(parts.k.x, parts.k.y, parts.k.z);
01455 scaleOrientation = vector4(axis.x, axis.y, axis.z, ang);
01456
01457 #ifndef MIRROR_BY_VERTICES
01458 if(parts.f < 0.0f) scale = -scale;
01459 #else
01460 if(!det) translation = -translation;
01461 #endif
01462
01463 if(translation != vector3(0.0f, 0.0f, 0.0f))
01464 tw->Write(*tabs)->Write("translation ")->Write(translation._v, 3, " ")->Write("\n");
01465 if((rotation.w != 0.0f) || (rotation.w != -0.0f))
01466 tw->Write(*tabs)->Write("rotation ")->Write(rotation._v, 4, " ")->Write("\n");
01467 if(scale != vector3(1.0f, 1.0f, 1.0f))
01468 tw->Write(*tabs)->Write("scale ")->Write(scale._v, 3, " ")->Write("\n");
01469 if(scaleOrientation.w != 0.0f && scaleOrientation.w != -0.0f)
01470 tw->Write(*tabs)->Write("scaleOrientation ")->Write(scaleOrientation._v, 4, " ")->Write("\n");
01471
01472 return parts.f > 0.0f;
01473 }
01474
01475
01476 void VRMLWriter::AngAxisFromQa(const Quat& q, float *ang, vector3& axis) {
01477 double omega, s, x, y, z, w, l, c;
01478 x = (double)q.x;
01479 y = (double)q.y;
01480 z = (double)q.z;
01481 w = (double)q.w;
01482 l = sqrt(x*x + y*y + z*z + w*w);
01483 if (l == 0.0) {
01484 w = 1.0;
01485 y = z = x = 0.0;
01486 }
01487 else {
01488 c = 1.0/l;
01489 x *= c;
01490 y *= c;
01491 z *= c;
01492 w *= c;
01493 }
01494 omega = acos(w);
01495 *ang = (float)(2.0*omega);
01496 s = sin(omega);
01497 if (fabs(s) > 0.000001f)
01498 {
01499 axis.x = (float)(x / s);
01500 axis.y = (float)(y / s);
01501 axis.z = (float)(z / s);
01502 }
01503 else
01504 axis = vector3(0,0,0);
01505 }
01506