Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into pr/2088
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastienblor committed Oct 30, 2024
2 parents b1e5ca3 + f12ed72 commit 0890752
Show file tree
Hide file tree
Showing 13 changed files with 948 additions and 29 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@

## Pending feature release

### Bug fixes
- [usd#2129](https://github.com/Autodesk/arnold-usd/issues/2129) - Fixed crashes when instancers have empty / invalid positions
- [usd#2131](https://github.com/Autodesk/arnold-usd/issues/2131) - Wrong transform when an instanceable prim is not xformable
- [usd#2133](https://github.com/Autodesk/arnold-usd/issues/2133) - Fixed crash when the root primitive is invalid

## Pending feature release - 803176

### Feature
- [usd#1738](https://github.com/Autodesk/arnold-usd/issues/1738) - Support all camera Arnold attributes in Hydra
- [usd#1965](https://github.com/Autodesk/arnold-usd/issues/1965) - Write color manager attributes in the RenderSettings primitive
Expand Down Expand Up @@ -59,6 +66,7 @@
- [usd#2102](https://github.com/Autodesk/arnold-usd/issues/2102) - Remove hydra warning subdiv_iterations: use type BYTE, not INT
- [usd#2105](https://github.com/Autodesk/arnold-usd/issues/2105) - Ensure the Arnold scene isn't modified after a Hydra batch render started
- [usd#2127](https://github.com/Autodesk/arnold-usd/issues/2127) - Support deform_keys in curves
- [usd#2129](https://github.com/Autodesk/arnold-usd/issues/2129) - Fixed crashes when instancers have empty / invalid positions

### Build
- [usd#1969](https://github.com/Autodesk/arnold-usd/issues/1969) - Remove support for USD versions older than 21.05
Expand Down
14 changes: 10 additions & 4 deletions libs/translator/reader/read_geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,8 @@ AtNode* UsdArnoldReadPointInstancer::Read(const UsdPrim &prim, UsdArnoldReaderCo
if (i == 0 || scalesAttr.ValueMightBeTimeVarying())
scalesAttr.Get(&scales, times[i]);

if (positions.empty())
continue;
// We're calling this PointInstancer API for each time key,
// with the proper samples that are needed for each attribute.
// We used to call ComputeInstanceTransformsAtTimes just once
Expand Down Expand Up @@ -1686,10 +1688,14 @@ AtNode* UsdArnoldReadPointInstancer::Read(const UsdPrim &prim, UsdArnoldReaderCo

// use the proper matrix, that was computed either with/without the proto's xform.
// It depends on whether the prototype is a child usd proc or a simple geometry
const GfMatrix4d& inputMtx = (mixedProtos && nodesChildProcs[protoIndices[i]]) ?
excludedXformsArray[t][i] : xformsArray[t][i];
AtMatrix &outMtx = instance_matrices[i + t * numInstances];
ConvertValue(outMtx, inputMtx);
std::vector<VtArray<GfMatrix4d> > &inputXform = (mixedProtos && nodesChildProcs[protoIndices[i]]) ? excludedXformsArray : xformsArray;

if (t < inputXform.size() && i < inputXform[t].size()) {
const GfMatrix4d& inputMtx = inputXform[t][i];

AtMatrix &outMtx = instance_matrices[i + t * numInstances];
ConvertValue(outMtx, inputMtx);
}

}
instanceIdxs[i] = protoIndices[i];
Expand Down
25 changes: 2 additions & 23 deletions libs/translator/reader/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,25 +694,8 @@ void UsdArnoldReader::ReadPrimitive(const UsdPrim &prim, UsdArnoldReaderContext
context.SetPrototypeName(prevPrototypeName);
return;
}
AtArray *protoMatrix = nullptr;
AtNode *ginstance = context.CreateArnoldNode("ginstance", objName.c_str());
if (prim.IsA<UsdGeomXformable>()) {
ReadMatrix(prim, ginstance, time, context);
if (protoMatrix) {
// for each key, divide the ginstance matrix by the protoMatrix
AtArray *gMtx = AiNodeGetArray(ginstance, str::matrix);
size_t numKeys = AiArrayGetNumKeys(gMtx);
size_t numProtoKeys = AiArrayGetNumKeys(protoMatrix);
for (size_t i = 0; i < numKeys; ++i) {
AtMatrix mtx = AiArrayGetMtx(gMtx, i);
AtMatrix protoInvMtx = AiM4Invert(AiArrayGetMtx(protoMatrix, AiMax(i, numProtoKeys - 1)));
mtx = AiM4Mult(protoInvMtx, mtx);
AiArraySetMtx(gMtx, i, mtx);
}
}
}
if (protoMatrix)
AiArrayDestroy(protoMatrix);
ReadMatrix(prim, ginstance, time, context);

AiNodeSetFlt(ginstance, str::motion_start, time.motionStart);
AiNodeSetFlt(ginstance, str::motion_end, time.motionEnd);
Expand All @@ -739,8 +722,7 @@ void UsdArnoldReader::ReadPrimitive(const UsdPrim &prim, UsdArnoldReaderContext
return;
}
}



// We want to ensure we only read a single RenderSettings prim. So we compare
// if the path provided to the reader. If nothing was set, we'll just look
// for the first RenderSettings in the stage
Expand Down Expand Up @@ -1226,7 +1208,6 @@ void UsdArnoldReaderThreadContext::AddConnection(
AtNode *source, const std::string &attr, const std::string &target, ConnectionType type,
const std::string &outputElement)
{
//std::cerr<<"--------------- add connection here "<<std::endl;
if (_reader->GetReadStep() == UsdArnoldReader::READ_TRAVERSE) {
// store a link between attributes/nodes to process it later
// If we have a dispatcher, we want to lock here
Expand Down Expand Up @@ -1255,7 +1236,6 @@ void UsdArnoldReaderThreadContext::ProcessConnections()
{
_primvarsStack.clear();
_primvarsStack.push_back(std::vector<UsdGeomPrimvar>());
//std::cerr<<"reader process connection "<<_connections.size()<<std::endl;
std::vector<Connection> danglingConnections;
for (const auto& connection : _connections) {
// if ProcessConnections returns false, it means that the target
Expand All @@ -1266,7 +1246,6 @@ void UsdArnoldReaderThreadContext::ProcessConnections()
}
// our connections list is now cleared by contains all the ones
// that couldn't be resolved
//std::cerr<<"bloblo"<<std::endl;
_connections = danglingConnections;
}
AtNode* UsdArnoldReaderThreadContext::LookupTargetNode(const char *targetName, const AtNode* source, ConnectionType type)
Expand Down
4 changes: 2 additions & 2 deletions libs/translator/writer/writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ void UsdArnoldWriter::SetRegistry(UsdArnoldWriterRegistry *registry) { _registry

void UsdArnoldWriter::CreateScopeHierarchy(const SdfPath &path)
{
if (path == SdfPath::AbsoluteRootPath() || _stage->GetPrimAtPath(path))
if (path.IsEmpty() || path == SdfPath::AbsoluteRootPath() || _stage->GetPrimAtPath(path))
return;

// Ensure the parents scopes are created first, otherwise they'll
Expand All @@ -241,7 +241,7 @@ void UsdArnoldWriter::CreateScopeHierarchy(const SdfPath &path)

void UsdArnoldWriter::CreateHierarchy(const SdfPath &path, bool leaf)
{
if (path == SdfPath::AbsoluteRootPath())
if (path.IsEmpty() || path == SdfPath::AbsoluteRootPath())
return;

if (!leaf) {
Expand Down
7 changes: 7 additions & 0 deletions testsuite/test_2129/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Instancer with empty / invalid values

Fixes #2129

author: sebastien.ortega

PARAMS: {'scene': 'test.usda'}
217 changes: 217 additions & 0 deletions testsuite/test_2129/data/test.usda
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#usda 1.0
(
startTimeCode = 0
endTimeCode = 1
metersPerUnit = 0.0254
startTimeCode = 0
timeCodesPerSecond = 30
upAxis = "Z"
)

def Xform "ProtoRed" () {
def Cube "cube" () {
ColorFloat[] primvars:displayColor = [(1,0,0)]
bool primvars:arnold:smoothing = 0
}
token visibility = "invisible"
}

def Xform "ProtoGreen" () {
def Cone "cone" () {
ColorFloat[] primvars:displayColor = [(0,1,0)]
bool primvars:arnold:smoothing = 0
}
token visibility = "invisible"
}

// Normal instancer setup
def PointInstancer "InstancerAllAttrAuth" {
int[] protoIndices.timeSamples = {
0:[ 1, 0 ],

}
rel prototypes = [ <Protos/Proto1>, <Protos/Proto2> ]

point3f[] positions = [(10,0,0), (-10,0,0)]
quath[] orientations = [(1,0,0,0), (1,0,0,0)]
point3f[] scales = [(1,1,1), (1,1,1)]

def "Protos" {

def "Proto1" (
references = </ProtoRed>
) {
token visibility = "visible"
}
def Xform "Proto2" (
references = </ProtoGreen>
) {
token visibility = "visible"
}
}
}

// Instancer with no PRS attributes setup
def PointInstancer "InstancerAttrNotAuth" {
int[] protoIndices.timeSamples = {
0:[ 1, 0 ],

}
rel prototypes = [ <Protos/Proto1>, <Protos/Proto2> ]

def "Protos" {

def "Proto1" (
references = </ProtoRed>
) {
token visibility = "visible"
}
def Xform "Proto2" (
references = </ProtoGreen>
) {
token visibility = "visible"
}
}
}

// Instancer with PRS attributes setup empty / malformed data.
def PointInstancer "InstancerAttrAuthEmpty" {
int[] protoIndices.timeSamples = {
0:[ 1, 0 ],

}
rel prototypes = [ <Protos/Proto1>, <Protos/Proto2> ]

point3f[] positions = []
quath[] orientations = []
point3f[] scales = []

def "Protos" {

def "Proto1" (
references = </ProtoRed>
) {
token visibility = "visible"
}
def Xform "Proto2" (
references = </ProtoGreen>
) {
token visibility = "visible"
}
}
}


// Instancer with PRS attributes setup at a non-default time.
def PointInstancer "InstancerAttrAuthAtTime" {
int[] protoIndices.timeSamples = {
0:[ 1, 0 ],

}
rel prototypes = [ <Protos/Proto1>, <Protos/Proto2> ]

point3f[] positions.timeSamples = {
0:[(10,0,0), (-10,0,0)]
}

quath[] orientations.timeSamples = {
0:[(1,0,0,0), (1,0,0,0)]
}

point3f[] scales.timeSamples = {
0:[(1,1,1), (1,1,1)]
}

def "Protos" {

def "Proto1" (
references = </ProtoRed>
) {
token visibility = "visible"
}
def Xform "Proto2" (
references = </ProtoGreen>
) {
token visibility = "visible"
}
}
}

def PointInstancer "SubobjCentersInstances" {
int[] protoIndices.timeSamples = {
0:[ 1, 0 ],

}
rel prototypes = [ <Protos/Proto1>, <Protos/Proto2> ]

point3f[] positions = [(10,10,10), (0,0,0)]
quath[] orientations = [(1,0,0,0), (1,0,0,0)]
point3f[] scales = [(1,1,1), (1,1,1)]

def "Protos" {

def "Proto1" (
references = </ProtoRed>
) {
token visibility = "visible"
}
def Xform "Proto2" (
references = </ProtoGreen>
) {
token visibility = "visible"
}
}
}

def Sphere "SubobjCenterPrim"
{
matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (50, 50, 50, 1) )
uniform token[] xformOpOrder = ["xformOp:transform"]
}


def Scope "Render"
{
def RenderSettings "settings"
{
float arnold:meters_per_unit = 0.01
string arnold:name = "options"
bool arnold:texture_automip = 0
bool arnold:texture_per_file_stats = 1
prepend rel camera = </persp>
uniform int2 resolution = (160, 120)
}

}
def DomeLight "light"
{
float primvars:arnold:camera = 0
}
def Camera "persp"
{
float2 clippingRange = (0.1, 10000)
float focalLength = 35
float focusDistance = 1
float horizontalAperture = 35.999928
float[] primvars:arnold:aperture_size = [0]
float[] primvars:arnold:fov = [54.432224]
float2[] primvars:arnold:lens_shift = [(0, 0)]
float2[] primvars:arnold:lens_tilt_angle = [(0, 0)]
vector3f[] primvars:arnold:look_at = [(0, 0, -1)]
float primvars:arnold:motion_end = 0
vector3f[] primvars:arnold:position = [(0, 0, 0)]
float2[] primvars:arnold:screen_window_max = [(1, 1)]
float2[] primvars:arnold:screen_window_min = [(-1, -1)]
vector3f[] primvars:arnold:up = [(0, 1, 0)]
color4f primvars:arnold:uv_remap = (0, 0, 0, 1)
string primvars:dcc_name = "cameraShape1" (
elementSize = 1
interpolation = "constant"
)
token projection = "perspective"
double shutter:close = 0
double shutter:open = 0
float verticalAperture = 23.999952
double3 xformOp:translate = (-2.0660716187878085, 6.1982148563634105, 80.08531126363758)
uniform token[] xformOpOrder = ["xformOp:translate"]
}
Loading

0 comments on commit 0890752

Please sign in to comment.