Erratic behaviour with ofNode::roll

Hello!

Learning Of with the ofBook repo, I am adapting a few examples from the animation chapter written by @zach.
Using example #14 sinExample_atan, I wanted to make the rectangle class an extension of OfNode and simply make this node roll around its z local axis to target the mouse position.
My code does’t work properly and I can’t figure out why. This might not be the best way to proceed?
I also thought of using the lookAt() function but I do not wan’t the Z axis to aim at mouse position but the X axis instead.
Thanks for any help.

rectangle.h

#include "rectangle.h"


//------------------------------------------------------------------
rectangle::rectangle(){

pos.set(0,0);
prevPos.set(0,0);
}

//------------------------------------------------------------------
void rectangle::customDraw() {
ofFill();

ofSetRectMode(OF_RECTMODE_CENTER);
ofSetColor(230);

ofRect(0, 0, 40,40);
ofRect(20,0,18,5);

}

//------------------------------------------------------------------
void rectangle::orient(){

pos.x = ofGetMouseX();
pos.y = ofGetMouseY();

float dx = pos.x - prevPos.x;
float dy = pos.y - prevPos.y;

angle = (atan2(dy, dx)) * RAD_TO_DEG;

prevPos.x = pos.x;
prevPos.y = pos.y;

this->roll(angle);

}

rectangle.ccp

#pragma once

#include "ofMain.h"

class rectangle : public ofNode {

public:
 
rectangle();

void	customDraw();
void	orient();
ofVec2f	pos;
ofVec2f	prevPos;
float	angle;

};

ofApp.ccp

-----------
void ofApp::setup(){

ofSetVerticalSync(true);
ofBackground(20);

myRectangle.setPosition(300, 300, 0);
}

//--------------------------------------------------------------
void ofApp::update(){

myRectangle.orient();
}

//--------------------------------------------------------------
void ofApp::draw(){

myRectangle.draw();
ofDrawBitmapString(ofToString(myRectangle.angle), 20, 20);

in ofApp.h

rectangle myRectangle;

Until now I didn’t take care about ofNode (shame on me !)

I don’t see an addChildren function in ofNode
Does it means that we must create ofMeshes, then use ofMesh.addParent() to connect them to an ofNode (which would be seen as a NULL object in AfterEffects for example) ?

Looking into ofMesh source code it doesn’t derive from ofNode, so do we need to create a new class deriving from both ofMesh and ofNode ?

@tactif - two options, either create an object that extends ofNode (and overrides the custom draw function) or use the transformGL() / restoreTransformGL() functionality.

@tim1 – do you want the object to face the mouse by rotating on it’s Z axis? Right now, you are calculating an angle based on relative mouse changes, but this seems wrong – if the mouse is moving straight to the right, angle is always going to be 0, if it’s moving to the left, 180. it seems better to compute the angle between the object and the mouse, like:

//------------------------------------------------------------------
void rectangle::orient(){
    
    pos.x = ofGetMouseX();
    pos.y = ofGetMouseY();
    
    float dx = pos.x - getGlobalPosition().x;
    float dy = pos.y - getGlobalPosition().y;
    
    angle = (atan2(dy, dx)) * RAD_TO_DEG;
    
    prevPos.x = pos.x;
    prevPos.y = pos.y;
    
    cout << angle << endl;
    
    this->setOrientation(ofVec3f(0,0,angle));
    
}

when I do this, the object follows the mouse. (also, note things things like roll are cummulative, if you call roll(1) every frame, the object will spin… in this case, we find the absolute angle change between the object and the mouse and se the absolute orientation).

hope that helps?

@tactif of3dPrimitive is a mesh and an ofNode, it’s the easiest to use when you want to have a mesh + transformations in one object

1 Like

@tim1 you can also use 2 nested ofNodes, one to rotate the object so it’s z looks to the left and then another one to do a lookAt:

//.h
of3dPrimitive mesh;
ofNode lookAt;

//setup
mesh.setParent(lookAt);
mesh.pan(90);

//update
lookAt.lookAt(pos);

//draw
mesh.draw();

it might be slower than calculating the orientation directly and in this case it might not simplify much compared to just using the trigonometric functions but for other uses nesting 2 or more nodes to get transformations that you can’t do with one is really useful.

I often stop myself from posting basic question on the forum but I must admit that your reactivity is the best learning tool.

@zach
Late at night, I was wrong trying to compute delta angle based on relative mouse positions. My bad.
Thanks for pointing the non cumulative setOrientation function. That was what I needed.

@arturo
Thank you as well. Nested nodes is definitely something I will experiment.

(I really like ofNode)

ofNode is great - here’s a very simple example using cumulative transformations to draw a complex shape: