mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
works fine
This commit is contained in:
+1
-1
@@ -97,4 +97,4 @@ src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
|
||||
.DS_Store
|
||||
|
||||
# clangd cache
|
||||
.cache
|
||||
.cache
|
||||
|
||||
@@ -637,7 +637,8 @@ int main(int argc, char** argv) {
|
||||
XML = IfcUtil::path::from_utf8(".xml"),
|
||||
CITY_JSON = IfcUtil::path::from_utf8(".cityjson"),
|
||||
IFC = IfcUtil::path::from_utf8(".ifc"),
|
||||
USD = IfcUtil::path::from_utf8(".usd");
|
||||
USD = IfcUtil::path::from_utf8(".usd"),
|
||||
USDA = IfcUtil::path::from_utf8(".usda");
|
||||
|
||||
// @todo clean up serializer selection
|
||||
// @todo detect program options that conflict with the chosen serializer
|
||||
@@ -830,8 +831,8 @@ int main(int argc, char** argv) {
|
||||
serializer = boost::make_shared<GltfSerializer>(IfcUtil::path::to_utf8(output_temp_filename), geometry_settings, serializer_settings);
|
||||
#endif
|
||||
#ifdef WITH_USD
|
||||
} else if (output_extension == USD) {
|
||||
serializer = boost::make_shared<USDSerializer>(IfcUtil::path::to_utf8(output_temp_filename), settings);
|
||||
} else if (output_extension == USD || output_extension == USDA) {
|
||||
serializer = boost::make_shared<USDSerializer>(IfcUtil::path::to_utf8(output_filename), settings);
|
||||
#endif
|
||||
#ifdef IFOPSH_WITH_OPENCASCADE
|
||||
} else if (output_extension == STP) {
|
||||
@@ -1171,9 +1172,11 @@ int main(int argc, char** argv) {
|
||||
|
||||
Logger::Message(Logger::LOG_PERF, "done file geometry conversion");
|
||||
|
||||
|
||||
// Renaming might fail (e.g. maybe the existing file was open in a viewer application)
|
||||
// Do not remove the temp file as user can salvage the conversion result from it.
|
||||
bool successful = IfcUtil::path::rename_file(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(output_filename));
|
||||
bool successful = IfcUtil::path::rename_file(IfcUtil::path::to_utf8(output_temp_filename), IfcUtil::path::to_utf8(output_filename))
|
||||
|| output_extension == USD || output_extension == USDA;
|
||||
if (!successful) {
|
||||
cerr_ << "Unable to write output file '" << output_filename << "', see '" <<
|
||||
output_temp_filename << "' for the conversion result.";
|
||||
|
||||
@@ -10,23 +10,18 @@
|
||||
#include "pxr/usd/usdGeom/tokens.h"
|
||||
#include "pxr/usd/usdGeom/scope.h"
|
||||
#include "pxr/usd/usdLux/distantLight.h"
|
||||
#include "pxr/usd/usdShade/material.h"
|
||||
#include "pxr/usd/usdShade/shader.h"
|
||||
#include "pxr/usd/usdShade/tokens.h"
|
||||
#include "pxr/usd/usdShade/materialBindingAPI.h"
|
||||
#include "pxr/usd/usdShade/connectableAPI.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
USDSerializer::USDSerializer(const std::string& filename, const SerializerSettings& settings)
|
||||
: WriteOnlyGeometrySerializer(settings)
|
||||
, filename_(filename)
|
||||
USDSerializer::USDSerializer(const std::string& out_filename, const SerializerSettings& settings):
|
||||
WriteOnlyGeometrySerializer(settings),
|
||||
filename_(out_filename)
|
||||
{
|
||||
// create a new stage
|
||||
stage_ = pxr::UsdStage::CreateNew(filename + ".usda");
|
||||
|
||||
// create root xform prim 'World'
|
||||
stage_ = pxr::UsdStage::CreateNew(filename_ + ".usda");
|
||||
|
||||
pxr::UsdGeomXform::Define(stage_, pxr::SdfPath("/World"));
|
||||
pxr::UsdGeomScope::Define(stage_, pxr::SdfPath("/Looks"));
|
||||
createLighting();
|
||||
@@ -52,32 +47,32 @@ void USDSerializer::createLighting() {
|
||||
}
|
||||
|
||||
void USDSerializer::writeMaterial(const pxr::UsdGeomMesh& mesh,const IfcGeom::Material& style) {
|
||||
std::stringstream ss;
|
||||
ss << "/Looks/" << style.original_name();
|
||||
pxr::UsdShadeMaterial::Define(stage_, pxr::SdfPath(ss.str()));
|
||||
pxr::UsdShadeMaterial material(stage_->GetPrimAtPath(pxr::SdfPath(ss.str())));
|
||||
pxr::UsdShadeShader shader = pxr::UsdShadeShader::Define(stage_, pxr::SdfPath(ss.str() + "/Shader"));
|
||||
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"));
|
||||
|
||||
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<float>(style.diffuse()[i]);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
rgba[i] = static_cast<float>(style.diffuse()[i]);
|
||||
shader.CreateInput(pxr::TfToken("diffuseColor"), pxr::SdfValueTypeNames->Color3f).Set(pxr::GfVec3f(rgba[0], rgba[1], rgba[2]));
|
||||
|
||||
if(style.hasTransparency())
|
||||
rgba[3] = 1.0f - style.transparency();
|
||||
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<float>(style.specular()[i]);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
rgba[i] = static_cast<float>(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, pxr::TfToken("surface"));
|
||||
//pxr::UsdShadeMaterialBindingAPI(mesh).Bind(material);
|
||||
material.CreateSurfaceOutput().ConnectToSource(shader.ConnectableAPI(), pxr::TfToken("surface"));
|
||||
pxr::UsdShadeMaterialBindingAPI(mesh).Bind(material);
|
||||
}
|
||||
|
||||
bool USDSerializer::ready() {
|
||||
@@ -85,36 +80,50 @@ bool USDSerializer::ready() {
|
||||
}
|
||||
|
||||
void USDSerializer::writeHeader() {
|
||||
std::stringstream ss;
|
||||
ss << "File generated by IfcOpenShell " << IFCOPENSHELL_VERSION;
|
||||
stage_->GetRootLayer()->SetComment(ss.str());
|
||||
stage_->GetRootLayer()->SetComment("File generated by IfcOpenShell " + std::string(IFCOPENSHELL_VERSION));
|
||||
}
|
||||
|
||||
void USDSerializer::write(const IfcGeom::TriangulationElement* o) {
|
||||
const IfcGeom::Representation::Triangulation& mesh = o->geometry();
|
||||
if ( mesh.material_ids().empty() || mesh.verts().empty() || mesh.faces().empty() )
|
||||
return;
|
||||
|
||||
std::stringstream ss("/World/");
|
||||
ss << mesh.id();
|
||||
pxr::UsdGeomMesh usd_mesh = pxr::UsdGeomMesh::Define(stage_, pxr::SdfPath(ss.str()));
|
||||
auto verts = mesh.verts();
|
||||
auto faces = mesh.faces();
|
||||
const std::vector<double>& m = o->transformation().matrix().data();
|
||||
|
||||
const int vcount = (int) mesh.verts().size() / 3;
|
||||
pxr::VtVec3dArray points;
|
||||
for ( std::vector<double>::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) {
|
||||
points.push_back(pxr::GfVec3d(*(it++), *(it++), *(it++)));
|
||||
if ( mesh.material_ids().empty() || verts.empty() || faces.empty() )
|
||||
return;
|
||||
|
||||
std::string name = o->name() + std::to_string(o->id());
|
||||
if(name.empty()) {
|
||||
name = "Unnamed_" + std::to_string(unnamed_count_);
|
||||
unnamed_count_++;
|
||||
} else {
|
||||
name = sanitize(name);
|
||||
}
|
||||
pxr::UsdGeomMesh usd_mesh = pxr::UsdGeomMesh::Define(stage_, pxr::SdfPath("/World/" + name));
|
||||
|
||||
usd_mesh.AddTranslateOp().Set(pxr::GfVec3d(m[9], m[10], m[11]));
|
||||
|
||||
pxr::VtVec3fArray points;
|
||||
for(std::size_t i = 0; i < verts.size(); i+=3) {
|
||||
points.push_back(pxr::GfVec3f(static_cast<float>(verts[i] * m[0] + verts[i+1] * m[3] + verts[i+2] * m[6]),
|
||||
static_cast<float>(verts[i] * m[1] + verts[i+1] * m[4] + verts[i+2] * m[7]),
|
||||
static_cast<float>(verts[i] * m[2] + verts[i+1] * m[5] + verts[i+2] * m[8])));
|
||||
}
|
||||
usd_mesh.CreatePointsAttr().Set(points);
|
||||
usd_mesh.CreateFaceVertexIndicesAttr().Set(usd_utils::toVtArray(mesh.faces()));
|
||||
const int fcount = (int) mesh.faces().size() / 3;
|
||||
usd_mesh.CreateFaceVertexCountsAttr().Set(pxr::VtArray<int>(fcount, 3));
|
||||
usd_mesh.CreateNormalsAttr().Set(usd_utils::toVtArray(mesh.normals()));
|
||||
|
||||
usd_mesh.CreateFaceVertexIndicesAttr().Set(usd_utils::toVtArray(faces));
|
||||
usd_mesh.CreateFaceVertexCountsAttr().Set(pxr::VtArray<int>((int) faces.size() / 3, 3));
|
||||
|
||||
pxr::VtVec3fArray normals;
|
||||
for (std::vector<double>::const_iterator it = mesh.normals().begin(); it != mesh.normals().end();)
|
||||
normals.push_back(pxr::GfVec3f(static_cast<float>(*(it++)), static_cast<float>(*(it++)), static_cast<float>(*(it++))));
|
||||
usd_mesh.CreateNormalsAttr().Set(normals);
|
||||
|
||||
writeMaterial(usd_mesh, mesh.materials()[0]);
|
||||
}
|
||||
|
||||
void USDSerializer::finalize() {
|
||||
stage_->GetRootLayer()->Save();
|
||||
stage_->Save();
|
||||
}
|
||||
|
||||
#endif // WITH_USD
|
||||
@@ -33,17 +33,21 @@
|
||||
#include "pxr/usd/usd/stage.h"
|
||||
#include "pxr/base/vt/array.h"
|
||||
#include "pxr/usd/usdGeom/mesh.h"
|
||||
#include "pxr/usd/usdShade/material.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
namespace usd_utils {
|
||||
template<typename T>
|
||||
pxr::VtArray<T> toVtArray(const std::vector<T>& vec) {
|
||||
auto array = pxr::VtArray<T>(vec.size());
|
||||
for (size_t i = 0; i < vec.size(); ++i)
|
||||
for (std::size_t i = 0; i < vec.size(); ++i)
|
||||
array[i] = vec[i];
|
||||
return array;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SERIALIZERS_API USDSerializer : public WriteOnlyGeometrySerializer {
|
||||
@@ -51,6 +55,19 @@ private:
|
||||
std::string filename_;
|
||||
bool ready_ = false;
|
||||
pxr::UsdStageRefPtr stage_;
|
||||
std::size_t unnamed_count_ = 0;
|
||||
std::map<std::string, pxr::UsdGeomMesh> meshes_;
|
||||
std::map<std::string, pxr::UsdShadeMaterial> materials_;
|
||||
|
||||
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; },
|
||||
'_');
|
||||
return s;
|
||||
}
|
||||
|
||||
void writeMaterial(const pxr::UsdGeomMesh&, const IfcGeom::Material&);
|
||||
void createLighting();
|
||||
|
||||
Reference in New Issue
Block a user