├── .gitignore ├── BarnesHut └── src │ ├── Body.h │ ├── Particle.h │ ├── ParticleSystem.h │ ├── Spring.h │ ├── Tree.h │ └── main.cpp ├── BinnedParticleSystem └── src │ ├── BinnedParticle.cpp │ ├── BinnedParticle.h │ ├── BinnedParticleSystem.cpp │ ├── BinnedParticleSystem.h │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── Box2dContours └── src │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── BulgeEffect ├── bin │ └── data │ │ ├── bulge.fs │ │ ├── bulge.vs │ │ └── gradient-grid.png └── src │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── BulgeEffectMulti ├── bin │ └── data │ │ ├── applyBulge.fs │ │ ├── blendBulge.fs │ │ └── generateBulge.fs └── src │ ├── BulgeEffect.cpp │ ├── BulgeEffect.h │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── CircleRenderer └── src │ └── main.cpp ├── ColorCube └── src │ └── main.cpp ├── Fading └── src │ └── main.cpp ├── GLSLParticleSystem ├── bin │ └── data │ │ ├── drawShader.fs │ │ ├── drawShader.vs │ │ └── updateShader.fs └── src │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── ImageQualityComparison └── src │ └── main.cpp ├── LineDrawing └── src │ └── main.cpp ├── LombScargle └── src │ └── main.cpp ├── LutExample ├── .gitignore ├── bin │ └── data │ │ ├── blue-boost-lut.exr │ │ ├── linear-lut.exr │ │ └── lut.frag └── src │ ├── Lut.h │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── NoiseFlocking └── src │ ├── Particle.cpp │ ├── Particle.h │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── P52OF └── src │ ├── PApp.cpp │ └── main.h ├── RemapExample ├── bin │ └── data │ │ ├── remap.exr │ │ └── remap.frag └── src │ ├── main.cpp │ ├── ofApp.cpp │ ├── ofApp.h │ └── ofxRemap.h ├── ShaderBuilder ├── bin │ └── data │ │ └── shader.fs └── src │ ├── main.cpp │ └── ofAutoShader.h ├── SignalPlot └── src │ ├── LinePlot.h │ ├── Markers.h │ ├── PlotUtilities.h │ ├── ZoomableRegion.h │ └── main.cpp ├── SignalPlotLomb └── src │ ├── LinePlot.h │ ├── PlotUtilities.h │ ├── ZoomableRegion.h │ └── main.cpp ├── SignalPlotWithScale └── src │ ├── LinePlot.h │ ├── Markers.h │ ├── PlotUtilities.h │ ├── ZoomableRegion.h │ └── main.cpp ├── SimpleParticleSystem └── src │ ├── Force.cpp │ ├── Force.h │ ├── Particle.cpp │ ├── Particle.h │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── SphericalEnvironmentMapping ├── Project.xcconfig ├── bin │ └── data │ │ ├── matcap.jpg │ │ ├── mesh.ply │ │ ├── sem.frag │ │ └── sem.vert ├── ofApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── ofApp.xccheckout │ └── xcshareddata │ │ └── xcschemes │ │ ├── ofApp Debug.xcscheme │ │ └── ofApp Release.xcscheme ├── openFrameworks-Info.plist └── src │ └── main.cpp ├── StackedPlot └── src │ ├── StackedPlot.cpp │ ├── StackedPlot.h │ └── main.cpp ├── TextInputExample └── src │ └── main.cpp ├── TileMatching └── src │ └── main.cpp ├── Timelapse └── src │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── TriangleTriangle └── src │ └── main.cpp ├── Verlet └── src │ └── main.cpp ├── VideoRecorder ├── ofxQTKitVideoGrabber │ ├── ofxQTKitVideoGrabber.h │ └── ofxQTKitVideoGrabber.mm └── src │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── VideoShuffler ├── bin │ └── data │ │ ├── GravuConBol │ │ ├── GravuConLig │ │ ├── settings.xml │ │ ├── videos.xml │ │ └── videos │ │ └── .gitkeep └── src │ ├── DelayTimer.h │ ├── main.cpp │ ├── ofApp.cpp │ └── ofApp.h ├── Worm └── src │ └── main.cpp ├── license.md ├── readme.md └── videoInputExample └── src ├── Camera.cpp ├── Camera.h ├── main.cpp ├── ofApp.cpp └── ofApp.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.depend 2 | *.layout 3 | *.mode*v3 4 | *.pbxuser 5 | *.app* 6 | *.DS_* 7 | 8 | .svn/ 9 | obj/ 10 | bin/ 11 | build/ 12 | !data/ 13 | xcuserdata/ 14 | 15 | SharedData/ -------------------------------------------------------------------------------- /BarnesHut/src/Body.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Body : public ofVec2f { 4 | public: 5 | float mass; 6 | Body(float x = 0, float y = 0, float mass = 0) : 7 | ofVec2f(x, y), 8 | mass(mass) { 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /BarnesHut/src/Particle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Body.h" 4 | #include "ofGraphics.h" 5 | 6 | class Particle : public Body { 7 | public: 8 | ofVec2f force; 9 | ofVec2f velocity; 10 | float radius; 11 | Particle(float _x, float _y, float _mass, 12 | float _xv = 0, float _yv = 0) : 13 | Body(_x, _y, _mass), 14 | velocity(_xv, _yv) { 15 | radius = sqrtf(mass); 16 | } 17 | void updatePosition(float dt, float friction = 1) { 18 | ofVec2f prevVelocity = velocity; 19 | ofVec2f acceleration = force / mass; 20 | velocity += dt * acceleration; 21 | velocity *= friction; 22 | *this += dt * prevVelocity.interpolate(velocity, .5); 23 | } 24 | void zeroForce() { 25 | force.set(0, 0); 26 | } 27 | void draw() const { 28 | //ofRect(x, y, mass, mass); 29 | ofDrawCircle(x, y, radius); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /BarnesHut/src/ParticleSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Tree.h" 4 | #include "Particle.h" 5 | #include "Spring.h" 6 | 7 | //#define USE_GCD 8 | 9 | #ifdef USE_GCD 10 | #define LOOP_BEGIN(i, n) dispatch_apply(n, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(size_t i) 11 | #else 12 | #define LOOP_BEGIN(i, n) for(int i = 0; i < n; i++) 13 | #endif 14 | 15 | #ifdef USE_GCD 16 | #define LOOP_END() ) 17 | #else 18 | #define LOOP_END() 19 | #endif 20 | 21 | class SpringParticleMatch { 22 | protected: 23 | shared_ptr particle; 24 | public: 25 | SpringParticleMatch(shared_ptr& particle) 26 | :particle(particle) { } 27 | bool operator()(const shared_ptr& spring) { 28 | return spring->a == particle || 29 | spring->b == particle; 30 | } 31 | }; 32 | 33 | template 34 | void eraseRemove(vector& x, const T& y) { 35 | x.erase(remove(x.begin(), x.end(), y), x.end()); 36 | } 37 | 38 | class ParticleSystem { 39 | protected: 40 | bool exact; 41 | float gravitationalConstant; 42 | float timeStep; 43 | float friction; 44 | int iterations; 45 | float centering; 46 | 47 | vector > particles; 48 | vector > springs; 49 | 50 | void zeroForces() { 51 | int n = particles.size(); 52 | LOOP_BEGIN(i, n) { 53 | particles[i]->zeroForce(); 54 | } LOOP_END(); 55 | } 56 | void sumGravityApproximate() { 57 | Tree tree; 58 | tree.build(particles); 59 | 60 | // ofPushStyle(); 61 | // ofNoFill(); 62 | // ofSetColor(255); 63 | // tree.draw(); 64 | // ofPopStyle(); 65 | 66 | int n = particles.size(); 67 | LOOP_BEGIN(i, n) { 68 | tree.sumForces(particles[i]); 69 | } LOOP_END(); 70 | } 71 | void sumGravityExact() { 72 | int n = particles.size(); 73 | LOOP_BEGIN(i, n) { 74 | Particle& a = *particles[i]; 75 | for(int j = 0; j < n; j++) { 76 | if(i != j) { 77 | const Particle& b = *particles[j]; 78 | ofVec2f d = b - a; 79 | float r = d.length(); 80 | r = MAX(r, (a.radius + b.radius)); 81 | float mor3 = b.mass / (r * r * r); 82 | a.force += d * mor3; 83 | } 84 | } 85 | } LOOP_END(); 86 | } 87 | void applyGravity() { 88 | int n = particles.size(); 89 | LOOP_BEGIN(i, n) { 90 | Particle& cur = *particles[i]; 91 | cur.force *= cur.mass * gravitationalConstant; 92 | } LOOP_END(); 93 | } 94 | void applyCentering() { 95 | int n = particles.size(); 96 | LOOP_BEGIN(i, n) { 97 | Particle& cur = *particles[i]; 98 | float length = cur.length(); 99 | cur.force += cur.mass * centering * -cur; 100 | } LOOP_END(); 101 | } 102 | void applySprings() { 103 | int n = springs.size(); 104 | LOOP_BEGIN(i, n) { 105 | springs[i]->update(); 106 | } LOOP_END(); 107 | } 108 | void updatePositions(float dt) { 109 | int n = particles.size(); 110 | LOOP_BEGIN(i, n) { 111 | particles[i]->updatePosition(dt, friction); 112 | } LOOP_END(); 113 | } 114 | public: 115 | ParticleSystem() { 116 | this->exact = true; 117 | this->gravitationalConstant = 1; 118 | this->timeStep = 1; 119 | this->friction = 1; 120 | this->iterations = 1; 121 | } 122 | void setExact(bool exact) { 123 | this->exact = exact; 124 | } 125 | void setGravitationalConstant(float gravitationalConstant) { 126 | this->gravitationalConstant = gravitationalConstant; 127 | } 128 | void setTimeStep(float timeStep) { 129 | this->timeStep = timeStep; 130 | } 131 | void setIterations(int iterations) { 132 | this->iterations = iterations; 133 | } 134 | void setFriction(float friction) { 135 | this->friction = friction; 136 | } 137 | void setCentering(float centering) { 138 | this->centering = centering; 139 | } 140 | shared_ptr& getParticle(int i) { 141 | return particles[i]; 142 | } 143 | shared_ptr addParticle(const Particle& particle) { 144 | particles.push_back(shared_ptr(new Particle(particle))); 145 | return particles.back(); 146 | } 147 | void removeParticle(int i) { 148 | if(!particles.empty()) { 149 | shared_ptr& cur = particles[i]; 150 | ofRemove(springs, SpringParticleMatch(cur)); 151 | particles.erase(particles.begin() + i); 152 | } 153 | } 154 | void removeParticle(shared_ptr& particle) { 155 | eraseRemove(particles, particle); 156 | } 157 | unsigned int getParticleCount() { 158 | return particles.size(); 159 | } 160 | shared_ptr& getSpring(int i) { 161 | return springs[i]; 162 | } 163 | void addSpring(int i, int j, float stiffness, float distance = 0) { 164 | if(i < particles.size() && j < particles.size()) { 165 | addSpring(particles[i], particles[j], stiffness, distance); 166 | } 167 | } 168 | void addSpring(shared_ptr& a, shared_ptr& b, float stiffness, float distance = 0) { 169 | if(a != b) { 170 | springs.push_back(shared_ptr(new Spring(a, b, stiffness, distance))); 171 | } 172 | } 173 | void removeSpring(int i) { 174 | if(!springs.empty()) { 175 | springs.erase(springs.begin() + i); 176 | } 177 | } 178 | void removeSpring(shared_ptr& spring) { 179 | (springs, spring); 180 | } 181 | unsigned int getSpringCount() { 182 | return springs.size(); 183 | } 184 | void clear() { 185 | springs.clear(); 186 | particles.clear(); 187 | } 188 | void update() { 189 | float dt = timeStep / iterations; 190 | for(int i = 0; i < iterations; i++) { 191 | zeroForces(); 192 | if(exact) { 193 | sumGravityExact(); 194 | } else { 195 | sumGravityApproximate(); 196 | } 197 | applyGravity(); 198 | if(centering != 0) { 199 | applyCentering(); 200 | } 201 | applySprings(); 202 | updatePositions(dt); 203 | } 204 | } 205 | void draw() const { 206 | ofPushStyle(); 207 | int i = 0; 208 | for(const shared_ptr& particle : particles) { 209 | ofSetColor(ofColor::fromHsb(((i++)%25)*10, 255, 255)); 210 | particle->draw(); 211 | } 212 | ofSetColor(255, 64); 213 | for(const shared_ptr& spring : springs) { 214 | spring->draw(); 215 | } 216 | ofPopStyle(); 217 | } 218 | }; 219 | -------------------------------------------------------------------------------- /BarnesHut/src/Spring.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Particle.h" 4 | #include "ofGraphics.h" 5 | 6 | class Spring { 7 | public: 8 | shared_ptr a; 9 | shared_ptr b; 10 | float length, stiffness; 11 | Spring(shared_ptr& a, shared_ptr& b, float stiffness, float length = 0) 12 | :a(a) 13 | ,b(b) 14 | ,stiffness(stiffness) { 15 | if(length == 0) { 16 | length = a->distance(*b); 17 | } 18 | this->length = length; 19 | } 20 | void update() { 21 | ofVec2f normal = *b - *a; 22 | float curLength = MAX(1, normal.length()); 23 | float dx = length - curLength; 24 | dx /= length; 25 | dx = 1 / (1 + exp(-dx)) - .5; 26 | normal *= (stiffness / curLength); 27 | a->force += normal * -dx; 28 | b->force += normal * +dx; 29 | } 30 | void draw() const { 31 | ofDrawLine(*a, *b); 32 | } 33 | }; -------------------------------------------------------------------------------- /BarnesHut/src/Tree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Particle.h" 4 | 5 | #define maxParticles 4 6 | 7 | class Tree : public Body { 8 | public: 9 | bool empty; 10 | int nParticles; 11 | Particle* particles[maxParticles]; 12 | bool hasChildren; 13 | shared_ptr nw, ne, sw, se; 14 | float minX, minY, midX, midY, maxX, maxY, side, diag; 15 | 16 | Tree() : 17 | empty(true), 18 | nParticles(0), 19 | hasChildren(false), 20 | minX(0), minY(0), 21 | midX(0), midY(0), 22 | maxX(0), maxY(0) { 23 | } 24 | Tree(float _minX, float _minY, float _maxX, float _maxY) : 25 | empty(true), 26 | nParticles(0), 27 | hasChildren(false), 28 | minX(_minX), minY(_minY), 29 | maxX(_maxX), maxY(_maxY) { 30 | setMid(); 31 | } 32 | void setMid() { 33 | midX = (minX + maxX) / 2; 34 | midY = (minY + maxY) / 2; 35 | side = maxX - minX; 36 | diag = sqrt(2 * side * side); 37 | } 38 | void findBoundaries(vector >& all) { 39 | minX = all[0]->x; 40 | minY = all[0]->y; 41 | maxX = minX; 42 | maxY = minY; 43 | for(shared_ptr& particle : all) { 44 | if(particle->x < minX) 45 | minX = particle->x; 46 | if(particle->y < minY) 47 | minY = particle->y; 48 | if(particle->x > maxX) 49 | maxX = particle->x; 50 | if(particle->y > maxY) 51 | maxY = particle->y; 52 | } 53 | setMid(); 54 | } 55 | void squareBoundaries() { 56 | float centerX = (minX + maxX) / 2; 57 | float centerY = (minY + maxY) / 2; 58 | float diffX = maxX - minX; 59 | float diffY = maxY - minY; 60 | float halfSide = max(diffX, diffY) / 2; 61 | minX = centerX - halfSide; 62 | maxX = centerX + halfSide; 63 | minY = centerY - halfSide; 64 | maxY = centerY + halfSide; 65 | setMid(); 66 | } 67 | void add(Particle& cur) { 68 | if(hasChildren) { 69 | if(cur.x < midX) { 70 | if(cur.y < midY) { 71 | nw->add(cur); 72 | } else { 73 | sw->add(cur); 74 | } 75 | } else { 76 | if(cur.y < midY) { 77 | ne->add(cur); 78 | } else { 79 | se->add(cur); 80 | } 81 | } 82 | } else { 83 | if(nParticles < maxParticles) { 84 | particles[nParticles] = &cur; 85 | nParticles++; 86 | empty = false; 87 | } else { 88 | nw = shared_ptr(new Tree(minX, minY, midX, midY)); 89 | ne = shared_ptr(new Tree(midX, minY, maxX, midY)); 90 | sw = shared_ptr(new Tree(minX, midY, midX, maxY)); 91 | se = shared_ptr(new Tree(midX, midY, maxX, maxY)); 92 | hasChildren = true; 93 | for(int i = 0; i < nParticles; i++) 94 | add(*particles[i]); 95 | nParticles = 0; 96 | add(cur); 97 | } 98 | } 99 | } 100 | void addAll(vector >& all) { 101 | for(shared_ptr& particle : all) { 102 | add(*particle.get()); 103 | } 104 | } 105 | void findCenterOfMass() { 106 | if(hasChildren) { 107 | nw->findCenterOfMass(); 108 | ne->findCenterOfMass(); 109 | sw->findCenterOfMass(); 110 | se->findCenterOfMass(); 111 | mass += 112 | nw->mass + 113 | ne->mass + 114 | sw->mass + 115 | se->mass; 116 | x += 117 | nw->x * nw->mass + 118 | ne->x * ne->mass + 119 | sw->x * sw->mass + 120 | se->x * se->mass; 121 | x /= mass; 122 | y += 123 | nw->y * nw->mass + 124 | ne->y * ne->mass + 125 | sw->y * sw->mass + 126 | se->y * se->mass; 127 | y /= mass; 128 | } else { 129 | if(nParticles) { 130 | for(int i = 0; i < nParticles; i++) { 131 | Particle& cur = *particles[i]; 132 | x += cur.x * cur.mass; 133 | y += cur.y * cur.mass; 134 | mass += cur.mass; 135 | } 136 | x /= mass; 137 | y /= mass; 138 | } 139 | } 140 | } 141 | void build(vector >& particles) { 142 | if(!particles.empty()) { 143 | findBoundaries(particles); 144 | squareBoundaries(); 145 | addAll(particles); 146 | findCenterOfMass(); 147 | } 148 | } 149 | void sumForces(shared_ptr& cur) const { 150 | if(!empty) { 151 | ofVec2f d = *this - *cur; 152 | if(d.x > +side || d.x < -side || 153 | d.y > +side || d.y < -side) { 154 | // far away, approximate 155 | float r = d.length(); 156 | d *= mass / (r * r * r); 157 | cur->force += d; 158 | } else if(nParticles) { 159 | // close, sum particles 160 | for(int i = 0; i < nParticles; i++) { 161 | const Particle& target = *particles[i]; 162 | // exact calculations 163 | if(target != *cur) { 164 | d = target - *cur; 165 | float r = d.length(); 166 | r = MAX(r, MAX(target.radius, cur->radius)); 167 | d *= target.mass / (r * r * r); 168 | cur->force += d; 169 | } 170 | // ofDrawLine(cur.x, cur.y, this->x, this->y); 171 | } 172 | } else { 173 | // too close, go deeper 174 | nw->sumForces(cur); 175 | ne->sumForces(cur); 176 | sw->sumForces(cur); 177 | se->sumForces(cur); 178 | } 179 | } 180 | } 181 | void draw() { 182 | ofDrawRectangle(minX, minY, maxX - minX, maxY - minY); 183 | if(hasChildren) { 184 | nw->draw(); 185 | ne->draw(); 186 | sw->draw(); 187 | se->draw(); 188 | } 189 | } 190 | }; 191 | -------------------------------------------------------------------------------- /BarnesHut/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ParticleSystem.h" 3 | 4 | class ofApp : public ofBaseApp { 5 | public: 6 | ParticleSystem ps; 7 | 8 | void setup(){ 9 | ofBackground(0); 10 | 11 | ps.clear(); 12 | ps.setExact(false); 13 | ps.setTimeStep(.2); 14 | ps.setFriction(.9); 15 | ps.setCentering(.1); 16 | ps.setGravitationalConstant(-1000); 17 | ps.setIterations(10); 18 | } 19 | 20 | void draw(){ 21 | ofPushMatrix(); 22 | ofFill(); 23 | ofTranslate(ofGetWidth() / 2, ofGetHeight() / 2); 24 | 25 | for(int i = 0; i < 10; i++) { 26 | int choice = ofRandom(3); 27 | switch(choice) { 28 | case 0: 29 | if(ps.getParticleCount() < 2000) { 30 | ps.addParticle(Particle(ofRandomWidth() - ofGetWidth() / 2, ofRandomHeight() - ofGetHeight() / 2, 1, 0, 0)); 31 | } else { 32 | ps.removeParticle(ofRandom(ps.getParticleCount())); 33 | } 34 | break; 35 | case 2: 36 | if(ps.getSpringCount() > ps.getParticleCount()) { 37 | ps.removeSpring(ofRandom(ps.getSpringCount())); 38 | } else { 39 | ps.addSpring(ofRandom(ps.getParticleCount()), ofRandom(ps.getParticleCount()), 2000, 200); 40 | } 41 | break; 42 | } 43 | } 44 | ps.update(); 45 | 46 | ps.draw(); 47 | ofPopMatrix(); 48 | 49 | ofSetColor(255); 50 | ofDrawBitmapString(ofToString((int) ofGetFrameRate()) + " fps @ " + ofToString((int) ps.getParticleCount()), 32, 52); 51 | } 52 | 53 | void keyPressed(int key){ 54 | if(key == 'p') 55 | ofSaveFrame(); 56 | if(key == 'r') 57 | setup(); 58 | } 59 | 60 | void mousePressed(int x, int y, int button){ 61 | float mass = 1;//ofRandom(1, 4); 62 | Particle particle(x - ofGetWidth() / 2, y - ofGetHeight() / 2, mass); 63 | ps.addParticle(particle); 64 | } 65 | }; 66 | 67 | int main() { 68 | ofSetupOpenGL(1680, 1050, OF_FULLSCREEN); 69 | ofRunApp(new ofApp()); 70 | } 71 | -------------------------------------------------------------------------------- /BinnedParticleSystem/src/BinnedParticle.cpp: -------------------------------------------------------------------------------- 1 | #include "BinnedParticle.h" 2 | 3 | #include "ofGraphics.h" 4 | 5 | BinnedParticle::BinnedParticle(float x, float y, float xv, float yv) : 6 | x(x), y(y), 7 | xv(xv), yv(yv) { 8 | } 9 | 10 | void BinnedParticle::updatePosition(float timeStep) { 11 | // f = ma, m = 1, f = a, v = int(a) 12 | xv += xf * timeStep; 13 | yv += yf * timeStep; 14 | x += xv * timeStep; 15 | y += yv * timeStep; 16 | } 17 | 18 | void BinnedParticle::resetForce() { 19 | xf = 0; 20 | yf = 0; 21 | } 22 | 23 | void BinnedParticle::bounceOffWalls(float left, float top, float right, float bottom, float damping) { 24 | bool collision = false; 25 | 26 | if (x > right){ 27 | x = right; 28 | xv *= -1; 29 | collision = true; 30 | } else if (x < left){ 31 | x = left; 32 | xv *= -1; 33 | collision = true; 34 | } 35 | 36 | if (y > bottom){ 37 | y = bottom; 38 | yv *= -1; 39 | collision = true; 40 | } else if (y < top){ 41 | y = top; 42 | yv *= -1; 43 | collision = true; 44 | } 45 | 46 | if (collision == true){ 47 | xv *= damping; 48 | yv *= damping; 49 | } 50 | } 51 | 52 | void BinnedParticle::addDampingForce(float damping) { 53 | xf -= xv * damping; 54 | yf -= yv * damping; 55 | } 56 | 57 | void BinnedParticle::draw() { 58 | glVertex2f(x, y); 59 | } -------------------------------------------------------------------------------- /BinnedParticleSystem/src/BinnedParticle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class BinnedParticle { 6 | public: 7 | float x, y; 8 | float xv, yv; 9 | float xf, yf; 10 | BinnedParticle(float x = 0, float y = 0, float xv = 0, float yv = 0); 11 | void updatePosition(float timeStep); 12 | void resetForce(); 13 | void bounceOffWalls(float left, float top, float right, float bottom, float damping = .3); 14 | void addDampingForce(float damping = .01); 15 | void draw(); 16 | }; 17 | -------------------------------------------------------------------------------- /BinnedParticleSystem/src/BinnedParticleSystem.cpp: -------------------------------------------------------------------------------- 1 | #include "BinnedParticleSystem.h" 2 | 3 | BinnedParticleSystem::BinnedParticleSystem() : 4 | timeStep(100) { 5 | } 6 | 7 | void BinnedParticleSystem::setup(int width, int height, int k) { 8 | this->width = width; 9 | this->height = height; 10 | this->k = k; 11 | binSize = 1 << k; 12 | xBins = (int) ceilf((float) width / (float) binSize); 13 | yBins = (int) ceilf((float) height / (float) binSize); 14 | bins.resize(xBins * yBins); 15 | } 16 | 17 | void BinnedParticleSystem::setTimeStep(float timeStep) { 18 | this->timeStep = timeStep; 19 | } 20 | 21 | void BinnedParticleSystem::add(BinnedParticle particle) { 22 | particles.push_back(particle); 23 | } 24 | 25 | unsigned BinnedParticleSystem::size() const { 26 | return particles.size(); 27 | } 28 | 29 | BinnedParticle& BinnedParticleSystem::operator[](unsigned i) { 30 | return particles[i]; 31 | } 32 | 33 | vector BinnedParticleSystem::getNeighbors(BinnedParticle& particle, float radius) { 34 | return getNeighbors(particle.x, particle.y, radius); 35 | } 36 | 37 | vector BinnedParticleSystem::getNeighbors(float x, float y, float radius) { 38 | vector region = getRegion( 39 | (int) (x - radius), 40 | (int) (y - radius), 41 | (int) (x + radius), 42 | (int) (y + radius)); 43 | vector neighbors; 44 | int n = region.size(); 45 | float xd, yd, rsq, maxrsq; 46 | maxrsq = radius * radius; 47 | for(int i = 0; i < n; i++) { 48 | BinnedParticle& cur = *region[i]; 49 | xd = cur.x - x; 50 | yd = cur.y - y; 51 | rsq = xd * xd + yd * yd; 52 | if(rsq < maxrsq) 53 | neighbors.push_back(region[i]); 54 | } 55 | return neighbors; 56 | } 57 | 58 | vector BinnedParticleSystem::getRegion(unsigned minX, unsigned minY, unsigned maxX, unsigned maxY) { 59 | vector region; 60 | back_insert_iterator< vector > back = back_inserter(region); 61 | unsigned minXBin = minX >> k; 62 | unsigned maxXBin = maxX >> k; 63 | unsigned minYBin = minY >> k; 64 | unsigned maxYBin = maxY >> k; 65 | maxXBin++; 66 | maxYBin++; 67 | if(maxXBin > xBins) 68 | maxXBin = xBins; 69 | if(maxYBin > yBins) 70 | maxYBin = yBins; 71 | for(int y = minYBin; y < maxYBin; y++) { 72 | for(int x = minXBin; x < maxXBin; x++) { 73 | vector& cur = bins[y * xBins + x]; 74 | copy(cur.begin(), cur.end(), back); 75 | } 76 | } 77 | return region; 78 | } 79 | 80 | void BinnedParticleSystem::setupForces() { 81 | int n = bins.size(); 82 | for(int i = 0; i < n; i++) { 83 | bins[i].clear(); 84 | } 85 | n = particles.size(); 86 | unsigned xBin, yBin, bin; 87 | for(int i = 0; i < n; i++) { 88 | BinnedParticle& cur = particles[i]; 89 | cur.resetForce(); 90 | xBin = ((unsigned) cur.x) >> k; 91 | yBin = ((unsigned) cur.y) >> k; 92 | bin = yBin * xBins + xBin; 93 | if(xBin < xBins && yBin < yBins) 94 | bins[bin].push_back(&cur); 95 | } 96 | } 97 | 98 | void BinnedParticleSystem::addRepulsionForce(const BinnedParticle& particle, float radius, float scale) { 99 | addRepulsionForce(particle.x, particle.y, radius, scale); 100 | } 101 | 102 | void BinnedParticleSystem::addRepulsionForce(float x, float y, float radius, float scale) { 103 | addForce(x, y, radius, scale); 104 | } 105 | 106 | void BinnedParticleSystem::addAttractionForce(const BinnedParticle& particle, float radius, float scale) { 107 | addAttractionForce(particle.x, particle.y, radius, scale); 108 | } 109 | 110 | void BinnedParticleSystem::addAttractionForce(float x, float y, float radius, float scale) { 111 | addForce(x, y, radius, -scale); 112 | } 113 | 114 | void BinnedParticleSystem::addForce(const BinnedParticle& particle, float radius, float scale) { 115 | addForce(particle.x, particle.y, radius, -scale); 116 | } 117 | 118 | void BinnedParticleSystem::addForce(float targetX, float targetY, float radius, float scale) { 119 | float minX = targetX - radius; 120 | float minY = targetY - radius; 121 | float maxX = targetX + radius; 122 | float maxY = targetY + radius; 123 | if(minX < 0) 124 | minX = 0; 125 | if(minY < 0) 126 | minY = 0; 127 | unsigned minXBin = ((unsigned) minX) >> k; 128 | unsigned minYBin = ((unsigned) minY) >> k; 129 | unsigned maxXBin = ((unsigned) maxX) >> k; 130 | unsigned maxYBin = ((unsigned) maxY) >> k; 131 | maxXBin++; 132 | maxYBin++; 133 | if(maxXBin > xBins) 134 | maxXBin = xBins; 135 | if(maxYBin > yBins) 136 | maxYBin = yBins; 137 | float xd, yd, length, maxrsq; 138 | #ifdef USE_INVSQRT 139 | float xhalf; 140 | int lengthi; 141 | #else 142 | float effect; 143 | #endif 144 | maxrsq = radius * radius; 145 | for(int y = minYBin; y < maxYBin; y++) { 146 | for(int x = minXBin; x < maxXBin; x++) { 147 | vector& curBin = bins[y * xBins + x]; 148 | int n = curBin.size(); 149 | for(int i = 0; i < n; i++) { 150 | BinnedParticle& curBinnedParticle = *(curBin[i]); 151 | xd = curBinnedParticle.x - targetX; 152 | yd = curBinnedParticle.y - targetY; 153 | length = xd * xd + yd * yd; 154 | if(length > 0 && length < maxrsq) { 155 | #ifdef DRAW_FORCES 156 | glVertex2f(targetX, targetY); 157 | glVertex2f(curBinnedParticle.x, curBinnedParticle.y); 158 | #endif 159 | #ifdef USE_INVSQRT 160 | xhalf = 0.5f * length; 161 | lengthi = *(int*) &length; 162 | lengthi = 0x5f3759df - (lengthi >> 1); 163 | length = *(float*) &lengthi; 164 | length *= 1.5f - xhalf * length * length; 165 | xd *= length; 166 | yd *= length; 167 | length *= radius; 168 | length = 1 / length; 169 | length = (1 - length); 170 | #ifdef USE_SMOOTH_FORCES 171 | length = smoothForce(length); 172 | #endif 173 | length *= scale; 174 | xd *= length; 175 | yd *= length; 176 | curBinnedParticle.xf += xd; 177 | curBinnedParticle.yf += yd; 178 | #else 179 | length = sqrtf(length); 180 | #ifdef USE_SMOOTH_FORCES 181 | length = smoothForce(length); 182 | #endif 183 | xd /= length; 184 | yd /= length; 185 | effect = (1 - (length / radius)) * scale; 186 | curBinnedParticle.xf += xd * effect; 187 | curBinnedParticle.yf += yd * effect; 188 | #endif 189 | } 190 | } 191 | } 192 | } 193 | } 194 | 195 | void BinnedParticleSystem::update(float lastTimeStep) { 196 | int n = particles.size(); 197 | float curTimeStep = lastTimeStep * timeStep; 198 | for(int i = 0; i < n; i++) { 199 | particles[i].updatePosition(curTimeStep); 200 | } 201 | } 202 | 203 | void BinnedParticleSystem::draw() { 204 | int n = particles.size(); 205 | glBegin(GL_POINTS); 206 | for(int i = 0; i < n; i++) 207 | particles[i].draw(); 208 | glEnd(); 209 | } 210 | 211 | int BinnedParticleSystem::getWidth() const { 212 | return width; 213 | } 214 | 215 | int BinnedParticleSystem::getHeight() const { 216 | return height; 217 | } 218 | -------------------------------------------------------------------------------- /BinnedParticleSystem/src/BinnedParticleSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BinnedParticle.h" 4 | 5 | #define DRAW_FORCES 6 | #define USE_INVSQRT 7 | #define USE_SMOOTH_FORCES 8 | 9 | class BinnedParticleSystem { 10 | protected: 11 | float timeStep; 12 | vector particles; 13 | vector< vector > bins; 14 | int width, height, k, xBins, yBins, binSize; 15 | 16 | public: 17 | BinnedParticleSystem(); 18 | 19 | void setup(int width, int height, int k); 20 | void setTimeStep(float timeStep); 21 | 22 | void add(BinnedParticle particle); 23 | vector getNeighbors(BinnedParticle& particle, float radius); 24 | vector getNeighbors(float x, float y, float radius); 25 | vector getRegion(unsigned minX, unsigned minY, unsigned maxX, unsigned maxY); 26 | unsigned size() const; 27 | BinnedParticle& operator[](unsigned i); 28 | 29 | void setupForces(); 30 | void addRepulsionForce(const BinnedParticle& particle, float radius, float scale); 31 | void addRepulsionForce(float x, float y, float radius, float scale); 32 | void addAttractionForce(const BinnedParticle& particle, float radius, float scale); 33 | void addAttractionForce(float x, float y, float radius, float scale); 34 | void addForce(const BinnedParticle& particle, float radius, float scale); 35 | void addForce(float x, float y, float radius, float scale); 36 | void update(float lastTimeStep); 37 | 38 | void draw(); 39 | 40 | int getWidth() const; 41 | int getHeight() const; 42 | }; 43 | 44 | inline float InvSqrt(float x){ 45 | float xhalf = 0.5f * x; 46 | int i = *(int*)&x; // store floating-point bits in integer 47 | i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method 48 | x = *(float*)&i; // convert new bits into float 49 | x = x*(1.5f - xhalf*x*x); // One round of Newton's method 50 | return x; 51 | } 52 | 53 | inline float smoothForce(float x) { 54 | const static float sharpness = 1; 55 | return 1. / (1. + expf((x - .5) * sharpness * -12)); 56 | } -------------------------------------------------------------------------------- /BinnedParticleSystem/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1024, 1024, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /BinnedParticleSystem/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup(){ 4 | ofSetVerticalSync(true); 5 | // this number describes how many bins are used 6 | // on my machine, 2 is the ideal number (2^2 = 4x4 pixel bins) 7 | // if this number is too high, binning is not effective 8 | // because the screen is not subdivided enough. if 9 | // it's too low, the bins take up so much memory as to 10 | // become inefficient. 11 | int binPower = 5; 12 | 13 | padding = 128; 14 | particleSystem.setup(ofGetWidth() + padding * 2, ofGetHeight() + padding * 2, binPower); 15 | 16 | kBinnedParticles = 800; 17 | for(int i = 0; i < kBinnedParticles; i++) { 18 | float x = ofRandom(0, ofGetWidth()) + padding; 19 | float y = ofRandom(0, ofGetHeight()) + padding; 20 | BinnedParticle particle(x, y, 0, 0); 21 | particleSystem.add(particle); 22 | } 23 | 24 | timeStep = 100; 25 | isMousePressed = false; 26 | slowMotion = true; 27 | particleNeighborhood = 64; 28 | particleRepulsion = .5; 29 | centerAttraction = .01; 30 | drawBalls = true; 31 | } 32 | 33 | void ofApp::update(){ 34 | } 35 | 36 | void ofApp::draw(){ 37 | ofBackground(0); 38 | 39 | particleSystem.setTimeStep(timeStep); 40 | 41 | ofSetColor(255); 42 | 43 | // do this once per frame 44 | particleSystem.setupForces(); 45 | 46 | ofPushMatrix(); 47 | ofTranslate(-padding, -padding); 48 | 49 | // apply per-particle forces 50 | if(!drawBalls) { 51 | ofSetLineWidth(8); 52 | glBegin(GL_LINES); // need GL_LINES if you want to draw inter-particle forces 53 | } 54 | for(int i = 0; i < particleSystem.size(); i++) { 55 | BinnedParticle& cur = particleSystem[i]; 56 | // global force on other particles 57 | particleSystem.addRepulsionForce(cur, particleNeighborhood, particleRepulsion); 58 | // forces on this particle 59 | cur.bounceOffWalls(0, 0, particleSystem.getWidth(), particleSystem.getHeight()); 60 | cur.addDampingForce(); 61 | } 62 | if(!drawBalls) { 63 | glEnd(); 64 | } 65 | 66 | // single-pass global forces 67 | particleSystem.addAttractionForce(particleSystem.getWidth() / 2, particleSystem.getHeight() / 2, particleSystem.getWidth() * 100, centerAttraction); 68 | if(isMousePressed) { 69 | particleSystem.addRepulsionForce(mouseX + padding, mouseY + padding, 200, 1); 70 | } 71 | particleSystem.update(ofGetLastFrameTime()); 72 | 73 | // draw all the particles 74 | if(drawBalls) { 75 | for(int i = 0; i < particleSystem.size(); i++) { 76 | ofCircle(particleSystem[i].x, particleSystem[i].y, particleNeighborhood * .3); 77 | } 78 | } 79 | 80 | ofPopMatrix(); 81 | 82 | ofSetColor(255); 83 | ofDrawBitmapString(ofToString(kBinnedParticles) + " particles", 32, 32); 84 | ofDrawBitmapString(ofToString((int) ofGetFrameRate()) + " fps", 32, 52); 85 | } 86 | 87 | void ofApp::keyPressed(int key){ 88 | if(key == 'p') { 89 | ofSaveScreen(ofToString(ofGetMinutes()) + "_" + ofToString(ofGetFrameNum()) + ".png"); 90 | } 91 | if(key == 's') { 92 | slowMotion = !slowMotion; 93 | if(slowMotion) 94 | timeStep = 10; 95 | else 96 | timeStep = 100; 97 | } 98 | if(key == 'b') { 99 | drawBalls = !drawBalls; 100 | } 101 | } 102 | 103 | void ofApp::mousePressed(int x, int y, int button){ 104 | isMousePressed = true; 105 | } 106 | 107 | void ofApp::mouseReleased(int x, int y, int button){ 108 | isMousePressed = false; 109 | } 110 | -------------------------------------------------------------------------------- /BinnedParticleSystem/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BinnedParticleSystem.h" 4 | #include "ofMain.h" 5 | 6 | class ofApp : public ofBaseApp{ 7 | public: 8 | void setup(); 9 | void update(); 10 | void draw(); 11 | 12 | void keyPressed (int key); 13 | void mousePressed(int x, int y, int button); 14 | void mouseReleased(int x, int y, int button); 15 | 16 | float timeStep; 17 | float particleNeighborhood, particleRepulsion; 18 | float centerAttraction; 19 | float padding; 20 | 21 | int kBinnedParticles; 22 | BinnedParticleSystem particleSystem; 23 | bool isMousePressed, slowMotion; 24 | 25 | bool drawBalls; 26 | }; 27 | -------------------------------------------------------------------------------- /Box2dContours/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | 4 | int main() { 5 | ofSetupOpenGL(1280, 720, OF_WINDOW); 6 | ofRunApp(new ofApp()); 7 | } 8 | -------------------------------------------------------------------------------- /Box2dContours/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | static int pts[] = {257,219,257,258,259,274,263,325,266,345,266,352,269,369,276,387,286,415,291,425,302,451,308,462,316,472,321,480,328,488,333,495,339,501,345,505,350,507,365,515,370,519,377,522,382,525,388,527,405,534,426,538,439,539,452,539,468,540,485,540,496,541,607,541,618,539,625,537,641,530,666,513,682,500,710,476,723,463,727,457,729,453,732,450,734,447,738,440,746,423,756,404,772,363,779,343,781,339,784,327,789,301,792,278,794,267,794,257,795,250,795,232,796,222,796,197,797,195,797,188,796,188}; 4 | static int nPts = 61*2; 5 | 6 | //-------------------------------------------------------------- 7 | void ofApp::setup() { 8 | ofBackground(0); 9 | 10 | bMouseForce = false; 11 | 12 | box2d.init(); 13 | box2d.setGravity(0, 10); 14 | box2d.createGround(); 15 | box2d.setFPS(60); 16 | box2d.registerGrabbing(); 17 | 18 | // lets add a contour to start 19 | for (int i=0; iaddAttractionPoint(mouseX, mouseY, strength); 45 | circles[i].get()->setDamping(damping, damping); 46 | } 47 | for(int i=0; iaddAttractionPoint(mouseX, mouseY, strength); 49 | customParticles[i].get()->setDamping(damping, damping); 50 | } 51 | 52 | } 53 | 54 | // remove shapes offscreen 55 | ofRemove(boxes, ofxBox2dBaseShape::shouldRemoveOffScreen); 56 | ofRemove(circles, ofxBox2dBaseShape::shouldRemoveOffScreen); 57 | ofRemove(customParticles, ofxBox2dBaseShape::shouldRemoveOffScreen); 58 | 59 | 60 | } 61 | 62 | 63 | //-------------------------------------------------------------- 64 | void ofApp::draw() { 65 | 66 | 67 | for(int i=0; idraw(); 71 | } 72 | 73 | for(int i=0; idraw(); 77 | } 78 | 79 | for(int i=0; idraw(); 81 | } 82 | 83 | ofNoFill(); 84 | ofSetColor(255); 85 | if(drawing.size()==0) { 86 | edgeLine.updateShape(); 87 | edgeLine.draw(); 88 | } 89 | else drawing.draw(); 90 | 91 | 92 | string info = ""; 93 | info += "Press [s] to draw a line strip ["+ofToString(bDrawLines)+"]\n"; 94 | info += "Press [f] to toggle Mouse Force ["+ofToString(bMouseForce)+"]\n"; 95 | info += "Press [c] for circles\n"; 96 | info += "Press [b] for blocks\n"; 97 | info += "Press [z] for custom particle\n"; 98 | info += "Total Bodies: "+ofToString(box2d.getBodyCount())+"\n"; 99 | info += "Total Joints: "+ofToString(box2d.getJointCount())+"\n\n"; 100 | info += "FPS: "+ofToString(ofGetFrameRate())+"\n"; 101 | ofSetColor(255); 102 | ofDrawBitmapString(info, 30, 30); 103 | } 104 | 105 | //-------------------------------------------------------------- 106 | void ofApp::keyPressed(int key) { 107 | 108 | if(key == 'c') { 109 | float r = ofRandom(4, 20); // a random radius 4px - 20px 110 | circles.push_back(shared_ptr(new ofxBox2dCircle)); 111 | circles.back().get()->setPhysics(3.0, 0.53, 0.1); 112 | circles.back().get()->setup(box2d.getWorld(), mouseX, mouseY, r); 113 | 114 | } 115 | 116 | if(key == 'b') { 117 | float w = ofRandom(4, 20); 118 | float h = ofRandom(4, 20); 119 | boxes.push_back(shared_ptr(new ofxBox2dRect)); 120 | boxes.back().get()->setPhysics(3.0, 0.53, 0.1); 121 | boxes.back().get()->setup(box2d.getWorld(), mouseX, mouseY, w, h); 122 | } 123 | 124 | if(key == 'z') { 125 | 126 | customParticles.push_back(shared_ptr(new CustomParticle)); 127 | CustomParticle * p = customParticles.back().get(); 128 | float r = ofRandom(3, 10); // a random radius 4px - 20px 129 | p->setPhysics(0.4, 0.53, 0.31); 130 | p->setup(box2d.getWorld(), mouseX, mouseY, r); 131 | p->color.r = ofRandom(20, 100); 132 | p->color.g = 0; 133 | p->color.b = ofRandom(150, 255); 134 | } 135 | 136 | if(key == 'f') bMouseForce = !bMouseForce; 137 | if(key == 't') ofToggleFullscreen(); 138 | 139 | 140 | 141 | } 142 | 143 | //-------------------------------------------------------------- 144 | void ofApp::keyReleased(int key) { 145 | 146 | } 147 | 148 | //-------------------------------------------------------------- 149 | void ofApp::mouseMoved(int x, int y ) { 150 | 151 | } 152 | 153 | //-------------------------------------------------------------- 154 | void ofApp::mouseDragged(int x, int y, int button) { 155 | drawing.addVertex(x, y); 156 | } 157 | 158 | //-------------------------------------------------------------- 159 | void ofApp::mousePressed(int x, int y, int button) { 160 | 161 | if(edgeLine.isBody()) { 162 | drawing.clear(); 163 | edgeLine.destroy(); 164 | } 165 | 166 | drawing.addVertex(x, y); 167 | } 168 | 169 | //-------------------------------------------------------------- 170 | void ofApp::mouseReleased(int x, int y, int button) { 171 | 172 | drawing.setClosed(false); 173 | drawing.simplify(); 174 | 175 | edgeLine.addVertexes(drawing); 176 | //polyLine.simplifyToMaxVerts(); // this is based on the max box2d verts 177 | edgeLine.setPhysics(0.0, 0.5, 0.5); 178 | edgeLine.create(box2d.getWorld()); 179 | 180 | drawing.clear(); 181 | 182 | } 183 | 184 | //-------------------------------------------------------------- 185 | void ofApp::resized(int w, int h){ 186 | 187 | } 188 | 189 | -------------------------------------------------------------------------------- /Box2dContours/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ofMain.h" 3 | #include "ofxBox2d.h" 4 | 5 | // ------------------------------------------------- a simple extended box2d circle 6 | class CustomParticle : public ofxBox2dCircle { 7 | 8 | public: 9 | CustomParticle() { 10 | } 11 | ofColor color; 12 | void draw() { 13 | float radius = getRadius(); 14 | 15 | glPushMatrix(); 16 | glTranslatef(getPosition().x, getPosition().y, 0); 17 | 18 | ofSetColor(color.r, color.g, color.b); 19 | ofFill(); 20 | ofCircle(0, 0, radius); 21 | 22 | glPopMatrix(); 23 | 24 | } 25 | }; 26 | 27 | 28 | // ------------------------------------------------- 29 | class ofApp : public ofBaseApp { 30 | 31 | public: 32 | 33 | void setup(); 34 | void update(); 35 | void draw(); 36 | 37 | void keyPressed(int key); 38 | void keyReleased(int key); 39 | void mouseMoved(int x, int y); 40 | void mouseDragged(int x, int y, int button); 41 | void mousePressed(int x, int y, int button); 42 | void mouseReleased(int x, int y, int button); 43 | void resized(int w, int h); 44 | 45 | float px, py; 46 | bool bDrawLines; 47 | bool bMouseForce; 48 | 49 | ofxBox2d box2d; // the box2d world 50 | ofPolyline drawing; // we draw with this first 51 | ofxBox2dEdge edgeLine; // the box2d edge/line shape (min 2 points) 52 | vector > circles; // default box2d circles 53 | vector > boxes; // defalut box2d rects 54 | vector > customParticles; // this is a custom particle the extends a cirlce 55 | 56 | 57 | }; 58 | -------------------------------------------------------------------------------- /BulgeEffect/bin/data/bulge.fs: -------------------------------------------------------------------------------- 1 | uniform sampler2DRect tex; 2 | uniform vec2 center; 3 | uniform float radius, shape; 4 | 5 | const float PI = 3.14159; 6 | 7 | void main() { 8 | vec2 offset = center - gl_TexCoord[0].xy; 9 | float mag = length(offset) / radius; 10 | //mag = 1. - pow(mag, shape); // simpler, c0, not c1 (better in the center) 11 | mag = (cos(PI * pow(min(mag, 1.), shape)) + 1.) / 2.; // complex , c0 and c1 (better near the edges) 12 | offset *= max(mag, 0.); 13 | //gl_FragColor = vec4(offset, 0., 1.); 14 | gl_FragColor = texture2DRect(tex, (gl_TexCoord[0].xy + offset)); 15 | } 16 | -------------------------------------------------------------------------------- /BulgeEffect/bin/data/bulge.vs: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | gl_FrontColor = gl_Color; 4 | gl_TexCoord[0] = gl_MultiTexCoord0; 5 | gl_Position = ftransform(); 6 | } 7 | -------------------------------------------------------------------------------- /BulgeEffect/bin/data/gradient-grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/openFrameworksDemos/ae7d2f9f43884ef54bec44420994c49e2bf8081a/BulgeEffect/bin/data/gradient-grid.png -------------------------------------------------------------------------------- /BulgeEffect/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(512, 512, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /BulgeEffect/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup() { 4 | ofSetVerticalSync(true); 5 | shader.load("bulge.vs", "bulge.fs"); 6 | //img.loadImage("gradient-grid.png"); 7 | img.initGrabber(640, 480); 8 | } 9 | 10 | void ofApp::update() { 11 | img.update(); 12 | } 13 | 14 | void ofApp::draw() { 15 | shader.begin(); 16 | shader.setUniform2f("center", mouseX, mouseY); 17 | shader.setUniform1f("radius", 256); 18 | shader.setUniform1f("shape", 1.5); 19 | shader.setUniformTexture("tex", img.getTextureReference(), 0); 20 | img.draw(0, 0); 21 | shader.end(); 22 | } 23 | -------------------------------------------------------------------------------- /BulgeEffect/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class ofApp : public ofBaseApp { 6 | public: 7 | void setup(); 8 | void update(); 9 | void draw(); 10 | 11 | ofShader shader; 12 | ofVideoGrabber img; 13 | }; 14 | -------------------------------------------------------------------------------- /BulgeEffectMulti/bin/data/applyBulge.fs: -------------------------------------------------------------------------------- 1 | uniform sampler2DRect tex, bulge; 2 | 3 | void main() { 4 | vec2 position = gl_TexCoord[0].xy; 5 | vec2 offset = 256. * (texture2DRect(bulge, position).xy - .5); 6 | gl_FragColor = texture2DRect(tex, position + offset); 7 | } 8 | -------------------------------------------------------------------------------- /BulgeEffectMulti/bin/data/blendBulge.fs: -------------------------------------------------------------------------------- 1 | uniform sampler2DRect base, tex; 2 | uniform float scale; 3 | 4 | void main() { 5 | vec3 a = texture2DRect(base, gl_FragCoord.xy).rgb - .5; 6 | vec3 b = texture2DRect(tex, gl_TexCoord[0].xy).rgb - .5; 7 | gl_FragColor = vec4(clamp((a + b * scale) + .5, 0., 1.), 1.); 8 | } 9 | -------------------------------------------------------------------------------- /BulgeEffectMulti/bin/data/generateBulge.fs: -------------------------------------------------------------------------------- 1 | uniform float scale, shape; 2 | const float PI = 3.14159; 3 | 4 | void main() { 5 | vec2 offset = vec2(scale, scale) - gl_FragCoord.xy; 6 | float mag = length(offset) / scale; 7 | //mag = 1. - pow(mag, shape); // simpler, c0, not c1 (better in the center) 8 | mag = (cos(PI * pow(min(mag, 1.), shape)) + 1.) / 2.; // complex , c0 and c1 (better near the edges) 9 | offset *= max(mag, 0.); 10 | gl_FragColor = vec4(offset / (2. * scale) + .5, 0., 1.); 11 | } 12 | -------------------------------------------------------------------------------- /BulgeEffectMulti/src/BulgeEffect.cpp: -------------------------------------------------------------------------------- 1 | #include "BulgeEffect.h" 2 | 3 | void BulgeEffect::setup(int width, int height, int resolution) { 4 | this->resolution = resolution; 5 | ofShader generateBulgeShader; 6 | generateBulgeShader.load("", "generateBulge.fs"); 7 | ofFbo::Settings settings; 8 | settings.width = resolution, settings.height = resolution; 9 | settings.internalformat = GL_RGB32F; 10 | bulge.allocate(settings); 11 | bulge.begin(); 12 | generateBulgeShader.begin(); 13 | generateBulgeShader.setUniform1f("scale", resolution / 2); 14 | generateBulgeShader.setUniform1f("shape", 1.5); 15 | ofRect(0, 0, resolution, resolution); 16 | generateBulgeShader.end(); 17 | bulge.end(); 18 | 19 | blendBulgeShader.load("", "blendBulge.fs"); 20 | settings.width = width, settings.height = height; 21 | blendBulge.allocate(settings); 22 | 23 | applyBulgeShader.load("", "applyBulge.fs"); 24 | 25 | needToClear = true; 26 | } 27 | 28 | void BulgeEffect::addBulge(float x, float y, float side) { 29 | if(needToClear) { 30 | clearBulges(); 31 | } 32 | 33 | blendBulge.begin(); 34 | blendBulgeShader.begin(); 35 | blendBulgeShader.setUniform1f("scale", side / resolution); 36 | bulge.setAnchorPercent(.5, .5); 37 | bulge.draw(x, y, side, side); 38 | blendBulgeShader.end(); 39 | blendBulge.end(); 40 | } 41 | 42 | void BulgeEffect::clearBulges() { 43 | blendBulgeShader.begin(); 44 | blendBulgeShader.setUniformTexture("base", blendBulge.getTextureReference(), 1); 45 | blendBulge.begin(); 46 | ofClear(128, 128, 0); 47 | blendBulgeShader.setUniformTexture("tex", bulge.getTextureReference(), 2); 48 | blendBulge.end(); 49 | blendBulgeShader.end(); 50 | needToClear = false; 51 | } 52 | 53 | void BulgeEffect::draw(ofTexture& tex, int x, int y) { 54 | applyBulgeShader.begin(); 55 | applyBulgeShader.setUniformTexture("bulge", blendBulge.getTextureReference(), 1); 56 | applyBulgeShader.setUniformTexture("tex", tex, 2); 57 | tex.draw(x, y); 58 | applyBulgeShader.end(); 59 | needToClear = true; 60 | } -------------------------------------------------------------------------------- /BulgeEffectMulti/src/BulgeEffect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class BulgeEffect { 6 | public: 7 | void setup(int width, int height, int resolution = 512); 8 | void addBulge(float x, float y, float side); 9 | void draw(ofTexture& tex, int x, int y); 10 | 11 | private: 12 | void clearBulges(); 13 | bool needToClear; 14 | 15 | int resolution; 16 | ofShader blendBulgeShader, applyBulgeShader; 17 | ofFbo bulge, blendBulge; 18 | }; 19 | -------------------------------------------------------------------------------- /BulgeEffectMulti/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1280, 720, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /BulgeEffectMulti/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup() { 4 | ofSetVerticalSync(true); 5 | cam.initGrabber(1280, 720); 6 | bulgeEffect.setup(1280, 720); 7 | } 8 | 9 | void ofApp::update() { 10 | cam.update(); 11 | } 12 | 13 | void ofApp::draw() { 14 | if(ofGetMousePressed()) { 15 | bulgeEffect.addBulge(ofGetWidth() / 2 - mouseX, ofGetHeight() / 2, mouseY); 16 | bulgeEffect.addBulge(ofGetWidth() / 2 + mouseX, ofGetHeight() / 2, mouseY); 17 | } else { 18 | ofSeedRandom(0); 19 | for(int i = 0; i < 64; i++) { 20 | float x = ofMap(sin(ofGetElapsedTimef() * ofRandom(3)), -1, 1, 0, ofGetWidth()); 21 | float y = ofMap(sin(ofGetElapsedTimef() * ofRandom(3)), -1, 1, 0, ofGetHeight()); 22 | bulgeEffect.addBulge(x, y, ofRandom(64, 512)); 23 | } 24 | } 25 | 26 | bulgeEffect.draw(cam.getTextureReference(), 0, 0); 27 | 28 | ofDrawBitmapStringHighlight(ofToString((int) ofGetFrameRate()), 10, 20); 29 | } 30 | -------------------------------------------------------------------------------- /BulgeEffectMulti/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "BulgeEffect.h" 5 | 6 | class ofApp : public ofBaseApp { 7 | public: 8 | void setup(); 9 | void update(); 10 | void draw(); 11 | 12 | BulgeEffect bulgeEffect; 13 | ofVideoGrabber cam; 14 | }; 15 | -------------------------------------------------------------------------------- /CircleRenderer/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | #define STRINGIFY(A) #A 4 | string shaderProgram = STRINGIFY( 5 | uniform sampler2DRect spriteTex; 6 | uniform sampler2DRect colorTex; 7 | uniform vec2 colorSize; 8 | void main(void) { 9 | vec4 spriteTxt = texture2DRect(spriteTex, gl_TexCoord[0].st); 10 | vec4 colorTxt = texture2DRect(colorTex, gl_Color.rg * colorSize); 11 | gl_FragColor = spriteTxt * colorTxt; 12 | } 13 | ); 14 | 15 | int n = 32, m = 24; 16 | int circleSize = 10; 17 | 18 | class ofApp : public ofBaseApp { 19 | public: 20 | ofFbo smaller; 21 | ofVideoPlayer video; 22 | ofImage circle; 23 | ofMesh mesh; 24 | ofShader shader; 25 | void setup() { 26 | shader.setupShaderFromSource(GL_FRAGMENT_SHADER, shaderProgram); 27 | shader.linkProgram(); 28 | video.loadMovie("fingers.mov"); 29 | video.play(); 30 | smaller.allocate(n, m, GL_RGB); 31 | circle.loadImage("circle.png"); 32 | mesh.setMode(OF_PRIMITIVE_TRIANGLES); 33 | ofVec2f smallSize(n, m); 34 | ofVec2f circleTexSize = circle.getTextureReference().getCoordFromPercent(1, 1); 35 | for(int i = 0; i < n; i++) { 36 | for(int j = 0; j < m; j++) { 37 | ofVec2f nwv(i, j), nev(i + 1, j), sev(i + 1, j + 1), swv(i, j + 1); 38 | mesh.addVertex(nwv); 39 | mesh.addVertex(nev); 40 | mesh.addVertex(sev); 41 | mesh.addVertex(nwv); 42 | mesh.addVertex(sev); 43 | mesh.addVertex(swv); 44 | 45 | ofVec2f nwt(0, 0), net(circleTexSize.x, 0), set(circleTexSize), swt(0, circleTexSize.y); 46 | mesh.addTexCoord(nwt); 47 | mesh.addTexCoord(net); 48 | mesh.addTexCoord(set); 49 | mesh.addTexCoord(nwt); 50 | mesh.addTexCoord(set); 51 | mesh.addTexCoord(swt); 52 | 53 | ofVec2f nwc(nwv / smallSize), nec(nev / smallSize), sec(sev / smallSize), swc(swv / smallSize); 54 | mesh.addColor(ofFloatColor(nwc.x, nwc.y, 0)); 55 | mesh.addColor(ofFloatColor(nec.x, nec.y, 0)); 56 | mesh.addColor(ofFloatColor(sec.x, sec.y, 0)); 57 | mesh.addColor(ofFloatColor(nwc.x, nwc.y, 0)); 58 | mesh.addColor(ofFloatColor(sec.x, sec.y, 0)); 59 | mesh.addColor(ofFloatColor(swc.x, swc.y, 0)); 60 | } 61 | } 62 | } 63 | void update() { 64 | video.update(); 65 | smaller.begin(); 66 | video.draw(0, 0, n, m); 67 | smaller.end(); 68 | } 69 | void draw() { 70 | ofBackground(0); 71 | //video.draw(0, 0); 72 | //smaller.draw(0, 0); 73 | ofScale(video.getWidth() / smaller.getWidth(), video.getHeight() / smaller.getHeight()); 74 | shader.begin(); 75 | shader.setUniformTexture("spriteTex", circle.getTextureReference(), 0); 76 | shader.setUniformTexture("colorTex", smaller.getTextureReference(), 1); 77 | ofVec2f smallerTexSize = smaller.getTextureReference().getCoordFromPercent(1, 1); 78 | shader.setUniform2f("colorSize", smallerTexSize.x, smallerTexSize.y); 79 | mesh.draw(); 80 | shader.end(); 81 | } 82 | }; 83 | 84 | int main( ){ 85 | ofSetupOpenGL(320, 240, OF_WINDOW); 86 | ofRunApp(new ofApp()); 87 | } 88 | -------------------------------------------------------------------------------- /ColorCube/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | class ofApp : public ofBaseApp { 4 | public: 5 | ofEasyCam cam; 6 | ofVideoGrabber vid; 7 | ofMesh mesh; 8 | int w = 1280, h = 720; 9 | int n = w * h; 10 | void setup() { 11 | vid.initGrabber(w, h); 12 | mesh.setMode(OF_PRIMITIVE_POINTS); 13 | mesh.addVertices(vector(n)); 14 | mesh.addColors(vector(n)); 15 | } 16 | void update() { 17 | vid.update(); 18 | if(vid.isFrameNew()) { 19 | unsigned char* pix = vid.getPixels(); 20 | int j = 0; 21 | for(int i = 0; i < n; i++) { 22 | unsigned char& r = pix[j++]; 23 | unsigned char& g = pix[j++]; 24 | unsigned char& b = pix[j++]; 25 | mesh.setVertex(i, ofVec3f(r, g, b)); 26 | mesh.setColor(i, ofColor(r, g, b)); 27 | } 28 | } 29 | } 30 | void draw() { 31 | ofBackground(0); 32 | cam.begin(); 33 | ofNoFill(); 34 | ofDrawBox(0, 0, 0, 256, 256, 256); 35 | ofTranslate(-128, -128, -128); 36 | mesh.draw(); 37 | cam.end(); 38 | } 39 | }; 40 | 41 | int main() { 42 | ofSetupOpenGL(1280, 720, OF_WINDOW); 43 | ofRunApp(new ofApp()); 44 | } 45 | -------------------------------------------------------------------------------- /Fading/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | float sinnp(float x) { 4 | return (sin(x * TWO_PI) + 1) / 2; 5 | } 6 | 7 | class Oscillator { 8 | private: 9 | float offset = 0; 10 | float fadeInTime = 0; 11 | public: 12 | int x, y; 13 | float startTime = 0; 14 | float speed = 1; 15 | Oscillator(int x, int y) : x(x), y(y) { 16 | offset = ofRandom(1); 17 | fadeInTime = ofRandom(.5, 2); 18 | } 19 | void draw(float time) { 20 | float alpha = MIN(1, (time - startTime) / fadeInTime); 21 | float localTime = time + offset; 22 | float brightness = sinnp(localTime * speed); 23 | ofSetColor(brightness * 255, alpha * 255); 24 | ofDrawRectangle(x, y, 1, 1); 25 | } 26 | }; 27 | 28 | class OscillatorGrid { 29 | public: 30 | int width, height; 31 | vector inactive, active; 32 | void setup(int width, int height) { 33 | this->width = width; 34 | this->height = height; 35 | for(int y = 0; y < height; y++) { 36 | for(int x = 0; x < width; x++) { 37 | inactive.push_back(Oscillator(x, y)); 38 | } 39 | } 40 | ofRandomize(inactive); 41 | } 42 | bool exhausted() { 43 | return inactive.empty(); 44 | } 45 | bool poke(float time, float speed) { 46 | if(exhausted()) { 47 | return false; 48 | } 49 | active.push_back(inactive.back()); 50 | inactive.pop_back(); 51 | active.back().startTime = time; 52 | active.back().speed = speed; 53 | return true; 54 | } 55 | void draw(float time) { 56 | for(int i = 0; i < active.size(); i++) { 57 | active[i].draw(time); 58 | } 59 | } 60 | }; 61 | 62 | class OscillatorStack { 63 | public: 64 | vector grids; 65 | void setup(int levels) { 66 | grids.resize(levels); 67 | for(int i = 0; i < levels; i++) { 68 | int n = 1 << i; 69 | grids[i].setup(n, n); 70 | } 71 | } 72 | int exhaustion() { 73 | for(int i = 0; i < grids.size(); i++) { 74 | if(!grids[i].exhausted()) { 75 | return i; 76 | } 77 | } 78 | return grids.size(); 79 | } 80 | bool exhausted() { 81 | return exhaustion() == grids.size(); 82 | } 83 | bool poke(float time, float speed) { 84 | for(int i = 0; i < grids.size(); i++) { 85 | if(grids[i].poke(time, speed)) { 86 | return true; 87 | } 88 | } 89 | return false; 90 | } 91 | void draw(float time) { 92 | ofPushMatrix(); 93 | for(int i = 0; i < grids.size(); i++) { 94 | grids[i].draw(time); 95 | ofScale(.5, .5); 96 | } 97 | ofPopMatrix(); 98 | } 99 | }; 100 | 101 | class ofApp : public ofBaseApp { 102 | public: 103 | OscillatorStack ost; 104 | void setup() { 105 | ost.setup(6); 106 | } 107 | void update() { 108 | float heartRate = ofRandom(55, 95); // heartRate bpm goes here 109 | 110 | float speed = 60 / heartRate; 111 | float time = ofGetElapsedTimef(); 112 | if(!ost.exhausted()) { 113 | // pokes per second is based on how deep we are 114 | float pps = 1 << ost.exhaustion(); 115 | // pokes per second increases exponentially 116 | pps *= pps; 117 | // but we slow it down a bit 118 | pps *= .5; 119 | // pokes per frame is based on the framerate 120 | float ppf = pps / ofGetFrameRate(); 121 | // if pokes per frame is less than 1 122 | if(ppf < 1) { 123 | // we poke probablistically 124 | if(ofRandom(1) < ppf) { 125 | ost.poke(time, speed); 126 | } 127 | } else { 128 | // otherwise we poke ppf times 129 | for(int i = 0; i < ppf; i++) { 130 | ost.poke(time, speed); 131 | } 132 | } 133 | } 134 | } 135 | void draw() { 136 | int width = ofGetWidth(); 137 | int height = ofGetHeight(); 138 | int side = MAX(width, height); 139 | // center 140 | ofTranslate((width - side) / 2, (height - side) / 2); 141 | ofScale(side, side); 142 | ost.draw(ofGetElapsedTimef()); 143 | } 144 | }; 145 | 146 | int main() { 147 | ofSetupOpenGL(1280, 720, OF_WINDOW); 148 | ofRunApp(new ofApp()); 149 | } 150 | -------------------------------------------------------------------------------- /GLSLParticleSystem/bin/data/drawShader.fs: -------------------------------------------------------------------------------- 1 | uniform sampler2DRect tex; 2 | varying vec4 cur; 3 | 4 | void main() { 5 | gl_FragColor = vec4(vec3(mod(length(cur.zw), 1.)), 0.); 6 | } 7 | -------------------------------------------------------------------------------- /GLSLParticleSystem/bin/data/drawShader.vs: -------------------------------------------------------------------------------- 1 | uniform sampler2DRect tex; 2 | varying vec4 cur; 3 | 4 | void main() { 5 | gl_FrontColor = gl_Color; 6 | cur = texture2DRect(tex, gl_Vertex.xy); 7 | vec2 pos = cur.xy; 8 | gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 0., 1.); 9 | } 10 | -------------------------------------------------------------------------------- /GLSLParticleSystem/bin/data/updateShader.fs: -------------------------------------------------------------------------------- 1 | uniform sampler2DRect tex; 2 | uniform vec2 mouse; 3 | 4 | const float maxVelocity = .01; 5 | 6 | void main() { 7 | vec4 cur = texture2DRect(tex, gl_TexCoord[0].xy); 8 | vec2 curPos = cur.xy; 9 | vec2 curVel = (cur.zw - .5) * maxVelocity; 10 | vec2 diff = (mouse - curPos); 11 | vec2 nextVel = .1 * diff / length(diff); 12 | nextVel = mix(nextVel, curVel, .99); 13 | vec2 nextPos = curPos + nextVel; 14 | gl_FragColor = vec4(nextPos, nextVel / maxVelocity + .5); 15 | } 16 | -------------------------------------------------------------------------------- /GLSLParticleSystem/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1024, 1024, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /GLSLParticleSystem/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup() { 4 | ofSetVerticalSync(true); 5 | ofSetBackgroundAuto(false); 6 | ofBackground(128); 7 | updateShader.setup("updateShader"); 8 | drawShader.setup("drawShader"); 9 | 10 | side = 512; 11 | 12 | ofFbo::Settings settings; 13 | settings.width = side; 14 | settings.height = side; 15 | settings.maxFilter = GL_NEAREST; 16 | settings.minFilter = GL_NEAREST; 17 | settings.internalformat = GL_RGBA32F; 18 | ping.allocate(settings); 19 | pong.allocate(settings); 20 | 21 | img.allocate(side, side, OF_IMAGE_COLOR_ALPHA); 22 | mesh.setMode(OF_PRIMITIVE_POINTS); 23 | for(int y = 0; y < side; y++) { 24 | for(int x = 0; x < side; x++) { 25 | img.setColor(x, y, ofFloatColor(ofRandom(1), ofRandom(1), .5, .5)); 26 | mesh.addVertex(ofVec2f(x, y)); 27 | } 28 | } 29 | img.update(); 30 | 31 | randomize(); 32 | } 33 | void ofApp::randomize() { 34 | ping.begin(); 35 | img.draw(0, 0); 36 | ping.end(); 37 | pong.begin(); 38 | img.draw(0, 0); 39 | pong.end(); 40 | } 41 | 42 | void ofApp::update() { 43 | bool usePing = ofGetFrameNum() % 2 == 0; 44 | ofFbo& toFbo = usePing ? ping : pong; 45 | ofFbo& fromFbo = usePing ? pong : ping; 46 | toFbo.begin(); 47 | updateShader.begin(); 48 | ofSetMinMagFilters(GL_NEAREST, GL_NEAREST); 49 | updateShader.setUniform2f("mouse", (float) mouseX / ofGetWidth(), (float) mouseY / ofGetHeight()); 50 | updateShader.setUniformTexture("tex", fromFbo, 0); 51 | fromFbo.draw(0, 0); 52 | updateShader.end(); 53 | toFbo.end(); 54 | } 55 | 56 | void ofApp::draw() { 57 | ofPushMatrix(); 58 | ofScale(ofGetWidth(), ofGetHeight()); 59 | ofNoFill(); 60 | 61 | drawShader.begin(); 62 | ofSetMinMagFilters(GL_NEAREST, GL_NEAREST); 63 | bool usePing = ofGetFrameNum() % 2 == 0; 64 | drawShader.setUniformTexture("tex", usePing ? ping : pong, 0); 65 | mesh.draw(); 66 | drawShader.end(); 67 | ofPopMatrix(); 68 | } 69 | 70 | void ofApp::keyPressed(int key) { 71 | if(key == ' ') { 72 | randomize(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /GLSLParticleSystem/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "Poco/File.h" 5 | #include "Poco/Timestamp.h" 6 | 7 | class ofAutoShader : public ofShader { 8 | public: 9 | void setup(string name) { 10 | this->name = name; 11 | ofAddListener(ofEvents().update, this, &ofAutoShader::update); 12 | } 13 | 14 | void update(ofEventArgs &args) { 15 | bool needsReload = false; 16 | 17 | string fragName = name + ".fs"; 18 | ofFile fragFile(fragName); 19 | if(fragFile.exists()) { 20 | Poco::Timestamp fragTimestamp = Poco::File(fragFile.getAbsolutePath()).getLastModified(); 21 | if(fragTimestamp != lastFragTimestamp) { 22 | needsReload = true; 23 | lastFragTimestamp = fragTimestamp; 24 | } 25 | } else { 26 | fragName = ""; 27 | } 28 | 29 | string vertName = name + ".vs"; 30 | ofFile vertFile(vertName); 31 | if(vertFile.exists()) { 32 | Poco::Timestamp vertTimestamp = Poco::File(vertFile.getAbsolutePath()).getLastModified(); 33 | if(vertTimestamp != lastVertTimestamp) { 34 | needsReload = true; 35 | lastVertTimestamp = vertTimestamp; 36 | } 37 | } else { 38 | vertName = ""; 39 | } 40 | 41 | if(needsReload) { 42 | ofShader::load(vertName, fragName); 43 | } 44 | } 45 | private: 46 | string name; 47 | Poco::Timestamp lastFragTimestamp, lastVertTimestamp; 48 | }; 49 | 50 | class ofApp : public ofBaseApp { 51 | public: 52 | void setup(); 53 | void update(); 54 | void draw(); 55 | void randomize(); 56 | void keyPressed(int key); 57 | 58 | ofAutoShader updateShader, drawShader; 59 | ofFloatImage img; 60 | ofVboMesh mesh; 61 | ofFbo ping, pong; 62 | int side; 63 | }; 64 | -------------------------------------------------------------------------------- /ImageQualityComparison/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | class ofApp : public ofBaseApp { 4 | public: 5 | ofVideoGrabber cam; 6 | void setup() { 7 | cam.initGrabber(1280, 720); 8 | } 9 | void update() { 10 | cam.update(); 11 | } 12 | void draw() { 13 | cam.draw(0, 0); 14 | } 15 | void keyPressed(int key) { 16 | if(key == '1') { 17 | ofSaveImage(cam.getPixels(), "out-best.jpg", OF_IMAGE_QUALITY_BEST); 18 | } 19 | if(key == '2') { 20 | ofSaveImage(cam.getPixels(), "out-high.jpg", OF_IMAGE_QUALITY_HIGH); 21 | } 22 | if(key == '3') { 23 | ofSaveImage(cam.getPixels(), "out-medium.jpg", OF_IMAGE_QUALITY_MEDIUM); 24 | } 25 | } 26 | }; 27 | int main() { 28 | ofSetupOpenGL(1280, 720, OF_WINDOW); 29 | ofRunApp(new ofApp()); 30 | } 31 | -------------------------------------------------------------------------------- /LineDrawing/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | class LineRenderer { 4 | private: 5 | ofShader shader; 6 | 7 | #define stringify(x) #x 8 | 9 | string frag = 10 | stringify( 11 | const float pi = 3.1415926536; 12 | uniform float feather; 13 | uniform float taper; 14 | uniform float lineLength; 15 | uniform float lineWidth; 16 | uniform float dashSpacing; 17 | uniform float dashWidth; 18 | void main() { 19 | vec2 texCoord = gl_TexCoord[0].st; 20 | float alpha = 1; 21 | 22 | // determine alpha 23 | if(dashWidth < lineLength) { 24 | float x = texCoord.x * lineLength; 25 | float modWidth = mod(x, dashSpacing); 26 | if(modWidth < feather) { 27 | alpha = modWidth / feather; 28 | } else if(modWidth > dashWidth) { 29 | alpha = 1 - ((modWidth - dashWidth) / feather); 30 | alpha = max(0, alpha); 31 | } 32 | } 33 | 34 | // determine taper 35 | if(taper < 1) { 36 | float threshold = mix(sin(pi * texCoord.x), 1, taper); 37 | float offset = abs((2 * texCoord.y) - 1); 38 | float taperAlpha = (threshold - offset) / (2 * feather / lineWidth); 39 | alpha = alpha * clamp(taperAlpha, 0, 1); 40 | } 41 | 42 | if(alpha == 0) discard; 43 | gl_FragColor = vec4(gl_Color.rgb, alpha); 44 | } 45 | ); 46 | 47 | bool centered; 48 | bool attached; 49 | float feather, dashWidth, dashSpacing, taper, lineWidth; 50 | 51 | public: 52 | LineRenderer() 53 | :attached(false) 54 | ,centered(true) 55 | ,feather(1) 56 | ,dashWidth(0) 57 | ,dashSpacing(0) 58 | ,taper(1) 59 | ,lineWidth(2) { 60 | shader.setupShaderFromSource(GL_FRAGMENT_SHADER, "#version 120\n" + frag); 61 | shader.linkProgram(); 62 | } 63 | // to draw pixel-precise odd-width lines (e.g., 1 or 3 or 11 pixels wide) set centered = false 64 | static void drawLine(const ofVec2f& a, const ofVec2f& b, float width, bool centered = true) { 65 | ofVec2f normal = (b - a).rotateRad(HALF_PI).normalize(); 66 | ofVboMesh mesh; 67 | mesh.setMode(OF_PRIMITIVE_TRIANGLE_FAN); 68 | mesh.addTexCoord(ofVec2f(0, 0)); 69 | mesh.addTexCoord(ofVec2f(1, 0)); 70 | mesh.addTexCoord(ofVec2f(1, 1)); 71 | mesh.addTexCoord(ofVec2f(0, 1)); 72 | if(centered) { 73 | normal *= width / 2; 74 | mesh.addVertex(a - normal); 75 | mesh.addVertex(b - normal); 76 | mesh.addVertex(b + normal); 77 | mesh.addVertex(a + normal); 78 | } else { 79 | ofVec2f up = normal * ((width / 2) + .5); 80 | ofVec2f down = normal * ((width / 2) - .5); 81 | mesh.addVertex(a - up); 82 | mesh.addVertex(b - up); 83 | mesh.addVertex(b + down); 84 | mesh.addVertex(a + down); 85 | } 86 | mesh.draw(); 87 | } 88 | LineRenderer& setCentered(bool centered) { 89 | this->centered = centered; 90 | return *this; 91 | } 92 | LineRenderer& setFeather(float feather) { 93 | this->feather = feather; 94 | return *this; 95 | } 96 | LineRenderer& setWidth(float lineWidth) { 97 | this->lineWidth = lineWidth; 98 | return *this; 99 | } 100 | LineRenderer& setDash(float dashSpacing = 0, float dashWidth = 0) { 101 | this->dashSpacing = dashSpacing; 102 | this->dashWidth = dashWidth; 103 | return *this; 104 | } 105 | LineRenderer& setTaper(float taper) { 106 | this->taper = taper; 107 | return *this; 108 | } 109 | bool getDash() const { 110 | return dashSpacing > 0 & dashWidth > 0; 111 | } 112 | LineRenderer& begin() { 113 | shader.begin(); 114 | attached = true; 115 | return *this; 116 | } 117 | LineRenderer& draw(const ofVec2f& a, const ofVec2f& b) { 118 | if(!attached) { 119 | shader.begin(); 120 | } 121 | float lineLength = a.distance(b); 122 | shader.setUniform1f("feather", feather); 123 | shader.setUniform1f("taper", taper); 124 | shader.setUniform1f("lineLength", lineLength); 125 | shader.setUniform1f("lineWidth", lineWidth); 126 | if(getDash()) { 127 | shader.setUniform1f("dashSpacing", dashSpacing); 128 | shader.setUniform1f("dashWidth", dashWidth); 129 | } else { 130 | shader.setUniform1f("dashSpacing", lineLength); 131 | shader.setUniform1f("dashWidth", lineLength); 132 | } 133 | drawLine(a, b, lineWidth, centered); 134 | if(!attached) { 135 | shader.end(); 136 | } 137 | return *this; 138 | } 139 | LineRenderer& end() { 140 | shader.end(); 141 | attached = false; 142 | return *this; 143 | } 144 | }; 145 | 146 | class ofApp : public ofBaseApp { 147 | public: 148 | LineRenderer lineRenderer; 149 | void setup() { 150 | ofBackground(0); 151 | } 152 | void update() { 153 | } 154 | void draw() { 155 | ofSetColor(255); 156 | int spacing = 20; 157 | for(int i = 0; i < ofGetHeight(); i += spacing) { 158 | LineRenderer::drawLine(ofVec2f(0, i), ofVec2f(ofGetWidth(), i), 1, false); 159 | } 160 | for(int i = 0; i < ofGetWidth(); i += spacing) { 161 | LineRenderer::drawLine(ofVec2f(i, 0), ofVec2f(i, ofGetHeight()), 1, false); 162 | } 163 | lineRenderer 164 | .begin() 165 | .setWidth(1) 166 | .setTaper(1) 167 | .draw(ofVec2f(0, ofGetHeight()), ofVec2f(mouseX, mouseY)) 168 | .setDash(25, 20) 169 | .setWidth(20) 170 | .draw(ofVec2f(0, 0), ofVec2f(mouseX, mouseY)) 171 | .setTaper(0) 172 | .setDash(8, 4) 173 | .setWidth(50) 174 | .draw(ofVec2f(ofGetWidth(), 0), ofVec2f(mouseX, mouseY)) 175 | .setDash(0, 0) 176 | .draw(ofVec2f(ofGetWidth(), ofGetHeight()), ofVec2f(mouseX, mouseY)) 177 | .end(); 178 | } 179 | }; 180 | int main() { 181 | ofSetupOpenGL(800, 800, OF_WINDOW); 182 | ofRunApp(new ofApp()); 183 | } 184 | -------------------------------------------------------------------------------- /LombScargle/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | #define random ofRandom 4 | #define map ofMap 5 | 6 | vector hann(const vector& x) { 7 | int n = x.size(); 8 | vector result = vector(n); 9 | for(int i = 0; i < n; i++) { 10 | float weight = .5 * (1 - cos((TWO_PI * i) / (n - 1))); 11 | result[i] = x[i] * weight; 12 | } 13 | return result; 14 | } 15 | 16 | vector range(float start, float step, float end) { 17 | vector result = vector(); 18 | for(float t = start; t < end; t += step) { 19 | result.push_back(t); 20 | } 21 | return result; 22 | } 23 | 24 | vector range(float start, float end) { 25 | return range(start, 1, end); 26 | } 27 | 28 | vector rand(int count) { 29 | vector result = vector(count); 30 | for(int i = 0; i < count; i++) { 31 | result[i] = random(1); 32 | } 33 | return result; 34 | } 35 | 36 | vector mult(float x, const vector& y) { 37 | int n = y.size(); 38 | vector result = vector(n); 39 | for(int i = 0; i < n; i++) { 40 | result[i] = x * y[i]; 41 | } 42 | return result; 43 | } 44 | 45 | vector dotasterisk(const vector& x, const vector& y) { 46 | int n = y.size(); 47 | vector result = vector(n); 48 | for(int i = 0; i < n; i++) { 49 | result[i] = x[i] * y[i]; 50 | } 51 | return result; 52 | } 53 | 54 | vector add(float x, const vector& y) { 55 | int n = y.size(); 56 | vector result = vector(n); 57 | for(int i = 0; i < n; i++) { 58 | result[i] = x + y[i]; 59 | } 60 | return result; 61 | } 62 | 63 | vector add(const vector& x, const vector& y) { 64 | int n = y.size(); 65 | vector result = vector(n); 66 | for(int i = 0; i < n; i++) { 67 | result[i] = x[i] + y[i]; 68 | } 69 | return result; 70 | } 71 | 72 | vector interp1(const vector& x, const vector& v, const vector& xq) { 73 | int n = xq.size(); 74 | int m = x.size(); 75 | vector result = vector(n); 76 | for(int i = 0; i < n; i++) { 77 | float curq = xq[i]; 78 | int prej = 0, curj = 0; 79 | float prex = x[0], curx = x[0]; 80 | for(int j = 1; j < m; j++) { 81 | curj = j; 82 | curx = x[j]; 83 | if(prex <= curq && curx > curq) { 84 | break; 85 | } else { 86 | prej = curj; 87 | prex = curx; 88 | } 89 | } 90 | if(prex == curx) { 91 | result[i] = v[prej]; 92 | } else { 93 | result[i] = map(curq, prex, curx, v[prej], v[curj]); 94 | } 95 | } 96 | return result; 97 | } 98 | 99 | vector cos(const vector& x) { 100 | int n = x.size(); 101 | vector result = vector(n); 102 | for(int i = 0; i < n; i++) { 103 | result[i] = cos(x[i]); 104 | } 105 | return result; 106 | } 107 | 108 | vector sin(const vector& x) { 109 | int n = x.size(); 110 | vector result = vector(n); 111 | for(int i = 0; i < n; i++) { 112 | result[i] = cos(x[i]); 113 | } 114 | return result; 115 | } 116 | 117 | float sum(const vector& x) { 118 | float sum = 0; 119 | int n = x.size(); 120 | for(int i = 0; i < n; i++) { 121 | sum += x[i]; 122 | } 123 | return sum; 124 | } 125 | 126 | float mean(const vector& x) { 127 | return sum(x) / x.size(); 128 | } 129 | 130 | vector sq(const vector& x) { 131 | int n = x.size(); 132 | vector result = vector(n); 133 | for(int i = 0; i < n; i++) { 134 | result[i] = x[i] * x[i]; 135 | } 136 | return result; 137 | } 138 | 139 | float cov(const vector& x) { 140 | float ssd = sum(sq(add(-mean(x), x))); 141 | return ssd / x.size(); 142 | } 143 | 144 | float stddev(const vector& x) { 145 | return sqrt(cov(x)); 146 | } 147 | 148 | vector lomb(const vector& t, const vector& y, const vector& freq) { 149 | int nfreq = freq.size(); 150 | float fmax = freq[nfreq - 1]; 151 | float fmin = freq[0]; 152 | vector power = vector(nfreq); 153 | vector f4pi = mult(4*PI, freq); 154 | float var = cov(y); 155 | vector yn = add(-mean(y), y); 156 | for(int fi = 0; fi < nfreq; fi++) { 157 | float sinsum = sum(sin(mult(f4pi[fi], t))); 158 | float cossum = sum(cos(mult(f4pi[fi], t))); 159 | float tau = atan2(sinsum, cossum); 160 | vector argu = mult(TWO_PI * freq[fi], add(-tau, t)); 161 | vector cosarg = cos(argu); 162 | float cfi = sum(dotasterisk(yn, cosarg)); 163 | float cosnorm = sum(dotasterisk(cosarg, cosarg)); 164 | vector sinarg = sin(argu); 165 | float sfi = sum(dotasterisk(yn, sinarg)); 166 | float sinnorm = sum(dotasterisk(sinarg, sinarg)); 167 | power[fi] = (cfi*cfi/cosnorm+sfi*sfi/sinnorm)/(2*var); 168 | } 169 | return power; 170 | } 171 | 172 | class ofApp : public ofBaseApp { 173 | public: 174 | vector o18, power; 175 | 176 | void setup() { 177 | ofBackground(255); 178 | prep(); 179 | } 180 | void prep() { 181 | int n = 600; 182 | vector age = range(0, n); 183 | // randomSeed(0); 184 | vector ager = add(age, add(-.15, mult(0.3, rand(age.size())))); 185 | ager[0] = age[0]; ager[n - 1] = age[n - 1]; 186 | vector depth = mult(1/10., age); 187 | vector bkg = interp1(range(0, 10, n), rand(n / 10), ager); 188 | float f1 = 1./mouseX, f2 = 1./125; 189 | vector sig = add(cos(mult(TWO_PI*f1, ager)), 190 | cos(add(PI, mult(TWO_PI*f2, ager)))); 191 | o18 = add(sig, bkg); 192 | // o18 = hann(o18); 193 | // pick frequencies to evaluate spectral power 194 | vector freq = range(0, 0.0001, 0.02); 195 | power = lomb(age, o18, freq); 196 | power[0] = 0; 197 | // normalize to average 1 198 | power = mult(1./stddev(power), power); 199 | } 200 | void update() { 201 | } 202 | void draw() { 203 | prep(); 204 | ofNoFill(); 205 | ofSetColor(0); 206 | 207 | float width = ofGetWidth(); 208 | float height = ofGetHeight(); 209 | 210 | // plot the results 211 | ofBeginShape(); 212 | ofVertex(0, height); 213 | for(int i = 0; i < power.size(); i++) { 214 | float x = map(i, 0, power.size(), 0, width); 215 | float y = map(power[i], 0, 6, height, 0); 216 | ofVertex(x, y); 217 | } 218 | ofVertex(width, height); 219 | ofEndShape(); 220 | 221 | ofBeginShape(); 222 | for(int i = 0; i < o18.size(); i++) { 223 | float x = map(i, 0, o18.size(), 0, width); 224 | float y = map(o18[i], -10, 10, 0, height); 225 | ofVertex(x, y); 226 | } 227 | ofEndShape(); 228 | } 229 | }; 230 | int main() { 231 | ofSetupOpenGL(512, 512, OF_WINDOW); 232 | ofRunApp(new ofApp()); 233 | } 234 | -------------------------------------------------------------------------------- /LutExample/.gitignore: -------------------------------------------------------------------------------- 1 | *.depend 2 | *.layout 3 | *.mode*v3 4 | *.pbxuser 5 | *.app* 6 | *.DS_* 7 | 8 | .svn/ 9 | obj/ 10 | bin/ 11 | build/ 12 | !data/ 13 | 14 | *.sdf 15 | *.opensdf 16 | *.suo 17 | *.ipch -------------------------------------------------------------------------------- /LutExample/bin/data/blue-boost-lut.exr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/openFrameworksDemos/ae7d2f9f43884ef54bec44420994c49e2bf8081a/LutExample/bin/data/blue-boost-lut.exr -------------------------------------------------------------------------------- /LutExample/bin/data/linear-lut.exr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/openFrameworksDemos/ae7d2f9f43884ef54bec44420994c49e2bf8081a/LutExample/bin/data/linear-lut.exr -------------------------------------------------------------------------------- /LutExample/bin/data/lut.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2DRect lut, source; 2 | 3 | const float lutSize = 256.; 4 | 5 | void main(void) { 6 | vec2 st = gl_TexCoord[0].st; 7 | vec4 c = texture2DRect(source, st); 8 | gl_FragColor = vec4( 9 | texture2DRect(lut, vec2(lutSize * c.r, 1.)).r, 10 | texture2DRect(lut, vec2(lutSize * c.g, 1.)).g, 11 | texture2DRect(lut, vec2(lutSize * c.b, 1.)).b, 12 | c.a); 13 | } -------------------------------------------------------------------------------- /LutExample/src/Lut.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class Lut { 6 | private: 7 | ofTexture* source; 8 | ofFloatImage lut; 9 | ofFbo result; 10 | 11 | ofShader lutShader; 12 | 13 | public: 14 | void setup(int width, int height, string filename) { 15 | result.allocate(width, height, GL_RGB); // doesn't need a depth buffer 16 | lutShader.load("", "lut.frag"); 17 | lut.loadImage(filename); 18 | } 19 | void setSource(ofTexture& source) { 20 | this->source = &source; 21 | } 22 | void setGamma(float gamma) { 23 | setGamma(ofFloatColor(gamma, gamma, gamma)); 24 | } 25 | void setGamma(ofFloatColor gamma) { 26 | int n = 256; 27 | for(int i = 0; i < n; i++) { 28 | float x = (float) i / (n - 1.); 29 | ofFloatColor cur( 30 | powf(x, 1. / gamma.r), 31 | powf(x, 1. / gamma.g), 32 | powf(x, 1. / gamma.b)); 33 | lut.setColor(i, 0, cur); 34 | } 35 | lut.update(); 36 | } 37 | void update() { 38 | ofPushMatrix(); 39 | result.begin(); 40 | lutShader.begin(); 41 | lutShader.setUniformTexture("source", *source, 0); 42 | lutShader.setUniformTexture("lut", lut.getTextureReference(), 1); 43 | source->draw(0, 0); 44 | lutShader.end(); 45 | result.end(); 46 | ofPopMatrix(); 47 | } 48 | ofTexture& getTexture() { 49 | return result.getTextureReference(); 50 | } 51 | }; -------------------------------------------------------------------------------- /LutExample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1024, 1024, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /LutExample/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup(){ 4 | ofSetVerticalSync(true); 5 | camera.initGrabber(camWidth, camHeight); 6 | lut.setup(camWidth, camHeight, "blue-boost-lut.exr"); 7 | lut.setSource(camera.getTextureReference()); 8 | } 9 | 10 | void ofApp::update(){ 11 | camera.update(); 12 | if(camera.isFrameNew()) { 13 | lut.setGamma( 14 | ofFloatColor( 15 | ofMap(mouseX, 0, ofGetWidth(), 0, 3), 16 | ofMap(mouseY, 0, ofGetHeight(), 0, 3), 17 | 1.)); 18 | lut.update(); 19 | } 20 | } 21 | 22 | void ofApp::draw(){ 23 | ofSetColor(255); 24 | if(ofGetMousePressed()) { 25 | camera.draw(0, 0); 26 | } else { 27 | lut.getTexture().draw(0, 0); 28 | } 29 | ofSetColor(0); 30 | ofDrawBitmapString(ofToString((int) ofGetFrameRate()), 10, 20); 31 | } 32 | -------------------------------------------------------------------------------- /LutExample/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "Lut.h" 5 | 6 | class ofApp : public ofBaseApp{ 7 | public: 8 | void setup(); 9 | void update(); 10 | void draw(); 11 | 12 | static const int camWidth = 1280; 13 | static const int camHeight = 720; 14 | 15 | ofVideoGrabber camera; 16 | Lut lut; 17 | }; 18 | -------------------------------------------------------------------------------- /NoiseFlocking/src/Particle.cpp: -------------------------------------------------------------------------------- 1 | #include "Particle.h" 2 | 3 | vector 4 | Particle::forces; 5 | 6 | vector 7 | Particle::particles; 8 | 9 | ofVec2f 10 | Particle::centeringForce, 11 | Particle::globalOffset, 12 | Particle::externalForce; 13 | 14 | float 15 | Particle::speed, 16 | Particle::spread, 17 | Particle::viscosity, 18 | Particle::independence, 19 | Particle::neighborhood, 20 | Particle::confusion, 21 | Particle::indecision, 22 | Particle::age, 23 | Particle::globalDirection; 24 | 25 | void Particle::setup(int n, float radius) { 26 | globalOffset.set(1. / 3, 2. / 3); 27 | speed = 1; 28 | spread = 25; 29 | viscosity = .1; 30 | independence = 1; 31 | neighborhood = 100; 32 | confusion = .01; 33 | indecision = .01; 34 | age = 0; 35 | globalDirection = 0; 36 | 37 | for(int i = 0; i < n; i++) { 38 | Particle::particles.push_back(Particle(radius)); 39 | } 40 | } 41 | 42 | void Particle::drawAll() { 43 | ofMesh mesh; 44 | mesh.setMode(OF_PRIMITIVE_POINTS); 45 | for(int i = 0; i < particles.size(); i++) { 46 | mesh.addVertex(particles[i].position); 47 | } 48 | mesh.drawVertices(); 49 | } 50 | 51 | void Particle::updateAll(float dt = 1. / 60.) { 52 | for(int i = 0; i < particles.size(); i++) { 53 | particles[i].update(dt); 54 | } 55 | globalDirection += ofSignedNoise(indecision * age); 56 | ofVec2f direction(0, 1); 57 | direction.rotate(globalDirection); 58 | globalOffset += confusion * direction * dt; 59 | age += dt; 60 | forces.clear(); 61 | } 62 | 63 | void Particle::addForce(ofVec2f position, float magnitude) { 64 | forces.push_back(Force(position, magnitude)); 65 | } -------------------------------------------------------------------------------- /NoiseFlocking/src/Particle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | inline void randomize(ofVec2f& v) { 6 | v.x = ofRandomf(); 7 | v.y = ofRandomf(); 8 | v.normalize(); 9 | } 10 | 11 | class Force { 12 | public: 13 | ofVec2f position; 14 | float magnitude; 15 | Force(ofVec2f position, float magnitude) { 16 | this->position = position; 17 | this->magnitude = magnitude; 18 | } 19 | }; 20 | 21 | class Particle { 22 | public: 23 | static ofVec2f centeringForce, globalOffset, externalForce; 24 | static float speed, spread, viscosity, independence, rebirthRadius, neighborhood, confusion, indecision, age, globalDirection; 25 | static vector particles; 26 | static vector forces; 27 | static void setup(int n, float radius); 28 | static void drawAll(); 29 | static void addForce(ofVec2f position, float magnitude); 30 | static void updateAll(float dt); 31 | 32 | ofVec2f position, velocity, force, localOffset; 33 | Particle(float radius) { 34 | randomize(localOffset); 35 | randomize(position); 36 | position *= radius; 37 | } 38 | inline void applyFlockingForce() { 39 | float basex = position.x / neighborhood; 40 | float basey = position.y / neighborhood; 41 | force.x += 42 | ofSignedNoise( 43 | basex + globalOffset.x + localOffset.x * independence, 44 | basey); 45 | force.y += 46 | ofSignedNoise( 47 | basex, 48 | basey + globalOffset.y + localOffset.y * independence); 49 | } 50 | inline void applyViscosityForce() { 51 | force += velocity * -viscosity; 52 | } 53 | inline void applyCenteringForce() { 54 | centeringForce = position; 55 | float distanceToCenter = centeringForce.length(); 56 | centeringForce.normalize(); 57 | centeringForce *= -distanceToCenter / (spread * spread); 58 | force += centeringForce; 59 | } 60 | inline void applyExternalForce() { 61 | for(int i = 0; i < forces.size(); i++) { 62 | externalForce = position - forces[i].position; 63 | float distanceToForce = externalForce.length(); 64 | externalForce.normalize(); 65 | externalForce *= forces[i].magnitude / distanceToForce; 66 | force += externalForce; 67 | } 68 | } 69 | inline void update(float dt) { 70 | force.set(0, 0); 71 | applyFlockingForce(); 72 | applyViscosityForce(); 73 | applyCenteringForce(); 74 | applyExternalForce(); 75 | velocity += force * dt; // mass = 1, acceleration = force 76 | position += velocity * speed * dt; 77 | } 78 | }; 79 | -------------------------------------------------------------------------------- /NoiseFlocking/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1024, 768, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /NoiseFlocking/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup() { 4 | //ofSetBackgroundAuto(false); 5 | //ofSetVerticalSync(true); 6 | Particle::setup(50000, 100); 7 | ofBackground(0); 8 | } 9 | 10 | void ofApp::update() { 11 | if(ofGetMousePressed()) { 12 | Particle::addForce(ofVec2f(mouseX - ofGetWidth() / 2, mouseY - ofGetHeight() / 2), 100); 13 | } 14 | Particle::updateAll(60 * ofGetLastFrameTime()); 15 | } 16 | 17 | void ofApp::draw() { 18 | ofPushMatrix(); 19 | ofTranslate(ofGetWidth() / 2, ofGetHeight() / 2, 0); 20 | ofSetColor(255); 21 | //glPointSize(2); 22 | //glEnable(GL_POINT_SMOOTH); 23 | Particle::drawAll(); 24 | ofPopMatrix(); 25 | 26 | ofSetColor(0); 27 | ofRect(0, 0, 100, 100); 28 | ofSetColor(255); 29 | //ofDrawBitmapString(ofToString((int) ofGetFrameRate()), 10, 20); 30 | } 31 | 32 | void ofApp::keyPressed(int key) { 33 | if(key == 'f') 34 | ofToggleFullscreen(); 35 | } 36 | -------------------------------------------------------------------------------- /NoiseFlocking/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "Particle.h" 5 | 6 | class ofApp : public ofBaseApp { 7 | public: 8 | void setup(); 9 | void update(); 10 | void draw(); 11 | void keyPressed(int key); 12 | }; 13 | -------------------------------------------------------------------------------- /P52OF/src/PApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | class PApp : public ofBaseApp { 4 | public: 5 | float width, height; 6 | 7 | PApp() { 8 | width = ofGetWidth(); 9 | height = ofGetHeight(); 10 | ofEnableAlphaBlending(); 11 | } 12 | 13 | int framecount; 14 | void update() { 15 | framecount = ofGetFrameNum(); 16 | } 17 | 18 | int x, y, button; 19 | virtual void mousePressed() { 20 | } 21 | virtual void mouseReleased() { 22 | } 23 | virtual void mouseDragged() { 24 | } 25 | virtual void mouseMoved() { 26 | } 27 | void mousePressed(int x, int y, int button) { 28 | this->x = x; 29 | this->y = y; 30 | this->button = button; 31 | mousePressed(); 32 | } 33 | void mouseReleased(int x, int y, int button) { 34 | this->x = x; 35 | this->y = y; 36 | this->button = button; 37 | mouseReleased(); 38 | } 39 | void mouseDragged(int x, int y, int button) { 40 | this->x = x; 41 | this->y = y; 42 | this->button = button; 43 | mouseDragged(); 44 | } 45 | void mouseMoved(int x, int y) { 46 | this->x = x; 47 | this->y = y; 48 | mouseMoved(); 49 | } 50 | 51 | int key; 52 | virtual void keyPressed() { 53 | } 54 | virtual void keyReleased() { 55 | } 56 | void keyPressed(int key) { 57 | this->key = key; 58 | keyPressed(); 59 | } 60 | void keyReleased(int key) { 61 | this->key = key; 62 | keyReleased(); 63 | } 64 | 65 | void background(ofColor color) { 66 | ofBackground(color); 67 | } 68 | void background(float r, float g, float b) { 69 | ofBackground(r, g, b); 70 | } 71 | void pushMatrix() { 72 | ofPushMatrix(); 73 | } 74 | void popMatrix() { 75 | ofPopMatrix(); 76 | } 77 | void translate(float x, float y, float z = 0) { 78 | ofTranslate(x, y, z); 79 | } 80 | void stroke(ofColor color) { 81 | ofSetColor(color); 82 | } 83 | void stroke(ofColor color, float a) { 84 | ofSetColor(color, a); 85 | } 86 | void stroke(float r, float g, float b, float a = 255) { 87 | ofSetColor(r, g, b, a); 88 | } 89 | void fill(ofColor color) { 90 | ofSetColor(color); 91 | } 92 | void fill(ofColor color, float a) { 93 | ofSetColor(color, a); 94 | } 95 | void fill(float r, float g, float b, float a = 255) { 96 | ofSetColor(r, g, b, a); 97 | } 98 | float random(float max) { 99 | return ofRandom(max); 100 | } 101 | float random(float min, float max) { 102 | return ofRandom(min, max); 103 | } 104 | float norm(float x, float min, float max) { 105 | return ofNormalize(x, min, max); 106 | } 107 | float map(float x, float inMin, float inMax, float outMin, float outMax) { 108 | return ofMap(x, inMin, inMax, outMin, outMax); 109 | } 110 | float lerp(float min, float max, float amt) { 111 | return ofLerp(min, max, amt); 112 | } 113 | float noise(float x) { 114 | return ofNoise(x); 115 | } 116 | float noise(float x, float y) { 117 | return ofNoise(x, y); 118 | } 119 | float noise(float x, float y, float z) { 120 | return ofNoise(x, y, z); 121 | } 122 | void ellipse(float x, float y, float width, float height) { 123 | ofEllipse(x, y, width, height); 124 | } 125 | void line(float x1, float y1, float x2, float y2) { 126 | ofLine(x1, y1, x2, y2); 127 | } 128 | }; 129 | 130 | 131 | class ofApp : public PApp { 132 | public: 133 | #include "main.h" 134 | }; 135 | 136 | int main() { 137 | ofSetupOpenGL(512, 512, OF_WINDOW); 138 | ofRunApp(new ofApp()); 139 | } 140 | -------------------------------------------------------------------------------- /P52OF/src/main.h: -------------------------------------------------------------------------------- 1 | vector pollenMass; 2 | vector points; 3 | ofMesh mesh; 4 | 5 | int nPoints, step; 6 | float complexity, maxMass, timeSpeed, phase, windSpeed, t; 7 | bool debugMode; 8 | 9 | void setup() { 10 | nPoints = 4096; // points to draw 11 | complexity = 6; // wind complexity 12 | maxMass = .8; // max pollen mass 13 | timeSpeed = .02; // wind variation speed 14 | phase = TWO_PI; // separate u-noise from v-noise 15 | windSpeed = 40; // wind vector magnitude for debug 16 | step = 10; // spatial sampling rate for debug 17 | debugMode = false; 18 | 19 | points.resize(nPoints); 20 | pollenMass.resize(nPoints); 21 | for(int i = 0; i < nPoints; i++) { 22 | points[i] = ofVec2f(random(0, width), random(0, height)); 23 | pollenMass[i] = random(0, maxMass); 24 | } 25 | background(255); 26 | mesh.clear(); 27 | } 28 | 29 | ofVec2f getField(ofVec2f position) { 30 | float normx = norm(position.x, 0, width); 31 | float normy = norm(position.y, 0, height); 32 | float u = noise(t + phase, normx * complexity + phase, normy * complexity + phase); 33 | float v = noise(t - phase, normx * complexity - phase, normy * complexity + phase); 34 | return ofVec2f(u, v); 35 | } 36 | 37 | void draw() { 38 | t = framecount * timeSpeed; 39 | if(debugMode) { 40 | background(255); 41 | stroke(0); 42 | float s = windSpeed; 43 | for(int i = 0; i < width; i += step) { 44 | for(int j = 0; j < height; j += step) { 45 | ofVec2f field = getField(ofVec2f(i, j)); 46 | pushMatrix(); 47 | translate(i, j); 48 | line(0, 0, lerp(-windSpeed, windSpeed, field.x), lerp(-windSpeed, windSpeed, field.y)); 49 | popMatrix(); 50 | } 51 | } 52 | stroke(255, 0, 0); 53 | } else { 54 | stroke(0, 10); 55 | } 56 | 57 | mesh.setMode(OF_PRIMITIVE_POINTS); 58 | for(int i = 0; i < nPoints; i++) { 59 | float x = points[i].x, y = points[i].y; 60 | ofVec2f field = getField(points[i]); 61 | float speed = (1 + noise(t, field.x, field.y)) / pollenMass[i]; 62 | x += lerp(-speed, speed, field.x); 63 | y += lerp(-speed, speed, field.y); 64 | 65 | if(x < 0 || x > width || y < 0 || y > height) { 66 | x = random(0, width); 67 | y = random(0, height); 68 | } 69 | 70 | if(debugMode) { 71 | ellipse(x, y, 3, 3); 72 | } else { 73 | mesh.addVertex(ofVec2f(x, y)); 74 | } 75 | 76 | points[i].x = x; 77 | points[i].y = y; 78 | } 79 | if(!debugMode) { 80 | mesh.draw(); 81 | } 82 | } 83 | 84 | void mousePressed() { 85 | setup(); 86 | } 87 | 88 | void keyPressed() { 89 | debugMode = !debugMode; 90 | background(255); 91 | } 92 | -------------------------------------------------------------------------------- /RemapExample/bin/data/remap.exr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/openFrameworksDemos/ae7d2f9f43884ef54bec44420994c49e2bf8081a/RemapExample/bin/data/remap.exr -------------------------------------------------------------------------------- /RemapExample/bin/data/remap.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2DRect remap, source; 2 | 3 | // which components you use (rg, gb) depend on how you stored the texture 4 | // and it looks like there's an rb bug with float loading atm. 5 | 6 | void main(void) { 7 | vec2 st = gl_TexCoord[0].st; 8 | 9 | // offset style 10 | vec2 offset = texture2DRect(remap, st).gb - .5; // values from 0 to 1 11 | gl_FragColor = texture2DRect(source, st + offset * 128.); 12 | 13 | // absolute style 14 | //vec2 target = texture2DRect(remap, st).rg * vec2(1280., 720.); // values from 0 to 1 15 | //gl_FragColor = texture2DRect(source, target); 16 | } -------------------------------------------------------------------------------- /RemapExample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1280, 720, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /RemapExample/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup(){ 4 | ofSetVerticalSync(true); 5 | camera.initGrabber(camWidth, camHeight); 6 | remapImage.loadImage("remap.exr"); 7 | remap.setup(camWidth, camHeight); 8 | remap.setSource(camera.getTextureReference()); 9 | remap.setRemap(remapImage.getTextureReference()); 10 | } 11 | 12 | void ofApp::update(){ 13 | camera.update(); 14 | if(camera.isFrameNew()) { 15 | remap.update(); 16 | } 17 | } 18 | 19 | void ofApp::draw(){ 20 | ofSetColor(255); 21 | remap.getTexture().draw(0, 0); 22 | ofSetColor(0); 23 | ofDrawBitmapString(ofToString((int) ofGetFrameRate()), 10, 20); 24 | } 25 | -------------------------------------------------------------------------------- /RemapExample/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "ofxRemap.h" 5 | 6 | class ofApp : public ofBaseApp{ 7 | public: 8 | void setup(); 9 | void update(); 10 | void draw(); 11 | 12 | static const int camWidth = 1280; 13 | static const int camHeight = 720; 14 | 15 | ofVideoGrabber camera; 16 | 17 | ofFloatImage remapImage; 18 | ofxRemap remap; 19 | }; 20 | -------------------------------------------------------------------------------- /RemapExample/src/ofxRemap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class ofxRemap { 6 | private: 7 | ofTexture* source; 8 | ofTexture* remap; 9 | ofFbo result; 10 | 11 | ofShader remapShader; 12 | 13 | public: 14 | void setup(int width, int height) { 15 | result.allocate(width, height, GL_RGBA); // doesn't need a depth buffer 16 | remapShader.load("", "remap.frag"); 17 | } 18 | void setSource(ofTexture& source) { 19 | this->source = &source; 20 | } 21 | void setRemap(ofTexture& remap) { 22 | this->remap = &remap; 23 | } 24 | void update() { 25 | ofPushMatrix(); 26 | result.begin(); 27 | remapShader.begin(); 28 | remapShader.setUniformTexture("source", *source, 0); 29 | remapShader.setUniformTexture("remap", *remap, 1); 30 | source->draw(0, 0); 31 | remapShader.end(); 32 | result.end(); 33 | ofPopMatrix(); 34 | } 35 | ofTexture& getTexture() { 36 | return result.getTextureReference(); 37 | } 38 | }; -------------------------------------------------------------------------------- /ShaderBuilder/bin/data/shader.fs: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | uniform vec3 iResolution; // viewport resolution (in pixels) 4 | uniform float iGlobalTime; // shader playback time (in seconds) 5 | uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click 6 | 7 | const int NUM_STEPS = 8; 8 | const float PI = 3.1415; 9 | const float EPSILON = 1e-3; 10 | float EPSILON_NRM = 0.1 / iResolution.x; 11 | 12 | // sea 13 | const int ITER_GEOMETRY = 3; 14 | const int ITER_FRAGMENT = 5; 15 | const float SEA_HEIGHT = 0.6; 16 | const float SEA_CHOPPY = 4.0; 17 | const float SEA_SPEED = 0.8; 18 | const float SEA_FREQ = 0.16; 19 | const vec3 SEA_BASE = vec3(0.1,0.19,0.22); 20 | const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6); 21 | float SEA_TIME = iGlobalTime * SEA_SPEED; 22 | mat2 octave_m = mat2(1.6,1.2,-1.2,1.6); 23 | 24 | // math 25 | mat3 fromEuler(vec3 ang) { 26 | vec2 a1 = vec2(sin(ang.x),cos(ang.x)); 27 | vec2 a2 = vec2(sin(ang.y),cos(ang.y)); 28 | vec2 a3 = vec2(sin(ang.z),cos(ang.z)); 29 | mat3 m; 30 | m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x); 31 | m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x); 32 | m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y); 33 | return m; 34 | } 35 | float hash( vec2 p ) { 36 | float h = dot(p,vec2(127.1,311.7)); 37 | return fract(sin(h)*43758.5453123); 38 | } 39 | float noise( in vec2 p ) { 40 | vec2 i = floor( p ); 41 | vec2 f = fract( p ); 42 | vec2 u = f*f*(3.0-2.0*f); 43 | return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ), 44 | hash( i + vec2(1.0,0.0) ), u.x), 45 | mix( hash( i + vec2(0.0,1.0) ), 46 | hash( i + vec2(1.0,1.0) ), u.x), u.y); 47 | } 48 | 49 | // lighting 50 | float diffuse(vec3 n,vec3 l,float p) { 51 | return pow(dot(n,l) * 0.4 + 0.6,p); 52 | } 53 | float specular(vec3 n,vec3 l,vec3 e,float s) { 54 | float nrm = (s + 8.0) / (3.1415 * 8.0); 55 | return pow(max(dot(reflect(e,n),l),0.0),s) * nrm; 56 | } 57 | 58 | // sky 59 | vec3 getSkyColor(vec3 e) { 60 | e.y = max(e.y,0.0); 61 | vec3 ret; 62 | ret.x = pow(1.0-e.y,2.0); 63 | ret.y = 1.0-e.y; 64 | ret.z = 0.6+(1.0-e.y)*0.4; 65 | return ret; 66 | } 67 | 68 | // sea 69 | float sea_octave(vec2 uv, float choppy) { 70 | uv += noise(uv); 71 | vec2 wv = 1.0-abs(sin(uv)); 72 | vec2 swv = abs(cos(uv)); 73 | wv = mix(wv,swv,wv); 74 | return pow(1.0-pow(wv.x * wv.y,0.65),choppy); 75 | } 76 | 77 | float map(vec3 p) { 78 | float freq = SEA_FREQ; 79 | float amp = SEA_HEIGHT; 80 | float choppy = SEA_CHOPPY; 81 | vec2 uv = p.xz; uv.x *= 0.75; 82 | 83 | float d, h = 0.0; 84 | for(int i = 0; i < ITER_GEOMETRY; i++) { 85 | d = sea_octave((uv+SEA_TIME)*freq,choppy); 86 | d += sea_octave((uv-SEA_TIME)*freq,choppy); 87 | h += d * amp; 88 | uv *= octave_m; freq *= 1.9; amp *= 0.22; 89 | choppy = mix(choppy,1.0,0.2); 90 | } 91 | return p.y - h; 92 | } 93 | 94 | float map_detailed(vec3 p) { 95 | float freq = SEA_FREQ; 96 | float amp = SEA_HEIGHT; 97 | float choppy = SEA_CHOPPY; 98 | vec2 uv = p.xz; uv.x *= 0.75; 99 | 100 | float d, h = 0.0; 101 | for(int i = 0; i < ITER_FRAGMENT; i++) { 102 | d = sea_octave((uv+SEA_TIME)*freq,choppy); 103 | d += sea_octave((uv-SEA_TIME)*freq,choppy); 104 | h += d * amp; 105 | uv *= octave_m; freq *= 1.9; amp *= 0.22; 106 | choppy = mix(choppy,1.0,0.2); 107 | } 108 | return p.y - h; 109 | } 110 | 111 | vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) { 112 | float fresnel = 1.0 - max(dot(n,-eye),0.0); 113 | fresnel = pow(fresnel,3.0) * 0.65; 114 | 115 | vec3 reflected = getSkyColor(reflect(eye,n)); 116 | vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12; 117 | 118 | vec3 color = mix(refracted,reflected,fresnel); 119 | 120 | float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0); 121 | color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten; 122 | 123 | color += vec3(specular(n,l,eye,60.0)); 124 | 125 | return color; 126 | } 127 | 128 | // tracing 129 | vec3 getNormal(vec3 p, float eps) { 130 | vec3 n; 131 | n.y = map_detailed(p); 132 | n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y; 133 | n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y; 134 | n.y = eps; 135 | return normalize(n); 136 | } 137 | 138 | float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) { 139 | float tm = 0.0; 140 | float tx = 1000.0; 141 | float hx = map(ori + dir * tx); 142 | if(hx > 0.0) return tx; 143 | float hm = map(ori + dir * tm); 144 | float tmid = 0.0; 145 | for(int i = 0; i < NUM_STEPS; i++) { 146 | tmid = mix(tm,tx, hm/(hm-hx)); 147 | p = ori + dir * tmid; 148 | float hmid = map(p); 149 | if(hmid < 0.0) { 150 | tx = tmid; 151 | hx = hmid; 152 | } else { 153 | tm = tmid; 154 | hm = hmid; 155 | } 156 | } 157 | return tmid; 158 | } 159 | 160 | // main 161 | void main(void) { 162 | vec2 uv = gl_FragCoord.xy / iResolution.xy; 163 | uv = uv * 2.0 - 1.0; 164 | uv.x *= iResolution.x / iResolution.y; 165 | float time = iGlobalTime * 0.3; 166 | 167 | // ray 168 | vec3 ang = vec3(0,0.2,0); 169 | vec3 ori = vec3(0.0,3.5, (-time + iMouse.x*0.01)* 5.0); 170 | vec3 dir = normalize(vec3(uv.xy,-2.0));// dir.z += length(uv) * 0.15; 171 | dir = normalize(dir) * fromEuler(ang); 172 | 173 | // tracing 174 | vec3 p; 175 | heightMapTracing(ori,dir,p); 176 | vec3 dist = p - ori; 177 | vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM); 178 | vec3 light = normalize(vec3(0.0,1.0,0.8)); 179 | 180 | // color 181 | vec3 color = mix( 182 | getSkyColor(dir), 183 | getSeaColor(p,n,light,dir,dist), 184 | pow(smoothstep(0.0,-0.05,dir.y),0.3)); 185 | 186 | // post 187 | gl_FragColor = vec4(pow(color,vec3(.75)), 1.0); 188 | } -------------------------------------------------------------------------------- /ShaderBuilder/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofAutoShader.h" 3 | 4 | class ofApp : public ofBaseApp { 5 | public: 6 | ofAutoShader shader; 7 | int mouseXPressed, mouseYPressed; 8 | void setup() { 9 | shader.setup("shader"); 10 | } 11 | void draw() { 12 | shader.begin(); 13 | shader.setUniform3f("iResolution", ofGetWidth(), ofGetHeight(), 0); 14 | shader.setUniform1f("iGlobalTime", ofGetElapsedTimef()); 15 | shader.setUniform4f("iMouse", mouseX, mouseY, mouseXPressed, mouseYPressed); 16 | ofDrawRectangle(0, 0, ofGetWidth(), ofGetHeight()); 17 | shader.end(); 18 | } 19 | void mousePressed(int x, int y, int button) { 20 | mouseDragged(x, y, button); 21 | } 22 | void mouseDragged(int x, int y, int button) { 23 | mouseXPressed = x; 24 | mouseYPressed = y; 25 | } 26 | }; 27 | 28 | int main() { 29 | ofSetupOpenGL(1280, 720, OF_WINDOW); 30 | ofRunApp(new ofApp()); 31 | } 32 | -------------------------------------------------------------------------------- /ShaderBuilder/src/ofAutoShader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "Poco/File.h" 5 | #include "Poco/Timestamp.h" 6 | 7 | class ofAutoShader : public ofShader { 8 | public: 9 | void setup(string name) { 10 | this->name = name; 11 | ofEventArgs args; 12 | update(args); 13 | ofAddListener(ofEvents().update, this, &ofAutoShader::update); 14 | } 15 | 16 | void update(ofEventArgs &args) { 17 | bool needsReload = false; 18 | 19 | string fragName = name + ".fs"; 20 | ofFile fragFile(fragName); 21 | if(fragFile.exists()) { 22 | Poco::Timestamp fragTimestamp = Poco::File(fragFile.getAbsolutePath()).getLastModified(); 23 | if(fragTimestamp != lastFragTimestamp) { 24 | needsReload = true; 25 | lastFragTimestamp = fragTimestamp; 26 | } 27 | } else { 28 | fragName = ""; 29 | } 30 | 31 | string vertName = name + ".vs"; 32 | ofFile vertFile(vertName); 33 | if(vertFile.exists()) { 34 | Poco::Timestamp vertTimestamp = Poco::File(vertFile.getAbsolutePath()).getLastModified(); 35 | if(vertTimestamp != lastVertTimestamp) { 36 | needsReload = true; 37 | lastVertTimestamp = vertTimestamp; 38 | } 39 | } else { 40 | vertName = ""; 41 | } 42 | 43 | if(needsReload) { 44 | ofShader::load(vertName, fragName); 45 | } 46 | } 47 | private: 48 | string name; 49 | Poco::Timestamp lastFragTimestamp, lastVertTimestamp; 50 | }; 51 | -------------------------------------------------------------------------------- /SignalPlot/src/LinePlot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "PlotUtilities.h" 5 | 6 | class LinePlot { 7 | private: 8 | ofVboMesh polyline; 9 | int counter = 0; 10 | float min = 0, max = 0; 11 | bool minmaxSet = false; 12 | bool valid(float data) { 13 | return data == data; 14 | } 15 | 16 | public: 17 | LinePlot() { 18 | polyline.setMode(OF_PRIMITIVE_LINE_STRIP); 19 | } 20 | void add(float data) { 21 | if(valid(data)) { 22 | if(minmaxSet) { 23 | min = MIN(min, data); 24 | max = MAX(max, data); 25 | } else { 26 | min = data, max = data; 27 | minmaxSet = true; 28 | } 29 | polyline.addVertex(ofVec2f(counter, data)); 30 | } 31 | counter++; 32 | } 33 | template 34 | void set(const vector& data) { 35 | for(int i = 0; i < data.size(); i++) { 36 | add(data[i]); 37 | } 38 | } 39 | unsigned int size() { 40 | return polyline.getNumVertices(); 41 | } 42 | void draw(float w, float h) { 43 | float xr = counter; 44 | float yr = max - min; 45 | ofPushStyle(); 46 | ofPushMatrix(); 47 | ofNoFill(); 48 | scaleAndTranslate(ofRectangle(0, min, xr, yr), ofRectangle(0, h, w, -h)); 49 | polyline.setMode(OF_PRIMITIVE_LINE_STRIP); 50 | polyline.draw(); 51 | polyline.setMode(OF_PRIMITIVE_POINTS); 52 | glPointSize(3); 53 | polyline.draw(); 54 | ofSetColor(ofGetStyle().color, 128); 55 | ofDrawLine(0, 0, size(), 0); 56 | ofDrawLine(0, 1, size(), 1); 57 | ofDrawLine(0, -1, size(), -1); 58 | ofPopMatrix(); 59 | ofPopStyle(); 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /SignalPlot/src/Markers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class Markers { 6 | public: 7 | class Marker { 8 | public: 9 | float position; 10 | string name; 11 | Marker(float position = 0, string name = "") 12 | :position(position) 13 | ,name(name) { 14 | } 15 | }; 16 | vector markers; 17 | void addMarker(float position, string name = "") { 18 | markers.push_back(Marker(position, name)); 19 | } 20 | int getRegion(float position) { 21 | int maxMarker = markers.size() - 1; 22 | for(int i = 0; i < markers.size(); i++) { 23 | if(markers[i].position > position) { 24 | maxMarker = i; 25 | break; 26 | } 27 | } 28 | return MAX(maxMarker - 1, 0); 29 | } 30 | void draw(float length, float w, float h) { 31 | if(length > 0) { 32 | ofPushMatrix(); 33 | ofScale(w / length, 1); 34 | for(int i = 0; i < markers.size(); i++) { 35 | float x = markers[i].position; 36 | ofDrawLine(x, 0, x, h); 37 | } 38 | ofPopMatrix(); 39 | } 40 | } 41 | }; -------------------------------------------------------------------------------- /SignalPlot/src/PlotUtilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | inline void scaleAndTranslate(const ofRectangle& from, const ofRectangle& to) { 6 | ofTranslate(to.x, to.y); 7 | ofScale(to.width, to.height); 8 | ofScale(1. / from.width, 1. / from.height); 9 | ofTranslate(-from.x, -from.y); 10 | } -------------------------------------------------------------------------------- /SignalPlot/src/ZoomableRegion.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class ZoomableRegion { 6 | private: 7 | float speed = 5; 8 | float zoom = 1, offset = 1; 9 | float startZoom, startOffset; 10 | ofVec2f startDrag; 11 | float width, height; 12 | public: 13 | ZoomableRegion() { 14 | ofAddListener(ofEvents().mouseDragged , this, &ZoomableRegion::mouseDragged); 15 | ofAddListener(ofEvents().mousePressed, this, &ZoomableRegion::mousePressed); 16 | } 17 | float unapply(float x) { 18 | return (x / zoom) - offset; 19 | } 20 | void begin(float width, float height) { 21 | this->width = width, this->height = height; 22 | float x = ofGetMouseX(); 23 | ofPushMatrix(); 24 | ofScale(zoom, 1); 25 | ofTranslate(offset, 0); 26 | } 27 | void end() { 28 | ofPopMatrix(); 29 | } 30 | void mouseDragged(ofMouseEventArgs& args) { 31 | ofVec2f diff = args - startDrag; 32 | zoom = startZoom * (1 + (exp((speed * diff.y) / height) - 1)); 33 | zoom = MAX(zoom, 1); 34 | offset = startOffset + (diff.x / zoom); 35 | float center = (startDrag.x) * (1 - zoom) / zoom; 36 | offset += center; 37 | offset = ofClamp(offset, width * (1 - zoom) / zoom, 0); 38 | } 39 | void mousePressed(ofMouseEventArgs& args) { 40 | startDrag = args; 41 | startZoom = zoom; 42 | float center = (args.x) * (1 - zoom) / zoom; 43 | startOffset = offset - center; 44 | } 45 | }; -------------------------------------------------------------------------------- /SignalPlot/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | #include "PlotUtilities.h" 4 | #include "LinePlot.h" 5 | #include "ZoomableRegion.h" 6 | #include "Markers.h" 7 | 8 | // 5th order high pass butterworth filter at 1.5 Hz from mkfilter 60Hz samplerate 9 | #define NZEROS 5 10 | #define NPOLES 5 11 | #define GAIN 1.289795686e+00 12 | static float highPassFilter(float input) { 13 | static float xv[NZEROS+1], yv[NPOLES+1]; 14 | static float runningLowAmp = 0; 15 | static float runningHighAmp = 0; 16 | xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; 17 | xv[5] = input / GAIN; 18 | yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; 19 | yv[5] = (xv[5] - xv[0]) + 5 * (xv[1] - xv[4]) + 10 * (xv[3] - xv[2]) 20 | + ( 0.6011158229 * yv[0]) + ( -3.3110475620 * yv[1]) 21 | + ( 7.3120812802 * yv[2]) + ( -8.0940554178 * yv[3]) 22 | + ( 4.4918309651 * yv[4]); 23 | return yv[5]; 24 | } 25 | 26 | static float lerp(float x, float y, float t) { 27 | return x*(1-t) + y*(t); 28 | } 29 | 30 | struct agcDoubleFilter{ 31 | float smoothing = .001; 32 | float min = 0; 33 | float max = 0; 34 | float run(float x) { 35 | if(x <= min) { 36 | min = x; 37 | } else { 38 | min = lerp(min, x, smoothing); 39 | } 40 | if(x >= max) { 41 | max = x; 42 | } else { 43 | max = lerp(max, x, smoothing); 44 | } 45 | return (x - min) / (max - min); 46 | } 47 | }; 48 | 49 | struct agcSingleFilter{ 50 | float smoothingRising = .9; 51 | float smoothingFalling = .002; 52 | float max = 0; 53 | float run(float x) { 54 | if(x >= max) { 55 | max = lerp(max, x, smoothingRising); 56 | } else { 57 | max = lerp(max, x, smoothingFalling); 58 | } 59 | return x / max; 60 | } 61 | }; 62 | 63 | struct derivativeFilter { 64 | float px = 0; 65 | float run(float x) { 66 | float cur = x - px; 67 | px = x; 68 | return cur; 69 | } 70 | }; 71 | 72 | float unsignedToSigned(float x) { 73 | return (x * 2) - 1; 74 | } 75 | 76 | // peak filter triggers immediately but is rate limited 77 | static bool rateLimitedPeakFilter(bool input) { 78 | static long previousPeak = 0; 79 | static const long rateLimit = 20; // 180 bpm at 60 Hz (60 * 60 / 180) 80 | if(input && previousPeak > rateLimit) { 81 | previousPeak = 0; 82 | return true; 83 | } else { 84 | previousPeak++; 85 | return false; 86 | } 87 | } 88 | 89 | const float minBpm = 30, maxBpm = 150; 90 | bool rangeFilter(float input) { 91 | static const int count = 3; 92 | static float recent[count]; 93 | static const float range = 2.; 94 | if(input < minBpm || input > maxBpm) { 95 | return false; 96 | } 97 | int inRange = 0; 98 | for(int i = 0; i < count; i++) { 99 | if(recent[i] / range < input && recent[i] * range > input) { 100 | inRange++; 101 | } 102 | recent[i] = recent[i + 1]; 103 | } 104 | recent[count - 1] = input; 105 | return (inRange + 1 >= count); 106 | } 107 | float bpmFilter(unsigned long timeMs) { 108 | static unsigned long previousTimeMs = 0; 109 | float curBpm = (60. * 1000.) / (timeMs - previousTimeMs); 110 | previousTimeMs = timeMs; 111 | return curBpm; 112 | } 113 | 114 | bool heartbeatFilter(float x, unsigned long timeMs) { 115 | static derivativeFilter derivativea, derivativeb; 116 | static agcDoubleFilter agca; 117 | static agcSingleFilter agcb; 118 | static float smoothBpm = 60; 119 | static float prevBpm = 60; 120 | if(x != x) { 121 | return false; 122 | } 123 | x = highPassFilter(x); 124 | x = agca.run(x); 125 | x = unsignedToSigned(x); 126 | x = derivativea.run(x); 127 | x = derivativeb.run(x); 128 | x = abs(x); 129 | x = agcb.run(x); 130 | x = rateLimitedPeakFilter(x > .5); 131 | bool beat = false; 132 | if(x) { 133 | float filteredBpm = bpmFilter(timeMs); 134 | if(rangeFilter(filteredBpm)) { 135 | x = filteredBpm; 136 | prevBpm = filteredBpm; 137 | beat = true; 138 | } else { 139 | x = prevBpm; 140 | } 141 | } else { 142 | x = prevBpm; 143 | } 144 | smoothBpm = lerp(smoothBpm, x, .005); 145 | return beat; 146 | // return smoothBpm; 147 | } 148 | 149 | void analyzeHeartRate(vector& data, vector& clean, vector& analysis) { 150 | derivativeFilter derivativea, derivativeb; 151 | agcDoubleFilter agca; 152 | agcSingleFilter agcb; 153 | clean.resize(data.size()); 154 | analysis.resize(data.size()); 155 | float smoothBpm = 60; 156 | float prevBpm = 60; 157 | for(int i = 0; i < data.size(); i++) { 158 | float x = data[i]; 159 | float strength; 160 | clean[i] = x; 161 | x = highPassFilter(x); 162 | x = agca.run(x); 163 | x = unsignedToSigned(x); 164 | x = derivativea.run(x); 165 | x = derivativeb.run(x); 166 | x = abs(x); 167 | x = agcb.run(x); 168 | x = rateLimitedPeakFilter(x > .5); 169 | if(x) { 170 | unsigned long timeMs = i * 1000 / 60.; 171 | float y = bpmFilter(timeMs); 172 | if(rangeFilter(y)) { 173 | ofLog() << (int) y << " bpm"; 174 | x = y; 175 | prevBpm = y; 176 | } else { 177 | ofLog() << (int) y << " bpm (ignored)"; 178 | x = prevBpm; 179 | } 180 | } else { 181 | if(i == 0) x = 60; 182 | else x = prevBpm; 183 | } 184 | smoothBpm = lerp(smoothBpm, x, .005); 185 | analysis[i] = smoothBpm; 186 | } 187 | } 188 | 189 | Markers buildHeartRateMarkers(vector& data) { 190 | Markers result; 191 | for(int i = 0; i < data.size(); i++) { 192 | if(heartbeatFilter(data[i], i * 1000 / 60.)) { 193 | result.addMarker(i); 194 | } 195 | } 196 | return result; 197 | } 198 | 199 | class ofApp : public ofBaseApp { 200 | public: 201 | vector data; 202 | LinePlot clean, analysis; 203 | ZoomableRegion zoomable; 204 | Markers markers; 205 | 206 | void setup() { 207 | ofBackground(0); 208 | loadData("kyle-yun.csv"); 209 | } 210 | void draw() { 211 | zoomable.begin(ofGetWidth(), ofGetHeight()); 212 | ofSetColor(255, 255, 0); 213 | markers.draw(clean.size(), ofGetWidth(), ofGetHeight()); 214 | analysis.draw(ofGetWidth(), ofGetHeight()); 215 | ofSetColor(255); 216 | clean.draw(ofGetWidth(), ofGetHeight()); 217 | zoomable.end(); 218 | } 219 | void loadData(string filename) { 220 | ofBuffer buffer = ofBufferFromFile(filename); 221 | data = vector(); 222 | for(auto line : buffer.getLines()) { 223 | data.push_back(ofToFloat(line)); 224 | } 225 | markers = buildHeartRateMarkers(data); 226 | vector cleanData, analysisData; 227 | analyzeHeartRate(data, cleanData, analysisData); 228 | clean = LinePlot(); 229 | clean.set(cleanData); 230 | analysis = LinePlot(); 231 | analysis.set(analysisData); 232 | } 233 | void dragEvent(ofDragInfo dragInfo) { 234 | if(dragInfo.files.size()) { 235 | loadData(dragInfo.files.front()); 236 | } 237 | } 238 | }; 239 | int main() { 240 | ofSetupOpenGL(1024, 512, OF_WINDOW); 241 | ofSetWindowShape(2048, 512); 242 | ofRunApp(new ofApp()); 243 | } 244 | -------------------------------------------------------------------------------- /SignalPlotLomb/src/LinePlot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "PlotUtilities.h" 5 | 6 | class LinePlot { 7 | private: 8 | ofVboMesh polyline; 9 | int counter = 0; 10 | float min = 0, max = 0; 11 | bool minmaxSet = false; 12 | bool valid(float data) { 13 | return data == data; 14 | } 15 | 16 | public: 17 | LinePlot() { 18 | polyline.setMode(OF_PRIMITIVE_LINE_STRIP); 19 | } 20 | void add(float data) { 21 | if(valid(data)) { 22 | if(minmaxSet) { 23 | min = MIN(min, data); 24 | max = MAX(max, data); 25 | } else { 26 | min = data, max = data; 27 | minmaxSet = true; 28 | } 29 | polyline.addVertex(ofVec2f(counter, data)); 30 | } 31 | counter++; 32 | } 33 | template 34 | void set(const vector& data) { 35 | for(int i = 0; i < data.size(); i++) { 36 | add(data[i]); 37 | } 38 | } 39 | unsigned int size() { 40 | return polyline.getNumVertices(); 41 | } 42 | void draw(float w, float h) { 43 | float xr = counter; 44 | float yr = max - min; 45 | ofPushMatrix(); 46 | ofNoFill(); 47 | scaleAndTranslate(ofRectangle(0, min, xr, yr), ofRectangle(0, h, w, -h)); 48 | polyline.setMode(OF_PRIMITIVE_LINE_STRIP); 49 | polyline.draw(); 50 | polyline.setMode(OF_PRIMITIVE_POINTS); 51 | glPointSize(3); 52 | polyline.draw(); 53 | ofPopMatrix(); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /SignalPlotLomb/src/PlotUtilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | inline void scaleAndTranslate(const ofRectangle& from, const ofRectangle& to) { 6 | ofTranslate(to.x, to.y); 7 | ofScale(to.width, to.height); 8 | ofScale(1. / from.width, 1. / from.height); 9 | ofTranslate(-from.x, -from.y); 10 | } -------------------------------------------------------------------------------- /SignalPlotLomb/src/ZoomableRegion.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class ZoomableRegion { 6 | private: 7 | float speed = 5; 8 | float zoom = 1, offset = 1; 9 | float startZoom, startOffset; 10 | ofVec2f startDrag; 11 | float width, height; 12 | public: 13 | ZoomableRegion() { 14 | ofAddListener(ofEvents().mouseDragged , this, &ZoomableRegion::mouseDragged); 15 | ofAddListener(ofEvents().mousePressed, this, &ZoomableRegion::mousePressed); 16 | } 17 | float unapply(float x) { 18 | return (x / zoom) - offset; 19 | } 20 | void begin(float width, float height) { 21 | this->width = width, this->height = height; 22 | float x = ofGetMouseX(); 23 | ofPushMatrix(); 24 | ofScale(zoom, 1); 25 | ofTranslate(offset, 0); 26 | } 27 | void end() { 28 | ofPopMatrix(); 29 | } 30 | void mouseDragged(ofMouseEventArgs& args) { 31 | ofVec2f diff = args - startDrag; 32 | zoom = startZoom * (1 + (exp((speed * diff.y) / height) - 1)); 33 | zoom = MAX(zoom, 1); 34 | offset = startOffset + (diff.x / zoom); 35 | float center = (startDrag.x) * (1 - zoom) / zoom; 36 | offset += center; 37 | offset = ofClamp(offset, width * (1 - zoom) / zoom, 0); 38 | } 39 | void mousePressed(ofMouseEventArgs& args) { 40 | startDrag = args; 41 | startZoom = zoom; 42 | float center = (args.x) * (1 - zoom) / zoom; 43 | startOffset = offset - center; 44 | } 45 | }; -------------------------------------------------------------------------------- /SignalPlotLomb/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | #include "PlotUtilities.h" 4 | #include "LinePlot.h" 5 | #include "ZoomableRegion.h" 6 | 7 | // 5th order high pass butterworth filter at 1.5 Hz from mkfilter 60Hz samplerate 8 | #define NZEROS 5 9 | #define NPOLES 5 10 | #define GAIN 1.289795686e+00 11 | static float highPassFilter(float input) { 12 | static float xv[NZEROS+1], yv[NPOLES+1]; 13 | static float runningLowAmp = 0; 14 | static float runningHighAmp = 0; 15 | xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; 16 | xv[5] = input / GAIN; 17 | yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; 18 | yv[5] = (xv[5] - xv[0]) + 5 * (xv[1] - xv[4]) + 10 * (xv[3] - xv[2]) 19 | + ( 0.6011158229 * yv[0]) + ( -3.3110475620 * yv[1]) 20 | + ( 7.3120812802 * yv[2]) + ( -8.0940554178 * yv[3]) 21 | + ( 4.4918309651 * yv[4]); 22 | return yv[5]; 23 | } 24 | 25 | #define random ofRandom 26 | #define map ofMap 27 | 28 | vector hann(const vector& x) { 29 | int n = x.size(); 30 | vector result = vector(n); 31 | for(int i = 0; i < n; i++) { 32 | float weight = .5 * (1 - cos((TWO_PI * i) / (n - 1))); 33 | result[i] = x[i] * weight; 34 | } 35 | return result; 36 | } 37 | 38 | vector range(float start, float step, float end) { 39 | vector result = vector(); 40 | for(float t = start; t < end; t += step) { 41 | result.push_back(t); 42 | } 43 | return result; 44 | } 45 | 46 | vector range(float start, float end) { 47 | return range(start, 1, end); 48 | } 49 | 50 | vector rand(int count) { 51 | vector result = vector(count); 52 | for(int i = 0; i < count; i++) { 53 | result[i] = random(1); 54 | } 55 | return result; 56 | } 57 | 58 | vector mult(float x, const vector& y) { 59 | int n = y.size(); 60 | vector result = vector(n); 61 | for(int i = 0; i < n; i++) { 62 | result[i] = x * y[i]; 63 | } 64 | return result; 65 | } 66 | 67 | vector dotasterisk(const vector& x, const vector& y) { 68 | int n = y.size(); 69 | vector result = vector(n); 70 | for(int i = 0; i < n; i++) { 71 | result[i] = x[i] * y[i]; 72 | } 73 | return result; 74 | } 75 | 76 | vector add(float x, const vector& y) { 77 | int n = y.size(); 78 | vector result = vector(n); 79 | for(int i = 0; i < n; i++) { 80 | result[i] = x + y[i]; 81 | } 82 | return result; 83 | } 84 | 85 | vector add(const vector& x, const vector& y) { 86 | int n = y.size(); 87 | vector result = vector(n); 88 | for(int i = 0; i < n; i++) { 89 | result[i] = x[i] + y[i]; 90 | } 91 | return result; 92 | } 93 | 94 | vector interp1(const vector& x, const vector& v, const vector& xq) { 95 | int n = xq.size(); 96 | int m = x.size(); 97 | vector result = vector(n); 98 | for(int i = 0; i < n; i++) { 99 | float curq = xq[i]; 100 | int prej = 0, curj = 0; 101 | float prex = x[0], curx = x[0]; 102 | for(int j = 1; j < m; j++) { 103 | curj = j; 104 | curx = x[j]; 105 | if(prex <= curq && curx > curq) { 106 | break; 107 | } else { 108 | prej = curj; 109 | prex = curx; 110 | } 111 | } 112 | if(prex == curx) { 113 | result[i] = v[prej]; 114 | } else { 115 | result[i] = map(curq, prex, curx, v[prej], v[curj]); 116 | } 117 | } 118 | return result; 119 | } 120 | 121 | vector cos(const vector& x) { 122 | int n = x.size(); 123 | vector result = vector(n); 124 | for(int i = 0; i < n; i++) { 125 | result[i] = cos(x[i]); 126 | } 127 | return result; 128 | } 129 | 130 | vector sin(const vector& x) { 131 | int n = x.size(); 132 | vector result = vector(n); 133 | for(int i = 0; i < n; i++) { 134 | result[i] = cos(x[i]); 135 | } 136 | return result; 137 | } 138 | 139 | float sum(const vector& x) { 140 | float sum = 0; 141 | int n = x.size(); 142 | for(int i = 0; i < n; i++) { 143 | sum += x[i]; 144 | } 145 | return sum; 146 | } 147 | 148 | float mean(const vector& x) { 149 | return sum(x) / x.size(); 150 | } 151 | 152 | vector sq(const vector& x) { 153 | int n = x.size(); 154 | vector result = vector(n); 155 | for(int i = 0; i < n; i++) { 156 | result[i] = x[i] * x[i]; 157 | } 158 | return result; 159 | } 160 | 161 | float cov(const vector& x) { 162 | float ssd = sum(sq(add(-mean(x), x))); 163 | return ssd / x.size(); 164 | } 165 | 166 | float stddev(const vector& x) { 167 | return sqrt(cov(x)); 168 | } 169 | 170 | vector lomb(const vector& t, const vector& y, const vector& freq) { 171 | int nfreq = freq.size(); 172 | float fmax = freq[nfreq - 1]; 173 | float fmin = freq[0]; 174 | vector power = vector(nfreq); 175 | vector f4pi = mult(4*PI, freq); 176 | float var = cov(y); 177 | vector yn = add(-mean(y), y); 178 | for(int fi = 0; fi < nfreq; fi++) { 179 | float sinsum = sum(sin(mult(f4pi[fi], t))); 180 | float cossum = sum(cos(mult(f4pi[fi], t))); 181 | float tau = atan2(sinsum, cossum); 182 | vector argu = mult(TWO_PI * freq[fi], add(-tau, t)); 183 | vector cosarg = cos(argu); 184 | float cfi = sum(dotasterisk(yn, cosarg)); 185 | float cosnorm = sum(dotasterisk(cosarg, cosarg)); 186 | vector sinarg = sin(argu); 187 | float sfi = sum(dotasterisk(yn, sinarg)); 188 | float sinnorm = sum(dotasterisk(sinarg, sinarg)); 189 | power[fi] = (cfi*cfi/cosnorm+sfi*sfi/sinnorm)/(2*var); 190 | } 191 | return power; 192 | } 193 | 194 | vector cleanHeartRate(vector& data) { 195 | vector result; 196 | for(int i = 0; i < data.size(); i++) { 197 | float x = data[i]; 198 | x = highPassFilter(x); 199 | result.push_back(x); 200 | } 201 | return result; 202 | } 203 | 204 | float bpmToHz(float bpm) { 205 | return bpm / 60.; 206 | } 207 | 208 | class ofApp : public ofBaseApp { 209 | public: 210 | vector data; 211 | LinePlot plot, analysis; 212 | ZoomableRegion zoomable; 213 | 214 | void setup() { 215 | ofBackground(0); 216 | loadData("lauren-yun.csv"); 217 | } 218 | void draw() { 219 | zoomable.begin(ofGetWidth(), ofGetHeight()); 220 | ofSetColor(ofColor::yellow); 221 | analysis.draw(ofGetWidth(), ofGetHeight()); 222 | ofSetColor(255); 223 | plot.draw(ofGetWidth(), ofGetHeight()); 224 | zoomable.end(); 225 | } 226 | void loadData(string filename) { 227 | ofBuffer buffer = ofBufferFromFile(filename); 228 | data = vector(); 229 | for(auto line : buffer.getLines()) { 230 | data.push_back(ofToFloat(line)); 231 | } 232 | data = cleanHeartRate(data); 233 | plot = LinePlot(); 234 | plot.set(data); 235 | 236 | int n = data.size(); 237 | vector t = mult(1./60, range(0, n)); 238 | vector freq = range(bpmToHz(40), bpmToHz(1), bpmToHz(80)); 239 | vector lombData = lomb(t, data, freq); 240 | analysis = LinePlot(); 241 | analysis.set(lombData); 242 | } 243 | void dragEvent(ofDragInfo dragInfo) { 244 | if(dragInfo.files.size()) { 245 | loadData(dragInfo.files.front()); 246 | } 247 | } 248 | }; 249 | int main() { 250 | ofSetupOpenGL(1024, 512, OF_WINDOW); 251 | ofSetWindowShape(2048, 512); 252 | ofRunApp(new ofApp()); 253 | } 254 | -------------------------------------------------------------------------------- /SignalPlotWithScale/src/LinePlot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "PlotUtilities.h" 5 | 6 | class LinePlot { 7 | private: 8 | ofVboMesh polyline; 9 | int counter = 0; 10 | float min = 0, max = 0; 11 | bool minmaxSet = false; 12 | bool valid(float data) { 13 | return data == data; 14 | } 15 | 16 | public: 17 | LinePlot() { 18 | polyline.setMode(OF_PRIMITIVE_LINE_STRIP); 19 | } 20 | void add(float data) { 21 | if(valid(data)) { 22 | if(minmaxSet) { 23 | min = MIN(min, data); 24 | max = MAX(max, data); 25 | } else { 26 | min = data, max = data; 27 | minmaxSet = true; 28 | } 29 | polyline.addVertex(ofVec2f(counter, data)); 30 | } 31 | counter++; 32 | } 33 | template 34 | void set(const vector& data) { 35 | for(int i = 0; i < data.size(); i++) { 36 | add(data[i]); 37 | } 38 | } 39 | unsigned int size() { 40 | return polyline.getNumVertices(); 41 | } 42 | void draw(float w, float h) { 43 | float xr = counter; 44 | float yr = max - min; 45 | ofPushMatrix(); 46 | ofNoFill(); 47 | scaleAndTranslate(ofRectangle(0, min, xr, yr), ofRectangle(0, h, w, -h)); 48 | polyline.setMode(OF_PRIMITIVE_LINE_STRIP); 49 | polyline.draw(); 50 | polyline.setMode(OF_PRIMITIVE_POINTS); 51 | glPointSize(3); 52 | polyline.draw(); 53 | ofPopMatrix(); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /SignalPlotWithScale/src/Markers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class Markers { 6 | public: 7 | class Marker { 8 | public: 9 | float position; 10 | string name; 11 | Marker(float position = 0, string name = "") 12 | :position(position) 13 | ,name(name) { 14 | } 15 | }; 16 | vector markers; 17 | void addMarker(float position, string name = "") { 18 | markers.push_back(Marker(position, name)); 19 | } 20 | int getRegion(float position) { 21 | int maxMarker = markers.size() - 1; 22 | for(int i = 0; i < markers.size(); i++) { 23 | if(markers[i].position > position) { 24 | maxMarker = i; 25 | break; 26 | } 27 | } 28 | return MAX(maxMarker - 1, 0); 29 | } 30 | void draw(float length, float w, float h) { 31 | if(length > 0) { 32 | ofPushMatrix(); 33 | ofScale(w / length, 1); 34 | for(int i = 0; i < markers.size(); i++) { 35 | float x = markers[i].position; 36 | ofDrawLine(x, 0, x, h); 37 | } 38 | ofPopMatrix(); 39 | } 40 | } 41 | }; -------------------------------------------------------------------------------- /SignalPlotWithScale/src/PlotUtilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | inline void scaleAndTranslate(const ofRectangle& from, const ofRectangle& to) { 6 | ofTranslate(to.x, to.y); 7 | ofScale(to.width, to.height); 8 | ofScale(1. / from.width, 1. / from.height); 9 | ofTranslate(-from.x, -from.y); 10 | } -------------------------------------------------------------------------------- /SignalPlotWithScale/src/ZoomableRegion.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class ZoomableRegion { 6 | private: 7 | float speed = 5; 8 | float zoom = 1, offset = 1; 9 | float startZoom, startOffset; 10 | ofVec2f startDrag; 11 | float width, height; 12 | public: 13 | ZoomableRegion() { 14 | ofAddListener(ofEvents().mouseDragged , this, &ZoomableRegion::mouseDragged); 15 | ofAddListener(ofEvents().mousePressed, this, &ZoomableRegion::mousePressed); 16 | } 17 | float unapply(float x) { 18 | return (x / zoom) - offset; 19 | } 20 | void begin(float width, float height) { 21 | this->width = width, this->height = height; 22 | float x = ofGetMouseX(); 23 | ofPushMatrix(); 24 | ofScale(zoom, 1); 25 | ofTranslate(offset, 0); 26 | } 27 | void end() { 28 | ofPopMatrix(); 29 | } 30 | void mouseDragged(ofMouseEventArgs& args) { 31 | ofVec2f diff = args - startDrag; 32 | zoom = startZoom * (1 + (exp((speed * diff.y) / height) - 1)); 33 | zoom = MAX(zoom, 1); 34 | offset = startOffset + (diff.x / zoom); 35 | float center = (startDrag.x) * (1 - zoom) / zoom; 36 | offset += center; 37 | offset = ofClamp(offset, width * (1 - zoom) / zoom, 0); 38 | } 39 | void mousePressed(ofMouseEventArgs& args) { 40 | startDrag = args; 41 | startZoom = zoom; 42 | float center = (args.x) * (1 - zoom) / zoom; 43 | startOffset = offset - center; 44 | } 45 | }; -------------------------------------------------------------------------------- /SignalPlotWithScale/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | #include "PlotUtilities.h" 4 | #include "LinePlot.h" 5 | #include "ZoomableRegion.h" 6 | #include "Markers.h" 7 | 8 | // 5th order high pass butterworth filter at 1.5 Hz from mkfilter 60Hz samplerate 9 | #define NZEROS 5 10 | #define NPOLES 5 11 | #define GAIN 1.289795686e+00 12 | static float highPassFilter(float input) { 13 | static float xv[NZEROS+1], yv[NPOLES+1]; 14 | static float runningLowAmp = 0; 15 | static float runningHighAmp = 0; 16 | xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; 17 | xv[5] = input / GAIN; 18 | yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; 19 | yv[5] = (xv[5] - xv[0]) + 5 * (xv[1] - xv[4]) + 10 * (xv[3] - xv[2]) 20 | + ( 0.6011158229 * yv[0]) + ( -3.3110475620 * yv[1]) 21 | + ( 7.3120812802 * yv[2]) + ( -8.0940554178 * yv[3]) 22 | + ( 4.4918309651 * yv[4]); 23 | return yv[5]; 24 | } 25 | 26 | // finds a scaling factor on x that minimizes the difference 27 | static float getScale(float x[], float y[], int n) { 28 | float sumxy = 0, sumx2 = 0; 29 | for(int i = 0; i < n; i++) { 30 | sumxy += x[i] * y[i]; 31 | sumx2 += x[i] * x[i]; 32 | } 33 | return sumxy / (2 * sumx2); 34 | } 35 | 36 | // heart kernel based on observation at 60Hz samplerate 37 | static float heartFilter(float input) { 38 | static const int heartKernelSize = 9; 39 | static float heartHistory [heartKernelSize]; 40 | static float heartKernel [] = { 41 | -0.000312664, -0.00870198, -0.076416, -0.179242, 0, 42 | 0.179242, 0.076416, 0.00870198, 0.000312664}; 43 | for(int i = 0; i < heartKernelSize - 1; i++) { 44 | heartHistory[i] = heartHistory[i + 1]; 45 | } 46 | heartHistory[heartKernelSize - 1] = input; 47 | float scale = getScale(heartHistory, heartKernel, heartKernelSize); 48 | scale = MAX(0, scale); // only correctly oriented heartbeats 49 | static float movingScale = 1; 50 | movingScale = movingScale * .25 + scale * .75; 51 | float sumSquaredDiffs = 0; 52 | for(int i = 0; i < heartKernelSize; i++) { 53 | // float diff = heartHistory[i] - heartKernel[i]; 54 | float diff = movingScale * heartHistory[i] - heartKernel[i]; 55 | sumSquaredDiffs += diff * diff; 56 | } 57 | // return input; 58 | return -sqrt(sumSquaredDiffs); 59 | // return scale; 60 | } 61 | 62 | // moving min filter to introduce some hysteresis 63 | static float movingMaxFilter(float input) { 64 | static float hysteresis = .01; 65 | static float max = 0; 66 | if(input > max) { 67 | max = input; 68 | } else { 69 | max = (hysteresis * input) + ((1-hysteresis) * max); 70 | } 71 | return max; 72 | } 73 | 74 | // rising values filter checks for onsets 75 | static bool risingFilter(float input) { 76 | static float previous = 0; 77 | bool rising = input > previous; 78 | previous = input; 79 | return rising; 80 | } 81 | 82 | // peak filter triggers immediately but is rate limited 83 | static bool rateLimitedPeakFilter(bool input) { 84 | static long previousPeak = 0; 85 | static const long rateLimit = 20; // 180 bpm at 60 Hz (60 * 60 / 180) 86 | if(input && previousPeak > rateLimit) { 87 | previousPeak = 0; 88 | return true; 89 | } else { 90 | previousPeak++; 91 | return false; 92 | } 93 | } 94 | 95 | bool rangeFilter(float input) { 96 | static const int count = 3; 97 | static float recent[count]; 98 | static const float range = 2.; 99 | bool inRange = true; 100 | for(int i = 0; i < count; i++) { 101 | if(recent[i] / range > input || recent[i] * range < input) { 102 | inRange = false; 103 | } 104 | recent[i] = recent[i + 1]; 105 | } 106 | recent[count - 1] = input; 107 | return inRange; 108 | } 109 | 110 | float stddevFilter(float input) { 111 | static const int count = 5; 112 | static float recent[count]; 113 | float sum = 0, sumSquaredDifferences = 0; 114 | for(int i = 0; i < count; i++) { 115 | recent[i] = recent[i + 1]; 116 | sum += recent[i]; 117 | } 118 | float mean = sum / count; 119 | for(int i = 0; i < count; i++) { 120 | float diff = recent[i] - mean; 121 | sumSquaredDifferences = diff * diff; 122 | } 123 | recent[count - 1] = input; 124 | return sqrt(sumSquaredDifferences / count); 125 | } 126 | 127 | float bpmFilter(unsigned long timeMs) { 128 | static unsigned long previousTimeMs = 0; 129 | float curBpm = (60. * 1000.) / (timeMs - previousTimeMs); 130 | previousTimeMs = timeMs; 131 | return curBpm; 132 | } 133 | 134 | bool heartbeatFilter(float x, unsigned long timeMs) { 135 | if(x != x) { 136 | return false; 137 | } 138 | x = highPassFilter(x); 139 | x = heartFilter(x); 140 | x = movingMaxFilter(x); 141 | bool curBeat = risingFilter(x); 142 | // curBeat = rateLimitedPeakFilter(curBeat); 143 | if(curBeat) { 144 | // return rangeFilter(bpmFilter(timeMs)); 145 | return timeMs; 146 | } 147 | return false; 148 | } 149 | 150 | vector cleanHeartRate(vector& data) { 151 | vector result; 152 | for(int i = 0; i < data.size(); i++) { 153 | float x = data[i]; 154 | float strength; 155 | x = highPassFilter(x); 156 | // x = heartFilter(x); 157 | // x = movingMaxFilter(x); 158 | // x = risingFilter(x); 159 | // x = rateLimitedPeakFilter(x); 160 | // if(rateLimitedPeakFilter(x)) { 161 | // x = bpmFilter(i * 1000 / 60.); 162 | // x = stddevFilter(x); 163 | // } else { 164 | // if(result.empty()) x = 0; 165 | // else x = result.back(); 166 | // } 167 | result.push_back(x); 168 | } 169 | return result; 170 | } 171 | 172 | Markers buildHeartRateMarkers(vector& data) { 173 | Markers result; 174 | for(int i = 0; i < data.size(); i++) { 175 | if(heartbeatFilter(data[i], i * 1000 / 60.)) { 176 | result.addMarker(i); 177 | } 178 | } 179 | return result; 180 | } 181 | 182 | class ofApp : public ofBaseApp { 183 | public: 184 | vector data; 185 | LinePlot plot; 186 | ZoomableRegion zoomable; 187 | Markers markers; 188 | 189 | void setup() { 190 | ofBackground(0); 191 | loadData("lauren-yun.csv"); 192 | } 193 | void draw() { 194 | zoomable.begin(ofGetWidth(), ofGetHeight()); 195 | ofSetColor(255, 255, 0); 196 | markers.draw(plot.size(), ofGetWidth(), ofGetHeight()); 197 | ofSetColor(255); 198 | plot.draw(ofGetWidth(), ofGetHeight()); 199 | zoomable.end(); 200 | } 201 | void loadData(string filename) { 202 | ofBuffer buffer = ofBufferFromFile(filename); 203 | data = vector(); 204 | for(auto line : buffer.getLines()) { 205 | data.push_back(ofToFloat(line)); 206 | } 207 | markers = buildHeartRateMarkers(data); 208 | data = cleanHeartRate(data); 209 | plot = LinePlot(); 210 | plot.set(data); 211 | } 212 | void dragEvent(ofDragInfo dragInfo) { 213 | if(dragInfo.files.size()) { 214 | loadData(dragInfo.files.front()); 215 | } 216 | } 217 | }; 218 | int main() { 219 | ofSetupOpenGL(1024, 512, OF_WINDOW); 220 | ofSetWindowShape(2048, 512); 221 | ofRunApp(new ofApp()); 222 | } 223 | -------------------------------------------------------------------------------- /SimpleParticleSystem/src/Force.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Force.h" 4 | #include "Particle.h" 5 | 6 | void drawArrow(ofVec2f begin, ofVec2f end) { 7 | ofLine(begin, end); 8 | ofVec2f side = begin - end; 9 | side.normalize(); 10 | side *= 4; 11 | side.rotate(45); 12 | ofLine(end, end + side); 13 | side.rotate(-90); 14 | ofLine(end, end + side); 15 | } 16 | 17 | ForceLine::ForceLine(ofVec2f begin, ofVec2f end, float radius, float magnitude, float minRadius) 18 | :begin(begin) 19 | ,end(end) 20 | ,radius(radius) 21 | ,magnitude(magnitude) 22 | ,minRadius(minRadius) { 23 | } 24 | 25 | ofVec2f ForceLine::getForce(Particle& particle) const { 26 | ofVec2f line = end - begin; 27 | const ofVec2f& p = particle.getPosition(); 28 | float u = ((p.x - begin.x) * (end.x - begin.x) + (p.y - begin.y) * (end.y - begin.y)) / line.lengthSquared(); 29 | if(u < 0 || u > 1) { 30 | return ofVec2f(0); 31 | } 32 | ofVec2f inter = begin.getInterpolated(end, u); 33 | ofVec2f diff = p - inter; 34 | float length = diff.length(); 35 | if(length < minRadius || length > radius) { 36 | return ofVec2f(0); 37 | } else { 38 | diff.normalize(); 39 | diff *= magnitude / length; 40 | return diff; 41 | } 42 | } 43 | 44 | void ForceLine::draw() const { 45 | ofLine(begin, end); 46 | ofVec2f side = end - begin; 47 | side.rotate(90); 48 | side.normalize(); 49 | side *= radius; 50 | ofPushStyle(); 51 | ofSetColor(128); 52 | for(int i = 0; i < 8; i++) { 53 | ofVec2f cur = begin.getInterpolated(end, ofMap(i, 0, 7, 0, 1)); 54 | if(magnitude > 0) { 55 | drawArrow(cur, cur + side); 56 | drawArrow(cur, cur - side); 57 | } else { 58 | drawArrow(cur + side, cur); 59 | drawArrow(cur - side, cur); 60 | } 61 | } 62 | ofPopStyle(); 63 | } 64 | 65 | ForceCircle::ForceCircle(float x, float y, float radius, float magnitude, float minRadius) 66 | :center(ofVec2f(x, y)) 67 | ,radius(radius) 68 | ,magnitude(magnitude) 69 | ,minRadius(minRadius) { 70 | } 71 | 72 | ofVec2f ForceCircle::getForce(Particle& particle) const { 73 | ofVec2f diff = particle.getPosition() - center; 74 | float length = diff.length(); 75 | if(length < minRadius || length > radius) { 76 | return ofVec2f(0); 77 | } else { 78 | diff.normalize(); 79 | diff *= magnitude / length; 80 | return diff; 81 | } 82 | } 83 | 84 | void ForceCircle::draw() const { 85 | ofPushMatrix(); 86 | ofTranslate(center); 87 | ofPushStyle(); 88 | ofNoFill(); 89 | ofCircle(0, 0, radius); 90 | ofSetColor(128); 91 | for(int i = 0; i < 8; i++) { 92 | ofPushMatrix(); 93 | ofRotate(ofMap(i, 0, 8, 0, 360)); 94 | drawArrow(ofVec2f(radius, 0), ofVec2f(radius + (magnitude > 0 ? +8 : -8), 0)); 95 | ofPopMatrix(); 96 | } 97 | ofPopStyle(); 98 | ofPopMatrix(); 99 | } 100 | 101 | ForceFriction::ForceFriction(float magnitude) 102 | :magnitude(magnitude) { 103 | } 104 | 105 | ofVec2f ForceFriction::getForce(Particle& particle) const { 106 | return magnitude * particle.getVelocity(); 107 | } 108 | 109 | FieldDonut::FieldDonut(float x, float y, float radius, float magnitude, float minRadius) 110 | :center(ofVec2f(x, y)) 111 | ,radius(radius) 112 | ,magnitude(magnitude) 113 | ,minRadius(minRadius) { 114 | } 115 | 116 | ofVec2f FieldDonut::getForce(Particle& particle) const { 117 | ofVec2f diff = particle.getPosition() - center; 118 | float length = diff.length() - radius; 119 | if(fabsf(length) < minRadius) { 120 | return ofVec2f(0); 121 | } else { 122 | diff.normalize(); 123 | diff *= length * magnitude; 124 | return diff; 125 | } 126 | } 127 | 128 | void FieldDonut::draw() const { 129 | ofPushMatrix(); 130 | ofTranslate(center); 131 | ofPushStyle(); 132 | ofNoFill(); 133 | ofCircle(0, 0, radius); 134 | ofSetColor(128); 135 | for(int i = 0; i < 8; i++) { 136 | ofPushMatrix(); 137 | ofRotate(ofMap(i, 0, 8, 0, 360)); 138 | ofVec2f cur(radius, 0), side((magnitude > 0 ? +8 : -8), 0); 139 | if(magnitude > 0) { 140 | drawArrow(cur, cur + side); 141 | drawArrow(cur, cur - side); 142 | } else { 143 | drawArrow(cur + side, cur); 144 | drawArrow(cur - side, cur); 145 | } 146 | ofPopMatrix(); 147 | } 148 | ofPopStyle(); 149 | ofPopMatrix(); 150 | } 151 | 152 | 153 | FieldLine::FieldLine(ofVec2f begin, ofVec2f end, float magnitude, float minRadius) 154 | :begin(begin) 155 | ,end(end) 156 | ,magnitude(magnitude) 157 | ,minRadius(minRadius) { 158 | } 159 | 160 | ofVec2f FieldLine::getForce(Particle& particle) const { 161 | ofVec2f line = end - begin; 162 | const ofVec2f& p = particle.getPosition(); 163 | float u = ((p.x - begin.x) * (end.x - begin.x) + (p.y - begin.y) * (end.y - begin.y)) / line.lengthSquared(); 164 | ofVec2f inter = begin.getInterpolated(end, u); 165 | ofVec2f diff = p - inter; 166 | float length = diff.length(); 167 | if(length < minRadius) { 168 | return ofVec2f(0); 169 | } else { 170 | diff.normalize(); 171 | diff *= length * magnitude; 172 | return diff; 173 | } 174 | } 175 | 176 | void FieldLine::draw() const { 177 | ofLine(begin, end); 178 | ofVec2f side = end - begin; 179 | side.rotate(90); 180 | side.normalize(); 181 | side *= 32; 182 | ofPushStyle(); 183 | ofSetColor(128); 184 | for(int i = 0; i < 8; i++) { 185 | ofVec2f cur = begin.getInterpolated(end, ofMap(i, 0, 7, 0, 1)); 186 | if(magnitude > 0) { 187 | drawArrow(cur, cur + side); 188 | drawArrow(cur, cur - side); 189 | } else { 190 | drawArrow(cur + side, cur); 191 | drawArrow(cur - side, cur); 192 | } 193 | } 194 | ofPopStyle(); 195 | } -------------------------------------------------------------------------------- /SimpleParticleSystem/src/Force.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "Particle.h" 5 | 6 | class Particle; 7 | class Force { 8 | public: 9 | virtual ofVec2f getForce(Particle& particle) const = 0; 10 | virtual void draw() const = 0; 11 | }; 12 | 13 | class ForceLine : public Force { 14 | public: 15 | ForceLine(ofVec2f begin, ofVec2f end, float radius, float magnitude, float minRadius = 1); 16 | ofVec2f getForce(Particle& particle) const; 17 | void draw() const; 18 | protected: 19 | ofVec2f begin, end; 20 | float radius, magnitude, minRadius; 21 | }; 22 | 23 | class ForceCircle : public Force { 24 | public: 25 | ForceCircle(float x, float y, float radius, float magnitude, float minRadius = 1); 26 | ofVec2f getForce(Particle& particle) const; 27 | void draw() const; 28 | protected: 29 | ofVec2f center; 30 | float radius, magnitude, minRadius; 31 | }; 32 | 33 | class ForceFriction : public Force { 34 | public: 35 | ForceFriction(float magnitude); 36 | ofVec2f getForce(Particle& particle) const; 37 | void draw() const {} 38 | protected: 39 | float magnitude; 40 | }; 41 | 42 | class FieldDonut : public Force { 43 | public: 44 | FieldDonut(float x, float y, float radius, float magnitude, float minRadius = 1); 45 | ofVec2f getForce(Particle& particle) const; 46 | void draw() const; 47 | protected: 48 | ofVec2f center; 49 | float radius, magnitude, minRadius; 50 | }; 51 | 52 | class FieldLine : public Force { 53 | public: 54 | FieldLine(ofVec2f begin, ofVec2f end, float magnitude, float minRadius = 1); 55 | ofVec2f getForce(Particle& particle) const; 56 | void draw() const; 57 | protected: 58 | ofVec2f begin, end; 59 | float magnitude, minRadius; 60 | }; -------------------------------------------------------------------------------- /SimpleParticleSystem/src/Particle.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Particle.h" 4 | #include "Force.h" 5 | 6 | Particle::Particle(float x, float y) 7 | :position(ofVec2f(x, y)) 8 | ,maxVelocity(1) { 9 | } 10 | 11 | void Particle::addForce(ofPtr force) { 12 | forces.push_back(force); 13 | } 14 | 15 | void Particle::update(float timeStep) { 16 | force.set(0); 17 | for(int i = 0; i < forces.size(); i++) { 18 | force += forces[i]->getForce(*this); 19 | } 20 | velocity += force * timeStep; 21 | velocity.limit(maxVelocity); 22 | position += velocity * timeStep; 23 | } 24 | 25 | const ofVec2f& Particle::getPosition() const { 26 | return position; 27 | } 28 | 29 | const ofVec2f& Particle::getVelocity() const { 30 | return velocity; 31 | } 32 | 33 | void Particle::draw() const { 34 | ofCircle((int) position.x, (int) position.y, 1); 35 | } 36 | 37 | void Particle::setMaxVelocity(float maxVelocity) { 38 | this->maxVelocity = maxVelocity; 39 | } -------------------------------------------------------------------------------- /SimpleParticleSystem/src/Particle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class Force; 6 | class Particle { 7 | public: 8 | Particle(float x, float y); 9 | void addForce(ofPtr force); 10 | void update(float timeStep); 11 | const ofVec2f& getPosition() const; 12 | const ofVec2f& getVelocity() const; 13 | void setMaxVelocity(float maxVelocity); 14 | void draw() const; 15 | protected: 16 | ofVec2f position, velocity, force; 17 | vector > forces; 18 | float maxVelocity; 19 | }; 20 | -------------------------------------------------------------------------------- /SimpleParticleSystem/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1280, 720, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /SimpleParticleSystem/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup(){ 4 | ofSetVerticalSync(true); 5 | ofBackground(0); 6 | 7 | for(int i = 0; i < 1024; i++) { 8 | particles.push_back(Particle(ofRandomWidth(), ofRandomHeight())); 9 | } 10 | 11 | forces.push_back(ofPtr(new ForceFriction(-.01))); 12 | 13 | /* 14 | int w = ofGetWidth(), h = ofGetHeight(); 15 | forces.push_back(ofPtr(new FieldDonut(w / 2, h / 2, w / 6, -.01, 10))); 16 | forces.push_back(ofPtr(new FieldLine(ofVec2f(0, h / 2), ofVec2f(w, h / 2), -.01, 10))); 17 | */ 18 | 19 | for(int i = 0; i < 16; i++) { 20 | ofVec2f begin(ofRandomWidth(), ofRandomHeight()); 21 | ofVec2f end = begin + ofVec2f(ofRandomf(), ofRandomf()) * 500; 22 | float radius = ofRandom(5, 50); 23 | float magnitude = ofRandom(-2, +2); 24 | forces.push_back(ofPtr(new ForceLine(begin, end, radius, magnitude))); 25 | } 26 | 27 | for(int i = 0; i < 16; i++) { 28 | float x = ofRandomWidth(), y = ofRandomHeight(); 29 | float radius = ofRandom(10, 200), magnitude = ofRandom(-2, +2); 30 | forces.push_back(ofPtr(new ForceCircle(x, y, radius, magnitude))); 31 | } 32 | 33 | for(int i = 0; i < particles.size(); i++) { 34 | for(int j = 0; j < forces.size(); j++) { 35 | particles[i].addForce(forces[j]); 36 | } 37 | } 38 | } 39 | 40 | void ofApp::update() { 41 | for(int i = 0; i < particles.size(); i++) { 42 | particles[i].update(1); 43 | } 44 | } 45 | 46 | void ofApp::draw() { 47 | ofSetColor(255); 48 | for(int i = 0; i < particles.size(); i++) { 49 | particles[i].draw(); 50 | } 51 | for(int i = 0; i < forces.size(); i++) { 52 | forces[i]->draw(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SimpleParticleSystem/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "Force.h" 5 | #include "Particle.h" 6 | 7 | class ofApp : public ofBaseApp { 8 | public: 9 | void setup(); 10 | void update(); 11 | void draw(); 12 | 13 | vector > forces; 14 | vector particles; 15 | }; 16 | -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-debug.icns 10 | ICON_NAME_RELEASE = icon.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | //ICON_FILE_PATH = bin/data/ 15 | 16 | OTHER_LDFLAGS = $(OF_CORE_LIBS) 17 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 18 | -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/bin/data/matcap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/openFrameworksDemos/ae7d2f9f43884ef54bec44420994c49e2bf8081a/SphericalEnvironmentMapping/bin/data/matcap.jpg -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/bin/data/sem.frag: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | uniform sampler2D tMatCap; 4 | 5 | varying vec3 e; 6 | varying vec3 n; 7 | 8 | void main() { 9 | 10 | vec3 r = reflect( e, n ); 11 | //r = e - 2. * dot( n, e ) * n; 12 | float m = 2. * sqrt( pow( r.x, 2. ) + pow( r.y, 2. ) + pow( r.z + 1., 2. ) ); 13 | vec2 vN = r.xy / m + .5; 14 | 15 | vec3 base = texture2D( tMatCap, vN ).rgb; 16 | 17 | gl_FragColor = vec4( base, 1. ); 18 | 19 | } -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/bin/data/sem.vert: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | varying vec3 e; 4 | varying vec3 n; 5 | 6 | void main() { 7 | 8 | e = normalize( vec3( gl_ModelViewMatrix * vec4( gl_Vertex.xyz, 1.0 ) ) ); 9 | n = normalize( gl_NormalMatrix * gl_Normal ); 10 | 11 | gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; 12 | 13 | } -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/ofApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/ofApp.xcodeproj/project.xcworkspace/xcshareddata/ofApp.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | E73CBB43-4A74-48DA-ACAE-0582601AD9DB 9 | IDESourceControlProjectName 10 | ofApp 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | E67A4F6F-CCB2-427B-B008-C01CC58D3103 14 | ssh://github.com/kylemcdonald/openFrameworks.git 15 | EC9C09A2-5C09-44F7-BC4E-D7D4C555D45E 16 | ssh://github.com/kylemcdonald/openFrameworksDemos.git 17 | 18 | IDESourceControlProjectPath 19 | apps/openFrameworksDemos/SphericalEnvironmentMapping/ofApp.xcodeproj/project.xcworkspace 20 | IDESourceControlProjectRelativeInstallPathDictionary 21 | 22 | E67A4F6F-CCB2-427B-B008-C01CC58D3103 23 | ../../../../.. 24 | EC9C09A2-5C09-44F7-BC4E-D7D4C555D45E 25 | ../../.. 26 | 27 | IDESourceControlProjectURL 28 | ssh://github.com/kylemcdonald/openFrameworksDemos.git 29 | IDESourceControlProjectVersion 30 | 110 31 | IDESourceControlProjectWCCIdentifier 32 | E67A4F6F-CCB2-427B-B008-C01CC58D3103 33 | IDESourceControlProjectWCConfigurations 34 | 35 | 36 | IDESourceControlRepositoryExtensionIdentifierKey 37 | public.vcs.git 38 | IDESourceControlWCCIdentifierKey 39 | E67A4F6F-CCB2-427B-B008-C01CC58D3103 40 | IDESourceControlWCCName 41 | openFrameworks 42 | 43 | 44 | IDESourceControlRepositoryExtensionIdentifierKey 45 | public.vcs.git 46 | IDESourceControlWCCIdentifierKey 47 | EC9C09A2-5C09-44F7-BC4E-D7D4C555D45E 48 | IDESourceControlWCCName 49 | openFrameworksDemos 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/ofApp.xcodeproj/xcshareddata/xcschemes/ofApp Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/ofApp.xcodeproj/xcshareddata/xcschemes/ofApp Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | cc.openFrameworks.ofapp 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | CFBundleIconFile 20 | ${ICON} 21 | 22 | 23 | -------------------------------------------------------------------------------- /SphericalEnvironmentMapping/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | class ofApp : public ofBaseApp { 4 | public: 5 | ofImage matCap; 6 | ofVboMesh mesh; 7 | ofShader shader; 8 | ofEasyCam cam; 9 | 10 | void setup() { 11 | ofEnableDepthTest(); 12 | ofDisableArbTex(); 13 | matCap.load("matcap.jpg"); 14 | shader.load("sem"); 15 | mesh.load("mesh.ply"); 16 | cam.setTranslationKey('\t'); 17 | } 18 | 19 | void draw() { 20 | ofBackgroundGradient(64, 0); 21 | cam.begin(); 22 | shader.begin(); 23 | shader.setUniformTexture("tMatCap", matCap, 1); 24 | float scale = ofGetHeight() / 3; 25 | ofScale(scale, scale, scale); 26 | mesh.draw(); 27 | shader.end(); 28 | cam.end(); 29 | } 30 | 31 | void dragEvent(ofDragInfo dragInfo) { 32 | matCap.load(dragInfo.files[0]); 33 | matCap.update(); 34 | } 35 | }; 36 | 37 | int main() { 38 | ofSetupOpenGL(1024, 768, OF_WINDOW); 39 | ofRunApp(new ofApp()); 40 | } 41 | -------------------------------------------------------------------------------- /StackedPlot/src/StackedPlot.cpp: -------------------------------------------------------------------------------- 1 | #include "StackedPlot.h" 2 | 3 | float sum(const vector& x) { 4 | float sum = 0; 5 | for(int i = 0; i < x.size(); i++) { 6 | sum += x[i]; 7 | } 8 | return sum; 9 | } 10 | 11 | vector divide(const vector& x, float y) { 12 | vector out = x; 13 | for(int i = 0; i < out.size(); i++) { 14 | out[i] /= y; 15 | } 16 | return out; 17 | } 18 | 19 | vector normalize(const vector& x) { 20 | float summed = sum(x); 21 | return divide(x, summed); 22 | } 23 | 24 | vector accumulate(const vector& x) { 25 | vector out = x; 26 | for(int i = 1; i < out.size(); i++) { 27 | out[i] += out[i - 1]; 28 | } 29 | return out; 30 | } 31 | 32 | StackedPlot::StackedPlot() 33 | :historyLength(100) { 34 | } 35 | void StackedPlot::clear() { 36 | history.clear(); 37 | } 38 | void StackedPlot::addData(const vector& data) { 39 | if(size() && data.size() != dimensions()) { 40 | ofLogWarning("StackedPlot") << "added data does not have same size as existing data"; 41 | clear(); 42 | } 43 | vector normalized = normalize(data); 44 | vector accumulated = accumulate(normalized); 45 | vector all; 46 | all.push_back(0); 47 | all.insert(all.end(), accumulated.begin(), accumulated.end()); 48 | all.push_back(1); 49 | history.push_back(all); 50 | while(history.size() > historyLength) { 51 | history.pop_front(); 52 | } 53 | } 54 | void StackedPlot::addColor(ofColor color) { 55 | colors.push_back(color); 56 | } 57 | int StackedPlot::size() const { 58 | return history.size(); 59 | } 60 | int StackedPlot::dimensions() const { 61 | return size() ? history.front().size() - 2 : 0; 62 | } 63 | void StackedPlot::draw(float width, float height) const { 64 | ofPushMatrix(); 65 | ofPushStyle(); 66 | int d = dimensions(); 67 | vector meshes(d); 68 | for(int i = 0; i < d; i++) { 69 | meshes[i].setMode(OF_PRIMITIVE_TRIANGLE_STRIP); 70 | } 71 | list >::const_iterator itr; 72 | int i; 73 | for(itr = history.begin(), i = 0; itr != history.end(); itr++, i++) { 74 | const vector& cur = *itr; 75 | for(int j = 0; j < d; j++) { 76 | meshes[j].addVertex(ofVec2f(i, cur[j])); 77 | meshes[j].addVertex(ofVec2f(i, cur[j + 1])); 78 | } 79 | } 80 | ofScale(width / (historyLength - 1), height); 81 | for(int i = 0; i < d; i++) { 82 | if(colors.size()) { 83 | ofSetColor(colors[i % colors.size()]); 84 | } else { 85 | float hue = ofMap(i, 0, d, 0, 255); 86 | ofSetColor(ofColor::fromHsb(hue, 255, 255)); 87 | } 88 | meshes[i].draw(); 89 | } 90 | ofPopMatrix(); 91 | ofPopStyle(); 92 | } -------------------------------------------------------------------------------- /StackedPlot/src/StackedPlot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class StackedPlot { 6 | private: 7 | list > history; 8 | vector colors; 9 | public: 10 | int historyLength; 11 | 12 | StackedPlot(); 13 | void clear(); 14 | void addData(const vector& data); 15 | void addColor(ofColor color); 16 | int size() const; 17 | int dimensions() const; 18 | void draw(float width, float height) const; 19 | }; -------------------------------------------------------------------------------- /StackedPlot/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "StackedPlot.h" 3 | 4 | class ofApp : public ofBaseApp { 5 | public: 6 | StackedPlot plot; 7 | 8 | void setup() { 9 | plot.historyLength = 100; 10 | plot.addColor(ofColor::fromHex(0xF4C341)); 11 | plot.addColor(ofColor::fromHex(0x05A180)); 12 | plot.addColor(ofColor::fromHex(0xE25D48)); 13 | } 14 | void update() { 15 | vector data(3); 16 | data[0] = abs(mouseX); 17 | data[1] = abs(mouseY); 18 | data[2] = abs(sin(ofGetElapsedTimef())) * 100; 19 | plot.addData(data); 20 | } 21 | void draw() { 22 | plot.draw(ofGetWidth(), ofGetHeight()); 23 | } 24 | }; 25 | 26 | int main() { 27 | ofSetupOpenGL(300, 150, OF_WINDOW); 28 | ofRunApp(new ofApp()); 29 | } 30 | -------------------------------------------------------------------------------- /TextInputExample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | class SearchBar { 4 | protected: 5 | ofTrueTypeFont font; 6 | string value; 7 | int position; 8 | ofVec2f cursorPosition; 9 | ofVec2f cursorOffset; 10 | uint64_t lastTime; 11 | void updateCursor() { 12 | string substr = value.substr(0, position) + "."; 13 | ofRectangle box = font.getStringBoundingBox(substr, 0, 0); 14 | cursorPosition.x = box.width; 15 | } 16 | public: 17 | ofEvent valueChange; 18 | SearchBar() 19 | :position(0) 20 | ,cursorOffset(-4, 0) { 21 | } 22 | void setup(int fontSize) { 23 | font.load(OF_TTF_SANS, fontSize); 24 | ofAddListener(ofEvents().keyPressed, this, &SearchBar::keyPressed); 25 | updateCursor(); 26 | } 27 | void draw(float x, float y) { 28 | ofPushMatrix(); 29 | ofTranslate(x, y); 30 | font.drawString(value, 0, 0); 31 | uint64_t timeDiff = ofGetElapsedTimeMillis() - lastTime; 32 | if(timeDiff % 1500 < 1000) { 33 | float localX = .5 + int(cursorPosition.x + cursorOffset.x); 34 | ofDrawLine(localX, cursorOffset.y - font.getSize(), localX, cursorOffset.y - font.getDescenderHeight()); 35 | } 36 | ofPopMatrix(); 37 | } 38 | void keyPressed(ofKeyEventArgs& key) { 39 | string valueBefore = value; 40 | if(key.key == OF_KEY_LEFT) { 41 | position--; 42 | } else if(key.key == OF_KEY_RIGHT) { 43 | position++; 44 | } else if(key.key == OF_KEY_BACKSPACE) { 45 | if(position > 0) { 46 | value.erase(value.begin() + position - 1); 47 | position--; 48 | } 49 | } else if(key.key == OF_KEY_DEL) { 50 | if(position < value.length()) { 51 | value.erase(value.begin() + position); 52 | } 53 | // } else if(key.key == OF_KEY_RETURN) { 54 | // value.insert(position, "\n"); 55 | // position++; 56 | } else if(isprint(key.key)) { 57 | stringstream character; 58 | character << char(key.key); 59 | value.insert(position, character.str()); 60 | position++; 61 | } 62 | position = MAX(0, position); 63 | position = MIN(value.length(), position); 64 | lastTime = ofGetElapsedTimeMillis(); 65 | updateCursor(); 66 | if(valueBefore != value) { 67 | ofNotifyEvent(valueChange, value, this); 68 | } 69 | } 70 | }; 71 | 72 | class ofApp : public ofBaseApp { 73 | public: 74 | SearchBar search; 75 | void valueChange(string& value) { 76 | ofLog() << value; 77 | } 78 | void setup() { 79 | search.setup(24); 80 | ofAddListener(search.valueChange, this, &ofApp::valueChange); 81 | ofBackground(0); 82 | } 83 | void update() { 84 | } 85 | void draw() { 86 | ofSetColor(255); 87 | search.draw(48, ofGetHeight() / 2); 88 | } 89 | }; 90 | int main() { 91 | ofSetupOpenGL(1280, 720, OF_WINDOW); 92 | ofRunApp(new ofApp()); 93 | } 94 | -------------------------------------------------------------------------------- /TileMatching/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | float getBrightness(const ofPixels& pix, int x, int y, int w, int h) { 4 | float brightness = 0; 5 | for(int j = y; j < y + h; j++) { 6 | for(int i = x; i < x + w; i++) { 7 | brightness += pix.getColor(i, j).getBrightness(); 8 | } 9 | } 10 | brightness /= (w * h); 11 | return brightness; 12 | } 13 | 14 | class Tile { 15 | public: 16 | int x, y, side; 17 | float brightness; 18 | Tile(int x, int y, int side, float brightness) 19 | :x(x) 20 | ,y(y) 21 | ,side(side) 22 | ,brightness(brightness) { 23 | } 24 | static vector buildTiles(const ofPixels& pix, int x, int y, int w, int h, int side) { 25 | int nx = w / side, ny = h / side; 26 | vector tiles; 27 | for(int j = y; j < y + h; j+=side) { 28 | for(int i = x; i < x + w; i+=side) { 29 | float brightness = getBrightness(pix, i, j, side, side); 30 | // try the direction of the brightness (overall gradient) 31 | tiles.push_back(Tile(i, j, side, brightness)); 32 | } 33 | } 34 | return tiles; 35 | } 36 | 37 | }; 38 | 39 | bool TileCompare(const Tile& a, const Tile& b) { 40 | return a.brightness < b.brightness; 41 | } 42 | 43 | class ofApp : public ofBaseApp { 44 | public: 45 | ofVideoGrabber video; 46 | vector leftTiles, rightTiles; 47 | int side = 40; 48 | void setup() { 49 | video.initGrabber(1280, 720); 50 | } 51 | void update() { 52 | video.update(); 53 | if(video.isFrameNew()) { 54 | int w = video.getWidth(); 55 | int h = video.getHeight(); 56 | ofPixels& pix = video.getPixels(); 57 | leftTiles = Tile::buildTiles(pix, 0, 0, w / 2, h, side); 58 | rightTiles = Tile::buildTiles(pix, w / 2, 0, w / 2, h, side); 59 | ofSort(leftTiles, TileCompare); 60 | ofSort(rightTiles, TileCompare); 61 | } 62 | } 63 | void draw() { 64 | int n = leftTiles.size(); 65 | ofTexture& tex = video.getTexture(); 66 | for(int i = 0; i < n; i++) { 67 | Tile& left = leftTiles[i]; 68 | Tile& right = rightTiles[i]; 69 | tex.drawSubsection(left.x, left.y, side, side, right.x, right.y); 70 | tex.drawSubsection(right.x, right.y, side, side, left.x, left.y); 71 | } 72 | ofSetWindowTitle(ofToString((int) ofGetFrameRate())); 73 | } 74 | }; 75 | int main() { 76 | ofSetupOpenGL(1280, 720, OF_WINDOW); 77 | ofRunApp(new ofApp()); 78 | } 79 | -------------------------------------------------------------------------------- /Timelapse/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1280, 720, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /Timelapse/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup() { 4 | ofSetVerticalSync(true); 5 | cam.initGrabber(1280, 720); 6 | delayTime = 1; 7 | frameCount = 0; 8 | lastTime = 0; 9 | } 10 | 11 | void ofApp::update() { 12 | cam.update(); 13 | float curTime = ofGetElapsedTimef(); 14 | if(curTime - lastTime > delayTime) { 15 | img = cam.getPixelsRef(); 16 | img.update(); 17 | img.saveImage(ofToString(frameCount, 8, '0') + ".jpg"); 18 | frameCount++; 19 | lastTime = curTime; 20 | } 21 | } 22 | 23 | void ofApp::draw() { 24 | if(img.isAllocated()) { 25 | img.draw(0, 0); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Timelapse/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class ofApp : public ofBaseApp { 6 | public: 7 | void setup(); 8 | void update(); 9 | void draw(); 10 | 11 | ofVideoGrabber cam; 12 | ofImage img; 13 | float lastTime, delayTime; 14 | unsigned int frameCount; 15 | }; 16 | -------------------------------------------------------------------------------- /TriangleTriangle/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | bool lineIntersection(const ofVec2f& v1, const ofVec2f& v2, const ofVec2f& v3, const ofVec2f& v4) { 4 | float d = (v4.y-v3.y)*(v2.x-v1.x)-(v4.x-v3.x)*(v2.y-v1.y); 5 | float u = (v4.x-v3.x)*(v1.y-v3.y)-(v4.y-v3.y)*(v1.x-v3.x); 6 | float v = (v2.x-v1.x)*(v1.y-v3.y)-(v2.y-v1.y)*(v1.x-v3.x); 7 | if (d < 0) u = -u; v = -v; d = -d; 8 | return (0<=u && u<=d) && (0<=v && v<=d); 9 | } 10 | 11 | float cross(const ofVec2f& u, const ofVec2f& v) { 12 | return u.x*v.y-u.y*v.x; 13 | } 14 | 15 | // being on a corner or on an edge is not being inside 16 | bool pointInTriangle(const ofVec2f& P, const ofVec2f& A, const ofVec2f& B, const ofVec2f& C) { 17 | ofVec2f v0(C.x-A.x, C.y-A.y); 18 | ofVec2f v1(B.x-A.x, B.y-A.y); 19 | ofVec2f v2(P.x-A.x, P.y-A.y); 20 | float u = cross(v2,v0); 21 | float v = cross(v1,v2); 22 | float d = cross(v1,v0); 23 | if (d < 0) u = -u; v = -v; d = -d; 24 | return u>0 && v>0 && ((u+v) < d); 25 | } 26 | 27 | bool nearbyCircle(const ofVec2f& A1, const ofVec2f& B1, const ofVec2f& C1, 28 | const ofVec2f& A2, const ofVec2f& B2, const ofVec2f& C2) { 29 | ofVec2f center1 = (A1 + B1 + C1) / 3; 30 | ofVec2f center2 = (A2 + B2 + C2) / 3; 31 | float sizeSquared1 = MAX(A1.squareDistance(center1), MAX(B1.squareDistance(center1), C1.squareDistance(center1))); 32 | float sizeSquared2 = MAX(A2.squareDistance(center2), MAX(B2.squareDistance(center2), C2.squareDistance(center2))); 33 | float minimumDistance = sqrtf(sizeSquared1) + sqrtf(sizeSquared2); 34 | return center1.squareDistance(center2) <= (minimumDistance * minimumDistance); 35 | } 36 | 37 | bool triangleIntersection(const ofVec2f& A1, const ofVec2f& B1, const ofVec2f& C1, 38 | const ofVec2f& A2, const ofVec2f& B2, const ofVec2f& C2) { 39 | return 40 | pointInTriangle(A1, A2, B2, C2) || 41 | pointInTriangle(B1, A2, B2, C2) || 42 | pointInTriangle(C1, A2, B2, C2) || 43 | pointInTriangle(A2, A1, B1, C1) || 44 | pointInTriangle(B2, A1, B1, C1) || 45 | pointInTriangle(C2, A1, B1, C1) || 46 | lineIntersection(A1, B1, A2, B2) || 47 | lineIntersection(A1, B1, B2, C2) || 48 | lineIntersection(A1, B1, C2, A2) || 49 | lineIntersection(B1, C1, A2, B2) || 50 | lineIntersection(B1, C1, B2, C2) || 51 | lineIntersection(B1, C1, C2, A2) || 52 | lineIntersection(C1, A1, A2, B2) || 53 | lineIntersection(C1, A1, B2, C2) || 54 | lineIntersection(C1, A1, C2, A2); 55 | } 56 | 57 | // this is faster if triangles are small and spread out 58 | bool triangleIntersectionFast(const ofVec2f& A1, const ofVec2f& B1, const ofVec2f& C1, 59 | const ofVec2f& A2, const ofVec2f& B2, const ofVec2f& C2) { 60 | return nearbyCircle(A1, B1, C1, A2, B2, C2) && 61 | triangleIntersection(A1, B1, C1, A2, B2, C2); 62 | } 63 | 64 | 65 | class Triangle { 66 | public: 67 | ofVec2f A, B, C; 68 | Triangle(ofVec2f A, ofVec2f B, ofVec2f C) 69 | :A(A), B(B), C(C) { 70 | } 71 | }; 72 | 73 | class ofApp : public ofBaseApp { 74 | public: 75 | ofVec2f A1, B1, C1; 76 | ofVec2f A2, B2, C2; 77 | vector points; 78 | vector triangles; 79 | void setup() { 80 | ofBackground(0); 81 | for(int i = 0; i < 10000; i++) { 82 | points.emplace_back(ofRandomWidth(), ofRandomHeight()); 83 | } 84 | 85 | // test for on-corner behavior 86 | A1.set(0, 0); 87 | B1.set(100, 100); 88 | C1.set(0, 100); 89 | ofLog() << pointInTriangle(A1, A1, B1, C1); 90 | ofLog() << pointInTriangle(B1, A1, B1, C1); 91 | ofLog() << pointInTriangle(C1, A1, B1, C1); 92 | ofLog() << pointInTriangle((A1+B1) / 2, A1, B1, C1); 93 | ofLog() << lineIntersection(A1, B1, A1, B1); 94 | 95 | placeTriangle(); 96 | } 97 | void placeTriangle() { 98 | A1.set(ofRandomWidth(), ofRandomHeight()); 99 | B1.set(ofRandomWidth(), ofRandomHeight()); 100 | C1.set(ofRandomWidth(), ofRandomHeight()); 101 | A2.set(ofRandomWidth(), ofRandomHeight()); 102 | B2.set(ofRandomWidth(), ofRandomHeight()); 103 | C2.set(ofRandomWidth(), ofRandomHeight()); 104 | // 105 | // cout 106 | // << "A1.set(" << A1 << ");" << endl 107 | // << "B1.set(" << B1 << ");" << endl 108 | // << "C1.set(" << C1 << ");" << endl 109 | // << "A2.set(" << A2 << ");" << endl 110 | // << "B2.set(" << B2 << ");" << endl 111 | // << "C2.set(" << C2 << ");" << endl 112 | // << endl; 113 | } 114 | void update() { 115 | // triangles.clear(); 116 | // for(int i = 0; i < 1000; i++) { 117 | // triangles.emplace_back(ofVec2f(ofRandomWidth(), ofRandomHeight()), 118 | // ofVec2f(ofRandomWidth(), ofRandomHeight()), 119 | // ofVec2f(ofRandomWidth(), ofRandomHeight())); 120 | // } 121 | // float targetScale = 10; 122 | // for(Triangle& t : triangles) { 123 | // ofVec2f center = (t.A + t.B + t.C) / 3; 124 | // float size = MAX(t.A.distance(center), MAX(t.B.distance(center), t.C.distance(center))); 125 | // float scale = targetScale / size; 126 | // t.A = (t.A - center) * scale + center; 127 | // t.B = (t.B - center) * scale + center; 128 | // t.C = (t.C - center) * scale + center; 129 | // } 130 | // uint64_t start = ofGetElapsedTimeMillis(); 131 | // int intersecting = 0, total = 0; 132 | // for(Triangle t0 : triangles) { 133 | // for(Triangle t1 : triangles) { 134 | // if(triangleIntersectionFast(t0.A, t0.B, t0.C, t1.A, t1.B, t1.C)) { 135 | // intersecting++; 136 | // } 137 | // total++; 138 | // } 139 | // } 140 | // uint64_t stop = ofGetElapsedTimeMillis(); 141 | // ofLog() << stop - start << "ms for " << ((100.*intersecting)/total) << "% of " << total; 142 | } 143 | void draw() { 144 | ofFill(); 145 | for(auto& P : points) { 146 | bool T1 = pointInTriangle(P, A1, B1, C1); 147 | bool T2 = pointInTriangle(P, A2, B2, C2); 148 | ofSetColor(255, T1 * 255, T2 * 255, 64); 149 | ofDrawCircle(P, 2); 150 | } 151 | ofNoFill(); 152 | bool TT = triangleIntersection(A1, B1, C1, A2, B2, C2); 153 | ofSetColor(ofColor::green); 154 | if(TT) { 155 | ofSetColor(255, 128); 156 | ofFill(); 157 | } 158 | ofDrawTriangle(A1, B1, C1); 159 | ofDrawTriangle(A2, B2, C2); 160 | 161 | ofPushMatrix(); 162 | ofSetColor(255); 163 | ofTranslate(10, 20); 164 | ofDrawBitmapString(pointInTriangle(A1, A2, B2, C2) ? "pointInTriangle(A1, A2, B2, C2)" : "-", 0, 0); ofTranslate(0, 20); 165 | ofDrawBitmapString(pointInTriangle(B1, A2, B2, C2) ? "pointInTriangle(B1, A2, B2, C2)" : "-", 0, 0); ofTranslate(0, 20); 166 | ofDrawBitmapString(pointInTriangle(C1, A2, B2, C2) ? "pointInTriangle(C1, A2, B2, C2)" : "-", 0, 0); ofTranslate(0, 20); 167 | ofDrawBitmapString(pointInTriangle(A2, A1, B1, C1) ? "pointInTriangle(A2, A1, B1, C1)" : "-", 0, 0); ofTranslate(0, 20); 168 | ofDrawBitmapString(pointInTriangle(B2, A1, B1, C1) ? "pointInTriangle(B2, A1, B1, C1)" : "-", 0, 0); ofTranslate(0, 20); 169 | ofDrawBitmapString(pointInTriangle(C2, A1, B1, C1) ? "pointInTriangle(C2, A1, B1, C1)" : "-", 0, 0); ofTranslate(0, 20); 170 | ofDrawBitmapString(lineIntersection(A1, B1, A2, B2) ? "lineIntersection(A1, B1, A2, B2)" : "-", 0, 0); ofTranslate(0, 20); 171 | ofDrawBitmapString(lineIntersection(A1, B1, B2, C2) ? "lineIntersection(A1, B1, B2, C2)" : "-", 0, 0); ofTranslate(0, 20); 172 | ofDrawBitmapString(lineIntersection(A1, B1, C2, A2) ? "lineIntersection(A1, B1, C2, A2)" : "-", 0, 0); ofTranslate(0, 20); 173 | ofDrawBitmapString(lineIntersection(B1, C1, A2, B2) ? "lineIntersection(B1, C1, A2, B2)" : "-", 0, 0); ofTranslate(0, 20); 174 | ofDrawBitmapString(lineIntersection(B1, C1, B2, C2) ? "lineIntersection(B1, C1, B2, C2)" : "-", 0, 0); ofTranslate(0, 20); 175 | ofDrawBitmapString(lineIntersection(B1, C1, C2, A2) ? "lineIntersection(B1, C1, C2, A2)" : "-", 0, 0); ofTranslate(0, 20); 176 | ofDrawBitmapString(lineIntersection(C1, A1, A2, B2) ? "lineIntersection(C1, A1, A2, B2)" : "-", 0, 0); ofTranslate(0, 20); 177 | ofDrawBitmapString(lineIntersection(C1, A1, B2, C2) ? "lineIntersection(C1, A1, B2, C2)" : "-", 0, 0); ofTranslate(0, 20); 178 | ofDrawBitmapString(lineIntersection(C1, A1, C2, A2) ? "lineIntersection(C1, A1, C2, A2)" : "-", 0, 0); ofTranslate(0, 20); 179 | ofPopMatrix(); 180 | 181 | // ofSetColor(255); 182 | // ofNoFill(); 183 | // for(Triangle& t : triangles) { 184 | // ofDrawTriangle(t.A, t.B, t.C); 185 | // } 186 | } 187 | void keyPressed(int key) { 188 | placeTriangle(); 189 | } 190 | }; 191 | int main() { 192 | ofSetupOpenGL(800, 800, OF_WINDOW); 193 | ofRunApp(new ofApp()); 194 | } 195 | -------------------------------------------------------------------------------- /VideoRecorder/ofxQTKitVideoGrabber/ofxQTKitVideoGrabber.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ofxQTKitVideoGrabber.cpp 3 | * 4 | * Copyright 2010 (c) James George, http://www.jamesgeorge.org 5 | * in collaboration with FlightPhase http://www.flightphase.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | * 28 | * ---------------------- 29 | * 30 | * ofxQTKitVideoGrabber works exactly the same as the standard ofMovieGrabber 31 | * but uses the QTKit Objective-C Libraries to drive the video display. 32 | * These libraries are naturally GPU enabled, multi-threaded, as well 33 | * as supporting more Quicktime capture codecs such as HDV. 34 | * 35 | * You will need to add the QTKit.framework and CoreVide.framework 36 | * to the openFrameworks Xcode project 37 | * 38 | * Requires Mac OS 10.5 or greater 39 | */ 40 | 41 | #ifndef _OFX_QTKITVIDEOGRABBER 42 | #define _OFX_QTKITVIDEOGRABBER 43 | 44 | #include "ofMain.h" 45 | 46 | //using this #ifdef lets this .h file be included in cpp files without throwing errors 47 | //but when included in .m files it works correctly. another useful trick for mixing oF/ObjC 48 | #ifdef __OBJC__ 49 | @class QTKitVideoGrabber; 50 | #endif 51 | 52 | class ofxQTKitVideoGrabber : public ofBaseVideoGrabber 53 | { 54 | public: 55 | ofxQTKitVideoGrabber(); 56 | ~ofxQTKitVideoGrabber(); 57 | 58 | bool initGrabber(int w, int h); 59 | bool initGrabber(int w, int h, bool bUseAudio = false); 60 | void grabFrame(); 61 | bool isFrameNew(); 62 | void update(); 63 | void setUseTexture(bool bUse); 64 | 65 | void listVideoDevices(); 66 | void listDevices(); 67 | void listAudioDevices(); 68 | 69 | void close(); 70 | unsigned char *getPixels(); 71 | ofPixelsRef getPixelsRef(); 72 | 73 | ofTexture & getTextureReference(); 74 | void setVerbose(bool bTalkToMe); 75 | void setDeviceID(int deviceID); 76 | void setDeviceID(string deviceIDString); 77 | void setVideoDeviceID(int videoDeviceID); 78 | void setVideoDeviceID(string videoDeviceIDString); 79 | int getVideoDeviceID(); 80 | void setAudioDeviceID(int audioDeviceID); 81 | void setAudioDeviceID(string audioDeviceIDString); 82 | int getAudioDeviceID(); 83 | 84 | void setDesiredFrameRate(int framerate){ ofLog(OF_LOG_WARNING, "ofxQTKitVideoGrabber -- Cannot specify framerate."); }; 85 | void videoSettings(); 86 | // void audioSettings(); 87 | 88 | void initRecording(); 89 | void initGrabber(bool bUseAudio = true); // used to init with no preview/textures etc 90 | void listVideoCodecs(); 91 | void listAudioCodecs(); 92 | void setVideoCodec(string videoCodecIDString); 93 | void setAudioCodec(string audioCodecIDString); 94 | 95 | void startRecording(string filePath); 96 | void stopRecording(); 97 | bool isRecording(); 98 | 99 | void draw(float x, float y, float w, float h); 100 | void draw(float x, float y); 101 | 102 | float getHeight(); 103 | float getWidth(); 104 | 105 | void setPixelFormat(ofPixelFormat pixelFormat); 106 | ofPixelFormat getPixelFormat(); 107 | 108 | protected: 109 | 110 | bool confirmInit(); 111 | int videoDeviceID; 112 | int audioDeviceID; 113 | string videoCodecIDString; 114 | string audioCodecIDString; 115 | bool useAudio; 116 | bool isInited; 117 | bool bUseTexture; 118 | ofPixelFormat pixelFormat; 119 | 120 | #ifdef __OBJC__ 121 | QTKitVideoGrabber* grabber; //only obj-c needs to know the type of this protected var 122 | #else 123 | void* grabber; 124 | #endif 125 | }; 126 | 127 | #endif -------------------------------------------------------------------------------- /VideoRecorder/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(640, 360 * 2, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /VideoRecorder/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup() { 4 | ofSetVerticalSync(true); 5 | ofSetLogLevel(OF_LOG_VERBOSE); 6 | 7 | camWidth = 640; 8 | camHeight = 360; 9 | count = 0; 10 | 11 | startPreview(); 12 | } 13 | 14 | void ofApp::update() { 15 | if(mode == PREVIEW || mode == RECORD) { 16 | grabber.update(); 17 | } else { 18 | player.update(); 19 | } 20 | } 21 | 22 | void ofApp::draw() { 23 | ofBackground(0); 24 | ofSetColor(255); 25 | if(mode == PREVIEW || mode == RECORD) { 26 | grabber.draw(0, 0); 27 | } else { 28 | player.draw(0, camHeight); 29 | } 30 | ofDrawBitmapString(stringify(mode), 10, 20); 31 | } 32 | 33 | void ofApp::startPreview() { 34 | mode = PREVIEW; 35 | grabber.listVideoCodecs(); 36 | grabber.initGrabber(camWidth, camHeight, true); 37 | } 38 | 39 | void ofApp::stopPreview() { 40 | } 41 | 42 | void ofApp::startRecord() { 43 | mode = RECORD; 44 | grabber.initRecording(); 45 | grabber.setVideoCodec("QTCompressionOptionsSD480SizeMPEG4Video"); 46 | grabber.startRecording(ofToDataPath(ofToString(count) + ".mov")); 47 | } 48 | 49 | void ofApp::stopRecord() { 50 | grabber.stopRecording(); 51 | grabber.close(); 52 | count++; 53 | } 54 | 55 | void ofApp::startPlayback() { 56 | mode = PLAYBACK; 57 | player.loadMovie(ofToString(count - 1) + ".mov"); 58 | player.setLoopState(OF_LOOP_NONE); 59 | player.play(); 60 | } 61 | 62 | void ofApp::stopPlayback() { 63 | player.close(); 64 | } 65 | 66 | void ofApp::keyPressed(int key) { 67 | if(key == ' ') { 68 | switch(mode) { 69 | case PREVIEW: stopPreview(); startRecord(); break; 70 | case RECORD: stopRecord(); startPlayback(); break; 71 | case PLAYBACK: stopPlayback(); startPreview(); break; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /VideoRecorder/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "ofxQTKitVideoGrabber.h" 5 | 6 | class ofApp : public ofBaseApp { 7 | public: 8 | void setup(); 9 | void update(); 10 | void draw(); 11 | void keyPressed(int key); 12 | 13 | void startPreview(); void stopPreview(); 14 | void startRecord(); void stopRecord(); 15 | void startPlayback(); void stopPlayback(); 16 | 17 | ofxQTKitVideoGrabber grabber; 18 | ofVideoPlayer player; 19 | 20 | int camWidth, camHeight, count; 21 | 22 | enum Mode {PREVIEW, RECORD, PLAYBACK}; 23 | Mode mode; 24 | string stringify(Mode mode) { 25 | switch(mode) { 26 | case PREVIEW: return "Preview"; 27 | case RECORD: return "Record"; 28 | case PLAYBACK: return "Playback"; 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /VideoShuffler/bin/data/GravuConBol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/openFrameworksDemos/ae7d2f9f43884ef54bec44420994c49e2bf8081a/VideoShuffler/bin/data/GravuConBol -------------------------------------------------------------------------------- /VideoShuffler/bin/data/GravuConLig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/openFrameworksDemos/ae7d2f9f43884ef54bec44420994c49e2bf8081a/VideoShuffler/bin/data/GravuConLig -------------------------------------------------------------------------------- /VideoShuffler/bin/data/settings.xml: -------------------------------------------------------------------------------- 1 | 30 2 | 36 3 | 28 -------------------------------------------------------------------------------- /VideoShuffler/bin/data/videos.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 19 | 25 | 31 | 37 | 43 | 49 | 55 | 61 | 67 | 73 | 79 | 85 | 91 | 97 | 103 | 109 | 115 | 121 | 127 | 133 | 139 | 145 | 151 | 157 | -------------------------------------------------------------------------------- /VideoShuffler/bin/data/videos/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/openFrameworksDemos/ae7d2f9f43884ef54bec44420994c49e2bf8081a/VideoShuffler/bin/data/videos/.gitkeep -------------------------------------------------------------------------------- /VideoShuffler/src/DelayTimer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | /* 6 | DelayTimer is a synchronous timer, which means you can ask it 7 | whether it's time to do something again yet. 8 | Set it up with setFramerate() or setPeriod() (in seconds). 9 | Then call tick() to find out whether the timer has ticked 10 | since the last time you checked. 11 | 12 | setUseBuffer(true) means tick() will return true multiple times 13 | when multiple ticks have passed without you checking. 14 | */ 15 | 16 | class DelayTimer { 17 | protected: 18 | float period; 19 | float lastTime; 20 | int ticks; 21 | bool useBuffer; 22 | public: 23 | DelayTimer() : 24 | period(0), 25 | lastTime(0), 26 | ticks(0), 27 | useBuffer(false) { 28 | }; 29 | void setFramerate(float framerate) { 30 | period = 1 / framerate; 31 | } 32 | void setPeriod(float period) { 33 | this->period = period; 34 | } 35 | float getPeriod() { 36 | return period; 37 | } 38 | void setUseBuffer(bool useBuffer) { 39 | this->useBuffer = useBuffer; 40 | } 41 | bool tick() { 42 | float curTime = ofGetElapsedTimef(); 43 | int curTicks = (int) (curTime / period); 44 | int lastTicks = (int) (lastTime / period); 45 | lastTime = curTime; 46 | ticks += curTicks - lastTicks; 47 | if(ticks > 0) { 48 | if(useBuffer) { 49 | ticks--; 50 | } else { 51 | ticks = 0; 52 | } 53 | return true; 54 | } else { 55 | return false; 56 | } 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /VideoShuffler/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1280, 720, OF_FULLSCREEN); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /VideoShuffler/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | ofColor cyanPrint = ofColor::fromHex(0x00abec), magentaPrint = ofColor::fromHex(0xec008c), yellowPrint = ofColor::fromHex(0xffee00); 4 | 5 | void centerFitInside(float width, float height) { 6 | ofTranslate(ofGetWidth() / 2, ofGetHeight() / 2); 7 | float scale; 8 | if(width / ofGetWidth() > height / ofGetHeight()) { 9 | scale = ofGetWidth() / width; 10 | } else { 11 | scale = ofGetHeight() / height; 12 | } 13 | ofScale(scale, scale); 14 | ofTranslate(-width / 2, -height / 2); 15 | } 16 | 17 | ofRectangle addPadding(ofRectangle rect, float padding) { 18 | return ofRectangle(rect.x - padding, rect.y - padding, rect.width + 2 * padding, rect.height + 2 * padding); 19 | } 20 | 21 | void ofApp::setup() { 22 | ofSetVerticalSync(true); 23 | 24 | ofxXmlSettings xml; 25 | 26 | xml.loadFile("settings.xml"); 27 | timer.setPeriod(xml.getValue("period", 30)); 28 | h1.loadFont("GravuConBol", xml.getValue("h1Size", 36), true); 29 | h2.loadFont("GravuConLig", xml.getValue("h2Size", 28), true); 30 | 31 | xml.loadFile("videos.xml"); 32 | int n = xml.getNumTags("video"); 33 | for(int i = 0; i < n; i++) { 34 | xml.pushTag("video", i); 35 | Description cur; 36 | cur.file = xml.getValue("file", ""); 37 | cur.h1 = xml.getValue("h1", ""); 38 | cur.h2 = xml.getValue("h2", ""); 39 | descriptions.push_back(cur); 40 | xml.popTag(); 41 | 42 | playlist.push_back(i); 43 | } 44 | 45 | which = 0; 46 | 47 | skip = true; 48 | 49 | ofHideCursor(); 50 | } 51 | 52 | void ofApp::update() { 53 | if(timer.tick() || skip) { 54 | cur = descriptions[playlist[which]]; 55 | cout << "loading " << cur.file << endl; 56 | video.loadMovie("videos/" + cur.file, OFXQTVIDEOPLAYER_MODE_TEXTURE_ONLY); 57 | video.play(); 58 | float duration = video.getDuration(); 59 | float time = ofClamp(ofRandom(0, duration - timer.getPeriod()), 0, duration - timer.getPeriod()); 60 | video.setPosition(time / duration); 61 | which++; 62 | if(which == playlist.size()) { 63 | ofRandomize(playlist); 64 | which = 0; 65 | } 66 | skip = false; 67 | } 68 | 69 | video.update(); 70 | } 71 | void ofApp::draw() { 72 | ofBackground(0); 73 | 74 | ofPushMatrix(); 75 | centerFitInside(video.getWidth(), video.getHeight()); 76 | ofSetColor(255); 77 | video.draw(0, 0); 78 | ofPopMatrix(); 79 | 80 | ofSetColor(255); 81 | 82 | float padding = 8, margin = 16; 83 | 84 | ofRectangle titleBox = addPadding(h1.getStringBoundingBox(cur.h1, 0, 0), padding); 85 | ofRectangle authorBox = addPadding(h2.getStringBoundingBox(cur.h2, 0, 0), padding); 86 | 87 | ofFill(); 88 | 89 | ofTranslate(margin, margin + titleBox.height); 90 | ofSetColor(cyanPrint); 91 | ofRect(titleBox); 92 | ofSetColor(255); 93 | h1.drawString(cur.h1, 0, 0); 94 | 95 | ofTranslate(0, titleBox.height + padding); 96 | ofSetColor(magentaPrint); 97 | ofRect(authorBox); 98 | ofSetColor(255); 99 | h2.drawString(cur.h2, 0, 0); 100 | } 101 | 102 | void ofApp::keyPressed(int key) { 103 | if(key == 'f') { 104 | ofToggleFullscreen(); 105 | } 106 | if(key == ' ') { 107 | skip = true; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /VideoShuffler/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "DelayTimer.h" 5 | #include "ofxQTKitVideoPlayer.h" 6 | #include "ofxXmlSettings.h" 7 | 8 | class Description { 9 | public: 10 | string file, h1, h2; 11 | }; 12 | 13 | class ofApp : public ofBaseApp { 14 | public: 15 | void setup(); 16 | void update(); 17 | void draw(); 18 | void keyPressed(int key); 19 | 20 | DelayTimer timer; 21 | ofxQTKitVideoPlayer video; 22 | 23 | ofTrueTypeFont h1, h2; 24 | vector descriptions; 25 | vector playlist; 26 | int which; 27 | Description cur; 28 | bool skip; 29 | }; 30 | -------------------------------------------------------------------------------- /Worm/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | ofMesh thicken(ofMesh& mesh, float thickness) { 4 | ofMesh result; 5 | result.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); 6 | for(int i = 0; i < mesh.getNumVertices()-1; i++) { 7 | ofVec3f& cur = mesh.getVertices()[i]; 8 | ofVec3f& next = mesh.getVertices()[i+1]; 9 | ofVec2f normal = ofVec2f(next - cur).rotate(90).normalize() * thickness; 10 | result.addVertex(cur - normal); 11 | result.addVertex(cur + normal); 12 | if(i+2 == mesh.getNumVertices()) { 13 | result.addVertex(next - normal); 14 | result.addVertex(next + normal); 15 | } 16 | } 17 | return result; 18 | } 19 | 20 | class Worm { 21 | private: 22 | float phase; 23 | float angle() { 24 | return ofVec2f(1, 0).angle(velocity); 25 | } 26 | 27 | public: 28 | ofVec2f position; 29 | ofVec2f velocity; 30 | float smoothing; 31 | int resolution; 32 | float thickness; 33 | float length, width; 34 | float wiggleSpeed; 35 | 36 | Worm() : 37 | phase(0) { 38 | 39 | } 40 | void update(ofVec2f position) { 41 | this->velocity.interpolate(position - this->position, smoothing); 42 | this->position.interpolate(position, smoothing); 43 | this->phase += (velocity.length() / length) * wiggleSpeed; 44 | } 45 | void draw() { 46 | ofPushMatrix(); 47 | ofTranslate(position); 48 | ofRotate(angle()); 49 | ofMesh mesh; 50 | mesh.setMode(OF_PRIMITIVE_LINE_STRIP); 51 | for(int i = 0; i < resolution; i++) { 52 | float t = ofNormalize(i, 0, resolution - 1); 53 | float phase = t * TWO_PI + this->phase; 54 | float x = (t - 1.) * length; 55 | float y = sin(phase) * width; 56 | mesh.addVertex(ofVec2f(x, y)); 57 | } 58 | if(thickness > 0) { 59 | mesh = thicken(mesh, thickness); 60 | } 61 | mesh.draw(); 62 | ofPopMatrix(); 63 | } 64 | }; 65 | 66 | class ofApp : public ofBaseApp { 67 | public: 68 | Worm worm; 69 | ofVec2f prevMouse; 70 | 71 | void setup() { 72 | ofBackground(0); 73 | worm.smoothing = .1; 74 | worm.resolution = 8; 75 | worm.length = 200; 76 | worm.width = 20; 77 | worm.thickness = 16; 78 | worm.wiggleSpeed = .5; 79 | } 80 | void update() { 81 | worm.update(ofVec2f(mouseX, mouseY)); 82 | } 83 | void draw() { 84 | ofSetColor(255); 85 | worm.draw(); 86 | } 87 | void keyPressed(int key) { 88 | worm.resolution = ofRandom(4, 20); 89 | worm.length = ofRandom(20, 400); 90 | worm.width = worm.length * ofRandom(.1, .3); 91 | worm.thickness = worm.length * ofRandom(0, .2); 92 | worm.wiggleSpeed = ofRandom(.1, .6); 93 | } 94 | }; 95 | int main() { 96 | ofSetupOpenGL(1280, 720, OF_WINDOW); 97 | ofRunApp(new ofApp()); 98 | } 99 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | All code in this repository is available under the MIT License. 2 | 3 | https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license 4 | 5 | - - -- 6 | 7 | Copyright (c) 2011- Kyle McDonald 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # openFrameworksDemos 2 | 3 | This repository is a collection of assorted demos and examples using [openFrameworks](http://openframeworks.cc/). There is no theme, except that they each demonstrate a technique that doesn't really fit in any other repository. 4 | 5 | ## Descriptions 6 | 7 | * BarnesHut: basic 2d implementation of the [Barnes-Hut](https://en.wikipedia.org/wiki/Barnes%E2%80%93Hut_simulation) quadtree particle system optimization, good for simulating large force-at-a-distance systems. 8 | * BinnedParticleSystem: basic 2d binning optimization for particle-particle interaction. 9 | * BulgeEffect: magnification effect with GLSL for generating and applying the displacement map. 10 | * BulgeEffectMulti: magnification effect for many points by rendering displacement images into a big displacement FBO before applying them. 11 | * GLSLParticleSystem: example of using shaders to compute one-to-many interaction. 12 | * LutExample: applying a 3-channel lookup table to a live stream using a fragment shader. 13 | * NoiseFlocking: "[Clouds are Looming](http://www.openprocessing.org/sketch/6753)" style noise flocking simulation. 14 | * P52OF: port of a simple noise flocking simulation from Processing, done by pasting the code directly and creating a `PApp` class that wraps OF to make it look more like Processing. 15 | * RemapExample: per-pixel displacement example using a fragment shader. 16 | * VideoRecorder: demonstrates how to use ofxQTKitVideoGrabber on OSX to preview a webcam feed, record a video, and then load and play it back. 17 | * VideoShuffler: loads a collection of videos from the `videos/` folder as specified by the `videos.xml` file. -------------------------------------------------------------------------------- /videoInputExample/src/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include "Camera.h" 2 | 3 | videoInput vi; 4 | 5 | Camera::Camera() 6 | :deviceId(0) 7 | ,ready(false) 8 | ,previous(0) 9 | ,width(0) 10 | ,height(0) 11 | ,horizontalFlip(false) { 12 | } 13 | 14 | Camera::~Camera() { 15 | vi.stopDevice(deviceId); 16 | } 17 | 18 | void Camera::setHorizontalFlip(bool horizontalFlip) { 19 | this->horizontalFlip = horizontalFlip; 20 | } 21 | 22 | void Camera::setDeviceId(int deviceId) { 23 | this->deviceId = deviceId; 24 | } 25 | 26 | bool Camera::initGrabber(int width, int height) { 27 | this->width = width; 28 | this->height = height; 29 | int numDevices = vi.listDevices(); 30 | if(deviceId >= numDevices) { 31 | return false; 32 | } 33 | vi.setupDevice(deviceId, width, height); 34 | this->width = vi.getWidth(deviceId); 35 | this->height = vi.getHeight(deviceId); 36 | img.allocate(this->width, this->height, OF_IMAGE_COLOR); 37 | img.update(); 38 | return true; 39 | } 40 | 41 | bool Camera::update() { 42 | bool newFrame = vi.isFrameNew(deviceId); 43 | if(newFrame) { 44 | vi.getPixels(deviceId, img.getPixels(), true, true); 45 | if(!ready) { 46 | unsigned long cur = ((long*) img.getPixels())[0]; 47 | ready = previous != 0 && cur != previous; 48 | previous = cur; 49 | } 50 | if(ready) { 51 | if(horizontalFlip) { 52 | img.mirror(false, true); 53 | } 54 | img.update(); 55 | } else { 56 | newFrame = false; 57 | } 58 | } 59 | return newFrame; 60 | } 61 | 62 | int Camera::getWidth() const { 63 | return width; 64 | } 65 | 66 | int Camera::getHeight() const { 67 | return height; 68 | } 69 | 70 | bool Camera::getReady() const { 71 | return ready; 72 | } 73 | 74 | ofPixels& Camera::getPixels() { 75 | return img.getPixels(); 76 | } 77 | 78 | const ofPixels& Camera::getPixels() const { 79 | return img.getPixelsRef(); 80 | } 81 | 82 | ofTexture& Camera::getTextureReference() { 83 | return img.getTextureReference(); 84 | } 85 | 86 | void Camera::draw(int x, int y) { 87 | img.draw(x, y); 88 | } 89 | -------------------------------------------------------------------------------- /videoInputExample/src/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | class Camera : public ofBaseHasPixels { 6 | protected: 7 | int deviceId, width, height; 8 | ofImage img; 9 | bool horizontalFlip; 10 | bool ready; 11 | unsigned long previous; 12 | 13 | public: 14 | Camera(); 15 | ~Camera(); 16 | 17 | void setDeviceId(int deviceId); 18 | void setHorizontalFlip(bool horizontalFlip); 19 | bool initGrabber(int width, int height); 20 | bool update(); 21 | int getWidth() const; 22 | int getHeight() const; 23 | bool getReady() const; 24 | ofPixels& getPixels(); 25 | const ofPixels& getPixels() const; 26 | ofTexture& getTextureReference(); 27 | void draw(int x, int y); 28 | }; 29 | -------------------------------------------------------------------------------- /videoInputExample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | int main() { 4 | ofSetupOpenGL(1280, 720, OF_WINDOW); 5 | ofRunApp(new ofApp()); 6 | } 7 | -------------------------------------------------------------------------------- /videoInputExample/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | void ofApp::setup() { 4 | ofSetVerticalSync(true); 5 | cam.initGrabber(640, 480); 6 | } 7 | 8 | void ofApp::update() { 9 | if(cam.update()) { 10 | } 11 | } 12 | 13 | void ofApp::draw() { 14 | cam.draw(0, 0); 15 | } 16 | -------------------------------------------------------------------------------- /videoInputExample/src/ofApp.h: -------------------------------------------------------------------------------- 1 | /* 2 | this is an example of using videoInput directly instead of 3 | going through ofDirectShowGrabber. the advantage is that 4 | videoInput doesn't rescale for non-native sizes. 5 | */ 6 | 7 | #pragma once 8 | 9 | #include "ofMain.h" 10 | #include "Camera.h" 11 | 12 | class ofApp : public ofBaseApp { 13 | public: 14 | void setup(); 15 | void update(); 16 | void draw(); 17 | 18 | Camera cam; 19 | }; 20 | --------------------------------------------------------------------------------