Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HYDRA-955 : Pass normals and tangents to Hydra from render item and mesh adapters #116

Merged
merged 7 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/mayaHydra/hydraExtensions/adapters/adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,14 @@ class MayaHydraAdapter
MAYAHYDRALIB_API
virtual HdCullStyle GetCullStyle() const { return HdCullStyleNothing; }
MAYAHYDRALIB_API
virtual HdDisplayStyle GetDisplayStyle() { return { 0, false, false }; }
virtual HdDisplayStyle GetDisplayStyle() {
constexpr int refineLevel = 0;
constexpr bool flatShading = false;
constexpr bool displacement = false;
constexpr bool occludedSelectionShowsThrough = false;
constexpr bool pointsShadingEnabled = false;
constexpr bool materialIsFinal = false;
return HdDisplayStyle(refineLevel, flatShading, displacement, occludedSelectionShowsThrough, pointsShadingEnabled, materialIsFinal); }
MAYAHYDRALIB_API
virtual GfBBox3d GetBoundingBox() const { return GfBBox3d(); }
MAYAHYDRALIB_API
Expand Down
137 changes: 116 additions & 21 deletions lib/mayaHydra/hydraExtensions/adapters/meshAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ namespace {
const std::pair<MObject&, HdDirtyBits> _dirtyBits[] {
{ MayaAttrs::mesh::pnts,
// This is useful when the user edits the mesh.
HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyExtent
HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyExtent | HdChangeTracker::DirtyNormals
| HdChangeTracker::DirtySubdivTags },
{ MayaAttrs::mesh::inMesh,
// We are tracking topology changes and uv changes separately
HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyExtent
HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyExtent | HdChangeTracker::DirtyNormals
| HdChangeTracker::DirtySubdivTags },
{ MayaAttrs::mesh::worldMatrix, HdChangeTracker::DirtyTransform },
{ MayaAttrs::mesh::doubleSided, HdChangeTracker::DirtyDoubleSided },
Expand Down Expand Up @@ -160,20 +160,56 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
if (ARCH_UNLIKELY(!status)) {
return {};
}

//Uvs are face varying
VtArray<GfVec2f> uvs;
uvs.reserve(static_cast<size_t>(mesh.numFaceVertices()));
const size_t numFacesVertices = mesh.numFaceVertices();
uvs.resize(numFacesVertices);
float2* uvsPointer = (float2*)uvs.cdata();
size_t numUVsFloat2 = 0;
for (MItMeshPolygon pit(GetDagPath()); !pit.isDone(); pit.next()) {
const auto vertexCount = pit.polygonVertexCount();
for (auto i = decltype(vertexCount) { 0 }; i < vertexCount; ++i) {
float2 uv = { 0.0f, 0.0f };
pit.getUV(i, uv);
uvs.push_back(GfVec2f(uv[0], uv[1]));
pit.getUV(i, *uvsPointer);
++uvsPointer;
++numUVsFloat2;
}
}

if (numUVsFloat2 != numFacesVertices){
TF_CODING_ERROR("Number of UVs does not match number of face vertices" );
}

return VtValue(uvs);
}

VtValue GetTangents()
{
MStatus status;
MFnMesh mesh(GetDagPath(), &status);
if (ARCH_UNLIKELY(!status)) {
return {};
}

//Tangents are face varying
const size_t numFacesVertices = mesh.numFaceVertices();
MFloatVectorArray mayaTangents;
mesh.getTangents(mayaTangents);
const int tangentsCount = mayaTangents.length();
if (0 == tangentsCount){
return {};
}

if (tangentsCount != numFacesVertices){
TF_CODING_ERROR("Number of tangents does not match number of face vertices" );
}

const auto* tangentsArray = reinterpret_cast<const GfVec2f*>(&mayaTangents[0]);
VtVec2fArray ret;
ret.assign(tangentsArray, tangentsArray + numFacesVertices);
return VtValue(ret);
}

VtValue GetPoints(const MFnMesh& mesh)
{
MStatus status;
Expand All @@ -186,6 +222,19 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
return VtValue(ret);
}

VtValue GetNormals(const MFnMesh& mesh)
{
//Normals are per vertex
MStatus status;
MFloatVectorArray normals;
constexpr bool angleWeighted = false;
mesh.getVertexNormals(angleWeighted, normals);
const auto* rawNormals = reinterpret_cast<const GfVec3f*>(&normals[0]);
VtVec3fArray ret;
ret.assign(rawNormals, rawNormals + mesh.numVertices());
return VtValue(ret);
}

VtValue Get(const TfToken& key) override
{
TF_DEBUG(MAYAHYDRALIB_ADAPTER_GET)
Expand All @@ -201,9 +250,25 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
return {};
}
return GetPoints(mesh);
} else if (key == MayaHydraAdapterTokens->st) {
}

if (key == HdTokens->normals) {
MStatus status;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am doing a change in this file to standardize the methods and avoid passing sometimes a MfnMesh and sometimes not.

MFnMesh mesh(GetDagPath(), &status);
if (ARCH_UNLIKELY(!status)) {
return {};
}
return GetNormals(mesh);
}

if (key == MayaHydraAdapterTokens->tangents) {
return GetTangents();
}

if (key == MayaHydraAdapterTokens->st) {
return GetUVs();
}

return {};
}

Expand All @@ -222,11 +287,30 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
}
return GetMayaHydraSceneIndex()->SampleValues(
maxSampleCount, times, samples, [&]() -> VtValue { return GetPoints(mesh); });
} else if (key == MayaHydraAdapterTokens->st) {
}

if (key == HdTokens->normals) {
MStatus status;
MFnMesh mesh(GetDagPath(), &status);
if (ARCH_UNLIKELY(!status)) {
return 0;
}
return GetMayaHydraSceneIndex()->SampleValues(
maxSampleCount, times, samples, [&]() -> VtValue { return GetNormals(mesh); });
}

if (key == MayaHydraAdapterTokens->tangents) {
times[0] = 0.0f;
samples[0] = GetTangents();
return 1;
}

if (key == MayaHydraAdapterTokens->st) {
times[0] = 0.0f;
samples[0] = GetUVs();
return 1;
}

return 0;
}

Expand All @@ -246,11 +330,19 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
}
}

static const bool passNormalsToHydra = MayaHydraSceneIndex::passNormalsToHydra();
if (passNormalsToHydra){
return HdMeshTopology(
PxOsdOpenSubdivTokens->none,//For the OGS normals vertex buffer to be used, we need to use PxOsdOpenSubdivTokens->none
UsdGeomTokens->rightHanded,
faceVertexCounts,
faceVertexIndices);
}

return HdMeshTopology(
(GetMayaHydraSceneIndex()->GetParams().displaySmoothMeshes || GetDisplayStyle().refineLevel > 0)
? PxOsdOpenSubdivTokens->catmullClark
: PxOsdOpenSubdivTokens->none,

UsdGeomTokens->rightHanded,
faceVertexCounts,
faceVertexIndices);
Expand Down Expand Up @@ -339,20 +431,23 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
HdPrimvarDescriptorVector GetPrimvarDescriptors(HdInterpolation interpolation) override
{
if (interpolation == HdInterpolationVertex) {
HdPrimvarDescriptor desc;
desc.name = UsdGeomTokens->points;
desc.interpolation = interpolation;
desc.role = HdPrimvarRoleTokens->point;
return { desc };
static const bool passNormalsToHydra = MayaHydraSceneIndex::passNormalsToHydra();
return passNormalsToHydra ?
HdPrimvarDescriptorVector{
{UsdGeomTokens->points, interpolation, HdPrimvarRoleTokens->point},//Vertices
{UsdGeomTokens->normals, interpolation, HdPrimvarRoleTokens->normal}//Normals
} :
HdPrimvarDescriptorVector{
{UsdGeomTokens->points, interpolation, HdPrimvarRoleTokens->point}//Vertices only
};
} else if (interpolation == HdInterpolationFaceVarying) {
// UVs are face varying in maya.
// UVs and tangents are face varying in maya.
MFnMesh mesh(GetDagPath());
if (mesh.numUVs() > 0) {
HdPrimvarDescriptor desc;
desc.name = MayaHydraAdapterTokens->st;
desc.interpolation = interpolation;
desc.role = HdPrimvarRoleTokens->textureCoordinate;
return { desc };
return HdPrimvarDescriptorVector{
{MayaHydraAdapterTokens->st, interpolation, HdPrimvarRoleTokens->textureCoordinate},//uvs
{MayaHydraAdapterTokens->tangents, interpolation, HdPrimvarRoleTokens->textureCoordinate},//tangents
};
}
}
return {};
Expand Down Expand Up @@ -422,7 +517,7 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
auto* adapter = reinterpret_cast<MayaHydraMeshAdapter*>(clientData);
adapter->MarkDirty(
HdChangeTracker::DirtyTopology | HdChangeTracker::DirtyPrimvar
| HdChangeTracker::DirtyPoints);
| HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyNormals);
}

static void ComponentIdChanged(MUintArray componentIds[], unsigned int count, void* clientData)
Expand Down
Loading
Loading