From 9b82a9057985af31448a37509ae092fbb673ed18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=27=C3=A9lectron=20rare?= <108685187+electron-rare@users.noreply.github.com> Date: Mon, 18 May 2026 17:27:07 +0200 Subject: [PATCH] feat: add stereo waveform orbit rings Two perpendicular line-loop rings orbit the sphere, the blue ring modulated by CH1 and the orange ring by CH2, toggled with key 2. --- oscope-sphere/src/OrbitRings.cpp | 50 ++++++++++++++++++++++++++++++++ oscope-sphere/src/OrbitRings.h | 21 ++++++++++++++ oscope-sphere/src/ofApp.cpp | 3 ++ oscope-sphere/src/ofApp.h | 2 ++ 4 files changed, 76 insertions(+) create mode 100644 oscope-sphere/src/OrbitRings.cpp create mode 100644 oscope-sphere/src/OrbitRings.h diff --git a/oscope-sphere/src/OrbitRings.cpp b/oscope-sphere/src/OrbitRings.cpp new file mode 100644 index 0000000..b91bb56 --- /dev/null +++ b/oscope-sphere/src/OrbitRings.cpp @@ -0,0 +1,50 @@ +#include "OrbitRings.h" +#include + +void OrbitRings::setup(int pointsPerRing) { + n_ = pointsPerRing; + ring1_.clear(); + ring2_.clear(); + ring1_.setMode(OF_PRIMITIVE_LINE_LOOP); + ring2_.setMode(OF_PRIMITIVE_LINE_LOOP); + for (int i = 0; i < n_; ++i) { + ring1_.addVertex(glm::vec3(0.0f)); + ring2_.addVertex(glm::vec3(0.0f)); + } +} + +void OrbitRings::setWaveform(const std::vector& ch1, + const std::vector& ch2) { + const float twoPi = 6.28318530718f; + auto rebuild = [&](ofVboMesh& ring, const std::vector& src, + bool xzPlane) { + const int n = static_cast(src.size()); + for (int i = 0; i < n_; ++i) { + const float theta = twoPi * static_cast(i) / n_; + float s = 0.0f; + if (n > 0) { + int idx = static_cast( + static_cast(i) * n / n_); + if (idx >= n) idx = n - 1; + s = src[idx]; + } + const float r = baseRadius_ + amp_ * s; + const glm::vec3 p = xzPlane + ? glm::vec3(r * std::cos(theta), 0.0f, r * std::sin(theta)) + : glm::vec3(r * std::cos(theta), r * std::sin(theta), 0.0f); + ring.setVertex(i, p); + } + }; + rebuild(ring1_, ch1, true); + rebuild(ring2_, ch2, false); +} + +void OrbitRings::draw() { + ofPushStyle(); + ofSetLineWidth(2.0f); + ofSetColor(80, 200, 255); + ring1_.draw(); + ofSetColor(255, 140, 80); + ring2_.draw(); + ofPopStyle(); +} diff --git a/oscope-sphere/src/OrbitRings.h b/oscope-sphere/src/OrbitRings.h new file mode 100644 index 0000000..a5c4a44 --- /dev/null +++ b/oscope-sphere/src/OrbitRings.h @@ -0,0 +1,21 @@ +#pragma once +#include "ofMain.h" +#include + +// GL visual unit: two line-loop rings orbiting the sphere in +// perpendicular planes. Ring 1 follows CH1, ring 2 follows CH2; each +// point's orbit radius is modulated by the live waveform. +class OrbitRings { +public: + void setup(int pointsPerRing); + void setWaveform(const std::vector& ch1, + const std::vector& ch2); + void draw(); + +private: + int n_ = 0; + float baseRadius_ = 300.0f; + float amp_ = 70.0f; + ofVboMesh ring1_; // CH1, XZ plane + ofVboMesh ring2_; // CH2, XY plane +}; diff --git a/oscope-sphere/src/ofApp.cpp b/oscope-sphere/src/ofApp.cpp index ea89b2d..ef8b450 100644 --- a/oscope-sphere/src/ofApp.cpp +++ b/oscope-sphere/src/ofApp.cpp @@ -12,6 +12,7 @@ void ofApp::setup() { cam_.setFarClip(5000.0f); sphere_.setup(5, 512, 256, 1024); + rings_.setup(512); hantek_.setSampleRate(16000000u); const oscope::HantekStatus st = hantek_.start(); @@ -47,6 +48,7 @@ void ofApp::update() { sphere_.pushSpectrogramColumn(analyzerCh1_.magDown(), analyzerCh2_.magDown()); sphere_.setWaveform(buf1_, buf2_); + rings_.setWaveform(buf1_, buf2_); } void ofApp::draw() { @@ -54,6 +56,7 @@ void ofApp::draw() { ofPushMatrix(); ofRotateYDeg(ofGetElapsedTimef() * 6.0f); if (layerA_) sphere_.drawSkin(); + if (layerB_) rings_.draw(); ofPopMatrix(); cam_.end(); drawHud(); diff --git a/oscope-sphere/src/ofApp.h b/oscope-sphere/src/ofApp.h index 34024c2..84304b5 100644 --- a/oscope-sphere/src/ofApp.h +++ b/oscope-sphere/src/ofApp.h @@ -4,6 +4,7 @@ #include "AudioAnalyzer.h" #include "DemoSignal.h" #include "SphereViz.h" +#include "OrbitRings.h" #include #include @@ -23,6 +24,7 @@ private: oscope::DemoSignal demo_{48000.0f}; SphereViz sphere_; + OrbitRings rings_; ofEasyCam cam_; std::vector buf1_;