Hi All,
I’m trying to dynamically update some geometry created by an extruded spline - or more specifically I’m trying to do it in a way that isn’t computationally so expensive that it grinds my app to a halt.
I’m creating the geometry using code borrowed from the Extrude sample, this runs during setup():
void myApp::createBody(){
// circle helper function
const auto createCircle = []( float radius, int segments ) {
ci::Shape2d shape;
shape.moveTo( ci::vec2( 1, 0 ) * radius );
float inc = ( 2.0f * M_PI ) / (float) segments;
for( float angle = 0.0f; angle <= M_PI * 2.0f; angle += inc ) {
shape.lineTo( ci::vec2( cos( angle ), sin( angle ) ) * radius );
}
shape.lineTo( ci::vec2( 1, 0 ) * radius );
return shape;
};
// set spline points as initial particle positions
for (size_t i = 0; i < mParticles.size(); i++){
mSplinePoints.push_back(mParticles[i]->getLocation());
}
// create the initial spline
ci::BSpline3f spline = ci::BSpline3f(mSplinePoints, mSplinePoints.size() - 1, false, true);
// create trimesh by extruding along spline
ci::TriMesh source = ci::geom::ExtrudeSpline( createCircle( 0.25f, 9 ), // last segment normals / black faces
spline,
30 ).thickness( []( float t ) { return ci::smoothstep( 1.0f, 0.05f, t ); } );
const auto shader = ci::gl::getStockShader( ci::gl::ShaderDef().color() );
mBody = ci::gl::Batch::create( source, shader );
}
I have a vector of particles that are moving around ( these are the same particles I substituted in when initially creating the spline using the initial particle positions ). Is there a way to alter the ‘shape’ of the geometry without creating a new mesh every frame?
Currently I’m doing the following:
void myApp::updateBody(){
// circle helper function
const auto createCircle = []( float radius, int segments ) {
ci::Shape2d shape;
shape.moveTo( ci::vec2( 1, 0 ) * radius );
float inc = ( 2.0f * M_PI ) / (float) segments;
for( float angle = 0.0f; angle <= M_PI * 2.0f; angle += inc ) {
shape.lineTo( ci::vec2( cos( angle ), sin( angle ) ) * radius );
}
shape.lineTo( ci::vec2( 1, 0 ) * radius );
return shape;
};
// update the splinepoint locations with the current particle locations
for (size_t i = 0; i < mParticles.size(); i++){
mSplinePoints[i] = mParticles[i]->getLocation();
}
// rebuild the spline
ci::BSpline3f spline = ci::BSpline3f(mSplinePoints, mSplinePoints.size() - 1, false, true);
// rebuild the geometry
ci::TriMesh source = ci::geom::ExtrudeSpline( createCircle( 0.25f, 9 ), // last segment normals / black faces
spline,
30 ).thickness( []( float t ) { return ci::smoothstep( 1.0f, 0.05f, t ); } );
// create a new vbomesh
auto newVboMesh = ci::gl::VboMesh::create(source);
// replace the Batch's vbomesh with the newly generated one
mBody->replaceVboMesh( newVboMesh );
}
As one would expect, this causes the app to grind to a halt ( from 60fps to ~4fps). This isn’t unexpected as creating new geometry every frame is hardly a good idea, but I’m drawing a blank regarding another solution. Perhaps this could be done using a geometry shader? I thought about trying to store a vector of pointers to the particle positions, but this didn’t really make sense as the mBody batch’s mesh has no inherent knowledge of the spline used to create it.
Any thoughts/ideas would be appreciated.
Craig