Translating and rotating vertices using a glm matrix

Hi hi,

I’m trying to apply transformation to mesh vertices so I can later append them to a big mesh with the right traslation and rotation.

I can’t get this to work. It complains that it can’t multiply a glm::mat4 and a glm::tvec3.

ofNode n;
n.rollDeg(ofRandom(360));
n.tiltDeg(ofRandom(360));

ofMesh mm = ofMesh::box(ofRandom(150),
                        ofRandom(150),
                        ofRandom(150));

for(auto & v : mm.getVertices()) {
    v = n.getGlobalTransformMatrix() * v;
}

What’s an easy and fast way to do this? Should I use mat3 or vec4? Thanks!

Replying to myself, I found some improvement by converting the vec3 to vec4 and back.

void ofApp::mousePressed(int x, int y, int button) {
    ofNode n;
    n.rollDeg(ofRandom(360));
    n.tiltDeg(ofRandom(360));
    //n.truck(ofRandom(200));

    ofMesh newMesh = ofMesh::box(ofRandom(150),
                            ofRandom(150),
                            ofRandom(150));

    for(auto & v : newMesh.getVertices()) {
        v = (n.getGlobalTransformMatrix() * v.xyzz()).xyz();
    }
    newMesh.setColorForIndices(0, newMesh.getVertices().size()-1,
                          ofColor::fromHsb(ofRandom(256), 255, 200));
    theMesh.append(newMesh);
}

It seems to work.

Unless I use rotate AND translate (truck). Then the shapes are stretched in strange ways. I guess I’m doing something wrong with that matrix multiplication…

I figured it out :slight_smile:

It was not good to duplicate the z in v.xyzz(). If I convert it to a glm::vec4(v, 1) then it works. I wonder why getGlobalTransformMatrix() and .getVertices() are incompatible…

void ofApp::mousePressed(int x, int y, int button) {
    ofNode n;
    n.rollDeg(ofRandom(360));
    n.panDeg(ofRandom(360));
    n.truck(200);

    ofMesh newMesh = ofMesh::box(5, 50, 50);

    for(auto & v : newMesh.getVertices()) {
        v = (n.getGlobalTransformMatrix() * glm::vec4(v, 1)).xyz();
    }
    newMesh.setColorForIndices(0, newMesh.getVertices().size()-1,
                          ofColor::fromHsb(ofRandom(256), 255, 200));
    theMesh.append(newMesh);
}

Update

I did something wrong above when trying to set the colors. The box is aparently created without any color information for the vertices, so the loop that tries to set vertex colors does not work. This code

    newMesh.setColorForIndices(0, newMesh.getVertices().size()-1,
                          ofColor::fromHsb(ofRandom(256), 255, 200));

should make sure that we have the same number of colors as vertices. This actually works:

float hue = ofRandomuf();
while(newMesh.getColors().size() < newMesh.getVertices().size()) {
    newMesh.addColor(ofFloatColor::fromHsb(hue, 1, ofRandom(0.7f, 1.0f)));
}

It chooses one hue for the object and sets random brightneses for the vertices using that same hue. Note that what you see in the image is one single ofMesh, that was the goal of this whole exercise.

I didn’t know that you could create a Voronoi pattern like this :slight_smile:

1 Like

mathematically you can’t multiply a vec3 and a mat4x4 you need to have the same number of rows as columns in the matrix to be able to multiply 2 matrices.

when multiplying a 3d vector by a 4x4 matrix the most common thing to do is to add a 1 as the w coordinate multiply by the 4x4 matrix and then get the results xyz. if the matrix has any projective transformation instead of affine (scale, traslation and rotation are all affine transformations) then you would need to divide the result by the resulting w:

vec4 res4 = m4 * vec4(v3,1);
vec3 res3 = res4.xyz() / res4.w;

although this is the most common thing to do there’s cases in which you might want to add a 0 as w instead of 1 or even other numbers, that’s why glm doesn’t do it automatically as ofVec3f/ofMatrix4x4 did. this is all related to homogeneous coordinates if you want to know more details about it