Aligning particles to the mesh surface

In this recipe, we are going to use a 3D version of the particles' code base from the Creating a particle system in 2D recipe. To navigate in 3D space, we will use MayaCamUI covered in the Using MayaCamUI recipe in Chapter 2, Preparing for Development.

Getting ready

To simulate repulsion, we are using the code from the Applying repulsion and attraction forces recipe with slight modifications for three-dimensional space. For this example, we are using the ducky.mesh mesh file that you can find in the resources directory of the Picking3D sample inside the Cinder package. Please copy this file to the assets folder in your project.

How to do it…

We will create particles aligned to the mesh. Perform the following steps to do so:

  1. Add an anchor property to the Particle class in the Particle.h file.
    ci::Vec3f anchor;
  2. Set the anchor value at the end of the Particle class constructor in the Particle.cpp source file.
    anchor = position;
  3. Add the necessary headers in your main class.
    #include "cinder/TriMesh.h"
  4. Add the new properties to your application's main class.
    ParticleSystem mParticleSystem;
    
    float repulsionFactor;
    float maxAlignSpeed;
    
    CameraPersp  mCam;
    MayaCamUI       mMayaCam;
    
    TriMesh  mMesh;
    Vec3f    mRepPosition;
  5. Set the default values inside the setup method.
    repulsionFactor = -1.f;
    maxAlignSpeed = 10.f;
    mRepPosition = Vec3f::zero();
    
    mMesh.read( loadAsset("ducky.msh") );
    
    mCam.setPerspective(45.0f, getWindowAspectRatio(), 0.1, 10000);
    mCam.setEyePoint(Vec3f(7.f,7.f,7.f));
    mCam.setCenterOfInterestPoint(Vec3f::zero());
    mMayaCam.setCurrentCam(mCam);
  6. At the end of the setup method, add the following code snippet:
    for(vector<Vec3f>::iterator it = mMesh.getVertices().begin(); it != mMesh.getVertices().end(); ++it) {
      float mass = Rand::randFloat(2.f, 15.f);
      float drag = 0.95f;
      Particle *particle = new Particle
      ( (*it), 0.f, mass, drag );
      mParticleSystem.addParticle( particle );
    }
  7. Add methods for camera navigation.
    void MainApp::resize( ResizeEvent event ){
        mCam = mMayaCam.getCamera();
        mCam.setAspectRatio(getWindowAspectRatio());
        mMayaCam.setCurrentCam(mCam);
    }
    
    void MainApp::mouseDown(MouseEvent event){
        mMayaCam.mouseDown( event.getPos() );
    }
    
    void MainApp::mouseDrag( MouseEvent event ){
      mMayaCam.mouseDrag( event.getPos(), event.isLeftDown(), 
      event.isMiddleDown(), event.isRightDown() );
    }
  8. Implement the update and draw methods for your main application class.
    void MainApp::update() {
    
    mRepPosition.x = cos(getElapsedSeconds()) * 3.f;
    mRepPosition.y = sin(getElapsedSeconds()*2.f) * 3.f;
    mRepPosition.z = cos(getElapsedSeconds()*1.5f) * 3.f;
    
    for( std::vector<Particle*>::iterator it = mParticleSystem.particles.begin(); it != mParticleSystem.particles.end(); ++it ) {
    
      Vec3f repulsionForce = (*it)->position - mRepPosition;
      repulsionForce = repulsionForce.normalized() * math<float>::max(0.f, 3.f - repulsionForce.length());
      (*it)->forces += repulsionForce;
    
      Vec3f alignForce = (*it)->anchor - (*it)->position;
      alignForce.limit(maxAlignSpeed);
            (*it)->forces += alignForce;
        }
    
      mParticleSystem.update();
    }
    
    void MainApp::draw()
    {
      gl::enableDepthRead();
      gl::enableDepthWrite();
      gl::clear( Color::black() );
      gl::setViewport(getWindowBounds());
      gl::setMatrices(mMayaCam.getCamera());
    
      gl::color(Color(1.f,0.f,0.f));
      gl::drawSphere(mRepPosition, 0.25f);
    
      gl::color(Color::white());
      mParticleSystem.draw();
    }
  9. Replace the draw method for Particle inside the Particle.cpp source file to read as follows
    void Particle::draw(){
      glBegin(GL_POINTS);
      glVertex2f(position);
      glEnd();
    }

How it works…

Firstly, we created particles in place of vertices of the mesh that you can see in step 6.

How it works…

You can find another important calculation in step 8 where we tried to move particles back to their original positions stored in the anchor property. To displace the particles, we used the same repulsion code that we used in the Applying repulsion and attraction forces recipe but with slight modifications for three-dimensional space. Basically, it is about using Vec3f types instead of Vec2f.

How it works…
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.175.253