Trying to replicate a Zach's creation

Hi. I really like Zach’s works. I’m trying to learn how to get something like this done:

I think I could manage to display a path with arcs someway and get something similar, but I have no idea on how he achieved to animate then the interpolations and the stroke following the path.

it’s been a while since I made those but I think one thing that could be helpful is knowing ofPolyline has a “getPointAtPct()” function which allows you to interpolate along a path and is great for animation. My guess is, I keep adding to the polyline I am using that and just adding each arc separately, walking along it, and once I get to the end, I add it to a larger path. There may be some logic accounting for shorter and longer paths so the movement is steady…

Hi Zach, thanks for the answer

I came up with this:

it’s like a compass walking around with 2 nodes as parent and child that switches each time I click and a middle node as the emitter of vertices.

Now I’m dealing with the behavior when the emitter reaches the screen edges. Maybe I should set up a guide node within the screen space that the other nodes will follow and automate the parent switch. Also changing the parent and child distance to the emitter when switching, to change the arcs radius.

ofApp.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();

		void mousePressed(int x, int y, int button);
		
		
		ofNode node1, node2, emitter;
		float radius = 50, roll1 = 1, roll2 = 0;
		ofPolyline polyline;
};

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    node1.setPosition(ofGetWidth()/2, ofGetHeight()/2, 0);
    node2.setParent(node1);
    node2.setPosition(radius,0, 0);
    emitter.setParent(node1);
    emitter.setPosition(radius / 2, 0, 0);
}

//--------------------------------------------------------------
void ofApp::update(){
    node1.rollDeg(roll1*5);
    node2.rollDeg(roll2*5);
    polyline.addVertex(emitter.getGlobalPosition());

    if(polyline.getVertices().back().x < 0){
        polyline.getVertices().back().x += ofGetWidth();
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofPushMatrix();
    node1.draw();
    node2.draw();
    emitter.draw();
    polyline.draw();
    ofPopMatrix();
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button)
{
    glm::vec3 node1_global_position = node1.getGlobalPosition();
    glm::vec3 node2_global_position = node2.getGlobalPosition();
    glm::quat node1_global_orientation = node1.getGlobalOrientation();
    glm::quat node2_global_orientation = node2.getGlobalOrientation();

    if (roll1)
    {
        roll1 = 0;
        roll2 = -1;

        node2.clearParent();
        node2.setGlobalPosition(node2_global_position);
        node2.setGlobalOrientation(node2_global_orientation);
        node1.setParent(node2);
        node1.setGlobalPosition(node1_global_position);
        node1.setGlobalOrientation(node1_global_orientation);
    }
    else
    {
        roll1 = 1;
        roll2 = 0;

        node1.clearParent();
        node1.setGlobalPosition(node1_global_position);
        node1.setGlobalOrientation(node1_global_orientation);
        node2.setParent(node1);
        node2.setGlobalPosition(node2_global_position);
        node2.setGlobalOrientation(node2_global_orientation);
    }
}
1 Like