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 3 commits
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
155 changes: 119 additions & 36 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,23 +160,64 @@ 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 GetPoints(const MFnMesh& mesh)
VtValue GetTangents()
{
MStatus status;
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()
{
MStatus status;
MFnMesh mesh(GetDagPath(), &status);
if (ARCH_UNLIKELY(!status)) {
return {};
}

const auto* rawPoints = reinterpret_cast<const GfVec3f*>(mesh.getRawPoints(&status));
if (ARCH_UNLIKELY(!status)) {
return {};
Expand All @@ -186,6 +227,24 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
return VtValue(ret);
}

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

//Normals are per vertex
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 @@ -195,15 +254,21 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
GetDagPath().partialPathName().asChar());

if (key == HdTokens->points) {
MStatus status;
MFnMesh mesh(GetDagPath(), &status);
if (ARCH_UNLIKELY(!status)) {
return {};
}
return GetPoints(mesh);
} else if (key == MayaHydraAdapterTokens->st) {
return GetPoints();
}

if (key == HdTokens->normals) {
return GetNormals();
}

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

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

return {};
}

Expand All @@ -215,18 +280,27 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
}

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

if (key == HdTokens->normals) {
return GetMayaHydraSceneIndex()->SampleValues(
maxSampleCount, times, samples, [&]() -> VtValue { return GetNormals(); });
}

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 +320,17 @@ class MayaHydraMeshAdapter : public MayaHydraShapeAdapter
}
}

return HdMeshTopology(
static const bool passNormalsToHydra = MayaHydraSceneIndex::passNormalsToHydra();
return (passNormalsToHydra) ?
HdMeshTopology(
PxOsdOpenSubdivTokens->none,//For the OGS normals vertex buffer to be used, we need to use PxOsdOpenSubdivTokens->none
UsdGeomTokens->rightHanded,
faceVertexCounts,
faceVertexIndices) :
HdMeshTopology(
(GetMayaHydraSceneIndex()->GetParams().displaySmoothMeshes || GetDisplayStyle().refineLevel > 0)
? PxOsdOpenSubdivTokens->catmullClark
: PxOsdOpenSubdivTokens->none,

UsdGeomTokens->rightHanded,
faceVertexCounts,
faceVertexIndices);
Expand Down Expand Up @@ -339,20 +419,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 +505,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