From beb2e1041b9a4d35187358581b3e11952517eccf Mon Sep 17 00:00:00 2001 From: Daito Manabe Date: Sat, 5 Sep 2026 08:39:45 +0900 Subject: [PATCH 1/3] Modernize examples and add geometry and fragment shader studies --- .github/workflows/build.yml | 11 + LICENSES.md | 3 + README.md | 54 ++- docs/images/motion-field.png | Bin 0 -> 229747 bytes docs/images/motion-ribbons.png | Bin 0 -> 74690 bytes docs/shaders.md | 52 +++ .../example-bvh.xcodeproj/project.pbxproj | 4 +- example-bvh/src/main.cpp | 15 +- example-bvh/src/ofApp.cpp | 27 ++ example-bvh/src/ofApp.h | 16 + example-bvh/src/testApp.cpp | 93 ---- example-bvh/src/testApp.h | 28 -- example-motion-field/.gitignore | 6 + example-motion-field/LICENSE | 24 + example-motion-field/Makefile | 13 + example-motion-field/Project.xcconfig | 88 ++++ example-motion-field/README.md | 58 +++ example-motion-field/addons.make | 1 + example-motion-field/bin/data/.gitkeep | 0 .../bin/data/shaders/field.frag | 43 ++ .../bin/data/shaders/field.vert | 6 + example-motion-field/config.make | 2 + .../project.pbxproj | 360 +++++++++++++++ .../example-motion-field Debug.xcscheme | 104 +++++ .../example-motion-field Release.xcscheme | 104 +++++ example-motion-field/of.entitlements | 24 + .../openFrameworks-Info.plist | 34 ++ example-motion-field/src/main.cpp | 44 ++ example-motion-field/src/ofApp.cpp | 170 +++++++ example-motion-field/src/ofApp.h | 35 ++ example-motion-ribbons/.gitignore | 6 + example-motion-ribbons/LICENSE | 24 + example-motion-ribbons/Makefile | 13 + example-motion-ribbons/Project.xcconfig | 88 ++++ example-motion-ribbons/README.md | 55 +++ example-motion-ribbons/addons.make | 1 + example-motion-ribbons/bin/data/.gitkeep | 0 .../bin/data/shaders/ribbon.frag | 10 + .../bin/data/shaders/ribbon.geom | 35 ++ .../bin/data/shaders/ribbon.vert | 11 + example-motion-ribbons/config.make | 2 + .../project.pbxproj | 360 +++++++++++++++ .../example-motion-ribbons Debug.xcscheme | 104 +++++ .../example-motion-ribbons Release.xcscheme | 104 +++++ example-motion-ribbons/of.entitlements | 24 + .../openFrameworks-Info.plist | 34 ++ example-motion-ribbons/src/main.cpp | 44 ++ example-motion-ribbons/src/ofApp.cpp | 228 ++++++++++ example-motion-ribbons/src/ofApp.h | 43 ++ .../project.pbxproj | 4 +- example-pen-graphics/src/main.cpp | 16 +- example-pen-graphics/src/ofApp.cpp | 122 +++++ example-pen-graphics/src/ofApp.h | 35 ++ example-pen-graphics/src/testApp.cpp | 415 ------------------ example-pen-graphics/src/testApp.h | 32 -- .../project.pbxproj | 4 +- example-sync-sound/src/main.cpp | 15 +- example-sync-sound/src/ofApp.cpp | 63 +++ example-sync-sound/src/ofApp.h | 28 ++ example-sync-sound/src/testApp.cpp | 250 ----------- example-sync-sound/src/testApp.h | 35 -- .../marching-cubes.xcodeproj/project.pbxproj | 4 +- marching-cubes/src/MetaBall.h | 36 +- marching-cubes/src/main.cpp | 15 +- marching-cubes/src/ofApp.cpp | 70 +++ marching-cubes/src/ofApp.h | 28 ++ marching-cubes/src/testApp.cpp | 207 --------- marching-cubes/src/testApp.h | 46 -- .../project.pbxproj | 4 +- motion-visualization/src/main.cpp | 15 +- motion-visualization/src/ofApp.cpp | 72 +++ motion-visualization/src/ofApp.h | 26 ++ motion-visualization/src/testApp.cpp | 235 ---------- motion-visualization/src/testApp.h | 37 -- ofxBvh/src/ofxBvh.cpp | 110 +---- .../project.pbxproj | 4 +- particle-motion-example/src/main.cpp | 15 +- particle-motion-example/src/ofApp.cpp | 144 ++++++ particle-motion-example/src/ofApp.h | 43 ++ particle-motion-example/src/testApp.cpp | 393 ----------------- particle-motion-example/src/testApp.h | 26 -- scripts/build-all.sh | 2 + scripts/smoke-all.sh | 68 +++ scripts/validate-xcode-projects.sh | 10 +- shared/ExampleRuntime.h | 201 +++++++++ shared/LICENSE | 19 + 86 files changed, 3448 insertions(+), 2006 deletions(-) create mode 100644 docs/images/motion-field.png create mode 100644 docs/images/motion-ribbons.png create mode 100644 docs/shaders.md create mode 100644 example-bvh/src/ofApp.cpp create mode 100644 example-bvh/src/ofApp.h delete mode 100644 example-bvh/src/testApp.cpp delete mode 100644 example-bvh/src/testApp.h create mode 100644 example-motion-field/.gitignore create mode 100644 example-motion-field/LICENSE create mode 100644 example-motion-field/Makefile create mode 100644 example-motion-field/Project.xcconfig create mode 100644 example-motion-field/README.md create mode 100644 example-motion-field/addons.make create mode 100644 example-motion-field/bin/data/.gitkeep create mode 100644 example-motion-field/bin/data/shaders/field.frag create mode 100644 example-motion-field/bin/data/shaders/field.vert create mode 100644 example-motion-field/config.make create mode 100644 example-motion-field/example-motion-field.xcodeproj/project.pbxproj create mode 100644 example-motion-field/example-motion-field.xcodeproj/xcshareddata/xcschemes/example-motion-field Debug.xcscheme create mode 100644 example-motion-field/example-motion-field.xcodeproj/xcshareddata/xcschemes/example-motion-field Release.xcscheme create mode 100644 example-motion-field/of.entitlements create mode 100644 example-motion-field/openFrameworks-Info.plist create mode 100644 example-motion-field/src/main.cpp create mode 100644 example-motion-field/src/ofApp.cpp create mode 100644 example-motion-field/src/ofApp.h create mode 100644 example-motion-ribbons/.gitignore create mode 100644 example-motion-ribbons/LICENSE create mode 100644 example-motion-ribbons/Makefile create mode 100644 example-motion-ribbons/Project.xcconfig create mode 100644 example-motion-ribbons/README.md create mode 100644 example-motion-ribbons/addons.make create mode 100644 example-motion-ribbons/bin/data/.gitkeep create mode 100644 example-motion-ribbons/bin/data/shaders/ribbon.frag create mode 100644 example-motion-ribbons/bin/data/shaders/ribbon.geom create mode 100644 example-motion-ribbons/bin/data/shaders/ribbon.vert create mode 100644 example-motion-ribbons/config.make create mode 100644 example-motion-ribbons/example-motion-ribbons.xcodeproj/project.pbxproj create mode 100644 example-motion-ribbons/example-motion-ribbons.xcodeproj/xcshareddata/xcschemes/example-motion-ribbons Debug.xcscheme create mode 100644 example-motion-ribbons/example-motion-ribbons.xcodeproj/xcshareddata/xcschemes/example-motion-ribbons Release.xcscheme create mode 100644 example-motion-ribbons/of.entitlements create mode 100644 example-motion-ribbons/openFrameworks-Info.plist create mode 100644 example-motion-ribbons/src/main.cpp create mode 100644 example-motion-ribbons/src/ofApp.cpp create mode 100644 example-motion-ribbons/src/ofApp.h create mode 100644 example-pen-graphics/src/ofApp.cpp create mode 100644 example-pen-graphics/src/ofApp.h delete mode 100644 example-pen-graphics/src/testApp.cpp delete mode 100644 example-pen-graphics/src/testApp.h create mode 100644 example-sync-sound/src/ofApp.cpp create mode 100644 example-sync-sound/src/ofApp.h delete mode 100644 example-sync-sound/src/testApp.cpp delete mode 100644 example-sync-sound/src/testApp.h create mode 100644 marching-cubes/src/ofApp.cpp create mode 100644 marching-cubes/src/ofApp.h delete mode 100644 marching-cubes/src/testApp.cpp delete mode 100644 marching-cubes/src/testApp.h create mode 100644 motion-visualization/src/ofApp.cpp create mode 100644 motion-visualization/src/ofApp.h delete mode 100644 motion-visualization/src/testApp.cpp delete mode 100644 motion-visualization/src/testApp.h create mode 100644 particle-motion-example/src/ofApp.cpp create mode 100644 particle-motion-example/src/ofApp.h delete mode 100644 particle-motion-example/src/testApp.cpp delete mode 100644 particle-motion-example/src/testApp.h create mode 100755 scripts/smoke-all.sh create mode 100644 shared/ExampleRuntime.h create mode 100644 shared/LICENSE diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77a6a3d..0d1072a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,3 +48,14 @@ jobs: - name: Build all applications and run regression tests run: ./scripts/build-all.sh "${RUNNER_TEMP}/of_v0.12.1_osx_release" + + - name: Render all examples with OpenGL 3.2 + run: ./scripts/smoke-all.sh "${RUNNER_TEMP}/example-captures" + + - name: Keep rendering evidence + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: openframeworks-rendering + path: ${{ runner.temp }}/example-captures + retention-days: 7 diff --git a/LICENSES.md b/LICENSES.md index 30cf57a..df4e6c1 100644 --- a/LICENSES.md +++ b/LICENSES.md @@ -14,6 +14,9 @@ single combined work. | `motion-visualization` | [MIT](motion-visualization/LICENSE) | Copyright (c) 2012 Atsushi Tadokoro | | `marching-cubes` | [MIT](marching-cubes/LICENSE) | Copyright (c) 2012 Atsushi Tadokoro | | `ofxBvh` | [MIT](ofxBvh/LICENSE) | Copyright (c) 2012 Daito Manabe; originally published under the Perfume Dev Team name | +| `example-motion-ribbons` | [MIT](example-motion-ribbons/LICENSE) | Copyright (c) 2026 Daito Manabe | +| `example-motion-field` | [MIT](example-motion-field/LICENSE) | Copyright (c) 2026 Daito Manabe | +| `shared` | [MIT](shared/LICENSE) | Copyright (c) 2026 Daito Manabe | | `scripts` | [MIT](scripts/LICENSE) | Copyright (c) 2026 Daito Manabe | | `tests/ofxBvh-boundary` | [MIT](tests/ofxBvh-boundary/LICENSE) | Copyright (c) 2026 Daito Manabe | | `third_party/ofxMarchingCubes` | [LGPL-2.1-or-later](third_party/ofxMarchingCubes/LICENSE.txt) | Copyright (c) 2009 Rui Madeira; adapted by Greg Borenstein | diff --git a/README.md b/README.md index 7f93fa0..205637d 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,31 @@ [![Build openFrameworks 0.12.1](https://github.com/perfume-dev/example-openFrameworks/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/perfume-dev/example-openFrameworks/actions/workflows/build.yml) -This repository contains openFrameworks examples created around the 2012 -Perfume “Global Site Project.” It is maintained for -[openFrameworks 0.12.1](https://openframeworks.cc/download/), the current -stable release. The original visual character and data formats are preserved -while the application lifecycle, APIs, project files, dependency handling, and -BVH playback safety have been updated. +Motion-capture studies for [openFrameworks 0.12.1](https://openframeworks.cc/download/). +The six examples from the 2012 Perfume “Global Site Project” now use the +programmable OpenGL 3.2 renderer, `ofApp`, member-owned state, and mesh-based +drawing. Two new shader studies turn the bundled motion into luminous ribbons +and animated contour fields. + +## Start with the shader studies + +| Example | What you see | What you learn | +| --- | --- | --- | +| [Motion Ribbons](example-motion-ribbons) | Fine luminous trails following the dancers | Vertex, geometry, and fragment shaders; expanding a line into a ribbon | +| [Motion Field](example-motion-field) | Contours and halos around moving joints | Passing motion to a full-screen fragment shader | + +![Motion Ribbons rendered with its vertex, geometry, and fragment shaders](docs/images/motion-ribbons.png) + +![Motion Field rendered with its full-screen fragment shader](docs/images/motion-field.png) + +These are actual application captures, not concept images. The studies recenter +horizontal root travel to keep the three dancers legible; they show the recorded +poses rather than reconstructing the original stage formation. + +Both use the existing bundled BVH samples and need no external addons or audio +downloads. The [shader guide](docs/shaders.md) explains the rendering stages and +where to start editing. Companion studies are available in the +[Processing repository](https://github.com/perfume-dev/example-processing). ## Stewardship @@ -44,6 +63,8 @@ notices. | `particle-motion-example` | Particle forces driven by tracked joints | | `motion-visualization` | Long-exposure-style joint trajectories | | `marching-cubes` | A metaball surface driven by skeletal endpoints | +| `example-motion-ribbons` | Geometry-shader ribbons following the bundled motion | +| `example-motion-field` | A joint-driven fragment-shader contour field | | `ofxBvh` | The bundled BVH loader and player used by every example | ## Build with openFrameworks 0.12.1 @@ -60,7 +81,7 @@ cd "$OF_ROOT/apps/myApps/example-openFrameworks" ./scripts/build-all.sh "$OF_ROOT" ``` -The script builds all six applications in Release mode and runs the `ofxBvh` +The script builds all eight applications in Release mode and runs the `ofxBvh` boundary/malformed-input and marching-cubes lifecycle regression tests. An individual application can be built with, for example: @@ -69,6 +90,17 @@ make -C example-bvh Release OF_ROOT="$OF_ROOT" open example-bvh/bin/example-bvh.app ``` +To render every example in a hidden test window and save PNG evidence: + +```sh +./scripts/smoke-all.sh /path/to/captures +``` + +The GitHub workflow performs the same render checks after building. Its +`openframeworks-rendering` artifact contains screenshots and logs. This requires +a desktop OpenGL context, even though the test windows stay hidden. The shader +studies are captured at two motion timestamps to check that their output changes. + The checked-in Xcode projects were regenerated from the openFrameworks 0.12.1 macOS template. They use relative paths and expect the repository layout shown above. If you put the repository elsewhere, use the Makefiles with an explicit @@ -77,7 +109,8 @@ above. If you put the repository elsewhere, use the Makefiles with an explicit ## Motion and audio data `example-bvh` is ready to run with its bundled `A_test.bvh`, `B_test.bvh`, and -`C_test.bvh` files. The other five applications first look for the historical +`C_test.bvh` files. The two new shader studies read those same files. The other +five historical applications first look for the original Perfume Global Site assets in each application's `bin/data` directory: ```text @@ -106,3 +139,8 @@ the two examples by Atsushi Tadokoro retain their original copyright and MIT license notices. See [LICENSES.md](LICENSES.md) for the component-by-component license index; the repository does not apply one blanket license to every directory. + +The maintained example code uses GLM vectors and mesh drawing. `ofxBvh` retains +its older public vector/matrix types so existing addon consumers continue to +compile; its example rendering supports the programmable renderer. The vendored +marching-cubes dependency retains its upstream public interface and attribution. diff --git a/docs/images/motion-field.png b/docs/images/motion-field.png new file mode 100644 index 0000000000000000000000000000000000000000..e633278109e98a1830d0c5f7794de73ce5ba931d GIT binary patch literal 229747 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 z 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 Pa`}mhj&g;fRq+1--g*j9 literal 0 HcmV?d00001 diff --git a/docs/images/motion-ribbons.png b/docs/images/motion-ribbons.png new file mode 100644 index 0000000000000000000000000000000000000000..aba01f6d29f7dcbca526e0a13e027ce8af533b37 GIT binary patch literal 74690 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�w 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" }, "4A8C997B-B3CE-4C44-BC3A-FA84012AB644": { "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.cpp", - "name": "testApp.cpp", + "name": "ofApp.cpp", "sourceTree": "" }, "524986E5-48D9-40CF-A1DE-1AD77A70D460": { diff --git a/example-bvh/src/main.cpp b/example-bvh/src/main.cpp index a79738a..f7fd7c7 100644 --- a/example-bvh/src/main.cpp +++ b/example-bvh/src/main.cpp @@ -1,14 +1,5 @@ -#include "ofMain.h" -#include "testApp.h" +#include "ofApp.h" -//======================================================================== -int main() { - ofGLWindowSettings settings; - settings.setSize(1024, 768); - settings.setGLVersion(2, 1); - settings.windowMode = OF_WINDOW; - - auto window = ofCreateWindow(settings); - ofRunApp(window, std::make_shared()); - ofRunMainLoop(); +int main(int argc, char** argv) { + return example::launch(argc, argv, "example-bvh"); } diff --git a/example-bvh/src/ofApp.cpp b/example-bvh/src/ofApp.cpp new file mode 100644 index 0000000..8262b7e --- /dev/null +++ b/example-bvh/src/ofApp.cpp @@ -0,0 +1,27 @@ +#include "ofApp.h" + +void ofApp::setup() { + runtime.setup(); + ofBackground(0); + playback.load("example-bvh", true, runtime.isSmokeTest()); + camera.setTarget(glm::vec3(0, 80, 0)); + camera.setDistance(450); +} + +void ofApp::update() { + playback.update(runtime.deltaSeconds()); +} + +void ofApp::draw() { + ofEnableDepthTest(); + ofEnableBlendMode(OF_BLENDMODE_ALPHA); + camera.begin(); + for (auto& motion : playback.motions) motion.draw(); + camera.end(); + ofDisableDepthTest(); + if (!playback.ready) { + ofSetColor(255); + ofDrawBitmapString("Unable to load the bundled BVH files.", 20, 30); + } + runtime.finishFrame(playback.ready, "example-bvh", playback.motions.front().getNumJoints() * 48); +} diff --git a/example-bvh/src/ofApp.h b/example-bvh/src/ofApp.h new file mode 100644 index 0000000..1b1ce16 --- /dev/null +++ b/example-bvh/src/ofApp.h @@ -0,0 +1,16 @@ +#pragma once + +#include "../../shared/ExampleRuntime.h" + +class ofApp : public ofBaseApp { +public: + explicit ofApp(const example::RunOptions& options) : runtime(options) {} + void setup() override; + void update() override; + void draw() override; + +private: + example::Runtime runtime; + example::MotionPlayback playback; + ofEasyCam camera; +}; diff --git a/example-bvh/src/testApp.cpp b/example-bvh/src/testApp.cpp deleted file mode 100644 index ab619a6..0000000 --- a/example-bvh/src/testApp.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "testApp.h" - -//-------------------------------------------------------------- -void testApp::setup(){ - ofSetFrameRate(60); - ofSetVerticalSync(true); - - ofBackground(0); - - // setup bvh - assetsReady = bvh[0].load("A_test.bvh"); - assetsReady = bvh[1].load("B_test.bvh") && assetsReady; - assetsReady = bvh[2].load("C_test.bvh") && assetsReady; - - for (auto& motion : bvh) - { - motion.play(); - motion.setLoop(true); - } -} - -//-------------------------------------------------------------- -void testApp::update() -{ - for (auto& motion : bvh) - { - motion.update(); - } -} - -//-------------------------------------------------------------- -void testApp::draw(){ - ofEnableDepthTest(); - - ofEnableBlendMode(OF_BLENDMODE_ALPHA); - - cam.begin(); - - for (auto& motion : bvh) - { - motion.draw(); - } - - cam.end(); - - ofDisableDepthTest(); - if (!assetsReady) - { - ofSetColor(255); - ofDrawBitmapString("Unable to load the bundled BVH files.", 20, 30); - } - -} - -//-------------------------------------------------------------- -void testApp::keyPressed(int key){ -} - -//-------------------------------------------------------------- -void testApp::keyReleased(int key){ -} - -//-------------------------------------------------------------- -void testApp::mouseMoved(int x, int y ){ - -} - -//-------------------------------------------------------------- -void testApp::mouseDragged(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mousePressed(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mouseReleased(int x, int y, int button){ -} - -//-------------------------------------------------------------- -void testApp::windowResized(int w, int h){ -} - -//-------------------------------------------------------------- -void testApp::gotMessage(ofMessage msg){ - -} - -//-------------------------------------------------------------- -void testApp::dragEvent(ofDragInfo dragInfo){ -} diff --git a/example-bvh/src/testApp.h b/example-bvh/src/testApp.h deleted file mode 100644 index 90066df..0000000 --- a/example-bvh/src/testApp.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "ofMain.h" -#include "ofxBvh.h" - -#include - -class testApp : public ofBaseApp { - - public: - void setup() override; - void update() override; - void draw() override; - - void keyPressed(int key) override; - void keyReleased(int key) override; - void mouseMoved(int x, int y) override; - void mouseDragged(int x, int y, int button) override; - void mousePressed(int x, int y, int button) override; - void mouseReleased(int x, int y, int button) override; - void windowResized(int w, int h) override; - void dragEvent(ofDragInfo dragInfo) override; - void gotMessage(ofMessage msg) override; - - std::array bvh; - ofEasyCam cam; - bool assetsReady = false; -}; diff --git a/example-motion-field/.gitignore b/example-motion-field/.gitignore new file mode 100644 index 0000000..51c5894 --- /dev/null +++ b/example-motion-field/.gitignore @@ -0,0 +1,6 @@ +*.app +build/ +DerivedData/ +xcuserdata/ +obj/ +.DS_Store diff --git a/example-motion-field/LICENSE b/example-motion-field/LICENSE new file mode 100644 index 0000000..3d05ecf --- /dev/null +++ b/example-motion-field/LICENSE @@ -0,0 +1,24 @@ +MIT License + +Copyright (c) 2026 Daito Manabe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +This license covers the new code and shaders in this directory. Referenced +2012 BVH assets retain their original terms; this file does not relicense them. diff --git a/example-motion-field/Makefile b/example-motion-field/Makefile new file mode 100644 index 0000000..ab71e66 --- /dev/null +++ b/example-motion-field/Makefile @@ -0,0 +1,13 @@ +# Attempt to load a config.make file. +# If none is found, project defaults in config.project.make will be used. +ifneq ($(wildcard config.make),) + include config.make +endif + +# make sure the the OF_ROOT location is defined +ifndef OF_ROOT + OF_ROOT=../../../.. +endif + +# call the project makefile! +include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk diff --git a/example-motion-field/Project.xcconfig b/example-motion-field/Project.xcconfig new file mode 100644 index 0000000..7c338e1 --- /dev/null +++ b/example-motion-field/Project.xcconfig @@ -0,0 +1,88 @@ +//THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. +//THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED +OF_PATH = ../../../.. + +//THIS HAS ALL THE HEADER AND LIBS FOR OF CORE +#include "../../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" + +//UNCOMMENT BELOW TO ENABLE C++ 17 and std::filesystem +CLANG_CXX_LANGUAGE_STANDARD = c++23 +CLANG_C_LANGUAGE_STANDARD = c17 +MACOSX_DEPLOYMENT_TARGET = 11.5 + +// App Settings +PRODUCT_NAME = $(TARGET_NAME) +PRODUCT_NAME[config=Debug] = $(TARGET_NAME)Debug +PRODUCT_BUNDLE_IDENTIFIER = cc.openFrameworks.${TARGET_NAME:rfc1034identifier} +//PRODUCT_BUNDLE_IDENTIFIER[config=Debug] = cc.openFrameworks.$(TARGET_NAME)Debug +DEVELOPMENT_LANGUAGE = English +CODE_SIGN_IDENTITY = - +INFOPLIST_FILE = openFrameworks-Info.plist +GENERATE_INFOPLIST_FILE = YES + +// set application category to games, this is required to enable Game mode +// note: this sets the initial value in the Xcode UI +INFOPLIST_KEY_LSApplicationCategoryType = public.app-category.games + +// VERSIONING - overridden if changed in Xcode UI + +// this is "Version" in the Xcode target Identity UI +// suggested to use semantic versioning format ala #.#.# +MARKETING_VERSION = 0.1.0 + +// If users upgrade project to recommended settings it enables script sandboxing which breaks our post build script +ENABLE_USER_SCRIPT_SANDBOXING=NO + +// this is "Build" in the Xcode target Identity UI, an incremental build number +// important for the App Store as new build submissions need a diff number even +// if MARKETING_VERSION is the same +CURRENT_PROJECT_VERSION = 1 + +// ICONS + +// default oF app icon +ICON_NAME = of.icns +ICON_NAME[config=Debug] = of_debug.icns +ICON_FILE = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/$(ICON_NAME) + +// custom app icon, placed in main project folder +//ICON_NAME = MyApp.icns +//ICON_FILE = $(ICON_NAME) + +// custom app icon with separate Release and Debug versions placed in bin/data +//ICON_NAME = icon.icns +//ICON_NAME[config=Debug] = icon-debug.icns +//ICON_FILE = bin/data/$(ICON_NAME) + +// note: oF 0.7.2 - 0.11 used ICON_FILE_PATH which is no longer used in oF 0.12+ +// ex. change ICON_FILE_PATH = bin/data/ -> ICON_FILE = bin/data/$(ICON_NAME) & +// in a custom openFrameworks-Info.plist, set CFBundleIconFile to ICON_NAME + +//APPSTORE, uncomment next lines to bundle data folder and code sign +//OF_CODESIGN = 1 +//OF_BUNDLE_DATA_FOLDER = 1 +//OF_BUNDLE_DYLIBS = 1 + +HIGH_RESOLUTION_CAPABLE = NO + +// Optional include to keep any permanent settings as CODE_SIGN_IDENTITY. +#include? "App.xcconfig" + +//FOR AV ENGINE SOUND PLAYER UNCOMMENT THREE LINES BELOW +OF_NO_FMOD=1 +USER_PREPROCESSOR_DEFINITIONS="OF_NO_FMOD=1" +LIB_FMOD="" +GCC_PREPROCESSOR_DEFINITIONS=$(inherited) $(USER_PREPROCESSOR_DEFINITIONS) + +OTHER_CFLAGS = $(OF_CORE_CFLAGS) +OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) +HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) + +//THIS MAKES SURE THE APP BUILDS INSIDE THE BIN FOLDER +//If you comment this line out the app will be run from DerrivedData and your data/ files won't be accessible unless you uncomment OF_BUNDLE_DATA_FOLDER = 1 above +CONFIGURATION_BUILD_DIR = ${SRCROOT}/bin + +//OF_CORE_BUILD_COMMAND = echo \"💾 Compiling openFrameworks\"\nxcodebuild -project \"$OF_PATH/libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj\" -target openFrameworks -configuration \"${CONFIGURATION}\" CLANG_CXX_LANGUAGE_STANDARD=$CLANG_CXX_LANGUAGE_STANDARD MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET GCC_PREPROCESSOR_DEFINITIONS='$USER_PREPROCESSOR_DEFINITIONS' + + +OF_CORE_BUILD_COMMAND = xcodebuild -project $OF_PATH/libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj -target openFrameworks -configuration ${CONFIGURATION} CLANG_CXX_LANGUAGE_STANDARD=$CLANG_CXX_LANGUAGE_STANDARD MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET GCC_PREPROCESSOR_DEFINITIONS=$USER_PREPROCESSOR_DEFINITIONS diff --git a/example-motion-field/README.md b/example-motion-field/README.md new file mode 100644 index 0000000..ea8bd3f --- /dev/null +++ b/example-motion-field/README.md @@ -0,0 +1,58 @@ +# Motion Field + +Three dancing fields, drawn from sparse BVH landmarks with a single full-screen +rectangle. Cyan, coral and ivory isocontours merge and separate as hands, feet +and torso move. A subdued coordinate lattice and generous negative space keep +the result simple. + +Requires **openFrameworks 0.12.1**, desktop **OpenGL 3.2** and this entire +repository. The original 2012 A/B/C motion samples are shared rather than copied. + +## Run + +Place the repository at `openFrameworks/apps/myApps/example-openFrameworks`, +open `example-motion-field.xcodeproj` and select the Release scheme, or: + +```sh +make Release OF_ROOT=/path/to/openFrameworks +make RunRelease OF_ROOT=/path/to/openFrameworks +``` + +Keep `../example-bvh/bin/data/{A,B,C}_test.bvh` in place. + +## How the shader works + +The CPU uploads 13 projected joint positions per dancer as `uJoints[39]`. +Each dancer is horizontally recentered. Positions use canvas-height units, so +radial kernels do not stretch with aspect +ratio. `field.vert` draws one rectangle; `field.frag` sums smooth radial kernels, +extracts equal-potential contours and overlays tiny landmark dots. + +- `uResolution`: framebuffer width and height. +- `uJoints`: sparse positions, ordered dancer A then B then C. +- `uContourDensity`: count of contours per unit of field potential. +- `uTime`: the same playback clock as the BVH pose; pause freezes all animation. + +`fwidth` gives the contour edges pixel-aware antialiasing. The field has a +fixed-size uniform array and no texture, postprocess chain or additional addon. + +This is a pose study, not a reconstruction of the original stage formation. +Playback starts at 12 seconds, where the sample movement is already active. + +## Controls and capture + +- Space: pause/resume. +- R: rewind to the start of the study. +- Up/down arrows: increase/decrease contour density (3–16). +- H: toggle the bottom control legend. + +Use `--smoke-test` for 180 deterministic frames in a hidden window. +`--capture=/absolute/path/frame.png` saves the actual rendered FBO and exits; +`--capture-frame=420` selects a later pose. Both options can be combined. +The program prints `SMOKE_TEST_OK` only after shader/GL, visible-pixel and +joint-motion checks succeed. Automated runs never show or activate a window. +Interactive drawing and capture use the same 1440×900 FBO; other window shapes +are letterboxed to preserve the composition. + +The new source and shaders use [MIT](LICENSE). Shared motion assets and the +ofxBvh dependency retain their existing terms; see the repository license index. diff --git a/example-motion-field/addons.make b/example-motion-field/addons.make new file mode 100644 index 0000000..bec539d --- /dev/null +++ b/example-motion-field/addons.make @@ -0,0 +1 @@ +../ofxBvh diff --git a/example-motion-field/bin/data/.gitkeep b/example-motion-field/bin/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/example-motion-field/bin/data/shaders/field.frag b/example-motion-field/bin/data/shaders/field.frag new file mode 100644 index 0000000..c98e47c --- /dev/null +++ b/example-motion-field/bin/data/shaders/field.frag @@ -0,0 +1,43 @@ +#version 150 +// All coordinates are measured in canvas heights, so circles remain round. +uniform vec2 uResolution; +uniform vec2 uJoints[39]; // 13 sparse BVH landmarks for each of A / B / C. +uniform float uTime; +uniform float uContourDensity; +out vec4 fragColor; + +float contour(float value, float density) { + float phase = value * density; + float distanceToLine = abs(fract(phase - 0.5) - 0.5); + float antialias = max(fwidth(phase), 0.004); + return 1.0 - smoothstep(0.012, 0.012 + antialias, distanceToLine); +} + +void main() { + vec2 p = (gl_FragCoord.xy - 0.5 * uResolution) / uResolution.y; + vec3 color = vec3(0.024, 0.034, 0.055); + vec3 palette[3] = vec3[3](vec3(0.30, 0.92, 0.94), vec3(1.0, 0.37, 0.30), vec3(0.93, 0.91, 0.79)); + // The field is a sum of smooth radial kernels. Contours expose equal-potential curves. + for (int dancer = 0; dancer < 3; ++dancer) { + float field = 0.0; + float dots = 0.0; + for (int joint = 0; joint < 13; ++joint) { + vec2 delta = p - uJoints[dancer * 13 + joint]; + float radius = length(delta); + field += 0.23 * exp(-dot(delta, delta) / 0.0045); + dots += 1.0 - smoothstep(0.0012, 0.0028, radius); + } + float mask = smoothstep(0.035, 0.10, field); + float rings = contour(field, uContourDensity) * mask; + // A slow moving phase only modulates light; pause freezes this and the pose together. + float light = 0.86 + 0.14 * sin(uTime * 0.6 + float(dancer)); + color += palette[dancer] * (rings * 0.75 + min(field, 1.0) * 0.065) * light; + color += vec3(0.75, 0.82, 0.86) * min(dots, 1.0) * 0.55; + } + // Restrained coordinate lattice, with a broad vignette leaving generous negative space. + vec2 cell = abs(fract(p * 18.0 + 0.5) - 0.5); + float grid = 1.0 - smoothstep(0.008, 0.025, min(cell.x, cell.y)); + color += vec3(0.022, 0.028, 0.04) * grid; + color *= 1.0 - 0.28 * smoothstep(0.40, 0.95, length(p)); + fragColor = vec4(color, 1.0); +} diff --git a/example-motion-field/bin/data/shaders/field.vert b/example-motion-field/bin/data/shaders/field.vert new file mode 100644 index 0000000..0592aa8 --- /dev/null +++ b/example-motion-field/bin/data/shaders/field.vert @@ -0,0 +1,6 @@ +#version 150 +uniform mat4 modelViewProjectionMatrix; +in vec4 position; +void main() { + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/example-motion-field/config.make b/example-motion-field/config.make new file mode 100644 index 0000000..3ef32f8 --- /dev/null +++ b/example-motion-field/config.make @@ -0,0 +1,2 @@ +# Place the repository at apps/myApps/example-openFrameworks, or override OF_ROOT. +OF_ROOT ?= ../../../.. diff --git a/example-motion-field/example-motion-field.xcodeproj/project.pbxproj b/example-motion-field/example-motion-field.xcodeproj/project.pbxproj new file mode 100644 index 0000000..f1f98fc --- /dev/null +++ b/example-motion-field/example-motion-field.xcodeproj/project.pbxproj @@ -0,0 +1,360 @@ +{ + "_OFProjectGeneratorVersion": "0.103.0", + "archiveVersion": "1", + "classes": {}, + "objectVersion": "54", + "objects": { + "0672BD73-386E-4AA2-8522-1AE1EBCE268D": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "sourcecode.cpp.cpp", + "name": "ofxBvh.cpp", + "path": "../ofxBvh/src/ofxBvh.cpp", + "sourceTree": "SOURCE_ROOT" + }, + "08231D78-261E-4827-910A-0EF646EF3F4B": { + "children": [ + "B2FD32D8-4A28-48C5-91DE-310A908F1570" + ], + "isa": "PBXGroup", + "name": "ofxBvh", + "path": "../ofxBvh", + "sourceTree": "SOURCE_ROOT" + }, + "0E00E657-BCEF-4C35-A827-29575E2542A0": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "folder", + "name": "data", + "path": "bin/data", + "sourceTree": "SOURCE_ROOT" + }, + "191CD6FA2847E21E0085CBB6": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "text.plist.entitlements", + "path": "of.entitlements", + "sourceTree": "" + }, + "191EF70929D778A400F35F26": { + "isa": "PBXFileReference", + "lastKnownFileType": "folder", + "name": "openFrameworks", + "path": "../../../../libs/openFrameworks", + "sourceTree": "" + }, + "19B789C429E5AB4A0082E9B8": { + "alwaysOutOfDate": "1", + "buildActionMask": "2147483647", + "files": [], + "inputFileListPaths": [], + "inputPaths": [], + "isa": "PBXShellScriptBuildPhase", + "outputFileListPaths": [], + "outputPaths": [], + "runOnlyForDeploymentPostprocessing": "0", + "shellPath": "/bin/sh", + "shellScript": "\"$OF_PATH/scripts/osx/xcode_project.sh\"\n", + "showEnvVarsInLog": "0" + }, + "5D41C62D-77C5-426B-B174-981F8628A2EF": { + "children": [ + "08231D78-261E-4827-910A-0EF646EF3F4B" + ], + "isa": "PBXGroup", + "name": "local_addons", + "path": "", + "sourceTree": "SOURCE_ROOT" + }, + "A002B59D-9D01-4505-9A8C-520FEEFC4152": { + "fileRef": "0672BD73-386E-4AA2-8522-1AE1EBCE268D", + "isa": "PBXBuildFile" + }, + "B2FD32D8-4A28-48C5-91DE-310A908F1570": { + "children": [ + "0672BD73-386E-4AA2-8522-1AE1EBCE268D", + "FB36F179-2574-4CF3-A778-FF0E45F0FC51" + ], + "isa": "PBXGroup", + "name": "src", + "path": "src", + "sourceTree": "" + }, + "BB4B014C10F69532006C3DED": { + "children": [], + "isa": "PBXGroup", + "name": "addons", + "path": "../../../../addons", + "sourceTree": "" + }, + "E42962A92163ECCD00A6A9E2": { + "alwaysOutOfDate": "1", + "buildActionMask": "2147483647", + "files": [], + "inputPaths": [], + "isa": "PBXShellScriptBuildPhase", + "name": "Run Script — Compile OF", + "outputPaths": [], + "runOnlyForDeploymentPostprocessing": "0", + "shellPath": "/bin/sh", + "shellScript": "$OF_CORE_BUILD_COMMAND\n", + "showEnvVarsInLog": "0" + }, + "E4A5B60F29BAAAE400C2D356": { + "buildActionMask": "2147483647", + "dstPath": "", + "dstSubfolderSpec": "6", + "files": [], + "isa": "PBXCopyFilesBuildPhase", + "runOnlyForDeploymentPostprocessing": "0" + }, + "E4B69B4A0A3A1720003C02F2": { + "children": [ + "191CD6FA2847E21E0085CBB6", + "E4B6FCAD0C3E899E008CF71C", + "E4EB6923138AFD0F00A09F29", + "E4B69E1C0A3A1BDC003C02F2", + "191EF70929D778A400F35F26", + "BB4B014C10F69532006C3DED", + "E4B69B5B0A3A1756003C02F2", + "5D41C62D-77C5-426B-B174-981F8628A2EF", + "0E00E657-BCEF-4C35-A827-29575E2542A0" + ], + "isa": "PBXGroup", + "sourceTree": "" + }, + "E4B69B4C0A3A1720003C02F2": { + "attributes": { + "BuildIndependentTargetsInParallel": "YES", + "LastUpgradeCheck": "1540" + }, + "buildConfigurationList": "E4B69B4D0A3A1720003C02F2", + "compatibilityVersion": "Xcode 3.2", + "developmentRegion": "en", + "hasScannedForEncodings": "0", + "isa": "PBXProject", + "knownRegions": [ + "en", + "Base" + ], + "mainGroup": "E4B69B4A0A3A1720003C02F2", + "productRefGroup": "E4B69B4A0A3A1720003C02F2", + "projectDirPath": "", + "projectRoot": "", + "targets": [ + "E4B69B5A0A3A1756003C02F2" + ] + }, + "E4B69B4D0A3A1720003C02F2": { + "buildConfigurations": [ + "E4B69B4E0A3A1720003C02F2", + "E4B69B4F0A3A1720003C02F2" + ], + "defaultConfigurationIsVisible": "0", + "defaultConfigurationName": "Release", + "isa": "XCConfigurationList" + }, + "E4B69B4E0A3A1720003C02F2": { + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29", + "buildSettings": { + "CODE_SIGN_ENTITLEMENTS": "of.entitlements", + "COPY_PHASE_STRIP": "NO", + "ENABLE_TESTABILITY": "YES", + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_WARN_UNUSED_VARIABLE": "NO", + "HEADER_SEARCH_PATHS": [ + "$(OF_CORE_HEADERS)", + "src" + ], + "OTHER_CPLUSPLUSFLAGS": "-D__MACOSX_CORE__" + }, + "isa": "XCBuildConfiguration", + "name": "Debug" + }, + "E4B69B4F0A3A1720003C02F2": { + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29", + "buildSettings": { + "CODE_SIGN_ENTITLEMENTS": "of.entitlements", + "COPY_PHASE_STRIP": "YES", + "GCC_OPTIMIZATION_LEVEL": "3", + "GCC_UNROLL_LOOPS": "YES", + "HEADER_SEARCH_PATHS": [ + "$(OF_CORE_HEADERS)", + "src" + ], + "OTHER_CPLUSPLUSFLAGS": "-D__MACOSX_CORE__" + }, + "isa": "XCBuildConfiguration", + "name": "Release" + }, + "E4B69B580A3A1756003C02F2": { + "buildActionMask": "2147483647", + "files": [ + "E4B69E200A3A1BDC003C02F2", + "E4B69E210A3A1BDC003C02F2", + "A002B59D-9D01-4505-9A8C-520FEEFC4152" + ], + "isa": "PBXSourcesBuildPhase", + "runOnlyForDeploymentPostprocessing": "0" + }, + "E4B69B590A3A1756003C02F2": { + "buildActionMask": "2147483647", + "files": [], + "isa": "PBXFrameworksBuildPhase", + "runOnlyForDeploymentPostprocessing": "0" + }, + "E4B69B5A0A3A1756003C02F2": { + "buildConfigurationList": "E4B69B5F0A3A1757003C02F2", + "buildPhases": [ + "E42962A92163ECCD00A6A9E2", + "E4B69B580A3A1756003C02F2", + "E4B69B590A3A1756003C02F2", + "E4C2427710CC5ABF004149E2", + "E4A5B60F29BAAAE400C2D356", + "19B789C429E5AB4A0082E9B8" + ], + "buildRules": [], + "dependencies": [], + "isa": "PBXNativeTarget", + "name": "example-motion-field", + "productName": "myOFApp", + "productReference": "E4B69B5B0A3A1756003C02F2", + "productType": "com.apple.product-type.application" + }, + "E4B69B5B0A3A1756003C02F2": { + "explicitFileType": "wrapper.application", + "includeInIndex": "0", + "isa": "PBXFileReference", + "path": "example-motion-fieldDebug.app", + "sourceTree": "BUILT_PRODUCTS_DIR" + }, + "E4B69B5F0A3A1757003C02F2": { + "buildConfigurations": [ + "E4B69B600A3A1757003C02F2", + "E4B69B610A3A1757003C02F2" + ], + "defaultConfigurationIsVisible": "0", + "defaultConfigurationName": "Release", + "isa": "XCConfigurationList" + }, + "E4B69B600A3A1757003C02F2": { + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29", + "buildSettings": { + "ARCHS": "$(ARCHS_STANDARD)", + "COPY_PHASE_STRIP": "NO", + "FRAMEWORK_SEARCH_PATHS": "$(inherited)", + "GCC_DYNAMIC_NO_PIC": "NO", + "HEADER_SEARCH_PATHS": [ + "$(OF_CORE_HEADERS)", + "src", + "src", + "../ofxBvh/src" + ], + "LIBRARY_SEARCH_PATHS": "$(inherited)", + "OTHER_LDFLAGS": [ + "$(OF_CORE_LIBS)", + "$(OF_CORE_FRAMEWORKS)", + "$(LIB_OF_DEBUG)" + ] + }, + "isa": "XCBuildConfiguration", + "name": "Debug" + }, + "E4B69B610A3A1757003C02F2": { + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29", + "buildSettings": { + "ARCHS": "$(ARCHS_STANDARD)", + "COPY_PHASE_STRIP": "YES", + "FRAMEWORK_SEARCH_PATHS": "$(inherited)", + "HEADER_SEARCH_PATHS": [ + "$(OF_CORE_HEADERS)", + "src", + "src", + "../ofxBvh/src" + ], + "LIBRARY_SEARCH_PATHS": "$(inherited)", + "OTHER_LDFLAGS": [ + "$(OF_CORE_LIBS)", + "$(OF_CORE_FRAMEWORKS)", + "$(LIB_OF_RELEASE)" + ], + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29" + }, + "isa": "XCBuildConfiguration", + "name": "Release" + }, + "E4B69E1C0A3A1BDC003C02F2": { + "children": [ + "E4B69E1D0A3A1BDC003C02F2", + "E4B69E1E0A3A1BDC003C02F2", + "E4B69E1F0A3A1BDC003C02F2" + ], + "isa": "PBXGroup", + "path": "src", + "sourceTree": "SOURCE_ROOT" + }, + "E4B69E1D0A3A1BDC003C02F2": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "sourcecode.cpp.cpp", + "name": "main.cpp", + "path": "src/main.cpp", + "sourceTree": "SOURCE_ROOT" + }, + "E4B69E1E0A3A1BDC003C02F2": { + "explicitFileType": "sourcecode.cpp.cpp", + "fileEncoding": "4", + "isa": "PBXFileReference", + "name": "ofApp.cpp", + "path": "src/ofApp.cpp", + "sourceTree": "SOURCE_ROOT" + }, + "E4B69E1F0A3A1BDC003C02F2": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "sourcecode.c.h", + "name": "ofApp.h", + "path": "src/ofApp.h", + "sourceTree": "SOURCE_ROOT" + }, + "E4B69E200A3A1BDC003C02F2": { + "fileRef": "E4B69E1D0A3A1BDC003C02F2", + "isa": "PBXBuildFile" + }, + "E4B69E210A3A1BDC003C02F2": { + "fileRef": "E4B69E1E0A3A1BDC003C02F2", + "isa": "PBXBuildFile" + }, + "E4B6FCAD0C3E899E008CF71C": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "text.plist.xml", + "path": "openFrameworks-Info.plist", + "sourceTree": "" + }, + "E4C2427710CC5ABF004149E2": { + "buildActionMask": "2147483647", + "dstPath": "", + "dstSubfolderSpec": "10", + "files": [], + "isa": "PBXCopyFilesBuildPhase", + "runOnlyForDeploymentPostprocessing": "0" + }, + "E4EB6923138AFD0F00A09F29": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "text.xcconfig", + "path": "Project.xcconfig", + "sourceTree": "" + }, + "FB36F179-2574-4CF3-A778-FF0E45F0FC51": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "sourcecode.cpp.h", + "name": "ofxBvh.h", + "path": "../ofxBvh/src/ofxBvh.h", + "sourceTree": "SOURCE_ROOT" + } + }, + "rootObject": "E4B69B4C0A3A1720003C02F2" +} \ No newline at end of file diff --git a/example-motion-field/example-motion-field.xcodeproj/xcshareddata/xcschemes/example-motion-field Debug.xcscheme b/example-motion-field/example-motion-field.xcodeproj/xcshareddata/xcschemes/example-motion-field Debug.xcscheme new file mode 100644 index 0000000..41585f2 --- /dev/null +++ b/example-motion-field/example-motion-field.xcodeproj/xcshareddata/xcschemes/example-motion-field Debug.xcscheme @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example-motion-field/example-motion-field.xcodeproj/xcshareddata/xcschemes/example-motion-field Release.xcscheme b/example-motion-field/example-motion-field.xcodeproj/xcshareddata/xcschemes/example-motion-field Release.xcscheme new file mode 100644 index 0000000..64abd5a --- /dev/null +++ b/example-motion-field/example-motion-field.xcodeproj/xcshareddata/xcschemes/example-motion-field Release.xcscheme @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example-motion-field/of.entitlements b/example-motion-field/of.entitlements new file mode 100644 index 0000000..f4fc128 --- /dev/null +++ b/example-motion-field/of.entitlements @@ -0,0 +1,24 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.device.camera + + com.apple.security.device.usb + + com.apple.security.files.user-selected.read-write + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.print + + + diff --git a/example-motion-field/openFrameworks-Info.plist b/example-motion-field/openFrameworks-Info.plist new file mode 100644 index 0000000..c362e38 --- /dev/null +++ b/example-motion-field/openFrameworks-Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + ${DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + ${ICON_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${TARGET_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleShortVersionString + ${MARKETING_VERSION} + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSCameraUsageDescription + This app needs to access the camera + NSMicrophoneUsageDescription + This app needs to access the microphone + NSHighResolutionCapable + ${HIGH_RESOLUTION_CAPABLE} + NSCameraUseContinuityCameraDeviceType + + + diff --git a/example-motion-field/src/main.cpp b/example-motion-field/src/main.cpp new file mode 100644 index 0000000..ea192d4 --- /dev/null +++ b/example-motion-field/src/main.cpp @@ -0,0 +1,44 @@ +#include "ofMain.h" +#include "ofApp.h" + +#include +#include +#include + +int main(int argc, char* argv[]) { + AppOptions options; + try { + for (int i = 1; i < argc; ++i) { + const std::string argument = argv[i]; + if (argument == "--smoke-test") options.smokeTest = true; + else if (argument.starts_with("--capture=")) { + options.capturePath = argument.substr(10); + if (options.capturePath.empty()) throw std::invalid_argument("Capture path is empty."); + } else if (argument.starts_with("--capture-frame=")) { + const auto value = argument.substr(16); + std::size_t consumed = 0; + options.captureFrame = std::stoi(value, &consumed); + if (consumed != value.size()) throw std::invalid_argument("Capture frame must be an integer."); + } + else { + std::cerr << "Unknown option: " << argument << '\n'; + return 1; + } + } + if (options.captureFrame < 2 || options.captureFrame > 3600 || + (!options.capturePath.empty() && !of::filesystem::path(options.capturePath).is_absolute())) { + throw std::invalid_argument("Use an absolute capture path and a frame between 2 and 3600."); + } + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; + return 1; + } + ofGLFWWindowSettings settings; + settings.setSize(1440, 900); + settings.setGLVersion(3, 2); + settings.numSamples = 0; // The FBO owns the render target in interactive and automated runs. + settings.visible = !options.automated(); + auto window = ofCreateWindow(settings); + ofRunApp(window, std::make_shared(options)); + return ofRunMainLoop(); +} diff --git a/example-motion-field/src/ofApp.cpp b/example-motion-field/src/ofApp.cpp new file mode 100644 index 0000000..47193df --- /dev/null +++ b/example-motion-field/src/ofApp.cpp @@ -0,0 +1,170 @@ +#include "ofApp.h" +#include +#include +#include + +namespace { +constexpr std::array trackedJoints{ + "Hips", "Chest3", "Head", "LeftShoulder", "LeftElbow", "LeftWrist", + "RightShoulder", "RightElbow", "RightWrist", "LeftKnee", "LeftAnkle", + "RightKnee", "RightAnkle"}; +} + +void ofApp::setup() { + ofSetWindowTitle("Motion Field | perfume-dev"); + ofSetFrameRate(options.automated() ? 0 : 60); + ofSetVerticalSync(!options.automated()); + ofBackground(7, 10, 16); + ofFbo::Settings target; + target.width = 1440; + target.height = 900; + target.internalformat = GL_RGBA; + target.textureTarget = GL_TEXTURE_2D; + canvas.allocate(target); + bool loaded = true; + for (int dancer = 0; dancer < 3; ++dancer) { + const auto filename = std::string(1, static_cast('A' + dancer)) + "_test.bvh"; + loaded = motions[dancer].load("../../../example-bvh/bin/data/" + filename) && loaded; + motions[dancer].setLoop(true); + motions[dancer].play(); + if (motions[dancer].isLoaded()) { + motions[dancer].setPosition(0.0f); + motions[dancer].update(0.0f); + origins[dancer] = glm::vec3(motions[dancer].getJoint(0)->getPosition()); + for (const auto* name : trackedJoints) loaded = motions[dancer].getJoint(name) && loaded; + } + } + loaded = fieldShader.setupShaderFromFile(GL_VERTEX_SHADER, "shaders/field.vert") && loaded; + loaded = fieldShader.setupShaderFromFile(GL_FRAGMENT_SHADER, "shaders/field.frag") && loaded; + loaded = fieldShader.bindDefaults() && loaded; + loaded = fieldShader.linkProgram() && loaded; + // OF 0.12.1's isLoaded/linkProgram result alone does not guarantee successful linkage. + GLint linked = GL_FALSE; + glGetProgramiv(fieldShader.getProgram(), GL_LINK_STATUS, &linked); + ready = loaded && linked == GL_TRUE && canvas.isAllocated(); + if (!ready) { + ofLogError("Motion Field") << "Required BVH, shader, or framebuffer could not be loaded."; + ofExit(1); + return; + } + updatePose(); + previousJoint = jointPositions[5]; +} + +void ofApp::updatePose() { + // CPU: project a sparse pose into a stable 2D coordinate system, measured in canvas heights. + for (int dancer = 0; dancer < 3; ++dancer) { + auto& motion = motions[dancer]; + motion.setPosition(std::fmod(timeline, motion.getDuration()) / motion.getDuration()); + motion.update(0.0f); + const glm::vec3 root(motion.getJoint(0)->getPosition()); + const glm::vec3 origin(root.x, origins[dancer].y, root.z); + for (int joint = 0; joint < jointsPerDancer; ++joint) { + const auto p = glm::vec3(motion.getJoint(trackedJoints[joint])->getPosition()) - origin; + jointPositions[dancer * jointsPerDancer + joint] = + glm::vec2(p.x * 0.0020f + (dancer - 1) * 0.46f, p.y * 0.0020f); + } + } +} + +void ofApp::update() { + if (!ready || paused) return; + timeline += options.automated() ? 1.0f / 60.0f : static_cast(std::min(ofGetLastFrameTime(), 0.05)); + updatePose(); + traveled += glm::distance(previousJoint, jointPositions[5]); + previousJoint = jointPositions[5]; +} + +void ofApp::draw() { + if (!ready) return; + canvas.begin(); + ofClear(7, 10, 16, 255); + ofDisableDepthTest(); + ofSetColor(255); + fieldShader.begin(); + fieldShader.setUniform2f("uResolution", canvas.getWidth(), canvas.getHeight()); + fieldShader.setUniform1f("uTime", timeline); + fieldShader.setUniform1f("uContourDensity", contourDensity); + fieldShader.setUniform2fv("uJoints", &jointPositions.front().x, jointPositions.size()); + // A single rectangle is the entire GPU geometry for this example. + ofDrawRectangle(0, 0, canvas.getWidth(), canvas.getHeight()); + fieldShader.end(); + + ofSetColor(49, 61, 75); + ofDrawLine(68, 104, 1372, 104); + ofDrawLine(68, 808, 1372, 808); + ofSetColor(225, 229, 230); + ofDrawBitmapString("M O T I O N F I E L D", 68, 68); + ofSetColor(126, 140, 156); + ofDrawBitmapString("PERFUME / MOTION STUDY 02", 1110, 68); + if (showHelp) { + ofDrawBitmapString("SPACE pause / R reset / UP-DOWN contours / H help", 68, 849); + ofDrawBitmapString("FRAGMENT FIELD / " + ofToString(contourDensity, 0) + " CONTOURS / " + + ofToString(timeline, 2) + " s" + (paused ? " PAUSED" : ""), 974, 849); + } + canvas.end(); + ofSetColor(255); + // Preserve composition in tall/wide windows with centered letterboxing. + const float scale = std::min(ofGetWidth() / canvas.getWidth(), ofGetHeight() / canvas.getHeight()); + const ofRectangle viewport((ofGetWidth() - canvas.getWidth() * scale) * 0.5f, + (ofGetHeight() - canvas.getHeight() * scale) * 0.5f, + canvas.getWidth() * scale, canvas.getHeight() * scale); + canvas.draw(viewport); + finishAutomatedFrame(); +} + +void ofApp::finishAutomatedFrame() { + if (!options.automated() || ++renderedFrames < options.captureFrame) return; + ofPixels pixels; + canvas.readToPixels(pixels); + if (!pixels.isAllocated() || pixels.getWidth() != 1440 || pixels.getHeight() != 900 || + pixels.getNumChannels() != 4) { + ofLogError("Motion Field") << "Framebuffer readback failed."; + ofExit(1); + return; + } + std::size_t brightPixels = 0; + // Exclude every text/line overlay: only the central artwork can satisfy the check. + for (std::size_t y = 125; y < 750; ++y) { + for (std::size_t x = 68; x < 1372; ++x) { + const auto i = (y * pixels.getWidth() + x) * pixels.getNumChannels(); + if (pixels[i] > 70 || pixels[i + 1] > 70 || pixels[i + 2] > 70) ++brightPixels; + } + } + if (glGetError() != GL_NO_ERROR || brightPixels < 1000 || traveled < 0.001f) { + ofLogError("Motion Field") << "Render validation failed: pixels=" << brightPixels << ", motion=" << traveled; + ofExit(1); + return; + } + const float validatedMotion = traveled; + if (options.smokeTest) { + const float frozenTime = timeline; + keyPressed(' '); + update(); + if (!paused || timeline != frozenTime) { ofExit(1); return; } + keyPressed('r'); + if (timeline != 12.0f) { ofExit(1); return; } + keyPressed(' '); + } + if (!options.capturePath.empty() && !ofSaveImage(pixels, options.capturePath)) { + ofLogError("Motion Field") << "Could not save capture."; + ofExit(1); + return; + } + std::cout << "SMOKE_TEST_OK frames=" << renderedFrames << " brightPixels=" << brightPixels + << " motionDistance=" << validatedMotion << " shaderStages=2" + << " controlsChecked=" << options.smokeTest << std::endl; + ofExit(0); +} + +void ofApp::keyPressed(int key) { + if (key == ' ') paused = !paused; + if (key == 'r' || key == 'R') { + timeline = 12.0f; + updatePose(); + previousJoint = jointPositions[5]; + } + if (key == 'h' || key == 'H') showHelp = !showHelp; + if (key == OF_KEY_UP) contourDensity = std::min(contourDensity + 1.0f, 16.0f); + if (key == OF_KEY_DOWN) contourDensity = std::max(contourDensity - 1.0f, 3.0f); +} diff --git a/example-motion-field/src/ofApp.h b/example-motion-field/src/ofApp.h new file mode 100644 index 0000000..148234a --- /dev/null +++ b/example-motion-field/src/ofApp.h @@ -0,0 +1,35 @@ +#pragma once +#include "ofMain.h" +#include "ofxBvh.h" +#include + +struct AppOptions { + bool smokeTest = false; + std::string capturePath; + int captureFrame = 180; + bool automated() const { return smokeTest || !capturePath.empty(); } +}; + +class ofApp : public ofBaseApp { +public: + explicit ofApp(AppOptions options) : options(std::move(options)) {} + void setup() override; + void update() override; + void draw() override; + void keyPressed(int key) override; + +private: + static constexpr int jointsPerDancer = 13; + AppOptions options; + std::array motions; + std::array origins{}; + std::array jointPositions{}; + ofShader fieldShader; + ofFbo canvas; + bool ready = false, paused = false, showHelp = true; + float timeline = 12.0f, contourDensity = 8.0f, traveled = 0.0f; + int renderedFrames = 0; + glm::vec2 previousJoint{}; + void updatePose(); + void finishAutomatedFrame(); +}; diff --git a/example-motion-ribbons/.gitignore b/example-motion-ribbons/.gitignore new file mode 100644 index 0000000..51c5894 --- /dev/null +++ b/example-motion-ribbons/.gitignore @@ -0,0 +1,6 @@ +*.app +build/ +DerivedData/ +xcuserdata/ +obj/ +.DS_Store diff --git a/example-motion-ribbons/LICENSE b/example-motion-ribbons/LICENSE new file mode 100644 index 0000000..3d05ecf --- /dev/null +++ b/example-motion-ribbons/LICENSE @@ -0,0 +1,24 @@ +MIT License + +Copyright (c) 2026 Daito Manabe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +This license covers the new code and shaders in this directory. Referenced +2012 BVH assets retain their original terms; this file does not relicense them. diff --git a/example-motion-ribbons/Makefile b/example-motion-ribbons/Makefile new file mode 100644 index 0000000..ab71e66 --- /dev/null +++ b/example-motion-ribbons/Makefile @@ -0,0 +1,13 @@ +# Attempt to load a config.make file. +# If none is found, project defaults in config.project.make will be used. +ifneq ($(wildcard config.make),) + include config.make +endif + +# make sure the the OF_ROOT location is defined +ifndef OF_ROOT + OF_ROOT=../../../.. +endif + +# call the project makefile! +include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk diff --git a/example-motion-ribbons/Project.xcconfig b/example-motion-ribbons/Project.xcconfig new file mode 100644 index 0000000..7c338e1 --- /dev/null +++ b/example-motion-ribbons/Project.xcconfig @@ -0,0 +1,88 @@ +//THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. +//THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED +OF_PATH = ../../../.. + +//THIS HAS ALL THE HEADER AND LIBS FOR OF CORE +#include "../../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" + +//UNCOMMENT BELOW TO ENABLE C++ 17 and std::filesystem +CLANG_CXX_LANGUAGE_STANDARD = c++23 +CLANG_C_LANGUAGE_STANDARD = c17 +MACOSX_DEPLOYMENT_TARGET = 11.5 + +// App Settings +PRODUCT_NAME = $(TARGET_NAME) +PRODUCT_NAME[config=Debug] = $(TARGET_NAME)Debug +PRODUCT_BUNDLE_IDENTIFIER = cc.openFrameworks.${TARGET_NAME:rfc1034identifier} +//PRODUCT_BUNDLE_IDENTIFIER[config=Debug] = cc.openFrameworks.$(TARGET_NAME)Debug +DEVELOPMENT_LANGUAGE = English +CODE_SIGN_IDENTITY = - +INFOPLIST_FILE = openFrameworks-Info.plist +GENERATE_INFOPLIST_FILE = YES + +// set application category to games, this is required to enable Game mode +// note: this sets the initial value in the Xcode UI +INFOPLIST_KEY_LSApplicationCategoryType = public.app-category.games + +// VERSIONING - overridden if changed in Xcode UI + +// this is "Version" in the Xcode target Identity UI +// suggested to use semantic versioning format ala #.#.# +MARKETING_VERSION = 0.1.0 + +// If users upgrade project to recommended settings it enables script sandboxing which breaks our post build script +ENABLE_USER_SCRIPT_SANDBOXING=NO + +// this is "Build" in the Xcode target Identity UI, an incremental build number +// important for the App Store as new build submissions need a diff number even +// if MARKETING_VERSION is the same +CURRENT_PROJECT_VERSION = 1 + +// ICONS + +// default oF app icon +ICON_NAME = of.icns +ICON_NAME[config=Debug] = of_debug.icns +ICON_FILE = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/$(ICON_NAME) + +// custom app icon, placed in main project folder +//ICON_NAME = MyApp.icns +//ICON_FILE = $(ICON_NAME) + +// custom app icon with separate Release and Debug versions placed in bin/data +//ICON_NAME = icon.icns +//ICON_NAME[config=Debug] = icon-debug.icns +//ICON_FILE = bin/data/$(ICON_NAME) + +// note: oF 0.7.2 - 0.11 used ICON_FILE_PATH which is no longer used in oF 0.12+ +// ex. change ICON_FILE_PATH = bin/data/ -> ICON_FILE = bin/data/$(ICON_NAME) & +// in a custom openFrameworks-Info.plist, set CFBundleIconFile to ICON_NAME + +//APPSTORE, uncomment next lines to bundle data folder and code sign +//OF_CODESIGN = 1 +//OF_BUNDLE_DATA_FOLDER = 1 +//OF_BUNDLE_DYLIBS = 1 + +HIGH_RESOLUTION_CAPABLE = NO + +// Optional include to keep any permanent settings as CODE_SIGN_IDENTITY. +#include? "App.xcconfig" + +//FOR AV ENGINE SOUND PLAYER UNCOMMENT THREE LINES BELOW +OF_NO_FMOD=1 +USER_PREPROCESSOR_DEFINITIONS="OF_NO_FMOD=1" +LIB_FMOD="" +GCC_PREPROCESSOR_DEFINITIONS=$(inherited) $(USER_PREPROCESSOR_DEFINITIONS) + +OTHER_CFLAGS = $(OF_CORE_CFLAGS) +OTHER_LDFLAGS = $(OF_CORE_LIBS) $(OF_CORE_FRAMEWORKS) +HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) + +//THIS MAKES SURE THE APP BUILDS INSIDE THE BIN FOLDER +//If you comment this line out the app will be run from DerrivedData and your data/ files won't be accessible unless you uncomment OF_BUNDLE_DATA_FOLDER = 1 above +CONFIGURATION_BUILD_DIR = ${SRCROOT}/bin + +//OF_CORE_BUILD_COMMAND = echo \"💾 Compiling openFrameworks\"\nxcodebuild -project \"$OF_PATH/libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj\" -target openFrameworks -configuration \"${CONFIGURATION}\" CLANG_CXX_LANGUAGE_STANDARD=$CLANG_CXX_LANGUAGE_STANDARD MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET GCC_PREPROCESSOR_DEFINITIONS='$USER_PREPROCESSOR_DEFINITIONS' + + +OF_CORE_BUILD_COMMAND = xcodebuild -project $OF_PATH/libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj -target openFrameworks -configuration ${CONFIGURATION} CLANG_CXX_LANGUAGE_STANDARD=$CLANG_CXX_LANGUAGE_STANDARD MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET GCC_PREPROCESSOR_DEFINITIONS=$USER_PREPROCESSOR_DEFINITIONS diff --git a/example-motion-ribbons/README.md b/example-motion-ribbons/README.md new file mode 100644 index 0000000..6a9248a --- /dev/null +++ b/example-motion-ribbons/README.md @@ -0,0 +1,55 @@ +# Motion Ribbons + +A minimal three-dancer motion study: cyan, coral and ivory traces describe the +hands, feet and head, while a fine live skeleton keeps the choreography legible. +The data is the original A/B/C sample from the 2012 Perfume Global Site Project. + +Requires **openFrameworks 0.12.1**, a desktop **OpenGL 3.2** context and this entire +repository. The example uses modern `ofApp` lifecycle overrides, GLM positions, +RAII-owned meshes/shaders/framebuffer and a programmable rendering pipeline. + +## Run + +Place the repository at `openFrameworks/apps/myApps/example-openFrameworks`, +open `example-motion-ribbons.xcodeproj` and select the Release scheme, or: + +```sh +make Release OF_ROOT=/path/to/openFrameworks +make RunRelease OF_ROOT=/path/to/openFrameworks +``` + +Keep `../example-bvh/bin/data/{A,B,C}_test.bvh` in place. Data is shared using a +relative path from this example's `bin/data`, and is never duplicated. + +## Three shader stages + +1. CPU: sample BVH landmarks into bounded trails and upload colored line segments. + Each dancer is horizontally recentered to keep the composition stable. +2. `ribbon.vert`: transform line endpoints with OF's camera matrix. +3. `ribbon.geom`: expand each line into a screen-facing four-vertex strip. + `uWidth` is its pixel width and `uViewport` is the framebuffer size. +4. `ribbon.frag`: soften the transverse edge and fade old samples through vertex alpha. + +This is an actual geometry shader, so it is a **desktop GL** example, not an +OpenGL ES/mobile example. It uses no immediate-mode OpenGL or point sprites. + +This is a pose/trail study, not a reconstruction of the original stage formation. +Playback starts at 12 seconds, where the sample movement is already active. + +## Controls and capture + +- Space: pause/resume both pose and trails. +- R: rewind to the start of the study and clear trails. +- Drag / scroll: orbit / zoom the camera. +- H: toggle the bottom control legend. + +Launch the executable with `--smoke-test` to render 180 deterministic frames in +a hidden window. `--capture=/absolute/path/frame.png` saves the FBO image and +exits; `--capture-frame=420` chooses another pose. The two modes can be combined. +Validation checks shader linkage, GL errors, visible pixels and actual joint +movement before printing `SMOKE_TEST_OK`. Automated runs never show or activate +a window. Interactive drawing and capture use the same 1440×900 FBO; other +window shapes are letterboxed, and the orbit control area follows the image. + +The new source and shaders use [MIT](LICENSE). Shared motion assets and the +ofxBvh dependency retain their existing terms; see the repository license index. diff --git a/example-motion-ribbons/addons.make b/example-motion-ribbons/addons.make new file mode 100644 index 0000000..bec539d --- /dev/null +++ b/example-motion-ribbons/addons.make @@ -0,0 +1 @@ +../ofxBvh diff --git a/example-motion-ribbons/bin/data/.gitkeep b/example-motion-ribbons/bin/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/example-motion-ribbons/bin/data/shaders/ribbon.frag b/example-motion-ribbons/bin/data/shaders/ribbon.frag new file mode 100644 index 0000000..dcbefee --- /dev/null +++ b/example-motion-ribbons/bin/data/shaders/ribbon.frag @@ -0,0 +1,10 @@ +#version 150 +in vec4 ribbonColor; +in float acrossRibbon; +out vec4 fragColor; + +void main() { + // An antialiased soft edge without a second blur pass or large overdraw. + float edge = 1.0 - smoothstep(0.35, 1.0, abs(acrossRibbon)); + fragColor = vec4(ribbonColor.rgb, ribbonColor.a * edge); +} diff --git a/example-motion-ribbons/bin/data/shaders/ribbon.geom b/example-motion-ribbons/bin/data/shaders/ribbon.geom new file mode 100644 index 0000000..2763dda --- /dev/null +++ b/example-motion-ribbons/bin/data/shaders/ribbon.geom @@ -0,0 +1,35 @@ +#version 150 +// A world-space line becomes a constant-pixel-width screen-facing ribbon. +layout(lines) in; +layout(triangle_strip, max_vertices = 4) out; +uniform vec2 uViewport; +uniform float uWidth; +in vec4 vertexColor[]; +out vec4 ribbonColor; +out float acrossRibbon; + +void emitCorner(int endpoint, float side, vec2 offset) { + vec4 clip = gl_in[endpoint].gl_Position; + clip.xy += offset * side * clip.w; + gl_Position = clip; + ribbonColor = vertexColor[endpoint]; + acrossRibbon = side; + EmitVertex(); +} + +void main() { + vec4 a = gl_in[0].gl_Position; + vec4 b = gl_in[1].gl_Position; + // Do not divide by a point behind/on the camera plane. + if (a.w <= 0.001 || b.w <= 0.001) return; + vec2 direction = (b.xy / b.w - a.xy / a.w) * uViewport; + float magnitude = length(direction); + if (magnitude < 0.001) return; + vec2 normal = vec2(-direction.y, direction.x) / magnitude; + vec2 offset = normal * uWidth / uViewport; + emitCorner(0, -1.0, offset); + emitCorner(0, 1.0, offset); + emitCorner(1, -1.0, offset); + emitCorner(1, 1.0, offset); + EndPrimitive(); +} diff --git a/example-motion-ribbons/bin/data/shaders/ribbon.vert b/example-motion-ribbons/bin/data/shaders/ribbon.vert new file mode 100644 index 0000000..dbafb4f --- /dev/null +++ b/example-motion-ribbons/bin/data/shaders/ribbon.vert @@ -0,0 +1,11 @@ +#version 150 +// OF supplies these default mesh attributes and the camera transform. +uniform mat4 modelViewProjectionMatrix; +in vec4 position; +in vec4 color; +out vec4 vertexColor; + +void main() { + gl_Position = modelViewProjectionMatrix * position; + vertexColor = color; +} diff --git a/example-motion-ribbons/config.make b/example-motion-ribbons/config.make new file mode 100644 index 0000000..3ef32f8 --- /dev/null +++ b/example-motion-ribbons/config.make @@ -0,0 +1,2 @@ +# Place the repository at apps/myApps/example-openFrameworks, or override OF_ROOT. +OF_ROOT ?= ../../../.. diff --git a/example-motion-ribbons/example-motion-ribbons.xcodeproj/project.pbxproj b/example-motion-ribbons/example-motion-ribbons.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e84690b --- /dev/null +++ b/example-motion-ribbons/example-motion-ribbons.xcodeproj/project.pbxproj @@ -0,0 +1,360 @@ +{ + "_OFProjectGeneratorVersion": "0.103.0", + "archiveVersion": "1", + "classes": {}, + "objectVersion": "54", + "objects": { + "191CD6FA2847E21E0085CBB6": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "text.plist.entitlements", + "path": "of.entitlements", + "sourceTree": "" + }, + "191EF70929D778A400F35F26": { + "isa": "PBXFileReference", + "lastKnownFileType": "folder", + "name": "openFrameworks", + "path": "../../../../libs/openFrameworks", + "sourceTree": "" + }, + "19B789C429E5AB4A0082E9B8": { + "alwaysOutOfDate": "1", + "buildActionMask": "2147483647", + "files": [], + "inputFileListPaths": [], + "inputPaths": [], + "isa": "PBXShellScriptBuildPhase", + "outputFileListPaths": [], + "outputPaths": [], + "runOnlyForDeploymentPostprocessing": "0", + "shellPath": "/bin/sh", + "shellScript": "\"$OF_PATH/scripts/osx/xcode_project.sh\"\n", + "showEnvVarsInLog": "0" + }, + "4EF3C60D-9E16-4D00-8117-EE96E15C3813": { + "children": [ + "5D92FCD1-4A7D-409F-86ED-0AF488E11728" + ], + "isa": "PBXGroup", + "name": "local_addons", + "path": "", + "sourceTree": "SOURCE_ROOT" + }, + "5D92FCD1-4A7D-409F-86ED-0AF488E11728": { + "children": [ + "B7520A1D-B519-4D22-8E68-94171B73C52A" + ], + "isa": "PBXGroup", + "name": "ofxBvh", + "path": "../ofxBvh", + "sourceTree": "SOURCE_ROOT" + }, + "5EF610DD-C456-408D-AEF5-8A2900E51C01": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "sourcecode.cpp.cpp", + "name": "ofxBvh.cpp", + "path": "../ofxBvh/src/ofxBvh.cpp", + "sourceTree": "SOURCE_ROOT" + }, + "9369AD55-D1AF-48BA-855A-D14901B4453F": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "sourcecode.cpp.h", + "name": "ofxBvh.h", + "path": "../ofxBvh/src/ofxBvh.h", + "sourceTree": "SOURCE_ROOT" + }, + "B7520A1D-B519-4D22-8E68-94171B73C52A": { + "children": [ + "5EF610DD-C456-408D-AEF5-8A2900E51C01", + "9369AD55-D1AF-48BA-855A-D14901B4453F" + ], + "isa": "PBXGroup", + "name": "src", + "path": "src", + "sourceTree": "" + }, + "BB4B014C10F69532006C3DED": { + "children": [], + "isa": "PBXGroup", + "name": "addons", + "path": "../../../../addons", + "sourceTree": "" + }, + "E42962A92163ECCD00A6A9E2": { + "alwaysOutOfDate": "1", + "buildActionMask": "2147483647", + "files": [], + "inputPaths": [], + "isa": "PBXShellScriptBuildPhase", + "name": "Run Script — Compile OF", + "outputPaths": [], + "runOnlyForDeploymentPostprocessing": "0", + "shellPath": "/bin/sh", + "shellScript": "$OF_CORE_BUILD_COMMAND\n", + "showEnvVarsInLog": "0" + }, + "E4A5B60F29BAAAE400C2D356": { + "buildActionMask": "2147483647", + "dstPath": "", + "dstSubfolderSpec": "6", + "files": [], + "isa": "PBXCopyFilesBuildPhase", + "runOnlyForDeploymentPostprocessing": "0" + }, + "E4B69B4A0A3A1720003C02F2": { + "children": [ + "191CD6FA2847E21E0085CBB6", + "E4B6FCAD0C3E899E008CF71C", + "E4EB6923138AFD0F00A09F29", + "E4B69E1C0A3A1BDC003C02F2", + "191EF70929D778A400F35F26", + "BB4B014C10F69532006C3DED", + "E4B69B5B0A3A1756003C02F2", + "4EF3C60D-9E16-4D00-8117-EE96E15C3813", + "F377ED00-1313-423B-8416-AA0096AC9DB7" + ], + "isa": "PBXGroup", + "sourceTree": "" + }, + "E4B69B4C0A3A1720003C02F2": { + "attributes": { + "BuildIndependentTargetsInParallel": "YES", + "LastUpgradeCheck": "1540" + }, + "buildConfigurationList": "E4B69B4D0A3A1720003C02F2", + "compatibilityVersion": "Xcode 3.2", + "developmentRegion": "en", + "hasScannedForEncodings": "0", + "isa": "PBXProject", + "knownRegions": [ + "en", + "Base" + ], + "mainGroup": "E4B69B4A0A3A1720003C02F2", + "productRefGroup": "E4B69B4A0A3A1720003C02F2", + "projectDirPath": "", + "projectRoot": "", + "targets": [ + "E4B69B5A0A3A1756003C02F2" + ] + }, + "E4B69B4D0A3A1720003C02F2": { + "buildConfigurations": [ + "E4B69B4E0A3A1720003C02F2", + "E4B69B4F0A3A1720003C02F2" + ], + "defaultConfigurationIsVisible": "0", + "defaultConfigurationName": "Release", + "isa": "XCConfigurationList" + }, + "E4B69B4E0A3A1720003C02F2": { + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29", + "buildSettings": { + "CODE_SIGN_ENTITLEMENTS": "of.entitlements", + "COPY_PHASE_STRIP": "NO", + "ENABLE_TESTABILITY": "YES", + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_WARN_UNUSED_VARIABLE": "NO", + "HEADER_SEARCH_PATHS": [ + "$(OF_CORE_HEADERS)", + "src" + ], + "OTHER_CPLUSPLUSFLAGS": "-D__MACOSX_CORE__" + }, + "isa": "XCBuildConfiguration", + "name": "Debug" + }, + "E4B69B4F0A3A1720003C02F2": { + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29", + "buildSettings": { + "CODE_SIGN_ENTITLEMENTS": "of.entitlements", + "COPY_PHASE_STRIP": "YES", + "GCC_OPTIMIZATION_LEVEL": "3", + "GCC_UNROLL_LOOPS": "YES", + "HEADER_SEARCH_PATHS": [ + "$(OF_CORE_HEADERS)", + "src" + ], + "OTHER_CPLUSPLUSFLAGS": "-D__MACOSX_CORE__" + }, + "isa": "XCBuildConfiguration", + "name": "Release" + }, + "E4B69B580A3A1756003C02F2": { + "buildActionMask": "2147483647", + "files": [ + "E4B69E200A3A1BDC003C02F2", + "E4B69E210A3A1BDC003C02F2", + "EFE9A79B-8E39-480A-B50A-1E0CEBC48B9F" + ], + "isa": "PBXSourcesBuildPhase", + "runOnlyForDeploymentPostprocessing": "0" + }, + "E4B69B590A3A1756003C02F2": { + "buildActionMask": "2147483647", + "files": [], + "isa": "PBXFrameworksBuildPhase", + "runOnlyForDeploymentPostprocessing": "0" + }, + "E4B69B5A0A3A1756003C02F2": { + "buildConfigurationList": "E4B69B5F0A3A1757003C02F2", + "buildPhases": [ + "E42962A92163ECCD00A6A9E2", + "E4B69B580A3A1756003C02F2", + "E4B69B590A3A1756003C02F2", + "E4C2427710CC5ABF004149E2", + "E4A5B60F29BAAAE400C2D356", + "19B789C429E5AB4A0082E9B8" + ], + "buildRules": [], + "dependencies": [], + "isa": "PBXNativeTarget", + "name": "example-motion-ribbons", + "productName": "myOFApp", + "productReference": "E4B69B5B0A3A1756003C02F2", + "productType": "com.apple.product-type.application" + }, + "E4B69B5B0A3A1756003C02F2": { + "explicitFileType": "wrapper.application", + "includeInIndex": "0", + "isa": "PBXFileReference", + "path": "example-motion-ribbonsDebug.app", + "sourceTree": "BUILT_PRODUCTS_DIR" + }, + "E4B69B5F0A3A1757003C02F2": { + "buildConfigurations": [ + "E4B69B600A3A1757003C02F2", + "E4B69B610A3A1757003C02F2" + ], + "defaultConfigurationIsVisible": "0", + "defaultConfigurationName": "Release", + "isa": "XCConfigurationList" + }, + "E4B69B600A3A1757003C02F2": { + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29", + "buildSettings": { + "ARCHS": "$(ARCHS_STANDARD)", + "COPY_PHASE_STRIP": "NO", + "FRAMEWORK_SEARCH_PATHS": "$(inherited)", + "GCC_DYNAMIC_NO_PIC": "NO", + "HEADER_SEARCH_PATHS": [ + "$(OF_CORE_HEADERS)", + "src", + "src", + "../ofxBvh/src" + ], + "LIBRARY_SEARCH_PATHS": "$(inherited)", + "OTHER_LDFLAGS": [ + "$(OF_CORE_LIBS)", + "$(OF_CORE_FRAMEWORKS)", + "$(LIB_OF_DEBUG)" + ] + }, + "isa": "XCBuildConfiguration", + "name": "Debug" + }, + "E4B69B610A3A1757003C02F2": { + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29", + "buildSettings": { + "ARCHS": "$(ARCHS_STANDARD)", + "COPY_PHASE_STRIP": "YES", + "FRAMEWORK_SEARCH_PATHS": "$(inherited)", + "HEADER_SEARCH_PATHS": [ + "$(OF_CORE_HEADERS)", + "src", + "src", + "../ofxBvh/src" + ], + "LIBRARY_SEARCH_PATHS": "$(inherited)", + "OTHER_LDFLAGS": [ + "$(OF_CORE_LIBS)", + "$(OF_CORE_FRAMEWORKS)", + "$(LIB_OF_RELEASE)" + ], + "baseConfigurationReference": "E4EB6923138AFD0F00A09F29" + }, + "isa": "XCBuildConfiguration", + "name": "Release" + }, + "E4B69E1C0A3A1BDC003C02F2": { + "children": [ + "E4B69E1D0A3A1BDC003C02F2", + "E4B69E1E0A3A1BDC003C02F2", + "E4B69E1F0A3A1BDC003C02F2" + ], + "isa": "PBXGroup", + "path": "src", + "sourceTree": "SOURCE_ROOT" + }, + "E4B69E1D0A3A1BDC003C02F2": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "sourcecode.cpp.cpp", + "name": "main.cpp", + "path": "src/main.cpp", + "sourceTree": "SOURCE_ROOT" + }, + "E4B69E1E0A3A1BDC003C02F2": { + "explicitFileType": "sourcecode.cpp.cpp", + "fileEncoding": "4", + "isa": "PBXFileReference", + "name": "ofApp.cpp", + "path": "src/ofApp.cpp", + "sourceTree": "SOURCE_ROOT" + }, + "E4B69E1F0A3A1BDC003C02F2": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "sourcecode.c.h", + "name": "ofApp.h", + "path": "src/ofApp.h", + "sourceTree": "SOURCE_ROOT" + }, + "E4B69E200A3A1BDC003C02F2": { + "fileRef": "E4B69E1D0A3A1BDC003C02F2", + "isa": "PBXBuildFile" + }, + "E4B69E210A3A1BDC003C02F2": { + "fileRef": "E4B69E1E0A3A1BDC003C02F2", + "isa": "PBXBuildFile" + }, + "E4B6FCAD0C3E899E008CF71C": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "text.plist.xml", + "path": "openFrameworks-Info.plist", + "sourceTree": "" + }, + "E4C2427710CC5ABF004149E2": { + "buildActionMask": "2147483647", + "dstPath": "", + "dstSubfolderSpec": "10", + "files": [], + "isa": "PBXCopyFilesBuildPhase", + "runOnlyForDeploymentPostprocessing": "0" + }, + "E4EB6923138AFD0F00A09F29": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "text.xcconfig", + "path": "Project.xcconfig", + "sourceTree": "" + }, + "EFE9A79B-8E39-480A-B50A-1E0CEBC48B9F": { + "fileRef": "5EF610DD-C456-408D-AEF5-8A2900E51C01", + "isa": "PBXBuildFile" + }, + "F377ED00-1313-423B-8416-AA0096AC9DB7": { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "folder", + "name": "data", + "path": "bin/data", + "sourceTree": "SOURCE_ROOT" + } + }, + "rootObject": "E4B69B4C0A3A1720003C02F2" +} \ No newline at end of file diff --git a/example-motion-ribbons/example-motion-ribbons.xcodeproj/xcshareddata/xcschemes/example-motion-ribbons Debug.xcscheme b/example-motion-ribbons/example-motion-ribbons.xcodeproj/xcshareddata/xcschemes/example-motion-ribbons Debug.xcscheme new file mode 100644 index 0000000..be78bfc --- /dev/null +++ b/example-motion-ribbons/example-motion-ribbons.xcodeproj/xcshareddata/xcschemes/example-motion-ribbons Debug.xcscheme @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example-motion-ribbons/example-motion-ribbons.xcodeproj/xcshareddata/xcschemes/example-motion-ribbons Release.xcscheme b/example-motion-ribbons/example-motion-ribbons.xcodeproj/xcshareddata/xcschemes/example-motion-ribbons Release.xcscheme new file mode 100644 index 0000000..b77c762 --- /dev/null +++ b/example-motion-ribbons/example-motion-ribbons.xcodeproj/xcshareddata/xcschemes/example-motion-ribbons Release.xcscheme @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example-motion-ribbons/of.entitlements b/example-motion-ribbons/of.entitlements new file mode 100644 index 0000000..f4fc128 --- /dev/null +++ b/example-motion-ribbons/of.entitlements @@ -0,0 +1,24 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.device.audio-input + + com.apple.security.device.bluetooth + + com.apple.security.device.camera + + com.apple.security.device.usb + + com.apple.security.files.user-selected.read-write + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.print + + + diff --git a/example-motion-ribbons/openFrameworks-Info.plist b/example-motion-ribbons/openFrameworks-Info.plist new file mode 100644 index 0000000..c362e38 --- /dev/null +++ b/example-motion-ribbons/openFrameworks-Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + ${DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + ${ICON_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${TARGET_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleShortVersionString + ${MARKETING_VERSION} + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSCameraUsageDescription + This app needs to access the camera + NSMicrophoneUsageDescription + This app needs to access the microphone + NSHighResolutionCapable + ${HIGH_RESOLUTION_CAPABLE} + NSCameraUseContinuityCameraDeviceType + + + diff --git a/example-motion-ribbons/src/main.cpp b/example-motion-ribbons/src/main.cpp new file mode 100644 index 0000000..ea192d4 --- /dev/null +++ b/example-motion-ribbons/src/main.cpp @@ -0,0 +1,44 @@ +#include "ofMain.h" +#include "ofApp.h" + +#include +#include +#include + +int main(int argc, char* argv[]) { + AppOptions options; + try { + for (int i = 1; i < argc; ++i) { + const std::string argument = argv[i]; + if (argument == "--smoke-test") options.smokeTest = true; + else if (argument.starts_with("--capture=")) { + options.capturePath = argument.substr(10); + if (options.capturePath.empty()) throw std::invalid_argument("Capture path is empty."); + } else if (argument.starts_with("--capture-frame=")) { + const auto value = argument.substr(16); + std::size_t consumed = 0; + options.captureFrame = std::stoi(value, &consumed); + if (consumed != value.size()) throw std::invalid_argument("Capture frame must be an integer."); + } + else { + std::cerr << "Unknown option: " << argument << '\n'; + return 1; + } + } + if (options.captureFrame < 2 || options.captureFrame > 3600 || + (!options.capturePath.empty() && !of::filesystem::path(options.capturePath).is_absolute())) { + throw std::invalid_argument("Use an absolute capture path and a frame between 2 and 3600."); + } + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; + return 1; + } + ofGLFWWindowSettings settings; + settings.setSize(1440, 900); + settings.setGLVersion(3, 2); + settings.numSamples = 0; // The FBO owns the render target in interactive and automated runs. + settings.visible = !options.automated(); + auto window = ofCreateWindow(settings); + ofRunApp(window, std::make_shared(options)); + return ofRunMainLoop(); +} diff --git a/example-motion-ribbons/src/ofApp.cpp b/example-motion-ribbons/src/ofApp.cpp new file mode 100644 index 0000000..c939298 --- /dev/null +++ b/example-motion-ribbons/src/ofApp.cpp @@ -0,0 +1,228 @@ +#include "ofApp.h" +#include +#include +#include + +namespace { +constexpr std::size_t trailLength = 180; +constexpr std::array trackedJoints{ + "LeftWrist", "RightWrist", "LeftAnkle", "RightAnkle", "Head"}; +const std::array palette{ + ofFloatColor(0.30f, 0.92f, 0.94f), ofFloatColor(1.0f, 0.37f, 0.30f), + ofFloatColor(0.93f, 0.91f, 0.79f)}; +} + +void ofApp::setup() { + ofSetWindowTitle("Motion Ribbons | perfume-dev"); + ofSetFrameRate(options.automated() ? 0 : 60); + ofSetVerticalSync(!options.automated()); + ofBackground(7, 10, 16); + ofFbo::Settings target; + target.width = 1440; + target.height = 900; + target.internalformat = GL_RGBA; + target.useDepth = true; + target.textureTarget = GL_TEXTURE_2D; + canvas.allocate(target); + + bool loaded = true; + for (int dancer = 0; dancer < 3; ++dancer) { + const auto filename = std::string(1, static_cast('A' + dancer)) + "_test.bvh"; + loaded = motions[dancer].load("../../../example-bvh/bin/data/" + filename) && loaded; + motions[dancer].setLoop(true); + motions[dancer].play(); + if (motions[dancer].isLoaded()) { + motions[dancer].setPosition(0.0f); + motions[dancer].update(0.0f); + rootOffsets[dancer] = glm::vec3(motions[dancer].getJoint(0)->getPosition()); + for (const auto* name : trackedJoints) loaded = motions[dancer].getJoint(name) && loaded; + } + } + // GLSL 150 is the portable desktop GL 3.2 geometry-shader baseline. + loaded = ribbonShader.setupShaderFromFile(GL_VERTEX_SHADER, "shaders/ribbon.vert") && loaded; + loaded = ribbonShader.setupShaderFromFile(GL_GEOMETRY_SHADER, "shaders/ribbon.geom") && loaded; + loaded = ribbonShader.setupShaderFromFile(GL_FRAGMENT_SHADER, "shaders/ribbon.frag") && loaded; + loaded = ribbonShader.bindDefaults() && loaded; + loaded = ribbonShader.linkProgram() && loaded; + // OF 0.12.1's isLoaded/linkProgram result alone does not guarantee successful linkage. + GLint linked = GL_FALSE; + glGetProgramiv(ribbonShader.getProgram(), GL_LINK_STATUS, &linked); + ready = loaded && linked == GL_TRUE && canvas.isAllocated(); + if (!ready) { + ofLogError("Motion Ribbons") << "Required BVH, shader, or framebuffer could not be loaded."; + ofExit(1); + return; + } + ribbons.setMode(OF_PRIMITIVE_LINES); + skeleton.setMode(OF_PRIMITIVE_LINES); + camera.setNearClip(1.0f); + camera.setFarClip(4000.0f); + camera.setFov(36.0f); + camera.setPosition(0.0f, 190.0f, 850.0f); + camera.lookAt(glm::vec3(0.0f, 0.0f, -55.0f)); + if (options.automated()) camera.disableMouseInput(); + reset(); +} + +glm::vec3 ofApp::position(int dancer, const ofxBvhJoint* joint) const { + // Remove horizontal stage travel so the three studies stay in their own columns. + const glm::vec3 root(motions[dancer].getJoint(0)->getPosition()); + const glm::vec3 origin(root.x, rootOffsets[dancer].y, root.z); + return glm::vec3(joint->getPosition()) - origin + + glm::vec3((dancer - 1) * 230.0f, 0.0f, 0.0f); +} + +void ofApp::reset() { + timeline = 12.0f; + for (auto& dancer : trails) for (auto& trail : dancer) trail.clear(); + for (auto& motion : motions) { + motion.setPosition(timeline / motion.getDuration()); + motion.update(0.0f); + } + previousJoint = position(0, motions[0].getJoint("LeftWrist")); + traveled = 0.0f; + rebuildMeshes(); // Reset also takes effect immediately while playback is paused. +} + +void ofApp::update() { + if (!ready || paused) return; + const float delta = options.automated() ? 1.0f / 60.0f : static_cast(std::min(ofGetLastFrameTime(), 0.05)); + timeline += delta; + for (int dancer = 0; dancer < 3; ++dancer) { + auto& motion = motions[dancer]; + const float seconds = std::fmod(timeline, motion.getDuration()); + // A wrap is a discontinuity; never join the last pose to the first with a ribbon. + if (seconds < delta) for (auto& trail : trails[dancer]) trail.clear(); + motion.setPosition(seconds / motion.getDuration()); + motion.update(0.0f); + for (std::size_t joint = 0; joint < trackedJoints.size(); ++joint) { + auto& trail = trails[dancer][joint]; + trail.push_back(position(dancer, motion.getJoint(trackedJoints[joint]))); + if (trail.size() > trailLength) trail.pop_front(); + } + } + const auto current = position(0, motions[0].getJoint("LeftWrist")); + traveled += glm::distance(previousJoint, current); + previousJoint = current; + rebuildMeshes(); +} + +void ofApp::rebuildMeshes() { + ribbons.clear(); + skeleton.clear(); + for (int dancer = 0; dancer < 3; ++dancer) { + for (const auto& trail : trails[dancer]) { + for (std::size_t i = 1; i < trail.size(); ++i) { + for (const auto sample : {i - 1, i}) { + auto color = palette[dancer]; + color.a = std::pow(static_cast(sample + 1) / trail.size(), 0.8f) * 0.90f; + ribbons.addVertex(trail[sample]); + ribbons.addColor(color); + } + } + } + const auto& motion = motions[dancer]; + for (int j = 0; j < motion.getNumJoints(); ++j) { + const auto* joint = motion.getJoint(j); + if (!joint->getParent()) continue; + skeleton.addVertex(position(dancer, joint)); + skeleton.addVertex(position(dancer, joint->getParent())); + const auto tint = palette[dancer].getLerped(ofFloatColor(1.0f), 0.6f); + skeleton.addColor(ofFloatColor(tint.r, tint.g, tint.b, 0.35f)); + skeleton.addColor(ofFloatColor(tint.r, tint.g, tint.b, 0.35f)); + } + } +} + +void ofApp::draw() { + if (!ready) return; + canvas.begin(); + ofClear(7, 10, 16, 255); + ofEnableBlendMode(OF_BLENDMODE_ALPHA); + ofSetColor(26, 33, 43); + ofDrawLine(68, 104, 1372, 104); + ofDrawLine(68, 808, 1372, 808); + camera.begin(ofRectangle(0, 0, canvas.getWidth(), canvas.getHeight())); + // Pixel widths remain stable when orbiting or resizing. Soft alpha avoids a heavy neon bloom. + ribbonShader.begin(); + ribbonShader.setUniform2f("uViewport", canvas.getWidth(), canvas.getHeight()); + ribbonShader.setUniform1f("uWidth", 10.5f); + ribbons.draw(); + ribbonShader.setUniform1f("uWidth", 1.6f); + skeleton.draw(); + ribbonShader.end(); + camera.end(); + + ofSetColor(225, 229, 230); + ofDrawBitmapString("M O T I O N R I B B O N S", 68, 68); + ofSetColor(126, 140, 156); + ofDrawBitmapString("PERFUME / MOTION STUDY 01", 1110, 68); + ofDrawBitmapString("A / CYAN", 245, 775); + ofDrawBitmapString("B / CORAL", 672, 775); + ofDrawBitmapString("C / IVORY", 1101, 775); + if (showHelp) { + ofDrawBitmapString("SPACE pause / R reset / drag orbit / scroll zoom / H help", 68, 849); + ofDrawBitmapString("VERTEX > GEOMETRY > FRAGMENT / " + ofToString(timeline, 2) + " s" + + (paused ? " PAUSED" : ""), 941, 849); + } + canvas.end(); + ofSetColor(255); + // Preserve composition in tall/wide windows with centered letterboxing. + const float scale = std::min(ofGetWidth() / canvas.getWidth(), ofGetHeight() / canvas.getHeight()); + const ofRectangle viewport((ofGetWidth() - canvas.getWidth() * scale) * 0.5f, + (ofGetHeight() - canvas.getHeight() * scale) * 0.5f, + canvas.getWidth() * scale, canvas.getHeight() * scale); + canvas.draw(viewport); + camera.setControlArea(viewport); + finishAutomatedFrame(); +} + +void ofApp::finishAutomatedFrame() { + if (!options.automated() || ++renderedFrames < options.captureFrame) return; + ofPixels pixels; + canvas.readToPixels(pixels); + if (!pixels.isAllocated() || pixels.getWidth() != 1440 || pixels.getHeight() != 900 || + pixels.getNumChannels() != 4) { + ofLogError("Motion Ribbons") << "Framebuffer readback failed."; + ofExit(1); + return; + } + std::size_t brightPixels = 0; + // Exclude every text/line overlay: only the central artwork can satisfy the check. + for (std::size_t y = 125; y < 750; ++y) { + for (std::size_t x = 68; x < 1372; ++x) { + const auto i = (y * pixels.getWidth() + x) * pixels.getNumChannels(); + if (pixels[i] > 70 || pixels[i + 1] > 70 || pixels[i + 2] > 70) ++brightPixels; + } + } + if (glGetError() != GL_NO_ERROR || brightPixels < 1000 || traveled < 1.0f) { + ofLogError("Motion Ribbons") << "Render validation failed: pixels=" << brightPixels << ", motion=" << traveled; + ofExit(1); + return; + } + const float validatedMotion = traveled; + if (options.smokeTest) { + const float frozenTime = timeline; + keyPressed(' '); + update(); + if (!paused || timeline != frozenTime) { ofExit(1); return; } + keyPressed('r'); + if (timeline != 12.0f) { ofExit(1); return; } + keyPressed(' '); + } + if (!options.capturePath.empty() && !ofSaveImage(pixels, options.capturePath)) { + ofLogError("Motion Ribbons") << "Could not save capture."; + ofExit(1); + return; + } + std::cout << "SMOKE_TEST_OK frames=" << renderedFrames << " brightPixels=" << brightPixels + << " motionDistance=" << validatedMotion << " shaderStages=3" + << " controlsChecked=" << options.smokeTest << std::endl; + ofExit(0); +} + +void ofApp::keyPressed(int key) { + if (key == ' ') paused = !paused; + if (key == 'r' || key == 'R') reset(); + if (key == 'h' || key == 'H') showHelp = !showHelp; +} diff --git a/example-motion-ribbons/src/ofApp.h b/example-motion-ribbons/src/ofApp.h new file mode 100644 index 0000000..1836ac0 --- /dev/null +++ b/example-motion-ribbons/src/ofApp.h @@ -0,0 +1,43 @@ +#pragma once +#include "ofMain.h" +#include "ofxBvh.h" +#include +#include + +struct AppOptions { + bool smokeTest = false; + std::string capturePath; + int captureFrame = 180; + bool automated() const { return smokeTest || !capturePath.empty(); } +}; + +class ofApp : public ofBaseApp { +public: + explicit ofApp(AppOptions options) : options(std::move(options)) {} + void setup() override; + void update() override; + void draw() override; + void keyPressed(int key) override; + +private: + using Pose = std::array; + AppOptions options; + std::array motions; + std::array, 5>, 3> trails; + std::array rootOffsets{}; + ofEasyCam camera; + ofShader ribbonShader; + ofVboMesh ribbons, skeleton; + ofFbo canvas; + bool paused = false; + bool showHelp = true; + bool ready = false; + float timeline = 12.0f; + float traveled = 0.0f; + int renderedFrames = 0; + glm::vec3 previousJoint{}; + void reset(); + void rebuildMeshes(); + glm::vec3 position(int dancer, const ofxBvhJoint* joint) const; + void finishAutomatedFrame(); +}; diff --git a/example-pen-graphics/example-pen-graphics.xcodeproj/project.pbxproj b/example-pen-graphics/example-pen-graphics.xcodeproj/project.pbxproj index efeb1ee..0185c05 100644 --- a/example-pen-graphics/example-pen-graphics.xcodeproj/project.pbxproj +++ b/example-pen-graphics/example-pen-graphics.xcodeproj/project.pbxproj @@ -57,14 +57,14 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.cpp", - "name": "testApp.cpp", + "name": "ofApp.cpp", "sourceTree": "" }, "68E49E5E-0536-4955-B144-FA5AC4F1BE03": { "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.h", - "name": "testApp.h", + "name": "ofApp.h", "sourceTree": "" }, "AD7E4701-E012-467E-B335-FEF0977E4F7B": { diff --git a/example-pen-graphics/src/main.cpp b/example-pen-graphics/src/main.cpp index 07619f2..dc879fc 100644 --- a/example-pen-graphics/src/main.cpp +++ b/example-pen-graphics/src/main.cpp @@ -1,15 +1,5 @@ -#include "ofMain.h" -#include "testApp.h" +#include "ofApp.h" -//======================================================================== -int main() { - ofGLFWWindowSettings settings; - settings.setSize(1280, 720); - settings.setGLVersion(2, 1); - settings.windowMode = OF_WINDOW; - settings.numSamples = 4; - - auto window = ofCreateWindow(settings); - ofRunApp(window, std::make_shared()); - ofRunMainLoop(); +int main(int argc, char** argv) { + return example::launch(argc, argv, "example-pen-graphics"); } diff --git a/example-pen-graphics/src/ofApp.cpp b/example-pen-graphics/src/ofApp.cpp new file mode 100644 index 0000000..4acf9c8 --- /dev/null +++ b/example-pen-graphics/src/ofApp.cpp @@ -0,0 +1,122 @@ +#include "ofApp.h" + +void ofApp::RibbonTrail::update(const glm::vec3& noiseOffset) { + if (!motion->isFrameNew()) return; + for (size_t age = 0; age < history.size(); ++age) { + const float t = float(age) / float(history.size()); + for (auto& position : history[age]) { + glm::vec3 force{0}; + force.y = -2.5f * (1.0f - std::sin(t * t * PI)) + ofNoise(position.y * 0.0001f + noiseOffset.y) * 1.4f; + force.x = ofSignedNoise(position.x * 0.0001f + noiseOffset.x) * 3.0f; + force.z = ofSignedNoise(position.z * 0.0001f + noiseOffset.z) * 3.0f; + if (position.y < 0) force *= glm::vec3(5.0f, 0.02f, 5.0f); + position += force; + } + } + Frame frame; + for (int i = 0; i < motion->getNumJoints(); ++i) { + const auto* joint = motion->getJoint(i); + for (const auto* child : joint->getChildren()) { + frame.emplace_back(joint->getPosition()); + frame.emplace_back(child->getPosition()); + } + } + history.push_front(std::move(frame)); + if (history.size() > 200) history.pop_back(); + surfaces.clear(); + outlines.clear(); + for (size_t bone = 0; bone + 1 < history.front().size(); bone += 2) { + ofVboMesh strip; + strip.setMode(OF_PRIMITIVE_TRIANGLE_STRIP); + ofPolyline left; + ofPolyline right; + glm::vec3 normal{0, 1, 0}; + for (size_t age = 0; age + 1 < history.size(); ++age) { + const float t = ofMap(float(age), 0, float(history.size()), 0.1f, 1.0f); + const auto& a = history[age][bone]; + const auto& b = history[age][bone + 1]; + const glm::vec3 direction = a - b; + const auto side = example::safeNormalize(glm::cross(direction, glm::vec3(0, 1, 0))); + normal = example::safeNormalize(glm::mix(normal, example::safeNormalize(glm::cross(side, direction)), 0.3f)); + const auto tip = glm::mix(b, a, t); + strip.addVertex(a); + strip.addNormal(normal); + strip.addVertex(tip); + strip.addNormal(normal); + left.addVertex(a); + right.addVertex(tip); + } + surfaces.push_back(std::move(strip)); + outlines.push_back(std::move(left)); + outlines.push_back(std::move(right)); + } + skeleton.clear(); + skeleton.setMode(OF_PRIMITIVE_LINES); + skeleton.addVertices(history.front()); +} + +void ofApp::RibbonTrail::draw() { + // Polygon offset remains part of core OpenGL; geometry lives in vertex buffers. + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1, 1); + ofSetColor(255); + for (auto& surface : surfaces) surface.draw(); + glDisable(GL_POLYGON_OFFSET_FILL); + ofSetColor(0); + for (const auto& outline : outlines) outline.draw(); + skeleton.draw(); +} + +void ofApp::setup() { + runtime.setup(); + ofBackground(255); + playback.load("example-pen-graphics", false, runtime.isSmokeTest()); + for (size_t i = 0; i < trails.size(); ++i) trails[i].motion = &playback.motions[i]; + noiseOffset = {ofRandom(1), ofRandom(1), ofRandom(1)}; + noiseVelocity = {ofRandom(0.001f), ofRandom(0.005f), ofRandom(0.001f)}; + ground.setMode(OF_PRIMITIVE_LINES); + for (int x = -10; x < 10; ++x) { + for (int z = -10; z < 10; ++z) { + const glm::vec3 position(x * 500, 0, z * 500); + ground.addVertex(position + glm::vec3(-10, 0, 0)); + ground.addVertex(position + glm::vec3(10, 0, 0)); + ground.addVertex(position + glm::vec3(0, 0, -10)); + ground.addVertex(position + glm::vec3(0, 0, 10)); + } + } +} + +void ofApp::update() { + playback.update(runtime.deltaSeconds()); + if (!playback.ready) return; + glm::vec3 targetCenter{0}; + for (const auto& motion : playback.motions) targetCenter += glm::vec3(motion.getJoint(0)->getPosition()); + center = glm::mix(center, targetCenter / 3.0f, 1.0f - std::exp(-0.6f * runtime.deltaSeconds())); + for (auto& trail : trails) trail.update(noiseOffset); + noiseOffset += noiseVelocity * runtime.deltaSeconds() * 60.0f; + cameraPosition = glm::mix(cameraPosition, cameraTarget, 1.0f - std::exp(-0.6f * runtime.deltaSeconds())); + camera.setPosition(cameraPosition); + camera.lookAt(glm::vec3(0)); +} + +void ofApp::draw() { + ofEnableDepthTest(); + ofEnableBlendMode(OF_BLENDMODE_ALPHA); + camera.begin(); + ofPushMatrix(); + ofRotateYDeg(runtime.elapsedSeconds() * 20.0f); + ofTranslate(-center.x, -100, -center.z); + ofSetColor(200); + ground.draw(); + for (auto& trail : trails) trail.draw(); + ofPopMatrix(); + camera.end(); + ofDisableDepthTest(); + ofSetColor(20); + playback.drawStatus(); + runtime.finishFrame(playback.ready, "example-pen-graphics", trails.front().skeleton.getNumVertices()); +} + +void ofApp::keyPressed(int) { + cameraTarget = {ofRandom(-600, 600), ofRandom(-100, 200), ofRandom(-600, 600)}; +} diff --git a/example-pen-graphics/src/ofApp.h b/example-pen-graphics/src/ofApp.h new file mode 100644 index 0000000..81d13fc --- /dev/null +++ b/example-pen-graphics/src/ofApp.h @@ -0,0 +1,35 @@ +#pragma once + +#include "../../shared/ExampleRuntime.h" +#include + +class ofApp : public ofBaseApp { +public: + explicit ofApp(const example::RunOptions& options) : runtime(options) {} + void setup() override; + void update() override; + void draw() override; + void keyPressed(int key) override; + +private: + struct RibbonTrail { + using Frame = std::vector; + ofxBvh* motion = nullptr; + std::deque history; + std::vector surfaces; + std::vector outlines; + ofVboMesh skeleton; + void update(const glm::vec3& noiseOffset); + void draw(); + }; + example::Runtime runtime; + example::MotionPlayback playback; + std::array trails; + ofCamera camera; + ofVboMesh ground; + glm::vec3 center{0}; + glm::vec3 cameraPosition{0, 60, -420}; + glm::vec3 cameraTarget{0, 60, -420}; + glm::vec3 noiseOffset{0}; + glm::vec3 noiseVelocity{0}; +}; diff --git a/example-pen-graphics/src/testApp.cpp b/example-pen-graphics/src/testApp.cpp deleted file mode 100644 index b4620a1..0000000 --- a/example-pen-graphics/src/testApp.cpp +++ /dev/null @@ -1,415 +0,0 @@ -#include "testApp.h" - -#include - -namespace { - -const std::array kPerfumeMotionFiles = { - "bvhfiles/aachan.bvh", - "bvhfiles/kashiyuka.bvh", - "bvhfiles/nocchi.bvh" -}; - -const std::array kBundledMotionFiles = { - "../../../example-bvh/bin/data/A_test.bvh", - "../../../example-bvh/bin/data/B_test.bvh", - "../../../example-bvh/bin/data/C_test.bvh" -}; - -bool loadMotionFiles(std::array& motions) { - bool loaded = true; - for (size_t i = 0; i < motions.size(); ++i) { - if (!motions[i].load(kPerfumeMotionFiles[i])) { - ofLogWarning("example-pen-graphics") - << "Using bundled motion fallback for " << kPerfumeMotionFiles[i]; - loaded = motions[i].load(kBundledMotionFiles[i]) && loaded; - } - } - return loaded; -} - -} // namespace - -ofVec3f center, center_t; -ofVec3f campos, campos_t; -ofVec3f offset, offset_v; - -class Tracker -{ -public: - - ofxBvh *bvh = nullptr; - - typedef vector Frame; - deque track; - - struct Buffer - { - ofVec3f v1, v2; - ofVec3f norm; - }; - - typedef vector BufferArray; - vector buffer; - - void setup(ofxBvh *o) - { - bvh = o; - } - - void update() - { - if (bvh->isFrameNew()) - { - // update vertexes flow - - for (size_t i = 0; i < track.size(); ++i) - { - float delta = ofMap(static_cast(i), 0.0f, - static_cast(track.size()), 0.0f, 1.0f); - Frame &f = track[i]; - - for (auto& v : f) - { - ofVec3f force{}; - - // gravity - force.y -= 2.5 * (1 - sin(pow(delta, 2) * PI)); - force.y += ofNoise(v.y * 0.0001 + offset.y) * 1.4; - - force.x += ofSignedNoise(v.x * 0.0001 + offset.x) * 3; - force.z += ofSignedNoise(v.z * 0.0001 + offset.z) * 3; - - if (v.y < 0) - { - force.y *= 0.02; - force.x *= 5; - force.z *= 5; - } - - v += force; - } - } - - Frame f; - for (int i = 0; i < bvh->getNumJoints(); ++i) - { - const ofxBvhJoint *j = bvh->getJoint(i); - for (size_t n = 0; n < j->getChildren().size(); ++n) - { - f.push_back(j->getPosition()); - f.push_back(j->getChildren().at(n)->getPosition()); - } - } - - track.push_front(f); - - if (track.size() > 200) - track.pop_back(); - - - // cache vertexes - - buffer.clear(); - for (size_t n = 0; n + 1 < track.front().size(); n += 2) - { - ofVec3f norm; - - BufferArray arr; - - for (size_t i = 0; i + 1 < track.size(); ++i) - { - float delta = ofMap(static_cast(i), 0.0f, - static_cast(track.size()), 0.1f, 1.0f); - Frame &f1 = track[i]; - - const ofVec3f &v1 = f1[n]; - const ofVec3f &v2 = f1[n + 1]; - const ofVec3f d = v1 - v2; - - const ofVec3f c1 = d.getCrossed(ofVec3f(0, 1, 0)).getNormalized(); - const ofVec3f c = c1.getCrossed(d).getNormalized(); - // if (c.y < 0) c *= -1; - - if (i == 0) norm.set(c); - - ofVec3f m = v1 * delta + v2 * (1 - delta); - norm += (c - norm) * 0.3; - - Buffer buf; - - buf.norm = norm; - buf.v1 = v1; - buf.v2 = m; - - arr.push_back(buf); - } - - buffer.push_back(arr); - } - - } - } - - void draw() - { - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1, 1); - - // draw polygons - - ofSetColor(255); - - for (size_t i = 0; i < buffer.size(); ++i) - { - const BufferArray &arr = buffer[i]; - - glBegin(GL_TRIANGLE_STRIP); - for (const auto& b : arr) - { - glNormal3fv(b.norm.getPtr()); - glVertex3fv(b.v1.getPtr()); - glVertex3fv(b.v2.getPtr()); - } - glEnd(); - } - - // draw outline - - ofSetColor(0); - - for (size_t i = 0; i < buffer.size(); ++i) - { - const BufferArray &arr = buffer[i]; - - glBegin(GL_LINE_STRIP); - for (const auto& b : arr) - { - glNormal3fv(b.norm.getPtr()); - glVertex3fv(b.v1.getPtr()); - } - glEnd(); - } - - for (size_t i = 0; i < buffer.size(); ++i) - { - const BufferArray &arr = buffer[i]; - - glBegin(GL_LINE_STRIP); - for (const auto& b : arr) - { - glNormal3fv(b.norm.getPtr()); - glVertex3fv(b.v2.getPtr()); - } - glEnd(); - } - - if (!track.empty()) - { - Frame &f = track[0]; - - glBegin(GL_LINES); - for (size_t n = 0; n + 1 < f.size(); n += 2) - { - ofVec3f &v1 = f[n]; - ofVec3f &v2 = f[n + 1]; - - glVertex3fv(v1.getPtr()); - glVertex3fv(v2.getPtr()); - } - glEnd(); - } - - glDisable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(0, 0); - } - -}; - -vector> trackers; - -//-------------------------------------------------------------- -void testApp::setup() -{ - ofSetFrameRate(60); - ofSetVerticalSync(true); - - ofSetSmoothLighting(true); - ofSetGlobalAmbientColor(ofColor(220)); - - ofBackground(255); - - assetsReady = loadMotionFiles(bvh); - - for (auto& motion : bvh) - { - motion.setFrame(4); - } - - audioReady = ofFile::doesFileExist("Perfume_globalsite_sound.wav") - && track.load("Perfume_globalsite_sound.wav"); - if (audioReady) { - track.setLoop(true); - track.play(); - } else { - ofLogNotice("example-pen-graphics") - << "Audio file not found; using a silent internal clock."; - } - - // setup tracker - if (assetsReady) - { - for (auto& motion : bvh) - { - auto tracker = std::make_unique(); - tracker->setup(&motion); - trackers.push_back(std::move(tracker)); - } - } - - offset.x = ofRandom(1); - offset.y = ofRandom(1); - offset.z = ofRandom(1); - offset_v.x = ofRandom(0.001); - offset_v.y = ofRandom(0.005); - offset_v.z = ofRandom(0.001); - - campos_t.set(0, 0, -300); -} - -//-------------------------------------------------------------- -void testApp::update() -{ - if (!assetsReady) return; - const float motionDuration = bvh[0].getDuration(); - const float motionSeconds = audioReady - ? track.getPosition() * track.getDuration() - : std::fmod(ofGetElapsedTimef(), motionDuration); - const float t = ofClamp(motionSeconds / motionDuration, 0.0f, 1.0f); - - center_t.set(0, 0, 0); - - for (auto& motion : bvh) - { - motion.setPosition(t); - motion.update(); - - center_t += motion.getJoint(0)->getPosition(); - } - - center_t /= 3; - center += (center_t - center) * 0.01; - - for (auto& tracker : trackers) - { - tracker->update(); - } - - offset += offset_v; - - cam.setPosition(campos.x, campos.y, campos.z); - cam.lookAt(ofVec3f(0, 0, 0)); - campos += (campos_t - campos) * 0.01; -} - -//-------------------------------------------------------------- -void testApp::draw(){ - glEnable(GL_DEPTH_TEST); - glShadeModel(GL_SMOOTH); - - ofEnableSmoothing(); - - glEnable(GL_LINE_SMOOTH); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glLineWidth(1); - - ofEnableBlendMode(OF_BLENDMODE_ALPHA); - - light.enable(); - light.setPosition(0, -500, 0); - - cam.begin(); - - ofPushMatrix(); - { - glRotatef(ofGetElapsedTimef() * 20, 0, 1, 0); - glTranslatef(-center.x, -100, -center.z); - - ofSetColor(200); - - for (int x = -10; x < 10; x++) - { - for (int y = -10; y < 10; y++) - { - ofPushMatrix(); - glTranslatef(x * 500, 0, y * 500); - ofDrawLine(10, 0, 0, -10, 0, 0); - ofDrawLine(0, 0, 10, 0, 0, -10); - ofPopMatrix(); - } - } - - ofSetColor(ofColor::white, 80); - for (auto& tracker : trackers) - { - tracker->draw(); - } - } - ofPopMatrix(); - - cam.end(); - - light.disable(); - ofDisableDepthTest(); - ofSetColor(20); - - if (!assetsReady) - ofDrawBitmapString("Motion data is missing. See README.md.", 10, 20); - else if (!audioReady) - ofDrawBitmapString("Audio data is missing; running with a silent clock.", 10, 20); - -} - -//-------------------------------------------------------------- -void testApp::keyPressed(int key){ - campos_t.x = ofRandom(-600, 600); - campos_t.z = ofRandom(-600, 600); - campos_t.y = ofRandom(-100, 200); -} - -//-------------------------------------------------------------- -void testApp::keyReleased(int key){ - -} - -//-------------------------------------------------------------- -void testApp::mouseMoved(int x, int y ){ - -} - -//-------------------------------------------------------------- -void testApp::mouseDragged(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mousePressed(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mouseReleased(int x, int y, int button){ -} - -//-------------------------------------------------------------- -void testApp::windowResized(int w, int h){ -} - -//-------------------------------------------------------------- -void testApp::gotMessage(ofMessage msg){ - -} - -//-------------------------------------------------------------- -void testApp::dragEvent(ofDragInfo dragInfo){ -} diff --git a/example-pen-graphics/src/testApp.h b/example-pen-graphics/src/testApp.h deleted file mode 100644 index 6d384af..0000000 --- a/example-pen-graphics/src/testApp.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "ofMain.h" -#include "ofxBvh.h" - -#include - -class testApp : public ofBaseApp { - - public: - void setup() override; - void update() override; - void draw() override; - - void keyPressed(int key) override; - void keyReleased(int key) override; - void mouseMoved(int x, int y) override; - void mouseDragged(int x, int y, int button) override; - void mousePressed(int x, int y, int button) override; - void mouseReleased(int x, int y, int button) override; - void windowResized(int w, int h) override; - void dragEvent(ofDragInfo dragInfo) override; - void gotMessage(ofMessage msg) override; - - ofSoundPlayer track; - std::array bvh; - - ofCamera cam; - ofLight light; - bool assetsReady = false; - bool audioReady = false; -}; diff --git a/example-sync-sound/example-sync-sound.xcodeproj/project.pbxproj b/example-sync-sound/example-sync-sound.xcodeproj/project.pbxproj index 7d6e51c..74cd2f0 100644 --- a/example-sync-sound/example-sync-sound.xcodeproj/project.pbxproj +++ b/example-sync-sound/example-sync-sound.xcodeproj/project.pbxproj @@ -74,7 +74,7 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.h", - "name": "testApp.h", + "name": "ofApp.h", "sourceTree": "" }, "BB4B014C10F69532006C3DED": { @@ -88,7 +88,7 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.cpp", - "name": "testApp.cpp", + "name": "ofApp.cpp", "sourceTree": "" }, "C46DECE4-C688-4892-B7C0-BBA05139EB84": { diff --git a/example-sync-sound/src/main.cpp b/example-sync-sound/src/main.cpp index a79738a..6130ef3 100644 --- a/example-sync-sound/src/main.cpp +++ b/example-sync-sound/src/main.cpp @@ -1,14 +1,5 @@ -#include "ofMain.h" -#include "testApp.h" +#include "ofApp.h" -//======================================================================== -int main() { - ofGLWindowSettings settings; - settings.setSize(1024, 768); - settings.setGLVersion(2, 1); - settings.windowMode = OF_WINDOW; - - auto window = ofCreateWindow(settings); - ofRunApp(window, std::make_shared()); - ofRunMainLoop(); +int main(int argc, char** argv) { + return example::launch(argc, argv, "example-sync-sound"); } diff --git a/example-sync-sound/src/ofApp.cpp b/example-sync-sound/src/ofApp.cpp new file mode 100644 index 0000000..ab7d78d --- /dev/null +++ b/example-sync-sound/src/ofApp.cpp @@ -0,0 +1,63 @@ +#include "ofApp.h" + +void ofApp::Trail::update() { + if (!joint->getBvh()->isFrameNew()) return; + points.push_front(glm::vec3(joint->getPosition())); + if (points.size() > 15) points.pop_back(); + mesh.clear(); + mesh.setMode(OF_PRIMITIVE_LINE_STRIP); + for (size_t i = 0; i + 1 < points.size(); ++i) { + const float age = float(i) / float(points.size() - 1); + const float alpha = (1.0f - age) * ofMap(glm::distance(points[i], points[i + 1]), 3, 5, 0, 1, true); + mesh.addVertex(points[i]); + mesh.addColor(ofFloatColor(1, 1, 1, alpha)); + } +} + +void ofApp::setup() { + runtime.setup(); + ofBackground(0); + playback.load("example-sync-sound", false, runtime.isSmokeTest()); + if (!playback.ready) return; + for (auto& motion : playback.motions) { + for (int i = 0; i < motion.getNumJoints(); ++i) { + Trail trail; + trail.joint = motion.getJoint(i); + trails.push_back(std::move(trail)); + } + } +} + +void ofApp::update() { + const float dt = runtime.deltaSeconds(); + rotation += 6.0f * dt; + playbackSpeed = glm::mix(playbackSpeed, targetSpeed, 1.0f - std::exp(-21.4f * dt)); + playback.update(dt, playbackSpeed); + for (auto& trail : trails) trail.update(); +} + +void ofApp::draw() { + ofEnableDepthTest(); + ofEnableBlendMode(OF_BLENDMODE_ALPHA); + ofPushMatrix(); + ofTranslate(ofGetWidth() * 0.5f, ofGetHeight() * 0.5f + 150.0f); + ofRotateXDeg(-15); + ofRotateYDeg(rotation); + ofScale(1, -1, 1); + ofSetColor(255); + ofDrawLine(glm::vec3(-100, 0, 0), glm::vec3(100, 0, 0)); + ofDrawLine(glm::vec3(0, 0, -100), glm::vec3(0, 0, 100)); + for (auto& motion : playback.motions) motion.draw(); + ofDisableDepthTest(); + ofEnableBlendMode(OF_BLENDMODE_ADD); + for (auto& trail : trails) trail.mesh.draw(); + ofPopMatrix(); + ofEnableBlendMode(OF_BLENDMODE_ALPHA); + ofSetColor(255); + ofDrawBitmapString("Hold a key to scratch\nPlayback speed: " + ofToString(playbackSpeed, 1), 10, 20); + playback.drawStatus(10, 65); + runtime.finishFrame(playback.ready, "example-sync-sound", playback.motions.front().getNumJoints() * 48); +} + +void ofApp::keyPressed(int) { targetSpeed = -1.0f; } +void ofApp::keyReleased(int) { targetSpeed = 1.0f; } diff --git a/example-sync-sound/src/ofApp.h b/example-sync-sound/src/ofApp.h new file mode 100644 index 0000000..2adc8db --- /dev/null +++ b/example-sync-sound/src/ofApp.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../../shared/ExampleRuntime.h" +#include + +class ofApp : public ofBaseApp { +public: + explicit ofApp(const example::RunOptions& options) : runtime(options) {} + void setup() override; + void update() override; + void draw() override; + void keyPressed(int key) override; + void keyReleased(int key) override; + +private: + struct Trail { + const ofxBvhJoint* joint = nullptr; + std::deque points; + ofVboMesh mesh; + void update(); + }; + example::Runtime runtime; + example::MotionPlayback playback; + std::vector trails; + float rotation = 0.0f; + float playbackSpeed = 1.0f; + float targetSpeed = 1.0f; +}; diff --git a/example-sync-sound/src/testApp.cpp b/example-sync-sound/src/testApp.cpp deleted file mode 100644 index 2ebc6fa..0000000 --- a/example-sync-sound/src/testApp.cpp +++ /dev/null @@ -1,250 +0,0 @@ -#include "testApp.h" - -#include - -namespace { - -const std::array kPerfumeMotionFiles = { - "bvhfiles/aachan.bvh", - "bvhfiles/kashiyuka.bvh", - "bvhfiles/nocchi.bvh" -}; - -const std::array kBundledMotionFiles = { - "../../../example-bvh/bin/data/A_test.bvh", - "../../../example-bvh/bin/data/B_test.bvh", - "../../../example-bvh/bin/data/C_test.bvh" -}; - -bool loadMotionFiles(std::array& motions) { - bool loaded = true; - for (size_t i = 0; i < motions.size(); ++i) { - if (!motions[i].load(kPerfumeMotionFiles[i])) { - ofLogWarning("example-sync-sound") - << "Using bundled motion fallback for " << kPerfumeMotionFiles[i]; - loaded = motions[i].load(kBundledMotionFiles[i]) && loaded; - } - } - return loaded; -} - -} // namespace - -class Tracker -{ -public: - - const ofxBvhJoint *joint = nullptr; - deque points; - - void setup(const ofxBvhJoint *o) - { - joint = o; - } - - void update() - { - if (joint->getBvh()->isFrameNew()) - { - points.push_front(joint->getPosition()); - - if (points.size() > 15) - points.pop_back(); - } - } - - void draw() - { - if (points.empty()) return; - - glBegin(GL_LINE_STRIP); - for (size_t i = 0; i + 1 < points.size(); ++i) - { - float a = ofMap(static_cast(i), 0.0f, - static_cast(points.size() - 1), 1.0f, 0.0f, true); - - ofVec3f &p0 = points[i]; - ofVec3f &p1 = points[i + 1]; - - float d = p0.distance(p1); - a *= ofMap(d, 3, 5, 0, 1, true); - - glColor4f(1, 1, 1, a); - glVertex3fv(points[i].getPtr()); - } - glEnd(); - } -}; - -vector> trackers; - -//-------------------------------------------------------------- -void testApp::setup() -{ - ofSetFrameRate(60); - ofSetVerticalSync(true); - - ofBackground(0); - - play_rate = play_rate_t = 1.0f; - rotate = 0.0f; - - assetsReady = loadMotionFiles(bvh); - - for (auto& motion : bvh) - { - motion.setFrame(1); - } - - audioReady = ofFile::doesFileExist("Perfume_globalsite_sound.wav") - && track.load("Perfume_globalsite_sound.wav"); - if (audioReady) { - track.setLoop(true); - track.play(); - } else { - ofLogNotice("example-sync-sound") - << "Audio file not found; using a silent internal clock."; - } - - // setup tracker - if (assetsReady) - { - for (auto& motion : bvh) - { - for (int n = 0; n < motion.getNumJoints(); ++n) - { - auto tracker = std::make_unique(); - tracker->setup(motion.getJoint(n)); - trackers.push_back(std::move(tracker)); - } - } - } -} - -//-------------------------------------------------------------- -void testApp::update() -{ - rotate += 0.1; - - play_rate += (play_rate_t - play_rate) * 0.3; - if (audioReady) track.setSpeed(play_rate); - if (!assetsReady) return; - - const float motionDuration = bvh[0].getDuration(); - float motionSeconds = 0.0f; - if (audioReady) { - motionSeconds = track.getPosition() * track.getDuration(); - } else { - fallbackPlayhead += ofGetLastFrameTime() * play_rate; - fallbackPlayhead = std::fmod(fallbackPlayhead, motionDuration); - if (fallbackPlayhead < 0.0f) fallbackPlayhead += motionDuration; - motionSeconds = fallbackPlayhead; - } - const float t = ofClamp(motionSeconds / motionDuration, 0.0f, 1.0f); - - for (auto& motion : bvh) - { - motion.setPosition(t); - motion.update(); - } - - for (auto& tracker : trackers) - { - tracker->update(); - } -} - -//-------------------------------------------------------------- -void testApp::draw(){ - ofEnableDepthTest(); - - ofEnableBlendMode(OF_BLENDMODE_ALPHA); - - ofPushMatrix(); - { - ofTranslate(ofGetWidth()/2, ofGetHeight()/2); - ofTranslate(0, 150); - - ofRotateDeg(-15, 1, 0, 0); - ofRotateDeg(rotate, 0, 1, 0); - - ofScale(1, -1, 1); - - ofSetColor(ofColor::white); - - ofFill(); - - // draw ground - ofPushMatrix(); - ofRotateDeg(90, 1, 0, 0); - ofDrawLine(100, 0, -100, 0); - ofDrawLine(0, 100, 0, -100); - ofPopMatrix(); - - // draw actor - for (auto& motion : bvh) - { - motion.draw(); - } - - // draw tracker - ofDisableDepthTest(); - ofEnableBlendMode(OF_BLENDMODE_ADD); - - ofSetColor(ofColor::white, 80); - for (auto& tracker : trackers) - { - tracker->draw(); - } - } - ofPopMatrix(); - - ofSetColor(255); - ofDrawBitmapString("press any key to scratch\nplay_rate: " + ofToString(play_rate, 1), 10, 20); - if (!assetsReady) - ofDrawBitmapString("Motion data is missing. See README.md.", 10, 65); - else if (!audioReady) - ofDrawBitmapString("Audio data is missing; running with a silent clock.", 10, 65); -} - -//-------------------------------------------------------------- -void testApp::keyPressed(int key){ - play_rate_t = -1; -} - -//-------------------------------------------------------------- -void testApp::keyReleased(int key){ - play_rate_t = 1; -} - -//-------------------------------------------------------------- -void testApp::mouseMoved(int x, int y ){ - -} - -//-------------------------------------------------------------- -void testApp::mouseDragged(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mousePressed(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mouseReleased(int x, int y, int button){ -} - -//-------------------------------------------------------------- -void testApp::windowResized(int w, int h){ -} - -//-------------------------------------------------------------- -void testApp::gotMessage(ofMessage msg){ - -} - -//-------------------------------------------------------------- -void testApp::dragEvent(ofDragInfo dragInfo){ -} diff --git a/example-sync-sound/src/testApp.h b/example-sync-sound/src/testApp.h deleted file mode 100644 index b39cbd2..0000000 --- a/example-sync-sound/src/testApp.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "ofMain.h" -#include "ofxBvh.h" - -#include - -class testApp : public ofBaseApp { - - public: - void setup() override; - void update() override; - void draw() override; - - void keyPressed(int key) override; - void keyReleased(int key) override; - void mouseMoved(int x, int y) override; - void mouseDragged(int x, int y, int button) override; - void mousePressed(int x, int y, int button) override; - void mouseReleased(int x, int y, int button) override; - void windowResized(int w, int h) override; - void dragEvent(ofDragInfo dragInfo) override; - void gotMessage(ofMessage msg) override; - - ofSoundPlayer track; - std::array bvh; - - float rotate = 0.0f; - - float play_rate = 1.0f; - float play_rate_t = 1.0f; - float fallbackPlayhead = 0.0f; - bool assetsReady = false; - bool audioReady = false; -}; diff --git a/marching-cubes/marching-cubes.xcodeproj/project.pbxproj b/marching-cubes/marching-cubes.xcodeproj/project.pbxproj index 848bd4b..2ced9f6 100644 --- a/marching-cubes/marching-cubes.xcodeproj/project.pbxproj +++ b/marching-cubes/marching-cubes.xcodeproj/project.pbxproj @@ -98,7 +98,7 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.cpp", - "name": "testApp.cpp", + "name": "ofApp.cpp", "sourceTree": "" }, "622082E4-6557-44E8-9FB4-AF3BC4FB0BD3": { @@ -415,7 +415,7 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.h", - "name": "testApp.h", + "name": "ofApp.h", "sourceTree": "" }, "EBF0D554-7142-497D-9EDD-EBDC8A29A6D9": { diff --git a/marching-cubes/src/MetaBall.h b/marching-cubes/src/MetaBall.h index 3f0eaf1..4a2d696 100644 --- a/marching-cubes/src/MetaBall.h +++ b/marching-cubes/src/MetaBall.h @@ -1,32 +1,16 @@ #pragma once #include "ofMain.h" -#include "ofxMarchingCubes.h" -class MetaBall: public ofPoint{ -public: - ofPoint accel, vel; - float size; - MetaBall(){ - size = ofRandom(5, 10); - } - - void init(const ofPoint& _pos){ - x = _pos.x; - y = _pos.y; - } - - void goTo(const ofPoint& target, float k = 0.1f, float damp = 0.9f){ - accel = (target - *this)*k; - vel += accel; - vel *= damp; - *this += vel; - } - - void update(const ofPoint& _force, float damp = 0.9f){ - vel += _force; - vel *= damp; - *this += vel; +struct MetaBall { + glm::vec3 position{0}; + glm::vec3 velocity{0}; + float size = 1.4f; + + void follow(const glm::vec3& target, float deltaSeconds) { + const float steps = std::min(deltaSeconds * 60.0f, 4.0f); + velocity += (target - position) * 0.3f * steps; + velocity *= std::pow(0.94f, steps); + position += velocity * steps; } }; - diff --git a/marching-cubes/src/main.cpp b/marching-cubes/src/main.cpp index 3e1e85a..d07fe7c 100644 --- a/marching-cubes/src/main.cpp +++ b/marching-cubes/src/main.cpp @@ -1,14 +1,5 @@ -#include "ofMain.h" -#include "testApp.h" +#include "ofApp.h" -//======================================================================== -int main() { - ofGLWindowSettings settings; - settings.setSize(1280, 720); - settings.setGLVersion(2, 1); - settings.windowMode = OF_WINDOW; - - auto window = ofCreateWindow(settings); - ofRunApp(window, std::make_shared()); - ofRunMainLoop(); +int main(int argc, char** argv) { + return example::launch(argc, argv, "marching-cubes"); } diff --git a/marching-cubes/src/ofApp.cpp b/marching-cubes/src/ofApp.cpp new file mode 100644 index 0000000..1231859 --- /dev/null +++ b/marching-cubes/src/ofApp.cpp @@ -0,0 +1,70 @@ +#include "ofApp.h" + +void ofApp::setup() { + runtime.setup(); + playback.load("marching-cubes", false, runtime.isSmokeTest()); + camera.setFov(30); + camera.setDistance(700); + // The vendored addon retains ofPoint in its public interface. + marchingCubes.init(ofPoint(0, 0, 0), ofPoint(550, 550, 550), 60, 60, 60); + if (playback.ready) { + for (auto& motion : playback.motions) { + for (int i = 0; i < motion.getNumJoints(); ++i) { + const auto* joint = motion.getJoint(i); + if (joint->isSite()) balls.push_back({joint, {glm::vec3(joint->getPosition())}}); + } + } + } + surface.setMode(OF_PRIMITIVE_TRIANGLES); + light.setPosition(200, 350, 500); + light.setAmbientColor(ofFloatColor(0.1f, 0.3f, 0.8f)); + light.setDiffuseColor(ofFloatColor(0.7f)); + light.setSpecularColor(ofFloatColor(1.0f, 0.5f, 0.0f)); + material.setDiffuseColor(ofFloatColor(0.8f)); + material.setSpecularColor(ofFloatColor(1.0f)); + material.setShininess(60); +} + +void ofApp::update() { + playback.update(runtime.deltaSeconds()); + if (!playback.ready) return; + marchingCubes.resetIsoValues(); + for (auto& tracked : balls) { + tracked.ball.follow(glm::vec3(tracked.joint->getPosition()), runtime.deltaSeconds()); + const auto& position = tracked.ball.position; + marchingCubes.addMetaBall(ofPoint(position.x, position.y, position.z), tracked.ball.size); + } + marchingCubes.update(0.17f, true); + surface.clear(); + const auto& vertices = marchingCubes.getVertices(); + const auto& normals = marchingCubes.getNormals(); + for (size_t i = 0; i < vertices.size(); ++i) { + surface.addVertex(glm::vec3(vertices[i])); + surface.addNormal(glm::vec3(normals[i])); + } +} + +void ofApp::draw() { + ofBackground(34); + ofEnableDepthTest(); + camera.begin(); + light.enable(); + material.begin(); + ofPushMatrix(); + ofTranslate(0, -80); + ofRotateXDeg(5); + ofSetColor(255); + surface.draw(); + ofPopMatrix(); + material.end(); + light.disable(); + camera.end(); + ofDisableDepthTest(); + ofSetColor(255); + playback.drawStatus(); + runtime.finishFrame(playback.ready, "marching-cubes", surface.getNumVertices()); +} + +void ofApp::keyPressed(int key) { + if (key == 'f') ofToggleFullscreen(); +} diff --git a/marching-cubes/src/ofApp.h b/marching-cubes/src/ofApp.h new file mode 100644 index 0000000..de75029 --- /dev/null +++ b/marching-cubes/src/ofApp.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../../shared/ExampleRuntime.h" +#include "ofxMarchingCubes.h" +#include "MetaBall.h" + +class ofApp : public ofBaseApp { +public: + explicit ofApp(const example::RunOptions& options) : runtime(options) {} + void setup() override; + void update() override; + void draw() override; + void keyPressed(int key) override; + +private: + struct TrackedBall { + const ofxBvhJoint* joint = nullptr; + MetaBall ball; + }; + example::Runtime runtime; + example::MotionPlayback playback; + ofEasyCam camera; + ofxMarchingCubes marchingCubes; + std::vector balls; + ofVboMesh surface; + ofLight light; + ofMaterial material; +}; diff --git a/marching-cubes/src/testApp.cpp b/marching-cubes/src/testApp.cpp deleted file mode 100644 index 6ad4129..0000000 --- a/marching-cubes/src/testApp.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include "testApp.h" - -namespace { - -const std::array kPerfumeMotionFiles = { - "bvhfiles/aachan.bvh", - "bvhfiles/kashiyuka.bvh", - "bvhfiles/nocchi.bvh" -}; - -const std::array kBundledMotionFiles = { - "../../../example-bvh/bin/data/A_test.bvh", - "../../../example-bvh/bin/data/B_test.bvh", - "../../../example-bvh/bin/data/C_test.bvh" -}; - -bool loadMotionFiles(std::array& motions) { - bool loaded = true; - for (size_t i = 0; i < motions.size(); ++i) { - if (!motions[i].load(kPerfumeMotionFiles[i])) { - ofLogWarning("marching-cubes") - << "Using bundled motion fallback for " << kPerfumeMotionFiles[i]; - loaded = motions[i].load(kBundledMotionFiles[i]) && loaded; - } - } - return loaded; -} - -} // namespace - -float startTime = 0.02; - -//-------------------------------------------------------------- -void testApp::setup() { - ofSetFrameRate(60); - ofSetVerticalSync(true); - - rotate = 0; - - assetsReady = loadMotionFiles(bvh); - - audioReady = ofFile::doesFileExist("Perfume_globalsite_sound.wav") - && track.load("Perfume_globalsite_sound.wav"); - if (audioReady) { - track.setLoop(true); - track.play(); - } else { - ofLogNotice("marching-cubes") - << "Audio file not found; using a silent internal clock."; - } - - camera.setFov(30); - camera.setDistance(700); - - // MarchingCube init - ofPoint iniPos(0,0,0); - ofPoint gridSize(550, 550, 550); - int gridResX = 60; - int gridResY = 60; - int gridResZ = 60; - marchingCubes.init(iniPos, gridSize, gridResX, gridResY, gridResZ); - - // Metaball init - int metaballNum = bvh[0].getNumJoints() + bvh[1].getNumJoints() + bvh[2].getNumJoints(); - metaBalls.resize(metaballNum); - - int n = 0; - for (size_t i = 0; i < bvh.size(); ++i){ - for (int j = 0; j < bvh[i].getNumJoints(); j++) { - const ofxBvhJoint *o = bvh[i].getJoint(j); - if (o->isSite()) { - metaBalls[n].init(o->getPosition()); - metaBalls[n].size = 1.4; - } - n++; - } - } - - light.enable(); - light.setAmbientColor(ofFloatColor(0.1, 0.3, 0.8, 1.0)); - light.setDiffuseColor(ofFloatColor(0.7, 0.7, 0.7)); - light.setSpecularColor(ofFloatColor(1.0, 0.5, 0.0)); -} - -//-------------------------------------------------------------- -void testApp::update(){ - if (!assetsReady) return; - const float motionDuration = bvh[0].getDuration(); - const float motionSeconds = audioReady - ? track.getPosition() * track.getDuration() - : std::fmod(ofGetElapsedTimef(), motionDuration); - const float t = ofClamp(motionSeconds / motionDuration, 0.0f, 1.0f); - - for (auto& motion : bvh) { - motion.setPosition(t); - motion.update(); - } - - marchingCubes.resetIsoValues(); - - int n = 0; - for (size_t i = 0; i < bvh.size(); ++i){ - for (int j = 0; j < bvh[i].getNumJoints(); j++) { - const ofxBvhJoint *o = bvh[i].getJoint(j); - if (o->isSite()) { - if (t > startTime) { - metaBalls[n].goTo(o->getPosition(), 0.3, 0.94); - marchingCubes.addMetaBall(metaBalls[n], metaBalls[n].size); - } else { - metaBalls[n].goTo(o->getPosition(), 1.0, 0.1); - } - } - n++; - } - } - - marchingCubes.update(threshold, true); -} - -//-------------------------------------------------------------- -void testApp::draw(){ - ofBackgroundHex(0x222222); - - camera.begin(); - ofPushMatrix(); - { - ofTranslate(0, -80); - ofRotateDeg(5, 1, 0, 0); - ofScale(1, 1, 1); - - // draw MarchingCubes - vector& vertices = marchingCubes.getVertices(); - vector& normals = marchingCubes.getNormals(); - int numVertices = vertices.size(); - - glEnable(GL_DEPTH_TEST); - glColor3f(1.0f, 1.0f, 1.0f); - glBegin(GL_TRIANGLES); - - for(int i=0; i - -class testApp : public ofBaseApp { - - public: - void setup() override; - void update() override; - void draw() override; - void exit() override; - - void keyPressed(int key) override; - void keyReleased(int key) override; - void mouseMoved(int x, int y) override; - void mouseDragged(int x, int y, int button) override; - void mousePressed(int x, int y, int button) override; - void mouseReleased(int x, int y, int button) override; - void windowResized(int w, int h) override; - void dragEvent(ofDragInfo dragInfo) override; - void gotMessage(ofMessage msg) override; - - ofSoundPlayer track; - std::array bvh; - - float rotate = 0.0f; - float play_rate = 1.0f; - float play_rate_t = 1.0f; - - ofEasyCam camera; - ofImage background; - - ofxMarchingCubes marchingCubes; - vector metaBalls; - - float threshold = 0.17f; - ofLight light; - bool assetsReady = false; - bool audioReady = false; -}; diff --git a/motion-visualization/motion-visualization.xcodeproj/project.pbxproj b/motion-visualization/motion-visualization.xcodeproj/project.pbxproj index fbbd96f..02d79e3 100644 --- a/motion-visualization/motion-visualization.xcodeproj/project.pbxproj +++ b/motion-visualization/motion-visualization.xcodeproj/project.pbxproj @@ -71,7 +71,7 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.h", - "name": "testApp.h", + "name": "ofApp.h", "sourceTree": "" }, "A275555F-3A37-4876-8C1F-33BE548EB6DC": { @@ -346,7 +346,7 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.cpp", - "name": "testApp.cpp", + "name": "ofApp.cpp", "sourceTree": "" }, "F77F8C76-5ABD-4EC6-9124-D6447EDF405A": { diff --git a/motion-visualization/src/main.cpp b/motion-visualization/src/main.cpp index 3e1e85a..ccad0c3 100644 --- a/motion-visualization/src/main.cpp +++ b/motion-visualization/src/main.cpp @@ -1,14 +1,5 @@ -#include "ofMain.h" -#include "testApp.h" +#include "ofApp.h" -//======================================================================== -int main() { - ofGLWindowSettings settings; - settings.setSize(1280, 720); - settings.setGLVersion(2, 1); - settings.windowMode = OF_WINDOW; - - auto window = ofCreateWindow(settings); - ofRunApp(window, std::make_shared()); - ofRunMainLoop(); +int main(int argc, char** argv) { + return example::launch(argc, argv, "motion-visualization"); } diff --git a/motion-visualization/src/ofApp.cpp b/motion-visualization/src/ofApp.cpp new file mode 100644 index 0000000..97e600b --- /dev/null +++ b/motion-visualization/src/ofApp.cpp @@ -0,0 +1,72 @@ +#include "ofApp.h" + +void ofApp::setup() { + runtime.setup(); + playback.load("motion-visualization", false, runtime.isSmokeTest()); + if (playback.ready) { + for (auto& motion : playback.motions) { + for (int i = 0; i < motion.getNumJoints(); ++i) trails.push_back({motion.getJoint(i), {}}); + } + } + camera.setFov(45); + camera.setDistance(520); + camera.disableMouseInput(); + if (ofFile::doesFileExist("background.png")) background.load("background.png"); + ribbons.setMode(OF_PRIMITIVE_TRIANGLES); +} + +void ofApp::update() { + rotation += runtime.deltaSeconds() * 2.4f; + playback.update(runtime.deltaSeconds()); + if (!playback.ready) return; + for (auto& trail : trails) { + const glm::vec3 position(trail.joint->getPosition()); + if (trail.points.empty() || glm::distance(position, trail.points.front()) > 1.0f) { + trail.points.push_front(position); + if (trail.points.size() > 200) trail.points.pop_back(); + } + } +} + +void ofApp::draw() { + ofBackground(0); + ofSetColor(255); + if (background.isAllocated()) background.draw(0, 0, ofGetWidth(), ofGetHeight()); + ofEnableBlendMode(OF_BLENDMODE_ADD); + camera.begin(); + ofPushMatrix(); + ofTranslate(0, -80); + ofRotateYDeg(rotation); + + // Camera-facing triangle ribbons replace unsupported wide core-profile lines. + const glm::mat4 inverseView = glm::inverse(ofGetCurrentMatrix(OF_MATRIX_MODELVIEW)); + const glm::vec3 viewDirection = example::safeNormalize(glm::vec3(inverseView[2])); + ribbons.clear(); + for (const auto& trail : trails) { + for (size_t i = 0; i + 1 < trail.points.size(); ++i) { + const auto& a = trail.points[i]; + const auto& b = trail.points[i + 1]; + const float distance = glm::distance(a, b); + if (distance <= 1e-6f || distance >= 40.0f) continue; + const auto side = example::safeNormalize(glm::cross(b - a, viewDirection)) + * ofMap(distance, 0, 30, 0.2f, 2.4f, true); + const ofFloatColor color(ofColor(ofClamp(distance * 20, 0, 255), + ofClamp(127 - distance * 10, 0, 255), ofClamp(255 - distance * 20, 0, 255))); + for (const auto& vertex : {a - side, a + side, b + side, a - side, b + side, b - side}) { + ribbons.addVertex(vertex); + ribbons.addColor(color); + } + } + } + ribbons.draw(); + ofPopMatrix(); + camera.end(); + ofEnableBlendMode(OF_BLENDMODE_ALPHA); + ofSetColor(255); + playback.drawStatus(); + runtime.finishFrame(playback.ready, "motion-visualization", ribbons.getNumVertices()); +} + +void ofApp::keyPressed(int key) { + if (key == 'f') ofToggleFullscreen(); +} diff --git a/motion-visualization/src/ofApp.h b/motion-visualization/src/ofApp.h new file mode 100644 index 0000000..e70eb3d --- /dev/null +++ b/motion-visualization/src/ofApp.h @@ -0,0 +1,26 @@ +#pragma once + +#include "../../shared/ExampleRuntime.h" +#include + +class ofApp : public ofBaseApp { +public: + explicit ofApp(const example::RunOptions& options) : runtime(options) {} + void setup() override; + void update() override; + void draw() override; + void keyPressed(int key) override; + +private: + struct Trail { + const ofxBvhJoint* joint = nullptr; + std::deque points; + }; + example::Runtime runtime; + example::MotionPlayback playback; + std::vector trails; + ofEasyCam camera; + ofImage background; + ofVboMesh ribbons; + float rotation = 0.0f; +}; diff --git a/motion-visualization/src/testApp.cpp b/motion-visualization/src/testApp.cpp deleted file mode 100644 index bb79afe..0000000 --- a/motion-visualization/src/testApp.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#include "testApp.h" - -#include - -namespace { - -const std::array kPerfumeMotionFiles = { - "bvhfiles/aachan.bvh", - "bvhfiles/kashiyuka.bvh", - "bvhfiles/nocchi.bvh" -}; - -const std::array kBundledMotionFiles = { - "../../../example-bvh/bin/data/A_test.bvh", - "../../../example-bvh/bin/data/B_test.bvh", - "../../../example-bvh/bin/data/C_test.bvh" -}; - -bool loadMotionFiles(std::array& motions) { - bool loaded = true; - for (size_t i = 0; i < motions.size(); ++i) { - if (!motions[i].load(kPerfumeMotionFiles[i])) { - ofLogWarning("motion-visualization") - << "Using bundled motion fallback for " << kPerfumeMotionFiles[i]; - loaded = motions[i].load(kBundledMotionFiles[i]) && loaded; - } - } - return loaded; -} - -} // namespace - -int trackerLength = 200; -float startTime = 0.035; - -class Tracker -{ -public: - - const ofxBvhJoint *joint = nullptr; - deque points; - float trackerLength = 0.0f; - - void setup(const ofxBvhJoint *o){ - joint = o; - } - - void update() { - const ofVec3f &p = joint->getPosition(); - - if (points.empty() || p.distance(points.front()) > 1) - points.push_front(joint->getPosition()); - - if (points.size() > trackerLength){ - points.pop_back(); - } - } - - void draw() { - if (points.empty()) return; - - for (size_t i = 0; i + 1 < points.size(); ++i){ - ofVec3f &p0 = points[i]; - ofVec3f &p1 = points[i + 1]; - - float dist = p0.distance(p1); - - if (dist < 40) { - ofSetLineWidth(ofMap(dist, 0, 30, 0, 14)); - ofSetColor(dist*20, 127-dist*10, 255-dist*20); - ofDrawLine(p0.x, p0.y, p0.z, p1.x, p1.y, p1.z); - } - } - } - - void clear() { - points.clear(); - } - - void setTrackerLength(float _trackerLength) { - trackerLength = _trackerLength; - } -}; - -vector> trackers; - -//-------------------------------------------------------------- -void testApp::setup() { - ofSetFrameRate(60); - ofSetVerticalSync(true); - - rotate = 0; - - assetsReady = loadMotionFiles(bvh); - - audioReady = ofFile::doesFileExist("Perfume_globalsite_sound.wav") - && track.load("Perfume_globalsite_sound.wav"); - if (audioReady) { - track.setLoop(true); - track.play(); - } else { - ofLogNotice("motion-visualization") - << "Audio file not found; using a silent internal clock."; - } - - // setup tracker - if (assetsReady) - { - for (auto& motion : bvh) { - for (int n = 0; n < motion.getNumJoints(); ++n) { - auto tracker = std::make_unique(); - tracker->setup(motion.getJoint(n)); - tracker->setTrackerLength(trackerLength); - trackers.push_back(std::move(tracker)); - } - } - } - - camera.setFov(45); - camera.setDistance(360); - camera.disableMouseInput(); - - background.load("background.png"); - -} - -//-------------------------------------------------------------- -void testApp::update() -{ - rotate += 0.04; - - if (!assetsReady) return; - const float motionDuration = bvh[0].getDuration(); - const float motionSeconds = audioReady - ? track.getPosition() * track.getDuration() - : std::fmod(ofGetElapsedTimef(), motionDuration); - const float t = ofClamp(motionSeconds / motionDuration, 0.0f, 1.0f); - - for (auto& motion : bvh) { - motion.setPosition(t); - motion.update(); - } - - for (auto& tracker : trackers) { - if (t > startTime) { - tracker->setTrackerLength(trackerLength); - tracker->update(); - } - } -} - -//-------------------------------------------------------------- -void testApp::draw(){ - ofBackgroundHex(0x000000); - ofSetHexColor(0xffffff); - background.draw(0,0,ofGetWidth(),ofGetHeight()); - - ofEnableDepthTest(); - - camera.begin(); - ofPushMatrix(); - { - ofTranslate(0, -80); - ofRotateDeg(rotate, 0, 1, 0); - ofScale(1, 1, 1); - - // draw tracker - ofDisableDepthTest(); - ofEnableBlendMode(OF_BLENDMODE_ADD); - - //ofSetColor(ofColor::white, 80); - for (auto& tracker : trackers){ - tracker->draw(); - } - - } - ofPopMatrix(); - camera.end(); - ofDisableDepthTest(); - ofSetColor(255); - - if (!assetsReady) - ofDrawBitmapString("Motion data is missing. See README.md.", 10, 20); - else if (!audioReady) - ofDrawBitmapString("Audio data is missing; running with a silent clock.", 10, 20); - -} - -void testApp::exit(){ - -} - -//-------------------------------------------------------------- -void testApp::keyPressed(int key){ - if (key == 'f') { - ofToggleFullscreen(); - } -} - -//-------------------------------------------------------------- -void testApp::keyReleased(int key){ - -} - -//-------------------------------------------------------------- -void testApp::mouseMoved(int x, int y ){ - -} - -//-------------------------------------------------------------- -void testApp::mouseDragged(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mousePressed(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mouseReleased(int x, int y, int button){ -} - -//-------------------------------------------------------------- -void testApp::windowResized(int w, int h){ -} - -//-------------------------------------------------------------- -void testApp::gotMessage(ofMessage msg){ - -} - -//-------------------------------------------------------------- -void testApp::dragEvent(ofDragInfo dragInfo){ -} diff --git a/motion-visualization/src/testApp.h b/motion-visualization/src/testApp.h deleted file mode 100644 index 7108383..0000000 --- a/motion-visualization/src/testApp.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "ofMain.h" -#include "ofxBvh.h" - -#include - -class testApp : public ofBaseApp { - - public: - void setup() override; - void update() override; - void draw() override; - void exit() override; - - void keyPressed(int key) override; - void keyReleased(int key) override; - void mouseMoved(int x, int y) override; - void mouseDragged(int x, int y, int button) override; - void mousePressed(int x, int y, int button) override; - void mouseReleased(int x, int y, int button) override; - void windowResized(int w, int h) override; - void dragEvent(ofDragInfo dragInfo) override; - void gotMessage(ofMessage msg) override; - - ofSoundPlayer track; - std::array bvh; - - float rotate = 0.0f; - float play_rate = 1.0f; - float play_rate_t = 1.0f; - - ofEasyCam camera; - ofImage background; - bool assetsReady = false; - bool audioReady = false; -}; diff --git a/ofxBvh/src/ofxBvh.cpp b/ofxBvh/src/ofxBvh.cpp index 385b96d..a7f0a2e 100644 --- a/ofxBvh/src/ofxBvh.cpp +++ b/ofxBvh/src/ofxBvh.cpp @@ -5,8 +5,6 @@ #include #include -static inline void billboard(); - namespace { bool parseFloatToken(const string& token, float& value) @@ -283,42 +281,32 @@ void ofxBvh::update(float deltaSeconds) void ofxBvh::draw() { if (!isLoaded()) return; - - ofPushStyle(); - ofFill(); - - for (int i = 0; i < joints.size(); i++) - { - ofxBvhJoint *o = joints[i]; - glPushMatrix(); - glMultMatrixf(o->getGlobalMatrix().getPtr()); - - if (o->isSite()) - { - ofSetColor(ofColor::yellow); - billboard(); - ofDrawCircle(0, 0, 6); - } - else if (o->getChildren().size() == 1) - { - ofSetColor(ofColor::white); - billboard(); - ofDrawCircle(0, 0, 2); - } - else if (o->getChildren().size() > 1) - { - if (o->isRoot()) - ofSetColor(ofColor::cyan); - else - ofSetColor(ofColor::green); - - billboard(); - ofDrawCircle(0, 0, 4); + // Build camera-facing discs using the renderer's GLM matrix stack. + // No fixed-function OpenGL calls: this works in a 3.2 core context. + const glm::mat4 inverseView = glm::inverse(ofGetCurrentMatrix(OF_MATRIX_MODELVIEW)); + const glm::vec3 right(inverseView[0]); + const glm::vec3 up(inverseView[1]); + ofMesh discs; + discs.setMode(OF_PRIMITIVE_TRIANGLES); + constexpr int segments = 16; + for (const auto* joint : joints) { + const glm::vec3 position(joint->getPosition()); + const float radius = joint->isSite() ? 6.0f : (joint->getChildren().size() == 1 ? 2.0f : 4.0f); + const ofFloatColor color(joint->isSite() ? ofColor::yellow + : joint->isRoot() ? ofColor::cyan + : joint->getChildren().size() > 1 ? ofColor::green : ofColor::white); + for (int segment = 0; segment < segments; ++segment) { + const float a = TWO_PI * float(segment) / segments; + const float b = TWO_PI * float(segment + 1) / segments; + discs.addVertex(position); + discs.addVertex(position + radius * (right * std::cos(a) + up * std::sin(a))); + discs.addVertex(position + radius * (right * std::cos(b) + up * std::sin(b))); + for (int vertex = 0; vertex < 3; ++vertex) discs.addColor(color); } - - glPopMatrix(); } - + ofPushStyle(); + ofSetColor(255); + discs.draw(); ofPopStyle(); } @@ -604,53 +592,3 @@ const ofxBvhJoint* ofxBvh::getJoint(const string& name) const const auto it = jointMap.find(name); return it == jointMap.end() ? nullptr : it->second; } - -static inline void billboard() -{ - GLfloat m[16]; - glGetFloatv(GL_MODELVIEW_MATRIX, m); - - constexpr float epsilon = 1e-12f; - - m[8] = -m[12]; - m[9] = -m[13]; - m[10] = -m[14]; - float lengthSquared = m[8] * m[8] + m[9] * m[9] + m[10] * m[10]; - if (lengthSquared > epsilon) - { - const float inverseLength = 1.0f / std::sqrt(lengthSquared); - m[8] *= inverseLength; - m[9] *= inverseLength; - m[10] *= inverseLength; - } - else - { - m[8] = 0.0f; - m[9] = 0.0f; - m[10] = 1.0f; - } - - m[0] = -m[14]; - m[1] = 0.0; - m[2] = m[12]; - lengthSquared = m[0] * m[0] + m[1] * m[1] + m[2] * m[2]; - if (lengthSquared > epsilon) - { - const float inverseLength = 1.0f / std::sqrt(lengthSquared); - m[0] *= inverseLength; - m[1] *= inverseLength; - m[2] *= inverseLength; - } - else - { - m[0] = 1.0f; - m[1] = 0.0f; - m[2] = 0.0f; - } - - m[4] = m[9] * m[2] - m[10] * m[1]; - m[5] = m[10] * m[0] - m[8] * m[2]; - m[6] = m[8] * m[1] - m[9] * m[0]; - - glLoadMatrixf(m); -} diff --git a/particle-motion-example/particle-motion-example.xcodeproj/project.pbxproj b/particle-motion-example/particle-motion-example.xcodeproj/project.pbxproj index 5e2f048..cc2d64e 100644 --- a/particle-motion-example/particle-motion-example.xcodeproj/project.pbxproj +++ b/particle-motion-example/particle-motion-example.xcodeproj/project.pbxproj @@ -62,7 +62,7 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.cpp", - "name": "testApp.cpp", + "name": "ofApp.cpp", "sourceTree": "" }, "9BE696A4-1E70-463C-B9BE-75BAC6A5A775": { @@ -350,7 +350,7 @@ "fileEncoding": "4", "isa": "PBXFileReference", "lastKnownFileType": "sourcecode.cpp.h", - "name": "testApp.h", + "name": "ofApp.h", "sourceTree": "" } }, diff --git a/particle-motion-example/src/main.cpp b/particle-motion-example/src/main.cpp index 1349dcd..842ef2c 100644 --- a/particle-motion-example/src/main.cpp +++ b/particle-motion-example/src/main.cpp @@ -1,14 +1,5 @@ -#include "ofMain.h" -#include "testApp.h" +#include "ofApp.h" -//======================================================================== -int main() { - ofGLWindowSettings settings; - settings.setSize(1280, 768); - settings.setGLVersion(2, 1); - settings.windowMode = OF_WINDOW; - - auto window = ofCreateWindow(settings); - ofRunApp(window, std::make_shared()); - ofRunMainLoop(); +int main(int argc, char** argv) { + return example::launch(argc, argv, "particle-motion-example"); } diff --git a/particle-motion-example/src/ofApp.cpp b/particle-motion-example/src/ofApp.cpp new file mode 100644 index 0000000..b9176e8 --- /dev/null +++ b/particle-motion-example/src/ofApp.cpp @@ -0,0 +1,144 @@ +#include "ofApp.h" + +void ofApp::Trail::update() { + samples.emplace_front(joint->getPosition()); + if (samples.size() > 10) samples.pop_back(); + float distance = 0.0f; + float alignment = 0.0f; + for (size_t i = 0; i + 1 < samples.size(); ++i) distance += glm::distance(samples[i], samples[i + 1]); + for (size_t i = 1; i + 1 < samples.size(); ++i) { + const auto a = samples[i - 1] - samples[i]; + const auto b = samples[i] - samples[i + 1]; + if (glm::dot(a, a) > 1e-12f && glm::dot(b, b) > 1e-12f) alignment += glm::dot(glm::normalize(a), glm::normalize(b)); + } + if (samples.size() > 2) alignment /= float(samples.size() - 2); + const float brightness = ofMap(distance, 30, 40, 0, 1, true) * ofClamp(alignment, 0.0f, 1.0f); + mesh.clear(); + mesh.setMode(OF_PRIMITIVE_LINE_STRIP); + for (size_t i = 0; i < samples.size(); ++i) { + const float age = samples.size() > 1 ? float(i) / float(samples.size() - 1) : 0.0f; + mesh.addVertex(samples[i]); + mesh.addColor(ofFloatColor(brightness, brightness, brightness, 0.55f * (1.0f - age))); + } +} + +void ofApp::ParticleShape::setup(ofxBvh& source) { + motion = &source; + for (int i = 1; i < source.getNumJoints(); ++i) { + const auto* joint = source.getJoint(i); + if (joint->getName().find("Chest") == std::string::npos) { + Trail trail; + trail.joint = joint; + trails.push_back(std::move(trail)); + } + } + particles.resize(15000); + points.setMode(OF_PRIMITIVE_POINTS); + points.getVertices().resize(particles.size()); +} + +void ofApp::ParticleShape::update(float deltaSeconds) { + const float steps = std::min(deltaSeconds * 60.0f, 4.0f); + for (auto& particle : particles) particle.force = glm::vec3(0); + if (motion->isFrameNew()) { + for (auto& trail : trails) { + trail.update(); + const glm::vec3 position(trail.joint->getPosition()); + for (auto& particle : particles) { + auto direction = particle.position - position; + const float squaredDistance = glm::dot(direction, direction); + if (squaredDistance > 1e-4f && squaredDistance < 900.0f) { + const float distance = std::sqrt(squaredDistance); + particle.force += (0.4f / squaredDistance - 1.6f / std::pow(distance, 1.1f)) * direction / distance * 2.0f; + } + } + for (int i = 0; i < 10; ++i) { + particles[nextParticle] = {position, glm::vec3(0), glm::vec3(0)}; + nextParticle = (nextParticle + 1) % particles.size(); + } + } + } + for (size_t i = 0; i < particles.size(); ++i) { + auto& particle = particles[i]; + particle.force.y -= 0.1f; + particle.velocity *= std::pow(0.98f, steps); + particle.velocity += particle.force * 0.9f * steps; + particle.position += particle.velocity * 0.9f * steps; + if (particle.position.y < 0) { + particle.position.y = 0; + particle.velocity *= std::pow(0.95f, steps); + } + points.setVertex(i, particle.position); + } +} + +void ofApp::setup() { + runtime.setup(); + ofBackground(0); + playback.load("particle-motion-example", false, runtime.isSmokeTest()); + if (playback.ready) { + for (size_t i = 0; i < shapes.size(); ++i) shapes[i].setup(playback.motions[i]); + } + camera.setDistance(450); + // gl_PointCoord supplies a soft circular sprite without a texture dependency. + shaderReady = pointShader.setupShaderFromSource(GL_VERTEX_SHADER, R"GLSL(#version 150 +uniform mat4 modelViewProjectionMatrix; +uniform mat4 modelViewMatrix; +in vec4 position; +void main() { + vec4 viewPosition = modelViewMatrix * position; + gl_Position = modelViewProjectionMatrix * position; + gl_PointSize = clamp(1500.0 / max(1.0, -viewPosition.z), 1.0, 12.0); +} +)GLSL"); + shaderReady = pointShader.setupShaderFromSource(GL_FRAGMENT_SHADER, R"GLSL(#version 150 +out vec4 fragColor; +void main() { + float radius = length(gl_PointCoord * 2.0 - 1.0); + float alpha = 0.12 * (1.0 - smoothstep(0.0, 1.0, radius)); + fragColor = vec4(vec3(1.0), alpha); +} +)GLSL") && shaderReady; + pointShader.bindDefaults(); + shaderReady = pointShader.linkProgram() && shaderReady; + GLint linked = GL_FALSE; + glGetProgramiv(pointShader.getProgram(), GL_LINK_STATUS, &linked); + shaderReady = shaderReady && linked == GL_TRUE; +} + +void ofApp::update() { + const float dt = paused ? 0.0f : runtime.deltaSeconds(); + playback.update(dt, paused ? 0.0f : 1.0f); + if (!playback.ready) return; + glm::vec3 average{0}; + for (auto& shape : shapes) { + if (!paused) shape.update(dt); + average += glm::vec3(shape.motion->getJoint(0)->getPosition()); + } + center = glm::mix(center, average / 3.0f, 1.0f - std::exp(-6.3f * dt)); +} + +void ofApp::draw() { + ofDisableDepthTest(); + ofEnableBlendMode(OF_BLENDMODE_ADD); + camera.begin(); + ofPushMatrix(); + ofRotateYDeg(runtime.elapsedSeconds() * 10.0f); + ofTranslate(-center); + for (auto& shape : shapes) for (auto& trail : shape.trails) trail.mesh.draw(); + if (shaderReady) { + glEnable(GL_PROGRAM_POINT_SIZE); + pointShader.begin(); + for (auto& shape : shapes) shape.points.draw(); + pointShader.end(); + glDisable(GL_PROGRAM_POINT_SIZE); + } + ofPopMatrix(); + camera.end(); + ofEnableBlendMode(OF_BLENDMODE_ALPHA); + ofSetColor(255); + playback.drawStatus(); + runtime.finishFrame(playback.ready && shaderReady, "particle-motion-example", shapes.front().points.getNumVertices()); +} + +void ofApp::keyPressed(int) { paused = !paused; } diff --git a/particle-motion-example/src/ofApp.h b/particle-motion-example/src/ofApp.h new file mode 100644 index 0000000..6630a90 --- /dev/null +++ b/particle-motion-example/src/ofApp.h @@ -0,0 +1,43 @@ +#pragma once + +#include "../../shared/ExampleRuntime.h" +#include + +class ofApp : public ofBaseApp { +public: + explicit ofApp(const example::RunOptions& options) : runtime(options) {} + void setup() override; + void update() override; + void draw() override; + void keyPressed(int key) override; + +private: + struct Particle { + glm::vec3 position{0}; + glm::vec3 velocity{0}; + glm::vec3 force{0}; + }; + struct Trail { + const ofxBvhJoint* joint = nullptr; + std::deque samples; + ofVboMesh mesh; + void update(); + }; + struct ParticleShape { + ofxBvh* motion = nullptr; + std::vector trails; + std::vector particles; + ofVboMesh points; + size_t nextParticle = 0; + void setup(ofxBvh& motion); + void update(float deltaSeconds); + }; + example::Runtime runtime; + example::MotionPlayback playback; + std::array shapes; + ofEasyCam camera; + ofShader pointShader; + glm::vec3 center{0}; + bool paused = false; + bool shaderReady = false; +}; diff --git a/particle-motion-example/src/testApp.cpp b/particle-motion-example/src/testApp.cpp deleted file mode 100644 index 1c374d9..0000000 --- a/particle-motion-example/src/testApp.cpp +++ /dev/null @@ -1,393 +0,0 @@ -#include "testApp.h" - -#include -#include - -namespace { - -const std::array kPerfumeMotionFiles = { - "bvhfiles/aachan.bvh", - "bvhfiles/kashiyuka.bvh", - "bvhfiles/nocchi.bvh" -}; - -const std::array kBundledMotionFiles = { - "../../../example-bvh/bin/data/A_test.bvh", - "../../../example-bvh/bin/data/B_test.bvh", - "../../../example-bvh/bin/data/C_test.bvh" -}; - -bool loadMotionFiles(std::array& motions) { - bool loaded = true; - for (size_t i = 0; i < motions.size(); ++i) { - if (!motions[i].load(kPerfumeMotionFiles[i])) { - ofLogWarning("particle-motion-example") - << "Using bundled motion fallback for " << kPerfumeMotionFiles[i]; - loaded = motions[i].load(kBundledMotionFiles[i]) && loaded; - } - } - return loaded; -} - -} // namespace - -class Particle -{ -public: - - ofVec3f pos = {0, 0, 0}; - ofVec3f vel = {0, 0, 0}; - ofVec3f force = {0, 0, 0}; -}; - -class Tracker -{ -public: - - const ofxBvhJoint *joint = nullptr; - deque samples; - - void setup(const ofxBvhJoint *o) - { - joint = o; - } - - void update(vector& particles) - { - const ofVec3f &p = joint->getPosition(); - - // update sample - { - samples.push_front(joint->getPosition()); - while (samples.size() > 10) - samples.pop_back(); - } - - // update particle force - { - const float n = 2.0; - const float A = 0.4; - const float m = 1.1; - const float B = 1.6; - - for (auto& particle : particles) - { - ofVec3f dist = particle.pos - p; - float r = dist.lengthSquared(); - - if (r > 0 && r < 30*30) - { - r = sqrt(r); - dist /= r; - - particle.force += ((A / pow(r, n)) - (B / pow(r, m))) * dist * 2; - } - } - } - } - - float length() - { - if (samples.empty()) return 0; - - float v = 0; - for (size_t i = 0; i + 1 < samples.size(); ++i) - v += samples[i].distance(samples[i + 1]); - - return v; - } - - float dot() - { - if (samples.size() < 3) return 0; - - float v = 0; - - for (size_t i = 1; i + 1 < samples.size(); ++i) - { - const ofVec3f &v0 = samples[i - 1]; - const ofVec3f &v1 = samples[i]; - const ofVec3f &v2 = samples[i + 1]; - - if (v0.squareDistance(v1) == 0) continue; - if (v1.squareDistance(v2) == 0) continue; - - const ofVec3f d0 = (v0 - v1).getNormalized(); - const ofVec3f d1 = (v1 - v2).getNormalized(); - - v += (d0).dot(d1); - } - - return v / ((float)samples.size() - 2); - } - - void draw() - { - if (samples.size() < 2) return; - - float len = length(); - len = ofMap(len, 30, 40, 0, 1, true); - - float d = dot(); - d = ofMap(d, 1, 0, 255, 0, true); - - glBegin(GL_LINE_STRIP); - for (size_t i = 0; i < samples.size(); ++i) - { - float a = ofMap(static_cast(i), 0.0f, - static_cast(samples.size() - 1), 1.0f, 0.0f, true); - ofSetColor(d * len, 140 * a); - glVertex3fv(samples[i].getPtr()); - } - glEnd(); - } -}; - -class ParticleShape -{ -public: - - ofxBvh *bvh = nullptr; - - vector> tracker; - - vector particles; - size_t particle_index = 0; - - void setup(ofxBvh &o) - { - bvh = &o; - - for (int i = 1; i < o.getNumJoints(); ++i) - { - if (bvh->getJoint(i)->getName().find("Chest") == string::npos) - { - auto item = std::make_unique(); - item->setup(bvh->getJoint(i)); - tracker.push_back(std::move(item)); - } - } - - particles.resize(15000); - } - - void update() - { - bvh->update(); - - for (auto& particle : particles) - { - particle.force.set(0, 0, 0); - } - - if (bvh->isFrameNew()) - { - for (auto& item : tracker) - { - // update force - item->update(particles); - - const ofVec3f &p = item->joint->getPosition(); - - // emit 10 particle every frame - for (int i = 0; i < 10; ++i) - { - particles[particle_index].pos.set(p); - - particle_index++; - if (particle_index >= particles.size()) - particle_index = 0; - } - } - } - - // update particle position - for (auto& p : particles) - { - p.force.y += -0.1; - p.vel *= 0.98; - - p.vel += p.force * 0.9; - p.pos += p.vel * 0.9; - - if (p.pos.y <= 0) - { - p.pos.y = 0; - p.vel *= 0.95; - } - } - } - - void draw() - { - // bvh->draw(); - - for (auto& item : tracker) - { - item->draw(); - } - - ofSetColor(255, 15); - glBegin(GL_POINTS); - for (auto& p : particles) - { - glVertex3fv(p.pos.getPtr()); - } - glEnd(); - } -}; - -constexpr size_t NUM_ACTOR = 3; -std::array particle_shapes; -std::array bvh; - -ofSoundPlayer player; - -ofVec3f center; - -//-------------------------------------------------------------- -void testApp::setup() -{ - ofSetFrameRate(60); - ofSetVerticalSync(true); - - ofBackground(0); - - assetsReady = loadMotionFiles(bvh); - - for (size_t i = 0; i < NUM_ACTOR; ++i) - { - bvh[i].setFrame(1); - if (assetsReady) particle_shapes[i].setup(bvh[i]); - } - - audioReady = ofFile::doesFileExist("Perfume_globalsite_sound.wav") - && player.load("Perfume_globalsite_sound.wav"); - if (audioReady) { - player.setLoop(true); - player.play(); - } else { - ofLogNotice("particle-motion-example") - << "Audio file not found; using a silent internal clock."; - } -} - -//-------------------------------------------------------------- -void testApp::update() -{ - if (!assetsReady) return; - const float motionDuration = bvh[0].getDuration(); - const float motionSeconds = audioReady - ? player.getPosition() * player.getDuration() - : std::fmod(ofGetElapsedTimef(), motionDuration); - const float t = ofClamp(motionSeconds / motionDuration, 0.0f, 1.0f); - - ofVec3f avg; - - for (size_t i = 0; i < NUM_ACTOR; ++i) - { - ofxBvh *o = particle_shapes[i].bvh; - - o->setPosition(t); - particle_shapes[i].update(); - - avg += o->getJoint(0)->getPosition(); - } - - avg /= 3; - - center += (avg - center) * 0.1; -} - -//-------------------------------------------------------------- -void testApp::draw() -{ - ofDisableDepthTest(); - ofEnableBlendMode(OF_BLENDMODE_ADD); - - // smooth particle - glEnable(GL_POINT_SMOOTH); - glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); - - static GLfloat distance[] = {0.0, 0.0, 1.0}; - glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, distance); - glPointSize(1500); - - glLineWidth(2); - - cam.begin(); - ofRotateYDeg(ofGetElapsedTimef() * 10); - ofTranslate(-center); - - for (size_t i = 0; i < NUM_ACTOR; ++i) - { - particle_shapes[i].draw(); - } - - cam.end(); - ofEnableBlendMode(OF_BLENDMODE_ALPHA); - ofSetColor(255); - - if (!assetsReady) - ofDrawBitmapString("Motion data is missing. See README.md.", 10, 20); - else if (!audioReady) - ofDrawBitmapString("Audio data is missing; running with a silent clock.", 10, 20); -} - -//-------------------------------------------------------------- -void testApp::keyPressed(int key) -{ - if (!audioReady) return; - if (player.getSpeed() > 0) - player.setSpeed(0); - else - player.setSpeed(1); -} - -//-------------------------------------------------------------- -void testApp::keyReleased(int key) -{ - -} - -//-------------------------------------------------------------- -void testApp::mouseMoved(int x, int y) -{ - -} - -//-------------------------------------------------------------- -void testApp::mouseDragged(int x, int y, int button) -{ - -} - -//-------------------------------------------------------------- -void testApp::mousePressed(int x, int y, int button) -{ - -} - -//-------------------------------------------------------------- -void testApp::mouseReleased(int x, int y, int button) -{ - -} - -//-------------------------------------------------------------- -void testApp::windowResized(int w, int h) -{ - -} - -//-------------------------------------------------------------- -void testApp::gotMessage(ofMessage msg) -{ - -} - -//-------------------------------------------------------------- -void testApp::dragEvent(ofDragInfo dragInfo) -{ - -} diff --git a/particle-motion-example/src/testApp.h b/particle-motion-example/src/testApp.h deleted file mode 100644 index c62abd2..0000000 --- a/particle-motion-example/src/testApp.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "ofMain.h" -#include "ofxBvh.h" - -class testApp : public ofBaseApp { - -public: - void setup() override; - void update() override; - void draw() override; - - void keyPressed(int key) override; - void keyReleased(int key) override; - void mouseMoved(int x, int y) override; - void mouseDragged(int x, int y, int button) override; - void mousePressed(int x, int y, int button) override; - void mouseReleased(int x, int y, int button) override; - void windowResized(int w, int h) override; - void dragEvent(ofDragInfo dragInfo) override; - void gotMessage(ofMessage msg) override; - - ofEasyCam cam; - bool assetsReady = false; - bool audioReady = false; -}; diff --git a/scripts/build-all.sh b/scripts/build-all.sh index f8b23b1..a34baa7 100755 --- a/scripts/build-all.sh +++ b/scripts/build-all.sh @@ -23,6 +23,8 @@ apps=( "particle-motion-example" "motion-visualization" "marching-cubes" + "example-motion-ribbons" + "example-motion-field" ) for app in "${apps[@]}"; do diff --git a/scripts/smoke-all.sh b/scripts/smoke-all.sh new file mode 100755 index 0000000..de60cd8 --- /dev/null +++ b/scripts/smoke-all.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +capture_dir="${1:-}" +if [[ -z "$capture_dir" ]]; then + echo "usage: $0 /path/to/capture-directory" >&2 + exit 2 +fi +mkdir -p "$capture_dir" +capture_dir="$(cd "$capture_dir" && pwd)" + +apps=( + "example-bvh" + "example-sync-sound" + "example-pen-graphics" + "particle-motion-example" + "motion-visualization" + "marching-cubes" + "example-motion-ribbons" + "example-motion-field" +) + +render_app() { + local app="$1" + local artifact="$2" + shift 2 + local binary app_pid watchdog_pid result + binary="$repo_root/$app/bin/$app.app/Contents/MacOS/$app" + if [[ ! -x "$binary" ]]; then + echo "Build $app first with scripts/build-all.sh." >&2 + exit 1 + fi + echo "Rendering $app" + "$binary" --smoke-test "--capture=$capture_dir/$artifact.png" "$@" >"$capture_dir/$artifact.log" 2>&1 & + app_pid=$! + # Bound an unresponsive renderer without terminating unrelated processes. + ( + sleep 90 + kill -TERM "$app_pid" 2>/dev/null || true + ) & + watchdog_pid=$! + result=0 + wait "$app_pid" || result=$? + kill "$watchdog_pid" 2>/dev/null || true + wait "$watchdog_pid" 2>/dev/null || true + if [[ "$result" -ne 0 ]] || ! grep -q 'SMOKE_TEST_OK' "$capture_dir/$artifact.log" \ + || [[ ! -s "$capture_dir/$artifact.png" ]]; then + cat "$capture_dir/$artifact.log" >&2 + echo "$app rendering failed (exit $result)." >&2 + exit 1 + fi + grep 'SMOKE_TEST_OK' "$capture_dir/$artifact.log" +} + +for app in "${apps[@]}"; do + render_app "$app" "$app" +done + +# A second pose verifies that each new shader study produces changing artwork. +for app in example-motion-ribbons example-motion-field; do + render_app "$app" "$app-later" --capture-frame=420 + if cmp -s "$capture_dir/$app.png" "$capture_dir/$app-later.png"; then + echo "$app produced identical captures at different motion frames." >&2 + exit 1 + fi +done diff --git a/scripts/validate-xcode-projects.sh b/scripts/validate-xcode-projects.sh index 99ee0e7..3502c6e 100755 --- a/scripts/validate-xcode-projects.sh +++ b/scripts/validate-xcode-projects.sh @@ -13,6 +13,8 @@ apps=( "particle-motion-example" "motion-visualization" "marching-cubes" + "example-motion-ribbons" + "example-motion-field" ) for app in "${apps[@]}"; do @@ -23,11 +25,11 @@ for app in "${apps[@]}"; do xcodebuild -project "$project" -list >/dev/null grep -Fq '"path": "src/main.cpp"' "$pbxproj" - grep -Fq '"name": "testApp.cpp"' "$pbxproj" - grep -Fq '"name": "testApp.h"' "$pbxproj" + grep -Fq '"name": "ofApp.cpp"' "$pbxproj" + grep -Fq '"name": "ofApp.h"' "$pbxproj" grep -Fq '"path": "../ofxBvh/src/ofxBvh.cpp"' "$pbxproj" - if grep -Eq 'ofApp\.(cpp|h)' "$pbxproj"; then - echo "$app references a missing template ofApp source" >&2 + if grep -Eq 'testApp\.(cpp|h)' "$pbxproj"; then + echo "$app references a removed testApp source" >&2 exit 1 fi diff --git a/shared/ExampleRuntime.h b/shared/ExampleRuntime.h new file mode 100644 index 0000000..9fe181b --- /dev/null +++ b/shared/ExampleRuntime.h @@ -0,0 +1,201 @@ +#pragma once + +#include "ofMain.h" +#include "ofAppGLFWWindow.h" +#include "ofxBvh.h" +#include + +#include +#include +#include + +namespace example { + +struct RunOptions { + bool smokeTest = false; + int frames = 90; + std::string capturePath; + + static RunOptions parse(int argc, char** argv) { + RunOptions options; + for (int i = 1; i < argc; ++i) { + const std::string argument(argv[i]); + if (argument == "--smoke-test") options.smokeTest = true; + else if (argument.rfind("--capture=", 0) == 0) options.capturePath = argument.substr(10); + else if (argument.rfind("--frames=", 0) == 0) options.frames = std::max(2, ofToInt(argument.substr(9))); + } + if (!options.capturePath.empty()) options.smokeTest = true; + return options; + } +}; + +// A hidden GLFW window still renders every frame, without activating a preview. +template +int launch(int argc, char** argv, const std::string& title) { + const auto options = RunOptions::parse(argc, argv); + ofGLFWWindowSettings settings; + settings.setSize(1024, 768); + settings.setGLVersion(3, 2); + settings.windowMode = OF_WINDOW; + settings.title = title; + settings.visible = !options.smokeTest; + auto window = ofCreateWindow(settings); + ofRunApp(window, std::make_shared(options)); + return ofRunMainLoop(); +} + +class Runtime { +public: + explicit Runtime(const RunOptions& options) : options(options) {} + + void setup() const { + ofSetFrameRate(options.smokeTest ? 0 : 60); + ofSetVerticalSync(!options.smokeTest); + if (options.smokeTest) ofSetRandomSeed(2012); + } + + float deltaSeconds() const { return options.smokeTest ? 1.0f / 60.0f : ofGetLastFrameTime(); } + float elapsedSeconds() const { return options.smokeTest ? ofGetFrameNum() / 60.0f : ofGetElapsedTimef(); } + bool isSmokeTest() const { return options.smokeTest; } + + void finishFrame(bool ready, const std::string& name, size_t geometryVertices) const { + if (!options.smokeTest) return; + auto* window = dynamic_cast(ofGetWindowPtr()); + auto* nativeWindow = window ? window->getGLFWWindow() : nullptr; + const bool passive = nativeWindow && !glfwGetWindowAttrib(nativeWindow, GLFW_VISIBLE) + && !glfwGetWindowAttrib(nativeWindow, GLFW_FOCUSED); + const GLenum error = glGetError(); + if (!ready || !passive || error != GL_NO_ERROR) { + ofLogError(name) << "SMOKE_TEST_FAILED ready=" << ready << " passive=" << passive << " glError=" << error; + ofExit(1); + return; + } + const bool lastFrame = ofGetFrameNum() + 1 >= options.frames; + if (ofGetFrameNum() != 0 && !lastFrame) return; + + ofImage capture; + capture.grabScreen(0, 0, ofGetWidth(), ofGetHeight()); + const auto& pixels = capture.getPixels(); + if (!pixels.isAllocated() || pixels.getWidth() < 16 || pixels.getHeight() < 128) { + ofLogError(name) << "SMOKE_TEST_FAILED framebuffer capture unavailable"; + ofExit(1); + return; + } + unsigned char minimum = 255; + unsigned char maximum = 0; + uint64_t hash = 1469598103934665603ull; + size_t variedPixels = 0; + const int left = pixels.getWidth() / 10; + const int right = pixels.getWidth() * 9 / 10; + const int top = std::max(100, int(pixels.getHeight() / 10)); + const int bottom = pixels.getHeight() * 9 / 10; + const auto reference = pixels.getColor(left, top); + for (int y = top; y < bottom; ++y) { + for (int x = left; x < right; ++x) { + const auto color = pixels.getColor(x, y); + for (const auto channel : {color.r, color.g, color.b}) { + minimum = std::min(minimum, channel); + maximum = std::max(maximum, channel); + hash = (hash ^ channel) * 1099511628211ull; + } + if (std::abs(int(color.r) - reference.r) + std::abs(int(color.g) - reference.g) + + std::abs(int(color.b) - reference.b) > 24) ++variedPixels; + } + } + if (!lastFrame) { + initialPixelsHash = hash; + return; + } + if (!pixels.isAllocated() || geometryVertices == 0 || maximum - minimum < 8 + || variedPixels < size_t((right - left) * (bottom - top)) / 500 || hash == initialPixelsHash) { + ofLogError(name) << "SMOKE_TEST_FAILED empty, flat, or unchanged content region" + << " vertices=" << geometryVertices << " variedPixels=" << variedPixels; + ofExit(1); + return; + } + if (!options.capturePath.empty() && !capture.save(options.capturePath)) { + ofLogError(name) << "SMOKE_TEST_FAILED unable to save capture"; + ofExit(1); + return; + } + ofLogNotice(name) << "SMOKE_TEST_OK frames=" << options.frames + << " renderer=GL3 pixelRange=" << int(maximum - minimum) << " geometryVertices=" << geometryVertices + << " variedPixels=" << variedPixels << " motionChanged=true hidden=true focused=false"; + ofExit(0); + } + +private: + RunOptions options; + mutable uint64_t initialPixelsHash = 0; +}; + +class MotionPlayback { +public: + std::array motions; + bool ready = false; + bool audioReady = false; + bool usingBundledMotion = false; + + void load(const std::string& name, bool bundledOnly, bool silent) { + constexpr std::array original = { + "bvhfiles/aachan.bvh", "bvhfiles/kashiyuka.bvh", "bvhfiles/nocchi.bvh"}; + constexpr std::array bundled = {"A_test.bvh", "B_test.bvh", "C_test.bvh"}; + ready = true; + usingBundledMotion = false; + for (size_t i = 0; i < motions.size(); ++i) { + const bool originalExists = !bundledOnly && ofFile::doesFileExist(original[i]); + usingBundledMotion = usingBundledMotion || !originalExists; + const auto path = originalExists ? std::string(original[i]) + : (bundledOnly ? std::string(bundled[i]) : "../../../example-bvh/bin/data/" + std::string(bundled[i])); + ready = motions[i].load(path) && ready; + motions[i].setLoop(true); + } + audioReady = !bundledOnly && !silent && ofFile::doesFileExist("Perfume_globalsite_sound.wav") + && audio.load("Perfume_globalsite_sound.wav"); + if (audioReady) { + audio.setLoop(true); + audio.play(); + } else if (!bundledOnly) { + ofLogNotice(name) << (usingBundledMotion ? "Bundled motion" : "Project motion") << "; using a silent internal clock."; + } + playhead = silent ? 4.0f : 0.0f; + } + + void update(float deltaSeconds, float speed = 1.0f) { + if (!ready) return; + const float duration = motions.front().getDuration(); + if (audioReady) { + audio.setSpeed(speed); + playhead = audio.getPosition() * audio.getDuration(); + } else { + playhead += deltaSeconds * speed; + } + playhead = std::fmod(playhead, duration); + if (playhead < 0.0f) playhead += duration; + position = playhead / duration; + for (auto& motion : motions) { + motion.setPosition(position); + motion.update(0.0f); + } + } + + float normalizedPosition() const { return position; } + + void drawStatus(float x = 10.0f, float y = 20.0f) const { + if (!ready) ofDrawBitmapString("Motion data is missing. See README.md.", x, y); + else if (!audioReady) ofDrawBitmapString(usingBundledMotion ? "Bundled motion / silent clock" : "Project motion / silent clock", x, y); + else if (usingBundledMotion) ofDrawBitmapString("Bundled motion / audio clock", x, y); + } + +private: + ofSoundPlayer audio; + float playhead = 0.0f; + float position = 0.0f; +}; + +inline glm::vec3 safeNormalize(const glm::vec3& value, const glm::vec3& fallback = {0, 1, 0}) { + const float lengthSquared = glm::dot(value, value); + return lengthSquared > 1e-12f ? value / std::sqrt(lengthSquared) : fallback; +} + +} // namespace example diff --git a/shared/LICENSE b/shared/LICENSE new file mode 100644 index 0000000..1816353 --- /dev/null +++ b/shared/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2026 Daito Manabe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From e16c584ac0435906801cbe5c5287ddefe8841328 Mon Sep 17 00:00:00 2001 From: Daito Manabe Date: Sat, 5 Sep 2026 08:49:33 +0900 Subject: [PATCH 2/3] Verify OpenGL rendering on Linux Mesa in CI --- .github/workflows/build.yml | 56 +++++++++++++++++++++++++++++++++++-- README.md | 12 +++++--- scripts/build-all.sh | 7 ++++- scripts/smoke-all.sh | 12 ++++++-- 4 files changed, 78 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d1072a..23a7035 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -49,8 +49,59 @@ jobs: - name: Build all applications and run regression tests run: ./scripts/build-all.sh "${RUNNER_TEMP}/of_v0.12.1_osx_release" - - name: Render all examples with OpenGL 3.2 - run: ./scripts/smoke-all.sh "${RUNNER_TEMP}/example-captures" + + linux-render: + name: Linux Mesa rendering + runs-on: ubuntu-22.04 + timeout-minutes: 60 + + env: + OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.12.1/of_v0.12.1_linux64_gcc6_release.tar.gz + OF_SHA256: d6c1dcab777665b2aa63e5e3d9122cc116f096b3421db3493f795a621b399c63 + LIBGL_ALWAYS_SOFTWARE: "1" + GALLIUM_DRIVER: llvmpipe + + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Cache openFrameworks 0.12.1 + id: cache-openframeworks + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/of_v0.12.1_linux64_gcc6_release + key: openframeworks-0.12.1-ubuntu-22.04-${{ runner.arch }}-d6c1dcab7776-v1 + + - name: Download verified openFrameworks release + if: steps.cache-openframeworks.outputs.cache-hit != 'true' + shell: bash + run: | + OF_ARCHIVE="${RUNNER_TEMP}/of_v0.12.1_linux64_gcc6_release.tar.gz" + curl --fail --location --retry 3 --output "$OF_ARCHIVE" "$OF_URL" + echo "$OF_SHA256 $OF_ARCHIVE" | sha256sum --check + tar --extract --gzip --file "$OF_ARCHIVE" --directory "${RUNNER_TEMP}" + + - name: Install official Ubuntu dependencies and software OpenGL + shell: bash + run: | + # This installer comes from the checksum-pinned release and supports Ubuntu 22.04. + sudo env DEBIAN_FRONTEND=noninteractive bash \ + "${RUNNER_TEMP}/of_v0.12.1_linux64_gcc6_release/scripts/linux/ubuntu/install_dependencies.sh" -y + sudo apt-get install --yes --no-install-recommends xvfb xauth mesa-utils libgl1-mesa-dri + + - name: Build all applications and run regression tests + run: ./scripts/build-all.sh "${RUNNER_TEMP}/of_v0.12.1_linux64_gcc6_release" + + - name: Render all examples with Mesa OpenGL + shell: bash + run: | + mkdir -p "${RUNNER_TEMP}/example-captures" + xvfb-run --auto-servernum --server-args="-screen 0 1600x1000x24 +extension GLX -nolisten tcp" \ + bash -euo pipefail -c ' + glxinfo -B | tee "${RUNNER_TEMP}/example-captures/opengl-context.log" + grep -qi llvmpipe "${RUNNER_TEMP}/example-captures/opengl-context.log" + ./scripts/smoke-all.sh "${RUNNER_TEMP}/example-captures" + ' - name: Keep rendering evidence if: always() @@ -58,4 +109,5 @@ jobs: with: name: openframeworks-rendering path: ${{ runner.temp }}/example-captures + if-no-files-found: error retention-days: 7 diff --git a/README.md b/README.md index 205637d..0941743 100644 --- a/README.md +++ b/README.md @@ -96,10 +96,14 @@ To render every example in a hidden test window and save PNG evidence: ./scripts/smoke-all.sh /path/to/captures ``` -The GitHub workflow performs the same render checks after building. Its -`openframeworks-rendering` artifact contains screenshots and logs. This requires -a desktop OpenGL context, even though the test windows stay hidden. The shader -studies are captured at two motion timestamps to check that their output changes. +The GitHub workflow builds and runs regression tests on macOS, then independently +builds and renders all eight examples on Ubuntu 22.04 with Mesa llvmpipe and Xvfb. +This supplies a real software OpenGL context where hosted macOS runners cannot +provide the required pixel format. The `openframeworks-rendering` artifact contains +screenshots, application logs and the OpenGL context report. Render failures fail +CI; the shader studies are captured at two motion timestamps to check that their +output changes. Local capture also requires a desktop OpenGL context, even though +the test windows stay hidden. The build/capture scripts support macOS and Linux. The checked-in Xcode projects were regenerated from the openFrameworks 0.12.1 macOS template. They use relative paths and expect the repository layout shown diff --git a/scripts/build-all.sh b/scripts/build-all.sh index a34baa7..de0cd59 100755 --- a/scripts/build-all.sh +++ b/scripts/build-all.sh @@ -36,6 +36,11 @@ echo "==> Building regression test suite" make -C "$repo_root/tests/ofxBvh-boundary" Release OF_ROOT="$of_root" -j"$jobs" echo "==> Running regression test suite" -"$repo_root/tests/ofxBvh-boundary/bin/ofxBvh-boundary.app/Contents/MacOS/ofxBvh-boundary" \ +case "$(uname -s)" in + Darwin) test_binary="$repo_root/tests/ofxBvh-boundary/bin/ofxBvh-boundary.app/Contents/MacOS/ofxBvh-boundary" ;; + Linux) test_binary="$repo_root/tests/ofxBvh-boundary/bin/ofxBvh-boundary" ;; + *) echo "Unsupported platform: $(uname -s)" >&2; exit 2 ;; +esac +"$test_binary" \ "$repo_root/example-bvh/bin/data" \ "$repo_root/tests/ofxBvh-boundary/fixtures" diff --git a/scripts/smoke-all.sh b/scripts/smoke-all.sh index de60cd8..61d5e4e 100755 --- a/scripts/smoke-all.sh +++ b/scripts/smoke-all.sh @@ -27,13 +27,21 @@ render_app() { local artifact="$2" shift 2 local binary app_pid watchdog_pid result - binary="$repo_root/$app/bin/$app.app/Contents/MacOS/$app" + case "$(uname -s)" in + Darwin) binary="$repo_root/$app/bin/$app.app/Contents/MacOS/$app" ;; + Linux) binary="$repo_root/$app/bin/$app" ;; + *) echo "Unsupported platform: $(uname -s)" >&2; exit 2 ;; + esac if [[ ! -x "$binary" ]]; then echo "Build $app first with scripts/build-all.sh." >&2 exit 1 fi echo "Rendering $app" - "$binary" --smoke-test "--capture=$capture_dir/$artifact.png" "$@" >"$capture_dir/$artifact.log" 2>&1 & + # Linux resolves data relative to the working directory; use the same bin layout on both platforms. + ( + cd "$repo_root/$app/bin" + exec "$binary" --smoke-test "--capture=$capture_dir/$artifact.png" "$@" + ) >"$capture_dir/$artifact.log" 2>&1 & app_pid=$! # Bound an unresponsive renderer without terminating unrelated processes. ( From ee14eff93e6b15689e3a428fe5e11f95e215dd16 Mon Sep 17 00:00:00 2001 From: Daito Manabe Date: Sat, 5 Sep 2026 08:56:37 +0900 Subject: [PATCH 3/3] Isolate Linux rendering dependencies in a pinned Ubuntu container --- .github/workflows/build.yml | 23 +++++++++++++++++++++-- README.md | 4 +++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 23a7035..26c04a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,16 +52,35 @@ jobs: linux-render: name: Linux Mesa rendering - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 60 + # A clean Jammy package set avoids dependency conflicts with SDKs preinstalled on hosted runners. + container: + image: ubuntu:22.04@sha256:2edbbc5dc405e9612ba3584ce95480277e3eb374407b5505fe26f17df77c7dbc + defaults: + run: + shell: bash env: OF_URL: https://github.com/openframeworks/openFrameworks/releases/download/0.12.1/of_v0.12.1_linux64_gcc6_release.tar.gz OF_SHA256: d6c1dcab777665b2aa63e5e3d9122cc116f096b3421db3493f795a621b399c63 LIBGL_ALWAYS_SOFTWARE: "1" GALLIUM_DRIVER: llvmpipe + DEBIAN_FRONTEND: noninteractive + TZ: Etc/UTC steps: + - name: Bootstrap clean Ubuntu container + run: | + apt-get update + apt-get install --yes --no-install-recommends \ + ca-certificates curl git sudo zstd lsb-release pkg-config + mkdir -p "${RUNNER_TEMP}/example-captures" + apt-cache policy libunwind-dev libunwind8 libgstreamer1.0-dev \ + | tee "${RUNNER_TEMP}/example-captures/dependency-policy.log" + # Install the GStreamer prerequisite explicitly; fail here if package resolution breaks. + apt-get install --yes --no-install-recommends libunwind-dev + - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -70,7 +89,7 @@ jobs: uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ runner.temp }}/of_v0.12.1_linux64_gcc6_release - key: openframeworks-0.12.1-ubuntu-22.04-${{ runner.arch }}-d6c1dcab7776-v1 + key: openframeworks-0.12.1-jammy-container-2edbbc5dc405-${{ runner.arch }}-d6c1dcab7776-v1 - name: Download verified openFrameworks release if: steps.cache-openframeworks.outputs.cache-hit != 'true' diff --git a/README.md b/README.md index 0941743..2bca991 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,9 @@ To render every example in a hidden test window and save PNG evidence: ``` The GitHub workflow builds and runs regression tests on macOS, then independently -builds and renders all eight examples on Ubuntu 22.04 with Mesa llvmpipe and Xvfb. +builds and renders all eight examples in a clean, digest-pinned Ubuntu 22.04 +container with Mesa llvmpipe and Xvfb. The container isolates OF dependencies +from the hosted runner's preinstalled compiler SDKs. This supplies a real software OpenGL context where hosted macOS runners cannot provide the required pixel format. The `openframeworks-rendering` artifact contains screenshots, application logs and the OpenGL context report. Render failures fail