Skip to content

Commit c8b0b65

Browse files
committed
works fine
1 parent 38b4a22 commit c8b0b65

File tree

4 files changed

+73
-44
lines changed

4 files changed

+73
-44
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,4 @@ src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
9797
.DS_Store
9898

9999
# clangd cache
100-
.cache
100+
.cache

src/ifcconvert/IfcConvert.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,8 @@ int main(int argc, char** argv) {
637637
XML = IfcUtil::path::from_utf8(".xml"),
638638
CITY_JSON = IfcUtil::path::from_utf8(".cityjson"),
639639
IFC = IfcUtil::path::from_utf8(".ifc"),
640-
USD = IfcUtil::path::from_utf8(".usd");
640+
USD = IfcUtil::path::from_utf8(".usd"),
641+
USDA = IfcUtil::path::from_utf8(".usda");
641642

642643
// @todo clean up serializer selection
643644
// @todo detect program options that conflict with the chosen serializer
@@ -830,8 +831,8 @@ int main(int argc, char** argv) {
830831
serializer = boost::make_shared<GltfSerializer>(IfcUtil::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
831832
#endif
832833
#ifdef WITH_USD
833-
} else if (output_extension == USD) {
834-
serializer = boost::make_shared<USDSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
834+
} else if (output_extension == USD || output_extension == USDA) {
835+
serializer = boost::make_shared<USDSerializer>(IfcUtil::path::to_utf8(output_filename), settings);
835836
#endif
836837
#ifdef IFOPSH_WITH_OPENCASCADE
837838
} else if (output_extension == STP) {
@@ -1171,9 +1172,11 @@ int main(int argc, char** argv) {
11711172

11721173
Logger::Message(Logger::LOG_PERF, "done file geometry conversion");
11731174

1175+
11741176
// Renaming might fail (e.g. maybe the existing file was open in a viewer application)
11751177
// Do not remove the temp file as user can salvage the conversion result from it.
1176-
bool successful = IfcUtil::path::rename_file(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(output_filename));
1178+
bool successful = IfcUtil::path::rename_file(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(output_filename))
1179+
|| output_extension == USD || output_extension == USDA;
11771180
if (!successful) {
11781181
cerr_ << "Unable to write output file '" << output_filename << "', see '" <<
11791182
output_temp_filename << "' for the conversion result.";

src/serializers/USDSerializer.cpp

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,18 @@
1010
#include "pxr/usd/usdGeom/tokens.h"
1111
#include "pxr/usd/usdGeom/scope.h"
1212
#include "pxr/usd/usdLux/distantLight.h"
13-
#include "pxr/usd/usdShade/material.h"
1413
#include "pxr/usd/usdShade/shader.h"
1514
#include "pxr/usd/usdShade/tokens.h"
1615
#include "pxr/usd/usdShade/materialBindingAPI.h"
1716
#include "pxr/usd/usdShade/connectableAPI.h"
1817

19-
#include <string>
20-
#include <sstream>
21-
22-
USDSerializer::USDSerializer(const std::string& filename, const SerializerSettings& settings)
23-
: WriteOnlyGeometrySerializer(settings)
24-
, filename_(filename)
18+
USDSerializer::USDSerializer(const std::string& out_filename, const SerializerSettings& settings):
19+
WriteOnlyGeometrySerializer(settings),
20+
filename_(out_filename)
2521
{
2622
// create a new stage
27-
stage_ = pxr::UsdStage::CreateNew(filename + ".usda");
28-
29-
// create root xform prim 'World'
23+
stage_ = pxr::UsdStage::CreateNew(filename_ + ".usda");
24+
3025
pxr::UsdGeomXform::Define(stage_, pxr::SdfPath("/World"));
3126
pxr::UsdGeomScope::Define(stage_, pxr::SdfPath("/Looks"));
3227
createLighting();
@@ -52,69 +47,83 @@ void USDSerializer::createLighting() {
5247
}
5348

5449
void USDSerializer::writeMaterial(const pxr::UsdGeomMesh& mesh,const IfcGeom::Material& style) {
55-
std::stringstream ss;
56-
ss << "/Looks/" << style.original_name();
57-
pxr::UsdShadeMaterial::Define(stage_, pxr::SdfPath(ss.str()));
58-
pxr::UsdShadeMaterial material(stage_->GetPrimAtPath(pxr::SdfPath(ss.str())));
59-
pxr::UsdShadeShader shader = pxr::UsdShadeShader::Define(stage_, pxr::SdfPath(ss.str() + "/Shader"));
50+
std::string path("/Looks/" + sanitize(style.original_name()));
51+
auto material = pxr::UsdShadeMaterial::Define(stage_, pxr::SdfPath(path));
52+
auto shader = pxr::UsdShadeShader::Define(stage_, pxr::SdfPath(path + "/Shader"));
6053
shader.CreateIdAttr().Set(pxr::TfToken("UsdPreviewSurface"));
6154

6255
float rgba[4] { 0.18f, 0.18f, 0.18f, 1.0f };
6356
if (style.hasDiffuse())
64-
for (int i = 0; i < 3; ++i) rgba[i] = static_cast<float>(style.diffuse()[i]);
57+
for (int i = 0; i < 3; ++i)
58+
rgba[i] = static_cast<float>(style.diffuse()[i]);
6559
shader.CreateInput(pxr::TfToken("diffuseColor"), pxr::SdfValueTypeNames->Color3f).Set(pxr::GfVec3f(rgba[0], rgba[1], rgba[2]));
6660

6761
if(style.hasTransparency())
68-
rgba[3] = 1.0f - style.transparency();
62+
rgba[3] -= style.transparency();
6963
shader.CreateInput(pxr::TfToken("opacity"), pxr::SdfValueTypeNames->Float).Set(rgba[3]);
7064

7165
if(style.hasSpecular()) {
72-
for (int i = 0; i < 3; ++i) rgba[i] = static_cast<float>(style.specular()[i]);
66+
for (int i = 0; i < 3; ++i)
67+
rgba[i] = static_cast<float>(style.specular()[i]);
7368
shader.CreateInput(pxr::TfToken("useSpecularWorkflow"), pxr::SdfValueTypeNames->Int).Set(1);
7469
} else {
7570
shader.CreateInput(pxr::TfToken("useSpecularWorkflow"), pxr::SdfValueTypeNames->Int).Set(0);
7671
}
7772
shader.CreateInput(pxr::TfToken("specularColor"), pxr::SdfValueTypeNames->Color3f).Set(pxr::GfVec3f(rgba[0], rgba[1], rgba[2]));
7873

79-
//material.CreateSurfaceOutput().ConnectToSource(shader, pxr::TfToken("surface"));
80-
//pxr::UsdShadeMaterialBindingAPI(mesh).Bind(material);
74+
material.CreateSurfaceOutput().ConnectToSource(shader.ConnectableAPI(), pxr::TfToken("surface"));
75+
pxr::UsdShadeMaterialBindingAPI(mesh).Bind(material);
8176
}
8277

8378
bool USDSerializer::ready() {
8479
return ready_;
8580
}
8681

8782
void USDSerializer::writeHeader() {
88-
std::stringstream ss;
89-
ss << "File generated by IfcOpenShell " << IFCOPENSHELL_VERSION;
90-
stage_->GetRootLayer()->SetComment(ss.str());
83+
stage_->GetRootLayer()->SetComment("File generated by IfcOpenShell " + std::string(IFCOPENSHELL_VERSION));
9184
}
9285

9386
void USDSerializer::write(const IfcGeom::TriangulationElement* o) {
9487
const IfcGeom::Representation::Triangulation& mesh = o->geometry();
95-
if ( mesh.material_ids().empty() || mesh.verts().empty() || mesh.faces().empty() )
88+
auto verts = mesh.verts();
89+
auto faces = mesh.faces();
90+
const std::vector<double>& m = o->transformation().matrix().data();
91+
92+
if ( mesh.material_ids().empty() || verts.empty() || faces.empty() )
9693
return;
9794

98-
std::stringstream ss("/World/");
99-
ss << mesh.id();
100-
pxr::UsdGeomMesh usd_mesh = pxr::UsdGeomMesh::Define(stage_, pxr::SdfPath(ss.str()));
101-
const std::vector<double>& m = o->transformation().matrix().data();
95+
std::string name = o->name() + std::to_string(o->id());
96+
if(name.empty()) {
97+
name = "Unnamed_" + std::to_string(unnamed_count_);
98+
unnamed_count_++;
99+
} else {
100+
name = sanitize(name);
101+
}
102+
pxr::UsdGeomMesh usd_mesh = pxr::UsdGeomMesh::Define(stage_, pxr::SdfPath("/World/" + name));
103+
104+
usd_mesh.AddTranslateOp().Set(pxr::GfVec3d(m[9], m[10], m[11]));
102105

103-
const int vcount = (int) mesh.verts().size() / 3;
104-
pxr::VtVec3dArray points;
105-
for ( std::vector<double>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) {
106-
points.push_back(pxr::GfVec3d(*(it++), *(it++), *(it++)));
106+
pxr::VtVec3fArray points;
107+
for(std::size_t i = 0; i < verts.size(); i+=3) {
108+
points.push_back(pxr::GfVec3f(static_cast<float>(verts[i] * m[0] + verts[i+1] * m[3] + verts[i+2] * m[6]),
109+
static_cast<float>(verts[i] * m[1] + verts[i+1] * m[4] + verts[i+2] * m[7]),
110+
static_cast<float>(verts[i] * m[2] + verts[i+1] * m[5] + verts[i+2] * m[8])));
107111
}
108112
usd_mesh.CreatePointsAttr().Set(points);
109-
usd_mesh.CreateFaceVertexIndicesAttr().Set(usd_utils::toVtArray(mesh.faces()));
110-
const int fcount = (int) mesh.faces().size() / 3;
111-
usd_mesh.CreateFaceVertexCountsAttr().Set(pxr::VtArray<int>(fcount, 3));
112-
usd_mesh.CreateNormalsAttr().Set(usd_utils::toVtArray(mesh.normals()));
113113

114+
usd_mesh.CreateFaceVertexIndicesAttr().Set(usd_utils::toVtArray(faces));
115+
usd_mesh.CreateFaceVertexCountsAttr().Set(pxr::VtArray<int>((int) faces.size() / 3, 3));
116+
117+
pxr::VtVec3fArray normals;
118+
for (std::vector<double>::const_iterator it = mesh.normals().begin(); it != mesh.normals().end();)
119+
normals.push_back(pxr::GfVec3f(static_cast<float>(*(it++)), static_cast<float>(*(it++)), static_cast<float>(*(it++))));
120+
usd_mesh.CreateNormalsAttr().Set(normals);
121+
122+
writeMaterial(usd_mesh, mesh.materials()[0]);
114123
}
115124

116125
void USDSerializer::finalize() {
117-
stage_->GetRootLayer()->Save();
126+
stage_->Save();
118127
}
119128

120129
#endif // WITH_USD

src/serializers/USDSerializer.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,41 @@
3333
#include "pxr/usd/usd/stage.h"
3434
#include "pxr/base/vt/array.h"
3535
#include "pxr/usd/usdGeom/mesh.h"
36+
#include "pxr/usd/usdShade/material.h"
3637

3738
#include <vector>
39+
#include <string>
40+
#include <algorithm>
41+
#include <map>
3842

3943
namespace usd_utils {
4044
template<typename T>
4145
pxr::VtArray<T> toVtArray(const std::vector<T>& vec) {
4246
auto array = pxr::VtArray<T>(vec.size());
43-
for (size_t i = 0; i < vec.size(); ++i)
47+
for (std::size_t i = 0; i < vec.size(); ++i)
4448
array[i] = vec[i];
4549
return array;
46-
}
50+
}
4751
}
4852

4953
class SERIALIZERS_API USDSerializer : public WriteOnlyGeometrySerializer {
5054
private:
5155
std::string filename_;
5256
bool ready_ = false;
5357
pxr::UsdStageRefPtr stage_;
58+
std::size_t unnamed_count_ = 0;
59+
std::map<std::string, pxr::UsdGeomMesh> meshes_;
60+
std::map<std::string, pxr::UsdShadeMaterial> materials_;
61+
62+
std::string sanitize(std::string s) {
63+
std::replace_if(s.begin(), s.end(),
64+
[](char c) { return c == ' ' || c == '.' || c == ','
65+
|| c == ';' || c == ':' || c == '/'
66+
|| c == '-' || c == '+' || c == '"'
67+
|| c > 127; },
68+
'_');
69+
return s;
70+
}
5471

5572
void writeMaterial(const pxr::UsdGeomMesh&, const IfcGeom::Material&);
5673
void createLighting();

0 commit comments

Comments
 (0)