void Emitter::exportFrame() { static int frame=0; ++frame; // this is the data we are going to store, alembic uses Imath // internally so we convert from ngl // this is the array of particle positions for the frame std::vector<Imath::V3f> positions(m_numParticles); // these are the particle id's which are required so use use index no std::vector<Alembic::Util::uint64_t> id(m_numParticles); // set this to push back into the array Imath::V3f data; // colour values std::vector<Imath::V3f> colours(m_numParticles); std::vector<Imath::V3f> velocities(m_numParticles); std::vector< Alembic::Util::float32_t > widths; AbcG::OFloatGeomParam::Sample widthSamp; widthSamp.setScope(Alembic::AbcGeom::kVertexScope); widthSamp.setVals(Alembic::Abc::FloatArraySample(widths)); for(size_t i=0; i<m_numParticles; ++i) { positions[i]=Imath::V3f(m_particles[i].m_px,m_particles[i].m_py,m_particles[i].m_pz); id[i]=i; colours[i]=Imath::V3f(m_particles[i].m_r,m_particles[i].m_g,m_particles[i].m_b); velocities[i]=Imath::V3f(m_particles[i].m_r,m_particles[i].m_g,m_particles[i].m_b); } // create as samples we need to do this else we get a most vexing parse // https://en.wikipedia.org/wiki/Most_vexing_parse using below // psamp(V3fArraySample( positions),UInt64ArraySample(id)) AbcG::V3fArraySample pos(positions); AbcG::UInt64ArraySample ids(id); AbcG::OPointsSchema::Sample psamp( pos,ids,velocities ); AbcG::OPointsSchema &pSchema = m_partsOut->getSchema(); std::cout<<"Schema "<<pSchema.getNumSamples()<<" "<<pSchema.valid()<<"\n"; pSchema.set( psamp ); AbcG::V3fArraySample colourArray(colours); m_rgbOut->set(colourArray); }
void MayaPointPrimitiveWriter::write(double iFrame) { MStatus status; std::vector<float> position; std::vector<float> velocity; std::vector< Alembic::Util::uint64_t > particleIds; std::vector<float> width; bool runupFromStart = false; MTime to(iFrame, MTime::kSeconds); // need to force re-evaluation MFnParticleSystem particle(mDagPath); particle.evaluateDynamics(to, runupFromStart); unsigned int size = particle.count(); Alembic::AbcGeom::OPointsSchema::Sample samp; if (size == 0) { samp.setPositions(Alembic::Abc::V3fArraySample(NULL, 0)); samp.setVelocities(Alembic::Abc::V3fArraySample(NULL, 0)); samp.setIds(Alembic::Abc::UInt64ArraySample(NULL, 0)); mSchema.set(samp); return; } position.reserve(size*3); velocity.reserve(size*3); particleIds.reserve(size); width.reserve(size); // get particle position MVectorArray posArray; particle.position(posArray); for (unsigned int i = 0; i < size; i++) { MVector vec = posArray[i]; position.push_back(static_cast<float>(vec.x)); position.push_back(static_cast<float>(vec.y)); position.push_back(static_cast<float>(vec.z)); } samp.setPositions( Alembic::Abc::P3fArraySample((const Imath::V3f *) &position.front(), position.size() / 3) ); // get particle velocity MVectorArray vecArray; particle.velocity(vecArray); for (unsigned int i = 0; i < size; i++) { MVector vec = vecArray[i]; velocity.push_back(static_cast<float>(vec.x)); velocity.push_back(static_cast<float>(vec.y)); velocity.push_back(static_cast<float>(vec.z)); } if (!velocity.empty()) { samp.setVelocities( Alembic::Abc::V3fArraySample((const Imath::V3f *) &velocity.front(), velocity.size() / 3) ); } // get particleIds MIntArray idArray; particle.particleIds(idArray); for (unsigned int i = 0; i < size; i++) { particleIds.push_back(idArray[i]); } samp.setIds( Alembic::Abc::UInt64ArraySample(&(particleIds.front()), particleIds.size()) ); // assume radius is width MDoubleArray radiusArray; MPlug radius = particle.findPlug("radiusPP", true, &status); AbcGeom::GeometryScope widthScope = AbcGeom::kUnknownScope; if ( status == MS::kSuccess) { // RadiusPP exists, get all particles value widthScope = AbcGeom::kVaryingScope; particle.radius(radiusArray); for (unsigned int i = 0; i < size; i++) { float radius = static_cast<float>(radiusArray[i]); width.push_back(radius); } } else { // Get the value of the radius attribute widthScope = AbcGeom::kUniformScope; width.push_back( particle.findPlug("radius").asDouble() ); } if (!width.empty()) { Alembic::AbcGeom::OFloatGeomParam::Sample widthSamp; widthSamp.setVals(width); widthSamp.setScope(widthScope); samp.setWidths( widthSamp ); } mSchema.set(samp); }