Skip to content

Commit 05fce6d

Browse files
committed
FromNukePointsConverter: Support for additional primvar from particleSprite
1 parent ea49e91 commit 05fce6d

File tree

2 files changed

+83
-7
lines changed

2 files changed

+83
-7
lines changed

include/IECoreNuke/FromNukePointsConverter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class IECORENUKE_API FromNukePointsConverter : public FromNukeConverter
5656

5757
/// The caller is responsible for ensuring that geo is alive
5858
/// for as long as the converter is.
59-
FromNukePointsConverter( const DD::Image::GeoInfo *geo );
59+
FromNukePointsConverter( const DD::Image::GeoInfo *geo, DD::Image::Op* op );
6060
virtual ~FromNukePointsConverter();
6161

6262
protected :
@@ -66,6 +66,7 @@ class IECORENUKE_API FromNukePointsConverter : public FromNukeConverter
6666
private :
6767

6868
const DD::Image::GeoInfo *m_geo;
69+
DD::Image::Op* m_op;
6970

7071
};
7172

src/IECoreNuke/FromNukePointsConverter.cpp

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@
3838

3939
#include "IECoreScene/PointsPrimitive.h"
4040

41+
#include "DDImage/ParticleOp.h"
42+
4143
using namespace IECoreNuke;
4244
using namespace IECore;
4345
using namespace IECoreScene;
46+
using namespace DD::Image;
4447

45-
FromNukePointsConverter::FromNukePointsConverter( const DD::Image::GeoInfo *geo )
46-
: FromNukeConverter( "Converts nuke meshes to IECore meshes." ), m_geo( geo )
48+
FromNukePointsConverter::FromNukePointsConverter( const DD::Image::GeoInfo *geo, DD::Image::Op* op )
49+
: FromNukeConverter( "Converts nuke ParticleSprites to IECore PointsPrimitive." ), m_geo( geo ), m_op( op )
4750
{
4851
}
4952

@@ -66,15 +69,87 @@ IECore::ObjectPtr FromNukePointsConverter::doConversion( IECore::ConstCompoundOb
6669

6770
// get colour
6871
const DD::Image::Attribute *colorAttr = m_geo->get_typed_attribute( "Cf", DD::Image::VECTOR4_ATTRIB );
69-
if( colorAttr && colorAttr->size()==result->getNumPoints() )
72+
if( colorAttr && colorAttr->size() == result->getNumPoints() )
7073
{
71-
Color3fVectorDataPtr colorData = new Color3fVectorData();
74+
Color4fVectorDataPtr colorData = new Color4fVectorData();
7275
colorData->writable().resize( result->getNumPoints() );
73-
std::transform( colorAttr->vector4_list->begin(), colorAttr->vector4_list->end(), colorData->writable().begin(), IECore::convert<Imath::Color3f, DD::Image::Vector4> );
76+
std::transform( colorAttr->vector4_list->begin(), colorAttr->vector4_list->end(), colorData->writable().begin(), IECore::convert<Imath::Color4f, DD::Image::Vector4> );
7477
result->variables["Cs"] = PrimitiveVariable( PrimitiveVariable::Vertex, colorData );
78+
79+
// Adding a separate alpha primvar as according to my test
80+
// Cs is a Color3f in Gaffer. While we could also use 3f here, I think it is reasonable
81+
// to combine alpha inside Cs and hope it gets supported by Gaffer and then we can remove
82+
// the alpha primvar.
83+
FloatVectorDataPtr alphaData = new FloatVectorData();
84+
auto& alpha = alphaData->writable();
85+
alpha.resize( result->getNumPoints() );
86+
87+
for( size_t i=0; i < result->getNumPoints(); i++ )
88+
{
89+
alpha[i] = colorAttr->vector4( i ).w;
90+
}
91+
result->variables["alpha"] = PrimitiveVariable( PrimitiveVariable::Vertex, alphaData );
92+
}
93+
94+
// get pid
95+
const DD::Image::Attribute *idAttr = m_geo->get_typed_attribute( "id", DD::Image::INT_ATTRIB );
96+
if( idAttr && idAttr->size() == result->getNumPoints() )
97+
{
98+
IntVectorDataPtr idData = new IntVectorData();
99+
auto& id = idData->writable();
100+
id.resize( result->getNumPoints() );
101+
for( size_t i=0; i < result->getNumPoints(); i++ )
102+
{
103+
id[i] = idAttr->integer( i );
104+
}
105+
result->variables["pid"] = PrimitiveVariable( PrimitiveVariable::Vertex, idData );
106+
}
107+
108+
// get size/width
109+
const DD::Image::Attribute *sizeAttr = m_geo->get_typed_attribute( "size", DD::Image::FLOAT_ATTRIB );
110+
if( sizeAttr && sizeAttr->size() == result->getNumPoints() )
111+
{
112+
FloatVectorDataPtr widthData = new FloatVectorData();
113+
auto& width = widthData->writable();
114+
width.resize( result->getNumPoints() );
115+
116+
for( size_t i=0; i < result->getNumPoints(); i++ )
117+
{
118+
width[i] = sizeAttr->flt( i );
119+
}
120+
result->variables["width"] = PrimitiveVariable( PrimitiveVariable::Vertex, widthData );
75121
}
76122

77-
/// \todo Other primitive variables
123+
// get vel
124+
// Nuke's particle system seems to be a bit ad-hock rather than integrated in the 3D sub-system.
125+
// To get the particle velocity, we mix the API ( ParticleOp and GeoOp ). Arguably, we could switch
126+
// to use the ParticleOp API for everything but for now I decided to keep accessing what can be using the
127+
// GeoOp/GeoInfo API, hoping that Foundry will ultimately get the particle to geo fully supported.
128+
//
129+
// Another important detail here is that we are using the m_op->input0, this is based on the expectation
130+
// that the LiveScene will always be the client of this kind of converter.
131+
// In which case, the LiveScene is always internal to a GeoOp derived node (LiveSceneHolder or WriteGeo)
132+
auto particleOp = m_op->particleOp();
133+
if ( particleOp )
134+
{
135+
OutputContext oc;
136+
oc.setFrame( m_op->outputContext().frame() );
137+
particleOp->setOutputContext( oc );
138+
float prevTime, outTime;
139+
const auto particleSystem = particleOp->getParticleSystem(prevTime, outTime, true, nullptr);
140+
141+
V3fVectorDataPtr velData = new V3fVectorData();
142+
auto& vel = velData->writable();
143+
vel.resize( result->getNumPoints() );
144+
for( size_t i=0; i < result->getNumPoints(); i++ )
145+
{
146+
// velocity seems to be calculated per time step so we need to multiply by the frames per second to get velocity compatible with motion blur rendering.
147+
vel[i] = IECore::convert<Imath::V3f>( particleSystem->particleVelocity( i ) ) * DD::Image::root_real_fps();
148+
}
149+
150+
result->variables["velocity"] = PrimitiveVariable( PrimitiveVariable::Vertex, velData );
151+
}
152+
// \todo Other primitive variables
78153

79154
return result;
80155
}

0 commit comments

Comments
 (0)