From a8f1ab192301d57cfaee63daa43053cd7795b0ae Mon Sep 17 00:00:00 2001 From: D4ve-R Date: Mon, 8 May 2023 00:30:33 +0200 Subject: [PATCH] material subsets --- src/serializers/USDSerializer.cpp | 73 ++++++++++++++++++++----------- src/serializers/USDSerializer.h | 9 ++-- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/serializers/USDSerializer.cpp b/src/serializers/USDSerializer.cpp index 88c5e232cf..6c81adc830 100644 --- a/src/serializers/USDSerializer.cpp +++ b/src/serializers/USDSerializer.cpp @@ -46,33 +46,40 @@ void USDSerializer::createLighting() { light.CreateColorAttr().Set(pxr::GfVec3f(1.0f, 1.0f, 1.0f)); } -void USDSerializer::writeMaterial(const pxr::UsdGeomMesh& mesh,const IfcGeom::Material& style) { - std::string path("/Looks/" + sanitize(style.original_name())); - auto material = pxr::UsdShadeMaterial::Define(stage_, pxr::SdfPath(path)); - auto shader = pxr::UsdShadeShader::Define(stage_, pxr::SdfPath(path + "/Shader")); - shader.CreateIdAttr().Set(pxr::TfToken("UsdPreviewSurface")); +std::vector USDSerializer::createMaterials(const pxr::UsdGeomMesh& mesh, + const std::vector& styles) +{ + std::vector materials {}; - float rgba[4] { 0.18f, 0.18f, 0.18f, 1.0f }; - if (style.hasDiffuse()) - for (int i = 0; i < 3; ++i) - rgba[i] = static_cast(style.diffuse()[i]); - shader.CreateInput(pxr::TfToken("diffuseColor"), pxr::SdfValueTypeNames->Color3f).Set(pxr::GfVec3f(rgba[0], rgba[1], rgba[2])); + for(auto style : styles) { + std::string path("/Looks/" + sanitize(style.original_name())); + auto material = pxr::UsdShadeMaterial::Define(stage_, pxr::SdfPath(path)); + auto shader = pxr::UsdShadeShader::Define(stage_, pxr::SdfPath(path + "/Shader")); + shader.CreateIdAttr().Set(pxr::TfToken("UsdPreviewSurface")); - if(style.hasTransparency()) - rgba[3] -= style.transparency(); - shader.CreateInput(pxr::TfToken("opacity"), pxr::SdfValueTypeNames->Float).Set(rgba[3]); + float rgba[4] { 0.18f, 0.18f, 0.18f, 1.0f }; + if (style.hasDiffuse()) + for (int i = 0; i < 3; ++i) + rgba[i] = static_cast(style.diffuse()[i]); + shader.CreateInput(pxr::TfToken("diffuseColor"), pxr::SdfValueTypeNames->Color3f).Set(pxr::GfVec3f(rgba[0], rgba[1], rgba[2])); - if(style.hasSpecular()) { - for (int i = 0; i < 3; ++i) - rgba[i] = static_cast(style.specular()[i]); - shader.CreateInput(pxr::TfToken("useSpecularWorkflow"), pxr::SdfValueTypeNames->Int).Set(1); - } else { - shader.CreateInput(pxr::TfToken("useSpecularWorkflow"), pxr::SdfValueTypeNames->Int).Set(0); + if(style.hasTransparency()) + rgba[3] -= style.transparency(); + shader.CreateInput(pxr::TfToken("opacity"), pxr::SdfValueTypeNames->Float).Set(rgba[3]); + + if(style.hasSpecular()) { + for (int i = 0; i < 3; ++i) + rgba[i] = static_cast(style.specular()[i]); + shader.CreateInput(pxr::TfToken("useSpecularWorkflow"), pxr::SdfValueTypeNames->Int).Set(1); + } else { + shader.CreateInput(pxr::TfToken("useSpecularWorkflow"), pxr::SdfValueTypeNames->Int).Set(0); + } + shader.CreateInput(pxr::TfToken("specularColor"), pxr::SdfValueTypeNames->Color3f).Set(pxr::GfVec3f(rgba[0], rgba[1], rgba[2])); + + material.CreateSurfaceOutput().ConnectToSource(shader.ConnectableAPI(), pxr::TfToken("surface")); + materials.push_back(material); } - shader.CreateInput(pxr::TfToken("specularColor"), pxr::SdfValueTypeNames->Color3f).Set(pxr::GfVec3f(rgba[0], rgba[1], rgba[2])); - - material.CreateSurfaceOutput().ConnectToSource(shader.ConnectableAPI(), pxr::TfToken("surface")); - pxr::UsdShadeMaterialBindingAPI(mesh).Bind(material); + return materials; } bool USDSerializer::ready() { @@ -92,12 +99,12 @@ void USDSerializer::write(const IfcGeom::TriangulationElement* o) { if ( mesh.material_ids().empty() || verts.empty() || faces.empty() ) return; - std::string name = o->name() + std::to_string(o->id()); + std::string name = o->name(); if(name.empty()) { name = "Unnamed_" + std::to_string(unnamed_count_); unnamed_count_++; } else { - name = sanitize(name); + name = sanitize(name) + std::to_string(o->id()); } pxr::UsdGeomMesh usd_mesh = pxr::UsdGeomMesh::Define(stage_, pxr::SdfPath("/World/" + name)); @@ -119,7 +126,21 @@ void USDSerializer::write(const IfcGeom::TriangulationElement* o) { normals.push_back(pxr::GfVec3f(static_cast(*(it++)), static_cast(*(it++)), static_cast(*(it++)))); usd_mesh.CreateNormalsAttr().Set(normals); - writeMaterial(usd_mesh, mesh.materials()[0]); + auto materials = createMaterials(usd_mesh, mesh.materials()); + pxr::UsdShadeMaterialBindingAPI material_api(usd_mesh); + if(materials.size() > 1) { + auto material_ids = mesh.material_ids(); + std::vector> subsets(materials.size()); + for(int i = 0; i < material_ids.size(); ++i) { + subsets[material_ids[i]].push_back(i); + } + for(std::size_t i = 0; i < subsets.size(); ++i){ + auto subset = material_api.CreateMaterialBindSubset(pxr::TfToken("subset_" + std::to_string(i)), subsets[i]); + pxr::UsdShadeMaterialBindingAPI(subset).Bind(materials[i]); + } + } else { + material_api.Bind(materials[0]); + } } void USDSerializer::finalize() { diff --git a/src/serializers/USDSerializer.h b/src/serializers/USDSerializer.h index 92e7501a21..2d09c303aa 100644 --- a/src/serializers/USDSerializer.h +++ b/src/serializers/USDSerializer.h @@ -59,17 +59,14 @@ private: std::map meshes_; std::map materials_; - std::string sanitize(std::string s) { + inline std::string sanitize(std::string s) { std::replace_if(s.begin(), s.end(), - [](char c) { return c == ' ' || c == '.' || c == ',' - || c == ';' || c == ':' || c == '/' - || c == '-' || c == '+' || c == '"' - || c > 127; }, + [](char c) { return c > 122 || c < 48 || (c > 57 && c < 65) || (c > 90 && c < 97); }, '_'); return s; } - void writeMaterial(const pxr::UsdGeomMesh&, const IfcGeom::Material&); + std::vector createMaterials(const pxr::UsdGeomMesh&, const std::vector&); void createLighting(); public: USDSerializer(const std::string&, const SerializerSettings&);