Skip to content

Instantly share code, notes, and snippets.

@mattcox
Created November 20, 2017 19:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattcox/e0d7a95930a2a12d49cdfe96fecab77d to your computer and use it in GitHub Desktop.
Save mattcox/e0d7a95930a2a12d49cdfe96fecab77d to your computer and use it in GitHub Desktop.
This demonstrates how to evaluate a particle source for it's particles. By default, only position, transform and ID are evaluated, however it could easily be extended to support other types.
/*
* This demonstrates how to evaluate a particle source for it's particles.
* By default, only position, transform and ID are evaluated, however it
* could easily be extended to support other types.
*
* To evaluate particles, you must provide a TriangleSoup to the Tableau,
* allowing it populate your soup with the particle data. This is very
* similar to reading surfaces, but we only care about vertex data, not
* polygons.
*
* To use this example, first query your particle source item for the
* ILxParticleItem interface, and in your Modifier Allocate function, call
* the Prepare method on the ParticleItem to allocate the channels it needs
* to evaluate. In your modifier Evaluate method, call the Evaluate method
* on the ParticleItem, passing in the index returned from the Prepare method.
* This should return a TableauSurface, which can be queried for particles
* by passing it and a vector of Particles into the Soup Sample method.
*/
#include <lxsdk/lx_particle.hpp>
#include <lxsdk/lx_tableau.hpp>
#include <lxsdk/lx_vector.hpp>
struct Particle
{
Particle () : index (0.0)
{
LXx_VCLR (pos);
lx::MatrixIdent (xfrm);
}
float index;
LXtFVector pos;
LXtMatrix xfrm;
};
enum PART_FEATURE
{
PART_FEATURE_POS,
PART_FEATURE_XFRM,
PART_FEATURE_ID,
PART_FEATURE_MAX
};
class Soup :
public CLxImpl_TriangleSoup,
public CLxSingletonPolymorph
{
public:
LXxSINGLETON_METHOD;
Soup ()
{
AddInterface (new CLxIfc_TriangleSoup <Soup>);
mEnabled[PART_FEATURE_POS] = false;
mEnabled[PART_FEATURE_XFRM] = false;
mEnabled[PART_FEATURE_ID] = false;
mBase = 0;
mCurrent = 0;
/*
* Create a new TableauVertex, then add the particle
* features we're interested in reading. The features
* are returned in a single float array, so we also
* store the offset to lookup the values in the vector.
*/
if (mTblSvc.NewVertex (mTblVrx))
{
unsigned int i = 0, count = 0;
if (LXx_OK (mTblVrx.AddFeature (LXiTBLX_PARTICLES, LXsTBLX_PARTICLE_POS, &i)))
{
mEnabled[PART_FEATURE_POS] = true;
mOffsets[PART_FEATURE_POS] = count;
count += 3;
}
if (LXx_OK (mTblVrx.AddFeature (LXiTBLX_PARTICLES, LXsTBLX_PARTICLE_XFRM, &i)))
{
mEnabled[PART_FEATURE_XFRM] = true;
mOffsets[PART_FEATURE_XFRM] = count;
count += 9;
}
if (LXx_OK (mTblVrx.AddFeature (LXiTBLX_PARTICLES, LXsTBLX_PARTICLE_ID, &i)))
{
mEnabled[PART_FEATURE_ID] = true;
mOffsets[PART_FEATURE_ID] = count;
count += 1;
}
}
}
LXxO_TriangleSoup_Segment
{
/*
* Segment is called at the start of each segment.
* We only care about reading points/particles, so
* we skip any other type.
*/
mCurrent = mParticles->size ();
mBase = mCurrent;
return (type == LXiTBLX_SEG_POINT) ? LXe_TRUE : LXe_FALSE;
}
LXxO_TriangleSoup_Vertex
{
/*
* Read the particle and add it to the vector. We
* only read the features that are enabled, just in
* case a particle source doesn't provide a specific
* feature.
*/
if (!mParticles)
return LXe_FAILED;
Particle particle;
if (mEnabled[PART_FEATURE_POS])
{
particle.position[0] = vertex[mOffsets[PART_FEATURE_POS]];
particle.position[1] = vertex[mOffsets[PART_FEATURE_POS] + 1];
particle.position[2] = vertex[mOffsets[PART_FEATURE_POS] + 2];
}
if (mEnabled[PART_FEATURE_XFRM])
{
particle.xfrm[0][0] = vertex[mOffsets[PART_FEATURE_XFRM]];
particle.xfrm[0][1] = vertex[mOffsets[PART_FEATURE_XFRM] + 1];
particle.xfrm[0][2] = vertex[mOffsets[PART_FEATURE_XFRM] + 2];
particle.xfrm[1][0] = vertex[mOffsets[PART_FEATURE_XFRM] + 3];
particle.xfrm[1][1] = vertex[mOffsets[PART_FEATURE_XFRM] + 4];
particle.xfrm[1][2] = vertex[mOffsets[PART_FEATURE_XFRM] + 5];
particle.xfrm[2][0] = vertex[mOffsets[PART_FEATURE_XFRM] + 6];
particle.xfrm[2][1] = vertex[mOffsets[PART_FEATURE_XFRM] + 7];
particle.xfrm[2][2] = vertex[mOffsets[PART_FEATURE_XFRM] + 8];
}
if (mEnabled[PART_FEATURE_ID])
particle.index = vertex[mOffsets[PART_FEATURE_ID]];
mParticles->push_back (particle);
*index = (mCurrent++) - mBase;
return LXe_OK;
}
LXxO_TriangleSoup_Polygon
{
/*
* We don't care about partices, but we have to
* implement this function, otherwise things fail.
*/
return LXe_OK;
}
void
Sample (
CLxUser_TableauSurface &surface,
std::vector <Particle> *particles)
{
if (!surface.test () || !particles)
return;
mParticles = particles;
/*
* Sample the TableauSurface using our Soup object.
*/
if (LXx_OK (surface.SetVertex (mTblVrx)))
surface.Sample (NULL, -1.0, *this);
mParticles = NULL;
}
private:
CLxUser_TableauService mTblSvc;
CLxLoc_TableauVertex mTblVrx;
std::vector <Particle> *mParticles;
bool mEnabled[PART_FEATURE_MAX];
unsigned int mOffsets[PART_FEATURE_MAX];
unsigned int mBase, mCurrent;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment