diff options
| author | Tim Redfern <tim@getdrop.com> | 2022-09-29 21:12:40 +0100 |
|---|---|---|
| committer | Tim Redfern <tim@getdrop.com> | 2022-09-29 21:12:40 +0100 |
| commit | a2c919f85c366e02cdc71f0fb46f4ebd4e4afebe (patch) | |
| tree | ba1b88607e8de35b0b49683648d7f64ac8259fe1 /passadesgui/src/ofApp.cpp | |
| parent | 8c43a654fdc0a0fd822fd0bd9462cdadf6d96456 (diff) | |
revert to working single plugin chaos
Diffstat (limited to 'passadesgui/src/ofApp.cpp')
| -rw-r--r-- | passadesgui/src/ofApp.cpp | 1294 |
1 files changed, 1294 insertions, 0 deletions
diff --git a/passadesgui/src/ofApp.cpp b/passadesgui/src/ofApp.cpp new file mode 100644 index 0000000..36e0785 --- /dev/null +++ b/passadesgui/src/ofApp.cpp @@ -0,0 +1,1294 @@ +#include "ofApp.h" +#include "glew.h" + +const ofPoint outputWindowSize=ofPoint(1200,900); +const float guiScale=560.0f/4096.0f; + + +string sourcenames[5]={ + "TEST", +// "NDI", + "Player", + "SVG outlines", + "SVG segmenters", + "Audio" +}; + +//-------------------------------------------------------------- +void ofApp::setup(){ + + source=Audio; +/* + //==================================================== ofxNDI + + senderName[0] = 0; // The sender name used for display + nSenders = 0; // Total number of NDI senders + senderWidth = 0; // Sender width + senderHeight = 0; // Sender height + bNDIreceiver = false; // Receiver creation + + // Create an intial receiving image + ndiImage.allocate(ofGetWidth(), ofGetHeight(), OF_IMAGE_COLOR_ALPHA); + + // For received frame fps calculations - independent of the rendering rate + startTime = lastTime = frameTime = 0; + fps = frameRate = 1; // starting value +*/ + + //============================= Audio + + plotter.setup(5,true); + + bufferSize = 2048; + sampleRate = 44100; + + gist.setUseForOnsetDetection(GIST_PEAK_ENERGY); + gist.setThreshold(GIST_PEAK_ENERGY, .05);// + + ofAddListener(GistEvent::ON,this,&ofApp::onNoteOn); + ofAddListener(GistEvent::OFF,this,&ofApp::onNoteOff); + + // ofAddListener(ofApp::useMic->Value,this,&ofApp::useMicChanged); + + soundStream.setup(this,0, 1, sampleRate, bufferSize, 1); + + //loadSong("12 Ferric Appetite.aiff"); + loadSong("passades/1 The Ninth Set-sector1:sector2pt.1.aiff"); + + //============================ gui + + lasergui.setup("laser","",230,820); + lasergui.add(laser_power.set("power", false)); + lasergui.add(laser_intensity.set("intensity", 30, 0, 255)); + lasergui.add(laser_points.set("points", 30000, 0, 40000)); + lasergui.add(laser_subdivide.set("subdivide", 15, 1, 100)); + 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)); + + responsegui.setup("audio response","",230,970); + responsegui.add(onset_threshold.set("onset threshold", 0.05f, 0.0f, 1.0f )); + responsegui.add(use_onset.set("trigger onset",false)); + responsegui.add(onset_duration.set("duration", 10, 1, 100)); + + onset_frame=0; + + chaosgui.setup("chaos","",460,820); + chaosgui.add(plotter.usechaos.set("use",false)); + chaosgui.add(plotter.chaosamount.set("amount", 0.0f, -0.1f, 0.1f)); + chaosgui.add(plotter.chaosscale.set("scale", 100.0f, 1.0f, 1000.0f)); + chaosgui.add(plotter.chaos_a.set("a", 0.85f, 0.0f, 10.0f)); + chaosgui.add(plotter.chaos_b.set("b", 0.9f, 0.0f, 10.0f)); + chaosgui.add(plotter.chaos_k.set("k", 0.4f, 0.0f, 10.0f)); + chaosgui.add(plotter.chaos_p.set("p", 7.7f, 0.0f, 10.0f)); + + drawgui.setup("drawing","",10,0); + drawgui.add(contour_threshold.setup("threshold", 140, 0, 255)); + drawgui.add(contour_simplify.setup("simplify", 0.8, 0.0, 10.0)); + drawgui.add(contour_useColour.setup("use colour", true)); + drawgui.add(laser_R.setup("red", 140, 0, 255)); + drawgui.add(laser_G.setup("green", 140, 0, 255)); + drawgui.add(laser_B.setup("blue", 140, 0, 255)); + drawgui.add(video_speed.setup("playback speed", 1.0, 0.0, 3.0)); + drawgui.add(shapes_randomise.setup("randomise shapes", true)); + drawgui.add(shapes_amount.setup("shapes amount", 0.2, 0.0, 0.8)); + drawgui.add(shapes_duration.setup("shape duration", 5, 0, 25)); + drawgui.add(use_mask.setup("use mask", true)); + drawgui.add(invert_mask.setup("invert mask", false)); + drawgui.add(use_segmenter.setup("use segmenter", false)); + drawgui.add(segmenter_speed.setup("segmenter speed", 0.2, -1.0, 1.0)); + drawgui.add(segmenter_length.setup("segmenter length", 0.2, 0.0, 1.0)); + drawgui.add(segmenter_number.setup("segmenter number", 1, 1, 8)); + drawgui.add(use_rotate.setup("XF rotate", false)); + drawgui.add(xf_rotate.setup("rotate speed", 0.0, -1.0, 1.0)); + drawgui.add(use_scale.setup("XF scale", false)); + drawgui.add(xf_scale_speed.setup("scale speed", 1.0, 0.0, 10.0)); + drawgui.add(xf_scale_min.setup("scale min", 1.0, 0.0, 3.0)); + drawgui.add(xf_scale_max.setup("scale max", 2.0, 0.0, 3.0)); + + audiogui.setup("audio","",10,450); + audiogui.add(useMic.set("mic",false)); + audiogui.add(useFft.set("fft",false)); + audiogui.add(scalePlot.set("plotscale", 0.1f, 0.0f, 1.0f )); //parameters are recognised by name only? + audiogui.add(decayPlot.set("decay", 0.9f, 0.0f, 1.0f )); + audiogui.add(plotter.random.set("random",true)); + audiogui.add(plotter.joined.set("joined",true)); + audiogui.add(plotter.bars.set("bars",true)); + audiogui.add(plotter.mirror.set("mirror",false)); + audiogui.add(plotter.width.set("point width", 2, 1, 256)); + audiogui.add(plotter.num_points.set("num points", 50, 1, 64)); + audiogui.add(plotter.history_size.set("num plots", 5, 1, 64)); + audiogui.add(plotter.translate.set("translate",ofVec2f(0,0),ofVec2f(-50,-50),ofVec2f(50,50))); + audiogui.add(plotter.rotate.set("rotate",0.0f,-10.0f,10.0f)); + audiogui.add(plotter.scale.set("scale",ofVec2f(1.0f,1.0f),ofVec2f(0.5f,0.5f),ofVec2f(2.0f,2.0f))); + audiogui.add(plotter.startColour.set("start",ofColor(255,255,255))); + audiogui.add(plotter.endColour.set("end",ofColor(0,0,0))); + + framecounter=0; + + //============================ MIDI + + midiIn.listInPorts(); + midiIn.openPort(0); + midiIn.addListener(this); + + //======================================= //positioning interface + + safety_frame.addVertex(0,0); //etc + + bShowPositionInterface=false; + bOutputSelected=false; + + outputOffsetScale=1.0f; + commandPressed=false; + + + select_warpframe=-1; + bDrawFrame=false; + + if( XML.loadFile("settings.xml") ){ + cout << "settings.xml loaded!" <<std::endl; + + } + else{ + 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) + ); + + outputPosition=ofPoint( + XML.getValue("POSITION:X", 0), + XML.getValue("POSITION:Y", 0) + ); + + outputScale=XML.getValue("SCALE", 1.0f); + +} + +//====================== audio functions + +void ofApp::loadSong(string str){ + + cout<<"loadSong "<<str<<endl; + + player.stop(); + player.loadSound(str); + player.setLoop(true); + player.play(); + useMic = 0; + gist.clearHistory(); +} + +void ofApp::onNoteOn(GistEvent &e){ + //ofLog() << "<<NOTE ON>>"; + onset_frame=0; + onset_number++; + //noteOnRadius = 100; +}; + + +void ofApp::onNoteOff(GistEvent &e){ + //ofLog() << "<<NOTE OFF>>"; + //turn off? + //noteOnRadius = 0; +}; + +void ofApp::processAudio(float * input, int bufferSize, int nChannels){ + //convert float array to vector + + + left.resize(bufferSize/nChannels); + right.resize(bufferSize/nChannels); + centre.resize(bufferSize/nChannels); + + float max=0.0f; + + + if (nChannels==2){ + + + for (int i = 0; i < bufferSize/nChannels; i++){ + left[i] = input[i*nChannels]; + right[i] = input[i*nChannels+1]; + centre[i] = (left[i]+right[i])*0.5; + if (centre[i]>max){ + max=centre[i]; + } + } + + + } + else if (nChannels==1){ + for (int i = 0; i < bufferSize;i++){ + left[i] = input[i]; + right[i] = input[i]; + centre[i] = input[i]; + if (centre[i]>max){ + max=centre[i]; + } + } + } + + //ofLog()<<"audio data max "<<max; + //float audio data is +- 0.5 + + + vector<float>buffer; + buffer.assign(&input[0],&input[bufferSize]); + + gist.processAudio(buffer, bufferSize, nChannels,sampleRate); +} + + +void ofApp::audioIn(float * input, int bufferSize, int nChannels){ + if(!useMic){ + return; + } + + //ofLog() << "processing "<<bufferSize<<" samples from mic"; + + processAudio(input, bufferSize, nChannels); + +} + +void ofApp::useMicChanged(){ + if (useMic) { + player.stop(); + } + else { + player.play(); + } +} + +//====================== 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", outputPosition.x); + XML.setValue("POSITION:Y", outputPosition.y); + + XML.setValue("SCALE", outputScale); + + XML.saveFile("settings.xml"); + cout << "settings.xml saved!" <<std::endl; +} + +//-------------------------------------------------------------- +void ofApp::updateOutput(ofEventArgs & args){ +//todo: set up listener for laser params or move them into a lasergui class + laser.set_pts(laser_points); + laser.set_subdivide(laser_subdivide); + laser.set_blanknum(laser_blank_num); + laser.set_maxangle(laser_max_angle); + + laser.set_intensity(laser_intensity); + + movie.setSpeed(video_speed); + + if(!useMic){ + if(player.isLoaded()){ + if (player.isPlaying()){ + vector<float> output = player.getCurrentBuffer(bufferSize); + processAudio(&output[0], bufferSize, 2); + // + if (useFft){ + fftSmoothed = player.getFFT(); + /* + float * fft = ofSoundGetSpectrum(plotter.num_points); + fftSmoothed.resize(plotter.num_points); + //printf("fft: "); + for (int i=0;i<plotter.num_points;i++){ + fftSmoothed[i]=fft[i]; + //printf("%f,",fftSmoothed[i]); + } + //printf("\r\n"); + */ + plotter.addpoints(fftSmoothed); + } + else { + plotter.addpoints(centre); + } + } + else { + player.play(); + } + } + + } + else { + if (player.isPlaying()){ + player.stop(); + } + if (centre.size()){ + if (useFft){ + float * fft = ofSoundGetSpectrum(plotter.num_points); + fftSmoothed.resize(plotter.num_points); + printf("fft: "); + for (int i=0;i<plotter.num_points;i++){ + fftSmoothed[i]=fft[i]; + printf("%f,",fftSmoothed[i]); + } + printf("\r\n"); + plotter.addpoints(fftSmoothed); + } + else { + if (!use_onset||onset_frame<onset_duration){ + plotter.addpoints(centre); + } + else { + plotter.blankframe(); + } + } + } + } + +} + +void ofApp::update(){ +/* + // Update the NDI sender list to find new senders + // There is no delay if no new senders are found + nSenders = ndiReceiver.FindSenders(); + + if(nSenders > 0) { + + // Has the user changed the sender index ? + if(ndiReceiver.SenderSelected()) { + // Release the current receiver. + // A new one is then created from the selected sender index. + ndiReceiver.ReleaseReceiver(); + bNDIreceiver = false; + } + + // Create a new receiver if one does not exist. + // We don't know the sender dimensions until a frame is received. + if(!bNDIreceiver) { + + // The receiver will detect which format a sender is using and convert + // the pixel buffer to BGRA for return. However, we can specify here + // that RGBA is the preferred format. + bNDIreceiver = ndiReceiver.CreateReceiver(NDIlib_recv_color_format_e_RGBX_RGBA); + // bNDIreceiver = ndiReceiver.CreateReceiver(); // default is BRRA + + // + // A receiver is created from an index into a list of sender names. + // The current user selected index is saved in the NDIreceiver class + // and is used to create the receiver unless you specify a particular index. + // + // The name of the sender can also be retrieved if you need it. + // If you specified a particular sender index to create the receiver + // use that index to retrieve it's name. + // + // In this application we use it to display the sender name. + // + + ndiReceiver.GetSenderName(senderName); + if(bNDIreceiver) + cout << "Created NDI receiver for " << senderName << endl; + + // Reset the starting values for frame rate calulations + fps = frameRate = 1; + + } + + } + + if(bNDIreceiver) { + + unsigned int width = 0; + unsigned int height = 0; + + // If the NDI sender uses BGRA format, the received buffer is converted to rgba by ReceiveImage. + // Optionally you can flip the image if necessary. + + // !CHECKME MACOS + // ReceiveImage needs an unsigned char* so changed + // ndiImage.getPixels() to ndiImage.getPixels().getData() + // to avoid type error + if(ndiReceiver.ReceiveImage(ndiImage.getPixels().getData(), width, height, false)) { // receives as rgba + + ndiImage.update(); + + // ---------------------------- + // Calculate received frame fps + lastTime = startTime; + startTime = ofGetElapsedTimeMicros(); + frameTime = (startTime - lastTime)/1000000; // seconds + if( frameTime > 0.01) { + frameRate = floor(1.0/frameTime + 0.5); + // damping from a starting fps value + fps *= 0.95; + fps += 0.05*frameRate; + } + // ---------------------------- + + // Have the NDI sender dimensions changed ? + if(senderWidth != width || senderHeight != height) { + + // Update the sender dimensions + senderWidth = width; + senderHeight = height; + + // Update the receiving image size + ndiImage.allocate(senderWidth, senderHeight, OF_IMAGE_COLOR_ALPHA); + + } + } + + } +*/ + if (movie.isLoaded()){ + movie.update(); + } + + gist.setThreshold(GIST_PEAK_ENERGY,onset_threshold); + + onset_frame++; +} + +const ofPoint previewframesize=ofPoint(320,240); + +//-------------------------------------------------------------- GUI +void ofApp::draw(){ + ofBackground(0); + + ofSetColor(255); + ofNoFill(); + + if (bShowPositionInterface){ + + glPushMatrix(); + + glTranslatef(20,20,0); + + ofDrawRectangle(0,0,560,560); + + glTranslatef(outputOffset.x,outputOffset.y,0); + + glScalef(guiScale,guiScale,guiScale ); + + glTranslatef(2048.0f+outputPosition.x,2048.0f+outputPosition.y,0); + + if (bOutputSelected) { + if (commandPressed) { + ofSetColor(0,255,0); + } + else { + ofSetColor(255,0,0); + } + } + + ofDrawRectangle( + (-outputWindowSize.x/2)*outputScale*outputOffsetScale, + (-outputWindowSize.y/2)*outputScale*outputOffsetScale, + outputWindowSize.x*outputScale*outputOffsetScale, + outputWindowSize.y*outputScale*outputOffsetScale); + + glPopMatrix(); + } + else { + lasergui.draw(); + drawgui.draw(); + audiogui.draw(); + chaosgui.draw(); + responsegui.draw(); + + //================================== NDI +/* + glPushMatrix(); + + glTranslatef(230,0,0); + + ofDrawRectangle(20,20,previewframesize.x+4,previewframesize.y+4); + + char str[256]; + + if(bNDIreceiver) { + + ndiImage.draw(22, 22, previewframesize.x, previewframesize.y); + + // Show fps etc. + if(nSenders > 0) { + if(bNDIreceiver) { + #ifdef _MSC_VER + sprintf_s(str, 256, "[%s] (%dx%d) - fps %2.0f", senderName, senderWidth, senderHeight, fps); + #else + // !CHECK MACOS + snprintf(str, 256, "[%s] (%dx%d) - fps %2.0f", senderName, senderWidth, senderHeight, fps); + str[255] = 0; + #endif + ofDrawBitmapString(str, 20, previewframesize.y+42); + } + + if(nSenders == 1) { + ofDrawBitmapString("1 network source", 25, 32); + } + else { + #ifdef _MSC_VER + sprintf_s(str, 256, "%d network sources", nSenders); + #else + // !CHECK MACOS + snprintf(str, 256, "%d network sources", nSenders); + str[255] = 0; + #endif + ofDrawBitmapString(str, 25, 32); + //ofDrawBitmapString("'SPACE' to list senders or RH click to open sender dialog", 20, ofGetHeight()-20); + } + } + } + else { + ofDrawBitmapString("Connecting . . .", 25, 32); + } + + glPopMatrix(); + + //================================== NDI + + glPushMatrix(); + + glTranslatef(230,300,0); + */ + //================================== video + + glPushMatrix(); + + glTranslatef(230,0,0); + + ofDrawRectangle(20,20,previewframesize.x+4,previewframesize.y+4); + + if (movie.isLoaded()){ + movie.draw(22, 22, previewframesize.x, previewframesize.y); + } + + glPopMatrix(); + + //================================== SVG + mask + + float scale=previewframesize.x/outputWindowSize.x; + + //================================== SVG + + glPushMatrix(); + + + glTranslatef(230,270,0); + + ofDrawRectangle(20,20,previewframesize.x+4,previewframesize.y+4); + + glTranslatef(22,22,0); + + glScalef(scale,scale,scale); + + for (auto shape=segmenters.begin();shape!=segmenters.end();shape++){ + shape->getPoly().draw(); + } + + glPopMatrix(); + + //================================== Mask + + glPushMatrix(); + + glTranslatef(230,540,0); + + ofDrawRectangle(20,20,previewframesize.x+4,previewframesize.y+4); + + ofFill(); + + glTranslatef(22,22,0); + + glScalef(scale,scale,scale); + + for (auto& shape:mask){ + shape.draw(); + } + + ofNoFill(); + + glPopMatrix(); + + } + + ofSetColor(255); + + ofDrawBitmapString(ofToString(onset_number)+":"+(onset_frame==0?"BEAT":ofToString(onset_frame)),10,ofGetHeight()-15); + +} + +void ofApp::drawOutput(ofEventArgs & args){ + ofBackground(0); + //composite output window + + ofSetColor(255,255,255); + + vector <colourPolyline> polyOutput; + + float interval=ofGetElapsedTimef()-prev_time; + rotate_amt+=interval*xf_rotate*5; + + phase=fmod(phase+(interval*segmenter_speed),1); + prev_time=ofGetElapsedTimef(); + + while (phase<0.0f) { + phase+=1.0f; + } + + scale_phase+=(interval*xf_scale_speed); + + scale_amt=(((sin(scale_phase)*0.5)+0.5)*(xf_scale_max-xf_scale_min))+xf_scale_min; + + switch (source){ + case TEST:{ + ofMatrix4x4 m = ofMatrix4x4::newIdentityMatrix(); + m.rotateRad(ofGetElapsedTimef(),0,0,1); + m.translate(ofGetWidth()/2,ofGetHeight()/2,0); + + glm::vec2 src[]={ + glm::vec2(0,0), + glm::vec2(ofGetWidth(),0), + glm::vec2(ofGetWidth(),ofGetHeight()), + glm::vec2(0,ofGetHeight()) + }; + + ofMatrix4x4 warp =lineTransformer::getPerspectiveTransformMatrix(src,warpframe); + + //drawPoly(polyLineTransform(makePolygon(4,200),m),200,200); + //drawPoly(polyLineTransform(makePolygon(5,200),m),-200,200); + //drawPoly(polyLineTransform(makePolygon(6,200),m),-200,-200); + + ofPolyline poly=lineTransformer::polyLineTransform(warp, + lineTransformer::polyLineTransform(m, + lineTransformer::makePolygon(6,200) + ) + ); + polyOutput.push_back(colourPolyline(poly,ofColor(laser_R,laser_G,laser_B))); + + } +/* + case NDI:{ + ofPoint scale=ofPoint(outputWindowSize.x/ndiImage.getWidth(),outputWindowSize.x/ndiImage.getHeight()); + + //does not work no matter what the fuck you do + + //grayImage.setFromPixels(pixels.getData(),ndiImage.getWidth(),ndiImage.getHeight()); + + //grayImage.draw(0,0,outputWindowSize.x,outputWindowSize.y); + + grayImage = colorImg; + + grayImage.threshold(contour_threshold); + + //virtual int findContours( ofxCvGrayscaleImage& input, + // int minArea, int maxArea, + // int nConsidered, bool bFindHoles, + // bool bUseApproximation = true); + contourFinder.findContours(grayImage, 20, (340*240)/3, 10, true); + + for (int i = 0; i < contourFinder.nBlobs; i++){ + colourPolyline shape; + for (auto& point:contourFinder.blobs[i].pts){ + ofVec3f p=point*scale; + ofColor c=colorImg.getPixels().getColor(point.x,point.y); + shape.addVertex(p,contour_useColour?c:ofColor(laser_R,laser_G,laser_B)); + } + shape.simplify(contour_simplify); + polyOutput.push_back(shape); + } + break; + + } +*/ + case Player:{ + if (!use_onset||onset_frame<onset_duration){ + if (movie.isLoaded()){ + ofPoint scale=ofPoint(outputWindowSize.x/movie.getWidth(),outputWindowSize.y/movie.getHeight()); + colorImg.setFromPixels(movie.getPixels()); + if (grayImage.getWidth()!=colorImg.getWidth()||grayImage.getHeight()!=colorImg.getHeight()){ + grayImage.clear(); + } + grayImage=colorImg; + grayImage.threshold(contour_threshold); + contourFinder.findContours(grayImage, 20, (340*240)/3, 10, true); + for (int i = 0; i < contourFinder.nBlobs; i++){ + colourPolyline shape; + for (auto& point:contourFinder.blobs[i].pts){ + ofVec3f p=point*scale; + ofColor c=colorImg.getPixels().getColor(point.x,point.y); + shape.addVertex(p,contour_useColour?c:ofColor(laser_R,laser_G,laser_B)); + } + shape.simplify(contour_simplify); + polyOutput.push_back(shape); + } + } + } + break; + } + case SVG_outlines:{ + if (shapes_randomise){ + if (framecounter==0){ + select_random_shapes(); + framecounter=shapes_duration; + } + for (auto s:shape_selection){ + if (use_segmenter){ + auto segments=segmenters[s].getSegments(segmenter_number,segmenter_length,phase); + for (auto segment=segments.begin();segment!=segments.end();segment++){ + polyOutput.push_back(colourPolyline(*segment,ofColor(laser_R,laser_G,laser_B))); + } + } + else { + polyOutput.push_back(colourPolyline(segmenters[s].getPoly(),ofColor(laser_R,laser_G,laser_B))); + } + } + framecounter--; + } + else { + for (auto shape=segmenters.begin();shape!=segmenters.end();shape++){ + if (use_segmenter){ + auto segments=shape->getSegments(segmenter_number,segmenter_length,phase); + for (auto segment=segments.begin();segment!=segments.end();segment++){ + polyOutput.push_back(colourPolyline(*segment,ofColor(laser_R,laser_G,laser_B))); + } + } + else { + polyOutput.push_back(colourPolyline(shape->getPoly(),ofColor(laser_R,laser_G,laser_B))); + + } + } + } + break; + } + case Audio:{ + ofMatrix4x4 x=ofMatrix4x4(1.0f,0.0f,0.0f,0.0f, + 0.0f,1.0f,0.0f,0.0f, + 0.0f,0.0f,1.0f,0.0f, + 0.0f,0.0f,0.0f,1.0f); + polyOutput=plotter.output(scalePlot,decayPlot); + break; + } + default: { + break; + } + } + + vector <colourPolyline> transformedOutput; + + if (use_rotate||use_scale){ + ofMatrix4x4 rm = ofMatrix4x4::newIdentityMatrix(); + rm.translate(-outputWindowSize.x/2,-outputWindowSize.y/2,0); + if (use_rotate){ + rm.rotateRad(rotate_amt,0,0,1); + } + if (use_scale){ + rm.scale(scale_amt,scale_amt,scale_amt); + } + rm.translate(outputWindowSize.x/2,outputWindowSize.y/2,0); + for (auto& shape:polyOutput){ + transformedOutput.push_back(lineTransformer::polyLineTransform(rm,shape)); + } + } + else { + transformedOutput=polyOutput; + } + + vector <colourPolyline> clippedOutput; + + if (mask.size()&&use_mask){ + clipper.Clear(); + clipper.addPolylines(mask, ClipperLib::ptClip); + vector <ofPolyline> shapes; //TODO make clipper clip colourpolylines + for (auto& poly: transformedOutput) + { + shapes.push_back(poly); + } + clipper.addPolylines(shapes,ClipperLib::ptSubject); + vector <ofPolyline> clipped; + if (invert_mask){ + clipped = clipper.getClippedLines(ClipperLib::ctDifference); + }else { + clipped = clipper.getClippedLines(ClipperLib::ctIntersection); + } + for (auto& clip: clipped) + { + clip.simplify(contour_simplify); + clippedOutput.push_back(colourPolyline(clip,ofColor(laser_R,laser_G,laser_B))); + } + } + else { + clippedOutput=transformedOutput; + } + + 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*outputOffsetScale)+mp, + ((warpframe[1]-mp)*outputScale*outputOffsetScale)+mp, + ((warpframe[2]-mp)*outputScale*outputOffsetScale)+mp, + ((warpframe[3]-mp)*outputScale*outputOffsetScale)+mp + }; + + ofMatrix4x4 scaled_warp =lineTransformer::getPerspectiveTransformMatrix(src,scaled_dest); + ofMatrix4x4 warp =lineTransformer::getPerspectiveTransformMatrix(src,warpframe); + + vector <colourPolyline> warpedOutput; + vector <colourPolyline> scaledWarpedOutput; + + for (auto s:clippedOutput){ + warpedOutput.push_back(lineTransformer::polyLineTransform(warp,s)); + scaledWarpedOutput.push_back(lineTransformer::polyLineTransform(scaled_warp,s)); + } + + int num = 0; + int pnum=0; + + + if (laser_power&&polyOutput.size()) { + num=laser.draw(scaledWarpedOutput); + } + else { + colourPolyline blank; + for (int i=0;i<100;i++){ + blank.addVertex(ofGetWidth()/2,ofGetHeight()/2,0,0,0); + } + laser.draw(blank); + } + for (auto& shape:warpedOutput){ + shape.draw(); + pnum+=shape.size(); + } + + + if (bDrawFrame){ + lineTransformer::drawWarpFrame(warpframe); + } + + if (num>0){ + ofSetWindowTitle(sourcenames[source]+": "+ofToString(ofGetFrameRate(), 2)+" fps laser points: "+ofToString(num)); + } + else { + + ofSetWindowTitle(sourcenames[source]+": "+ofToString(ofGetFrameRate(), 2)+" fps laser error points: "+ofToString(pnum)); + } + +} + +//-------------------------------------------------------------- +void ofApp::exit() { + audiogui.clear(); + +} + + + +//-------------------------------------------------------------- +void ofApp::outputKeyPressed(ofKeyEventArgs &args){ + + keyPressed(args); + + +} + +void ofApp::keyPressed(ofKeyEventArgs &args){ + if (args.key==OF_KEY_COMMAND){ + commandPressed=true; + } + + switch(args.key){ + case '`':{ + bShowPositionInterface=!bShowPositionInterface; + break; + } + case 'q':{ + source--; + if (source<0){ + source=Source_end-1; + } + break; + } + case 'p':{ + source=(source+1)%Source_end; + break; + } + case 'w':{ + bDrawFrame=!bDrawFrame; + break; + } + case 'd':{ + default_settings(); + break; + } + case 's':{ + save_settings(); + break; + } + } +} + +//-------------------------------------------------------------- +void ofApp::outputKeyReleased(ofKeyEventArgs &args){ + + outputKeyReleased(args); + + +} + +void ofApp::keyReleased(ofKeyEventArgs &args){ + if (args.key==OF_KEY_COMMAND){ + commandPressed=false; + } +} + + +//-------------------------------------------------------------- +void ofApp::mouseMoved(int x, int y ){ + +} + +//-------------------------------------------------------------- +void ofApp::outputMouseDragged(ofMouseEventArgs & args){ + if (select_warpframe>-1){ + warpframe[select_warpframe]=glm::vec2(args.x,args.y); + } +} + +void ofApp::mouseDragged(int x, int y, int button){ + if (bOutputSelected){ + if (commandPressed){ + float startDistance=((outputPosition*guiScale)+ofPoint(300,300)).distance(outputSelectionPoint); + float currentDistance=((outputPosition*guiScale)+ofPoint(300,300)).distance(ofPoint(x,y)); + outputOffsetScale=currentDistance/startDistance; + } + else { + outputOffset=ofPoint(x,y)-outputSelectionPoint; + laser.set_centre(ofPoint( + outputPosition.x+(outputOffset.x/guiScale), + outputPosition.y+(outputOffset.y/guiScale) + )); + } + } +} + +//-------------------------------------------------------------- +void ofApp::outputMousePressed(ofMouseEventArgs & args){ + for (int i=0;i<4;i++){ + if (ofPoint(args.x,args.y).distance(warpframe[i])<25){ + select_warpframe=i; + } + } +} + +void ofApp::mousePressed(int x, int y, int button){ + if (bShowPositionInterface){ + if (x>(300+((outputPosition.x-((outputWindowSize.x/2)*outputScale))*guiScale))&& + x<(300+((outputPosition.x+((outputWindowSize.x/2)*outputScale))*guiScale))&& + y>(300+((outputPosition.y-((outputWindowSize.y/2)*outputScale))*guiScale))&& + y<(300+((outputPosition.y+((outputWindowSize.y/2)*outputScale))*guiScale)) + ){ + outputSelectionPoint=ofPoint(x,y); + bOutputSelected=true; + } + } + +} + +//-------------------------------------------------------------- +void ofApp::outputMouseReleased(ofMouseEventArgs & args){ + select_warpframe=-1; +} + +void ofApp::mouseReleased(int x, int y, int button){ + if (bOutputSelected){ + if (commandPressed){ + outputScale*=outputOffsetScale; + } + else { + outputPosition+=outputOffset/guiScale; + } + bOutputSelected=false; + outputOffset=ofPoint(0,0); + outputOffsetScale=1.0f; + } + +} + +//-------------------------------------------------------------- +void ofApp::mouseEntered(int x, int y){ + +} + +//-------------------------------------------------------------- +void ofApp::mouseExited(int x, int y){ + +} + +//-------------------------------------------------------------- +void ofApp::outputWindowResized(ofResizeEventArgs &resizeargs){ + +} + +void ofApp::windowResized(int w, int h){ + +} + +void ofApp::select_random_shapes(){ + shape_selection.clear(); + while (shape_selection.size()<(segmenters.size()*shapes_amount)){ + int selection=rand()%segmenters.size(); + if (shape_selection.find(selection)==shape_selection.end()){ + shape_selection.insert(selection); + } + } + std::stringstream strm; + for (auto& s:shape_selection){ + strm << s <<" "; + } + //cout << "randomly selected (" << strm.str() <<") \n"; +} + +//-------------------------------------------------------------- +void ofApp::dragEvent(ofDragInfo dragInfo){ + + if (dragInfo.position.x>250&&dragInfo.position.x<570&&dragInfo.position.y>20&&dragInfo.position.y<266){ + std::string filename= *dragInfo.files.begin(); + if (movie.load(filename)){ + cout << "loaded "<< filename<<std::endl; + movie.setLoopState(OF_LOOP_NORMAL); + movie.setVolume(0.0f); + movie.play(); + } + else { + cout << "failed to load"<<std::endl; + } + } + + if (dragInfo.position.x>250&&dragInfo.position.x<570&&dragInfo.position.y>320&&dragInfo.position.y<566){ + std::string filename= *dragInfo.files.begin(); + svg.load(filename); + vector <ofPath> imagepaths= svg.getPaths(); + + std::stringstream strm; + + if (imagepaths.size()){ + segmenters.clear(); + for (auto& path:imagepaths){ + path.setPolyWindingMode(OF_POLY_WINDING_ODD); + + vector <ofPolyline> outlines= path.getOutline(); + for (auto& outline:outlines){ + strm << outline.size() << "->"; + outline.simplify(contour_simplify); + strm << outline.size() << " "; + segmenters.push_back(lineSegmenter(outline)); + } + strm << " , "; + } + + cout << "SVG: found " << imagepaths.size() << " paths with " << segmenters.size() << " shapes [ " << strm.str() << " ]" <<std::endl; + select_random_shapes(); + } + + } + + if (dragInfo.position.x>250&&dragInfo.position.x<570&&dragInfo.position.y>620&&dragInfo.position.y<866){ + std::string filename= *dragInfo.files.begin(); + svg.load(filename); + vector <ofPath> imagepaths= svg.getPaths(); + + std::stringstream strm; + + if (imagepaths.size()){ + mask.clear(); + for (auto& path:imagepaths){ + path.setPolyWindingMode(OF_POLY_WINDING_ODD); + + vector <ofPolyline> outlines= path.getOutline(); + for (auto& outline:outlines){ + strm << outline.size() << "->"; + outline.simplify(contour_simplify); + strm << outline.size() << " "; + mask.push_back(outline); + } + strm << " , "; + } + + cout << "Mask: found " << imagepaths.size() << " paths with " << mask.size() << " shapes [ " << strm.str() << " ]" <<std::endl; + + } + + } + +} + +void ofApp::newMidiMessage(ofxMidiMessage& msg) { + //column 0 for general controls + //printf("Midi: %i %i %i\n",msg.channel,msg.control,msg.value); + + int offset; + + //=============================================== + offset=0; + + if (msg.channel==1&&msg.control==1+offset){ + //pot + xf_rotate=(((float)msg.value)/64.0f)-1.0f; + } + if (msg.channel==1&&msg.control==33+offset){ + //pot button + use_rotate=use_rotate?false:true; + } + if (msg.channel==1&&msg.control==65+offset){ + //top button + rotate_amt=ofRandom(5.0f); + } + if (msg.channel==1&&msg.control==73+offset){ + //bottom button + } + if (msg.channel==1&&msg.control==81+offset){ + //fader + laser_intensity=msg.value*2; + } + + //=============================================== + offset=1; + + if (msg.channel==1&&msg.control==1+offset){ + //pot + xf_scale_speed=(((float)msg.value)/128.0f)*10.0f; + } + if (msg.channel==1&&msg.control==33+offset){ + //pot button + use_scale=use_scale?false:true; + } + if (msg.channel==1&&msg.control==65+offset){ + //top button + scale_phase=ofRandom(5.0f); + } + if (msg.channel==1&&msg.control==73+offset){ + //bottom button + } + if (msg.channel==1&&msg.control==81+offset){ + //fader + laser_R=msg.value*2; + } + + //=============================================== + offset=2; + + if (msg.channel==1&&msg.control==1+offset){ + //pot + xf_scale_min=(((float)msg.value)/128.0f); + } + if (msg.channel==1&&msg.control==33+offset){ + //pot button + } + if (msg.channel==1&&msg.control==65+offset){ + //top button + } + if (msg.channel==1&&msg.control==73+offset){ + //bottom button + } + if (msg.channel==1&&msg.control==81+offset){ + //fader + laser_G=msg.value*2; + } + + //=============================================== + offset=3; + + if (msg.channel==1&&msg.control==1+offset){ + //pot + xf_scale_max=(((float)msg.value)/128.0f); + } + if (msg.channel==1&&msg.control==33+offset){ + //pot button + } + if (msg.channel==1&&msg.control==65+offset){ + //top button + } + if (msg.channel==1&&msg.control==73+offset){ + //bottom button + } + if (msg.channel==1&&msg.control==81+offset){ + //fader + laser_B=msg.value*2; + } + + //=============================================== + offset=4; + + if (msg.channel==1&&msg.control==1+offset){ + //pot + } + if (msg.channel==1&&msg.control==33+offset){ + //pot button + } + if (msg.channel==1&&msg.control==65+offset){ + //top button + } + if (msg.channel==1&&msg.control==73+offset){ + //bottom button + } + if (msg.channel==1&&msg.control==81+offset){ + //fader + video_speed=((float)msg.value)/40.0f; + } + + //=============================================== + offset=5; + + if (msg.channel==1&&msg.control==1+offset){ + //pot + } + if (msg.channel==1&&msg.control==33+offset){ + //pot button + } + if (msg.channel==1&&msg.control==65+offset){ + //top button + } + if (msg.channel==1&&msg.control==73+offset){ + //bottom button + } + if (msg.channel==1&&msg.control==81+offset){ + //fader + segmenter_speed=(((float)msg.value)/64.0f)-1.0f; + } +} + |
