Implement --use-names and --use-guids for DAE, OBJ, and SVG output.

This commit is contained in:
Stinkfist0
2016-03-10 11:35:32 +02:00
parent 50a467fda5
commit 43f5d446ec
17 changed files with 316 additions and 164 deletions
+130 -46
View File
@@ -19,48 +19,96 @@
#ifdef WITH_OPENCOLLADA #ifdef WITH_OPENCOLLADA
#include <string>
#include "ColladaSerializer.h" #include "ColladaSerializer.h"
std::string collada_id(const std::string& s) { #include <COLLADASWPrimitves.h>
std::string id; #include <COLLADASWSource.h>
id.reserve(s.size()); #include <COLLADASWScene.h>
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { #include <COLLADASWNode.h>
const std::string::value_type c = *it; #include <COLLADASWInstanceGeometry.h>
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || ( c == '-')) { #include <COLLADASWBaseInputElement.h>
id.push_back(c); #include <COLLADASWAsset.h>
}
} #include <string>
return id; #include <cmath>
static void collada_id(std::string &s)
{
IfcUtil::sanitate_material_name(s);
IfcUtil::escape_xml(s);
} }
void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector<double>& floats, const char* coords /* = "XYZ" */) { #if 0
static std::vector<real_t> boxProjectUVs(const std::vector<real_t> &vertices, const std::vector<real_t> &normals) {
assert(vertices.size() == normals.size());
//TODO if (vertices.size() != normals.size()) log error?
std::vector<real_t> uvs;
uvs.resize(vertices.size() / 3 * 2);
for(size_t uv_idx = 0, v_idx = 0;
uv_idx < uvs.size() && v_idx < vertices.size() && v_idx < normals.size();
uv_idx += 2, v_idx += 3) {
real_t n_x = normals[v_idx], n_y = normals[v_idx+1], n_z = normals[v_idx+2];
real_t v_x = vertices[v_idx], v_y = vertices[v_idx+1], v_z = vertices[v_idx+2];
if (std::abs(n_x) > std::abs(n_y) && std::abs(n_x) > std::abs(n_z)) {
uvs[uv_idx] = v_z;
uvs[uv_idx+1] = v_y;
}
if (std::abs(n_y) > std::abs(n_x) && std::abs(n_y) > std::abs(n_z)) {
uvs[uv_idx] = v_x;
uvs[uv_idx+1] = v_z;
}
if (std::abs(n_z) > std::abs(n_x) && std::abs(n_z) > std::abs(n_y)) {
uvs[uv_idx] = v_x;
uvs[uv_idx+1] = v_y;
}
}
return uvs;
}
#endif
void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id,
const std::string& suffix, const std::vector<real_t>& floats, const char* coords /* = "XYZ" */)
{
COLLADASW::FloatSource source(mSW); COLLADASW::FloatSource source(mSW);
source.setId(mesh_id + suffix); source.setId(mesh_id + suffix);
source.setArrayId(mesh_id + suffix + COLLADASW::LibraryGeometries::ARRAY_ID_SUFFIX); source.setArrayId(mesh_id + suffix + COLLADASW::LibraryGeometries::ARRAY_ID_SUFFIX);
source.setAccessorStride((unsigned long)strlen(coords)); const size_t num_elems = strlen(coords);
source.setAccessorCount((unsigned long)floats.size() / 3); source.setAccessorStride(static_cast<unsigned long>(num_elems));
for (unsigned int i = 0; i < source.getAccessorStride(); ++i) { source.setAccessorCount(static_cast<unsigned long>(floats.size() / num_elems));
for (size_t i = 0; i < num_elems; ++i) {
source.getParameterNameList().push_back(std::string(1, coords[i])); source.getParameterNameList().push_back(std::string(1, coords[i]));
} }
source.prepareToAppendValues(); source.prepareToAppendValues();
for (std::vector<double>::const_iterator it = floats.begin(); it != floats.end(); ++it) { for (std::vector<real_t>::const_iterator it = floats.begin(); it != floats.end(); ++it) {
source.appendValues(*it); source.appendValues(*it);
} }
source.finish(); source.finish();
} }
void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::string mesh_id, const std::string& default_material_name, const std::vector<double>& positions, const std::vector<double>& normals, const std::vector<int>& faces, const std::vector<int>& edges, const std::vector<int> material_ids, const std::vector<IfcGeom::Material>& materials) { void ColladaSerializer::ColladaExporter::ColladaGeometries::write(
const std::string &mesh_id, const std::string& default_material_name, const std::vector<real_t>& positions,
const std::vector<real_t>& normals, const std::vector<int>& faces, const std::vector<int>& edges,
const std::vector<int> material_ids, const std::vector<IfcGeom::Material>& materials)
{
openMesh(mesh_id); openMesh(mesh_id);
// The normals vector can be empty for example when the WELD_VERTICES setting is used. // The normals vector can be empty for example when the WELD_VERTICES setting is used.
// IfcOpenShell does not provide them with multiple face normals collapsed into a single vertex. // IfcOpenShell does not provide them with multiple face normals collapsed into a single vertex.
const bool has_normals = !normals.empty(); const bool has_normals = !normals.empty();
#if 0
const bool generate_uvs = (has_normals && serializer->settings()..get(IfcGeom::IteratorSettings::GENERATE_UVS));
#endif
addFloatSource(mesh_id, COLLADASW::LibraryGeometries::POSITIONS_SOURCE_ID_SUFFIX, positions); addFloatSource(mesh_id, COLLADASW::LibraryGeometries::POSITIONS_SOURCE_ID_SUFFIX, positions);
if (has_normals) { if (has_normals) {
addFloatSource(mesh_id, COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, normals); addFloatSource(mesh_id, COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, normals);
#if 0
if (generate_uvs) {
addFloatSource(mesh_id, COLLADASW::LibraryGeometries::TEXCOORDS_SOURCE_ID_SUFFIX, boxProjectUVs(positions, normals), "UV");
}
#endif
} }
COLLADASW::VerticesElement vertices(mSW); COLLADASW::VerticesElement vertices(mSW);
@@ -73,20 +121,29 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::str
int previous_material_id = -1; int previous_material_id = -1;
for (std::vector<int>::const_iterator it = faces.begin(); !faces.empty(); it += 3) { for (std::vector<int>::const_iterator it = faces.begin(); !faces.empty(); it += 3) {
const int current_material_id = *(material_it++); const int current_material_id = *(material_it++);
const unsigned long num_triangles = (unsigned long)std::distance(index_range_start, it) / 3; const size_t num_triangles = std::distance(index_range_start, it) / 3;
if ((previous_material_id != current_material_id && num_triangles > 0) || (it == faces.end())) { if ((previous_material_id != current_material_id && num_triangles > 0) || (it == faces.end())) {
COLLADASW::Triangles triangles(mSW); COLLADASW::Triangles triangles(mSW);
triangles.setMaterial(materials[previous_material_id].name()); std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? materials[previous_material_id].original_name() : materials[previous_material_id].name());
triangles.setCount(num_triangles); collada_id(material_name);
triangles.setMaterial(material_name);
triangles.setCount((unsigned long)num_triangles);
int offset = 0; int offset = 0;
triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++ ) ); triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++));
if (has_normals) { if (has_normals) {
triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::NORMAL,"#" + mesh_id + COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, offset++ ) ); triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::NORMAL,"#" + mesh_id + COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, offset++));
} }
#if 0
if (generate_uvs) {
triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::TEXCOORD,"#" + mesh_id + COLLADASW::LibraryGeometries::TEXCOORDS_SOURCE_ID_SUFFIX, offset++));
}
#endif
triangles.prepareToAppendValues(); triangles.prepareToAppendValues();
for (std::vector<int>::const_iterator jt = index_range_start; jt != it; ++jt) { for (std::vector<int>::const_iterator jt = index_range_start; jt != it; ++jt) {
const int idx = *jt; const int idx = *jt;
if (has_normals) { /*if (has_normals && generate_uvs) {
triangles.appendValues(idx, idx, idx);
} else*/ if(has_normals) {
triangles.appendValues(idx, idx); triangles.appendValues(idx, idx);
} else { } else {
triangles.appendValues(idx); triangles.appendValues(idx);
@@ -125,10 +182,12 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::str
for (linelist_t::const_iterator it = linelist.begin(); it != linelist.end(); ++it) { for (linelist_t::const_iterator it = linelist.begin(); it != linelist.end(); ++it) {
COLLADASW::Lines lines(mSW); COLLADASW::Lines lines(mSW);
lines.setMaterial(materials[it->first].name()); std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? materials[it->first].original_name() : materials[it->first].name());
collada_id(material_name);
lines.setMaterial(material_name);
lines.setCount((unsigned long)it->second.size()); lines.setCount((unsigned long)it->second.size());
int offset = 0; int offset = 0;
lines.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX, "#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++)); lines.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX, "#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset));
lines.prepareToAppendValues(); lines.prepareToAppendValues();
lines.appendValues(it->second); lines.appendValues(it->second);
lines.finish(); lines.finish();
@@ -142,7 +201,10 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::close() {
closeLibrary(); closeLibrary();
} }
void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector<std::string>& material_ids, const std::vector<double>& matrix) { void ColladaSerializer::ColladaExporter::ColladaScene::add(
const std::string& node_id, const std::string& node_name, const std::string& geom_name,
const std::vector<std::string>& material_ids, const std::vector<real_t>& matrix)
{
if (!scene_opened) { if (!scene_opened) {
openVisualScene(scene_id); openVisualScene(scene_id);
scene_opened = true; scene_opened = true;
@@ -156,18 +218,26 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& no
// The matrix attribute of an entity is basically a 4x3 representation of its ObjectPlacement. // The matrix attribute of an entity is basically a 4x3 representation of its ObjectPlacement.
// Note that this placement is absolute, ie it is multiplied with all parent placements. // Note that this placement is absolute, ie it is multiplied with all parent placements.
double matrix_array[4][4] = { double matrix_array[4][4] = {
{matrix[0], matrix[3], matrix[6], matrix[ 9]}, { (double)matrix[0], (double)matrix[3], (double)matrix[6], (double)matrix[ 9] },
{matrix[1], matrix[4], matrix[7], matrix[10]}, { (double)matrix[1], (double)matrix[4], (double)matrix[7], (double)matrix[10] },
{matrix[2], matrix[5], matrix[8], matrix[11]}, { (double)matrix[2], (double)matrix[5], (double)matrix[8], (double)matrix[11] },
{ 0, 0, 0, 1} { 0, 0, 0, 1 }
}; };
#if 0
matrix_array[0][3] += serializer->settings().offset[0];
matrix_array[1][3] += serializer->settings().offset[1];
matrix_array[2][3] += serializer->settings().offset[2];
#endif
node.start(); node.start();
node.addMatrix(matrix_array); node.addMatrix(matrix_array);
COLLADASW::InstanceGeometry instanceGeometry(mSW); COLLADASW::InstanceGeometry instanceGeometry(mSW);
instanceGeometry.setUrl ("#" + geom_name); instanceGeometry.setUrl ("#" + geom_name);
for (std::vector<std::string>::const_iterator it = material_ids.begin(); it != material_ids.end(); ++it) { foreach(std::string material_name, material_ids) {
COLLADASW::InstanceMaterial material (*it, "#" + *it); /// @todo This is done 6 times in this file, try to perform this once and be done with the material naming for the export.
collada_id(material_name);
COLLADASW::InstanceMaterial material (material_name, "#" + material_name);
instanceGeometry.getBindMaterial().getInstanceMaterialList().push_back(material); instanceGeometry.getBindMaterial().getInstanceMaterialList().push_back(material);
} }
instanceGeometry.add(); instanceGeometry.add();
@@ -184,8 +254,11 @@ void ColladaSerializer::ColladaExporter::ColladaScene::write() {
} }
} }
void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeom::Material& material) { void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeom::Material& material)
openEffect(collada_id(material.name()) + "-fx"); {
std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? material.original_name() : material.name());
collada_id(material_name);
openEffect(material_name + "-fx");
COLLADASW::EffectProfile effect(mSW); COLLADASW::EffectProfile effect(mSW);
effect.setShaderType(COLLADASW::EffectProfile::LAMBERT); effect.setShaderType(COLLADASW::EffectProfile::LAMBERT);
if (material.hasDiffuse()) { if (material.hasDiffuse()) {
@@ -228,10 +301,13 @@ bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeo
void ColladaSerializer::ColladaExporter::ColladaMaterials::write() { void ColladaSerializer::ColladaExporter::ColladaMaterials::write() {
effects.close(); effects.close();
for (std::vector<IfcGeom::Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) { foreach(const IfcGeom::Material& material, materials) {
const std::string& material_name = collada_id((*it).name()); std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? material.original_name() : material.name());
std::string material_name_unescaped = material_name; // workaround double-escaping that would occur in addInstanceEffect()
IfcUtil::sanitate_material_name(material_name_unescaped);
collada_id(material_name);
openMaterial(material_name); openMaterial(material_name);
addInstanceEffect("#" + material_name + "-fx"); addInstanceEffect("#" + material_name_unescaped + "-fx");
closeMaterial(); closeMaterial();
} }
closeLibrary(); closeLibrary();
@@ -247,14 +323,19 @@ void ColladaSerializer::ColladaExporter::startDocument(const std::string& unit_n
asset.add(); asset.add();
} }
void ColladaSerializer::ColladaExporter::write(const std::string& unique_id, const std::string& type, const std::vector<double>& matrix, const std::vector<double>& vertices, const std::vector<double>& normals, const std::vector<int>& faces, const std::vector<int>& edges, const std::vector<int>& material_ids, const std::vector<IfcGeom::Material>& _materials) { void ColladaSerializer::ColladaExporter::write(const std::string& unique_id, const std::string& type,
const std::vector<real_t>& matrix, const std::vector<real_t>& vertices, const std::vector<real_t>& normals,
const std::vector<int>& faces, const std::vector<int>& edges, const std::vector<int>& material_ids,
const std::vector<IfcGeom::Material>& _materials)
{
std::vector<std::string> material_references; std::vector<std::string> material_references;
for (std::vector<IfcGeom::Material>::const_iterator it = _materials.begin(); it != _materials.end(); ++it) { foreach(const IfcGeom::Material& material, _materials) {
const IfcGeom::Material& material = *it;
if (!materials.contains(material)) { if (!materials.contains(material)) {
materials.add(material); materials.add(material);
} }
material_references.push_back(collada_id(material.name())); std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? material.original_name() : material.name());
collada_id(material_name);
material_references.push_back(material_name);
} }
deferreds.push_back(DeferredObject(unique_id, type, matrix, vertices, normals, faces, edges, material_ids, _materials, material_references)); deferreds.push_back(DeferredObject(unique_id, type, matrix, vertices, normals, faces, edges, material_ids, _materials, material_references));
} }
@@ -284,9 +365,12 @@ void ColladaSerializer::writeHeader() {
exporter.startDocument(unit_name, unit_magnitude); exporter.startDocument(unit_name, unit_magnitude);
} }
void ColladaSerializer::write(const IfcGeom::TriangulationElement<double>* o) { void ColladaSerializer::write(const IfcGeom::TriangulationElement<real_t>* o) {
const IfcGeom::Representation::Triangulation<double>& mesh = o->geometry(); const IfcGeom::Representation::Triangulation<real_t>& mesh = o->geometry();
exporter.write(o->unique_id(), o->type(), o->transformation().matrix().data(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials()); const std::string name = settings().get(IfcGeom::IteratorSettings::USE_GUIDS) ?
o->guid() : (settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? o->name() : o->unique_id());
exporter.write(name, o->type(), o->transformation().matrix().data(), mesh.verts(),
mesh.normals(), mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials());
} }
void ColladaSerializer::finalize() { void ColladaSerializer::finalize() {
+50 -34
View File
@@ -27,17 +27,10 @@
#pragma warning(disable : 4201 4512) #pragma warning(disable : 4201 4512)
#endif #endif
#include <COLLADASWStreamWriter.h> #include <COLLADASWStreamWriter.h>
#include <COLLADASWPrimitves.h>
#include <COLLADASWLibraryGeometries.h> #include <COLLADASWLibraryGeometries.h>
#include <COLLADASWSource.h>
#include <COLLADASWScene.h>
#include <COLLADASWNode.h>
#include <COLLADASWInstanceGeometry.h>
#include <COLLADASWLibraryVisualScenes.h> #include <COLLADASWLibraryVisualScenes.h>
#include <COLLADASWLibraryEffects.h> #include <COLLADASWLibraryEffects.h>
#include <COLLADASWLibraryMaterials.h> #include <COLLADASWLibraryMaterials.h>
#include <COLLADASWBaseInputElement.h>
#include <COLLADASWAsset.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
@@ -58,12 +51,18 @@ private:
ColladaGeometries(const ColladaGeometries&); //N/A ColladaGeometries(const ColladaGeometries&); //N/A
ColladaGeometries& operator =(const ColladaGeometries&); //N/A ColladaGeometries& operator =(const ColladaGeometries&); //N/A
public: public:
explicit ColladaGeometries(COLLADASW::StreamWriter& stream) explicit ColladaGeometries(COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer)
: COLLADASW::LibraryGeometries(&stream) : COLLADASW::LibraryGeometries(&stream)
, serializer(_serializer)
{} {}
void addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector<double>& floats, const char* coords = "XYZ"); void addFloatSource(const std::string& mesh_id, const std::string& suffix,
void write(const std::string mesh_id, const std::string& default_material_name, const std::vector<double>& positions, const std::vector<double>& normals, const std::vector<int>& faces, const std::vector<int>& edges, const std::vector<int> material_ids, const std::vector<IfcGeom::Material>& materials); const std::vector<real_t>& floats, const char* coords = "XYZ");
void write(const std::string &mesh_id, const std::string& default_material_name,
const std::vector<real_t>& positions, const std::vector<real_t>& normals,
const std::vector<int>& faces, const std::vector<int>& edges,
const std::vector<int> material_ids, const std::vector<IfcGeom::Material>& materials);
void close(); void close();
ColladaSerializer *serializer;
}; };
class ColladaScene : public COLLADASW::LibraryVisualScenes class ColladaScene : public COLLADASW::LibraryVisualScenes
{ {
@@ -74,13 +73,16 @@ private:
const std::string scene_id; const std::string scene_id;
bool scene_opened; bool scene_opened;
public: public:
ColladaScene(const std::string& scene_id, COLLADASW::StreamWriter& stream) ColladaScene(const std::string& scene_id, COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer)
: COLLADASW::LibraryVisualScenes(&stream) : COLLADASW::LibraryVisualScenes(&stream)
, scene_id(scene_id) , scene_id(scene_id)
, scene_opened(false) , scene_opened(false)
, serializer(_serializer)
{} {}
void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector<std::string>& material_ids, const std::vector<double>& matrix); void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name,
const std::vector<std::string>& material_ids, const std::vector<real_t>& matrix);
void write(); void write();
ColladaSerializer *serializer;
}; };
class ColladaMaterials : public COLLADASW::LibraryMaterials class ColladaMaterials : public COLLADASW::LibraryMaterials
{ {
@@ -97,32 +99,36 @@ private:
{} {}
void write(const IfcGeom::Material& material); void write(const IfcGeom::Material& material);
void close(); void close();
ColladaSerializer *serializer;
}; };
std::vector<IfcGeom::Material> materials; std::vector<IfcGeom::Material> materials;
ColladaEffects effects;
public: public:
explicit ColladaMaterials(COLLADASW::StreamWriter& stream) explicit ColladaMaterials(COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer)
: COLLADASW::LibraryMaterials(&stream) : COLLADASW::LibraryMaterials(&stream)
, effects(stream) , effects(stream)
, serializer(_serializer)
{} {}
void add(const IfcGeom::Material& material); void add(const IfcGeom::Material& material);
bool contains(const IfcGeom::Material& material); bool contains(const IfcGeom::Material& material);
void write(); void write();
ColladaSerializer *serializer;
ColladaEffects effects;
}; };
class DeferredObject { class DeferredObject {
public: public:
std::string unique_id, type; std::string unique_id, type;
std::vector<double> matrix; std::vector<real_t> matrix;
std::vector<double> vertices; std::vector<real_t> vertices;
std::vector<double> normals; std::vector<real_t> normals;
std::vector<int> faces; std::vector<int> faces;
std::vector<int> edges; std::vector<int> edges;
std::vector<int> material_ids; std::vector<int> material_ids;
std::vector<IfcGeom::Material> materials; std::vector<IfcGeom::Material> materials;
std::vector<std::string> material_references; std::vector<std::string> material_references;
DeferredObject(const std::string& unique_id, const std::string& type, const std::vector<double>& matrix, const std::vector<double>& vertices, DeferredObject(const std::string& unique_id, const std::string& type, const std::vector<real_t>& matrix,
const std::vector<double>& normals, const std::vector<int>& faces, const std::vector<int>& edges, const std::vector<int>& material_ids, const std::vector<real_t>& vertices, const std::vector<real_t>& normals, const std::vector<int>& faces,
const std::vector<IfcGeom::Material>& materials, const std::vector<std::string>& material_references) const std::vector<int>& edges, const std::vector<int>& material_ids, const std::vector<IfcGeom::Material>& materials,
const std::vector<std::string>& material_references)
: unique_id(unique_id) : unique_id(unique_id)
, type(type) , type(type)
, matrix(matrix) , matrix(matrix)
@@ -137,35 +143,45 @@ private:
}; };
COLLADABU::NativeString filename; COLLADABU::NativeString filename;
COLLADASW::StreamWriter stream; COLLADASW::StreamWriter stream;
ColladaGeometries geometries;
ColladaScene scene; ColladaScene scene;
ColladaMaterials materials;
public: public:
ColladaExporter(const std::string& scene_name, const std::string& fn) ColladaExporter(const std::string& scene_name, const std::string& fn, ColladaSerializer *_serializer)
: filename(fn.c_str()) : filename(fn.c_str())
, stream(filename) , stream(filename)
, geometries(stream) , geometries(stream, _serializer)
, scene(scene_name, stream) , scene(scene_name, stream, _serializer)
, materials(stream) , materials(stream, _serializer)
{} , serializer(_serializer)
{
}
ColladaMaterials materials;
ColladaSerializer *serializer;
ColladaGeometries geometries;
std::vector<DeferredObject> deferreds; std::vector<DeferredObject> deferreds;
virtual ~ColladaExporter() {} virtual ~ColladaExporter() {}
void startDocument(const std::string& unit_name, float unit_magnitude); void startDocument(const std::string& unit_name, float unit_magnitude);
void write(const std::string& unique_id, const std::string& type, const std::vector<double>& matrix, const std::vector<double>& vertices, const std::vector<double>& normals, const std::vector<int>& faces, const std::vector<int>& edges, const std::vector<int>& material_ids, const std::vector<IfcGeom::Material>& materials); void write(const std::string& unique_id, const std::string& type, const std::vector<real_t>& matrix,
const std::vector<real_t>& vertices, const std::vector<real_t>& normals, const std::vector<int>& faces,
const std::vector<int>& edges, const std::vector<int>& material_ids, const std::vector<IfcGeom::Material>& materials);
void endDocument(); void endDocument();
}; };
ColladaExporter exporter; ColladaExporter exporter;
std::string unit_name; std::string unit_name;
float unit_magnitude; float unit_magnitude;
public: public:
ColladaSerializer(const std::string& dae_filename) ColladaSerializer(const std::string& dae_filename, const IfcGeom::IteratorSettings &settings)
: GeometrySerializer() : GeometrySerializer(settings)
, exporter("IfcOpenShell", dae_filename) , exporter("IfcOpenShell", dae_filename, this)
{} {
exporter.serializer = this;
exporter.materials.serializer = this;
exporter.materials.effects.serializer = this;
exporter.geometries.serializer = this;
}
bool ready(); bool ready();
void writeHeader(); void writeHeader();
void write(const IfcGeom::TriangulationElement<double>* o); void write(const IfcGeom::TriangulationElement<real_t>* o);
void write(const IfcGeom::BRepElement<double>* /*o*/) {} void write(const IfcGeom::BRepElement<real_t>* /*o*/) {}
void finalize(); void finalize();
bool isTesselated() const { return true; } bool isTesselated() const { return true; }
void setUnitNameAndMagnitude(const std::string& name, float magnitude) { void setUnitNameAndMagnitude(const std::string& name, float magnitude) {
+11 -2
View File
@@ -20,17 +20,26 @@
#ifndef GEOMETRYSERIALIZER_H #ifndef GEOMETRYSERIALIZER_H
#define GEOMETRYSERIALIZER_H #define GEOMETRYSERIALIZER_H
typedef double real_t; /**< @todo Will be configurable */
#include "../ifcconvert/Serializer.h" #include "../ifcconvert/Serializer.h"
#include "../ifcgeom/IfcGeomIterator.h" #include "../ifcgeom/IfcGeomIterator.h"
class GeometrySerializer : public Serializer { class GeometrySerializer : public Serializer {
public: public:
GeometrySerializer(const IfcGeom::IteratorSettings &settings) : settings_(settings) {}
virtual ~GeometrySerializer() {} virtual ~GeometrySerializer() {}
virtual bool isTesselated() const = 0; virtual bool isTesselated() const = 0;
virtual void write(const IfcGeom::TriangulationElement<double>* o) = 0; virtual void write(const IfcGeom::TriangulationElement<real_t>* o) = 0;
virtual void write(const IfcGeom::BRepElement<double>* o) = 0; virtual void write(const IfcGeom::BRepElement<real_t>* o) = 0;
virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0; virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0;
const IfcGeom::IteratorSettings& settings() const { return settings_; }
IfcGeom::IteratorSettings& settings() { return settings_; }
protected:
IfcGeom::IteratorSettings settings_;
}; };
#endif #endif
+16 -17
View File
@@ -47,7 +47,6 @@
#include <set> #include <set>
#include <time.h> #include <time.h>
typedef double real_t; /**< @todo Will be configurable */
#define INF std::numeric_limits<real_t>::infinity() #define INF std::numeric_limits<real_t>::infinity()
real_t bounds_min[3] = { INF, INF, INF }; real_t bounds_min[3] = { INF, INF, INF };
real_t bounds_max[3] = { -INF, -INF, -INF }; real_t bounds_max[3] = { -INF, -INF, -INF };
@@ -191,14 +190,14 @@ int main(int argc, char** argv) {
("bounds", boost::program_options::value<std::string>(&bounds), ("bounds", boost::program_options::value<std::string>(&bounds),
"Specifies the bounding rectangle, for example 512x512, to which the " "Specifies the bounding rectangle, for example 512x512, to which the "
"output will be scaled. Only used when converting to SVG.") "output will be scaled. Only used when converting to SVG.")
/*("use-names", ("use-names",
"Use entity names instead of unique IDs for naming objects and materials " "Use entity names instead of unique IDs for naming objects and materials "
"upon serialization. Applicable for .obj and .dae output.") "upon serialization. Applicable for .obj and .dae output.")
("use-guids", ("use-guids",
"Use entity GUIDs instead of unique IDs for naming objects upon serialization. " "Use entity GUIDs instead of unique IDs for naming objects upon serialization. "
"Overrides possible usage of --use-names for objects but not for materials." "Overrides possible usage of --use-names for objects but not for materials."
"Applicable for .obj and .dae output.") "Applicable for .obj and .dae output.")
("center-model", /*("center-model",
"Centers the models upon serialization by applying the center point of " "Centers the models upon serialization by applying the center point of "
"the scene bounds as an offset. Applicable only for .dae output currently.") "the scene bounds as an offset. Applicable only for .dae output currently.")
("generate-uvs", ("generate-uvs",
@@ -257,8 +256,8 @@ int main(int argc, char** argv) {
bool include_entities = vmap.count("include") != 0; bool include_entities = vmap.count("include") != 0;
const bool include_plan = vmap.count("plan") != 0; const bool include_plan = vmap.count("plan") != 0;
const bool include_model = vmap.count("model") != 0 || (!include_plan); const bool include_model = vmap.count("model") != 0 || (!include_plan);
//const bool use_names = vmap.count("use-names") != 0; const bool use_names = vmap.count("use-names") != 0;
//const bool use_guids = vmap.count("use-guids") != 0 ; const bool use_guids = vmap.count("use-guids") != 0 ;
//const bool no_normals = vmap.count("no-normals") != 0 ; //const bool no_normals = vmap.count("no-normals") != 0 ;
//const bool center_model = vmap.count("center-model") != 0 ; //const bool center_model = vmap.count("center-model") != 0 ;
//const bool generate_uvs = vmap.count("generate-uvs") != 0 ; //const bool generate_uvs = vmap.count("generate-uvs") != 0 ;
@@ -296,7 +295,7 @@ int main(int argc, char** argv) {
boost::to_lower(output_extension); boost::to_lower(output_extension);
// If no entities are specified these are the defaults to skip from output // If no entities are specified these are the defaults to skip from output
if (entity_vector.empty()) { if (entities.empty()) {
entities.insert("IfcSpace"); entities.insert("IfcSpace");
/// @todo Document in --help that SVG uses "--include --entities IfcSpace" by default. /// @todo Document in --help that SVG uses "--include --entities IfcSpace" by default.
if (output_extension == ".svg") { if (output_extension == ".svg") {
@@ -339,11 +338,11 @@ int main(int argc, char** argv) {
settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions); settings.set(IfcGeom::IteratorSettings::DISABLE_OPENING_SUBTRACTIONS, disable_opening_subtractions);
settings.set(IfcGeom::IteratorSettings::INCLUDE_CURVES, include_plan); settings.set(IfcGeom::IteratorSettings::INCLUDE_CURVES, include_plan);
settings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, !include_model); settings.set(IfcGeom::IteratorSettings::EXCLUDE_SOLIDS_AND_SURFACES, !include_model);
//settings.set(IfcConvertSettings::USE_NAMES, use_names); settings.set(IfcGeom::IteratorSettings::USE_NAMES, use_names);
//settings.set(IfcConvertSettings::USE_GUIDS, use_guids); settings.set(IfcGeom::IteratorSettings::USE_GUIDS, use_guids);
//settings.set(IfcGeom::IteratorSettings::NO_NORMALS, no_normals); //settings.set(IfcGeom::IteratorSettings::NO_NORMALS, no_normals);
//settings.set(IfcConvertSettings::CENTER_MODEL, center_model); //settings.set(IfcGeom::IteratorSettings::CENTER_MODEL, center_model);
//settings.set(IfcConvertSettings::GENERATE_UVS, generate_uvs); //settings.set(IfcGeom::IteratorSettings::GENERATE_UVS, generate_uvs);
//if (deflection_tolerance_specified) //if (deflection_tolerance_specified)
// settings.set_deflection_tolerance(deflection_tolerance); // settings.set_deflection_tolerance(deflection_tolerance);
@@ -354,21 +353,21 @@ int main(int argc, char** argv) {
Logger::Message(Logger::LOG_NOTICE, "Using world coords when writing WaveFront OBJ files"); Logger::Message(Logger::LOG_NOTICE, "Using world coords when writing WaveFront OBJ files");
settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true); settings.set(IfcGeom::IteratorSettings::USE_WORLD_COORDS, true);
} }
serializer = new WaveFrontOBJSerializer(output_filename, mtl_filename); serializer = new WaveFrontOBJSerializer(output_filename, mtl_filename, settings);
#ifdef WITH_OPENCOLLADA #ifdef WITH_OPENCOLLADA
} else if (output_extension == ".dae") { } else if (output_extension == ".dae") {
serializer = new ColladaSerializer(output_filename); serializer = new ColladaSerializer(output_filename, settings);
#endif #endif
} else if (output_extension == ".stp") { } else if (output_extension == ".stp") {
serializer = new StepSerializer(output_filename); serializer = new StepSerializer(output_filename, settings);
} else if (output_extension == ".igs") { } else if (output_extension == ".igs") {
// Not sure why this is needed, but it is. // Not sure why this is needed, but it is.
// See: http://tracker.dev.opencascade.org/view.php?id=23679 // See: http://tracker.dev.opencascade.org/view.php?id=23679
IGESControl_Controller::Init(); IGESControl_Controller::Init();
serializer = new IgesSerializer(output_filename); serializer = new IgesSerializer(output_filename, settings);
} else if (output_extension == ".svg") { } else if (output_extension == ".svg") {
settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true); settings.set(IfcGeom::IteratorSettings::DISABLE_TRIANGULATION, true);
serializer = new SvgSerializer(output_filename); serializer = new SvgSerializer(output_filename, settings);
if (bounding_width && bounding_height) { if (bounding_width && bounding_height) {
static_cast<SvgSerializer*>(serializer)->setBoundingRectangle(*bounding_width, *bounding_height); static_cast<SvgSerializer*>(serializer)->setBoundingRectangle(*bounding_width, *bounding_height);
} }
@@ -416,6 +415,8 @@ int main(int argc, char** argv) {
return 1; return 1;
} }
serializer->setFile(context_iterator.getFile());
if (convert_back_units) { if (convert_back_units) {
serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<float>(context_iterator.getUnitMagnitude())); serializer->setUnitNameAndMagnitude(context_iterator.getUnitName(), static_cast<float>(context_iterator.getUnitMagnitude()));
} else { } else {
@@ -470,8 +471,6 @@ int main(int argc, char** argv) {
Logger::Status("Serializing geometry..."); Logger::Status("Serializing geometry...");
//serializer->setSettings(settings);
if (serializer->isTesselated()) { // isTesselated() doesn't change at run-time if (serializer->isTesselated()) { // isTesselated() doesn't change at run-time
foreach(const IfcGeom::Element<real_t>* geom, geometries) { foreach(const IfcGeom::Element<real_t>* geom, geometries) {
serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t>*>(geom)); serializer->write(static_cast<const IfcGeom::TriangulationElement<real_t>*>(geom));
+2 -2
View File
@@ -32,8 +32,8 @@ class IgesSerializer : public OpenCascadeBasedSerializer
private: private:
IGESControl_Writer writer; IGESControl_Writer writer;
public: public:
explicit IgesSerializer(const std::string& out_filename) IgesSerializer(const std::string& out_filename, const IfcGeom::IteratorSettings &settings)
: OpenCascadeBasedSerializer(out_filename) : OpenCascadeBasedSerializer(out_filename, settings)
{} {}
virtual ~IgesSerializer() {} virtual ~IgesSerializer() {}
void writeShape(const TopoDS_Shape& shape) { void writeShape(const TopoDS_Shape& shape) {
+4 -4
View File
@@ -31,16 +31,16 @@ protected:
const std::string out_filename; const std::string out_filename;
const char* getSymbolForUnitMagnitude(float mag); const char* getSymbolForUnitMagnitude(float mag);
public: public:
explicit OpenCascadeBasedSerializer(const std::string& out_filename) explicit OpenCascadeBasedSerializer(const std::string& out_filename, const IfcGeom::IteratorSettings &settings)
: GeometrySerializer() : GeometrySerializer(settings)
, out_filename(out_filename) , out_filename(out_filename)
{} {}
virtual ~OpenCascadeBasedSerializer() {} virtual ~OpenCascadeBasedSerializer() {}
void writeHeader() {} void writeHeader() {}
bool ready(); bool ready();
virtual void writeShape(const TopoDS_Shape& shape) = 0; virtual void writeShape(const TopoDS_Shape& shape) = 0;
void write(const IfcGeom::TriangulationElement<double>* /*o*/) {} void write(const IfcGeom::TriangulationElement<real_t>* /*o*/) {}
void write(const IfcGeom::BRepElement<double>* o); void write(const IfcGeom::BRepElement<real_t>* o);
bool isTesselated() const { return false; } bool isTesselated() const { return false; }
void setFile(IfcParse::IfcFile*) {} void setFile(IfcParse::IfcFile*) {}
}; };
+2 -2
View File
@@ -32,8 +32,8 @@ class StepSerializer : public OpenCascadeBasedSerializer
private: private:
STEPControl_Writer writer; STEPControl_Writer writer;
public: public:
explicit StepSerializer(const std::string& out_filename) explicit StepSerializer(const std::string& out_filename, const IfcGeom::IteratorSettings &settings)
: OpenCascadeBasedSerializer(out_filename) : OpenCascadeBasedSerializer(out_filename, settings)
{} {}
virtual ~StepSerializer() {} virtual ~StepSerializer() {}
void writeShape(const TopoDS_Shape& shape) { void writeShape(const TopoDS_Shape& shape) {
+8 -3
View File
@@ -168,7 +168,8 @@ SvgSerializer::path_object& SvgSerializer::start_path(IfcSchema::IfcBuildingStor
return p; return p;
} }
void SvgSerializer::write(const IfcGeom::BRepElement<double>* o) { void SvgSerializer::write(const IfcGeom::BRepElement<real_t>* o)
{
IfcSchema::IfcBuildingStorey* storey = 0; IfcSchema::IfcBuildingStorey* storey = 0;
IfcSchema::IfcObjectDefinition* obdef = static_cast<IfcSchema::IfcObjectDefinition*>(file->entityById(o->id())); IfcSchema::IfcObjectDefinition* obdef = static_cast<IfcSchema::IfcObjectDefinition*>(file->entityById(o->id()));
@@ -340,10 +341,14 @@ void SvgSerializer::writeHeader() {
svg_file << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"; svg_file << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
} }
std::string SvgSerializer::nameElement(const IfcGeom::Element<double>* elem) { std::string SvgSerializer::nameElement(const IfcGeom::Element<real_t>* elem)
{
std::ostringstream oss; std::ostringstream oss;
const std::string type = "product"; const std::string type = "product";
oss << "id=\"" << type << "-" << elem->unique_id() << "\""; const std::string name = (settings().get(IfcGeom::IteratorSettings::USE_GUIDS)
? elem->guid() : (settings().get(IfcGeom::IteratorSettings::USE_NAMES)
? elem->name() : elem->unique_id()));
oss << "id=\"" << type << "-" << name<< "\"";
return oss.str(); return oss.str();
} }
+4 -4
View File
@@ -45,8 +45,8 @@ protected:
std::vector< boost::shared_ptr<util::string_buffer::float_item> > radii; std::vector< boost::shared_ptr<util::string_buffer::float_item> > radii;
IfcParse::IfcFile* file; IfcParse::IfcFile* file;
public: public:
explicit SvgSerializer(const std::string& out_filename) explicit SvgSerializer(const std::string& out_filename, const IfcGeom::IteratorSettings &settings)
: GeometrySerializer() : GeometrySerializer(settings)
, svg_file(out_filename.c_str()) , svg_file(out_filename.c_str())
, xmin(+std::numeric_limits<double>::infinity()) , xmin(+std::numeric_limits<double>::infinity())
, xmax(-std::numeric_limits<double>::infinity()) , xmax(-std::numeric_limits<double>::infinity())
@@ -62,8 +62,8 @@ public:
virtual ~SvgSerializer() {} virtual ~SvgSerializer() {}
virtual void writeHeader(); virtual void writeHeader();
virtual bool ready(); virtual bool ready();
virtual void write(const IfcGeom::TriangulationElement<double>* /*o*/) {} virtual void write(const IfcGeom::TriangulationElement<real_t>* /*o*/) {}
virtual void write(const IfcGeom::BRepElement<double>* o); virtual void write(const IfcGeom::BRepElement<real_t>* o);
virtual void write(path_object& p, const TopoDS_Wire& wire); virtual void write(path_object& p, const TopoDS_Wire& wire);
virtual path_object& start_path(IfcSchema::IfcBuildingStorey* storey, const std::string& id); virtual path_object& start_path(IfcSchema::IfcBuildingStorey* storey, const std::string& id);
virtual bool isTesselated() const { return false; } virtual bool isTesselated() const { return false; }
+24 -20
View File
@@ -17,12 +17,12 @@
* * * *
********************************************************************************/ ********************************************************************************/
#include <limits>
#include <iomanip> #include "WavefrontObjSerializer.h"
#include "../ifcgeom/IfcGeomRenderStyles.h" #include "../ifcgeom/IfcGeomRenderStyles.h"
#include "WavefrontObjSerializer.h" #include <iomanip>
bool WaveFrontOBJSerializer::ready() { bool WaveFrontOBJSerializer::ready() {
return obj_stream.is_open() && mtl_stream.is_open(); return obj_stream.is_open() && mtl_stream.is_open();
@@ -44,8 +44,11 @@ void WaveFrontOBJSerializer::writeHeader() {
mtl_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n"; mtl_stream << "# File generated by IfcOpenShell " << IFCOPENSHELL_VERSION << "\n";
} }
void WaveFrontOBJSerializer::writeMaterial(const IfcGeom::Material& style) { void WaveFrontOBJSerializer::writeMaterial(const IfcGeom::Material& style)
mtl_stream << "newmtl " << style.name() << "\n"; {
std::string material_name = (settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? style.original_name() : style.name());
IfcUtil::sanitate_material_name(material_name);
mtl_stream << "newmtl " << material_name << "\n";
if (style.hasDiffuse()) { if (style.hasDiffuse()) {
const double* diffuse = style.diffuse(); const double* diffuse = style.diffuse();
mtl_stream << "Kd " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << "\n"; mtl_stream << "Kd " << diffuse[0] << " " << diffuse[1] << " " << diffuse[2] << "\n";
@@ -66,27 +69,26 @@ void WaveFrontOBJSerializer::writeMaterial(const IfcGeom::Material& style) {
} }
} }
} }
void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement<double>* o) {
obj_stream << "g " << o->unique_id() << "\n"; void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement<real_t>* o)
{
obj_stream << "g " << (settings().get(IfcGeom::IteratorSettings::USE_GUIDS) ? o->guid() : (settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? o->name() : o->unique_id())) << "\n";
obj_stream << "s 1" << "\n"; obj_stream << "s 1" << "\n";
obj_stream << std::setprecision(std::numeric_limits<double>::digits10); const IfcGeom::Representation::Triangulation<real_t>& mesh = o->geometry();
const IfcGeom::Representation::Triangulation<double>& mesh = o->geometry();
const int vcount = (int)mesh.verts().size() / 3; const int vcount = (int)mesh.verts().size() / 3;
for ( std::vector<double>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) { for ( std::vector<real_t>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) {
const double x = *(it++); const real_t x = *(it++);
const double y = *(it++); const real_t y = *(it++);
const double z = *(it++); const real_t z = *(it++);
obj_stream << "v " << x << " " << y << " " << z << "\n"; obj_stream << "v " << x << " " << y << " " << z << "\n";
} }
for ( std::vector<double>::const_iterator it = mesh.normals().begin(); it != mesh.normals().end(); ) { for ( std::vector<real_t>::const_iterator it = mesh.normals().begin(); it != mesh.normals().end(); ) {
const double x = *(it++); const real_t x = *(it++);
const double y = *(it++); const real_t y = *(it++);
const double z = *(it++); const real_t z = *(it++);
obj_stream << "vn " << x << " " << y << " " << z << "\n"; obj_stream << "vn " << x << " " << y << " " << z << "\n";
} }
@@ -98,7 +100,8 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement<double>*
const int material_id = *(material_it++); const int material_id = *(material_it++);
if (material_id != previous_material_id) { if (material_id != previous_material_id) {
const IfcGeom::Material& material = mesh.materials()[material_id]; const IfcGeom::Material& material = mesh.materials()[material_id];
const std::string material_name = material.name(); std::string material_name = (settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? material.original_name() : material.name());
IfcUtil::sanitate_material_name(material_name);
obj_stream << "usemtl " << material_name << "\n"; obj_stream << "usemtl " << material_name << "\n";
if (materials.find(material_name) == materials.end()) { if (materials.find(material_name) == materials.end()) {
writeMaterial(material); writeMaterial(material);
@@ -129,7 +132,8 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement<double>*
if (material_id != previous_material_id) { if (material_id != previous_material_id) {
const IfcGeom::Material& material = mesh.materials()[material_id]; const IfcGeom::Material& material = mesh.materials()[material_id];
const std::string material_name = material.name(); std::string material_name = (settings().get(IfcGeom::IteratorSettings::USE_NAMES) ? material.original_name() : material.name());
IfcUtil::sanitate_material_name(material_name);
obj_stream << "usemtl " << material_name << "\n"; obj_stream << "usemtl " << material_name << "\n";
if (materials.find(material_name) == materials.end()) { if (materials.find(material_name) == materials.end()) {
writeMaterial(material); writeMaterial(material);
+2 -2
View File
@@ -34,8 +34,8 @@ private:
unsigned int vcount_total; unsigned int vcount_total;
std::set<std::string> materials; std::set<std::string> materials;
public: public:
WaveFrontOBJSerializer(const std::string& obj_filename, const std::string& mtl_filename) WaveFrontOBJSerializer(const std::string& obj_filename, const std::string& mtl_filename, const IfcGeom::IteratorSettings &settings)
: GeometrySerializer() : GeometrySerializer(settings)
, obj_stream(obj_filename.c_str()) , obj_stream(obj_filename.c_str())
, mtl_filename(mtl_filename) , mtl_filename(mtl_filename)
, mtl_stream(mtl_filename.c_str()) , mtl_stream(mtl_filename.c_str())
+5 -5
View File
@@ -72,17 +72,17 @@ namespace IfcGeom
/// model in other modelling application in any case. /// model in other modelling application in any case.
//NO_NORMALS = 1 << 11, //NO_NORMALS = 1 << 11,
/// Use entity names instead of unique IDs for naming objects and materials. /// Use entity names instead of unique IDs for naming objects and materials.
/// Applicable for .obj and .dae output. /// Applicable for OBJ, DAE, and SVG output.
//USE_NAMES = 1 << 12, USE_NAMES = 1 << 12,
/// Use entity GUIDs instead of unique IDs for naming objects. /// Use entity GUIDs instead of unique IDs for naming objects.
/// Overrides possible usage of --use-names for objects but not for materials. /// Overrides possible usage of --use-names for objects but not for materials.
/// Applicable for .obj and .dae output. /// Applicable for OBJ, DAE, and SVG output.
//USE_GUIDS = 1 << 13, USE_GUIDS = 1 << 13,
/// Centers the models upon serialization by the applying the center point of /// Centers the models upon serialization by the applying the center point of
/// the scene bounds as an offset. Applicable only for .dae output currently. /// the scene bounds as an offset. Applicable only for .dae output currently.
//CENTER_MODEL = 1 << 14, //CENTER_MODEL = 1 << 14,
/// Generates UVs by using simple box projection. Requires normals. /// Generates UVs by using simple box projection. Requires normals.
/// Applicable only for .dae output currently. /// Applicable only for DAE output currently.
//GENERATE_UVS = 1 << 15, //GENERATE_UVS = 1 << 15,
//NUM_SETTINGS = 15 //NUM_SETTINGS = 15
}; };
+2 -1
View File
@@ -30,5 +30,6 @@ const double* IfcGeom::Material::diffuse() const { if (hasDiffuse()) return &((*
const double* IfcGeom::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; } const double* IfcGeom::Material::specular() const { if (hasSpecular()) return &((*style->Specular()).R()); else return black; }
double IfcGeom::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; } double IfcGeom::Material::transparency() const { if (hasTransparency()) return *style->Transparency(); else return 0; }
double IfcGeom::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; } double IfcGeom::Material::specularity() const { if (hasSpecularity()) return *style->Specularity(); else return 0; }
const std::string IfcGeom::Material::name() const { return style->Name(); } const std::string &IfcGeom::Material::name() const { return style->Name(); }
const std::string &IfcGeom::Material::original_name() const { return style->original_name(); }
bool IfcGeom::Material::operator==(const IfcGeom::Material& other) const { return style == other.style; } bool IfcGeom::Material::operator==(const IfcGeom::Material& other) const { return style == other.style; }
+2 -1
View File
@@ -41,7 +41,8 @@ namespace IfcGeom {
const double* specular() const; const double* specular() const;
double transparency() const; double transparency() const;
double specularity() const; double specularity() const;
const std::string name() const; const std::string &name() const;
const std::string &original_name() const;
bool operator==(const Material& other) const; bool operator==(const Material& other) const;
}; };
+10 -7
View File
@@ -44,22 +44,22 @@ namespace IfcGeom {
double& B() { return data[2]; } double& B() { return data[2]; }
}; };
private: private:
std::string original_name_;
boost::optional<std::string> name; boost::optional<std::string> name;
boost::optional<int> id; boost::optional<int> id;
boost::optional<ColorComponent> diffuse, specular; boost::optional<ColorComponent> diffuse, specular;
boost::optional<double> transparency; boost::optional<double> transparency;
boost::optional<double> specularity; boost::optional<double> specularity;
public: public:
SurfaceStyle() { SurfaceStyle() : name("surface-style") {}
this->name = "surface-style";
}
SurfaceStyle(int id) : id(id) { SurfaceStyle(int id) : id(id) {
std::stringstream sstr; std::stringstream sstr;
sstr << "surface-style-" << id; sstr << "surface-style-" << id;
this->name = sstr.str(); this->name = sstr.str();
} }
SurfaceStyle(const std::string& name) : name(name) {} SurfaceStyle(const std::string& name) : name(name), original_name_(name) {}
SurfaceStyle(int id, const std::string& name) : id(id) { SurfaceStyle(int id, const std::string& name) : id(id), original_name_(name)
{
std::stringstream sstr; std::stringstream sstr;
std::string sanitized = name; std::string sanitized = name;
std::transform(sanitized.begin(), sanitized.end(), sanitized.begin(), ::tolower); std::transform(sanitized.begin(), sanitized.end(), sanitized.begin(), ::tolower);
@@ -72,7 +72,7 @@ namespace IfcGeom {
// architecture can just as easily be accomplished by comparing the // architecture can just as easily be accomplished by comparing the
// pointer addresses of the styles, as they are always referenced // pointer addresses of the styles, as they are always referenced
// from out of a global map of some sort. // from out of a global map of some sort.
bool operator==(const SurfaceStyle& other) { bool operator==(const SurfaceStyle& other) const {
if (name && other.name) { if (name && other.name) {
return *name == *other.name; return *name == *other.name;
} else if (id && other.id) { } else if (id && other.id) {
@@ -82,7 +82,10 @@ namespace IfcGeom {
} }
} }
const std::string& Name() const { return *name; } /// ID name, e.g. "surface-style-66675-metal---aluminium"
const std::string& Name() const { return *name; }
/// Original name, if available, e.g. "Metal - Aluminium"
const std::string& original_name() const { return original_name_; }
const boost::optional<ColorComponent>& Diffuse() const { return diffuse; } const boost::optional<ColorComponent>& Diffuse() const { return diffuse; }
const boost::optional<ColorComponent>& Specular() const { return specular; } const boost::optional<ColorComponent>& Specular() const { return specular; }
+25
View File
@@ -160,3 +160,28 @@ boost::regex IfcUtil::wildcard_string_to_regex(std::string str)
boost::replace_all(str, "*", ".*"); boost::replace_all(str, "*", ".*");
return boost::regex(str); return boost::regex(str);
} }
void IfcUtil::sanitate_material_name(std::string &str)
{
// Spaces in material names have been observed to cause problems with obj and dae importers.
// Handle other potential problematic characters here too if observing problems.
boost::replace_all(str, " ", "_");
}
void IfcUtil::escape_xml(std::string &str)
{
boost::replace_all(str, "\"", "&quot;");
boost::replace_all(str, "'", "&apos;");
boost::replace_all(str, "<", "&lt;");
boost::replace_all(str, ">", "&gt;");
boost::replace_all(str, "&", "&amp;");
}
void IfcUtil::unescape_xml(std::string &str)
{
boost::replace_all(str, "&quot;", "\"");
boost::replace_all(str, "&apos;", "'");
boost::replace_all(str, "&lt;", "<");
boost::replace_all(str, "&gt;", ">");
boost::replace_all(str, "&amp;", "&");
}
+5
View File
@@ -117,6 +117,11 @@ namespace IfcUtil {
bool valid_binary_string(const std::string& s); bool valid_binary_string(const std::string& s);
boost::regex wildcard_string_to_regex(std::string str); boost::regex wildcard_string_to_regex(std::string str);
/// Replaces spaces and potentially other problem causing characters with underscores.
void sanitate_material_name(std::string &str);
void escape_xml(std::string &str);
void unescape_xml(std::string &str);
} }
template <class T> template <class T>