From 2d504160d5394a5f53cd045d4ed07290adbaa990 Mon Sep 17 00:00:00 2001 From: Krisjanis Rijnieks Date: Mon, 3 Oct 2016 17:39:48 +0200 Subject: [PATCH] Add HexagonSurface as base for CircleSurface --- .../Modes/ProjectionMappingMode.cpp | 7 + src/Application/SettingsLoader.cpp | 48 ++++ src/Application/SettingsLoader.h | 1 + src/Gui/Widgets/SurfaceHighlightWidget.cpp | 2 + src/Gui/Widgets/TextureEditorWidget.cpp | 2 + src/Surfaces/HexagonSurface.cpp | 252 ++++++++++++++++++ src/Surfaces/HexagonSurface.h | 45 ++++ src/Surfaces/SurfaceFactory.cpp | 7 + src/Surfaces/SurfaceFactory.h | 2 + src/Surfaces/SurfaceType.h | 5 +- 10 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 src/Surfaces/HexagonSurface.cpp create mode 100644 src/Surfaces/HexagonSurface.h diff --git a/src/Application/Modes/ProjectionMappingMode.cpp b/src/Application/Modes/ProjectionMappingMode.cpp index c2cb5d9..8dd6b56 100644 --- a/src/Application/Modes/ProjectionMappingMode.cpp +++ b/src/Application/Modes/ProjectionMappingMode.cpp @@ -71,6 +71,13 @@ void ProjectionMappingMode::onKeyPressed(Application * app, ofKeyEventArgs & arg SurfaceType::GRID_WARP_SURFACE) ); break; + + case 'h': + app->getCmdManager()->exec( + new AddSurfaceCmd( + app->getSurfaceManager(), + SurfaceType::HEXAGON_SURFACE)); + break; case OF_KEY_BACKSPACE: if(app->getSurfaceManager()->getSelectedSurface() == 0){ diff --git a/src/Application/SettingsLoader.cpp b/src/Application/SettingsLoader.cpp index 8dd461d..c69f003 100644 --- a/src/Application/SettingsLoader.cpp +++ b/src/Application/SettingsLoader.cpp @@ -127,6 +127,12 @@ bool SettingsLoader::load( gridWarpSurface->setSource(source); } surfaces->push_back(gridWarpSurface); + }else if(type == SurfaceType::HEXAGON_SURFACE){ + BaseSurface * hexagonSurface = getHexagonSurface(xmlSettings); + if(sourceName != "none" && source != 0){ + hexagonSurface->setSource(source); + } + surfaces->push_back(hexagonSurface); } xmlSettings->popTag(); // surface @@ -460,8 +466,50 @@ BaseSurface * SettingsLoader::getGridWarpSurface(ofxXmlSettings * xmlSettings){ return gridWarpSurface; } +BaseSurface * SettingsLoader::getHexagonSurface(ofxXmlSettings * xmlSettings){ + vector vertices; + + if(xmlSettings->tagExists("vertices")){ + xmlSettings->pushTag("vertices"); + + unsigned int v = 0; + while(xmlSettings->tagExists("vertex", v)){ + xmlSettings->pushTag("vertex", v); + vertices.push_back(ofVec2f(xmlSettings->getValue("x", 0.0f), + xmlSettings->getValue("y", 0.0f))); + xmlSettings->popTag(); // vertex + v += 1; + } + + xmlSettings->popTag(); // vertices + } + + vector texCoords; + if(xmlSettings->tagExists("texCoords")){ + xmlSettings->pushTag("texCoords"); + + unsigned int t = 0; + while(xmlSettings->tagExists("texCoord", t)){ + xmlSettings->pushTag("texCoord", t); + texCoords.push_back(ofVec2f(xmlSettings->getValue("x", 0.0f), + xmlSettings->getValue("y", 0.0f))); + xmlSettings->popTag(); // texCoord + t += 1; + } + xmlSettings->popTag(); // texCoords + } + + // Create and add a triangle surface + BaseSurface * hexagonSurface = + SurfaceFactory::instance()->createSurface( + SurfaceType::HEXAGON_SURFACE); + hexagonSurface->setVertices(vertices); + hexagonSurface->setTexCoords(texCoords); + + return hexagonSurface; +} } // namespace piMapper } // namespace ofx diff --git a/src/Application/SettingsLoader.h b/src/Application/SettingsLoader.h index 329385d..d785557 100644 --- a/src/Application/SettingsLoader.h +++ b/src/Application/SettingsLoader.h @@ -31,6 +31,7 @@ class SettingsLoader { BaseSurface * getTriangleSurface(ofxXmlSettings * xmlSettings); BaseSurface * getQuadSurface(ofxXmlSettings * xmlSettings); BaseSurface * getGridWarpSurface(ofxXmlSettings * xmlSettings); + BaseSurface * getHexagonSurface(ofxXmlSettings * xmlSettings); string _lastLoadedFilename; }; diff --git a/src/Gui/Widgets/SurfaceHighlightWidget.cpp b/src/Gui/Widgets/SurfaceHighlightWidget.cpp index eca6eaf..beddbb4 100644 --- a/src/Gui/Widgets/SurfaceHighlightWidget.cpp +++ b/src/Gui/Widgets/SurfaceHighlightWidget.cpp @@ -26,6 +26,8 @@ void SurfaceHighlightWidget::draw(){ line.draw(); }else if(_sm->getSelectedSurface()->getType() == SurfaceType::GRID_WARP_SURFACE){ _sm->getSelectedSurface()->getMesh().drawWireframe(); + }else if(_sm->getSelectedSurface()->getType() == SurfaceType::HEXAGON_SURFACE){ + _sm->getSelectedSurface()->getMesh().drawWireframe(); }else{ ofPolyline p; for(unsigned int i = 0; diff --git a/src/Gui/Widgets/TextureEditorWidget.cpp b/src/Gui/Widgets/TextureEditorWidget.cpp index 21b17c2..780b87c 100644 --- a/src/Gui/Widgets/TextureEditorWidget.cpp +++ b/src/Gui/Widgets/TextureEditorWidget.cpp @@ -137,6 +137,8 @@ void TextureEditorWidget::createJoints(){ tc = texCoords; }else if(surface->getType() == SurfaceType::QUAD_SURFACE){ tc = texCoords; + }else if(surface->getType() == SurfaceType::HEXAGON_SURFACE){ + tc = texCoords; }else if(surface->getType() == SurfaceType::GRID_WARP_SURFACE){ GridWarpSurface * s = (GridWarpSurface *)surface; diff --git a/src/Surfaces/HexagonSurface.cpp b/src/Surfaces/HexagonSurface.cpp new file mode 100644 index 0000000..b02123c --- /dev/null +++ b/src/Surfaces/HexagonSurface.cpp @@ -0,0 +1,252 @@ +#include "HexagonSurface.h" + +namespace ofx { +namespace piMapper { + +HexagonSurface::HexagonSurface(){ + setup(); +} + +void HexagonSurface::setup(){ + + // Create 6 + 1 points for the hexagon surface. + + vector verts; + verts.resize(7); + + // Start with the center. + verts[0] = ofVec2f((float)ofGetWidth() / 2.0f, (float)ofGetHeight() / 2.0f); + + // Then from top left clockwise. + verts[1] = ofVec2f((float)ofGetWidth() / 3.0f, 0); + verts[2] = ofVec2f((float)ofGetWidth() / 3.0f * 2.0f, 0); + verts[3] = ofVec2f(ofGetWidth(), (float)ofGetHeight() / 2.0f); + verts[4] = ofVec2f((float)ofGetWidth() / 3.0f * 2.0f, ofGetHeight()); + verts[5] = ofVec2f((float)ofGetWidth() / 3.0f, ofGetHeight()); + verts[6] = ofVec2f(0, (float)ofGetHeight() / 2.0f); + + // No create the texture coordinates. + vector coords; + coords.resize(7); + + // Start with center. + coords[0] = ofVec2f(0.5f, 0.5f); + + // Then from top left and go clockwise. + coords[1] = ofVec2f(1.0f / 3.0f, 0.0f); + coords[2] = ofVec2f(1.0f / 3.0f * 2.0f, 0.0f); + coords[3] = ofVec2f(1.0f, 0.5f); + coords[4] = ofVec2f(1.0f / 3.0f * 2.0f, 1.0f); + coords[5] = ofVec2f(1.0f / 3.0f, 1.0f); + coords[6] = ofVec2f(0.0f, 0.5f); + + // And finally setup + setup(verts, coords, source); +} + +void HexagonSurface::setup( + vector & verts, + vector & coords, + BaseSource * newSource){ + + // Assign texture + source = newSource; + + // Clear mesh + mesh.clear(); + + // Add vertices to the mesh + for(unsigned int i = 0; i < verts.size(); ++i){ + mesh.addVertex(verts[i]); + } + + // Form triangles + for(unsigned int i = 1; i < verts.size() - 1; ++i){ + unsigned int v1 = 0; // Center vertex always there + unsigned int v2 = i; + unsigned int v3 = i + 1; + mesh.addTriangle(v1, v2, v3); + + // Add the last triangle + if(i == verts.size() - 2){ + v1 = 0; + v2 = i + 1; + v3 = 1; + mesh.addTriangle(v1, v2, v3); + } + } + + // Add texture coords + for(unsigned int i = 0; i < coords.size(); ++i){ + mesh.addTexCoord(coords[i]); + } +} + +void HexagonSurface::draw(){ + if(source->getTexture() == 0){ + return; + } + + if(!source->getTexture()->isAllocated()){ + return; + } + + bool normalizedTexCoords = ofGetUsingNormalizedTexCoords(); + ofEnableNormalizedTexCoords(); + + source->getTexture()->bind(); + mesh.draw(); + source->getTexture()->unbind(); + + if(!normalizedTexCoords){ + ofDisableNormalizedTexCoords(); + } +} + +void HexagonSurface::setVertex(int index, ofVec2f p){ + if(index >= mesh.getVertices().size()){ + ofLog() << "Vertex with this index does not exist: " << index << endl; + return; + } + + mesh.setVertex(index, p); + ofVec3f v = mesh.getVertex(index); + ofNotifyEvent(vertexChangedEvent, index, this); +} + +void HexagonSurface::setVertices(vector v){ + if(v.size() != mesh.getVertices().size()){ + throw runtime_error("Wrong number of vertices"); + } + + for(int i = 0; i < v.size(); ++i){ + mesh.setVertex(i, v[i]); + } + + ofNotifyEvent(verticesChangedEvent, mesh.getVertices(), this); +} + +void HexagonSurface::setVertices(vector v){ + if(v.size() != mesh.getVertices().size()){ + throw runtime_error("Wrong number of vertices"); + } + + for(int i = 0; i < v.size(); ++i){ + mesh.setVertex(i, v[i]); + } + + ofNotifyEvent(verticesChangedEvent, mesh.getVertices(), this); +} + +void HexagonSurface::setTexCoord(int index, ofVec2f t){ + if(index >= mesh.getTexCoords().size()){ + ofLog() << "Texture coordinate with this index does not exist: " << index + << endl; + return; + } + + mesh.setTexCoord(index, t); +} + +void HexagonSurface::setTexCoords(vector t){ + if(t.size() != mesh.getTexCoords().size()){ + throw runtime_error("Wrong number of texture coordinates"); + } + for(int i = 0; i < t.size(); ++i){ + mesh.setTexCoord(i, t[i]); + } +} + +void HexagonSurface::moveBy(ofVec2f v){ + vector & vertices = getVertices(); + + for(int i = 0; i < vertices.size(); i++){ + vertices[i] += v; + } + + setMoved(true); + ofNotifyEvent(verticesChangedEvent, mesh.getVertices(), this); +} + +int HexagonSurface::getType(){ + return SurfaceType::HEXAGON_SURFACE; +} + +bool HexagonSurface::hitTest(ofVec2f p){ + // Construct ofPolyline from vertices + ofPolyline line = getHitArea(); + + if(line.inside(p.x, p.y)){ + return true; + }else{ + return false; + } +} + +ofVec2f HexagonSurface::getVertex(int index){ + if(index > 2){ + ofLog() << "Vertex with this index does not exist: " << index << endl; + throw runtime_error("Vertex index out of bounds."); + } + + ofVec3f vert = mesh.getVertex(index); + return ofVec2f(vert.x, vert.y); +} + +ofVec2f HexagonSurface::getTexCoord(int index){ + if(index > 2){ + throw runtime_error("Texture coordinate index out of bounds."); + } + + return mesh.getTexCoord(index); +} + +ofPolyline HexagonSurface::getHitArea(){ + ofPolyline line; + + for(unsigned int i = 1; i < mesh.getVertices().size(); ++i){ + line.addVertex(ofPoint(mesh.getVertex(i).x, mesh.getVertex(i).y)); + } + + line.close(); + + return line; +} + +ofPolyline HexagonSurface::getTextureHitArea(){ + ofPolyline line; + vector & texCoords = mesh.getTexCoords(); + ofVec2f textureSize = ofVec2f( + source->getTexture()->getWidth(), + source->getTexture()->getHeight()); + + for(int i = 1; i < texCoords.size(); i++){ + line.addVertex(ofPoint(texCoords[i] * textureSize)); + } + + line.close(); + + return line; +} + +vector & HexagonSurface::getVertices(){ + // return only joint vertices + return mesh.getVertices(); +} + +vector & HexagonSurface::getTexCoords(){ + return mesh.getTexCoords(); +} + +BaseSurface * HexagonSurface::clone(){ + HexagonSurface * s = new HexagonSurface(); + s->setVertices(getVertices()); + s->setTexCoords(getTexCoords()); + BaseSource * src = getSource(); + src->referenceCount++; + s->setSource(src); + return s; +} + +} // namespace piMapper +} // namespace ofx \ No newline at end of file diff --git a/src/Surfaces/HexagonSurface.h b/src/Surfaces/HexagonSurface.h new file mode 100644 index 0000000..a22896f --- /dev/null +++ b/src/Surfaces/HexagonSurface.h @@ -0,0 +1,45 @@ +#pragma once + +#include "ofMain.h" +#include "BaseSurface.h" +#include "SurfaceType.h" + +namespace ofx { +namespace piMapper { + +// TODO: Transform this into CircleSurface. + +class HexagonSurface : public BaseSurface { + public: + HexagonSurface(); + + void setup(); + void setup( + vector & verts, + vector & coords, + BaseSource * newSource); + void draw(); + + void setVertex(int index, ofVec2f p); + void setVertices(vector v); + void setVertices(vector v); + + void setTexCoord(int index, ofVec2f t); + void setTexCoords(vector t); + + void moveBy(ofVec2f v); + + int getType(); + bool hitTest(ofVec2f p); + ofVec2f getVertex(int index); + ofVec2f getTexCoord(int index); + ofPolyline getHitArea(); + ofPolyline getTextureHitArea(); + vector & getVertices(); + vector & getTexCoords(); + + BaseSurface * clone(); +}; + +} // namespace piMapper +} // namespace ofx \ No newline at end of file diff --git a/src/Surfaces/SurfaceFactory.cpp b/src/Surfaces/SurfaceFactory.cpp index 19bf379..295c43a 100644 --- a/src/Surfaces/SurfaceFactory.cpp +++ b/src/Surfaces/SurfaceFactory.cpp @@ -19,6 +19,8 @@ BaseSurface * SurfaceFactory::createSurface(int type){ return createQuadSurface(); }else if(type == SurfaceType::GRID_WARP_SURFACE){ return createGridWarpSurface(); + }else if(type == SurfaceType::HEXAGON_SURFACE){ + return createHexagonSurface(); }else{ throw runtime_error("Undefined surface type"); } @@ -76,5 +78,10 @@ GridWarpSurface * SurfaceFactory::createGridWarpSurface(){ return gridWarpSurface; } +HexagonSurface * SurfaceFactory::createHexagonSurface(){ + HexagonSurface * hexagonSurface = new HexagonSurface(); + return hexagonSurface; +} + } // namespace piMapper } // namespace ofx diff --git a/src/Surfaces/SurfaceFactory.h b/src/Surfaces/SurfaceFactory.h index b3ca976..9b49e4f 100644 --- a/src/Surfaces/SurfaceFactory.h +++ b/src/Surfaces/SurfaceFactory.h @@ -6,6 +6,7 @@ #include "TriangleSurface.h" #include "QuadSurface.h" #include "GridWarpSurface.h" +#include "HexagonSurface.h" namespace ofx { namespace piMapper { @@ -24,6 +25,7 @@ class SurfaceFactory { TriangleSurface * createTriangleSurface(); QuadSurface * createQuadSurface(); GridWarpSurface * createGridWarpSurface(); + HexagonSurface * createHexagonSurface(); }; } // namespace piMapper diff --git a/src/Surfaces/SurfaceType.h b/src/Surfaces/SurfaceType.h index 3ee1301..3017629 100644 --- a/src/Surfaces/SurfaceType.h +++ b/src/Surfaces/SurfaceType.h @@ -5,7 +5,10 @@ namespace piMapper { struct SurfaceType { enum { - TRIANGLE_SURFACE, QUAD_SURFACE, GRID_WARP_SURFACE + TRIANGLE_SURFACE, + QUAD_SURFACE, + GRID_WARP_SURFACE, + HEXAGON_SURFACE }; };