ofMatrix4x4, scaling and rotating around a registration point

here is a bit of code that i know that works,
its a really simple box rotating around a “registration point” of its own center.

void ofApp::draw(){
    int w = 200;
    int h = 200;
    float rotation = ofGetElapsedTimef() * 10;
    
    ofMatrix4x4 mat;
    mat.preMultRotate(ofQuaternion(rotation, ofVec3f(0, 0, 1)));
    
    ofPushMatrix();
    ofTranslate(200, 200);
    ofMultMatrix(mat);
    ofRect(-w * 0.5, -h * 0.5, w, h);
    ofPopMatrix();
}

now for the problem!
i need to work out how to rotate around the box center without the box being offset,
so ofRect now becomes,

ofRect(0, 0, w, h);

and i need to be able to do this only using ofMatrix4x4.
so far ive tried a few things which are giving me incorrect results.
like the below,

void ofApp::draw(){
    int w = 200;
    int h = 200;
    float rotation = ofGetElapsedTimef() * 10;
    
    ofMatrix4x4 mat;
    mat.preMultTranslate(ofVec3f(-w * 0.5, -h * 0.5, 0));
    mat.preMultRotate(ofQuaternion(rotation, ofVec3f(0, 0, 1)));
    mat.preMultTranslate(ofVec3f(w * 0.5, h * 0.5, 0));
    
    ofPushMatrix();
    ofTranslate(200, 200);
    ofMultMatrix(mat);
    ofRect(0, 0, w, h);
    ofPopMatrix();
}

can any math heads help me out with this one?

cheers,
L.

ok so the problem was me making stupid mistakes.
solution below.

this rotates the box around its center,

void ofApp::draw(){
    float rotation = ofGetElapsedTimef() * 10;
    
    ofPushMatrix();

    ofTranslate(200, 200);
    ofTranslate(100, 100);
    ofRotate(rotation);
    ofTranslate(-100, -100);
    
    ofRect(0, 0, 200, 200);
    ofPopMatrix();
}

and can also be written like this,

void ofApp::draw(){
    float rotation = ofGetElapsedTimef() * 10;
    
    ofMatrix4x4 mat;
    mat.preMultTranslate(ofVec3f(200, 200, 0));
    mat.preMultTranslate(ofVec3f(100, 100, 0));
    mat.preMultRotate(ofQuaternion(rotation, ofVec3f(0, 0, 1)));
    mat.preMultTranslate(ofVec3f(-100, -100, 0));
    
    ofPushMatrix();

    ofMultMatrix(mat);
    
    ofRect(0, 0, 200, 200);
    ofPopMatrix();
}
1 Like

you could also do ofSetRectMode(OF_RECTMODE_CENTER);

but anyway for future reference if you are in coordinate system A , but you want to do something relative to coordinate system B(say a rotation R) your matrix order should be A * B * R * inverse(B), so in your case. you did this.

mat.preMultTranslate(ofVec3f(200, 200, 0)); // takes you to coordinate system A
mat.preMultTranslate(ofVec3f(100, 100, 0)); // coordinate system B
mat.preMultRotate(ofQuaternion(rotation, ofVec3f(0, 0, 1))); // perform a rotation R relative to coordinate system B
mat.preMultTranslate(ofVec3f(-100, -100, 0)); // multiply by inverse(B) to take you back to coordinate system A