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;
}
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 *ret;
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
// not self-intersecting, so not much to do.
// Export a triangle mesh, in the requested format.
//-----------------------------------------------------------------------------
void SolveSpace::ExportMeshTo(char *filename) {
SMesh *m = &(SK.GetGroup(SS.GW.activeGroup)->displayMesh);
@ -567,18 +553,36 @@ void SolveSpace::ExportMeshTo(char *filename) {
Error("Couldn't write to '%s'", filename);
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];
memset(str, 0, sizeof(str));
strcpy(str, "STL exported mesh");
fwrite(str, 1, 80, f);
DWORD n = m->l.n;
DWORD n = sm->l.n;
fwrite(&n, 4, 1, f);
double s = SS.exportScale;
int i;
for(i = 0; i < m->l.n; i++) {
STriangle *tr = &(m->l.elem[i]);
for(i = 0; i < sm->l.n; i++) {
STriangle *tr = &(sm->l.elem[i]);
Vector n = tr->Normal().WithMagnitude(1);
float w;
w = (float)n.x; fwrite(&w, 4, 1, f);
@ -596,8 +600,41 @@ void SolveSpace::ExportMeshTo(char *filename) {
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) {
SPoint *p;
for(p = l.First(); p; p = l.NextAfter(p)) {
return (IndexForPoint(pt) >= 0);
}
int SPointList::IndexForPoint(Vector pt) {
int i;
for(i = 0; i < l.n; i++) {
SPoint *p = &(l.elem[i]);
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) {

View File

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

View File

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

View File

@ -82,8 +82,10 @@ int SaveFileYesNoCancel(void);
#define PNG_PATTERN "PNG (*.png)\0*.png\0All Files (*)\0*\0\0"
#define PNG_EXT "png"
// Triangle mesh
#define STL_PATTERN "STL Mesh (*.stl)\0*.stl\0All Files (*)\0*\0\0"
#define STL_EXT "stl"
#define MESH_PATTERN "STL Mesh (*.stl)\0*.stl\0" \
"Wavefront OBJ Mesh (*.obj)\0*.obj\0" \
"All Files (*)\0*\0\0"
#define MESH_EXT "stl"
// NURBS surfaces
#define SRF_PATTERN "STEP File (*.step;*.stp)\0*.step;*.stp\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 MakePathAbsolute(char *base, char *path);
bool StringAllPrintable(char *str);
bool StringEndsIn(char *str, char *ending);
class System {
public:
@ -406,7 +409,6 @@ public:
Vector ptMin, ptMax;
static double MmToPts(double mm);
static bool StringEndsIn(char *str, char *ending);
static VectorFileWriter *ForFile(char *file);
@ -629,6 +631,8 @@ public:
// And the various export options
void ExportAsPngTo(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 ExportSectionTo(char *file);
void ExportWireframeCurves(SEdgeList *sel, SBezierList *sbl,

View File

@ -88,6 +88,20 @@ bool StringAllPrintable(char *str)
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,
double a21, double a22, double a23, double a24,
double a31, double a32, double a33, double a34,