Skip to content

Instantly share code, notes, and snippets.

@roxlu
Created March 20, 2012 22:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save roxlu/2141784 to your computer and use it in GitHub Desktop.
Save roxlu/2141784 to your computer and use it in GitHub Desktop.
Poor mans Hyphae growth
#include "rxParticle.h"
rxParticle::rxParticle(ofVec3f pos, float mass)
:position(pos)
,mass(mass)
,velocity(0)
,forces(0)
,age(0)
,lifetime(10)
{
if(mass < 0.001) {
mass = 0.001;
}
inv_mass = 1.0/mass;
}
rxParticle::~rxParticle() {
printf("~rxParticle, lifetime: %f\n", lifetime);
}
void rxParticle::update() {
forces *= inv_mass;
velocity += forces;
position += velocity;
velocity *= 0.98f;
forces.set(0,0,0);
}
void rxParticle::draw() {
glVertex3fv(&position.x);
}
void rxParticle::reset() {
neighbors.clear();
//age = 0;
lifetime = 10;
}
#ifndef ROXLU_RXPARTICLEH
#define ROXLU_RXPARTICLEH
#include "ofMain.h"
class rxParticle {
public:
rxParticle(ofVec3f position, float mass);
~rxParticle();
void update();
void draw();
void reset();
float mass;
float inv_mass;
float age;
float lifetime;
ofVec3f forces;
ofVec3f velocity;
ofVec3f position;
vector<rxParticle*> neighbors;
};
#endif
#include "rxParticles.h"
rxParticles::rxParticles() {
}
rxParticles::~rxParticles() {
}
void rxParticles::update() {
list<rxParticle*>::iterator it = particles.begin();
while(it != particles.end()) {
(*it)->update();
++it;
}
list<rxSpring*>::iterator its = springs.begin();
while(its != springs.end()) {
(*its)->update();
++its;
}
}
void rxParticles::draw() {
glColor3f(0,0,0);
// glBegin(GL_TRIANGLES);
glBegin(GL_LINES);
list<rxSpring*>::iterator its = springs.begin();
while(its != springs.end()) {
(*its)->draw();
++its;
}
glEnd();
glPointSize(8);
glColor3f(0,0,0);
glBegin(GL_POINTS);
list<rxParticle*>::iterator it = particles.begin();
while(it != particles.end()) {
(*it)->draw();
++it;
}
glEnd();
glColor3f(1,1,1);
}
void rxParticles::addParticle(rxParticle* p) {
particles.push_back(p);
}
// only remove, no delete
void rxParticles::removeParticle(rxParticle* p) {
list<rxParticle*>::iterator it = std::find(particles.begin(), particles.end(), p);
if(it != particles.end()) {
particles.erase(it);
}
}
void rxParticles::addSpring(rxSpring* s) {
springs.push_back(s);
}
void rxParticles::addSwirp(rxSwirp* s) {
swirps.push_back(s);
}
void rxParticles::addForce(const ofVec3f& f) {
list<rxParticle*>::iterator it = particles.begin();
while(it != particles.end()) {
(*it)->forces += f;
++it;
}
}
void rxParticles::follow(const ofVec3f& f, float effect) {
list<rxParticle*>::iterator it = particles.begin();
ofVec3f dir;
float force;
float length;
while(it != particles.end()) {
rxParticle& p = *(*it);
dir = f - p.position;
length = dir.length();
dir.normalize();
dir *= length * effect;
(*it)->forces += dir;
++it;
}
}
void rxParticles::repel(float effect) {
ofVec3f dir;
float f;
float length_sq;
int now = ofGetElapsedTimeMillis();
list<rxParticle*>::iterator ita = particles.begin();
list<rxParticle*>::iterator itb = particles.begin();
while(ita != particles.end()) {
itb = ita;
++itb;
rxParticle& a = *(*ita);
while(itb != particles.end()) {
rxParticle& b = *(*itb);
dir = b.position - a.position;
length_sq = dir.lengthSquared();
if(length_sq > 0.0f) {
f = 1.0f/length_sq;
dir *= (f * effect);
a.forces -= dir;
b.forces += dir;
}
++itb;
}
++ita;
}
int end = ofGetElapsedTimeMillis();
}
#ifndef ROXLU_RXPARTICLESH
#define ROXLU_RXPARTICLESH
#include "ofMain.h"
#include "rxParticle.h"
#include "rxSpring.h"
#include "rxSwirp.h"
#include <list>
using std::list;
class rxParticles {
public:
rxParticles();
~rxParticles();
void draw();
void update();
void repel(float effect = 0.3);
void follow(const ofVec3f& pos, float effect = 0.001f);
void addForce(const ofVec3f& f);
void addParticle(rxParticle* p);
void removeParticle(rxParticle* p);
void addSpring(rxSpring* s);
void addSwirp(rxSwirp* s);
list<rxParticle*> particles;
list<rxSpring*> springs;
list<rxSwirp*> swirps;
};
#endif
#include "rxVeins.h"
rxVeins::rxVeins() {
}
rxVeins::~rxVeins() {
}
void rxVeins::addSource(rxParticle* p) {
sources.push_back(p);
sources_ps.addParticle(p);
}
void rxVeins::addRoot(rxParticle* p) {
roots.push_back(p);
}
void rxVeins::step() {
printf("Num sources: %zu, num roots: %zu\n", sources.size(), roots.size());
vector<rxParticle*>::iterator sit = sources.begin();
vector<rxParticle*>::iterator rit = roots.begin();
sources_to_nodes.clear();
while(rit != roots.end()) {
(*rit)->reset();
++rit;
}
// for each source search the particles which is closest auxin sources.
ofVec3f dir(0,0,0);
float length_sq = 0.0;
while(sit != sources.end()) {
rxParticle& source = *(*sit);
// do we need to remove this auxin source?
if(source.lifetime < 0) {
sources_ps.removeParticle(*sit);
delete *sit;
sit = sources.erase(sit);
continue;
}
// find the closest root for this source
rit = roots.begin();
float closest_dist = FLT_MAX;
rxParticle* closest_node = NULL;
while(rit != roots.end()) {
rxParticle& root = *(*rit);
dir = root.position - source.position;
length_sq = dir.lengthSquared();
if(length_sq < closest_dist) {
closest_dist = length_sq;
closest_node = *rit;
}
++rit;
}
if(closest_node != NULL) {
closest_node->lifetime = 5;
sources_to_nodes[*sit].push_back(closest_node);
closest_node->neighbors.push_back(*sit);
}
++sit;
}
// move roots towards auxin sources.
float min_dist = 2;
float min_dist_sq = min_dist*min_dist;
float dist_sq = 0;
float num_sources = 0.0f;
float D = 3;
ofVec3f average(0,0,0);
rit = roots.begin();
vector<rxParticle*> new_roots;
while(rit != roots.end()) {
rxParticle& root = *(*rit);
if(root.lifetime != 5) {
delete *rit;
rit = roots.erase(rit);
// ++rit;
continue;
}
average.set(0,0,0);
num_sources = 0;
vector<rxParticle*>::iterator nit = root.neighbors.begin();
while(nit != root.neighbors.end()) {
dir = (*nit)->position - root.position;
dist_sq = dir.lengthSquared();
average += dir;
num_sources++;
// mark for deletion.
if(dist_sq < min_dist_sq) {
(*nit)->lifetime = -1;
}
++nit;
}
average /= num_sources;
average.normalize();
average *= D;
average += root.position;
rxParticle* new_root = new rxParticle(average, 0);
new_roots.push_back(new_root);
nodes.push_back(average);
++rit;
}
for(int i = 0; i < new_roots.size(); ++i) {
addRoot(new_roots[i]);
}
}
void rxVeins::draw() {
vector<rxParticle*>::iterator it = sources.begin();
while(it != sources.end()) {
rxParticle& p = *(*it);
glColor3f(1,1,1);
ofCircle(p.position.x, p.position.y, 3);
glColor3f(0.22,0.33,0.44);
ofCircle(p.position.x, p.position.y, 2);
++it;
}
glColor3f(0,1,1);
vector<rxParticle*>::iterator rit = roots.begin();
while(rit != roots.end()) {
rxParticle& p = *(*rit);
glColor3f(1,1,1);
ofCircle(p.position.x, p.position.y, 2);
glColor3f(1,0.0,0.0);
ofCircle(p.position.x, p.position.y, 1);
++rit;
}
glColor3f(1,1,1);
glBegin(GL_POINTS);
vector<ofVec3f>::iterator nit = nodes.begin();
while(nit != nodes.end()) {
glVertex3fv(&nit->x);
//ofCircle(nit->x, nit->y, 3);
++nit;
}
glEnd();
glBegin(GL_LINES);
map<rxParticle*, list<rxParticle*> >::iterator mit = sources_to_nodes.begin();
while(mit != sources_to_nodes.end()) {
glColor3f(1,0,0);
rxParticle& a = *(mit->first);
glVertex3fv(&a.position.x);
list<rxParticle*>::iterator lt = mit->second.begin();
while(lt != mit->second.end()) {
rxParticle& b = *(*lt);
glColor3f(1,1,1);
glVertex3fv(&b.position.x);
++lt;
}
++mit;
}
glEnd();
}
void rxVeins::update() {
sources_ps.repel(0.1);
sources_ps.update();
}
#ifndef ROXLU_VEINSH
#define ROXLU_VEINSH
#include "ofMain.h"
#include "rxParticle.h"
#include "rxParticles.h"
#include <list>
class rxVeins {
public:
rxVeins();
~rxVeins();
void addSource(rxParticle* s);
void addRoot(rxParticle* r);
void step();
void update();
void draw();
rxParticles sources_ps;
vector<rxParticle*> sources;
vector<rxParticle*> roots;
vector<ofVec3f> nodes;
map<rxParticle*, list<rxParticle*> > sources_to_nodes;
};
#endif
@roxlu
Copy link
Author

roxlu commented Mar 20, 2012

WORK IN PROGRESS, NOT CORRECT, WITH BUGS

Free Image Hosting at www.ImageShack.us
Free Image Hosting at www.ImageShack.us

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment