Last active
August 29, 2015 14:02
-
-
Save paulhoux/09d5211604da8586bda7 to your computer and use it in GitHub Desktop.
One way to create a particle system where all particles move across a unit sphere surface.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cinder/app/AppNative.h" | |
#include "cinder/gl/gl.h" | |
#include "cinder/gl/Vbo.h" | |
#include "cinder/Camera.h" | |
#include "cinder/MayaCamUI.h" | |
#include "cinder/Quaternion.h" | |
#include "cinder/Rand.h" | |
using namespace ci; | |
using namespace ci::app; | |
using namespace std; | |
class ParticlesOnSphereApp : public AppNative { | |
public: | |
void setup(); | |
void update(); | |
void draw(); | |
void mouseDown( MouseEvent event ); | |
void mouseDrag( MouseEvent event ); | |
void resize(); | |
private: | |
static const int kNumParticles = 10000; | |
Vec3f mPosition[kNumParticles]; | |
Vec3f mAxis[kNumParticles]; | |
float mVelocity[kNumParticles]; | |
gl::VboMesh mVBO; | |
CameraPersp mCamera; | |
MayaCamUI mMayaCam; | |
double mCurrentTime; | |
}; | |
void ParticlesOnSphereApp::setup() | |
{ | |
// setup camera | |
mCamera.setPerspective(45.0f, getWindowAspectRatio(), 0.1f, 100.0f); | |
mCamera.setWorldUp( Vec3f::yAxis() ); | |
mCamera.setEyePoint( Vec3f(0, 0, -3) ); | |
mCamera.setCenterOfInterestPoint( Vec3f(0, 0, 0) ); | |
// create particles | |
for(int i=0; i<kNumParticles; ++i) { | |
// set a random position on unit sphere | |
mPosition[i] = Rand::randVec3f(); | |
// set a random rotation axis of unit length | |
mAxis[i] = Rand::randVec3f(); | |
// set a random velocity in radians per second | |
mVelocity[i] = Rand::randFloat(0.1f, 0.5f); | |
} | |
// create dynamic VBO, so we can draw all particles in a single draw call | |
gl::VboMesh::Layout layout; | |
layout.setDynamicPositions(); | |
layout.setStaticIndices(); | |
std::vector<uint32_t> indices(kNumParticles); | |
for(int i=0; i<kNumParticles; ++i) | |
indices[i] = i; | |
mVBO = gl::VboMesh(kNumParticles, kNumParticles, layout, GL_POINTS); | |
mVBO.bufferIndices(indices); | |
// keep track of time | |
mCurrentTime = getElapsedSeconds(); | |
} | |
void ParticlesOnSphereApp::update() | |
{ | |
// calculate elapsed time in seconds | |
double elapsedTime = getElapsedSeconds() - mCurrentTime; | |
mCurrentTime += elapsedTime; | |
// update particles | |
for(auto itr = mVBO.mapVertexBuffer(); itr.isDone(); ++itr) | |
{ | |
size_t i = itr.getIndex(); | |
// slowly rotate around axis (adjusted for frame rate) | |
mPosition[i] = Quatf( mAxis[i], (float)elapsedTime * mVelocity[i] ) * mPosition[i]; | |
// normalize position to avoid accumulating rounding errors | |
mPosition[i].normalize(); | |
// update dynamic position | |
itr.setPosition( mPosition[i] ); | |
} | |
} | |
void ParticlesOnSphereApp::draw() | |
{ | |
gl::clear(); | |
// enable camera | |
gl::pushMatrices(); | |
gl::setMatrices(mCamera); | |
// enable depth buffer | |
gl::enableDepthRead(); | |
gl::enableDepthWrite(); | |
// draw particles | |
gl::color( Color(1,1,1) ); | |
gl::draw( mVBO ); | |
// draw transparent sphere (using back face culling) | |
gl::disableDepthWrite(); | |
gl::enableAlphaBlending(); | |
gl::color( ColorA(0.10f, 0.10f, 0.10f, 0.75f) ); | |
gl::enable( GL_CULL_FACE ); | |
glCullFace( GL_BACK ); | |
gl::drawSphere( Vec3f::zero(), 1.0f, 40 ); | |
gl::disable( GL_CULL_FACE ); | |
gl::disableAlphaBlending(); | |
// disable depth buffer | |
gl::disableDepthRead(); | |
gl::disableDepthWrite(); | |
// disable camera | |
gl::popMatrices(); | |
} | |
void ParticlesOnSphereApp::mouseDown( MouseEvent event ) | |
{ | |
mMayaCam.setCurrentCam( mCamera ); | |
mMayaCam.mouseDown( event.getPos() ); | |
} | |
void ParticlesOnSphereApp::mouseDrag( MouseEvent event ) | |
{ | |
mMayaCam.mouseDrag( event.getPos(), event.isLeftDown(), event.isMiddleDown(), event.isRightDown() ); | |
mCamera = mMayaCam.getCamera(); | |
} | |
void ParticlesOnSphereApp::resize() | |
{ | |
mCamera.setAspectRatio( getWindowAspectRatio() ); | |
} | |
CINDER_APP_NATIVE( ParticlesOnSphereApp, RendererGl ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
funny, I got the sphere, but no particles...