Browse Source

CircleSurface + changes in various files to support the new surface

master
c-mendoza 8 years ago
parent
commit
e98cae857d
  1. 85
      src/Application/SettingsLoader.cpp
  2. 3
      src/Gui/Widgets/TextureEditorWidget.cpp
  3. 299
      src/Surfaces/CircleSurface.cpp
  4. 63
      src/Surfaces/CircleSurface.h
  5. 7
      src/Surfaces/SurfaceFactory.cpp
  6. 2
      src/Surfaces/SurfaceFactory.h
  7. 3
      src/Surfaces/SurfaceType.h

85
src/Application/SettingsLoader.cpp

@ -20,46 +20,46 @@ bool SettingsLoader::load(
SurfaceManager & surfaceManager,
MediaServer & mediaServer,
string fileName){
ofxXmlSettings * xmlSettings = new ofxXmlSettings();
string sourceType = "";
string sourceName = "";
BaseSource * source = 0;
if(!xmlSettings->loadFile(fileName)){
ofLogWarning("SettingsLoader::load()") << "Could not load XML settings";
return false;
}
if(!xmlSettings->tagExists("surfaces")){
xmlSettings->addTag("surfaces");
}
// Count <surfaces> tags.
unsigned int numPresets = xmlSettings->getNumTags("surfaces");
cout << "numPresets: " << numPresets << endl;
// Clear previous presets and surfaces first.
surfaceManager.clearPresets();
// Loop through <surfaces> tags in the XML.
for(unsigned int i = 0; i < numPresets; ++i){
xmlSettings->pushTag("surfaces", i);
SurfaceStack * surfaces = surfaceManager.createPreset();
int numSurfaces = xmlSettings->getNumTags("surface");
for(int i = 0; i < numSurfaces; i++){
if(xmlSettings->tagExists("surface", i)){
SurfaceType type = SurfaceType::NONE;
if(xmlSettings->attributeExists("surface", "type")){
type = static_cast<SurfaceType>(
xmlSettings->getAttribute("surface", "type", 0, i));
}
xmlSettings->pushTag("surface", i);
// attempt to load surface source
@ -122,6 +122,13 @@ bool SettingsLoader::load(
quadSurface->setSource(source);
}
surfaces->push_back(quadSurface);
}else if(type == SurfaceType::CIRCLE_SURFACE){
QuadSurface * base = (QuadSurface*)getQuadSurface(xmlSettings);
CircleSurface * circleSurface = new CircleSurface(*base);
if(sourceName != "none" && source != 0){
circleSurface->setSource(source);
}
surfaces->push_back(circleSurface);
}else if(type == SurfaceType::GRID_WARP_SURFACE){
BaseSurface * gridWarpSurface = getGridWarpSurface(xmlSettings);
if(sourceName != "none" && source != 0){
@ -227,13 +234,13 @@ bool SettingsLoader::save(SurfaceManager & surfaceManager, string fileName){
xmlSettings->addValue("gridRows", gws->getGridRows());
xmlSettings->popTag();
}
xmlSettings->popTag(); // surface
}
xmlSettings->popTag(); // surfaces
} // for
xmlSettings->save(fileName);
}
@ -245,17 +252,17 @@ bool SettingsLoader::create(string fileName){
BaseSurface * SettingsLoader::getTriangleSurface(ofxXmlSettings * xmlSettings){
vector <ofVec2f> vertices;
if(xmlSettings->tagExists("vertices")){
xmlSettings->pushTag("vertices");
if(xmlSettings->tagExists("vertex", 0)){
xmlSettings->pushTag("vertex", 0);
vertices.push_back(ofVec2f(xmlSettings->getValue("x", 0.0f),
xmlSettings->getValue("y", 0.0f)));
xmlSettings->popTag();
}
if(xmlSettings->tagExists("vertex", 1)){
xmlSettings->pushTag("vertex", 1);
vertices.push_back(ofVec2f(xmlSettings->getValue("x", 100.0f),
@ -277,14 +284,14 @@ BaseSurface * SettingsLoader::getTriangleSurface(ofxXmlSettings * xmlSettings){
if(xmlSettings->tagExists("texCoords")){
xmlSettings->pushTag("texCoords");
if(xmlSettings->tagExists("texCoord", 0)){
xmlSettings->pushTag("texCoord", 0);
texCoords.push_back(ofVec2f(xmlSettings->getValue("x", 0.0f),
xmlSettings->getValue("y", 0.0f)));
xmlSettings->popTag();
}
if(xmlSettings->tagExists("texCoord", 1)){
xmlSettings->pushTag("texCoord", 1);
texCoords.push_back(ofVec2f(xmlSettings->getValue("x", 1.0f),
@ -308,16 +315,16 @@ BaseSurface * SettingsLoader::getTriangleSurface(ofxXmlSettings * xmlSettings){
SurfaceType::TRIANGLE_SURFACE);
triangleSurface->setVertices(vertices);
triangleSurface->setTexCoords(texCoords);
return triangleSurface;
}
BaseSurface * SettingsLoader::getQuadSurface(ofxXmlSettings * xmlSettings){
vector <ofVec2f> vertices;
if(xmlSettings->tagExists("vertices")){
xmlSettings->pushTag("vertices");
if(xmlSettings->tagExists("vertex", 0)){
xmlSettings->pushTag("vertex", 0);
vertices.push_back(ofVec2f(xmlSettings->getValue("x", 0.0f),
@ -348,7 +355,7 @@ BaseSurface * SettingsLoader::getQuadSurface(ofxXmlSettings * xmlSettings){
xmlSettings->popTag(); // vertices
}
vector <ofVec2f> texCoords;
if(xmlSettings->tagExists("texCoords")){
@ -360,7 +367,7 @@ BaseSurface * SettingsLoader::getQuadSurface(ofxXmlSettings * xmlSettings){
xmlSettings->getValue("y", 0.0f)));
xmlSettings->popTag();
}
if(xmlSettings->tagExists("texCoord", 1)){
xmlSettings->pushTag("texCoord", 1);
texCoords.push_back(ofVec2f(xmlSettings->getValue("x", 1.0f),
@ -384,14 +391,14 @@ BaseSurface * SettingsLoader::getQuadSurface(ofxXmlSettings * xmlSettings){
xmlSettings->popTag(); // texCoords
}
// Create and add quad surface
BaseSurface * quadSurface =
SurfaceFactory::instance()->createSurface(
SurfaceType::QUAD_SURFACE);
quadSurface->setVertices(vertices);
quadSurface->setTexCoords(texCoords);
// Read properties
// Only perspective warping for now
bool perspectiveWarping = false;
@ -402,18 +409,18 @@ BaseSurface * SettingsLoader::getQuadSurface(ofxXmlSettings * xmlSettings){
}
QuadSurface * qs = (QuadSurface *)quadSurface;
qs->setPerspectiveWarping(perspectiveWarping);
return quadSurface;
}
BaseSurface * SettingsLoader::getGridWarpSurface(ofxXmlSettings * xmlSettings){
vector <ofVec2f> vertices;
if(xmlSettings->tagExists("vertices")){
xmlSettings->pushTag("vertices");
int iv = 0;
while(xmlSettings->tagExists("vertex", iv)){
xmlSettings->pushTag("vertex", iv);
vertices.push_back(ofVec2f(xmlSettings->getValue("x", 0.0f),
@ -424,14 +431,14 @@ BaseSurface * SettingsLoader::getGridWarpSurface(ofxXmlSettings * xmlSettings){
xmlSettings->popTag(); // vertices
}
vector <ofVec2f> texCoords;
if(xmlSettings->tagExists("texCoords")){
xmlSettings->pushTag("texCoords");
int it = 0;
while(xmlSettings->tagExists("texCoord", it)){
xmlSettings->pushTag("texCoord", it);
texCoords.push_back(ofVec2f(xmlSettings->getValue("x", 0.0f),
@ -442,7 +449,7 @@ BaseSurface * SettingsLoader::getGridWarpSurface(ofxXmlSettings * xmlSettings){
xmlSettings->popTag(); // texCoords
}
// Read properties
// Only perspective warping for now
int gridCols = 0;
@ -453,7 +460,7 @@ BaseSurface * SettingsLoader::getGridWarpSurface(ofxXmlSettings * xmlSettings){
gridRows = xmlSettings->getValue("gridRows", 0);
xmlSettings->popTag(); // properties
}
// Create and add quad surface
BaseSurface * gridWarpSurface =
SurfaceFactory::instance()->createSurface(
@ -463,16 +470,16 @@ BaseSurface * SettingsLoader::getGridWarpSurface(ofxXmlSettings * xmlSettings){
((GridWarpSurface *)gridWarpSurface)->createGridMesh();
gridWarpSurface->setVertices(vertices);
gridWarpSurface->setTexCoords(texCoords);
return gridWarpSurface;
}
BaseSurface * SettingsLoader::getHexagonSurface(ofxXmlSettings * xmlSettings){
vector <ofVec2f> vertices;
if(xmlSettings->tagExists("vertices")){
xmlSettings->pushTag("vertices");
unsigned int v = 0;
while(xmlSettings->tagExists("vertex", v)){
xmlSettings->pushTag("vertex", v);
@ -489,7 +496,7 @@ BaseSurface * SettingsLoader::getHexagonSurface(ofxXmlSettings * xmlSettings){
if(xmlSettings->tagExists("texCoords")){
xmlSettings->pushTag("texCoords");
unsigned int t = 0;
while(xmlSettings->tagExists("texCoord", t)){
xmlSettings->pushTag("texCoord", t);
@ -508,7 +515,7 @@ BaseSurface * SettingsLoader::getHexagonSurface(ofxXmlSettings * xmlSettings){
SurfaceType::HEXAGON_SURFACE);
hexagonSurface->setVertices(vertices);
hexagonSurface->setTexCoords(texCoords);
return hexagonSurface;
}

3
src/Gui/Widgets/TextureEditorWidget.cpp

@ -149,7 +149,8 @@ void TextureEditorWidget::createJoints(){
if(surface->getType() == SurfaceType::TRIANGLE_SURFACE){
tc = texCoords;
}else if(surface->getType() == SurfaceType::QUAD_SURFACE){
}else if(surface->getType() == SurfaceType::QUAD_SURFACE ||
surface->getType() == SurfaceType::CIRCLE_SURFACE){
tc = texCoords;
}else if(surface->getType() == SurfaceType::HEXAGON_SURFACE){
tc = texCoords;

299
src/Surfaces/CircleSurface.cpp

@ -0,0 +1,299 @@
//
// CircleSurface.cpp
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
#include "CircleSurface.h"
namespace ofx {
namespace piMapper {
CircleSurface::CircleSurface() : QuadSurface() {
setup();
}
CircleSurface::CircleSurface(QuadSurface &surface) {
setup();
setVertices(surface.getVertices());
setTexCoords(surface.getTexCoords());
setPerspectiveWarping(surface.getPerspectiveWarping());
}
CircleSurface::~CircleSurface() {}
void CircleSurface::setup() {
setPerspectiveWarping(true);
QuadSurface::setup();
updateMask = true;
// maskIsReady = false;
glESVertexShader = STRINGIFY(
attribute vec4 position;
attribute vec4 color;
attribute vec4 normal;
attribute vec2 texcoord;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform sampler2D maskTex;
varying vec4 colorVarying;
varying vec2 texCoordVarying;
void main() {
//get our current vertex position so we can modify it
vec4 pos = projectionMatrix*modelViewMatrix*position;
gl_Position = pos;
colorVarying = color;
texCoordVarying = texcoord;
}
);
glESFragmentShader = STRINGIFY(
//#ifdef GL_ES
// define default precision for float, vec, mat.
precision highp float;
//#endif
uniform sampler2D tex0;
uniform sampler2D maskTex;
uniform vec4 globalColor;
varying vec2 texCoordVarying;
void main (void)
{
vec2 pos = texCoordVarying;
vec3 src = texture2D(tex0, pos).rgb;
float mask = texture2D(maskTex, pos).r;
gl_FragColor = vec4( src , mask);
}
);
gl2FragmentShader = "#version 120\n #extension GL_ARB_texture_rectangle : enable\n";
gl2FragmentShader += STRINGIFY(
uniform sampler2DRect tex0;
uniform sampler2DRect maskTex;
void main (void) {
vec2 pos = gl_TexCoord[0].st;
vec3 src = texture2DRect(tex0, pos).rgb;
float mask = texture2DRect(maskTex, pos).r;
gl_FragColor = vec4(src, mask);
}
);
#ifdef TARGET_OPENGLES
maskShader.setupShaderFromSource(GL_VERTEX_SHADER, glESVertexShader);
maskShader.setupShaderFromSource(GL_FRAGMENT_SHADER, glESFragmentShader);
maskShader.bindDefaults();
maskShader.linkProgram();
#else
if (ofIsGLProgrammableRenderer()) {
} else {
maskShader.setupShaderFromSource(GL_FRAGMENT_SHADER, gl2FragmentShader);
maskShader.linkProgram();
}
#endif
ofVec2f t1 = ofVec2f(ofVec2f(0.0f, 0.0f));
ofVec2f t2 = ofVec2f(ofVec2f(1.0f, 0.0f));
ofVec2f t3 = ofVec2f(ofVec2f(1.0f, 1.0f));
ofVec2f t4 = ofVec2f(ofVec2f(0.0f, 1.0f));
defaultTexCoords.push_back(t1);
defaultTexCoords.push_back(t2);
defaultTexCoords.push_back(t3);
defaultTexCoords.push_back(t4);
}
void CircleSurface::draw() {
ofEnableAlphaBlending();
if (source->getTexture() == 0)
{
return;
}
if (!source->getTexture()->isAllocated()){
return;
}
if (source != currentSource) { // Pointer comparison
// Create the mask here
setupTextures();
currentSource = source;
}
// Save Normie state:
auto isNorm = ofGetUsingNormalizedTexCoords();
// If we get to this part of the function, the mask fbo
// should already be allocated and the mask texture created.
ofEnableNormalizedTexCoords();
// Get the texture from the source an store a copy
// of the source texture's id:
auto sourceTex = ofTexture(*(source->getTexture()));
auto sourceTexId = sourceTex.getTextureData().textureID;
// Get the quad surface's mesh texture coordinates:
auto quadTexCoords = getMesh().getTexCoords();
maskMesh.clearTexCoords();
// Set the mesh's texture coords to the quads.
// This gets us the coordinates set in the TextureEditor
maskMesh.addTexCoords(quadTexCoords);
float w = outputFbo.getWidth();
float h = outputFbo.getHeight();
// Draw the scaled texture into an FBO
scaledSourceFbo.begin(true);
{
ofClear(0, 0, 0, 255);
ofSetupScreenOrtho(w, h, -1, 1);
ofEnableNormalizedTexCoords();
ofFill();
ofSetColor(255);
sourceTex.bind();
maskMesh.draw();
sourceTex.unbind();
}
scaledSourceFbo.end();
// Now draw the texture, masked, into the outputFbo.
// This enables us to use the TextureEditor to determine
// what part of the source will be masked:
maskMesh.clearTexCoords();
// Set default normalized texCoords
maskMesh.addTexCoords(defaultTexCoords);
outputFbo.begin(true);
{
ofClear(0, 0, 0, 0);
ofSetupScreenOrtho(w, h, -1, 1);
ofEnableNormalizedTexCoords();
maskShader.begin();
maskShader.setUniformTexture("maskTex", maskFbo.getTexture(), 1);
ofSetColor(255);
ofFill();
ofSetRectMode(OF_RECTMODE_CORNER);
scaledSourceFbo.getTexture().bind();
maskMesh.draw();
scaledSourceFbo.getTexture().unbind();
maskShader.end();
}
outputFbo.end();
getMesh().clearTexCoords();
getMesh().addTexCoords(defaultTexCoords);
// Swap the texture id of the source with the one of our
// newly drawn outputFbo:
source->getTexture()->getTextureData().textureID = outputFbo.getTexture().getTextureData().textureID;
// Draw the Quad:
QuadSurface::draw();
// Reset the texture id of the source
source->getTexture()->getTextureData().textureID = sourceTexId;
// Reset the texture coords of the QuadSurface mesh:
getMesh().clearTexCoords();
getMesh().addTexCoords(quadTexCoords);
if (!isNorm) ofDisableNormalizedTexCoords();
}
void CircleSurface::setFeathering(float f) {
feathering = f;
updateMask = true;
}
void CircleSurface::setupTextures() {
float w = source->getTexture()->getWidth();
float h = source->getTexture()->getHeight();
float dia = 0;
if (w > h) {
dia = h;
} else {
dia = w;
}
float padding = 10;
maskFbo.allocate(w, h);
maskFbo.begin(false);
ofPushStyle();
ofSetupScreenOrtho(w, h, -1, 1);
ofClear(0, 0, 0, 255);
ofFill();
ofSetColor(255);
ofSetCircleResolution(300);
ofDrawEllipse(w/2, h/2, w-padding, h-padding);
ofPopStyle();
maskFbo.end();
outputFbo.allocate(w, h);
outputFbo.begin();
ofClear(0, 0, 0, 255);
outputFbo.end();
scaledSourceFbo.allocate(w, h);
scaledSourceFbo.begin();
ofClear(0, 0, 0, 255);
scaledSourceFbo.end();
// This is lifted from QuadSurface::setup to ensure that the two
// meshes are similar:
// Create 4 points for the 2 triangles
ofVec2f p1 = ofVec2f(0, 0);
ofVec2f p2 = ofVec2f(0, h);
ofVec2f p3 = ofVec2f(w, h);
ofVec2f p4 = ofVec2f(w, 0);
// Create 4 point for the texture coordinates
ofVec2f t1 = ofVec2f(ofVec2f(0.0f, 0.0f));
ofVec2f t2 = ofVec2f(ofVec2f(1.0f, 0.0f));
ofVec2f t3 = ofVec2f(ofVec2f(1.0f, 1.0f));
ofVec2f t4 = ofVec2f(ofVec2f(0.0f, 1.0f));
// Clear maskMesh
maskMesh.clear();
// Create a surface with the points
maskMesh.addVertex(p1);
maskMesh.addVertex(p2);
maskMesh.addVertex(p3);
maskMesh.addVertex(p4);
// Add 2 triangles
maskMesh.addTriangle(0, 2, 3);
maskMesh.addTriangle(0, 1, 2);
// Add texture coordinates
maskMesh.addTexCoord(t1);
maskMesh.addTexCoord(t2);
maskMesh.addTexCoord(t3);
maskMesh.addTexCoord(t4);
}
int CircleSurface::getType() {
return SurfaceType::CIRCLE_SURFACE;
}
}
}

63
src/Surfaces/CircleSurface.h

@ -0,0 +1,63 @@
//
// CircleSurface.h
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
#ifndef OFXPIMAPPER_CIRCLESURFACE_H
#define OFXPIMAPPER_CIRCLESURFACE_H
#include "QuadSurface.h"
#define STRINGIFY(A) #A
namespace ofx {
namespace piMapper {
class CircleSurface : public QuadSurface {
public:
CircleSurface();
CircleSurface(QuadSurface &surface);
int getType() override;
~CircleSurface();
void draw() override;
void setup() override;
// TODO: Feathering
void setFeathering(float f);
protected:
void setupTextures();
ofFbo maskFbo;
ofFbo scaledSourceFbo;
ofFbo outputFbo;
ofShader maskShader;
ofShader gradientShader;
float feathering = 0.0f;
bool updateMask;
bool maskIsReady;
string glESFragmentShader;
string glESVertexShader;
string gl2FragmentShader;
string gl2VertexShader;
ofMesh maskMesh;
// TODO: gl3 Shaders
// string gl3VertexShader;
// string gl3FragmentShader;
private:
std::vector<ofVec2f> defaultTexCoords;
// We will use this pointer to determine if the source has changed.
// This is a total kludge, but it keeps me from messing with the
// upstream source.
BaseSource* currentSource = 0;
};
}
}
#endif //OFXPIMAPPER_CIRCLESURFACE_H

7
src/Surfaces/SurfaceFactory.cpp

@ -21,6 +21,8 @@ BaseSurface * SurfaceFactory::createSurface(SurfaceType type){
return createGridWarpSurface();
}else if(type == SurfaceType::HEXAGON_SURFACE){
return createHexagonSurface();
}else if(type == SurfaceType::CIRCLE_SURFACE){
return createCircleSurface();
}else{
throw runtime_error("Undefined surface type");
}
@ -83,5 +85,10 @@ HexagonSurface * SurfaceFactory::createHexagonSurface(){
return hexagonSurface;
}
CircleSurface * SurfaceFactory::createCircleSurface() {
CircleSurface * circleSurface = new CircleSurface();
return circleSurface;
}
} // namespace piMapper
} // namespace ofx

2
src/Surfaces/SurfaceFactory.h

@ -7,6 +7,7 @@
#include "QuadSurface.h"
#include "GridWarpSurface.h"
#include "HexagonSurface.h"
#include "CircleSurface.h"
namespace ofx {
namespace piMapper {
@ -26,6 +27,7 @@ class SurfaceFactory {
QuadSurface * createQuadSurface();
GridWarpSurface * createGridWarpSurface();
HexagonSurface * createHexagonSurface();
CircleSurface* createCircleSurface();
};
} // namespace piMapper

3
src/Surfaces/SurfaceType.h

@ -8,7 +8,8 @@ enum SurfaceType{
QUAD_SURFACE,
GRID_WARP_SURFACE,
HEXAGON_SURFACE,
NONE
NONE,
CIRCLE_SURFACE
};
} // namespace piMapper

Loading…
Cancel
Save