# Manipulating a TriMesh

Hi Everyone,

I’m loading an Obj file (using `ObjLoader`) to a `TriMesh`, in order to get its AABB (by calling `calcBoundingBox()`) which I need for some physics calculation.

However, the model needs to be manipulated before (scale, rotation and translation).
Is there any way to apply those transformation on the mesh that are not in the context of drawing?
(e.g something similar to chaining `geom::Scale()`/geom::Rotate()`/`geom::Translate()`as with geom::Source) such that when calling to`calcBoundingBox()` the model would already be in its final configuration.

Thanks!

Hi,

You can submit a `mat4` for `calcBoundingBox()` and then your model will be transformed by that matrix when calculating the bounding box. Would this solve your problem?

-Gabor

Hi @gabor_papp thanks for the quick reply.
Could you elaborate please? Is there a way to build that matrix once and use it for both the drawing and the calculation of the AABB?

Not tested code:

``````mat4 translate = translate( mat4(), vec3( 10.0f, 0.0f, 0.0f ) );
mat4 scale = scale( vec3( 2.0f, 2.0f, 2.0f ) );
mat4 rotate = rotate( 0.5f, vec3( 1.0f, 0.0f, 0.0f );
mTransform = translate * rotate * scale;
``````

Use `gl::multModelMatrix( mTransform );` before drawing your mesh.

You can calculate the bounding box with this transformation matrix like this:

``````AxisAlignedBox bbox = mTriMesh->calcBoundingBox( mTransform );
``````

This can be slow if you transform many vertices, but if the model is static, you can calculate the bounding box once and transform it with the matrix every frame as the transformation changes.

``````// do this once when loading the mesh
mTriMeshBbox = mTriMesh->calcBoundingBox();
...
// update this every frame
AxisAlignedBox bbox = mTriMeshBbox.transformed( mTransform );
``````

thanks again @gabor_papp it looks exactly like what I needed.

However, I’m getting the following compiler error:

``````error: type 'mat4' (aka 'tmat4x4<float, highp>') does not provide a call operator
mat4 scale = scale(0.027f, 0.027f, 0.027f);
``````

(Using clang on MacOS, and cinder 0.9.1)

Weirdly, `mat4 rotate = rotate( 0.5f, vec3( 1.0f, 0.0f, 0.0f );` does compile and work.

sorry, try this:

``````mat4 scale = scale( vec3( 0.027f, 0.027f, 0.027f ) );
``````

@gabor_papp still getting the same error.

@gabor_papp If I understand correctly those functions are all directly implemented by GLM, and are documented here: https://glm.g-truc.net/0.9.4/api/a00206.html

According to this, both calls should work.

can you try:

``````mat4 scale = glm::scale( vec3( 0.027f, 0.027f, 0.027f ) );
``````

@gabor_papp Hah! it did the trick. I was sure I’ve tried it before…

The whole thing works now - thanks.

Still, I don’t understand how `rotate()` was found without the namespace prefix and `scale()` wasn’t (I don’t have other function with the same name in any scope)

Some `glm` functions and types are aliased in the `cinder` namespace. For example, `ci::vec4` is an alias for `glm::vec4`. Same might be true for `rotate`.

-Paul

P.S. I’d like to add two tips to @gabor_papp’s :

• before calling `gl::multModelMatrix`, make sure to store/push the current matrix so you can restore it when you’re done drawing the mesh. You can do this by calling `gl::pushModelMatrix` and `gl::popModelMatrix`, but a more convenient way is to call `gl::ScopedModelMatrix scpModel;` This will create an object which pushes the matrices, then pops them again when it goes out of scope, RAII style. There are many more scoped variations like that, all worth using. The following code is equivalent:
``````// A
{
gl::pushModelMatrix();
gl::multModelMatrix( mTransform );
gl::draw( mTriMesh );
gl::popModelMatrix();
}

// B
{
gl::ScopedModelMatrix scpModel;
gl::multModelMatrix( mTransform );
gl::draw( mTriMesh );
}
``````
• When multiplying matrices, the order is important. Transformations are performed from last to first in the line `mTransform = translate * rotate * scale;`. Usually, a mesh is first rotated and/or scaled, followed by a translation. That way, it rotates or scales around its own origin.
2 Likes