├── example ├── addons.make ├── bin │ └── data │ │ └── of.png ├── src │ ├── main.cpp │ ├── ofApp.h │ └── ofApp.cpp ├── Makefile ├── Project.xcconfig ├── openFrameworks-Info.plist ├── example.xcodeproj │ ├── xcshareddata │ │ └── xcschemes │ │ │ ├── example Debug.xcscheme │ │ │ └── example Release.xcscheme │ └── project.pbxproj └── config.make ├── .github └── FUNDING.yml ├── ofxaddons_thumbnail.png ├── .gitattributes ├── src ├── utils │ ├── ofxMeshWarpManagedController.h │ └── ofxMeshWarpManagedController.cpp ├── ofxMeshWarpIO.h ├── ofxMeshWarpIO.cpp ├── ofxMeshWarp.h ├── ofxMeshWarpController.h ├── ofxMeshWarp.cpp └── ofxMeshWarpController.cpp ├── readme.md └── .gitignore /example/addons.make: -------------------------------------------------------------------------------- 1 | ofxMeshWarp 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: nariakiiwatani 4 | -------------------------------------------------------------------------------- /example/bin/data/of.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nariakiiwatani/ofxMeshWarp/HEAD/example/bin/data/of.png -------------------------------------------------------------------------------- /ofxaddons_thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nariakiiwatani/ofxMeshWarp/HEAD/ofxaddons_thumbnail.png -------------------------------------------------------------------------------- /example/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofApp.h" 3 | 4 | //======================================================================== 5 | int main( ){ 6 | ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context 7 | 8 | // this kicks off the running of my app 9 | // can be OF_WINDOW or OF_FULLSCREEN 10 | // pass in width and height too: 11 | ofRunApp(new ofApp()); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /example/Makefile: -------------------------------------------------------------------------------- 1 | # Attempt to load a config.make file. 2 | # If none is found, project defaults in config.project.make will be used. 3 | ifneq ($(wildcard config.make),) 4 | include config.make 5 | endif 6 | 7 | # make sure the the OF_ROOT location is defined 8 | ifndef OF_ROOT 9 | OF_ROOT=$(realpath ../../..) 10 | endif 11 | 12 | # call the project makefile! 13 | include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # This is based on the Github .gitattributes templates 2 | # Set default behaviour, in case users don't have core.autocrlf set. 3 | * text=auto 4 | 5 | # Explicitly declare text files we want to always be normalized and converted 6 | # to native line endings on checkout. 7 | *.cpp text 8 | *.h text 9 | *.mm text 10 | 11 | # Declare files that will always have CRLF line endings on checkout. 12 | *.sln text eol=crlf 13 | *.vcxproj* text eol=crlf 14 | 15 | # Denote all files that are truly binary and should not be modified. 16 | *.png binary 17 | *.jpg binary 18 | 19 | # Exclude .patch files in apothecary from EOL normalization 20 | scripts/apothecary/**/*.patch -text 21 | 22 | -------------------------------------------------------------------------------- /example/Project.xcconfig: -------------------------------------------------------------------------------- 1 | //THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. 2 | //THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED 3 | OF_PATH = ../../.. 4 | 5 | //THIS HAS ALL THE HEADER AND LIBS FOR OF CORE 6 | #include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" 7 | 8 | //ICONS - NEW IN 0072 9 | ICON_NAME_DEBUG = icon-debug.icns 10 | ICON_NAME_RELEASE = icon.icns 11 | ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ 12 | 13 | //IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: 14 | //ICON_FILE_PATH = bin/data/ 15 | 16 | OTHER_CFLAGS = $(OF_CORE_CFLAGS) 17 | OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) 18 | HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) 19 | -------------------------------------------------------------------------------- /example/openFrameworks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | ${ICON} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | APPL 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | 22 | 23 | -------------------------------------------------------------------------------- /example/src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "ofxMeshWarp.h" 5 | #include "ofxMeshWarpManagedController.h" 6 | 7 | class ofApp : public ofBaseApp{ 8 | 9 | public: 10 | void setup(); 11 | void update(); 12 | void draw(); 13 | 14 | void keyPressed(int key); 15 | void keyReleased(int key); 16 | void mouseMoved(int x, int y ); 17 | void mouseDragged(int x, int y, int button); 18 | void mousePressed(int x, int y, int button); 19 | void mouseReleased(int x, int y, int button); 20 | void mouseEntered(int x, int y); 21 | void mouseExited(int x, int y); 22 | void windowResized(int w, int h); 23 | void dragEvent(ofDragInfo dragInfo); 24 | void gotMessage(ofMessage msg); 25 | private: 26 | std::shared_ptr mesh_; 27 | ofxMeshWarpController controller_; 28 | ofTexture tex_; 29 | }; 30 | -------------------------------------------------------------------------------- /src/utils/ofxMeshWarpManagedController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofxMeshWarpController.h" 4 | #include "ofEvents.h" 5 | 6 | namespace ofx{namespace MeshWarp{ 7 | namespace Editor { 8 | class ManagedController : public ControllerBase { 9 | public: 10 | void add(std::shared_ptr target); 11 | void clear(); 12 | void clearOperation(); 13 | 14 | void setUVResolution(const glm::vec2 &res) { mover_.setUVResolution(res); } 15 | 16 | void setAnchorPoint(float x, float y); 17 | void setTranslation(float x, float y); 18 | void setScale(float s); 19 | 20 | void drawCustom() const; 21 | 22 | void mousePressed(ofMouseEventArgs &args); 23 | void mouseReleased(ofMouseEventArgs &args); 24 | void mouseMoved(ofMouseEventArgs &args); 25 | void mouseDragged(ofMouseEventArgs &args); 26 | void mouseScrolled(ofMouseEventArgs &args); 27 | void mouseEntered(ofMouseEventArgs &args); 28 | void mouseExited(ofMouseEventArgs &args); 29 | void keyPressed(ofKeyEventArgs &args); 30 | void keyReleased(ofKeyEventArgs &args); 31 | private: 32 | bool is_mover_active_ = false; 33 | bool is_divider_active_ = false; 34 | PointController mover_; 35 | DivideController divider_; 36 | std::vector controllers_{&mover_,÷r_}; 37 | void activateMover(); 38 | void activateDivider(); 39 | }; 40 | } 41 | }} 42 | using ofxMeshWarpController = ofx::MeshWarp::Editor::ManagedController; 43 | -------------------------------------------------------------------------------- /src/ofxMeshWarpIO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofxMeshWarp.h" 4 | #include "ofFileUtils.h" 5 | 6 | namespace ofx{namespace MeshWarp{ 7 | namespace IO { 8 | class PointHelper { 9 | public: 10 | PointHelper(MeshPoint *p):target_(p){} 11 | void get(ofBuffer &buffer) const; 12 | int set(const char *buffer); 13 | private: 14 | MeshPoint *target_; 15 | struct PointData { 16 | glm::vec3 point; 17 | glm::vec2 coord; 18 | glm::vec3 normal; 19 | ofFloatColor color; 20 | bool is_node; 21 | }; 22 | }; 23 | class MeshHelper { 24 | public: 25 | MeshHelper(Mesh *m):target_(m){} 26 | void get(ofBuffer &buffer) const; 27 | int set(const char *buffer); 28 | private: 29 | Mesh *target_; 30 | struct MeshData { 31 | int divx, divy, resolution; 32 | ofVec4f uv_rect; 33 | }; 34 | }; 35 | class Saver { 36 | public: 37 | void addMesh(std::shared_ptr mesh); 38 | void addMeshes(std::vector> mesh); 39 | void save(const std::string &filename) const; 40 | void save(ofBuffer &buffer) const; 41 | private: 42 | std::vector> meshes_; 43 | }; 44 | class Loader { 45 | public: 46 | std::vector> load(const std::string &filename) const; 47 | std::vector> load(const ofBuffer &buffer) const; 48 | std::vector> load(const char *data, std::size_t size) const; 49 | }; 50 | } 51 | 52 | }} 53 | using ofxMeshWarpSave = ofx::MeshWarp::IO::Saver; 54 | using ofxMeshWarpLoad = ofx::MeshWarp::IO::Loader; 55 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ofxMeshWarp 2 | Warping mesh points with mouse and keyboard. 3 | You can do it by code, of course. 4 | 5 | ## How to use 6 | ### code 7 | See example 8 | 9 | ### selecting points 10 | You can select/deselect point(s) by clicking on the point or making rectangle including the points. 11 | With shift key pressed, additive. 12 | With command key pressed, alternative. 13 | 14 | ### moving points 15 | You can move points' position by dragging on a selected point. 16 | With option key pressed, texcoord will be moved instead. 17 | With shift key pressed, points move according axis. 18 | You can also move by arrow keys. 19 | 20 | ### editing alpha 21 | You can edit points' alpha by scrolling Y-axis. 22 | 23 | ### switching nodal or not 24 | Each point has a property of nodal or not. 25 | By clicking on a point with option key pressed, you can switch it. 26 | If a point is nodal, you can control its position or texcoord directly. 27 | If a point is not nodal, you cannot but it will be controled by mood. 28 | 29 | ### dividing or reducing mesh points 30 | Click on a line to divide mesh. 31 | With option key pressed, reduce. 32 | 33 | _**warning** 34 | Dividing mesh allocates memory for new points but reducing doesn't free them. 35 | So if you call divide/reduce many times, you may need to call `ofxMeshWarp::gc()` on reasonable time._ 36 | 37 | 38 | ## Other Features 39 | ### Save/Load 40 | See example 41 | 42 | ## Tested on 43 | - Mac OSX 10.13.6 44 | - oF 0.10.0 45 | - Xcode 9.4.1 46 | 47 | ## License 48 | MIT license. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # general 3 | ######################### 4 | 5 | [Bb]uild/ 6 | [Oo]bj/ 7 | *.o 8 | examples/**/[Dd]ebug*/ 9 | examples/**/[Rr]elease*/ 10 | examples/**/gcc-debug/ 11 | examples/**/gcc-release/ 12 | tests/**/[Dd]ebug*/ 13 | tests/**/[Rr]elease*/ 14 | tests/**/gcc-debug/ 15 | tests/**/gcc-release/ 16 | *.mode* 17 | *.app/ 18 | *.pyc 19 | .svn/ 20 | *.log 21 | *.cpp.eep 22 | *.cpp.elf 23 | *.cpp.hex 24 | 25 | ######################### 26 | # IDE 27 | ######################### 28 | 29 | # XCode 30 | *.pbxuser 31 | *.perspective 32 | *.perspectivev3 33 | *.mode1v3 34 | *.mode2v3 35 | # XCode 4 36 | xcuserdata 37 | *.xcworkspace 38 | 39 | # Code::Blocks 40 | *.depend 41 | *.layout 42 | 43 | # Visual Studio 44 | *.sdf 45 | *.opensdf 46 | *.suo 47 | *.pdb 48 | *.ilk 49 | *.aps 50 | ipch/ 51 | 52 | # Eclipse 53 | .metadata 54 | local.properties 55 | .externalToolBuilders 56 | 57 | # Android Studio 58 | .idea 59 | .gradle 60 | gradle 61 | gradlew 62 | gradlew.bat 63 | 64 | # QtCreator 65 | *.qbs.user 66 | *.pro.user 67 | *.pri 68 | 69 | 70 | ######################### 71 | # operating system 72 | ######################### 73 | 74 | # Linux 75 | *~ 76 | # KDE 77 | .directory 78 | .AppleDouble 79 | 80 | # OSX 81 | .DS_Store 82 | *.swp 83 | *~.nib 84 | # Thumbnails 85 | ._* 86 | 87 | # Windows 88 | # Windows image file caches 89 | Thumbs.db 90 | # Folder config file 91 | Desktop.ini 92 | 93 | # Android 94 | .csettings 95 | /libs/openFrameworksCompiled/project/android/paths.make 96 | 97 | # Android Studio 98 | *.iml 99 | 100 | ######################### 101 | # miscellaneous 102 | ######################### 103 | 104 | .mailmap 105 | -------------------------------------------------------------------------------- /example/src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | #include "ofxMeshWarpIO.h" 3 | using namespace std; 4 | 5 | //-------------------------------------------------------------- 6 | void ofApp::setup(){ 7 | ofLoadImage(tex_, "of.png"); 8 | mesh_ = make_shared(); 9 | mesh_->setup(4,4,512,512); 10 | mesh_->setUVRect(ofRectangle(0, 0, tex_.getWidth(), tex_.getHeight())); 11 | controller_.add(mesh_); 12 | controller_.enable(); 13 | } 14 | 15 | //-------------------------------------------------------------- 16 | void ofApp::update(){ 17 | ofSetWindowTitle(ofToString(ofGetFrameRate(),2)); 18 | mesh_->update(); 19 | } 20 | 21 | //-------------------------------------------------------------- 22 | void ofApp::draw(){ 23 | tex_.bind(); 24 | // mesh_->drawMesh(); 25 | controller_.drawFace(); 26 | tex_.unbind(); 27 | controller_.draw(); 28 | } 29 | 30 | //-------------------------------------------------------------- 31 | void ofApp::keyPressed(int key){ 32 | switch(key) { 33 | case 's': { 34 | ofxMeshWarpSave saver; 35 | saver.addMesh(mesh_); 36 | saver.save("hoge.txt"); 37 | } break; 38 | case 'l': { 39 | ofxMeshWarpLoad loader; 40 | vector> result = loader.load("hoge.txt"); 41 | if(!result.empty()) { 42 | controller_.clear(); 43 | mesh_ = result[0]; 44 | controller_.add(mesh_); 45 | } 46 | } break; 47 | } 48 | } 49 | 50 | //-------------------------------------------------------------- 51 | void ofApp::keyReleased(int key){ 52 | 53 | } 54 | 55 | //-------------------------------------------------------------- 56 | void ofApp::mouseMoved(int x, int y ){ 57 | 58 | } 59 | 60 | //-------------------------------------------------------------- 61 | void ofApp::mouseDragged(int x, int y, int button){ 62 | 63 | } 64 | 65 | //-------------------------------------------------------------- 66 | void ofApp::mousePressed(int x, int y, int button){ 67 | 68 | } 69 | 70 | //-------------------------------------------------------------- 71 | void ofApp::mouseReleased(int x, int y, int button){ 72 | 73 | } 74 | 75 | //-------------------------------------------------------------- 76 | void ofApp::mouseEntered(int x, int y){ 77 | 78 | } 79 | 80 | //-------------------------------------------------------------- 81 | void ofApp::mouseExited(int x, int y){ 82 | 83 | } 84 | 85 | //-------------------------------------------------------------- 86 | void ofApp::windowResized(int w, int h){ 87 | 88 | } 89 | 90 | //-------------------------------------------------------------- 91 | void ofApp::gotMessage(ofMessage msg){ 92 | 93 | } 94 | 95 | //-------------------------------------------------------------- 96 | void ofApp::dragEvent(ofDragInfo dragInfo){ 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/ofxMeshWarpIO.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxMeshWarpIO.h" 2 | 3 | using namespace ofx::MeshWarp; 4 | using namespace ofx::MeshWarp::IO; 5 | using namespace std; 6 | 7 | void PointHelper::get(ofBuffer &buffer) const 8 | { 9 | PointData data; 10 | data.point = target_->point(); 11 | data.coord = target_->coord(); 12 | data.normal = target_->normal(); 13 | data.color = target_->color(); 14 | data.is_node = target_->isNode(); 15 | buffer.append((const char*)(&data), sizeof(PointData)); 16 | } 17 | int PointHelper::set(const char *buffer) 18 | { 19 | PointData *data = (PointData*)buffer; 20 | target_->setPoint(data->point); 21 | target_->setCoord(data->coord); 22 | target_->setNormal(data->normal); 23 | target_->setColor(data->color); 24 | target_->setNodal(data->is_node); 25 | return sizeof(PointData); 26 | } 27 | void MeshHelper::get(ofBuffer &buffer) const 28 | { 29 | MeshData data; 30 | data.divx = target_->getDivX(); 31 | data.divy = target_->getDivY(); 32 | data.resolution = target_->getChildMeshResolution(); 33 | ofRectangle uv = target_->getUVRect(); 34 | data.uv_rect.set(uv.x, uv.y, uv.width, uv.height); 35 | buffer.append((const char*)(&data), sizeof(MeshData)); 36 | auto points = target_->getPoints(); 37 | for(auto &p : points) { 38 | PointHelper(p).get(buffer); 39 | } 40 | } 41 | int MeshHelper::set(const char *buffer) 42 | { 43 | int ret = 0; 44 | MeshData *data = (MeshData*)buffer; 45 | target_->setup(ofRectangle(0,0,1,1), data->divx, data->divy); 46 | target_->setUVRect(ofRectangle(data->uv_rect[0], data->uv_rect[1], data->uv_rect[2], data->uv_rect[3])); 47 | ret += sizeof(MeshData); 48 | auto points = target_->getPoints(); 49 | for(auto &p : points) { 50 | ret += PointHelper(p).set(buffer+ret); 51 | } 52 | return ret; 53 | } 54 | void Saver::addMesh(shared_ptr mesh) 55 | { 56 | meshes_.push_back(mesh); 57 | } 58 | void Saver::addMeshes(vector> mesh) 59 | { 60 | meshes_.insert(end(meshes_), begin(mesh), end(mesh)); 61 | } 62 | void Saver::save(const string &filename) const 63 | { 64 | ofBuffer buffer; 65 | save(buffer); 66 | ofBufferToFile(filename, buffer, true); 67 | } 68 | void Saver::save(ofBuffer &buffer) const 69 | { 70 | for(auto &mesh : meshes_) { 71 | MeshHelper(mesh.get()).get(buffer); 72 | } 73 | } 74 | 75 | vector> Loader::load(const string &filename) const 76 | { 77 | return load(ofBufferFromFile(filename, true)); 78 | } 79 | 80 | vector> Loader::load(const ofBuffer &buffer) const 81 | { 82 | return load(buffer.getData(), buffer.size()); 83 | } 84 | 85 | vector> Loader::load(const char *data, size_t size) const 86 | { 87 | vector> ret; 88 | const char *end = data+size; 89 | while(data < end) { 90 | auto mesh = make_shared(); 91 | data += MeshHelper(mesh.get()).set(data); 92 | ret.push_back(mesh); 93 | } 94 | return ret; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /example/example.xcodeproj/xcshareddata/xcschemes/example Debug.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/example.xcodeproj/xcshareddata/xcschemes/example Release.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /src/utils/ofxMeshWarpManagedController.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxMeshWarpManagedController.h" 2 | #include "ofGraphics.h" 3 | 4 | using namespace ofx::MeshWarp; 5 | using namespace ofx::MeshWarp::Editor; 6 | using namespace std; 7 | 8 | void ManagedController::clearOperation() 9 | { 10 | for_each(begin(controllers_), end(controllers_), [&](ControllerBase *t){t->clearOperation();}); 11 | } 12 | void ManagedController::add(shared_ptr mesh) 13 | { 14 | ControllerBase::add(mesh); 15 | for_each(begin(controllers_), end(controllers_), [&](ControllerBase *t){t->add(mesh);}); 16 | } 17 | void ManagedController::clear() 18 | { 19 | ControllerBase::clear(); 20 | for_each(begin(controllers_), end(controllers_), [&](ControllerBase *t){t->clear();}); 21 | } 22 | void ManagedController::drawCustom() const 23 | { 24 | if(is_mover_active_) { 25 | mover_.drawCustom(); 26 | } 27 | if(is_divider_active_) { 28 | divider_.drawCustom(); 29 | } 30 | } 31 | 32 | void ManagedController::setAnchorPoint(float x, float y) 33 | { 34 | ControllerBase::setAnchorPoint(x,y); 35 | for_each(begin(controllers_), end(controllers_), [&](ControllerBase *t){t->setAnchorPoint(x,y);}); 36 | } 37 | void ManagedController::setTranslation(float x, float y) 38 | { 39 | ControllerBase::setTranslation(x,y); 40 | for_each(begin(controllers_), end(controllers_), [&](ControllerBase *t){t->setTranslation(x,y);}); 41 | } 42 | void ManagedController::setScale(float s) 43 | { 44 | ControllerBase::setScale(s); 45 | for_each(begin(controllers_), end(controllers_), [&](ControllerBase *t){t->setScale(s);}); 46 | } 47 | 48 | void ManagedController::activateMover() 49 | { 50 | is_mover_active_ = true; 51 | is_divider_active_ = false; 52 | divider_.clearOperation(); 53 | } 54 | void ManagedController::activateDivider() 55 | { 56 | is_mover_active_ = false; 57 | is_divider_active_ = true; 58 | } 59 | void ManagedController::mousePressed(ofMouseEventArgs &args) 60 | { 61 | if(is_mover_active_) { 62 | mover_.mousePressed(args); 63 | } 64 | if(is_divider_active_) { 65 | divider_.mousePressed(args); 66 | } 67 | } 68 | void ManagedController::mouseReleased(ofMouseEventArgs &args) 69 | { 70 | mover_.mouseReleased(args); 71 | divider_.mouseReleased(args); 72 | if(mover_.isEditing()) { 73 | activateMover(); 74 | } 75 | else { 76 | if(divider_.isEditing()) { 77 | activateDivider(); 78 | } 79 | else { 80 | activateMover(); 81 | } 82 | } 83 | } 84 | void ManagedController::mouseMoved(ofMouseEventArgs &args) 85 | { 86 | mover_.mouseMoved(args); 87 | if(mover_.isEditing()) { 88 | activateMover(); 89 | } 90 | else { 91 | divider_.mouseMoved(args); 92 | if(divider_.isEditing()) { 93 | activateDivider(); 94 | } 95 | else { 96 | activateMover(); 97 | } 98 | } 99 | } 100 | void ManagedController::mouseDragged(ofMouseEventArgs &args) 101 | { 102 | if(is_mover_active_) { 103 | mover_.mouseDragged(args); 104 | } 105 | if(is_divider_active_) { 106 | divider_.mouseDragged(args); 107 | } 108 | } 109 | void ManagedController::mouseScrolled(ofMouseEventArgs &args) 110 | { 111 | if(is_mover_active_) { 112 | mover_.mouseScrolled(args); 113 | } 114 | if(is_divider_active_) { 115 | divider_.mouseScrolled(args); 116 | } 117 | } 118 | void ManagedController::mouseEntered(ofMouseEventArgs &args) 119 | { 120 | if(is_mover_active_) { 121 | mover_.mouseEntered(args); 122 | } 123 | if(is_divider_active_) { 124 | divider_.mouseEntered(args); 125 | } 126 | } 127 | void ManagedController::mouseExited(ofMouseEventArgs &args) 128 | { 129 | if(is_mover_active_) { 130 | mover_.mouseExited(args); 131 | } 132 | if(is_divider_active_) { 133 | divider_.mouseExited(args); 134 | } 135 | } 136 | void ManagedController::keyPressed(ofKeyEventArgs &args) 137 | { 138 | if(is_mover_active_) { 139 | mover_.keyPressed(args); 140 | } 141 | if(is_divider_active_) { 142 | divider_.keyPressed(args); 143 | } 144 | } 145 | void ManagedController::keyReleased(ofKeyEventArgs &args) 146 | { 147 | if(is_mover_active_) { 148 | mover_.keyReleased(args); 149 | } 150 | if(is_divider_active_) { 151 | divider_.keyReleased(args); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/ofxMeshWarp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofConstants.h" 4 | #include "glm/vec2.hpp" 5 | #include "glm/vec3.hpp" 6 | #include "ofColor.h" 7 | #include "ofMesh.h" 8 | #include "ofRectangle.h" 9 | 10 | namespace ofx{namespace MeshWarp{ 11 | class MeshPoint 12 | { 13 | public: 14 | static MeshPoint getLerped(const MeshPoint &a, const MeshPoint &b, float mix) { 15 | MeshPoint ret; 16 | ret.point_ = glm::mix(a.point_, b.point_, mix); 17 | ret.coord_ = glm::mix(a.coord_, b.coord_, mix); 18 | ret.normal_ = glm::mix(a.normal_, b.normal_, mix); 19 | ret.color_ = a.color_.getLerped(b.color_, mix); 20 | return ret; 21 | } 22 | const glm::vec3 &point() const { return point_; } 23 | const glm::vec2 &coord() const { return coord_; } 24 | const glm::vec3 &normal() const { return normal_; } 25 | const ofFloatColor &color() const { return color_; } 26 | float alpha() const { return color_.a; } 27 | bool isNode() const { return is_node_; } 28 | void setPoint(const glm::vec3 &point) { point_=point; } 29 | void setCoord(const glm::vec2 &coord) { coord_=coord; } 30 | void setNormal(const glm::vec3 &normal) { normal_=normal; } 31 | void setColor(const ofFloatColor &color) { color_=color; } 32 | void setAlpha(float alpha) { color_.a=alpha; } 33 | void setNodal(bool set) { is_node_=set; } 34 | void toggleNodal() { is_node_^=true; } 35 | 36 | private: 37 | glm::vec3 point_ = glm::vec3(0,0,0); 38 | glm::vec2 coord_ = glm::vec2(0,0); 39 | glm::vec3 normal_ = glm::vec3(0,0,1); 40 | ofFloatColor color_ = ofFloatColor::white; 41 | bool is_node_ = true; 42 | }; 43 | 44 | 45 | class Mesh 46 | { 47 | public: 48 | void setup(const ofRectangle &rect, int div_x, int div_y); 49 | void setDirty() { dirty_ = true; } 50 | bool isDirty() const { return dirty_; } 51 | void update(); 52 | OF_DEPRECATED_MSG("use setUVRect instead", void setTexCoordSize(float u, float v)); 53 | void setUVRect(const ofRectangle &uv); 54 | void setChildMeshResolution(int resolution); 55 | void divideCol(int pos, float ratio); 56 | void divideRow(int pos, float ratio); 57 | void reduceCol(int pos); 58 | void reduceRow(int pos); 59 | void reset(const ofRectangle &rect); 60 | void drawMesh() const; 61 | void drawWireframe() const; 62 | void drawDetailedWireframe() const; 63 | std::vector getPoints(); 64 | const ofMesh& getOfMesh() const { return of_mesh_; } 65 | int getDivX() const { return div_x_; } 66 | int getDivY() const { return div_y_; } 67 | const ofRectangle& getUVRect() const { return uv_rect_; } 68 | int getChildMeshResolution() const { return child_mesh_resolution_; } 69 | void gc(); 70 | void setEnablePointInterpolation(bool set) { interpolate_flags_.point=set; } 71 | void setEnableCoordInterpolation(bool set) { interpolate_flags_.coord=set; } 72 | void setEnableNormalInterpolation(bool set) { interpolate_flags_.normal=set; } 73 | void setEnableColorInterpolation(bool set) { interpolate_flags_.color=set; } 74 | bool isEnabledPointInterpolation() const { return interpolate_flags_.point; } 75 | bool isEnabledCoordInterpolation() const { return interpolate_flags_.coord; } 76 | bool isEnabledNormalInterpolation() const { return interpolate_flags_.normal; } 77 | bool isEnabledColorInterpolation() const { return interpolate_flags_.color; } 78 | private: 79 | int div_x_, div_y_; 80 | ofRectangle uv_rect_ = ofRectangle(0,0,1,1); 81 | std::vector indices_; 82 | std::vector mesh_; 83 | ofMesh of_mesh_; 84 | ofIndexType getIndex(int x, int y) const { return indices_[y*div_x_+x]; } 85 | int child_mesh_resolution_ = 8; 86 | void drawChildMesh() const; 87 | Mesh makeChildMesh(int x, int y, int resolution) const; 88 | struct { 89 | bool point=true, coord=true, normal=true, color=true; 90 | } interpolate_flags_; 91 | bool isEnabledAnyInterpolation() const { 92 | return interpolate_flags_.point 93 | || interpolate_flags_.coord 94 | || interpolate_flags_.normal 95 | || interpolate_flags_.color; 96 | } 97 | std::vector> child_meshes_; 98 | bool dirty_=true; 99 | void solve(); 100 | void refreshChildMeshes(); 101 | }; 102 | }} 103 | using ofxMeshWarp = ofx::MeshWarp::Mesh; 104 | using ofxMeshWarpPoint = ofx::MeshWarp::MeshPoint; 105 | -------------------------------------------------------------------------------- /example/config.make: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # CONFIGURE PROJECT MAKEFILE (optional) 3 | # This file is where we make project specific configurations. 4 | ################################################################################ 5 | 6 | ################################################################################ 7 | # OF ROOT 8 | # The location of your root openFrameworks installation 9 | # (default) OF_ROOT = ../../.. 10 | ################################################################################ 11 | # OF_ROOT = ../../.. 12 | 13 | ################################################################################ 14 | # PROJECT ROOT 15 | # The location of the project - a starting place for searching for files 16 | # (default) PROJECT_ROOT = . (this directory) 17 | # 18 | ################################################################################ 19 | # PROJECT_ROOT = . 20 | 21 | ################################################################################ 22 | # PROJECT SPECIFIC CHECKS 23 | # This is a project defined section to create internal makefile flags to 24 | # conditionally enable or disable the addition of various features within 25 | # this makefile. For instance, if you want to make changes based on whether 26 | # GTK is installed, one might test that here and create a variable to check. 27 | ################################################################################ 28 | # None 29 | 30 | ################################################################################ 31 | # PROJECT EXTERNAL SOURCE PATHS 32 | # These are fully qualified paths that are not within the PROJECT_ROOT folder. 33 | # Like source folders in the PROJECT_ROOT, these paths are subject to 34 | # exlclusion via the PROJECT_EXLCUSIONS list. 35 | # 36 | # (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) 37 | # 38 | # Note: Leave a leading space when adding list items with the += operator 39 | ################################################################################ 40 | # PROJECT_EXTERNAL_SOURCE_PATHS = 41 | 42 | ################################################################################ 43 | # PROJECT EXCLUSIONS 44 | # These makefiles assume that all folders in your current project directory 45 | # and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations 46 | # to look for source code. The any folders or files that match any of the 47 | # items in the PROJECT_EXCLUSIONS list below will be ignored. 48 | # 49 | # Each item in the PROJECT_EXCLUSIONS list will be treated as a complete 50 | # string unless teh user adds a wildcard (%) operator to match subdirectories. 51 | # GNU make only allows one wildcard for matching. The second wildcard (%) is 52 | # treated literally. 53 | # 54 | # (default) PROJECT_EXCLUSIONS = (blank) 55 | # 56 | # Will automatically exclude the following: 57 | # 58 | # $(PROJECT_ROOT)/bin% 59 | # $(PROJECT_ROOT)/obj% 60 | # $(PROJECT_ROOT)/%.xcodeproj 61 | # 62 | # Note: Leave a leading space when adding list items with the += operator 63 | ################################################################################ 64 | # PROJECT_EXCLUSIONS = 65 | 66 | ################################################################################ 67 | # PROJECT LINKER FLAGS 68 | # These flags will be sent to the linker when compiling the executable. 69 | # 70 | # (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs 71 | # 72 | # Note: Leave a leading space when adding list items with the += operator 73 | ################################################################################ 74 | 75 | # Currently, shared libraries that are needed are copied to the 76 | # $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to 77 | # add a runtime path to search for those shared libraries, since they aren't 78 | # incorporated directly into the final executable application binary. 79 | # TODO: should this be a default setting? 80 | # PROJECT_LDFLAGS=-Wl,-rpath=./libs 81 | 82 | ################################################################################ 83 | # PROJECT DEFINES 84 | # Create a space-delimited list of DEFINES. The list will be converted into 85 | # CFLAGS with the "-D" flag later in the makefile. 86 | # 87 | # (default) PROJECT_DEFINES = (blank) 88 | # 89 | # Note: Leave a leading space when adding list items with the += operator 90 | ################################################################################ 91 | # PROJECT_DEFINES = 92 | 93 | ################################################################################ 94 | # PROJECT CFLAGS 95 | # This is a list of fully qualified CFLAGS required when compiling for this 96 | # project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS 97 | # defined in your platform specific core configuration files. These flags are 98 | # presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. 99 | # 100 | # (default) PROJECT_CFLAGS = (blank) 101 | # 102 | # Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in 103 | # your platform specific configuration file will be applied by default and 104 | # further flags here may not be needed. 105 | # 106 | # Note: Leave a leading space when adding list items with the += operator 107 | ################################################################################ 108 | # PROJECT_CFLAGS = 109 | 110 | ################################################################################ 111 | # PROJECT OPTIMIZATION CFLAGS 112 | # These are lists of CFLAGS that are target-specific. While any flags could 113 | # be conditionally added, they are usually limited to optimization flags. 114 | # These flags are added BEFORE the PROJECT_CFLAGS. 115 | # 116 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. 117 | # 118 | # (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) 119 | # 120 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. 121 | # 122 | # (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) 123 | # 124 | # Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the 125 | # PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration 126 | # file will be applied by default and further optimization flags here may not 127 | # be needed. 128 | # 129 | # Note: Leave a leading space when adding list items with the += operator 130 | ################################################################################ 131 | # PROJECT_OPTIMIZATION_CFLAGS_RELEASE = 132 | # PROJECT_OPTIMIZATION_CFLAGS_DEBUG = 133 | 134 | ################################################################################ 135 | # PROJECT COMPILERS 136 | # Custom compilers can be set for CC and CXX 137 | # (default) PROJECT_CXX = (blank) 138 | # (default) PROJECT_CC = (blank) 139 | # Note: Leave a leading space when adding list items with the += operator 140 | ################################################################################ 141 | # PROJECT_CXX = 142 | # PROJECT_CC = 143 | -------------------------------------------------------------------------------- /src/ofxMeshWarpController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofEvents.h" 4 | #include "ofxMeshWarp.h" 5 | #include "ofRectangle.h" 6 | #include "ofPolyline.h" 7 | 8 | namespace ofx{namespace MeshWarp{ 9 | namespace Editor { 10 | class PointHelper : public std::pair { 11 | public: 12 | PointHelper(MeshPoint *p):pair(p,*p){} 13 | void setVertex(const glm::vec2 &point) { first->setPoint(glm::vec3(point,0)); } 14 | void setVertexMove(const glm::vec2 &move) { first->setPoint(second.point()+move); } 15 | void moveVertex(const glm::vec2 &move) { first->setPoint(first->point()+move); } 16 | void resetVertex() { first->setPoint(second.point()); } 17 | void setCoord(const glm::vec2 &point) { first->setCoord(point); } 18 | void setCoordMove(const glm::vec2 &move) { first->setCoord(second.coord()+move); } 19 | void moveCoord(const glm::vec2 &move) { first->setCoord(first->coord()+move); } 20 | void resetCoord() { first->setCoord(second.coord()); } 21 | void setColor(const ofFloatColor &color) { first->setColor(color); } 22 | void resetColor() { first->setColor(second.color()); } 23 | void setAlpha(float alpha) { first->setAlpha(alpha); } 24 | void addAlpha(float alpha) { first->setAlpha(first->alpha()+alpha); } 25 | void resetAlpha() { first->setAlpha(second.alpha()); } 26 | }; 27 | class MeshHelper 28 | { 29 | public: 30 | MeshHelper(Mesh *m):target_(m){} 31 | MeshPoint* getHit(const glm::vec2 &test, float room, int index=0) const; 32 | std::vector getHit(const ofRectangle &test) const; 33 | std::vector getBox(int top_left_index) const; 34 | std::vector getBoxIndices(int top_left_index) const; 35 | bool isHitBox(const glm::vec2 &test, int top_left_index) const; 36 | bool isHitLine(const glm::vec2 &test, int index0, int index1, float room, float &pos) const; 37 | std::vector getColPoints(int point_index) const; 38 | std::vector getRowPoints(int point_index) const; 39 | private: 40 | Mesh *target_; 41 | }; 42 | 43 | class ControllerBase { 44 | public: 45 | ControllerBase(); 46 | virtual ~ControllerBase(); 47 | void add(std::shared_ptr target); 48 | void enable(); 49 | void disable(); 50 | void setEnable(bool set) { set?enable():disable(); } 51 | bool isEnabled() const { return is_enabled_; } 52 | void clear(); 53 | void draw() const; 54 | void drawFace() const; 55 | 56 | void setAnchorPoint(float x, float y) { setAnchorPoint(glm::vec2(x,y)); } 57 | void setAnchorPoint(const glm::vec2 &point) { anchor_point_ = point; } 58 | void setTranslation(float x, float y) { setTranslation(glm::vec2(x,y)); } 59 | void setTranslation(const glm::vec2 &point) { translation_ = point; } 60 | void setScale(float s) { assert(s>0); scale_ = s; } 61 | 62 | virtual bool isEditing() const { return false; } 63 | 64 | virtual void clearOperation(){}; 65 | 66 | virtual void mousePressed(ofMouseEventArgs &args){} 67 | virtual void mouseReleased(ofMouseEventArgs &args){} 68 | virtual void mouseMoved(ofMouseEventArgs &args){} 69 | virtual void mouseDragged(ofMouseEventArgs &args){} 70 | virtual void mouseScrolled(ofMouseEventArgs &args){} 71 | virtual void mouseEntered(ofMouseEventArgs &args){} 72 | virtual void mouseExited(ofMouseEventArgs &args){} 73 | virtual void keyPressed(ofKeyEventArgs &args){} 74 | virtual void keyReleased(ofKeyEventArgs &args){} 75 | protected: 76 | std::set> meshes_; 77 | bool is_enabled_ = false; 78 | virtual void drawCustom() const{}; 79 | 80 | glm::vec2 anchor_point_=glm::vec2(0,0); 81 | glm::vec2 translation_=glm::vec2(0,0); 82 | float scale_=1; 83 | glm::vec2 screenToLocal(glm::vec2 src) const { return (src-translation_)/scale_+anchor_point_; } 84 | glm::vec2 localToScreen(glm::vec2 src) const { return (src-anchor_point_)*scale_+translation_; } 85 | }; 86 | 87 | class PointController : public ControllerBase 88 | { 89 | public: 90 | void clearOperation(); 91 | void drawCustom() const; 92 | bool isEditing() const; 93 | 94 | void setUVResolution(const glm::vec2 &res) { screen_to_coord_ = res; } 95 | 96 | virtual void mousePressed(ofMouseEventArgs &args); 97 | virtual void mouseReleased(ofMouseEventArgs &args); 98 | virtual void mouseMoved(ofMouseEventArgs &args); 99 | virtual void mouseDragged(ofMouseEventArgs &args); 100 | virtual void mouseScrolled(ofMouseEventArgs &args); 101 | virtual void mouseEntered(ofMouseEventArgs &args); 102 | virtual void mouseExited(ofMouseEventArgs &args); 103 | virtual void keyPressed(ofKeyEventArgs &args); 104 | virtual void keyReleased(ofKeyEventArgs &args); 105 | protected: 106 | struct MouseOperation { 107 | MeshPoint *hover = nullptr; 108 | std::vector inside_rect; 109 | glm::vec2 pressed_pos, pos; 110 | std::vector edit; 111 | enum { 112 | STATE_NONE, 113 | STATE_GRABBING, 114 | STATE_MAKING_RECT, 115 | } pressed_state = STATE_NONE; 116 | } mouse_op_; 117 | std::set selected_; 118 | float point_size_ = 10; 119 | glm::vec2 screen_to_coord_=glm::vec2(1024.f,1024.f); 120 | float scroll_to_alpha_ = -1/100.f; 121 | 122 | bool isGrabbing() const { return mouse_op_.pressed_state==MouseOperation::STATE_GRABBING; } 123 | bool isMakingRect() const { return mouse_op_.pressed_state==MouseOperation::STATE_MAKING_RECT; } 124 | virtual bool isToggleNode() const { return ofGetKeyPressed(OF_KEY_ALT); } 125 | virtual bool isSlide() const { return ofGetKeyPressed(OF_KEY_SHIFT); } 126 | virtual bool isAdditive() const { return ofGetKeyPressed(OF_KEY_SHIFT); } 127 | virtual bool isAlternative() const { return ofGetKeyPressed(OF_KEY_COMMAND); } 128 | virtual bool isArrowKeyJump() const { return ofGetKeyPressed(OF_KEY_SHIFT); } 129 | virtual bool isEditCoord() const { return ofGetKeyPressed(OF_KEY_ALT); } 130 | virtual bool isEditVertex() const { return !ofGetKeyPressed(OF_KEY_ALT); } 131 | 132 | MeshPoint* getHit(const glm::vec2 &test) const; 133 | }; 134 | class DivideController : public ControllerBase 135 | { 136 | public: 137 | void clearOperation(); 138 | void drawCustom() const; 139 | bool isEditing() const; 140 | 141 | virtual void mousePressed(ofMouseEventArgs &args); 142 | virtual void mouseReleased(ofMouseEventArgs &args); 143 | virtual void mouseMoved(ofMouseEventArgs &args); 144 | virtual void mouseDragged(ofMouseEventArgs &args); 145 | virtual void mouseScrolled(ofMouseEventArgs &args); 146 | virtual void mouseEntered(ofMouseEventArgs &args); 147 | virtual void mouseExited(ofMouseEventArgs &args); 148 | virtual void keyPressed(ofKeyEventArgs &args); 149 | virtual void keyReleased(ofKeyEventArgs &args); 150 | protected: 151 | float line_hit_size_ = 10; 152 | struct HitInfo { 153 | Mesh *mesh = nullptr; 154 | int area_index = -1; 155 | int line_index_0 = -1, line_index_1 = -1; 156 | float pos_intersection = -1; 157 | bool isArea() const { return area_index; } 158 | bool isLine() const { return line_index_0 != -1 && line_index_1 != -1; } 159 | bool isLineX() const { return isLine() && abs(line_index_0-line_index_1)==1; } 160 | bool isLineY() const { return isLine() && !isLineX(); } 161 | } hit_info_; 162 | 163 | virtual bool isDivide() const { return !ofGetKeyPressed(OF_KEY_ALT); } 164 | virtual bool isReduce() const { return ofGetKeyPressed(OF_KEY_ALT); } 165 | HitInfo getHitInfo(const glm::vec2 &test) const; 166 | }; 167 | } 168 | }} 169 | using ofxMeshWarpControllerBase = ofx::MeshWarp::Editor::ControllerBase; 170 | using ofxMeshWarpPointController = ofx::MeshWarp::Editor::PointController; 171 | using ofxMeshWarpMeshDivider = ofx::MeshWarp::Editor::DivideController; 172 | -------------------------------------------------------------------------------- /src/ofxMeshWarp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxMeshWarp.h" 2 | #include "ofTexture.h" 3 | #include 4 | 5 | using namespace ofx::MeshWarp; 6 | using namespace std; 7 | 8 | void Mesh::setup(const ofRectangle &rect, int div_x, int div_y) 9 | { 10 | if(div_x < 1 || div_y < 1) { 11 | ofLogError(__FILE__, "div_x and div_y must be bigger than 1"); 12 | return; 13 | } 14 | div_x_ = div_x; 15 | div_y_ = div_y; 16 | reset(rect); 17 | of_mesh_.setMode(OF_PRIMITIVE_TRIANGLES); 18 | } 19 | void Mesh::update() 20 | { 21 | if(dirty_) { 22 | solve(); 23 | } 24 | } 25 | void Mesh::setTexCoordSize(float u, float v) 26 | { 27 | setUVRect(ofRectangle(0,0,u,v)); 28 | } 29 | void Mesh::setUVRect(const ofRectangle &rect) 30 | { 31 | uv_rect_ = rect; 32 | setDirty(); 33 | } 34 | void Mesh::setChildMeshResolution(int resolution) 35 | { 36 | child_mesh_resolution_ = resolution; 37 | setDirty(); 38 | } 39 | void Mesh::divideCol(int pos, float ratio) 40 | { 41 | if(pos < 0 || div_x_-1 <= pos) { 42 | ofLogError(__FILE__, "index out of bounds: %d", pos); 43 | return; 44 | } 45 | auto indices = indices_; 46 | auto it = begin(indices)+pos+1; 47 | for(int y = 0; y < div_y_; ++y) { 48 | MeshPoint &a = mesh_[getIndex(pos,y)]; 49 | MeshPoint &b = mesh_[getIndex(pos+1,y)]; 50 | MeshPoint point = MeshPoint(MeshPoint::getLerped(a, b, ratio)); 51 | it = indices.insert(it, mesh_.size()); 52 | mesh_.push_back(point); 53 | if(y < div_y_-1) { 54 | it += div_x_+1; 55 | } 56 | } 57 | indices_ = indices; 58 | ++div_x_; 59 | setDirty(); 60 | } 61 | void Mesh::divideRow(int pos, float ratio) 62 | { 63 | if(pos < 0 || div_y_-1 <= pos) { 64 | ofLogError(__FILE__, "index out of bounds: %d", pos); 65 | return; 66 | } 67 | auto indices = indices_; 68 | auto it = begin(indices)+(pos+1)*div_x_; 69 | for(int x = 0; x < div_x_; ++x) { 70 | MeshPoint &a = mesh_[getIndex(x,pos)]; 71 | MeshPoint &b = mesh_[getIndex(x,pos+1)]; 72 | MeshPoint point = MeshPoint(MeshPoint::getLerped(a, b, ratio)); 73 | it = indices.insert(it, (ofIndexType)mesh_.size())+1; 74 | mesh_.push_back(point); 75 | } 76 | indices_ = indices; 77 | ++div_y_; 78 | setDirty(); 79 | } 80 | void Mesh::reduceCol(int pos) 81 | { 82 | if(div_x_ <= 2) { 83 | ofLogError(__FILE__, "cannot reduce col anymore."); 84 | return; 85 | } 86 | if(pos < 0 || div_x_ <= pos) { 87 | ofLogError(__FILE__, "index out of bounds: %d", pos); 88 | return; 89 | } 90 | for(int i = div_y_; --i >= 0;) { 91 | int index = i*div_x_+pos; 92 | indices_.erase(begin(indices_)+index); 93 | } 94 | --div_x_; 95 | setDirty(); 96 | } 97 | void Mesh::reduceRow(int pos) 98 | { 99 | if(div_y_ <= 2) { 100 | ofLogError(__FILE__, "cannot reduce row anymore."); 101 | return; 102 | } 103 | if(pos < 0 || div_y_ <= pos) { 104 | ofLogError(__FILE__, "index out of bounds: %d", pos); 105 | return; 106 | } 107 | auto from = begin(indices_)+pos*div_x_; 108 | auto to = from+div_x_; 109 | indices_.erase(from, to); 110 | --div_y_; 111 | setDirty(); 112 | } 113 | void Mesh::reset(const ofRectangle &rect) 114 | { 115 | int num = div_x_*div_y_; 116 | mesh_.resize(num); 117 | for(int i = 0; i < num; ++i) { 118 | MeshPoint &point = mesh_[i]; 119 | glm::vec2 coord = glm::vec2(i%div_x_,i/div_x_)/glm::vec2(div_x_-1,div_y_-1); 120 | point.setCoord(coord); 121 | point.setPoint(rect.position + glm::vec3(coord*glm::vec2(rect.getWidth(),rect.getHeight()), 0)); 122 | } 123 | indices_.resize(num); 124 | iota(begin(indices_), end(indices_), 0); 125 | setDirty(); 126 | } 127 | void Mesh::solve() 128 | { 129 | if(!isEnabledAnyInterpolation()) { 130 | return; 131 | } 132 | auto solveFlameX = [&](int y) { 133 | vector work; 134 | work.clear(); 135 | work.push_back(&mesh_[getIndex(0,y)]); 136 | for(int x = 1; x < div_x_; ++x) { 137 | MeshPoint *p1 = &mesh_[getIndex(x,y)]; 138 | if(p1->isNode() || x == div_x_-1) { 139 | if(work.size() > 1) { 140 | MeshPoint *p0 = work[0]; 141 | for(size_t w = 1, num = work.size(); w < num; ++w) { 142 | MeshPoint lerped = MeshPoint::getLerped(*p0, *p1, w/(float)num); 143 | if(isEnabledPointInterpolation()) work[w]->setPoint(lerped.point()); 144 | if(isEnabledCoordInterpolation()) work[w]->setCoord(lerped.coord()); 145 | if(isEnabledNormalInterpolation()) work[w]->setNormal(lerped.normal()); 146 | if(isEnabledColorInterpolation()) work[w]->setColor(lerped.color()); 147 | } 148 | } 149 | work.clear(); 150 | } 151 | work.push_back(p1); 152 | } 153 | }; 154 | auto solveFlameY = [&](int x) { 155 | vector work; 156 | work.clear(); 157 | work.push_back(&mesh_[getIndex(x,0)]); 158 | for(int y = 1; y < div_y_; ++y) { 159 | MeshPoint *p1 = &mesh_[getIndex(x,y)]; 160 | if(p1->isNode() || y == div_y_-1) { 161 | if(work.size() > 1) { 162 | MeshPoint *p0 = work[0]; 163 | for(size_t w = 1, num = work.size(); w < num; ++w) { 164 | MeshPoint lerped = MeshPoint::getLerped(*p0, *p1, w/(float)num); 165 | if(isEnabledPointInterpolation()) work[w]->setPoint(lerped.point()); 166 | if(isEnabledCoordInterpolation()) work[w]->setCoord(lerped.coord()); 167 | if(isEnabledNormalInterpolation()) work[w]->setNormal(lerped.normal()); 168 | if(isEnabledColorInterpolation()) work[w]->setColor(lerped.color()); 169 | } 170 | } 171 | work.clear(); 172 | } 173 | work.push_back(p1); 174 | } 175 | }; 176 | auto solveInternal = [&](int x, int y) { 177 | assert(0 < x && x < div_x_-1 && 0 < y && y < div_y_-1); 178 | auto getDistanceToNode = [&](int x, int y, int diff_x, int diff_y) mutable ->pair { 179 | int ret = 0; 180 | while(0 < x && x < div_x_-1 && 0 < y && y < div_y_-1) { 181 | x += diff_x; y += diff_y; 182 | ++ret; 183 | if(mesh_[getIndex(x,y)].isNode()) break; 184 | } 185 | assert(ret>0); 186 | return make_pair(&mesh_[getIndex(x,y)],ret); 187 | }; 188 | map around{ 189 | getDistanceToNode(x,y, -1,-1), 190 | getDistanceToNode(x,y, -1, 0), 191 | getDistanceToNode(x,y, -1, 1), 192 | getDistanceToNode(x,y, 1,-1), 193 | getDistanceToNode(x,y, 1, 0), 194 | getDistanceToNode(x,y, 1,+1), 195 | getDistanceToNode(x,y, 0,-1), 196 | getDistanceToNode(x,y, 0,+1), 197 | }; 198 | float inv_sum = [&around]()->float{float ret=0;for(auto &p:around)ret+=1/(float)p.second;return ret;}(); 199 | auto ratio = [&around,inv_sum](int self)->float { 200 | return ofMap(1/(float)self, 0, inv_sum, 0, 1, false); 201 | }; 202 | MeshPoint &dst = mesh_[getIndex(x,y)]; 203 | if(isEnabledPointInterpolation()) { 204 | glm::vec3 point = [&around,&ratio](){glm::vec3 ret;for(auto &p:around)ret+=p.first->point()*ratio(p.second);return ret;}(); 205 | dst.setPoint(point); 206 | } 207 | if(isEnabledCoordInterpolation()) { 208 | glm::vec2 coord = [&around,&ratio](){glm::vec2 ret;for(auto &p:around)ret+=p.first->coord()*ratio(p.second);return ret;}(); 209 | dst.setCoord(coord); 210 | } 211 | if(isEnabledNormalInterpolation()) { 212 | glm::vec3 normal = [&around,&ratio](){glm::vec3 ret;for(auto &p:around)ret+=p.first->normal()*ratio(p.second);return ret;}(); 213 | dst.setNormal(normal); 214 | } 215 | if(isEnabledColorInterpolation()) { 216 | ofVec4f color = [&around,&ratio]() { 217 | ofVec4f ret; 218 | for(auto &p:around) { 219 | auto color = p.first->color(); 220 | ret += ofVec4f(color[0], color[1], color[2], color[3])*ratio(p.second); 221 | } 222 | return ret; 223 | }(); 224 | dst.setColor(ofFloatColor(color[0],color[1],color[2],color[3])); 225 | } 226 | }; 227 | solveFlameX(0); 228 | solveFlameX(div_y_-1); 229 | solveFlameY(0); 230 | solveFlameY(div_x_-1); 231 | for(int y = 1; y < div_y_-1; ++y) { 232 | for(int x = 1; x < div_x_-1; ++x) { 233 | if(!mesh_[getIndex(x,y)].isNode()) { 234 | solveInternal(x,y); 235 | } 236 | } 237 | } 238 | if(child_mesh_resolution_ > 1) { 239 | refreshChildMeshes(); 240 | } 241 | 242 | of_mesh_.clear(); 243 | for(auto &p :mesh_) { 244 | glm::vec2 coord = p.coord(); 245 | coord.x =ofMap(coord.x, 0, 1, uv_rect_.getLeft(), uv_rect_.getRight()); 246 | coord.y =ofMap(coord.y, 0, 1, uv_rect_.getTop(), uv_rect_.getBottom()); 247 | of_mesh_.addTexCoord(coord); 248 | of_mesh_.addColor(p.color()); 249 | of_mesh_.addNormal(p.normal()); 250 | of_mesh_.addVertex(p.point()); 251 | } 252 | for(int y = 0; y < div_y_-1; ++y) { 253 | for(int x = 0; x < div_x_-1; ++x) { 254 | of_mesh_.addIndex(getIndex(x ,y )); 255 | of_mesh_.addIndex(getIndex(x ,y+1)); 256 | of_mesh_.addIndex(getIndex(x+1,y )); 257 | of_mesh_.addIndex(getIndex(x+1,y )); 258 | of_mesh_.addIndex(getIndex(x ,y+1)); 259 | of_mesh_.addIndex(getIndex(x+1,y+1)); 260 | } 261 | } 262 | 263 | dirty_ = false; 264 | } 265 | 266 | void Mesh::gc() 267 | { 268 | if(mesh_.size() == indices_.size()) { 269 | ofLogNotice(__FILE__, "no need for gc-ing"); 270 | return; 271 | } 272 | vector neu; 273 | for(auto &i : indices_) { 274 | neu.push_back(mesh_[i]); 275 | } 276 | neu.swap(mesh_); 277 | iota(begin(indices_), end(indices_), 0); 278 | dirty_ = true; 279 | } 280 | 281 | vector Mesh::getPoints() 282 | { 283 | vector ret; 284 | for(int y = 0; y < div_y_; ++y) { 285 | for(int x = 0; x < div_x_; ++x) { 286 | ret.push_back(&mesh_[getIndex(x,y)]); 287 | } 288 | } 289 | return ret; 290 | } 291 | 292 | void Mesh::drawMesh() const 293 | { 294 | if(child_mesh_resolution_ > 1) { 295 | drawChildMesh(); 296 | } 297 | else { 298 | of_mesh_.draw(); 299 | } 300 | } 301 | 302 | Mesh Mesh::makeChildMesh(int x, int y, int resolution) const 303 | { 304 | Mesh mesh; 305 | mesh.setChildMeshResolution(1); 306 | mesh.setUVRect(uv_rect_); 307 | mesh.setup(ofRectangle(0,0,1,1), resolution, resolution); 308 | auto isCorner = [resolution](int x, int y) { 309 | return (x==0||x==resolution-1)&&(y==0||y==resolution-1); 310 | }; 311 | #ifndef OFXMESHWARP_USE_OLD_CHILDMESH 312 | const MeshPoint *quad[2][2] = { 313 | {&mesh_[getIndex(x,y)], &mesh_[getIndex(x,y+1)]}, 314 | {&mesh_[getIndex(x+1,y)], &mesh_[getIndex(x+1,y+1)]} 315 | }; 316 | for(int iy = 0; iy < resolution; ++iy) { 317 | float ry = iy/(float)(resolution-1); 318 | MeshPoint cp[2] = {MeshPoint::getLerped(*quad[0][0], *quad[0][1], ry), MeshPoint::getLerped(*quad[1][0], *quad[1][1], ry)}; 319 | for(int ix = 0; ix < resolution; ++ix) { 320 | float rx = ix/(float)(resolution-1); 321 | mesh.mesh_[mesh.getIndex(ix,iy)] = MeshPoint::getLerped(cp[0], cp[1], rx); 322 | } 323 | } 324 | mesh.update(); 325 | #else 326 | mesh.mesh_[mesh.getIndex(0,0)] = mesh_[getIndex(x,y)]; 327 | mesh.mesh_[mesh.getIndex(resolution-1,0)] = mesh_[getIndex(x+1,y)]; 328 | mesh.mesh_[mesh.getIndex(0,resolution-1)] = mesh_[getIndex(x,y+1)]; 329 | mesh.mesh_[mesh.getIndex(resolution-1,resolution-1)] = mesh_[getIndex(x+1,y+1)]; 330 | for(int iy = 0; iy < resolution; ++iy) { 331 | for(int ix = 0; ix < resolution; ++ix) { 332 | mesh.mesh_[mesh.getIndex(ix,iy)].setNodal(isCorner(ix,iy)); 333 | } 334 | } 335 | mesh.solve(); 336 | #endif 337 | return mesh; 338 | } 339 | void Mesh::drawChildMesh() const 340 | { 341 | if(child_mesh_resolution_ < 2) { 342 | ofLogWarning(__FILE__, "child mesh resolution should be more than 2: %d", child_mesh_resolution_); 343 | return; 344 | } 345 | for(int x = 0; x < div_x_-1; ++x) { 346 | for(int y = 0; y < div_y_-1; ++y) { 347 | child_meshes_[x][y].drawMesh(); 348 | } 349 | } 350 | } 351 | void Mesh::drawWireframe() const 352 | { 353 | for(int y = 0; y < div_y_; ++y) { 354 | ofMesh mesh; 355 | mesh.setMode(OF_PRIMITIVE_LINE_STRIP); 356 | for(int x = 0; x < div_x_; ++x) { 357 | mesh.addVertex(mesh_[getIndex(x,y)].point()); 358 | } 359 | mesh.draw(); 360 | } 361 | for(int x = 0; x < div_x_; ++x) { 362 | ofMesh mesh; 363 | mesh.setMode(OF_PRIMITIVE_LINE_STRIP); 364 | for(int y = 0; y < div_y_; ++y) { 365 | mesh.addVertex(mesh_[getIndex(x,y)].point()); 366 | } 367 | mesh.draw(); 368 | } 369 | } 370 | void Mesh::drawDetailedWireframe() const 371 | { 372 | if(child_mesh_resolution_ > 1) { 373 | for(int x = 0; x < div_x_-1; ++x) { 374 | for(int y = 0; y < div_y_-1; ++y) { 375 | child_meshes_[x][y].drawWireframe(); 376 | } 377 | } 378 | } 379 | else { 380 | drawWireframe(); 381 | } 382 | } 383 | 384 | void Mesh::refreshChildMeshes() 385 | { 386 | child_meshes_.resize(div_x_-1); 387 | for(int x = 0; x < div_x_-1; ++x) { 388 | child_meshes_[x].resize(div_y_-1); 389 | for(int y = 0; y < div_y_-1; ++y) { 390 | child_meshes_[x][y] = makeChildMesh(x, y, child_mesh_resolution_); 391 | } 392 | } 393 | } 394 | 395 | -------------------------------------------------------------------------------- /src/ofxMeshWarpController.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxMeshWarpController.h" 2 | #include "ofGraphics.h" 3 | #include "glm/vec3.hpp" 4 | 5 | using namespace ofx::MeshWarp; 6 | using namespace ofx::MeshWarp::Editor; 7 | using namespace std; 8 | 9 | ControllerBase::ControllerBase() 10 | { 11 | // enable(); 12 | } 13 | ControllerBase::~ControllerBase() 14 | { 15 | disable(); 16 | } 17 | void ControllerBase::enable() 18 | { 19 | if(!is_enabled_) { 20 | ofRegisterMouseEvents(this); 21 | ofRegisterKeyEvents(this); 22 | is_enabled_ = true; 23 | } 24 | } 25 | void ControllerBase::disable() 26 | { 27 | if(is_enabled_) { 28 | ofUnregisterMouseEvents(this); 29 | ofUnregisterKeyEvents(this); 30 | is_enabled_ = false; 31 | clearOperation(); 32 | } 33 | } 34 | void ControllerBase::add(shared_ptr mesh) 35 | { 36 | meshes_.insert(mesh); 37 | } 38 | void ControllerBase::clear() 39 | { 40 | clearOperation(); 41 | meshes_.clear(); 42 | } 43 | void ControllerBase::draw() const 44 | { 45 | ofPushMatrix(); 46 | ofTranslate(translation_); 47 | ofScale(scale_, scale_); 48 | ofTranslate(-anchor_point_); 49 | for(auto &mesh : meshes_) { 50 | mesh->drawWireframe(); 51 | } 52 | drawCustom(); 53 | ofPopMatrix(); 54 | } 55 | void ControllerBase::drawFace() const 56 | { 57 | ofPushMatrix(); 58 | ofTranslate(translation_); 59 | ofScale(scale_, scale_); 60 | ofTranslate(-anchor_point_); 61 | for(auto &mesh : meshes_) { 62 | mesh->drawMesh(); 63 | } 64 | ofPopMatrix(); 65 | } 66 | // ========== 67 | void PointController::clearOperation() 68 | { 69 | mouse_op_.hover = nullptr; 70 | mouse_op_.inside_rect.clear(); 71 | mouse_op_.edit.clear(); 72 | selected_.clear(); 73 | mouse_op_.pressed_state = MouseOperation::STATE_NONE; 74 | } 75 | void PointController::drawCustom() const 76 | { 77 | auto drawCircle = [&](MeshPoint* p, float size_add=0) { 78 | float size = point_size_*(p->isNode()?1:0.5f)+size_add; 79 | ofDrawCircle(p->point(), size/scale_); 80 | }; 81 | ofPushStyle(); 82 | ofSetColor(ofColor::green); 83 | ofNoFill(); 84 | for(auto &mesh : meshes_) { 85 | auto points = mesh->getPoints(); 86 | for(auto &p : points) { 87 | drawCircle(p); 88 | } 89 | } 90 | ofSetColor(ofColor::green); 91 | ofFill(); 92 | if(mouse_op_.hover) { 93 | drawCircle(mouse_op_.hover, 2); 94 | } 95 | for(auto &p : mouse_op_.inside_rect) { 96 | drawCircle(p, 2); 97 | } 98 | ofSetColor(ofColor::red); 99 | ofFill(); 100 | for(auto &p : selected_) { 101 | drawCircle(p); 102 | } 103 | for(auto &p : mouse_op_.edit) { 104 | drawCircle(p.first); 105 | } 106 | if(isMakingRect()) { 107 | ofFill(); 108 | ofSetColor(ofColor::white, 128); 109 | ofDrawRectangle(ofRectangle(mouse_op_.pressed_pos, mouse_op_.pos)); 110 | } 111 | ofPopStyle(); 112 | } 113 | 114 | bool PointController::isEditing() const 115 | { 116 | return mouse_op_.hover!=nullptr || isGrabbing() || isMakingRect(); 117 | } 118 | void PointController::mousePressed(ofMouseEventArgs &args) 119 | { 120 | glm::vec2 local = screenToLocal(args); 121 | mouse_op_.pressed_pos = local; 122 | mouse_op_.pressed_state = MouseOperation::STATE_NONE; 123 | switch(args.button) { 124 | case OF_MOUSE_BUTTON_LEFT: 125 | if(mouse_op_.hover) { 126 | mouse_op_.pressed_state = MouseOperation::STATE_GRABBING; 127 | } 128 | else { 129 | mouse_op_.pressed_state = MouseOperation::STATE_MAKING_RECT; 130 | } 131 | break; 132 | case OF_MOUSE_BUTTON_MIDDLE: 133 | if(mouse_op_.hover) { 134 | mouse_op_.pressed_state = MouseOperation::STATE_GRABBING; 135 | } 136 | break; 137 | } 138 | switch(mouse_op_.pressed_state) { 139 | case MouseOperation::STATE_GRABBING: { 140 | const auto &it = selected_.insert(mouse_op_.hover); 141 | if(it.second) { 142 | if(!isAlternative() && !isAdditive()) { 143 | selected_.clear(); 144 | selected_.insert(mouse_op_.hover); 145 | } 146 | } 147 | else { 148 | if(isAlternative()) { 149 | selected_.erase(mouse_op_.hover); 150 | mouse_op_.pressed_state = MouseOperation::STATE_NONE; 151 | } 152 | } 153 | if(isToggleNode()) { 154 | bool set = !mouse_op_.hover->isNode(); 155 | mouse_op_.hover->setNodal(set); 156 | for(auto &p : selected_) { 157 | p->setNodal(set); 158 | } 159 | mouse_op_.pressed_state = MouseOperation::STATE_NONE; 160 | for(auto &m : meshes_) { 161 | m->setDirty(); 162 | } 163 | } 164 | else if(isGrabbing()) { 165 | for(auto &p : selected_) { 166 | mouse_op_.edit.push_back(p); 167 | } 168 | mouse_op_.hover = nullptr; 169 | } 170 | } break; 171 | default: 172 | break; 173 | } 174 | } 175 | void PointController::mouseReleased(ofMouseEventArgs &args) 176 | { 177 | glm::vec2 local = screenToLocal(args); 178 | if(isMakingRect()) { 179 | if(!isAlternative() && !isAdditive()) { 180 | selected_.clear(); 181 | } 182 | for(auto &p : mouse_op_.inside_rect) { 183 | const auto &it = selected_.insert(p); 184 | if(isAlternative() && !it.second) { 185 | selected_.erase(it.first); 186 | } 187 | } 188 | mouse_op_.inside_rect.clear(); 189 | } 190 | else { 191 | mouse_op_.edit.clear(); 192 | } 193 | mouse_op_.pressed_state = MouseOperation::STATE_NONE; 194 | mouse_op_.hover = getHit(local); 195 | } 196 | void PointController::mouseMoved(ofMouseEventArgs &args) 197 | { 198 | glm::vec2 local = screenToLocal(args); 199 | mouse_op_.pos = local; 200 | mouse_op_.hover = getHit(local); 201 | } 202 | MeshPoint* PointController::getHit(const glm::vec2 &test) const 203 | { 204 | for(auto &mesh : meshes_) { 205 | MeshHelper m(mesh.get()); 206 | if(MeshPoint *hover = m.getHit(test, point_size_/scale_)) { 207 | return hover; 208 | } 209 | } 210 | return nullptr; 211 | } 212 | 213 | void PointController::mouseDragged(ofMouseEventArgs &args) 214 | { 215 | glm::vec2 local = screenToLocal(args); 216 | mouse_op_.pos = local; 217 | if(isMakingRect()) { 218 | mouse_op_.inside_rect.clear(); 219 | ofRectangle rect(mouse_op_.pressed_pos, local); 220 | for(auto &mesh : meshes_) { 221 | const auto &hit = MeshHelper(mesh.get()).getHit(rect); 222 | mouse_op_.inside_rect.insert(end(mouse_op_.inside_rect), begin(hit), end(hit)); 223 | } 224 | } 225 | else if(isGrabbing()) { 226 | glm::vec2 delta = local-mouse_op_.pressed_pos; 227 | if(isSlide()) { 228 | delta.x = abs(delta.x)isNode()) { 234 | if(isEditVertex()) { 235 | work.setVertexMove(delta); 236 | work.resetCoord(); 237 | } 238 | if(isEditCoord()) { 239 | work.setCoordMove(delta/screen_to_coord_); 240 | work.resetVertex(); 241 | } 242 | moved_any = true; 243 | } 244 | } 245 | if(moved_any) { 246 | for(auto &m : meshes_) { 247 | m->setDirty(); 248 | } 249 | } 250 | } 251 | } 252 | void PointController::mouseScrolled(ofMouseEventArgs &args) 253 | { 254 | float delta = args.scrollY*scroll_to_alpha_; 255 | bool moved_any = false; 256 | for(auto &p : selected_) { 257 | if(p->isNode()) { 258 | float alpha = ofClamp(p->alpha()+delta, 0, ofFloatColor::limit()); 259 | PointHelper(p).setAlpha(alpha); 260 | moved_any = true; 261 | } 262 | } 263 | if(moved_any) { 264 | for(auto &m : meshes_) { 265 | m->setDirty(); 266 | } 267 | } 268 | } 269 | void PointController::mouseEntered(ofMouseEventArgs &args) 270 | { 271 | } 272 | void PointController::mouseExited(ofMouseEventArgs &args) 273 | { 274 | } 275 | void PointController::keyPressed(ofKeyEventArgs &args) 276 | { 277 | glm::vec2 delta; 278 | switch(args.key) { 279 | case OF_KEY_UP: delta = glm::vec2(0,-1)/scale_; break; 280 | case OF_KEY_DOWN: delta = glm::vec2(0, 1)/scale_; break; 281 | case OF_KEY_LEFT: delta = glm::vec2(-1,0)/scale_; break; 282 | case OF_KEY_RIGHT: delta = glm::vec2(1, 0)/scale_; break; 283 | } 284 | if(glm::length2(delta) > 0) { 285 | bool moved_any = false; 286 | for(auto &p : selected_) { 287 | if(p->isNode()) { 288 | if(isEditVertex()) { 289 | PointHelper(p).moveVertex(delta*(isArrowKeyJump()?10:1)); 290 | } 291 | if(isEditCoord()){ 292 | PointHelper(p).moveCoord(delta*(isArrowKeyJump()?10:1)/screen_to_coord_); 293 | } 294 | moved_any = true; 295 | } 296 | } 297 | if(moved_any) { 298 | for(auto &m : meshes_) { 299 | m->setDirty(); 300 | } 301 | } 302 | mouse_op_.hover = getHit(mouse_op_.pos); 303 | } 304 | } 305 | void PointController::keyReleased(ofKeyEventArgs &args) 306 | { 307 | } 308 | 309 | // ========== 310 | void DivideController::clearOperation() 311 | { 312 | hit_info_ = HitInfo(); 313 | } 314 | void DivideController::drawCustom() const 315 | { 316 | for(auto &mesh : meshes_) { 317 | mesh->drawWireframe(); 318 | } 319 | if(hit_info_.mesh) { 320 | const auto &points = hit_info_.mesh->getPoints(); 321 | ofMesh mesh; 322 | mesh.setMode(OF_PRIMITIVE_LINE_STRIP); 323 | ofPushStyle(); 324 | if(isDivide()) { 325 | if(hit_info_.isLineX()) { 326 | const auto &points0 = MeshHelper(hit_info_.mesh).getColPoints(hit_info_.line_index_0); 327 | const auto &points1 = MeshHelper(hit_info_.mesh).getColPoints(hit_info_.line_index_1); 328 | assert(points0.size() == points1.size()); 329 | ofSetColor(ofColor::green); 330 | for(size_t i = 0, num = points0.size(); i < num; ++i) { 331 | glm::vec3 p = glm::mix(points0[i]->point(), points1[i]->point(), hit_info_.pos_intersection); 332 | mesh.addVertex(p); 333 | } 334 | glEnd(); 335 | } 336 | if(hit_info_.isLineY()) { 337 | const auto &points0 = MeshHelper(hit_info_.mesh).getRowPoints(hit_info_.line_index_0); 338 | const auto &points1 = MeshHelper(hit_info_.mesh).getRowPoints(hit_info_.line_index_1); 339 | assert(points0.size() == points1.size()); 340 | ofSetColor(ofColor::green); 341 | for(size_t i = 0, num = points0.size(); i < num; ++i) { 342 | glm::vec3 p = glm::mix(points0[i]->point(), points1[i]->point(), hit_info_.pos_intersection); 343 | mesh.addVertex(p); 344 | } 345 | } 346 | } 347 | if(isReduce()) { 348 | if(hit_info_.isLineX()) { 349 | const auto &points = MeshHelper(hit_info_.mesh).getRowPoints(hit_info_.line_index_0); 350 | ofSetColor(ofColor::red); 351 | for(auto &p : points) { 352 | mesh.addVertex(p->point()); 353 | } 354 | } 355 | if(hit_info_.isLineY()) { 356 | const auto &points = MeshHelper(hit_info_.mesh).getColPoints(hit_info_.line_index_0); 357 | ofSetColor(ofColor::red); 358 | for(auto &p : points) { 359 | mesh.addVertex(p->point()); 360 | } 361 | } 362 | } 363 | if(mesh.getNumVertices() > 0) { 364 | mesh.draw(); 365 | } 366 | ofPopStyle(); 367 | } 368 | } 369 | 370 | bool DivideController::isEditing() const 371 | { 372 | return hit_info_.isLine(); 373 | } 374 | 375 | void DivideController::mousePressed(ofMouseEventArgs &args) 376 | { 377 | glm::vec2 local = screenToLocal(args); 378 | bool dirty = false; 379 | if(isDivide()) { 380 | if(hit_info_.isLineX()) { 381 | hit_info_.mesh->divideCol(hit_info_.line_index_0%hit_info_.mesh->getDivX(), hit_info_.pos_intersection); 382 | dirty = true; 383 | } 384 | if(hit_info_.isLineY()) { 385 | hit_info_.mesh->divideRow(hit_info_.line_index_0/hit_info_.mesh->getDivX(), hit_info_.pos_intersection); 386 | dirty = true; 387 | } 388 | } 389 | if(isReduce()) { 390 | if(hit_info_.isLineX()) { 391 | hit_info_.mesh->reduceRow(hit_info_.line_index_0/hit_info_.mesh->getDivX()); 392 | dirty = true; 393 | } 394 | if(hit_info_.isLineY()) { 395 | hit_info_.mesh->reduceCol(hit_info_.line_index_0%hit_info_.mesh->getDivX()); 396 | dirty = true; 397 | } 398 | } 399 | if(dirty) { 400 | hit_info_.mesh->setDirty(); 401 | hit_info_ = getHitInfo(local); 402 | } 403 | } 404 | void DivideController::mouseReleased(ofMouseEventArgs &args) 405 | { 406 | } 407 | void DivideController::mouseMoved(ofMouseEventArgs &args) 408 | { 409 | glm::vec2 local = screenToLocal(args); 410 | hit_info_ = getHitInfo(local); 411 | } 412 | void DivideController::mouseDragged(ofMouseEventArgs &args) 413 | { 414 | } 415 | void DivideController::mouseScrolled(ofMouseEventArgs &args) 416 | { 417 | } 418 | void DivideController::mouseEntered(ofMouseEventArgs &args) 419 | { 420 | } 421 | void DivideController::mouseExited(ofMouseEventArgs &args) 422 | { 423 | } 424 | void DivideController::keyPressed(ofKeyEventArgs &args) 425 | { 426 | } 427 | void DivideController::keyReleased(ofKeyEventArgs &args) 428 | { 429 | } 430 | DivideController::HitInfo DivideController::getHitInfo(const glm::vec2 &test) const 431 | { 432 | HitInfo info; 433 | bool is_hit = false; 434 | for(auto &m : meshes_) { 435 | const auto &points = m->getPoints(); 436 | int div_x = m->getDivX(); 437 | int div_y = m->getDivY(); 438 | for(int y = 0; y < div_y-1; ++y) { 439 | for(int x = 0; x < div_x-1; ++x) { 440 | int index = y*div_x+x; 441 | if(MeshHelper(m.get()).isHitBox(test, index)) { 442 | info.mesh = m.get(); 443 | info.area_index = index; 444 | is_hit = true; 445 | } 446 | } 447 | } 448 | } 449 | if(is_hit) { 450 | const auto &indices = MeshHelper(info.mesh).getBoxIndices(info.area_index); 451 | assert(indices.size() == 4); 452 | auto check = [this,&info,&test](int index0, int index1) { 453 | if(MeshHelper(info.mesh).isHitLine(test, index0, index1, line_hit_size_/scale_, info.pos_intersection)) { 454 | info.line_index_0 = index0; info.line_index_1 = index1; 455 | return true; 456 | } 457 | return false; 458 | }; 459 | if(check(indices[0], indices[1])) return info; 460 | if(check(indices[0], indices[2])) return info; 461 | if(check(indices[1], indices[3])) return info; 462 | if(check(indices[2], indices[3])) return info; 463 | } 464 | return info; 465 | } 466 | 467 | 468 | // ========== 469 | MeshPoint* MeshHelper::getHit(const glm::vec2 &test, float room, int index) const 470 | { 471 | const vector &points = target_->getPoints(); 472 | for(auto &p : points) { 473 | if(index < 0) { 474 | return nullptr; 475 | } 476 | if(glm::distance2(glm::vec3(test,0), p->point()) < room*room && index-- == 0) { 477 | return p; 478 | } 479 | } 480 | return nullptr; 481 | } 482 | vector MeshHelper::getHit(const ofRectangle &test) const 483 | { 484 | vector ret; 485 | const vector &points = target_->getPoints(); 486 | for(auto &p : points) { 487 | if(test.inside(p->point())) { 488 | ret.push_back(p); 489 | } 490 | } 491 | return ret; 492 | } 493 | vector MeshHelper::getBox(int top_left_index) const 494 | { 495 | vector ret; 496 | auto indices = getBoxIndices(top_left_index); 497 | const auto &points = target_->getPoints(); 498 | for(auto i : indices) { 499 | ret.emplace_back(points[i]); 500 | } 501 | return ret; 502 | } 503 | vector MeshHelper::getBoxIndices(int top_left_index) const 504 | { 505 | vector ret;; 506 | if(top_left_index+1 % target_->getDivX()+1 == 0) { 507 | ofLogWarning(__FILE__, "cannot get box with edge index(right)"); 508 | return ret; 509 | } 510 | if(top_left_index >= (target_->getDivX()+1)*target_->getDivY()) { 511 | ofLogWarning(__FILE__, "cannot get box with edge index(bottom)"); 512 | return ret; 513 | } 514 | ret.emplace_back(top_left_index); 515 | ret.emplace_back(top_left_index+1); 516 | ret.emplace_back(top_left_index+target_->getDivX()); 517 | ret.emplace_back(top_left_index+target_->getDivX()+1); 518 | return ret; 519 | } 520 | bool MeshHelper::isHitBox(const glm::vec2 &test, int top_left_index) const 521 | { 522 | const auto &box = getBox(top_left_index); 523 | assert(box.size() == 4); 524 | ofPolyline poly; 525 | poly.addVertex(box[0]->point()); 526 | poly.addVertex(box[1]->point()); 527 | poly.addVertex(box[3]->point()); 528 | poly.addVertex(box[2]->point()); 529 | return poly.inside(test.x, test.y); 530 | } 531 | bool MeshHelper::isHitLine(const glm::vec2 &test, int index0, int index1, float room, float &pos) const 532 | { 533 | const auto &points = target_->getPoints(); 534 | const glm::vec3 &pivot = points[index0]->point(); 535 | const glm::vec3 &anchor = points[index1]->point(); 536 | float angle = atan2((test-pivot).y, (test-pivot).x)-atan2((anchor-pivot).y, (anchor-pivot).x); 537 | glm::vec3 alternative = glm::rotate(glm::vec3(test,0)-pivot, -angle*2, glm::vec3(0,0,1)) + pivot; 538 | glm::vec3 intersection = (glm::vec3(test,0)+alternative)/2.f; 539 | if(pivot.x == anchor.x) { 540 | pos = ofMap(intersection.y, pivot.y, anchor.y, 0, 1, false); 541 | } 542 | else { 543 | pos = ofMap(intersection.x, pivot.x, anchor.x, 0, 1, false); 544 | } 545 | if(0<=pos&&pos<=1) { 546 | return glm::distance2(glm::vec3(test,0), intersection) < room*room; 547 | } 548 | return false; 549 | } 550 | 551 | vector MeshHelper::getColPoints(int point_index) const 552 | { 553 | vector ret; 554 | int div_x = target_->getDivX(); 555 | const auto &points = target_->getPoints(); 556 | for(size_t index = point_index%div_x, num = points.size(); index < num; index += div_x) { 557 | ret.emplace_back(points[index]); 558 | } 559 | return ret; 560 | } 561 | vector MeshHelper::getRowPoints(int point_index) const 562 | { 563 | vector ret; 564 | int div_x = target_->getDivX(); 565 | int start = (point_index/div_x)*div_x; 566 | const auto &points = target_->getPoints(); 567 | for(int index = start; index < start+div_x; ++index) { 568 | ret.emplace_back(points[index]); 569 | } 570 | return ret; 571 | } 572 | -------------------------------------------------------------------------------- /example/example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 26E644D906B096668B202176 /* ofxMeshWarpIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FB422832F3529653C73969F /* ofxMeshWarpIO.cpp */; }; 11 | 495E638BFCE697B5EBA4F9AF /* ofxMeshWarpManagedController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 96F5A2E6283D0BECD5078F6A /* ofxMeshWarpManagedController.cpp */; }; 12 | 96C4B5F7DFEE9AF547996035 /* ofxMeshWarpController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F3E52D9101DBB3C5FC82AA7 /* ofxMeshWarpController.cpp */; }; 13 | C3670937900D24095EF91E8F /* ofxMeshWarp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2833749CEB2CD821978836F4 /* ofxMeshWarp.cpp */; }; 14 | E4328149138ABC9F0047C5CB /* openFrameworksDebug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E4328148138ABC890047C5CB /* openFrameworksDebug.a */; }; 15 | E4B69E200A3A1BDC003C02F2 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4B69E1D0A3A1BDC003C02F2 /* main.cpp */; }; 16 | E4B69E210A3A1BDC003C02F2 /* ofApp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4B69E1E0A3A1BDC003C02F2 /* ofApp.cpp */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | E4328147138ABC890047C5CB /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; 23 | proxyType = 2; 24 | remoteGlobalIDString = E4B27C1510CBEB8E00536013; 25 | remoteInfo = openFrameworks; 26 | }; 27 | E4EEB9AB138B136A00A80321 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; 30 | proxyType = 1; 31 | remoteGlobalIDString = E4B27C1410CBEB8E00536013; 32 | remoteInfo = openFrameworks; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXCopyFilesBuildPhase section */ 37 | E4C2427710CC5ABF004149E2 /* CopyFiles */ = { 38 | isa = PBXCopyFilesBuildPhase; 39 | buildActionMask = 2147483647; 40 | dstPath = ""; 41 | dstSubfolderSpec = 10; 42 | files = ( 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXCopyFilesBuildPhase section */ 47 | 48 | /* Begin PBXFileReference section */ 49 | 1F3E52D9101DBB3C5FC82AA7 /* ofxMeshWarpController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ofxMeshWarpController.cpp; path = ../../../addons/ofxMeshWarp/src/ofxMeshWarpController.cpp; sourceTree = SOURCE_ROOT; }; 50 | 1FB422832F3529653C73969F /* ofxMeshWarpIO.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ofxMeshWarpIO.cpp; path = ../../../addons/ofxMeshWarp/src/ofxMeshWarpIO.cpp; sourceTree = SOURCE_ROOT; }; 51 | 2833749CEB2CD821978836F4 /* ofxMeshWarp.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ofxMeshWarp.cpp; path = ../../../addons/ofxMeshWarp/src/ofxMeshWarp.cpp; sourceTree = SOURCE_ROOT; }; 52 | 5AC8E8B8114B873122F9E155 /* ofxMeshWarpController.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ofxMeshWarpController.h; path = ../../../addons/ofxMeshWarp/src/ofxMeshWarpController.h; sourceTree = SOURCE_ROOT; }; 53 | 79D11F0DBD55DA42C3B11349 /* ofxMeshWarpIO.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ofxMeshWarpIO.h; path = ../../../addons/ofxMeshWarp/src/ofxMeshWarpIO.h; sourceTree = SOURCE_ROOT; }; 54 | 8B1E350E285B120E0743B2F6 /* ofxMeshWarp.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ofxMeshWarp.h; path = ../../../addons/ofxMeshWarp/src/ofxMeshWarp.h; sourceTree = SOURCE_ROOT; }; 55 | 96F5A2E6283D0BECD5078F6A /* ofxMeshWarpManagedController.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ofxMeshWarpManagedController.cpp; path = ../../../addons/ofxMeshWarp/src/utils/ofxMeshWarpManagedController.cpp; sourceTree = SOURCE_ROOT; }; 56 | AFD9861C6BE5D89A568CB54F /* ofxMeshWarpManagedController.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ofxMeshWarpManagedController.h; path = ../../../addons/ofxMeshWarp/src/utils/ofxMeshWarpManagedController.h; sourceTree = SOURCE_ROOT; }; 57 | E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = openFrameworksLib.xcodeproj; path = ../../../libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj; sourceTree = SOURCE_ROOT; }; 58 | E4B69B5B0A3A1756003C02F2 /* exampleDebug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = exampleDebug.app; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | E4B69E1D0A3A1BDC003C02F2 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = src/main.cpp; sourceTree = SOURCE_ROOT; }; 60 | E4B69E1E0A3A1BDC003C02F2 /* ofApp.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ofApp.cpp; path = src/ofApp.cpp; sourceTree = SOURCE_ROOT; }; 61 | E4B69E1F0A3A1BDC003C02F2 /* ofApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ofApp.h; path = src/ofApp.h; sourceTree = SOURCE_ROOT; }; 62 | E4B6FCAD0C3E899E008CF71C /* openFrameworks-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "openFrameworks-Info.plist"; sourceTree = ""; }; 63 | E4EB691F138AFCF100A09F29 /* CoreOF.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = CoreOF.xcconfig; path = ../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig; sourceTree = SOURCE_ROOT; }; 64 | E4EB6923138AFD0F00A09F29 /* Project.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Project.xcconfig; sourceTree = ""; }; 65 | /* End PBXFileReference section */ 66 | 67 | /* Begin PBXFrameworksBuildPhase section */ 68 | E4B69B590A3A1756003C02F2 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | E4328149138ABC9F0047C5CB /* openFrameworksDebug.a in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 0EC69C5488FE32328D061788 /* ofxMeshWarp */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 5E921ED3A52D6154CEB1DEC0 /* src */, 83 | ); 84 | name = ofxMeshWarp; 85 | sourceTree = ""; 86 | }; 87 | 5E921ED3A52D6154CEB1DEC0 /* src */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 1FB422832F3529653C73969F /* ofxMeshWarpIO.cpp */, 91 | FDFE70AFF13C04452EC28D6A /* utils */, 92 | 2833749CEB2CD821978836F4 /* ofxMeshWarp.cpp */, 93 | 5AC8E8B8114B873122F9E155 /* ofxMeshWarpController.h */, 94 | 79D11F0DBD55DA42C3B11349 /* ofxMeshWarpIO.h */, 95 | 1F3E52D9101DBB3C5FC82AA7 /* ofxMeshWarpController.cpp */, 96 | 8B1E350E285B120E0743B2F6 /* ofxMeshWarp.h */, 97 | ); 98 | name = src; 99 | sourceTree = ""; 100 | }; 101 | 6948EE371B920CB800B5AC1A /* local_addons */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | ); 105 | name = local_addons; 106 | sourceTree = ""; 107 | }; 108 | BB4B014C10F69532006C3DED /* addons */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 0EC69C5488FE32328D061788 /* ofxMeshWarp */, 112 | ); 113 | name = addons; 114 | sourceTree = ""; 115 | }; 116 | E4328144138ABC890047C5CB /* Products */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | E4328148138ABC890047C5CB /* openFrameworksDebug.a */, 120 | ); 121 | name = Products; 122 | sourceTree = ""; 123 | }; 124 | E4B69B4A0A3A1720003C02F2 = { 125 | isa = PBXGroup; 126 | children = ( 127 | E4B6FCAD0C3E899E008CF71C /* openFrameworks-Info.plist */, 128 | E4EB6923138AFD0F00A09F29 /* Project.xcconfig */, 129 | E4B69E1C0A3A1BDC003C02F2 /* src */, 130 | E4EEC9E9138DF44700A80321 /* openFrameworks */, 131 | BB4B014C10F69532006C3DED /* addons */, 132 | 6948EE371B920CB800B5AC1A /* local_addons */, 133 | E4B69B5B0A3A1756003C02F2 /* exampleDebug.app */, 134 | ); 135 | sourceTree = ""; 136 | }; 137 | E4B69E1C0A3A1BDC003C02F2 /* src */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | E4B69E1D0A3A1BDC003C02F2 /* main.cpp */, 141 | E4B69E1E0A3A1BDC003C02F2 /* ofApp.cpp */, 142 | E4B69E1F0A3A1BDC003C02F2 /* ofApp.h */, 143 | ); 144 | path = src; 145 | sourceTree = SOURCE_ROOT; 146 | }; 147 | E4EEC9E9138DF44700A80321 /* openFrameworks */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | E4EB691F138AFCF100A09F29 /* CoreOF.xcconfig */, 151 | E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */, 152 | ); 153 | name = openFrameworks; 154 | sourceTree = ""; 155 | }; 156 | FDFE70AFF13C04452EC28D6A /* utils */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | AFD9861C6BE5D89A568CB54F /* ofxMeshWarpManagedController.h */, 160 | 96F5A2E6283D0BECD5078F6A /* ofxMeshWarpManagedController.cpp */, 161 | ); 162 | name = utils; 163 | sourceTree = ""; 164 | }; 165 | /* End PBXGroup section */ 166 | 167 | /* Begin PBXNativeTarget section */ 168 | E4B69B5A0A3A1756003C02F2 /* example */ = { 169 | isa = PBXNativeTarget; 170 | buildConfigurationList = E4B69B5F0A3A1757003C02F2 /* Build configuration list for PBXNativeTarget "example" */; 171 | buildPhases = ( 172 | E4B69B580A3A1756003C02F2 /* Sources */, 173 | E4B69B590A3A1756003C02F2 /* Frameworks */, 174 | E4B6FFFD0C3F9AB9008CF71C /* ShellScript */, 175 | E4C2427710CC5ABF004149E2 /* CopyFiles */, 176 | 8466F1851C04CA0E00918B1C /* ShellScript */, 177 | ); 178 | buildRules = ( 179 | ); 180 | dependencies = ( 181 | E4EEB9AC138B136A00A80321 /* PBXTargetDependency */, 182 | ); 183 | name = example; 184 | productName = myOFApp; 185 | productReference = E4B69B5B0A3A1756003C02F2 /* exampleDebug.app */; 186 | productType = "com.apple.product-type.application"; 187 | }; 188 | /* End PBXNativeTarget section */ 189 | 190 | /* Begin PBXProject section */ 191 | E4B69B4C0A3A1720003C02F2 /* Project object */ = { 192 | isa = PBXProject; 193 | attributes = { 194 | LastUpgradeCheck = 0930; 195 | }; 196 | buildConfigurationList = E4B69B4D0A3A1720003C02F2 /* Build configuration list for PBXProject "example" */; 197 | compatibilityVersion = "Xcode 3.2"; 198 | developmentRegion = English; 199 | hasScannedForEncodings = 0; 200 | knownRegions = ( 201 | English, 202 | Japanese, 203 | French, 204 | German, 205 | ); 206 | mainGroup = E4B69B4A0A3A1720003C02F2; 207 | productRefGroup = E4B69B4A0A3A1720003C02F2; 208 | projectDirPath = ""; 209 | projectReferences = ( 210 | { 211 | ProductGroup = E4328144138ABC890047C5CB /* Products */; 212 | ProjectRef = E4328143138ABC890047C5CB /* openFrameworksLib.xcodeproj */; 213 | }, 214 | ); 215 | projectRoot = ""; 216 | targets = ( 217 | E4B69B5A0A3A1756003C02F2 /* example */, 218 | ); 219 | }; 220 | /* End PBXProject section */ 221 | 222 | /* Begin PBXReferenceProxy section */ 223 | E4328148138ABC890047C5CB /* openFrameworksDebug.a */ = { 224 | isa = PBXReferenceProxy; 225 | fileType = archive.ar; 226 | path = openFrameworksDebug.a; 227 | remoteRef = E4328147138ABC890047C5CB /* PBXContainerItemProxy */; 228 | sourceTree = BUILT_PRODUCTS_DIR; 229 | }; 230 | /* End PBXReferenceProxy section */ 231 | 232 | /* Begin PBXShellScriptBuildPhase section */ 233 | 8466F1851C04CA0E00918B1C /* ShellScript */ = { 234 | isa = PBXShellScriptBuildPhase; 235 | buildActionMask = 12; 236 | files = ( 237 | ); 238 | inputPaths = ( 239 | ); 240 | outputPaths = ( 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | shellPath = /bin/sh; 244 | shellScript = "echo \"$GCC_PREPROCESSOR_DEFINITIONS\";\nAPPSTORE=`expr \"$GCC_PREPROCESSOR_DEFINITIONS\" : \".*APPSTORE=\\([0-9]*\\)\"`\nif [ -z \"$APPSTORE\" ] ; then\necho \"Note: Not copying bin/data to App Package or doing App Code signing. Use AppStore target for AppStore distribution\";\nelse\n# Copy bin/data into App/Resources\nrsync -avz --exclude='.DS_Store' \"${SRCROOT}/bin/data/\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/data/\"\n\n# ---- Code Sign App Package ----\n\n# WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY!\n\n# Verify that $CODE_SIGN_IDENTITY is set\nif [ -z \"${CODE_SIGN_IDENTITY}\" ] ; then\necho \"CODE_SIGN_IDENTITY needs to be set for framework code-signing\"\nexit 0\nfi\n\nif [ -z \"${CODE_SIGN_ENTITLEMENTS}\" ] ; then\necho \"CODE_SIGN_ENTITLEMENTS needs to be set for framework code-signing!\"\n\nif [ \"${CONFIGURATION}\" = \"Release\" ] ; then\nexit 1\nelse\n# Code-signing is optional for non-release builds.\nexit 0\nfi\nfi\n\nITEMS=\"\"\n\nFRAMEWORKS_DIR=\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}\"\necho \"$FRAMEWORKS_DIR\"\nif [ -d \"$FRAMEWORKS_DIR\" ] ; then\nFRAMEWORKS=$(find \"${FRAMEWORKS_DIR}\" -depth -type d -name \"*.framework\" -or -name \"*.dylib\" -or -name \"*.bundle\" | sed -e \"s/\\(.*framework\\)/\\1\\/Versions\\/A\\//\")\nRESULT=$?\nif [[ $RESULT != 0 ]] ; then\nexit 1\nfi\n\nITEMS=\"${FRAMEWORKS}\"\nfi\n\nLOGINITEMS_DIR=\"${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Library/LoginItems/\"\nif [ -d \"$LOGINITEMS_DIR\" ] ; then\nLOGINITEMS=$(find \"${LOGINITEMS_DIR}\" -depth -type d -name \"*.app\")\nRESULT=$?\nif [[ $RESULT != 0 ]] ; then\nexit 1\nfi\n\nITEMS=\"${ITEMS}\"$'\\n'\"${LOGINITEMS}\"\nfi\n\n# Prefer the expanded name, if available.\nCODE_SIGN_IDENTITY_FOR_ITEMS=\"${EXPANDED_CODE_SIGN_IDENTITY_NAME}\"\nif [ \"${CODE_SIGN_IDENTITY_FOR_ITEMS}\" = \"\" ] ; then\n# Fall back to old behavior.\nCODE_SIGN_IDENTITY_FOR_ITEMS=\"${CODE_SIGN_IDENTITY}\"\nfi\n\necho \"Identity:\"\necho \"${CODE_SIGN_IDENTITY_FOR_ITEMS}\"\n\necho \"Entitlements:\"\necho \"${CODE_SIGN_ENTITLEMENTS}\"\n\necho \"Found:\"\necho \"${ITEMS}\"\n\n# Change the Internal Field Separator (IFS) so that spaces in paths will not cause problems below.\nSAVED_IFS=$IFS\nIFS=$(echo -en \"\\n\\b\")\n\n# Loop through all items.\nfor ITEM in $ITEMS;\ndo\necho \"Signing '${ITEM}'\"\ncodesign --force --verbose --sign \"${CODE_SIGN_IDENTITY_FOR_ITEMS}\" --entitlements \"${CODE_SIGN_ENTITLEMENTS}\" \"${ITEM}\"\nRESULT=$?\nif [[ $RESULT != 0 ]] ; then\necho \"Failed to sign '${ITEM}'.\"\nIFS=$SAVED_IFS\nexit 1\nfi\ndone\n\n# Restore $IFS.\nIFS=$SAVED_IFS\n\nfi\n"; 245 | }; 246 | E4B6FFFD0C3F9AB9008CF71C /* ShellScript */ = { 247 | isa = PBXShellScriptBuildPhase; 248 | buildActionMask = 2147483647; 249 | files = ( 250 | ); 251 | inputPaths = ( 252 | ); 253 | outputPaths = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | shellPath = /bin/sh; 257 | shellScript = "mkdir -p \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/\"\n# Copy default icon file into App/Resources\nrsync -aved \"$ICON_FILE\" \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/\"\n# Copy libfmod and change install directory for fmod to run\nrsync -aved \"$OF_PATH/libs/fmodex/lib/osx/libfmodex.dylib\" \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/\";\ninstall_name_tool -change @executable_path/libfmodex.dylib @executable_path/../Frameworks/libfmodex.dylib \"$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME\";\n\necho \"$GCC_PREPROCESSOR_DEFINITIONS\";\n"; 258 | }; 259 | /* End PBXShellScriptBuildPhase section */ 260 | 261 | /* Begin PBXSourcesBuildPhase section */ 262 | E4B69B580A3A1756003C02F2 /* Sources */ = { 263 | isa = PBXSourcesBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | E4B69E200A3A1BDC003C02F2 /* main.cpp in Sources */, 267 | E4B69E210A3A1BDC003C02F2 /* ofApp.cpp in Sources */, 268 | 26E644D906B096668B202176 /* ofxMeshWarpIO.cpp in Sources */, 269 | 495E638BFCE697B5EBA4F9AF /* ofxMeshWarpManagedController.cpp in Sources */, 270 | C3670937900D24095EF91E8F /* ofxMeshWarp.cpp in Sources */, 271 | 96C4B5F7DFEE9AF547996035 /* ofxMeshWarpController.cpp in Sources */, 272 | ); 273 | runOnlyForDeploymentPostprocessing = 0; 274 | }; 275 | /* End PBXSourcesBuildPhase section */ 276 | 277 | /* Begin PBXTargetDependency section */ 278 | E4EEB9AC138B136A00A80321 /* PBXTargetDependency */ = { 279 | isa = PBXTargetDependency; 280 | name = openFrameworks; 281 | targetProxy = E4EEB9AB138B136A00A80321 /* PBXContainerItemProxy */; 282 | }; 283 | /* End PBXTargetDependency section */ 284 | 285 | /* Begin XCBuildConfiguration section */ 286 | 99FA3DBB1C7456C400CFA0EE /* AppStore */ = { 287 | isa = XCBuildConfiguration; 288 | baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; 289 | buildSettings = { 290 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 291 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 292 | CLANG_WARN_BOOL_CONVERSION = YES; 293 | CLANG_WARN_COMMA = YES; 294 | CLANG_WARN_CONSTANT_CONVERSION = YES; 295 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 296 | CLANG_WARN_EMPTY_BODY = YES; 297 | CLANG_WARN_ENUM_CONVERSION = YES; 298 | CLANG_WARN_INFINITE_RECURSION = YES; 299 | CLANG_WARN_INT_CONVERSION = YES; 300 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 301 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 302 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 303 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 304 | CLANG_WARN_STRICT_PROTOTYPES = YES; 305 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 306 | CLANG_WARN_UNREACHABLE_CODE = YES; 307 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 308 | CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; 309 | COPY_PHASE_STRIP = YES; 310 | DEAD_CODE_STRIPPING = YES; 311 | ENABLE_STRICT_OBJC_MSGSEND = YES; 312 | GCC_AUTO_VECTORIZATION = YES; 313 | GCC_ENABLE_SSE3_EXTENSIONS = YES; 314 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; 315 | GCC_INLINES_ARE_PRIVATE_EXTERN = NO; 316 | GCC_NO_COMMON_BLOCKS = YES; 317 | GCC_OPTIMIZATION_LEVEL = 3; 318 | "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "DISTRIBUTION=1"; 319 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 320 | GCC_UNROLL_LOOPS = YES; 321 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 322 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; 323 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; 324 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 325 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO; 326 | GCC_WARN_UNDECLARED_SELECTOR = YES; 327 | GCC_WARN_UNINITIALIZED_AUTOS = NO; 328 | GCC_WARN_UNUSED_FUNCTION = YES; 329 | GCC_WARN_UNUSED_VALUE = NO; 330 | GCC_WARN_UNUSED_VARIABLE = NO; 331 | HEADER_SEARCH_PATHS = ( 332 | "$(OF_CORE_HEADERS)", 333 | src, 334 | ../../../addons/ofxMeshWarp/src, 335 | ../../../addons/ofxMeshWarp/src/utils, 336 | ); 337 | MACOSX_DEPLOYMENT_TARGET = 10.9; 338 | OTHER_CPLUSPLUSFLAGS = ( 339 | "-D__MACOSX_CORE__", 340 | "-mtune=native", 341 | ); 342 | SDKROOT = macosx; 343 | }; 344 | name = AppStore; 345 | }; 346 | 99FA3DBC1C7456C400CFA0EE /* AppStore */ = { 347 | isa = XCBuildConfiguration; 348 | baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; 349 | buildSettings = { 350 | CLANG_ENABLE_OBJC_WEAK = YES; 351 | COMBINE_HIDPI_IMAGES = YES; 352 | COPY_PHASE_STRIP = YES; 353 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 354 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 355 | GCC_MODEL_TUNING = NONE; 356 | "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "APPSTORE=1"; 357 | HEADER_SEARCH_PATHS = ( 358 | "$(OF_CORE_HEADERS)", 359 | src, 360 | ../../../addons/ofxMeshWarp/src, 361 | ../../../addons/ofxMeshWarp/src/utils, 362 | ); 363 | ICON = "$(ICON_NAME_RELEASE)"; 364 | ICON_FILE = "$(ICON_FILE_PATH)$(ICON)"; 365 | INFOPLIST_FILE = "openFrameworks-Info.plist"; 366 | INSTALL_PATH = /Applications; 367 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 368 | PRODUCT_BUNDLE_IDENTIFIER = cc.openFrameworks.ofapp; 369 | PRODUCT_NAME = "$(TARGET_NAME)"; 370 | WRAPPER_EXTENSION = app; 371 | baseConfigurationReference = E4EB6923138AFD0F00A09F29; 372 | }; 373 | name = AppStore; 374 | }; 375 | E4B69B4E0A3A1720003C02F2 /* Debug */ = { 376 | isa = XCBuildConfiguration; 377 | baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; 378 | buildSettings = { 379 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 380 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 381 | CLANG_WARN_BOOL_CONVERSION = YES; 382 | CLANG_WARN_COMMA = YES; 383 | CLANG_WARN_CONSTANT_CONVERSION = YES; 384 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 385 | CLANG_WARN_EMPTY_BODY = YES; 386 | CLANG_WARN_ENUM_CONVERSION = YES; 387 | CLANG_WARN_INFINITE_RECURSION = YES; 388 | CLANG_WARN_INT_CONVERSION = YES; 389 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 390 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 391 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 392 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 393 | CLANG_WARN_STRICT_PROTOTYPES = YES; 394 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 395 | CLANG_WARN_UNREACHABLE_CODE = YES; 396 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 397 | CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; 398 | COPY_PHASE_STRIP = NO; 399 | DEAD_CODE_STRIPPING = YES; 400 | ENABLE_STRICT_OBJC_MSGSEND = YES; 401 | ENABLE_TESTABILITY = YES; 402 | GCC_AUTO_VECTORIZATION = YES; 403 | GCC_ENABLE_SSE3_EXTENSIONS = YES; 404 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; 405 | GCC_INLINES_ARE_PRIVATE_EXTERN = NO; 406 | GCC_NO_COMMON_BLOCKS = YES; 407 | GCC_OPTIMIZATION_LEVEL = 0; 408 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 409 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 410 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; 411 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; 412 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 413 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO; 414 | GCC_WARN_UNDECLARED_SELECTOR = YES; 415 | GCC_WARN_UNINITIALIZED_AUTOS = NO; 416 | GCC_WARN_UNUSED_FUNCTION = YES; 417 | GCC_WARN_UNUSED_VALUE = NO; 418 | GCC_WARN_UNUSED_VARIABLE = NO; 419 | HEADER_SEARCH_PATHS = ( 420 | "$(OF_CORE_HEADERS)", 421 | src, 422 | ../../../addons/ofxMeshWarp/src, 423 | ../../../addons/ofxMeshWarp/src/utils, 424 | ); 425 | MACOSX_DEPLOYMENT_TARGET = 10.9; 426 | ONLY_ACTIVE_ARCH = YES; 427 | OTHER_CPLUSPLUSFLAGS = ( 428 | "-D__MACOSX_CORE__", 429 | "-mtune=native", 430 | ); 431 | SDKROOT = macosx; 432 | }; 433 | name = Debug; 434 | }; 435 | E4B69B4F0A3A1720003C02F2 /* Release */ = { 436 | isa = XCBuildConfiguration; 437 | baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; 438 | buildSettings = { 439 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 440 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 441 | CLANG_WARN_BOOL_CONVERSION = YES; 442 | CLANG_WARN_COMMA = YES; 443 | CLANG_WARN_CONSTANT_CONVERSION = YES; 444 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INFINITE_RECURSION = YES; 448 | CLANG_WARN_INT_CONVERSION = YES; 449 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 450 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 451 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 452 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 453 | CLANG_WARN_STRICT_PROTOTYPES = YES; 454 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 455 | CLANG_WARN_UNREACHABLE_CODE = YES; 456 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 457 | CONFIGURATION_BUILD_DIR = "$(SRCROOT)/bin/"; 458 | COPY_PHASE_STRIP = YES; 459 | DEAD_CODE_STRIPPING = YES; 460 | ENABLE_STRICT_OBJC_MSGSEND = YES; 461 | GCC_AUTO_VECTORIZATION = YES; 462 | GCC_ENABLE_SSE3_EXTENSIONS = YES; 463 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES; 464 | GCC_INLINES_ARE_PRIVATE_EXTERN = NO; 465 | GCC_NO_COMMON_BLOCKS = YES; 466 | GCC_OPTIMIZATION_LEVEL = 3; 467 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 468 | GCC_UNROLL_LOOPS = YES; 469 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 470 | GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; 471 | GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; 472 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 473 | GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO; 474 | GCC_WARN_UNDECLARED_SELECTOR = YES; 475 | GCC_WARN_UNINITIALIZED_AUTOS = NO; 476 | GCC_WARN_UNUSED_FUNCTION = YES; 477 | GCC_WARN_UNUSED_VALUE = NO; 478 | GCC_WARN_UNUSED_VARIABLE = NO; 479 | HEADER_SEARCH_PATHS = ( 480 | "$(OF_CORE_HEADERS)", 481 | src, 482 | ../../../addons/ofxMeshWarp/src, 483 | ../../../addons/ofxMeshWarp/src/utils, 484 | ); 485 | MACOSX_DEPLOYMENT_TARGET = 10.9; 486 | OTHER_CPLUSPLUSFLAGS = ( 487 | "-D__MACOSX_CORE__", 488 | "-mtune=native", 489 | ); 490 | SDKROOT = macosx; 491 | }; 492 | name = Release; 493 | }; 494 | E4B69B600A3A1757003C02F2 /* Debug */ = { 495 | isa = XCBuildConfiguration; 496 | baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; 497 | buildSettings = { 498 | CLANG_ENABLE_OBJC_WEAK = YES; 499 | COMBINE_HIDPI_IMAGES = YES; 500 | COPY_PHASE_STRIP = NO; 501 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 502 | GCC_DYNAMIC_NO_PIC = NO; 503 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 504 | GCC_MODEL_TUNING = NONE; 505 | HEADER_SEARCH_PATHS = ( 506 | "$(OF_CORE_HEADERS)", 507 | src, 508 | ../../../addons/ofxMeshWarp/src, 509 | ../../../addons/ofxMeshWarp/src/utils, 510 | ); 511 | ICON = "$(ICON_NAME_DEBUG)"; 512 | ICON_FILE = "$(ICON_FILE_PATH)$(ICON)"; 513 | INFOPLIST_FILE = "openFrameworks-Info.plist"; 514 | INSTALL_PATH = /Applications; 515 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 516 | PRODUCT_BUNDLE_IDENTIFIER = cc.openFrameworks.ofapp; 517 | PRODUCT_NAME = "$(TARGET_NAME)Debug"; 518 | WRAPPER_EXTENSION = app; 519 | }; 520 | name = Debug; 521 | }; 522 | E4B69B610A3A1757003C02F2 /* Release */ = { 523 | isa = XCBuildConfiguration; 524 | baseConfigurationReference = E4EB6923138AFD0F00A09F29 /* Project.xcconfig */; 525 | buildSettings = { 526 | CLANG_ENABLE_OBJC_WEAK = YES; 527 | COMBINE_HIDPI_IMAGES = YES; 528 | COPY_PHASE_STRIP = YES; 529 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 530 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 531 | GCC_MODEL_TUNING = NONE; 532 | HEADER_SEARCH_PATHS = ( 533 | "$(OF_CORE_HEADERS)", 534 | src, 535 | ../../../addons/ofxMeshWarp/src, 536 | ../../../addons/ofxMeshWarp/src/utils, 537 | ); 538 | ICON = "$(ICON_NAME_RELEASE)"; 539 | ICON_FILE = "$(ICON_FILE_PATH)$(ICON)"; 540 | INFOPLIST_FILE = "openFrameworks-Info.plist"; 541 | INSTALL_PATH = /Applications; 542 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 543 | PRODUCT_BUNDLE_IDENTIFIER = cc.openFrameworks.ofapp; 544 | PRODUCT_NAME = "$(TARGET_NAME)"; 545 | WRAPPER_EXTENSION = app; 546 | baseConfigurationReference = E4EB6923138AFD0F00A09F29; 547 | }; 548 | name = Release; 549 | }; 550 | /* End XCBuildConfiguration section */ 551 | 552 | /* Begin XCConfigurationList section */ 553 | E4B69B4D0A3A1720003C02F2 /* Build configuration list for PBXProject "example" */ = { 554 | isa = XCConfigurationList; 555 | buildConfigurations = ( 556 | E4B69B4E0A3A1720003C02F2 /* Debug */, 557 | E4B69B4F0A3A1720003C02F2 /* Release */, 558 | 99FA3DBB1C7456C400CFA0EE /* AppStore */, 559 | ); 560 | defaultConfigurationIsVisible = 0; 561 | defaultConfigurationName = Release; 562 | }; 563 | E4B69B5F0A3A1757003C02F2 /* Build configuration list for PBXNativeTarget "example" */ = { 564 | isa = XCConfigurationList; 565 | buildConfigurations = ( 566 | E4B69B600A3A1757003C02F2 /* Debug */, 567 | E4B69B610A3A1757003C02F2 /* Release */, 568 | 99FA3DBC1C7456C400CFA0EE /* AppStore */, 569 | ); 570 | defaultConfigurationIsVisible = 0; 571 | defaultConfigurationName = Release; 572 | }; 573 | /* End XCConfigurationList section */ 574 | }; 575 | rootObject = E4B69B4C0A3A1720003C02F2 /* Project object */; 576 | } 577 | --------------------------------------------------------------------------------