/*ofApp.h*/
#pragma once
#include "ofMain.h"
#include "demoParticle.h"
using namespace cv;
using namespace std;
class ofApp : public ofBaseApp{
public:
void skin(Mat src);
};
[C++] 纯文本查看复制代码
/*demoParticle.cpp*/
#include "demoParticle.h"
#include "ofAppBaseWindow.h"
#include "ofApp.h"
void demoParticle::update(){
//extern int pointx;
//cout << pointx << endl;
//1 - APPLY THE FORCES BASED ON WHICH MODE WE ARE IN
if( mode == PARTICLE_MODE_ATTRACT ){
ofPoint attractPt(pointx, pointy);
frc = attractPt-pos; // we get the attraction force/vector by looking at the mouse pos relative to our pos
frc.normalize(); //by normalizing we disregard how close the particle is to the attraction point
vel *= drag; //apply drag
vel += frc * 0.6; //apply force
}
else if( mode == PARTICLE_MODE_REPEL ){
ofPoint attractPt(pointx, pointy);
frc = attractPt-pos;
//let get the distance and only repel points close to the mouse
float dist = frc.length();
frc.normalize();
vel *= drag;
if( dist < 150 ){
vel += -frc * 0.6; //notice the frc is negative
}else{
//if the particles are not close to us, lets add a little bit of random movement using noise. this is where uniqueVal comes in handy.
frc.x = ofSignedNoise(uniqueVal, pos.y * 0.01, ofGetElapsedTimef()*0.2);
frc.y = ofSignedNoise(uniqueVal, pos.x * 0.01, ofGetElapsedTimef()*0.2);
vel += frc * 0.04;
}
}
else if( mode == PARTICLE_MODE_NOISE ){
//lets simulate falling snow
//the fake wind is meant to add a shift to the particles based on where in x they are
//we add pos.y as an arg so to prevent obvious vertical banding around x values - try removing the pos.y * 0.006 to see the banding
float fakeWindX = ofSignedNoise(pos.x * 0.003, pos.y * 0.006, ofGetElapsedTimef() * 0.6);
frc.x = fakeWindX * 0.25 + ofSignedNoise(uniqueVal, pos.y * 0.04) * 0.6;
frc.y = ofSignedNoise(uniqueVal, pos.x * 0.006, ofGetElapsedTimef()*0.2) * 0.09 + 0.18;
vel *= drag;
vel += frc * 0.4;
//we do this so as to skip the bounds check for the bottom and make the particles go back to the top of the screen
if( pos.y + vel.y > ofGetHeight() ){
pos.y -= ofGetHeight();
}
}
else if( mode == PARTICLE_MODE_NEAREST_POINTS ){
if( attractPoints ){
//1 - find closest attractPoint
ofPoint closestPt;
int closest = -1;
float closestDist = 9999999;
for(unsigned int i = 0; i < attractPoints->size(); i++){
float lenSq = ( attractPoints->at(i)-pos ).lengthSquared();
if( lenSq < closestDist ){
closestDist = lenSq;
closest = i;
}
}
//2 - if we have a closest point - lets calcuate the force towards it
if( closest != -1 ){
closestPt = attractPoints->at(closest);
float dist = sqrt(closestDist);
//in this case we don't normalize as we want to have the force proportional to distance
frc = closestPt - pos;
vel *= drag;
//lets also limit our attraction to a certain distance and don't apply if 'f' key is pressed
if( dist < 300 && dist > 40 && !ofGetKeyPressed('f') ){
vel += frc * 0.003;
}else{
//if the particles are not close to us, lets add a little bit of random movement using noise. this is where uniqueVal comes in handy.
frc.x = ofSignedNoise(uniqueVal, pos.y * 0.01, ofGetElapsedTimef()*0.2);
frc.y = ofSignedNoise(uniqueVal, pos.x * 0.01, ofGetElapsedTimef()*0.2);
vel += frc * 0.4;
}
}
}
}
//2 - UPDATE OUR POSITION
pos += vel;
//3 - (optional) LIMIT THE PARTICLES TO STAY ON SCREEN
//we could also pass in bounds to check - or alternatively do this at the ofApp level
if( pos.x > ofGetWidth() ){
pos.x = ofGetWidth();
vel.x *= -1.0;
}else if( pos.x < 0 ){
pos.x = 0;
vel.x *= -1.0;
}
if( pos.y > ofGetHeight() ){
pos.y = ofGetHeight();
vel.y *= -1.0;
}
else if( pos.y < 0 ){
pos.y = 0;
vel.y *= -1.0;
}
}
[C++] 纯文本查看复制代码
/*demoParticle.h*/
#pragma once
#include "ofMain.h"
extern int pointx;
extern int pointy;
enum particleMode{
PARTICLE_MODE_ATTRACT = 0,
PARTICLE_MODE_REPEL,
PARTICLE_MODE_NEAREST_POINTS,
PARTICLE_MODE_NOISE
};
class demoParticle{
public:
demoParticle();
void update();
};