38
38
39
39
#include " IECoreScene/PointsPrimitive.h"
40
40
41
+ #include " DDImage/ParticleOp.h"
42
+
41
43
using namespace IECoreNuke ;
42
44
using namespace IECore ;
43
45
using namespace IECoreScene ;
46
+ using namespace DD ::Image;
44
47
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 )
47
50
{
48
51
}
49
52
@@ -66,15 +69,87 @@ IECore::ObjectPtr FromNukePointsConverter::doConversion( IECore::ConstCompoundOb
66
69
67
70
// get colour
68
71
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 () )
70
73
{
71
- Color3fVectorDataPtr colorData = new Color3fVectorData ();
74
+ Color4fVectorDataPtr colorData = new Color4fVectorData ();
72
75
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> );
74
77
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 );
75
121
}
76
122
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
78
153
79
154
return result;
80
155
}
0 commit comments