diff --git a/graphicswin.cpp b/graphicswin.cpp index 08bb54d..2be3f0b 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -16,7 +16,8 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = { { 1, "&Save\tCtrl+S", MNU_SAVE, 'S'|C, mFile }, { 1, "Save &As...", MNU_SAVE_AS, 0, mFile }, { 1, NULL, 0, 0, NULL }, -{ 1, "&Export Image...", MNU_EXPORT_PNG, 0, mFile }, +{ 1, "Export &Image...", MNU_EXPORT_PNG, 0, mFile }, +{ 1, "Export &Mesh...", MNU_EXPORT_MESH, 0, mFile }, { 1, NULL, 0, 0, NULL }, { 1, "E&xit", MNU_EXIT, 0, mFile }, diff --git a/solvespace.cpp b/solvespace.cpp index 8460be6..339af96 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -473,6 +473,57 @@ void SolveSpace::SolveGroup(hGroup hg) { FreeAllTemporary(); } +void SolveSpace::ExportMeshTo(char *filename) { + SMesh *m = &(SS.GetGroup(SS.GW.activeGroup)->runningMesh); + if(m->l.n == 0) { + Error("Active group mesh is empty; nothing to export."); + return; + } + SKdNode *root = SKdNode::From(m); + root->SnapToMesh(m); + SMesh vvm; + ZERO(&vvm); + root->MakeMeshInto(&vvm); + + FILE *f = fopen(filename, "wb"); + if(!f) { + Error("Couldn't write to '%s'", filename); + vvm.Clear(); + return; + } + char str[80]; + memset(str, 0, sizeof(str)); + strcpy(str, "STL exported mesh"); + fwrite(str, 1, 80, f); + + DWORD n = vvm.l.n; + fwrite(&n, 4, 1, f); + + int i; + for(i = 0; i < vvm.l.n; i++) { + STriangle *tr = &(vvm.l.elem[i]); + Vector n = tr->Normal().WithMagnitude(1); + float w; + w = (float)n.x; fwrite(&w, 4, 1, f); + w = (float)n.y; fwrite(&w, 4, 1, f); + w = (float)n.z; fwrite(&w, 4, 1, f); + w = (float)tr->a.x; fwrite(&w, 4, 1, f); + w = (float)tr->a.y; fwrite(&w, 4, 1, f); + w = (float)tr->a.z; fwrite(&w, 4, 1, f); + w = (float)tr->b.x; fwrite(&w, 4, 1, f); + w = (float)tr->b.y; fwrite(&w, 4, 1, f); + w = (float)tr->b.z; fwrite(&w, 4, 1, f); + w = (float)tr->c.x; fwrite(&w, 4, 1, f); + w = (float)tr->c.y; fwrite(&w, 4, 1, f); + w = (float)tr->c.z; fwrite(&w, 4, 1, f); + fputc(0, f); + fputc(0, f); + } + + vvm.Clear(); + fclose(f); +} + void SolveSpace::ExportAsPngTo(char *filename) { int w = (int)SS.GW.width, h = (int)SS.GW.height; // No guarantee that the back buffer contains anything valid right now, @@ -641,6 +692,13 @@ void SolveSpace::MenuFile(int id) { break; } + case GraphicsWindow::MNU_EXPORT_MESH: { + char exportFile[MAX_PATH] = ""; + if(!GetSaveFile(exportFile, STL_EXT, STL_PATTERN)) break; + SS.ExportMeshTo(exportFile); + break; + } + case GraphicsWindow::MNU_EXIT: if(!SS.OkayToStartNewFile()) break; SS.Exit(); diff --git a/solvespace.h b/solvespace.h index 7d4c2d9..fabce78 100644 --- a/solvespace.h +++ b/solvespace.h @@ -58,6 +58,8 @@ int SaveFileYesNoCancel(void); #define SLVS_EXT "slvs" #define PNG_PATTERN "PNG (*.png)\0*.png\0All Files (*)\0*\0\0" #define PNG_EXT "png" +#define STL_PATTERN "STL Mesh (*.stl)\0*.stl\0All Files (*)\0*\0\0" +#define STL_EXT "stl" BOOL GetSaveFile(char *file, char *defExtension, char *selPattern); BOOL GetOpenFile(char *file, char *defExtension, char *selPattern); void GetAbsoluteFilename(char *file); @@ -396,8 +398,9 @@ public: bool LoadFromFile(char *filename); bool LoadEntitiesFromFile(char *filename, EntityList *le, SMesh *m); void ReloadAllImported(void); - // And the PNG export too + // And the various export options void ExportAsPngTo(char *file); + void ExportMeshTo(char *file); void MarkGroupDirty(hGroup hg); void MarkGroupDirtyByEntity(hEntity he); diff --git a/ui.h b/ui.h index 1009a58..0e9e03a 100644 --- a/ui.h +++ b/ui.h @@ -148,6 +148,7 @@ public: MNU_SAVE, MNU_SAVE_AS, MNU_EXPORT_PNG, + MNU_EXPORT_MESH, MNU_EXIT, // View MNU_ZOOM_IN,