/* * ExportNebula.cpp * * This file adds the SAND to Dune: Save As Nebula Device * * This File: Copyright (C) 2001 Aaron Cram * * Dune: Copyright (C) 2000 Stephen F. White * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file "COPYING" for details); if * not, write to the Free Software Foundation, Inc., 675 Mass Ave, * Cambridge, MA 02139, USA. */ #include "../stdafx.h" #ifdef HAVE_SAND ///// skip this file if feature not enabled #include "ExportNebula.h" #include "../resource.h" #include "tools/wftoolbox.h" #include "tools/wftools.h" #ifdef WIN32 # include // for mkdir() #else # include # define _stricmp strcasecmp #endif #include "../StatusBar.h" #include "../Scene.h" #include "../Node.h" #include "../Proto.h" #include "../ExposedField.h" #include "../Field.h" #include "../MFFloat.h" #include "../MFNode.h" #include "../MFVec3f.h" #include "../MFVec2f.h" #include "../MFInt32.h" #include "../MFString.h" #include "../SFInt32.h" #include "../SFBool.h" #include "../SFNode.h" #include "../SFVec3f.h" #include "../SFColor.h" #include "../SFRotation.h" #include "../Vec3f.h" #include "../NodeImageTexture.h" ExportNebula::ExportNebula(void) { _scene = NULL; _currentDepth = _startDepth = 1; SetIndent(_startDepth); _textured = false; _alphaMap = false; _tclFP = NULL; _bbspExpand = true; // automatically preserve rotation/scale of billboards and sprites _texEnabled = true; // enable texture maps _writeMaterials = true; // output material library in .tcl file _alphaTestRef = 0.7f; // default ".setAlphaRef" value for alpha test _debugInScript = false; // insert additional debugging info in .tcl file _writeMeshes = true; // output mesh files _relativePaths = false; // makes the matlib refs relative, useful for avatars _alphaTest = true; // adds a default alpha test to alpha-mapped materials } void ExportNebula::InitMenu(SMENU menu) { _writeMeshes = true; // output mesh files _relativePaths = false; // makes the matlib refs relative, useful for avatars _alphaTest = true; // adds a default alpha test to alpha-mapped materials SMENU sandMenu = swAppendMenu(menu, "SAND"); swAppendMenuItem(sandMenu, "Export Scene", ID_SAND_EXPORT); swAppendSeparator(sandMenu); swAppendMenuItem(sandMenu, "Write Meshes", ID_SAND_WRITEMESHES); swAppendMenuItem(sandMenu, "Alpha Test Enabled", ID_SAND_ALPHATEST); swAppendMenuItem(sandMenu, "Use Relative Paths", ID_SAND_RELPATHS); swMenuSetFlags(menu, ID_SAND_WRITEMESHES, SW_MENU_CHECKED, SW_MENU_CHECKED); swMenuSetFlags(menu, ID_SAND_ALPHATEST, SW_MENU_CHECKED, SW_MENU_CHECKED); } void ExportNebula::OnToggleWriteMeshes(SMENU menu) { if (_writeMeshes) { _writeMeshes = false; swMenuSetFlags(menu, ID_SAND_WRITEMESHES, SW_MENU_CHECKED, 0); } else { _writeMeshes = true; swMenuSetFlags(menu, ID_SAND_WRITEMESHES, SW_MENU_CHECKED, SW_MENU_CHECKED); } } void ExportNebula::OnToggleUseRelativePaths(SMENU menu) { if (_relativePaths) { _relativePaths = false; swMenuSetFlags(menu, ID_SAND_RELPATHS, SW_MENU_CHECKED, 0); } else { _relativePaths = true; swMenuSetFlags(menu, ID_SAND_RELPATHS, SW_MENU_CHECKED, SW_MENU_CHECKED); } } void ExportNebula::OnToggleAlphaTest(SMENU menu) { if (_alphaTest) { _alphaTest = false; swMenuSetFlags(menu, ID_SAND_ALPHATEST, SW_MENU_CHECKED, 0); } else { _alphaTest = true; swMenuSetFlags(menu, ID_SAND_ALPHATEST, SW_MENU_CHECKED, SW_MENU_CHECKED); } } bool ExportNebula::ExportScene(char *path, Scene *scene, StatusBar *statusBar) { _statusBar = statusBar; strcpy(_tclPath, path); if (!strstr(_tclPath, ".tcl")) // TODO: make case-insensitive { strcat(_tclPath, ".tcl"); } _scene = scene; sprintf(_buf, "Exporting %s...", _tclPath); _statusBar->SetText(_buf); // setup paths and directories strcpy(_tclDir, _tclPath); char *endOfPath = strrchr(_tclDir, '\\'); if (endOfPath != NULL) { endOfPath++; *endOfPath='\0'; } // sprintf(_buf, "\n tclDir: %s\n", _tclDir); // swDebugf(_buf); sprintf(_meshDir, "%smeshes\\", _tclDir); sprintf(_mapDir, "%smaps\\", _tclDir); #ifdef WIN32 mkdir(_meshDir); mkdir(_mapDir); #else mkdir(_meshDir, S_IRWXU); mkdir(_mapDir, S_IRWXU); #endif WriteSetupScript(); _tclFP = fopen(_tclPath, "w"); if (!_tclFP) { swMessageBox(TheApp->mainWnd(), "Failed to open TCL file!", "Export Error:", SW_MB_OK, SW_MB_ERROR); return false; } if (_debugInScript) { fprintf(_tclFP, "##### debug mode on #####\n"); fprintf(_tclFP, "set debugFile [open \"debug.txt\" \"w\"]\n\n"); } if (_relativePaths) { fprintf(_tclFP, "new n3dnode matlib\n"); fprintf(_tclFP, "sel matlib\n"); } else { fprintf(_tclFP, "sel /usr/local/matlib\n"); } WalkScenegraph(_scene->getRoot(), _startDepth); if (_debugInScript) { fprintf(_tclFP, "close $debugFile\n"); } fclose(_tclFP); _statusBar->SetText("Done."); return true; } void ExportNebula::WriteSetupScript(void) { char setupPath[4096]; strcpy(setupPath, _tclPath); // extract filename from path char scriptName[512]; int spLen = strlen(setupPath); int i; int fNameLoc = 0; for (i=spLen; i>0; i--) { if (setupPath[i]=='\\' || setupPath[i]=='/') break; } if (i < spLen) { fNameLoc = i+1; char* temp = setupPath+fNameLoc; strcpy(scriptName, temp); } else return; // change file name to "world.tcl" setupPath[fNameLoc] = '\0'; strcat(setupPath, "world.tcl"); // check to see if "world.tcl" already exists. FILE* exists = fopen(setupPath, "r"); if (exists) { fclose(exists); // file is already there, we'll append onto it. _tclFP = fopen(setupPath, "a+"); if (!_tclFP) { swMessageBox(TheApp->mainWnd(), "Failed to append onto setup file!", "Export Error:", SW_MB_OK, SW_MB_ERROR); } } else { // no file exists, so we'll start over from scratch _tclFP = fopen(setupPath, "w"); if (!_tclFP) { swMessageBox(TheApp->mainWnd(), "Failed to create a new setup file!", "Export Error:", SW_MB_OK, SW_MB_ERROR); } if (_writeMaterials) { fprintf(_tclFP, "sel /usr/local\n"); fprintf(_tclFP, "new nroot matlib%s\n",_spaces); } fprintf(_tclFP, "sel /usr/local/scene\n"); fprintf(_tclFP, "new n3dnode world\n"); fprintf(_tclFP, "sel world\n"); fprintf(_tclFP, "new n3dnode lights\n"); /// begin lights TODO: make optional?? fprintf(_tclFP, "sel lights\n"); fprintf(_tclFP, " new nlightnode ambient\n"); fprintf(_tclFP, " ambient.settype ambient\n"); fprintf(_tclFP, " ambient.setcolor 0.5 0.5 0.5 1.0\n"); fprintf(_tclFP, "sel ..\n\n"); } fprintf(_tclFP, "source %s\n", scriptName); // source the scene file if (_tclFP) fclose(_tclFP); } void ExportNebula::SetIndent(int numSpaces) { _currentDepth = numSpaces; int tab = 2; memset(_spaces, ' ', 100); if (numSpaces*tab > 100) _spaces[100]='\0'; else if (numSpaces < 0) _spaces[0]='\0'; else _spaces[numSpaces*tab]='\0'; } // recursive function that walks the entire VRML scenegraph, // saving the required script commands and meshes as it goes void ExportNebula::WalkScenegraph(Node *node, int depth) { if (!_tclFP) return; // sprintf(_buf, "Depth: %i Type: %i Name: %s \n", depth, node->getType(), (const char *) (node->getName())); // swDebugf(_buf); _inSwitch = false; NodeList *children=NULL; FieldValue *value=NULL; const char *name; int numChildren = 0; int i=0; int tmp=0; const float *fpVector; Vec3f Vector; char *flag; bool billboard = false; bool sprite = false; switch (node->getType()) { case NODE_GROUP: children = ((MFNode*)node->getField(0))->getValues(); numChildren = children->size(); // sprintf(_buf, "\n numChildren: %i\n", numChildren); // swDebugf(_buf); for (i=0; iget(i), depth); if (children->get(i)->getType() == NODE_TRANSFORM) { SetIndent(depth); fprintf(_tclFP, "%ssel ..\n", _spaces); // fprintf(_tclFP, "##### NODE_GROUP\n"); } } break; // case NODE_DIRECTIONAL_LIGHT: case NODE_POINT_LIGHT: name = node->getName(); fprintf(_tclFP, "%snew n3dnode lights/%s\n",_spaces, name); fprintf(_tclFP, "%ssel lights/%s\n", _spaces, name); fpVector = ((SFVec3f *) node->getField(4))->getValue(); fprintf(_tclFP, "%s .txyz %f %f %f\n", _spaces, fpVector[0], fpVector[1], fpVector[2]); fprintf(_tclFP, "%s new nlightnode light\n",_spaces); fprintf(_tclFP, "%s sel light\n",_spaces); fprintf(_tclFP, "%s .settype point\n",_spaces); fpVector = ((SFColor *) node->getField(2))->getValue(); fprintf(_tclFP, "%s .setcolor %f %f %f 1\n",_spaces, fpVector[0], fpVector[1], fpVector[2]); /// fprintf(_tclFP, "%s .setattenuation 0.7 0 0\n",_spaces); fprintf(_tclFP, "%s sel /usr/local/scene/world\n",_spaces); break; case NODE_TRANSFORM: SetIndent(depth); name = node->getName(); fprintf(_tclFP, "%snew n3dnode %s\n", _spaces, name); fprintf(_tclFP, "%ssel %s\n", _spaces, name); SetIndent(++depth); // parse render flags strcpy(_buf, name); flag = strtok(_buf, "_"); while( flag != NULL ) { if (_stricmp(flag, "bb") == 0) billboard = true; if (_stricmp(flag, "sp") == 0) sprite = true; flag = strtok(NULL, "_"); } if (sprite) { fprintf(_tclFP, "%s.setsprite true\n", _spaces); } else if (billboard) { fprintf(_tclFP, "%s.setbillboard true\n", _spaces); } // output translation value = node->getField(5); if (!value->equals(node->getProto()->getField(5)->getDefault())) // only if not default { fpVector = ((SFVec3f*)value)->getValue(); fprintf(_tclFP, "%s.txyz %f %f %f\n", _spaces, fpVector[0], fpVector[1], fpVector[2]); } if (_bbspExpand && (sprite || billboard)) { fprintf(_tclFP, "%snew n3dnode transform\n", _spaces); fprintf(_tclFP, "%ssel transform\n", _spaces); SetIndent(++depth); } // output rotation value = node->getField(2); Vector = ((SFRotation*)value)->getEulerAngles(0); if (Vector.x!=0.0 || Vector.y!=0.0 || Vector.z!=0.0) // only if not default { fprintf(_tclFP, "%s.rxyz %f %f %f\n", _spaces, Vector.x, Vector.y, Vector.z); } // output scale value = node->getField(3); if (!value->equals(node->getProto()->getField(3)->getDefault())) // only if not default { fpVector = ((SFVec3f*)value)->getValue(); fprintf(_tclFP, "%s.sxyz %f %f %f\n", _spaces, fpVector[0], fpVector[1], fpVector[2]); } children = ((MFNode*)node->getField(1))->getValues(); numChildren = children->size(); for (i=0; iget(i)->getType() == NODE_SHAPE) { WriteShape(children->get(i)); if (_bbspExpand && (sprite || billboard)) // go back one more for billboards/sprites { SetIndent(_currentDepth-1); fprintf(_tclFP, "%ssel ..\n", _spaces); } } else { WalkScenegraph(children->get(i), depth); SetIndent(depth); fprintf(_tclFP, "%ssel ..\n", _spaces); // fprintf(_tclFP, "##### NODE_TRANSFORM (if)\n"); } } // SetIndent(depth); // fprintf(_tclFP, "%ssel ..\n", _spaces); // fprintf(_tclFP, "##### NODE_TRANSFORM\n"); break; case NODE_SWITCH: _inSwitch = true; children = ((MFNode*)node->getField(0))->getValues(); numChildren = children->size(); for (i=0; iget(i)->getType() == NODE_SHAPE) { WriteShape(children->get(i)); } else { // ??? } } if (_relativePaths) { fprintf(_tclFP, "sel ..\n"); } else { fprintf(_tclFP, "sel /usr/local/scene/world\n"); } /* fprintf(_tclFP, "new n3dnode world\n"); fprintf(_tclFP, "sel world\n"); fprintf(_tclFP, "new n3dnode lights\n"); /// begin lights TODO: make optional ******** fprintf(_tclFP, "sel lights\n"); fprintf(_tclFP, " new nlightnode ambient\n"); fprintf(_tclFP, " ambient.settype ambient\n"); fprintf(_tclFP, " ambient.setcolor 0.5 0.5 0.5 1.0\n"); fprintf(_tclFP, "sel ..\n"); */ _inSwitch = false; break; } } void ExportNebula::WriteShape(Node *node) { if (!_tclFP) return; // int type = node->getProto()->getField(0)->getType(); // sprintf(_buf, "%sNODE_SHAPE %i\n", _spaces, type); // swDebugf(_buf); Node *geoNode = ((SFNode*)node->getField(1))->getValue(); if (geoNode != NULL) { if (geoNode->getType() != NODE_INDEXED_FACE_SET) { static bool hasBeenWarned = false; if (!hasBeenWarned) { swMessageBox(TheApp->mainWnd(), "Nebula exporter only understands Geometry of type IndexedFaceSet.", "Export Warning:", SW_MB_OK, SW_MB_WARNING); hasBeenWarned = true; } return; } if (!_inSwitch) { const char *name = geoNode->getName(); if (_debugInScript) { fprintf(_tclFP, "puts $debugFile \"%s\"\n", name); } fprintf(_tclFP, "%snew n3dnode %s\n", _spaces, name); fprintf(_tclFP, "%ssel %s\n", _spaces, name); SetIndent(_currentDepth+1); } WriteGeometry(geoNode); } Node *appNode = ((SFNode*)node->getField(0))->getValue(); if (appNode != NULL) { if (_writeMaterials) { WriteAppearance(appNode); } } if (!_inSwitch) { SetIndent(_currentDepth-1); fprintf(_tclFP, "%ssel ..\n", _spaces); // fprintf(_tclFP, "##### WriteShape\n"); } } void ExportNebula::WriteAppearance(Node *node) { if (!_tclFP) return; // int type = node->getProto()->getField(0)->getType(); // sprintf(_buf, "%sNODE_Appearance %i\n", _spaces, type); // swDebugf(_buf); _alphaMap = false; _textured = false; Node *texNode = ((SFNode*)node->getField(1))->getValue(); if (texNode != NULL) { if (_texEnabled) { WriteTexture(texNode); _textured = true; } } Node *matNode = ((SFNode*)node->getField(0))->getValue(); if (matNode != NULL) { WriteMaterial(matNode); } } const char* ExportNebula::matlibPath(void) { static char path[128]; if (_relativePaths) { path[0]='\0'; for (int i=0; i<_currentDepth; i++) { strcat(path, "../"); } strcat(path, "matlib/"); } else { strcpy(path, "/usr/local/matlib/"); } return path; } void ExportNebula::WriteTexture(Node *node) { // String url(((MFString *) value)->getValue(0)); const char *name = node->getName(); if (node->needsDEF() && !_inSwitch) // link node { fprintf(_tclFP, "%snew nlinknode texmap\n", _spaces); fprintf(_tclFP, "%stexmap.settarget %s%s\n", _spaces, matlibPath(), name); } else // real node { FieldValue *value = node->getField(0); const char *url_path = (((MFString *) value)->getValue(0)); char *file_name = strrchr(url_path, '/'); if (file_name == NULL) file_name=(char*)url_path; else file_name++; _alphaMap = false; if (((NodeImageTexture*)node)->getNumComponents() == 4) _alphaMap = true; if (((NodeImageTexture*)node)->getWasScaleRequired()) { sprintf(_buf, "Texture \"%s\" is not sized in powers of two.", file_name); swMessageBox(TheApp->mainWnd(), _buf, "Export Warning:", SW_MB_OK, SW_MB_WARNING); } fprintf(_tclFP, "%snew ntexarraynode %s\n", _spaces, name); fprintf(_tclFP, "%ssel %s\n", _spaces, name); SetIndent(_startDepth+1); fprintf(_tclFP, "%s.setgenmipmaps 0 true\n", _spaces, name); fprintf(_tclFP, "%s.settexture 0 maps/%s none\n", _spaces, file_name); fprintf(_tclFP, "%ssel ..\n", _spaces); SetIndent(_startDepth); } } void ExportNebula::WriteMaterial(Node *node) { if (!_tclFP) return; const char *name = node->getName(); if (node->needsDEF() && !_inSwitch) // link node { fprintf(_tclFP, "%snew nlinknode shader\n", _spaces); fprintf(_tclFP, "%sshader.settarget %s%s\n", _spaces, matlibPath(), name); } else // real node { fprintf(_tclFP, "%snew nshadernode %s\n", _spaces, name); fprintf(_tclFP, "%ssel %s\n", _spaces, name); SetIndent(_startDepth+1); // parse render flags bool cullDisable = false; bool cullReverse = false; bool sphereMap = false; int vertexColorMode = 0; strcpy(_buf, name); char *flag = strtok(_buf, "_"); while( flag != NULL ) { if (_stricmp(flag, "sm") == 0) sphereMap = true; if (_stricmp(flag, "cd") == 0) cullDisable = true; if (_stricmp(flag, "cr") == 0) cullReverse = true; if (_stricmp(flag, "vd") == 0) vertexColorMode = 1; if (_stricmp(flag, "ve") == 0) vertexColorMode = 2; if (_stricmp(flag, "va") == 0) vertexColorMode = 3; flag = strtok(NULL, "_"); } fprintf(_tclFP, "%s.setnumstages 1\n",_spaces); fprintf(_tclFP, "%s.setlightenable true\n",_spaces); float ambient = ((SFFloat *)node->getField(0))->getValue(); fprintf(_tclFP, "%s.setambient %f %f %f 1\n", _spaces, ambient, ambient, ambient); // float difAlpha = 1.0; float difAlpha = 1.0f - ((SFFloat *)node->getField(5))->getValue(); if (_textured) { fprintf(_tclFP, "%s.setdiffuse 1 1 1 %f\n", _spaces, difAlpha); fprintf(_tclFP, "%s.setcolorop 0 \"mul tex prev\"\n",_spaces); fprintf(_tclFP, "%s.begintunit 0\n",_spaces); SetIndent(_startDepth+2); fprintf(_tclFP, "%s.setaddress wrap wrap\n",_spaces); fprintf(_tclFP, "%s.setminmagfilter linear_mipmap_nearest linear\n",_spaces); if (sphereMap) { fprintf(_tclFP, "%s.settexcoordsrc spheremap\n",_spaces); fprintf(_tclFP, "%s.setenabletransform true\n",_spaces); } else { fprintf(_tclFP, "%s.settexcoordsrc uv0\n",_spaces); fprintf(_tclFP, "%s.setenabletransform false\n",_spaces); } SetIndent(_startDepth+1); fprintf(_tclFP, "%s.endtunit\n",_spaces); } else { const float *diffuse = ((SFVec3f *)node->getField(1))->getValue(); fprintf(_tclFP, "%s.setdiffuse %f %f %f %f\n", _spaces, diffuse[0], diffuse[1], diffuse[2], difAlpha); } if (_alphaMap || difAlpha < 1.0) { fprintf(_tclFP, "%s.setalphaenable true\n",_spaces); fprintf(_tclFP, "%s.setalphablend srcalpha invsrcalpha\n",_spaces); // fprintf(_tclFP, "%s.setalphablend invsrcalpha srcalpha\n",_spaces); if (_textured && _alphaTest) { fprintf(_tclFP, "%s.setalphatestenable true\n",_spaces); fprintf(_tclFP, "%s.setalpharef %f\n",_spaces, _alphaTestRef); } } if (cullDisable) { fprintf(_tclFP, "%s.setcullmode none\n",_spaces); } else if (cullReverse) { fprintf(_tclFP, "%s.setcullmode cw\n",_spaces); } switch (vertexColorMode) { case 1: fprintf(_tclFP, "%s.setcolormaterial diffuse\n",_spaces); break; case 2: fprintf(_tclFP, "%s.setcolormaterial emissive\n",_spaces); break; case 3: fprintf(_tclFP, "%s.setcolormaterial ambient\n",_spaces); break; } fprintf(_tclFP, "%ssel ..\n",_spaces); SetIndent(_startDepth); } // sprintf(_buf, "%sambient %f\n", _spaces, ambient); // swDebugf(_buf); } void ExportNebula::WriteGeometry(Node *node) { if (!_tclFP) return; const char *name = node->getName(); if (node->needsDEF() && !_inSwitch) // link node (don't think this will work with all VRML files...) { fprintf(_tclFP, "%snew nmeshnode mesh\n", _spaces); fprintf(_tclFP, "%smesh.setfilename meshes/%s.n3d\n", _spaces, name); } else if (_writeMeshes) // real node { WriteMeshfile(node); } } // safe array access int ExportNebula::geti(const int *array, int size, int index) { if (size == 0) return -1; if (index >= size) return -1; return array[index]; } void ExportNebula::WriteMeshfile(Node *node) { const char *name = node->getName(); sprintf(_buf, "Processing geometry: %s", name); _statusBar->SetText(_buf); // fprintf(_tclFP, "\n\n*** %s\n", _buf); /// wfObject *mesh = new wfObject; // verticies Node *vtxNode = ((SFNode*)node->getField(1))->getValue(); if (vtxNode != NULL) { FieldValue *value=vtxNode->getField(0); int size = ((MFVec3f *)value)->getSize(); int stride = ((MFVec3f *)value)->getStride(); const float *vertex; for (int i=0; igetValue(i); wfCoord v(vertex[0],vertex[1],vertex[2]); mesh->v_array.push_back(v); // fprintf(_tclFP, "v %f %f %f\n", vertex[0], vertex[1], vertex[2]); /// } } // texture UVs Node *tuvNode = ((SFNode*)node->getField(3))->getValue(); if (tuvNode != NULL) { FieldValue *value=tuvNode->getField(0); int size = ((MFVec2f *)value)->getSize(); int stride = ((MFVec2f *)value)->getStride(); const float *uv; for (int i=0; igetValue(i); vector2 v(uv[0],uv[1]); mesh->vt_array.push_back(v); // fprintf(_tclFP, "vt %f %f\n", uv[0], uv[1]); /// } } // normals Node *nmlNode = ((SFNode*)node->getField(2))->getValue(); if (nmlNode != NULL) { FieldValue *value=nmlNode->getField(0); int size = ((MFVec3f *)value)->getSize(); int stride = ((MFVec3f *)value)->getStride(); const float *normal; for (int i=0; igetValue(i); vector3 v(normal[0],normal[1],normal[2]); mesh->vn_array.push_back(v); // fprintf(_tclFP, "n %f %f %f\n", normal[0], normal[1], normal[2]); /// } } // vertex colors Node *vtxColorNode = ((SFNode*)node->getField(0))->getValue(); if (vtxColorNode != NULL) { FieldValue *value=vtxColorNode->getField(0); int size = ((MFVec3f *)value)->getSize(); int stride = ((MFVec3f *)value)->getStride(); const float *vertex_color; for (int i=0; igetValue(i); vector4 vc(vertex_color[0],vertex_color[1],vertex_color[2], 1.0f); mesh->c_array.push_back(vc); // fprintf(_tclFP, "vc %f %f %f\n", vertex_color[0], vertex_color[1], vertex_color[2]); /// } } // int type = node->getProto()->getField(8)->getType(); // sprintf(_buf, "**** Coord_Index %i\n", type); // swDebugf(_buf); //// indecies FieldValue *vvalue, *tvalue, *nvalue, *cvalue; int vsize, tsize, nsize, csize; vvalue = node->getField(8); vsize = ((MFInt32 *)vvalue)->getSize(); tvalue = node->getField(13); tsize = ((MFInt32 *)tvalue)->getSize(); nvalue = node->getField(10); nsize = ((MFInt32 *)nvalue)->getSize(); cvalue = node->getField(5); csize = ((MFInt32 *)cvalue)->getSize(); // sprintf(_buf, "* vsize: %i tsize: %i nsize: %i\n", vsize, tsize, nsize); // swDebugf(_buf); const int *vi = ((MFInt32 *)vvalue)->getValues(); const int *ti = ((MFInt32 *)tvalue)->getValues(); const int *ni = ((MFInt32 *)nvalue)->getValues(); const int *ci = ((MFInt32 *)cvalue)->getValues(); for (int i=0; i=0) { wfPoint p(geti(vi,vsize,i), geti(ti,tsize,i), geti(ni,nsize,i), geti(ci,csize,i)); f.points.push_back(p); i++; } mesh->f_array.push_back(f); i++; } char meshPath[4096]; sprintf(meshPath, "%s%s.n3d", _meshDir, name); // sprintf(_buf, "Saving to file: %s\n\n", meshPath); // swDebugf(_buf); // save file FILE *meshFP; meshFP = fopen(meshPath, "w"); if (!meshFP) { // puts("Couldn't open .n3d file for output..."); return; } ////////// save original (for debugging) // mesh->save(meshFP); // fclose(meshFP); // delete mesh; // return; /////////////// wfToolbox toolbox; wfObject *mesh2; mesh2 = new wfObject; // swDebugf("Cleaning..."); toolbox.clean(*mesh,*mesh2,0.0000001f,0.0000001f,0.0000001f,0.0000001f); delete mesh; mesh = new wfObject; // swDebugf("Triangulating..."); toolbox.triangulate(*mesh2,*mesh); delete mesh2; mesh2 = new wfObject; // swDebugf("Flattening..."); toolbox.flatten(*mesh,*mesh2); delete mesh; mesh2->save(meshFP); fclose(meshFP); delete mesh2; } ///////////////// WriteMeshfile #endif /// #ifdef HAVE_SAND