Skip to content

Commit 4a1ce90

Browse files
committed
WIP
1 parent 659635e commit 4a1ce90

1 file changed

Lines changed: 116 additions & 30 deletions

File tree

src/libguc/src/converter.cpp

Lines changed: 116 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
#include <pxr/usd/usdGeom/camera.h>
2424
#include <pxr/usd/usdGeom/mesh.h>
2525
#include <pxr/usd/usdGeom/metrics.h>
26+
#include <pxr/usd/usdGeom/pointInstancer.h>
2627
#include <pxr/usd/usdGeom/primvarsAPI.h>
2728
#include <pxr/usd/usdGeom/scope.h>
29+
#include <pxr/usd/usdGeom/sphere.h>
2830
#include <pxr/usd/usdGeom/xform.h>
2931
#include <pxr/base/gf/camera.h>
3032
#include <pxr/usd/usdLux/shapingAPI.h>
@@ -787,6 +789,7 @@ namespace guc
787789
// TODO: proper material handling
788790
const cgltf_material* material = primitiveData->material;
789791

792+
// TODO: how to actually handle indices in a point cloud?
790793
// Indices
791794
VtIntArray indices;
792795
{
@@ -801,14 +804,14 @@ namespace guc
801804
}
802805
}
803806

804-
// Points
807+
// Points (& fallback indices)
805808
VtVec3fArray points;
806809
{
807810
const cgltf_accessor* accessor = cgltf_find_accessor(primitiveData, "POSITION");
808811

809812
if (!detail::readVtArrayFromAccessor(accessor, points) || accessor->count == 0)
810813
{
811-
TF_RUNTIME_ERROR("invalid POSITION accessor");
814+
TF_RUNTIME_ERROR("invalid %s accessor", accessor->name);
812815
return false;
813816
}
814817

@@ -826,19 +829,19 @@ namespace guc
826829
VtVec3fArray colors;
827830
VtFloatArray opacities;
828831
{
829-
const cgltf_accessor* accessor = cgltf_find_accessor(primitiveData, "COLOR0");
832+
const cgltf_accessor* accessor = cgltf_find_accessor(primitiveData, "COLOR_0");
830833

831-
if (accessor->type != cgltf_type_vec4)
832-
{
833-
// TODO: spec reads 'should' so missing alpha is valid
834-
TF_RUNTIME_ERROR("gsplat primitive has invalid COLOR0 accessor");
835-
return false;
836-
}
834+
// TODO: the spec does not make it clear if we can expect a vec3 or vec4
835+
// TODO: for now this is debug code.
836+
#if 1
837+
assert(accessor->type == cgltf_type_vec4);
838+
839+
colors.resize(accessor->count, GfVec3f(1.0f, 0.0f, 0.0f));
837840

838841
VtVec4fArray rgbaColors;
839842
if (!detail::readVtArrayFromAccessor(accessor, rgbaColors))
840843
{
841-
TF_RUNTIME_ERROR("can't read gsplat COLOR0 attribute");
844+
TF_RUNTIME_ERROR("can't read %s attribute; ignoring", accessor->name);
842845
return false;
843846
}
844847

@@ -850,34 +853,67 @@ namespace guc
850853
colors[k] = GfVec3f(rgbaColors[k].data());
851854
}
852855

853-
// Optimization: if material is opaque, we don't read the opacities anyway
854-
if (material->alpha_mode != cgltf_alpha_mode_opaque)
856+
opacities.resize(rgbaColorCount);
857+
for (size_t k = 0; k < rgbaColorCount; k++)
855858
{
856-
opacities.resize(rgbaColorCount);
857-
for (size_t k = 0; k < rgbaColorCount; k++)
858-
{
859-
opacities[k] = rgbaColors[k][3];
860-
}
859+
opacities[k] = rgbaColors[k][3];
860+
}
861+
#else
862+
// TODO: I think we need to add our own validation function proxy
863+
assert(accessor->type == cgltf_type_vec3); // TODO: only for debugging, should be part of cgltf validation
864+
865+
if (!detail::readVtArrayFromAccessor(accessor, colors))
866+
{
867+
TF_RUNTIME_ERROR("can't read gsplat %s attribute", accessor->name);
868+
return false;
861869
}
870+
#endif
862871
}
863872

864-
// Gsplat rotation, scale
865-
VtVec4fArray rotations;
866-
VtVec3fArray scales;
873+
// Opacities
874+
#if 0
875+
VtFloatArray opacities;
867876
{
868-
const cgltf_accessor* rotationAccessor = cgltf_find_accessor(primitiveData, "KHR_gaussian_splatting:ROTATION");
877+
const cgltf_accessor* accessor = cgltf_find_accessor(primitiveData, "KHR_gaussian_splatting:OPACITY");
869878

870-
if (!detail::readVtArrayFromAccessor(rotationAccessor, rotations))
879+
if (!accessor || !detail::readVtArrayFromAccessor(accessor, opacities))
871880
{
872-
TF_RUNTIME_ERROR("can't read gsplat ROTATION accessor");
881+
TF_RUNTIME_ERROR("can't read gsplat %s attribute", accessor->name);
873882
return false;
874883
}
884+
}
885+
#endif
875886

876-
const cgltf_accessor* scaleAccessor = cgltf_find_accessor(primitiveData, "KHR_gaussian_splatting:SCALE");
887+
// Rotations
888+
// TODO: try out if we just can keep the type vec4f
889+
VtQuatfArray rotations;
890+
{
891+
const cgltf_accessor* accessor = cgltf_find_accessor(primitiveData, "KHR_gaussian_splatting:ROTATION");
877892

878-
if (!detail::readVtArrayFromAccessor(scaleAccessor, scales))
893+
VtVec4fArray vec4Rots;
894+
if (!detail::readVtArrayFromAccessor(accessor, vec4Rots))
879895
{
880-
TF_RUNTIME_ERROR("can't read gsplat SCALE accessor");
896+
TF_RUNTIME_ERROR("can't read gsplat %s attribute", accessor->name);
897+
return false;
898+
}
899+
900+
size_t rotCount = vec4Rots.size();
901+
902+
rotations.resize(rotCount);
903+
for (size_t i = 0; i < rotCount; i++)
904+
{
905+
rotations[i] = GfQuatf(vec4Rots[i][3], vec4Rots[i][0], vec4Rots[i][1], vec4Rots[i][2]);
906+
}
907+
}
908+
909+
// Scales
910+
VtVec3fArray scales;
911+
{
912+
const cgltf_accessor* accessor = cgltf_find_accessor(primitiveData, "KHR_gaussian_splatting:SCALE");
913+
914+
if (!detail::readVtArrayFromAccessor(accessor, scales))
915+
{
916+
TF_RUNTIME_ERROR("can't read gsplat %s attribute", accessor->name);
881917
return false;
882918
}
883919
}
@@ -916,15 +952,65 @@ namespace guc
916952
}
917953
}
918954

955+
// Create point instancer
956+
auto pointInstancer = UsdGeomPointInstancer::Define(m_stage, path);
919957

920-
// TODO: now, we need to create a splat mesh (ellipsoid, triangle, quad)
921-
// TODO: inside an instancer
958+
VtIntArray proto0Indices(indices.size(), 0);
959+
pointInstancer.CreateProtoIndicesAttr(VtValue(proto0Indices));
960+
pointInstancer.CreatePositionsAttr(VtValue(points));
961+
pointInstancer.CreateOrientationsfAttr(VtValue(rotations));
962+
pointInstancer.CreateScalesAttr(VtValue(scales));
922963

964+
auto primvarsApi = UsdGeomPrimvarsAPI(pointInstancer);
965+
if (!colors.empty())
966+
{
967+
primvarsApi.CreatePrimvar(TfToken("displayColor"), SdfValueTypeNames->Vector3fArray, UsdGeomTokens->varying).Set(colors);
968+
primvarsApi.CreatePrimvar(TfToken("color"), SdfValueTypeNames->Vector3fArray, UsdGeomTokens->varying).Set(colors);
969+
}
970+
if (!opacities.empty())
971+
{
972+
primvarsApi.CreatePrimvar(TfToken("displayOpacity"), SdfValueTypeNames->FloatArray, UsdGeomTokens->varying).Set(opacities);
973+
primvarsApi.CreatePrimvar(TfToken("opacity"), SdfValueTypeNames->FloatArray, UsdGeomTokens->varying).Set(opacities);
974+
}
975+
size_t shCount = 0;
976+
for (auto& deg : shCoeffs)
977+
for (auto& values : deg)
978+
{
979+
auto name = TfToken("sh_coeff" + std::to_string(shCount++));
980+
primvarsApi.CreatePrimvar(name, SdfValueTypeNames->FloatArray, UsdGeomTokens->varying).Set(values);
981+
}
982+
983+
// Create prototype mesh
984+
auto protoPath = makeUniqueStageSubpath(m_stage, path, "ProtoGeom");
985+
#if 1
986+
UsdGeomSphere protoGeom = UsdGeomSphere::Define(m_stage, protoPath);
987+
#else
988+
UsdGeomMesh protoGeom = UsdGeomMesh::Define(m_stage, protoPath);
989+
990+
VtVec3fArray trianglePoints = {
991+
GfVec3f(0.0f, 0.0f, 0.0f),
992+
GfVec3f(0.01f, 0.0f, 0.0f),
993+
GfVec3f(0.005f, 0.00866f, 0.0f)
994+
};
995+
protoGeom.CreatePointsAttr(VtValue(trianglePoints));
923996
997+
VtIntArray faceVertexCounts = { 3 };
998+
protoGeom.CreateFaceVertexCountsAttr(VtValue(faceVertexCounts));
924999
925-
// TODO: we should also provide displayColors
1000+
VtIntArray faceVertexIndices = { 0, 1, 2 };
1001+
protoGeom.CreateFaceVertexIndicesAttr(VtValue(faceVertexIndices));
9261002
927-
// TODO: return something
1003+
protoGeom.CreateSubdivisionSchemeAttr(VtValue(UsdGeomTokens->none));
1004+
#endif
1005+
1006+
auto instancerProtoRel = pointInstancer.CreatePrototypesRel();
1007+
SdfPathVector protoPaths = { protoPath };
1008+
instancerProtoRel.SetTargets(protoPaths);
1009+
1010+
// TODO: assign GS material based on degree count
1011+
1012+
prim = pointInstancer.GetPrim();
1013+
return true;
9281014
}
9291015

9301016
bool Converter::createMeshPrimitive(const cgltf_primitive* primitiveData, SdfPath path, UsdPrim& prim)

0 commit comments

Comments
 (0)