Skip to content
Open
Changes from all 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
44 changes: 44 additions & 0 deletions src/IECoreScene/CoordinateSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@

#include "IECoreScene/CoordinateSystem.h"

#include "IECore/SimpleTypedData.h"
#include "IECore/MurmurHash.h"

#include "Imath/ImathMatrix.h"
#include "Imath/ImathMatrixAlgo.h"

using namespace IECore;
using namespace IECoreScene;
using namespace boost;
Expand Down Expand Up @@ -104,6 +108,46 @@ void CoordinateSystem::load( LoadContextPtr context )
unsigned int v = m_ioVersion;
ConstIndexedIOPtr container = context->container( staticTypeName(), v );
container->read( g_nameEntry, m_name );

// CoordinateSystem used to derive from the deprecated and removed StateRenderable
// holding additional transform information for the renderer. A better approach that is also
// used in Gaffer, the transform information is better stored as separate transform information.
// Cortex 10.6 also removed all DCC integrations, i.e. IECoreMaya, which stored, for example
// Locator transformation on the CoordinateSystem. We provide a way to still retrieve this
// information from old SceneCaches, although not fully transparent and backwards compatible.
// Clients of CoordinateSystem will need to be adjusted if needed.

// We look for a matrix entry somewhere underneath the CoordinateSystem, directly read it from
// there instead of loading an object and stash it in the BlindData.
const IndexedIO::EntryID matrixEntry( "matrix" );
Imath::M44f matrix;

std::function<void(ConstIndexedIOPtr)> findMatrixEntry = [&]( ConstIndexedIOPtr directory )
{
if( directory->hasEntry( matrixEntry ) )
{
float *f = matrix.getValue();
directory->read( matrixEntry, f, 16 );
Copy link
Member

Choose a reason for hiding this comment

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

Should this return as soon as a matrix is found? And if so, should we stop the iteration through levelDirectories when it does?

}

IndexedIO::EntryIDList levelDirectories;
directory->entryIds( levelDirectories, IndexedIO::EntryType::Directory );
Copy link
Member

Choose a reason for hiding this comment

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

I have a feeling that entryIds() doesn't return things in a stable order from one run to the next (the order is based on InternedString comparisons, which can give different results from process to process). So in the case of MatrixMotionTransform, you may not always be picking up the same time sample.


for ( auto levelDirectory : levelDirectories )
{
ConstIndexedIOPtr subdirectory = directory->subdirectory( levelDirectory, IndexedIO::MissingBehaviour::NullIfMissing );
if( subdirectory )
{
findMatrixEntry( subdirectory );
}
Comment on lines +136 to +142
Copy link
Member

Choose a reason for hiding this comment

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

Are you using this recursive search because you need to support MatrixMotionTransform as well as MatrixTransform, and it's convenient to deal with both using the same code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I solely focused on MatrixTransform. I don't think any on the DCC modules nor anything else in the IE codebase use it. The reason I went for the recursive search is, because it felt like the cleanest option, so I'd be happy to hear about a better way!

I initially wanted to go directly to the matrix entry, but IndexedIO::directory takes an EntryIDList type path. Constructing that path left me with a very ugly initializer list of interned strings since I need to add all the intermediate data directories as well (data/transform/data/MatrixTransform/data/matrix is the path underneath the current container). I figured I could just push back the required children in a loop, but somehow a more generic recursive searched felt best at the time.

Copy link
Member

Choose a reason for hiding this comment

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

To me, a naive reader, the recursive search says "I want to find any entry called matrix, no matter where it might be in an arbitrary tree of things". If we're actually looking for one specific thing, and we know where it should be, then recursive search seems fragile - it might find unexpected things. Hardcoding the expected path is more robust, and also helps a reader understand exactly what we're looking for.

To satisfy my curiosity, I tried this more direct approach. I don't know what's up with IndexedIO::directory() but I couldn't get it to work, so I did have to iterate the directories by hand : johnhaddon@c128789.

}
};

findMatrixEntry( container );
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps it's worth starting the search from container->subdirectory( "transform" ), so we're sure we can't accidentally pick up fields from elsewhere? This would also avoid a little bit of work when loading new files, where the subdirectory won't even exist.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similarly to the comment about using a recursive search, if I recall correctly, subdirectory did not give me the transform since it's one level deeper under data. I think container::load takes this into account when loading the actual object.

Here again, I might have missed something and am very open to a different and better solution

if( matrix != Imath::identity44f )
{
blindData()->writable()["LegacyTransform"] = new IECore::M44fData( matrix );
}
}

void CoordinateSystem::hash( MurmurHash &h ) const
Expand Down