Wavefront OBJ: export mesh color as well.
This commit is contained in:
parent
aa958504af
commit
f4e85127d6
|
@ -7,6 +7,8 @@ Changelog
|
||||||
New export/import features:
|
New export/import features:
|
||||||
* Three.js: allow configuring projection for exported model, and initially
|
* Three.js: allow configuring projection for exported model, and initially
|
||||||
use the current viewport projection.
|
use the current viewport projection.
|
||||||
|
* Wavefront OBJ: a material file is exported alongside the model, containing
|
||||||
|
mesh color information.
|
||||||
|
|
||||||
New rendering features:
|
New rendering features:
|
||||||
* The "Show/hide hidden lines" button is now a tri-state button that allows
|
* The "Show/hide hidden lines" button is now a tri-state button that allows
|
||||||
|
|
|
@ -532,7 +532,12 @@ public:
|
||||||
(int)((bgra) & 0xff),
|
(int)((bgra) & 0xff),
|
||||||
(int)(255 - ((bgra >> 24) & 0xff)));
|
(int)(255 - ((bgra >> 24) & 0xff)));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RgbaColorCompare {
|
||||||
|
bool operator()(RgbaColor a, RgbaColor b) const {
|
||||||
|
return a.ToARGB32() < b.ToARGB32();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BBox {
|
class BBox {
|
||||||
|
|
|
@ -816,7 +816,18 @@ void SolveSpaceUI::ExportMeshTo(const std::string &filename) {
|
||||||
if(FilenameHasExtension(filename, ".stl")) {
|
if(FilenameHasExtension(filename, ".stl")) {
|
||||||
ExportMeshAsStlTo(f, m);
|
ExportMeshAsStlTo(f, m);
|
||||||
} else if(FilenameHasExtension(filename, ".obj")) {
|
} else if(FilenameHasExtension(filename, ".obj")) {
|
||||||
ExportMeshAsObjTo(f, m);
|
std::string mtlFilename = filename.substr(0, filename.length() - 4) + ".mtl";
|
||||||
|
FILE *fMtl = ssfopen(mtlFilename, "wb");
|
||||||
|
if(!fMtl) {
|
||||||
|
Error("Couldn't write to '%s'", filename.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string mtlBasename = mtlFilename.substr(mtlFilename.rfind(PATH_SEP) + 1);
|
||||||
|
fprintf(f, "mtllib %s\n", mtlBasename.c_str());
|
||||||
|
ExportMeshAsObjTo(f, fMtl, m);
|
||||||
|
|
||||||
|
fclose(fMtl);
|
||||||
} else if(FilenameHasExtension(filename, ".js") ||
|
} else if(FilenameHasExtension(filename, ".js") ||
|
||||||
FilenameHasExtension(filename, ".html")) {
|
FilenameHasExtension(filename, ".html")) {
|
||||||
SOutlineList *e = &(SK.GetGroup(SS.GW.activeGroup)->displayOutlines);
|
SOutlineList *e = &(SK.GetGroup(SS.GW.activeGroup)->displayOutlines);
|
||||||
|
@ -872,34 +883,51 @@ void SolveSpaceUI::ExportMeshAsStlTo(FILE *f, SMesh *sm) {
|
||||||
// Export the mesh as Wavefront OBJ format. This requires us to reduce all the
|
// Export the mesh as Wavefront OBJ format. This requires us to reduce all the
|
||||||
// identical vertices to the same identifier, so do that first.
|
// identical vertices to the same identifier, so do that first.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void SolveSpaceUI::ExportMeshAsObjTo(FILE *f, SMesh *sm) {
|
void SolveSpaceUI::ExportMeshAsObjTo(FILE *fObj, FILE *fMtl, SMesh *sm) {
|
||||||
SPointList spl = {};
|
std::map<RgbaColor, std::string, RgbaColorCompare> colors;
|
||||||
STriangle *tr;
|
for(const STriangle &t : sm->l) {
|
||||||
for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) {
|
RgbaColor color = t.meta.color;
|
||||||
spl.IncrementTagFor(tr->a);
|
if(colors.find(color) == colors.end()) {
|
||||||
spl.IncrementTagFor(tr->b);
|
std::string id = ssprintf("h%02x%02x%02x",
|
||||||
spl.IncrementTagFor(tr->c);
|
color.red,
|
||||||
|
color.green,
|
||||||
|
color.blue);
|
||||||
|
colors.emplace(color, id);
|
||||||
|
}
|
||||||
|
for(int i = 0; i < 3; i++) {
|
||||||
|
fprintf(fObj, "v %.10f %.10f %.10f\n",
|
||||||
|
CO(t.vertices[i].ScaledBy(1 / SS.exportScale)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output all the vertices.
|
for(auto &it : colors) {
|
||||||
SPoint *sp;
|
fprintf(fMtl, "newmtl %s\n",
|
||||||
for(sp = spl.l.First(); sp; sp = spl.l.NextAfter(sp)) {
|
it.second.c_str());
|
||||||
fprintf(f, "v %.10f %.10f %.10f\r\n",
|
fprintf(fMtl, "Kd %.3f %.3f %.3f\n",
|
||||||
sp->p.x / SS.exportScale,
|
it.first.redF(), it.first.greenF(), it.first.blueF());
|
||||||
sp->p.y / SS.exportScale,
|
|
||||||
sp->p.z / SS.exportScale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// And now all the triangular faces, in terms of those vertices. The
|
for(const STriangle &t : sm->l) {
|
||||||
// file format counts from 1, not 0.
|
for(int i = 0; i < 3; i++) {
|
||||||
for(tr = sm->l.First(); tr; tr = sm->l.NextAfter(tr)) {
|
Vector n = t.normals[i].WithMagnitude(1.0);
|
||||||
fprintf(f, "f %d %d %d\r\n",
|
fprintf(fObj, "vn %.10f %.10f %.10f\n",
|
||||||
spl.IndexForPoint(tr->a) + 1,
|
CO(n));
|
||||||
spl.IndexForPoint(tr->b) + 1,
|
}
|
||||||
spl.IndexForPoint(tr->c) + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spl.Clear();
|
RgbaColor currentColor = {};
|
||||||
|
for(int i = 0; i < sm->l.n; i++) {
|
||||||
|
const STriangle &t = sm->l.elem[i];
|
||||||
|
if(!currentColor.Equals(t.meta.color)) {
|
||||||
|
currentColor = t.meta.color;
|
||||||
|
fprintf(fObj, "usemtl %s\n", colors[currentColor].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fObj, "f %d//%d %d//%d %d//%d\n",
|
||||||
|
i * 3 + 1, i * 3 + 1,
|
||||||
|
i * 3 + 2, i * 3 + 2,
|
||||||
|
i * 3 + 3, i * 3 + 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -815,7 +815,7 @@ public:
|
||||||
void ExportAsPngTo(const std::string &filename);
|
void ExportAsPngTo(const std::string &filename);
|
||||||
void ExportMeshTo(const std::string &filename);
|
void ExportMeshTo(const std::string &filename);
|
||||||
void ExportMeshAsStlTo(FILE *f, SMesh *sm);
|
void ExportMeshAsStlTo(FILE *f, SMesh *sm);
|
||||||
void ExportMeshAsObjTo(FILE *f, SMesh *sm);
|
void ExportMeshAsObjTo(FILE *fObj, FILE *fMtl, SMesh *sm);
|
||||||
void ExportMeshAsThreeJsTo(FILE *f, const std::string &filename,
|
void ExportMeshAsThreeJsTo(FILE *f, const std::string &filename,
|
||||||
SMesh *sm, SOutlineList *sol);
|
SMesh *sm, SOutlineList *sol);
|
||||||
void ExportViewOrWireframeTo(const std::string &filename, bool exportWireframe);
|
void ExportViewOrWireframeTo(const std::string &filename, bool exportWireframe);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user