summaryrefslogtreecommitdiff
path: root/lasertext
diff options
context:
space:
mode:
Diffstat (limited to 'lasertext')
-rw-r--r--lasertext/src/lineTransformer.cpp126
-rw-r--r--lasertext/src/lineTransformer.h21
-rw-r--r--lasertext/src/ofApp.cpp164
-rw-r--r--lasertext/src/ofApp.h128
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;
+
};