ofxPiMapper fixed for C++17 & oF 12.0
 
 

314 lines
7.0 KiB

#include "QuadSurface.h"
namespace ofx {
namespace piMapper {
QuadSurface::QuadSurface(){
_perspectiveWarping = false;
setup();
}
QuadSurface::~QuadSurface(){
std::cout << "QuadSurface destructor." << std::endl;
}
void QuadSurface::setup(){
// Create 4 points for the 2 triangles
Vec3 p1 = Vec3(0.0f, 0.0f, 0.0f);
Vec3 p2 = Vec3(0.0f, ofGetHeight(), 0.0f);
Vec3 p3 = Vec3(ofGetWidth(), ofGetHeight(), 0.0f);
Vec3 p4 = Vec3(ofGetWidth(), 0.0f, 0.0f);
// Create 4 point for the texture coordinates
Vec2 t1 = Vec2(0.0f, 0.0f);
Vec2 t2 = Vec2(1.0f, 0.0f);
Vec2 t3 = Vec2(1.0f, 1.0f);
Vec2 t4 = Vec2(0.0f, 1.0f);
setup(p1, p2, p3, p4, t1, t2, t3, t4, source);
}
void QuadSurface::setup(Vec3 p1, Vec3 p2, Vec3 p3, Vec3 p4,
Vec2 t1, Vec2 t2, Vec2 t3, Vec2 t4,
BaseSource * newSource){
// Assign texture
source = newSource;
// Clear mesh
mesh.clear();
// Create a surface with the points
mesh.addVertex(p1.toOf());
mesh.addVertex(p2.toOf());
mesh.addVertex(p3.toOf());
mesh.addVertex(p4.toOf());
// Add 2 triangles
mesh.addTriangle(0, 2, 3);
mesh.addTriangle(0, 1, 2);
// Add texture coordinates
mesh.addTexCoord(t1.toOf());
mesh.addTexCoord(t2.toOf());
mesh.addTexCoord(t3.toOf());
mesh.addTexCoord(t4.toOf());
}
void QuadSurface::draw(){
if(source->getTexture() == 0){
return;
}
if(!source->getTexture()->isAllocated()){
return;
}
if(_perspectiveWarping){
if(mesh.haveVertsChanged() || mesh.haveTexCoordsChanged()){
calculateHomography();
}
ofRectangle box = getMeshBoundingBox();
ofMesh m = mesh;
m.setVertex(0, Vec3(0, 0, 0).toOf());
m.setVertex(1, Vec3(box.width, 0, 0).toOf());
m.setVertex(2, Vec3(box.width, box.height, 0).toOf());
m.setVertex(3, Vec3(0, box.height, 0).toOf());
ofPushMatrix();
if(true){
bool normalizedTexCoords = ofGetUsingNormalizedTexCoords();
ofEnableNormalizedTexCoords();
glMultMatrixf(_matrix);
source->getTexture()->bind();
m.draw();
source->getTexture()->unbind();
if(!normalizedTexCoords){
ofDisableNormalizedTexCoords();
}
}
ofPopMatrix();
}else{
bool normalizedTexCoords = ofGetUsingNormalizedTexCoords();
ofEnableNormalizedTexCoords();
ofPushStyle();
ofSetColor(255, 255, 255);
source->getTexture()->bind();
mesh.draw();
source->getTexture()->unbind();
ofPopStyle();
if(!normalizedTexCoords){
ofDisableNormalizedTexCoords();
}
}
}
void QuadSurface::setVertex(int index, Vec3 p){
if(index > 3){
ofLog() << "Vertex with this index does not exist: " << index << std::endl;
return;
}
mesh.setVertex(index, p.toOf());
ofNotifyEvent(vertexChangedEvent, index, this);
}
void QuadSurface::setVertices(std::vector<Vec3> v){
if(v.size() != 4){
throw runtime_error("Wrong number of vertices");
}
for(int i = 0; i < 4; ++i){
mesh.setVertex(i, v[i].toOf());
}
std::vector<Vec3> vertices = Vec3::fromOf(mesh.getVertices());
ofNotifyEvent(verticesChangedEvent, vertices, this);
}
void QuadSurface::setTexCoord(int index, Vec2 t){
if(index > 3){
ofLog() << "Texture coordinate with this index does not exist: " << index
<< std::endl;
return;
}
mesh.setTexCoord(index, t.toOf());
}
void QuadSurface::setTexCoords(std::vector<Vec2> t){
if(t.size() != 4){
throw runtime_error("Wrong number of vertices");
}
for(int i = 0; i < 4; ++i){
mesh.setTexCoord(i, t[i].toOf());
}
}
void QuadSurface::moveBy(Vec3 v){
for(int i = 0; i < mesh.getVertices().size(); i++){
mesh.getVertices()[i] += v.toOf();
}
setMoved(true);
std::vector<Vec3> vertices = Vec3::fromOf(mesh.getVertices());
ofNotifyEvent(verticesChangedEvent, vertices, this);
}
int QuadSurface::getType(){
return SurfaceType::QUAD_SURFACE;
}
bool QuadSurface::hitTest(Vec2 p){
ofPolyline line = getHitArea();
if(line.inside(p.x, p.y)){
return true;
}else{
return false;
}
}
Vec3 QuadSurface::getVertex(int index){
if(index > 3){
ofLog() << "Vertex with this index does not exist: " << index << std::endl;
throw runtime_error("Vertex index out of bounds.");
}
return Vec3(
mesh.getVertex(index).x,
mesh.getVertex(index).y,
mesh.getVertex(index).z);
}
Vec2 QuadSurface::getTexCoord(int index){
if(index > 3){
throw runtime_error("Texture coordinate index out of bounds.");
}
return Vec2(
mesh.getTexCoord(index).x,
mesh.getTexCoord(index).y);
}
ofPolyline QuadSurface::getHitArea(){
ofPolyline line;
line.addVertex(ofPoint(mesh.getVertex(0).x, mesh.getVertex(0).y));
line.addVertex(ofPoint(mesh.getVertex(1).x, mesh.getVertex(1).y));
line.addVertex(ofPoint(mesh.getVertex(2).x, mesh.getVertex(2).y));
line.addVertex(ofPoint(mesh.getVertex(3).x, mesh.getVertex(3).y));
line.close();
return line;
}
ofPolyline QuadSurface::getTextureHitArea(){
ofPolyline line;
Vec2 textureSize =
Vec2(source->getTexture()->getWidth(),
source->getTexture()->getHeight());
for(int i = 0; i < mesh.getTexCoords().size(); i++){
line.addVertex(ofPoint(mesh.getTexCoords()[i] * textureSize.toOf()));
}
line.close();
return line;
}
std::vector<Vec3> QuadSurface::getVertices(){
return Vec3::fromOf(mesh.getVertices());
}
std::vector<Vec2> QuadSurface::getTexCoords(){
return Vec2::fromOf(mesh.getTexCoords());
}
void QuadSurface::calculateHomography(){
float src[4][2];
float dst[4][2];
ofRectangle box = getMeshBoundingBox();
src[0][0] = 0;
src[0][1] = 0;
src[1][0] = box.width;
src[1][1] = 0;
src[2][0] = box.width;
src[2][1] = box.height;
src[3][0] = 0;
src[3][1] = box.height;
Vec3 p0(mesh.getVertex(0).x, mesh.getVertex(0).y, mesh.getVertex(0).z);
Vec3 p1(mesh.getVertex(1).x, mesh.getVertex(1).y, mesh.getVertex(1).z);
Vec3 p2(mesh.getVertex(2).x, mesh.getVertex(2).y, mesh.getVertex(2).z);
Vec3 p3(mesh.getVertex(3).x, mesh.getVertex(3).y, mesh.getVertex(3).z);
dst[0][0] = p0.x;
dst[0][1] = p0.y;
dst[1][0] = p1.x;
dst[1][1] = p1.y;
dst[2][0] = p2.x;
dst[2][1] = p2.y;
dst[3][0] = p3.x;
dst[3][1] = p3.y;
HomographyHelper::findHomography(src, dst, _matrix);
}
void QuadSurface::setPerspectiveWarping(bool b){
_perspectiveWarping = b;
}
bool QuadSurface::getPerspectiveWarping(){
return _perspectiveWarping;
}
ofRectangle QuadSurface::getMeshBoundingBox(){
float minX = 10000.0f;
float minY = 10000.0f;
float maxX = 0.0f;
float maxY = 0.0f;
for(int i = 0; i < mesh.getVertices().size(); ++i){
if(mesh.getVertices()[i].x < minX){
minX = mesh.getVertices()[i].x;
}
if(mesh.getVertices()[i].y < minY){
minY = mesh.getVertices()[i].y;
}
if(mesh.getVertices()[i].x > maxX){
maxX = mesh.getVertices()[i].x;
}
if(mesh.getVertices()[i].y > maxY){
maxY = mesh.getVertices()[i].y;
}
}
ofRectangle boundingBox = ofRectangle(ofPoint(minX, minY), ofPoint(maxX, maxY));
return boundingBox;
}
BaseSurface * QuadSurface::clone(){
QuadSurface * s = new QuadSurface();
s->setVertices(getVertices());
s->setTexCoords(getTexCoords());
s->setPerspectiveWarping(getPerspectiveWarping());
BaseSource * src = getSource();
src->referenceCount++;
s->setSource(src);
return s;
}
} // namespace piMapper
} // namespace ofx