diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index a62655212e..bad908352f 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -636,7 +636,8 @@ int main(int argc, char** argv) { HDF = IfcUtil::path::from_utf8(".h5"), XML = IfcUtil::path::from_utf8(".xml"), CITY_JSON = IfcUtil::path::from_utf8(".cityjson"), - IFC = IfcUtil::path::from_utf8(".ifc"); + IFC = IfcUtil::path::from_utf8(".ifc"), + USD = IfcUtil::path::from_utf8(".usd"); // @todo clean up serializer selection // @todo detect program options that conflict with the chosen serializer @@ -830,7 +831,7 @@ int main(int argc, char** argv) { #endif #ifdef WITH_USD } else if (output_extension == USD) { - serializer = boost::make_shared(IfcUtil::path::to_utf8(output_temp_filename), settings); + serializer = boost::make_shared(IfcUtil::path::to_utf8(output_temp_filename), settings); #endif #ifdef IFOPSH_WITH_OPENCASCADE } else if (output_extension == STP) { diff --git a/src/serializers/USDSerializer.cpp b/src/serializers/USDSerializer.cpp index 95d5c161fc..18667566a2 100644 --- a/src/serializers/USDSerializer.cpp +++ b/src/serializers/USDSerializer.cpp @@ -2,15 +2,11 @@ #include "USDSerializer.h" -#include "../ifcparse/utils.h" - -#include "pxr/usd/sdf/path.h" -#include "pxr/usd/gf/vec3f.h" -#include "pxr/usd/gf/rotation.h" -#include "pxr/usd/tf/token.h" +#include "pxr/base/tf/token.h" +#include "pxr/base/gf/vec3f.h" +#include "pxr/base/gf/rotation.h" #include "pxr/usd/usdGeom/xform.h" #include "pxr/usd/usdGeom/xformOp.h" -#include "pxr/usd/usdGeom/mesh.h" #include "pxr/usd/usdGeom/tokens.h" #include "pxr/usd/usdGeom/scope.h" #include "pxr/usd/usdLux/distantLight.h" @@ -20,23 +16,16 @@ #include "pxr/usd/usdShade/materialBindingAPI.h" #include "pxr/usd/usdShade/connectableAPI.h" - -#include #include #include - USDSerializer::USDSerializer(const std::string& filename, const SerializerSettings& settings) : WriteOnlyGeometrySerializer(settings) , filename_(filename) - , settings_(settings) { // create a new stage stage_ = pxr::UsdStage::CreateNew(filename + ".usda"); - if( !settings().get(SerializerSettings::USE_Y_UP) ) - stage_->SetDefaultPrim(pxr::UsdGeomXform::Define(stage_, pxr::SdfPath("/"), pxr::UsdGeomTokens->z)); - else - stage_->SetDefaultPrim(pxr::UsdGeomXform::Define(stage_, pxr::SdfPath("/"), pxr::UsdGeomTokens->y)); + // create root xform prim 'World' pxr::UsdGeomXform::Define(stage_, pxr::SdfPath("/World")); pxr::UsdGeomScope::Define(stage_, pxr::SdfPath("/Looks")); @@ -55,7 +44,7 @@ void USDSerializer::createLighting() { // set the light's orientation pxr::UsdGeomXform xform(stage_->GetPrimAtPath(pxr::SdfPath(light_path))); pxr::GfVec3f light_direction(0.0f, 0.0f, -1.0f); - xform.AddRotateOp(pxr::UsdGeomXformOp::PrecisionFloat, pxr::UsdGeomXformOp::TypeRotateXYZ).Set(pxr::GfRotation(pxr::GfVec3f(0.0f, 1.0f, 0.0f), light_direction).GetQuaternion()); + //xform.AddRotateOp(pxr::UsdGeomXformOp::PrecisionFloat, pxr::UsdGeomXformOp::TypeRotateXYZ).Set(pxr::GfRotation(pxr::GfVec3f(0.0f, 1.0f, 0.0f), light_direction).GetQuaternion()); // set the light's color pxr::UsdLuxDistantLight light(stage_->GetPrimAtPath(pxr::SdfPath(light_path))); light.CreateIntensityAttr().Set(1000.0f); @@ -68,11 +57,11 @@ void USDSerializer::writeMaterial(const pxr::UsdGeomMesh& mesh,const IfcGeom::Ma 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")); - shader.CreateIdAttr().Set(TfToken("UsdPreviewSurface")); + 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 style.diffuse()[i]; + 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.hasTransparency()) @@ -80,15 +69,15 @@ void USDSerializer::writeMaterial(const pxr::UsdGeomMesh& mesh,const IfcGeom::Ma 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]; + 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, pxr::TfToken("surface")); - pxr::UsdShadeMaterialBindingAPI(mesh).Bind(material); + //material.CreateSurfaceOutput().ConnectToSource(shader, pxr::TfToken("surface")); + //pxr::UsdShadeMaterialBindingAPI(mesh).Bind(material); } bool USDSerializer::ready() { @@ -102,23 +91,25 @@ void USDSerializer::writeHeader() { } void USDSerializer::write(const IfcGeom::TriangulationElement* o) { - if ( o->geometry().material_ids().empty() ) + const IfcGeom::Representation::Triangulation& mesh = o->geometry(); + if ( mesh.material_ids().empty() || mesh.verts().empty() || mesh.faces().empty() ) return; - std:sstringstream ss("/World/"); - ss << o->geometry().id(); - pxr::UsdGeomMesh::Define(stage_, pxr::SdfPath(ss.str())); - const IfcGeom::Representation::Triangulation& mesh = o->geometry(); + std::stringstream ss("/World/"); + ss << mesh.id(); + pxr::UsdGeomMesh usd_mesh = pxr::UsdGeomMesh::Define(stage_, pxr::SdfPath(ss.str())); const std::vector& m = o->transformation().matrix().data(); - const int vcount = (int)mesh.verts().size() / 3; + const int vcount = (int) mesh.verts().size() / 3; + pxr::VtVec3dArray points; for ( std::vector::const_iterator it = mesh.verts().begin(); it != mesh.verts().end(); ) { - const double x = *(it++); - const double y = *(it++); - const double z = *(it++); - - - } + points.push_back(pxr::GfVec3d(*(it++), *(it++), *(it++))); + } + 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(fcount, 3)); + usd_mesh.CreateNormalsAttr().Set(usd_utils::toVtArray(mesh.normals())); } diff --git a/src/serializers/USDSerializer.h b/src/serializers/USDSerializer.h index aa50258802..39d9ef0aef 100644 --- a/src/serializers/USDSerializer.h +++ b/src/serializers/USDSerializer.h @@ -24,10 +24,27 @@ #include "../serializers/serializers_api.h" #include "../ifcgeom_schema_agnostic/GeometrySerializer.h" +#include "../ifcparse/utils.h" + +// undefine opencascade Handle macro, because it conflicts with USD +#undef Handle #include "pxr/pxr.h" #include "pxr/usd/usd/stage.h" +#include "pxr/base/vt/array.h" +#include "pxr/usd/usdGeom/mesh.h" +#include + +namespace usd_utils { + template + pxr::VtArray toVtArray(const std::vector& vec) { + auto array = pxr::VtArray(vec.size()); + for (size_t i = 0; i < vec.size(); ++i) + array[i] = vec[i]; + return array; + } +} class SERIALIZERS_API USDSerializer : public WriteOnlyGeometrySerializer { private: @@ -35,7 +52,7 @@ private: bool ready_ = false; pxr::UsdStageRefPtr stage_; - int writeMaterial(const IfcGeom::Material&); + void writeMaterial(const pxr::UsdGeomMesh&, const IfcGeom::Material&); void createLighting(); public: USDSerializer(const std::string&, const SerializerSettings&);