Add Wavefront OBJ support, to supplement the existing STL mesh

export. That doesn't seem very useful, but it's only a few dozen
lines of code.

[git-p4: depot-paths = "//depot/solvespace/": change = 2054]
This commit is contained in:
Jonathan Westhues 2009-10-12 03:34:43 -08:00
parent 83bbc004dc
commit f6bb680978
6 changed files with 89 additions and 27 deletions

View File

@ -340,19 +340,6 @@ double VectorFileWriter::MmToPts(double mm) {
return (mm/25.4)*72; return (mm/25.4)*72;
} }
bool VectorFileWriter::StringEndsIn(char *str, char *ending) {
int i, ls = strlen(str), le = strlen(ending);
if(ls < le) return false;
for(i = 0; i < le; i++) {
if(tolower(ending[le-i-1]) != tolower(str[ls-i-1])) {
return false;
}
}
return true;
}
VectorFileWriter *VectorFileWriter::ForFile(char *filename) { VectorFileWriter *VectorFileWriter::ForFile(char *filename) {
VectorFileWriter *ret; VectorFileWriter *ret;
if(StringEndsIn(filename, ".dxf")) { if(StringEndsIn(filename, ".dxf")) {
@ -552,8 +539,7 @@ void VectorFileWriter::BezierAsNonrationalCubic(DWORD rgb, double width,
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Export the mesh as an STL file; it should always be vertex-to-vertex and // Export a triangle mesh, in the requested format.
// not self-intersecting, so not much to do.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SolveSpace::ExportMeshTo(char *filename) { void SolveSpace::ExportMeshTo(char *filename) {
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh); SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
@ -567,18 +553,36 @@ void SolveSpace::ExportMeshTo(char *filename) {
Error("Couldn't write to '%s'", filename); Error("Couldn't write to '%s'", filename);
return; return;
} }
if(StringEndsIn(filename, ".stl")) {
ExportMeshAsStlTo(f, m);
} else if(StringEndsIn(filename, ".obj")) {
ExportMeshAsObjTo(f, m);
} else {
Error("Can't identify output file type from file extension of "
"filename '%s'; try .stl, .obj.", filename);
}
fclose(f);
}
//-----------------------------------------------------------------------------
// Export the mesh as an STL file; it should always be vertex-to-vertex and
// not self-intersecting, so not much to do.
//-----------------------------------------------------------------------------
void SolveSpace::ExportMeshAsStlTo(FILE *f, SMesh *sm) {
char str[80]; char str[80];
memset(str, 0, sizeof(str)); memset(str, 0, sizeof(str));
strcpy(str, "STL exported mesh"); strcpy(str, "STL exported mesh");
fwrite(str, 1, 80, f); fwrite(str, 1, 80, f);
DWORD n = m->l.n; DWORD n = sm->l.n;
fwrite(&n, 4, 1, f); fwrite(&n, 4, 1, f);
double s = SS.exportScale; double s = SS.exportScale;
int i; int i;
for(i = 0; i < m->l.n; i++) { for(i = 0; i < sm->l.n; i++) {
STriangle *tr = &(m->l.elem[i]); STriangle *tr = &(sm->l.elem[i]);
Vector n = tr->Normal().WithMagnitude(1); Vector n = tr->Normal().WithMagnitude(1);
float w; float w;
w = (float)n.x; fwrite(&w, 4, 1, f); w = (float)n.x; fwrite(&w, 4, 1, f);
@ -596,8 +600,41 @@ void SolveSpace::ExportMeshTo(char *filename) {
fputc(0, f); fputc(0, f);
fputc(0, f); fputc(0, f);
} }
}
fclose(f); //-----------------------------------------------------------------------------
// Export the mesh as Wavefront OBJ format. This requires us to reduce all the
// identical vertices to the same identifier, so do that first.
//-----------------------------------------------------------------------------
void SolveSpace::ExportMeshAsObjTo(FILE *f, SMesh *sm) {
SPointList spl;
ZERO(&spl);
STriangle *tr;
for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) {
spl.IncrementTagFor(tr->a);
spl.IncrementTagFor(tr->b);
spl.IncrementTagFor(tr->c);
}
// Output all the vertices.
SPoint *sp;
for(sp = spl.l.First(); sp; sp = spl.l.NextAfter(sp)) {
fprintf(f, "v %.10f %.10f %.10f\r\n",
sp->p.x / SS.exportScale,
sp->p.y / SS.exportScale,
sp->p.z / SS.exportScale);
}
// And now all the triangular faces, in terms of those vertices. The
// file format counts from 1, not 0.
for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) {
fprintf(f, "f %d %d %d\r\n",
spl.IndexForPoint(tr->a) + 1,
spl.IndexForPoint(tr->b) + 1,
spl.IndexForPoint(tr->c) + 1);
}
spl.Clear();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -313,13 +313,19 @@ void SPointList::Clear(void) {
} }
bool SPointList::ContainsPoint(Vector pt) { bool SPointList::ContainsPoint(Vector pt) {
SPoint *p; return (IndexForPoint(pt) >= 0);
for(p = l.First(); p; p = l.NextAfter(p)) { }
int SPointList::IndexForPoint(Vector pt) {
int i;
for(i = 0; i < l.n; i++) {
SPoint *p = &(l.elem[i]);
if(pt.Equals(p->p)) { if(pt.Equals(p->p)) {
return true; return i;
} }
} }
return false; // Not found, so return negative to indicate that.
return -1;
} }
void SPointList::IncrementTagFor(Vector pt) { void SPointList::IncrementTagFor(Vector pt) {

View File

@ -53,6 +53,7 @@ public:
void Clear(void); void Clear(void);
bool ContainsPoint(Vector pt); bool ContainsPoint(Vector pt);
int IndexForPoint(Vector pt);
void IncrementTagFor(Vector pt); void IncrementTagFor(Vector pt);
void Add(Vector pt); void Add(Vector pt);
}; };

View File

@ -435,7 +435,7 @@ void SolveSpace::MenuFile(int id) {
case GraphicsWindow::MNU_EXPORT_MESH: { case GraphicsWindow::MNU_EXPORT_MESH: {
char exportFile[MAX_PATH] = ""; char exportFile[MAX_PATH] = "";
if(!GetSaveFile(exportFile, STL_EXT, STL_PATTERN)) break; if(!GetSaveFile(exportFile, MESH_EXT, MESH_PATTERN)) break;
SS.ExportMeshTo(exportFile); SS.ExportMeshTo(exportFile);
break; break;
} }

View File

@ -82,8 +82,10 @@ int SaveFileYesNoCancel(void);
#define PNG_PATTERN "PNG (*.png)\0*.png\0All Files (*)\0*\0\0" #define PNG_PATTERN "PNG (*.png)\0*.png\0All Files (*)\0*\0\0"
#define PNG_EXT "png" #define PNG_EXT "png"
// Triangle mesh // Triangle mesh
#define STL_PATTERN "STL Mesh (*.stl)\0*.stl\0All Files (*)\0*\0\0" #define MESH_PATTERN "STL Mesh (*.stl)\0*.stl\0" \
#define STL_EXT "stl" "Wavefront OBJ Mesh (*.obj)\0*.obj\0" \
"All Files (*)\0*\0\0"
#define MESH_EXT "stl"
// NURBS surfaces // NURBS surfaces
#define SRF_PATTERN "STEP File (*.step;*.stp)\0*.step;*.stp\0" \ #define SRF_PATTERN "STEP File (*.step;*.stp)\0*.step;*.stp\0" \
"All Files(*)\0*\0\0" "All Files(*)\0*\0\0"
@ -228,6 +230,7 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
void MakePathRelative(char *base, char *path); void MakePathRelative(char *base, char *path);
void MakePathAbsolute(char *base, char *path); void MakePathAbsolute(char *base, char *path);
bool StringAllPrintable(char *str); bool StringAllPrintable(char *str);
bool StringEndsIn(char *str, char *ending);
class System { class System {
public: public:
@ -406,7 +409,6 @@ public:
Vector ptMin, ptMax; Vector ptMin, ptMax;
static double MmToPts(double mm); static double MmToPts(double mm);
static bool StringEndsIn(char *str, char *ending);
static VectorFileWriter *ForFile(char *file); static VectorFileWriter *ForFile(char *file);
@ -629,6 +631,8 @@ public:
// And the various export options // And the various export options
void ExportAsPngTo(char *file); void ExportAsPngTo(char *file);
void ExportMeshTo(char *file); void ExportMeshTo(char *file);
void ExportMeshAsStlTo(FILE *f, SMesh *sm);
void ExportMeshAsObjTo(FILE *f, SMesh *sm);
void ExportViewOrWireframeTo(char *file, bool wireframe); void ExportViewOrWireframeTo(char *file, bool wireframe);
void ExportSectionTo(char *file); void ExportSectionTo(char *file);
void ExportWireframeCurves(SEdgeList *sel, SBezierList *sbl, void ExportWireframeCurves(SEdgeList *sel, SBezierList *sbl,

View File

@ -88,6 +88,20 @@ bool StringAllPrintable(char *str)
return true; return true;
} }
bool StringEndsIn(char *str, char *ending)
{
int i, ls = strlen(str), le = strlen(ending);
if(ls < le) return false;
for(i = 0; i < le; i++) {
if(tolower(ending[le-i-1]) != tolower(str[ls-i-1])) {
return false;
}
}
return true;
}
void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
double a21, double a22, double a23, double a24, double a21, double a22, double a23, double a24,
double a31, double a32, double a33, double a34, double a31, double a32, double a33, double a34,