diff options
| -rw-r--r-- | lasertext/src/lineTransformer.cpp | 126 | ||||
| -rw-r--r-- | lasertext/src/lineTransformer.h | 21 | ||||
| -rw-r--r-- | lasertext/src/ofApp.cpp | 164 | ||||
| -rw-r--r-- | lasertext/src/ofApp.h | 128 |
4 files changed, 422 insertions, 17 deletions
diff --git a/lasertext/src/lineTransformer.cpp b/lasertext/src/lineTransformer.cpp new file mode 100644 index 0000000..8e2bd80 --- /dev/null +++ b/lasertext/src/lineTransformer.cpp @@ -0,0 +1,126 @@ +#include "lineTransformer.h" + + +void lineTransformer::drawWarpFrame(glm::vec2 warpframe[4]){ + ofSetColor(255,255,255); + ofNoFill(); + for (int i=0;i<4;i++){ + ofDrawCircle(warpframe[i],25); + ofDrawLine(warpframe[i],warpframe[(i+1)%4]); + } +} + +void lineTransformer::gaussianElimination(float * input, int n) +{ + auto i = 0; + auto j = 0; + auto m = n - 1; + + while (i < m && j < n) + { + auto iMax = i; + for (auto k = i + 1; k < m; ++k) + { + if (fabs(input[k * n + j]) > fabs(input[iMax * n + j])) + { + iMax = k; + } + } + + if (input[iMax * n + j] != 0) + { + if (i != iMax) + { + for (auto k = 0; k < n; ++k) + { + auto ikIn = input[i * n + k]; + input[i * n + k] = input[iMax * n + k]; + input[iMax * n + k] = ikIn; + } + } + + float ijIn = input[i * n + j]; + for (auto k = 0; k < n; ++k) + { + input[i * n + k] /= ijIn; + } + + for (auto u = i + 1; u < m; ++u) + { + auto ujIn = input[u * n + j]; + for (auto k = 0; k < n; ++k) + { + input[u * n + k] -= ujIn * input[i * n + k]; + } + } + + ++i; + } + ++j; + } + + for (auto i = m - 2; i >= 0; --i) + { + for (auto j = i + 1; j < n - 1; ++j) + { + input[i * n + m] -= input[i * n + j] * input[j * n + m]; + } + } +} + +glm::mat4 lineTransformer::getPerspectiveTransformMatrix(const glm::vec2 src[4], const glm::vec2 dst[4]) +{ + float p[8][9] = + { + { -src[0][0], -src[0][1], -1, 0, 0, 0, src[0][0] * dst[0][0], src[0][1] * dst[0][0], -dst[0][0] }, // h11 + { 0, 0, 0, -src[0][0], -src[0][1], -1, src[0][0] * dst[0][1], src[0][1] * dst[0][1], -dst[0][1] }, // h12 + { -src[1][0], -src[1][1], -1, 0, 0, 0, src[1][0] * dst[1][0], src[1][1] * dst[1][0], -dst[1][0] }, // h13 + { 0, 0, 0, -src[1][0], -src[1][1], -1, src[1][0] * dst[1][1], src[1][1] * dst[1][1], -dst[1][1] }, // h21 + { -src[2][0], -src[2][1], -1, 0, 0, 0, src[2][0] * dst[2][0], src[2][1] * dst[2][0], -dst[2][0] }, // h22 + { 0, 0, 0, -src[2][0], -src[2][1], -1, src[2][0] * dst[2][1], src[2][1] * dst[2][1], -dst[2][1] }, // h23 + { -src[3][0], -src[3][1], -1, 0, 0, 0, src[3][0] * dst[3][0], src[3][1] * dst[3][0], -dst[3][0] }, // h31 + { 0, 0, 0, -src[3][0], -src[3][1], -1, src[3][0] * dst[3][1], src[3][1] * dst[3][1], -dst[3][1] }, // h32 + }; + + gaussianElimination(&p[0][0], 9); + + return glm::mat4(p[0][8], p[3][8], 0, p[6][8], + p[1][8], p[4][8], 0, p[7][8], + 0, 0, 1, 0, + p[2][8], p[5][8], 0, 1); +} + +ofPolyline lineTransformer::polyLineTransform(const ofMatrix4x4 xform, const ofPolyline& poly){ + ofPolyline tempPoly; + for (auto& p:poly){ + tempPoly.addVertex(ofVec3f(p)*xform); + } + return tempPoly; +} + +colourPolyline lineTransformer::polyLineTransform(const ofMatrix4x4 xform,colourPolyline& poly,float colourFade){ + colourPolyline tempPoly; + for (int i=0;i<poly.size();i++){ + tempPoly.addVertex(ofVec3f(poly[i])*xform,poly.getColourAt(i)*colourFade); + } + return tempPoly; +} + +ofPolyline lineTransformer::makePolygon(int num,float diam){ + ofPolyline poly; + float step=PI*2/num; + for (int i=0;i<=num;i++){ + poly.addVertex(cos(step*i)*diam,sin(step*i)*diam); + } + return poly; +} + +void lineTransformer::drawPoly(ofPolyline poly,float x,float y){ + glPushMatrix(); + ofTranslate(x,y); + poly.draw(); + for (int i=0;i<poly.size();i++){ + ofDrawBitmapString(poly.getDegreesAtIndex(i),poly[i].x+10,poly[i].y+10,0); + } + glPopMatrix(); +} diff --git a/lasertext/src/lineTransformer.h b/lasertext/src/lineTransformer.h new file mode 100644 index 0000000..f5ec22f --- /dev/null +++ b/lasertext/src/lineTransformer.h @@ -0,0 +1,21 @@ +#pragma once + +#include "ofMain.h" +#include "colourPolyline.h" + +class lineTransformer { + + public: + lineTransformer(){ + } + void static drawWarpFrame(glm::vec2 warpframe[4]); + void static gaussianElimination(float * input, int n); + glm::mat4 static getPerspectiveTransformMatrix(const glm::vec2 src[4], const glm::vec2 dst[4]); + ofPolyline static polyLineTransform(const ofMatrix4x4 xform,const ofPolyline& poly); + ofPolyline static polyLineTransform(ofPoint (*transferFunction)(const ofPoint),const ofPolyline& poly); + colourPolyline static polyLineTransform(const ofMatrix4x4 xform,colourPolyline& poly,float colourFade=1.0f); + colourPolyline static polyLineTransform(ofPoint (*transferFunction)(const ofPoint),colourPolyline& poly,float colourFade=1.0f); + ofPolyline static makePolygon(int num,float diam); + void static drawPoly(ofPolyline poly,float x,float y); + +};
\ No newline at end of file diff --git a/lasertext/src/ofApp.cpp b/lasertext/src/ofApp.cpp index 5e6865e..a4e076d 100644 --- a/lasertext/src/ofApp.cpp +++ b/lasertext/src/ofApp.cpp @@ -5,19 +5,33 @@ what do we want to store/control per letter? */ + + //-------------------------------------------------------------- void ofApp::setup(){ + outputWindowSize=ofPoint(ofGetWidth(),ofGetHeight()); + fonts.open("fonts/"); fonts.allowExt("svg"); fonts.listDir(); ofLogNotice()<<"found "<<fonts.size()<<" fonts"; currentFont=0; - banner.loadFont("fonts/EMSPepita.svg"); //fonts.getPath(currentFont)); + banner.loadFont("fonts/EMSDecorousScript.svg"); // EMSPepita.svg"); //fonts.getPath(currentFont)); banner.init("Everything Is Going To Be Alright"); - textgui.setup("text","",5,680); - textgui.add(text_scale.set("scale", 1.0f, 0.5f, 3.0f)); + starsgui.setup("stars","",5,350); + starsgui.add(stars_x.set("x", 0.0f, -2000.0f, 2000.0f)); + starsgui.add(stars_y.set("y", 0.0f, -2000.0f, 2000.0f)); + starsgui.add(stars_radius.set("radius", 100.0f, 10.0f, 500.0f)); + starsgui.add(stars_speed.set("speed", 5.0f, 0.0f, 10.0f)); + starsgui.add(stars_life.set("life", 4.0f, 3.0f, 10.0f)); + + + textgui.setup("text","",5,650); + textgui.add(laser_scale.set("scale", 1.0f, 0.5f, 3.0f)); + textgui.add(laser_pos_x.set("x", 0.0f, -1000.0f, 1000.0f)); + textgui.add(laser_pos_y.set("y", 0.0f, -1000.0f, 1000.0f)); textgui.add(text_speed.set("speed", 1.0f, 0.0f, 2.0f)); lasergui.setup("laser","",5,750); @@ -28,6 +42,9 @@ void ofApp::setup(){ lasergui.add(laser_blank_num.set("blank points", 8, 0, 32)); lasergui.add(laser_max_angle.set("max angle", 15.0f, 1.0f, 90.0f)); + select_warpframe=-1; + bDrawFrame=false; + if( XML.loadFile("settings.xml") ){ cout << "settings.xml loaded!" <<std::endl; @@ -36,7 +53,61 @@ void ofApp::setup(){ cout << "unable to load settings.xml"<<std::endl; } + warpframe[0]=glm::vec2( + XML.getValue("WARP:p0:X", 0), + XML.getValue("WARP:p0:Y", 0) + ); + warpframe[1]=glm::vec2( + XML.getValue("WARP:p1:X", outputWindowSize.x), + XML.getValue("WARP:p1:Y", 0) + ); + warpframe[2]=glm::vec2( + XML.getValue("WARP:p2:X", outputWindowSize.x), + XML.getValue("WARP:p2:Y", outputWindowSize.y) + ); + warpframe[3]=glm::vec2( + XML.getValue("WARP:p3:X", 0), + XML.getValue("WARP:p3:Y", outputWindowSize.y) + ); + + laser_pos_x=XML.getValue("POSITION:X", 0); + laser_pos_y=XML.getValue("POSITION:Y", 0); + laser_scale=XML.getValue("SCALE", 1.0f); + + stars.init(ofVec2f(2000.0f,2000.0f),100.0f,1.0,5.0,4.0,1.0); + +} + +//====================== settings + +void ofApp::default_settings(){ + warpframe[0]=glm::vec2(0,0); + warpframe[1]=glm::vec2(outputWindowSize.x,0); + warpframe[2]=glm::vec2(outputWindowSize.x,outputWindowSize.y); + warpframe[3]=glm::vec2(0,outputWindowSize.y); + outputPosition=ofPoint(0,0); + outputScale=1.0f; } + +void ofApp::save_settings(){ + XML.setValue("WARP:p0:X", warpframe[0].x); + XML.setValue("WARP:p0:Y", warpframe[0].y); + XML.setValue("WARP:p1:X", warpframe[1].x); + XML.setValue("WARP:p1:Y", warpframe[1].y); + XML.setValue("WARP:p2:X", warpframe[2].x); + XML.setValue("WARP:p2:Y", warpframe[2].y); + XML.setValue("WARP:p3:X", warpframe[3].x); + XML.setValue("WARP:p3:Y", warpframe[3].y); + + XML.setValue("POSITION:X", laser_pos_x); + XML.setValue("POSITION:Y", laser_pos_y); + + XML.setValue("SCALE", laser_scale); + + XML.saveFile("settings.xml"); + cout << "settings.xml saved!" <<std::endl; +} + //-------------------------------------------------------------- void ofApp::update(){ banner.update(text_speed); @@ -47,6 +118,14 @@ void ofApp::update(){ laser.set_maxangle(laser_max_angle); laser.set_intensity(laser_intensity); + + + stars.centre=ofVec2f(stars_x,stars_y); + stars.radius=stars_radius; + stars.speed=stars_speed; + stars.lifespan=stars_life;; + + stars.update(); } //-------------------------------------------------------------- @@ -56,28 +135,79 @@ void ofApp::draw(){ textgui.draw(); lasergui.draw(); + starsgui.draw(); + + lineTransformer::drawWarpFrame(warpframe); + + glm::vec2 src[]={ + glm::vec2(0,0), + glm::vec2(ofGetWidth(),0), + glm::vec2(ofGetWidth(),ofGetHeight()), + glm::vec2(0,ofGetHeight()) + }; + + glm::vec2 mp=glm::vec2(outputWindowSize.x/2,outputWindowSize.y/2); + + glm::vec2 scaled_dest[]={ + ((warpframe[0]-mp)*outputScale)+mp, + ((warpframe[1]-mp)*outputScale)+mp, + ((warpframe[2]-mp)*outputScale)+mp, + ((warpframe[3]-mp)*outputScale)+mp + }; - vector<colourPolyline> shapes = banner.getOutlines(0.08f*text_scale); //+(0.02f*sin(ofGetElapsedTimef()*.1f))); + ofMatrix4x4 warp =lineTransformer::getPerspectiveTransformMatrix(src,warpframe); + + vector<colourPolyline> shapes = banner.getOutlines(0.08f); //*text_scale); //+(0.02f*sin(ofGetElapsedTimef()*.1f))); + + ofMatrix4x4 rm = ofMatrix4x4::newIdentityMatrix(); + rm.translate(laser_pos_x,laser_pos_y,0); + rm.scale(laser_scale,laser_scale,laser_scale); + rm.translate(outputWindowSize.x/2,outputWindowSize.y/2,0); + + vector <colourPolyline> warpedOutput; + vector <colourPolyline> warpedScaledOutput; + + for (auto s:shapes){ + warpedOutput.push_back(lineTransformer::polyLineTransform(warp,s)); + } + + for (auto s:warpedOutput){ + warpedScaledOutput.push_back(lineTransformer::polyLineTransform(rm,s)); + } int num = 0; - if (laser_power) num=laser.draw(shapes); + if (laser_power&&shapes.size()) num=laser.draw(warpedScaledOutput); //banner.draw(); ofPushMatrix(); ofTranslate(ofGetWidth()/2,ofGetHeight()/2); //ofScale(0.05,-0.05,0.05); - for (auto& s: shapes) s.draw(); + for (auto& s: warpedOutput) s.draw(); ofPopMatrix(); + ofSetColor(255,255,255); + + vector<colourPolyline> starshapes=stars.getPoints(); + int numstars=0; + for (auto& s: starshapes) { + numstars+=s.size(); + s.draw(); + } + + num+=laser.draw(starshapes); + if (num>0){ - ofSetWindowTitle(ofToString(ofGetFrameRate(), 2)+" fps laser points: "+ofToString(num)); + ofSetWindowTitle(ofToString(ofGetFrameRate(), 2)+" fps laser points: "+ofToString(num)+", stars: "+ofToString(numstars)); } else { - ofSetWindowTitle(ofToString(ofGetFrameRate(), 2)+" fps laser power off "); + ofSetWindowTitle(ofToString(ofGetFrameRate(), 2)+" fps laser power off, stars: "+ofToString(numstars)); } + + + } @@ -99,6 +229,7 @@ void ofApp::keyPressed(ofKeyEventArgs &args){ //-------------------------------------------------------------- void ofApp::keyReleased(int key){ + /* if (key>=' '&&key<='~'){ banner.addGlyph(key); } @@ -120,7 +251,13 @@ void ofApp::keyReleased(int key){ break; } } - + */ + switch(key){ + case 's':{ + save_settings(); + break; + } + } } //-------------------------------------------------------------- @@ -130,14 +267,23 @@ void ofApp::mouseMoved(int x, int y ){ //-------------------------------------------------------------- void ofApp::mouseDragged(int x, int y, int button){ + if (select_warpframe>-1){ + warpframe[select_warpframe]=glm::vec2(x,y); + } } //-------------------------------------------------------------- void ofApp::mousePressed(int x, int y, int button){ + for (int i=0;i<4;i++){ + if (ofPoint(x,y).distance(warpframe[i])<25){ + select_warpframe=i; + } + } } //-------------------------------------------------------------- void ofApp::mouseReleased(int x, int y, int button){ + select_warpframe=-1; } //-------------------------------------------------------------- diff --git a/lasertext/src/ofApp.h b/lasertext/src/ofApp.h index d87f37f..a78f0c2 100644 --- a/lasertext/src/ofApp.h +++ b/lasertext/src/ofApp.h @@ -6,9 +6,97 @@ #include "ofxXmlSettings.h" #include "ofxHelios.h" +#include "lineTransformer.h" #include "colourPolyline.h" +class star{ +public: + star(ofVec2f p,ofVec2f v,float l){ + pos=p; + vel=v; + birthday=ofGetElapsedTimef(); + lifespan=l; + } + void update(vector<star>& stars){ + pos+=vel; + } + ofVec2f pos; + ofVec2f vel; + float birthday; + float lifespan; +}; + +class starSystem{ +public: + vector<star> stars; + ofVec2f centre; + float radius; + float rate; + float speed; + float lifespan; + float agevar; + float last; + starSystem(ofVec2f c=ofVec2f(0,0), float _rad=100,float r=0.5,float s=5.0,float l=5.0,float v=1.0){ + init(c,_rad,r,s,l,v); + } + void init(ofVec2f c, float _rad,float r,float s,float l,float v){ + centre=c; + radius=_rad; + rate=r; + speed=s; + lifespan=l; + agevar=v; + } + void update(){ + float now=ofGetElapsedTimef(); + float segment=now-last; + last=now; + for(auto it = stars.begin(); it != stars.end();) + { + if(now-it->birthday>it->lifespan){ + //ofLog()<<"erase star"; + it = stars.erase(it); + } + else { + //ofLog()<<"update star"; + it->update(stars); + ++it; + } + } + if (ofRandom(rate)<segment){ + float a=ofRandom(3.57f); + float r=ofRandom(radius); + ofVec2f offset=ofVec2f(cos(a)*r,sin(a)*r); + + stars.push_back(star( + offset, + ofVec2f(ofRandom(speed)-(speed/2),ofRandom(speed)-(speed/2)), + lifespan+ofRandom(agevar)-(agevar/2) + )); + /* + ofLog()<<"create star: "<< + ofVec2f(ofRandom(ofGetWidth()),ofRandom(ofGetHeight()))<<", "<< + ofVec2f(ofRandom(speed)-(speed/2),ofRandom(speed)-(speed/2))<<" lifespan: "<< + lifespan+ofRandom(agevar)-(agevar/2); + */ + + + } + } + vector<colourPolyline> getPoints(){ + float now=ofGetElapsedTimef(); + vector<colourPolyline> o; + for(auto& s:stars){ + colourPolyline l; + //ofLog()<<"get star"; + l.addVertex(centre.x+s.pos.x,centre.y+s.pos.y,ofColor(1.0f-((now-s.birthday)/s.lifespan)*128.0f)); + l.addVertex(centre.x+s.pos.x+1,centre.y+s.pos.y+1,ofColor(1.0f-((now-s.birthday)/s.lifespan)*128.0f)); + o.push_back(l); + } + return o; + } +}; class glyph{ public: @@ -137,7 +225,7 @@ public: } } - void createWords(string message,bool usePalette=true){ + void createWords(string message,bool usePalette=false){ clear(); vector<string> m=split(message); for (auto& word: m){ @@ -146,7 +234,8 @@ public: w.glyphs.push_back(getGlyph(c, usePalette? palette[ofRandom(palette.size())]: - ofColor::fromHsb(ofRandom(255.0),225,255) + //112->231 hue sat 0->255 brightness 255 + ofColor::fromHsb(ofRandom(119)+112,ofRandom(255),255) )); } words.push_back(w); @@ -191,13 +280,13 @@ public: if (shape.size()) shapes.push_back(shape); return glyph(c,charWidth,shapes,col); } - void addGlyph(char g,bool usePalette=true){ + void addGlyph(char g,bool usePalette=false){ if (g==' ') words.push_back(glyphWord()); else { words[words.size()-1].glyphs.push_back(getGlyph(g, usePalette? palette[ofRandom(palette.size())]: - ofColor::fromHsb(ofRandom(255.0),225,255) + ofColor::fromHsb(ofRandom(119)+112,ofRandom(255),255) )); } } @@ -211,7 +300,7 @@ public: } } void clear(){words.clear();} - void update(float speed=1.0f,float usePalette=true){ + void update(float speed=1.0f,float usePalette=false){ float delta=ofGetElapsedTimef()-lastUpdateTime; lastUpdateTime=ofGetElapsedTimef(); @@ -239,7 +328,7 @@ public: g.colour= usePalette? palette[ofRandom(palette.size())]: - ofColor::fromHsb(ofRandom(255.0),225,255); + ofColor::fromHsb(ofRandom(119)+112,ofRandom(255),255); } } } @@ -255,7 +344,7 @@ public: for (auto& o:g.outline){ auto q=o; q.scale(s,-s); - q.translate(glm::vec3(p*s,0,0)); + q.translate(glm::vec3(p*s,-ofGetHeight()/3,0)); outlines.push_back(colourPolyline(q,g.colour*w.amount)); } } @@ -286,6 +375,9 @@ class ofApp : public ofBaseApp{ void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); + void default_settings(); + void save_settings(); + ofxHelios laser; ofDirectory fonts; @@ -293,8 +385,17 @@ class ofApp : public ofBaseApp{ string displaytext; glyphbanner banner; + ofxPanel starsgui; + ofParameter<float> stars_x; + ofParameter<float> stars_y; + ofParameter<float> stars_radius; + ofParameter<float> stars_speed; + ofParameter<float> stars_life; + ofxPanel textgui; - ofParameter<float> text_scale; + ofParameter<float> laser_scale; + ofParameter<float> laser_pos_x; + ofParameter<float> laser_pos_y; ofParameter<float> text_speed; //======= laser gui @@ -309,4 +410,15 @@ class ofApp : public ofBaseApp{ ofxXmlSettings XML; + starSystem stars; + + glm::vec2 warpframe[4]; + int select_warpframe; + bool bDrawFrame; + + ofPoint outputWindowSize; + + ofPoint outputPosition; + float outputScale; + }; |
