warp video

I need to warp my video like ‘f’ in the polygon example. I have the points set but the video won’t ‘warp’ when I move the points. I was wondering what I am missing.
Here is my code in the testApp.cpp.

Thanks!
T

  
#include "testApp.h"  
#include "stdio.h"  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	  
	ofSetVerticalSync(true);  
	ofBackground(0,0,0);  
	  
	ofSetFrameRate(60);  
	  
	riverMovie.loadMovie("movies/left-undercurrent.mov");  
	ofSetFullscreen(true);  
	riverMovie.play();  
  
	ard.connect("/dev/cu.usbserial-A6008dhC", 57600);	  
	bSetupArduino	= false;							// flag so we setup arduino when its ready, you don't need to touch this :)  
	  
	ofEnableSmoothing();  
	  
	nCurveVertexes = 8;  
	  
	start= 100;  
	vHeight = 240;  
	vWidth = 320;  
	  
	curveVertices[0].x = start;  
	curveVertices[0].y = start;  
	curveVertices[1].x = vWidth/2 + start;  
	curveVertices[1].y = start;  
	curveVertices[2].x = vWidth + start;  
	curveVertices[2].y = start;  
	curveVertices[3].x = vWidth + start;  
	curveVertices[3].y = vHeight/2 + start;  
	curveVertices[4].x = vWidth + start;  
	curveVertices[4].y = vHeight + start;  
	curveVertices[5].x = vWidth/2 + start;  
	curveVertices[5].y = vHeight + start;  
	curveVertices[6].x = start;  
	curveVertices[6].y = vHeight + start;  
	curveVertices[7].x = start;  
	curveVertices[7].y = vHeight/2 + start;  
	  
	for (int i = 0; i < nCurveVertexes; i++){  
		curveVertices[i].bOver 			= false;  
		curveVertices[i].bBeingDragged 	= false;  
		curveVertices[i].radius = 4;  
	}  
	  
	pingPin = 7;  
	  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
	riverMovie.idleMovie();  
	if ( ard.isArduinoReady()){  
		// 1st: setup the arduino if haven't already:  
		if (bSetupArduino == false){  
			setupArduino();  
			bSetupArduino = true;	// only do this once  
		}		  
		  
		// 2nd do the update of the arduino  
		updateArduino();  
		  
  
	}  
	  
	pingSmoothed = ard.getAnalog(pingPin);  
	pingSmoothed = 0.75f * pingSmoothed + 0.25f * pingValue;  
	  
}  
  
//--------------------------------------------------------------  
void testApp::setupArduino(){  
	// this is where you setup all the pins and pin modes, etc  
	for (int i = 0; i < 13; i++){  
		ard.sendDigitalPinMode(i, ARD_INPUT);  
	}  
  
	ard.sendDigitalPinMode(13, ARD_OUTPUT);  
	ard.sendAnalogPinReporting(0, ARD_ANALOG);	// AB: report data  
	ard.sendDigitalPinMode(7, ARD_INPUT);		// on diecimelia: 11 pwm?*/  
}  
  
//--------------------------------------------------------------  
  
  
  
void testApp::updateArduino(){  
	  
  
	// update the arduino, get any data or messages: 		  
	ard.update();  
  
	  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	riverMovie.draw(100,100,vWidth,vHeight);  
	riverMovie.setVolume(15);  
	  
	ofSetColor(0xFFFFFF);  
	ofSetVerticalSync(true);  
	  
	if (!ard.isArduinoReady()){  
		ofDrawBitmapString("arduino not ready\n", 0, 40);  
	} else {  
		  
		  
		tempPingSmoothed = abs(pingSmoothed);  
		if(ofInRange(tempPingSmoothed, 0, 40)){  
			riverMovie.setSpeed(.25);  
		} else if(ofInRange(tempPingSmoothed, 41, 108)){  
			riverMovie.setSpeed(1);  
		} else {  
			riverMovie.setSpeed(1);  
		}  
		  
		float pct = tempPingSmoothed / 108;  
        float speed = (2 * pct - 1) * 1.0f;  
		  
		ofSetColor(0xFFFFFF);  
		ofDrawBitmapString("video speed " + ofToString(speed) + "\n",0,500);  
		  
		ofDrawBitmapString("analog data on pin 7 Ping Sensor = " + ofToString(pingValue) + "\n",0,530);  
		ofDrawBitmapString("analog data on pin 7 smoothed = " + ofToString(pingSmoothed) + "\n",0,550);  
		ofDrawBitmapString("temp abs analog data on pin 7 smoothed = " + ofToString(tempPingSmoothed) + "\n",0,570);  
		  
		ofDrawBitmapString("speed from formula = " + ofToString(speed) + "\n",0,590);  
		//ofDrawBitmapString("arduino is ready",0, 40);  
						//"\nsending pwm: " + ofToString((int)(128 + 128 * sin(ofGetElapsedTimef()))), 545, 40);  
  
	}  
	  
	  
	ofSetColor(0x2bdbe6);  
	  
	ofBeginShape();  
	  
		for (int i = 0; i < nCurveVertexes; i++){  
			  
			  
			// sorry about all the if/states here, but to do catmull rom curves  
			// we need to duplicate the start and end points so the curve acutally   
			// goes through them.  
			  
			// for i == 0, we just call the vertex twice  
			// for i == nCurveVertexes-1 (last point) we call vertex 0 twice  
			// otherwise just normal ofCurveVertex call  
			  
			if (i == 0){  
				ofCurveVertex(curveVertices[0].x, curveVertices[0].y); // we need to duplicate 0 for the curve to start at point 0  
				ofCurveVertex(curveVertices[0].x, curveVertices[0].y); // we need to duplicate 0 for the curve to start at point 0  
			} else if (i == nCurveVertexes-1){  
				ofCurveVertex(curveVertices[i].x, curveVertices[i].y);  
				ofCurveVertex(curveVertices[0].x, curveVertices[0].y);	// to draw a curve from pt 6 to pt 0  
				ofCurveVertex(curveVertices[0].x, curveVertices[0].y);	// we duplicate the first point twice  
			} else {  
				ofCurveVertex(curveVertices[i].x, curveVertices[i].y);  
			}  
		}  
		  
	ofEndShape();  
	// show a faint the non-curve version of the same polygon:  
	ofEnableAlphaBlending();  
		ofNoFill();  
		ofSetColor(0xFFFFFF);  
		ofBeginShape();  
			for (int i = 0; i < nCurveVertexes; i++){  
				ofVertex(curveVertices[i].x, curveVertices[i].y);  
			}  
		ofEndShape(true);  
		  
		  
		ofSetColor(0xFFFFFF);  
		for (int i = 0; i < nCurveVertexes; i++){  
			if (curveVertices[i].bOver == true) ofFill();  
			else ofNoFill();  
			ofCircle(curveVertices[i].x, curveVertices[i].y,4);  
		}  
	ofDisableAlphaBlending();  
  
	  
	  
     
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed(int key){  
}  
  
//--------------------------------------------------------------  
void testApp::keyReleased(int key){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mouseMoved(int x, int y ){  
	for (int i = 0; i < nCurveVertexes; i++){  
		float diffx = x - curveVertices[i].x;  
		float diffy = y - curveVertices[i].y;  
		float dist = sqrt(diffx*diffx + diffy*diffy);  
		if (dist < curveVertices[i].radius){  
			curveVertices[i].bOver = true;  
		} else {  
			curveVertices[i].bOver = false;  
		}	  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::mouseDragged(int x, int y, int button){  
	for (int i = 0; i < nCurveVertexes; i++){  
		if (curveVertices[i].bBeingDragged == true){  
			curveVertices[i].x = x;  
			curveVertices[i].y = y;  
		}  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::mousePressed(int x, int y, int button){  
	for (int i = 0; i < nCurveVertexes; i++){  
		float diffx = x - curveVertices[i].x;  
		float diffy = y - curveVertices[i].y;  
		float dist = sqrt(diffx*diffx + diffy*diffy);  
		if (dist < curveVertices[i].radius){  
			curveVertices[i].bBeingDragged = true;  
		} else {  
			curveVertices[i].bBeingDragged = false;  
		}	  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::mouseReleased(int x, int y, int button){  
	for (int i = 0; i < nCurveVertexes; i++){  
		curveVertices[i].bBeingDragged = false;	  
	}  
}  
  
//--------------------------------------------------------------  
void testApp::windowResized(int w, int h){  
  
}  
  
  

it’s not clear what you want to do here. The curveVertex() calls are for drawing polygons and can’t manipulate video or any other textured drawable object (ofImage, ofVideoGrabber, etc).

can you elaborate?

take care!
zach

Thanks for your reply.

Ultimately I want a user’s presence to make the video wobble. I am using a distance sensor to detect the viewer. That will initiate the wobble.

I thought maybe I could use the same techniques that are in the polygonExample, but I guess I that’s the wrong approach…

I found some examples of warping video here:

http://forum.openframeworks.cc/t/render-to-texture/371/0

and here:

http://www.berio.alg-a.org/Warping-video-Part-2

the latter is with a mouse and I thought I could do this automatically using a random function to move the anchor points…

is this possible?

T

I’m afraid you can’t do this with the ofVertex ofCurveVertex methods. There are many ways to do it though (using the pixels array, openCV warp, pixel shader, vertex shader).

I think the easiest way is to:

  • bind the texture
  • Create a nested loop to create and draw a bunch of vertices with uv coordinates using openGL :glTexCoord(u, v); glVertex(x, y, z);
  • unbind the texture

then in your loop you just slide your vertices around (or slide the uv coordinates around)

whats the best way to bind the texture… :-/

T

you can do it like this (I think…)

  
  
vidPlayer.getTextureReference().bind();  
  

when you are done, you can unbind as well.

  • zach

thanks for your help.

that almost works but I can’t access

  
glTexCoord(u, v);   
glVertex(x, y, z);  

even after I bind and including #include <OpenGL/glu.h>

Here is my loop

  
  
int pixWidth = myMovie.width;  // how long is a line of pixels  
int pixHeight = myMovie.height;  
		  
		  
myMovie.getTextureReference().bind();  
		  
for (int i = 4; i < pixWidth; i+=8){  
	for (int j = 4; j < pixHeight; j+=8){  
		unsigned char pix = pixels[(j * pixWidth + i)];  
        }  
}  
  

but since I don’t have access to those gl functions I’m not sure how to proceed…

T

the function is called glTexCoord2d or glTexCoord3d, and the same with vertex, depending if you want 2 or 3 arguments.