Rotating models is anoying

I have been playing with the 3D features of raylib some and it went well until i wanted to rotate a model to an arbitrary angle.

As i understand the way to draw a model rotated is to specify the axis as a 3d vector and the angle to rotate around that axis. This is nice when you want to rotate around one axis, just chose around what to rotate and throw an angle at it. However as soon as you want to rotate a model around two axis such as pitch and yaw at the same time then it gets rather complicated.

So far i could not figure out how to get from euler angles such as pitch yaw roll to the axis-angle system used here. I think it would be better if there was a version of the DrawModelEx() function that accepted a OpenGL transformation matrix, also supply some helper functions that generate that matrix from ether Euler or the original Axis-Angle input. I don't know if this whole Axis-Angle is a OpenGL specific thing, but i would assume transformation matrixes are easier for the API to use than Axis-Angle.


  • My solution in the end was to not use the DrawModel() function and instead directly call in to rlgl.c with this:

    void rlglDrawMesh(Mesh mesh, Material material, Matrix transform);

    Its basically all that DrawModel() calls anyway, but without messing with my parameters so that i can simply pass a raw matrix. This function is not in the raylib.h so i added its prototype to the top of my C file and it worked fine.

    To generate my matrix i just made some functions containing code i found on the internet like for example:

    Matrix RotateMatrixX(float angle)
    Matrix tmp = (Matrix){1,0,0,0,
    tmp.m5 = cos(angle);
    tmp.m6 = -sin(angle);
    tmp.m9 = sin(angle);
    tmp.m10 = cos(angle);
    return tmp;

    Then to join multiple of them together i stole another function out of rlgl.h and added its prototype to the top of my C file:

    Matrix MatrixMultiply(Matrix , Matrix );

    Putting it all together a rotation around a given axis looks like this:
    MyModel.transform = MatrixMultiply( MyModel.transform, RotateMatrixX(0.3));

    Because this also threw away the useful scale and translation features of DrawModel() I also made functions for doing that in matrix forms as:
    Matrix MatrixScale(float x, float y, float z);
    Matrix MatrixTranslate(float x, float y, float z);

    All of this could be packed in to a single magic function that generates the matrix you want in one call, but that would make the order of operations on the matrix non flexible. If you scale a matrix and then translate it has a different result then if you first translate and then scale (Same for rotation around different axies). So just extra parameters is not the solution, but rather building transformation matrixes one operation at a time is rather powerful (Tho the DrawModel() is still super useful when you just want to simply plonk down a model as it is).

    Not only does this make rotating an object in complex ways a lot easier it also is very useful when adjusting your models origin. Just translate and rotate the object to the origin you want and add it to the beginning of your matrix multiply chain. Also useful for moving groups of objects like it was one solid object by reusing the same matrix on all of them. So i think OpenGL transformation matixes should be part of RayLib rather than hidden under its hood.

    Im sure Ray can find a way to implement them in a simple and easy to understand way to keep it with the spirit of this library.

  • edited April 2
    Hey Berni,

    Actually, you can use raymath.h library, just including it in your project. It includes all the required functionality to deal with 3D vector-matrix-quaternion math.

    myModel.transform property was intended to be used for complex (or custom) model transformations, just to embed the model transformation into the model. Other transformations passed by DrawModel() or DrawModelEx() as parameters are just accumulated to model transformations.

    I mean, you have two ways to define model local transformations, just using the functions parameters (basic transformations) or define a custom myModel.transform matrix (more flexible, requires using raymath.h or any other math library).

    Probably some example will be useful to illustrate that... :)
  • Ah i haven't noticed all the matrix building functions are already in raymath.h. By default the build script in notepad++ only points to a include path with raylib.h and nothing else (So to include it i needs to be copied in from src). I assumed the other h files are for internal use by the library so i didn't dig trough them much apart from peeking in to one or two to find how the library does something. Quite a bit of useful stuff in those files.

    An example of how to use transformation matrices would certainly been welcome when i was still figuring this out. Its probably good for beginners to get introduced to matrices at some point since they will likely find them useful in most 3D things (even outside of raylib) rather than just being that scary thing they hated so much back in math class.

    Oh and it might be a good idea to add some compacted down structure definitions in to the cheat sheet. In raylib the contents of some structures often need to be written directly(such as Model, Material, Camera). So you do need to dig trough raylib.h quite often to look up what the name of the struct elements is. Also looking at whats in structures gave me a lot of insight of how raylib works by seeing what data is actually passed around inside.
  • edited April 3
    Hi Berni!

    In src folder there are some header only files that can be quite useful as standalone libraries... I need to promote those files a bit more...

    Here it is some extra info:

    About extra examples on 3D usage, you are right... I take note of that... Actually, I'm planning to reorganize examples folder from this to this.

    About structure definition, I created this wiki entry but it's uncomplete, it needs some extra work...

    Ok, I see I need to improve documentation in general...
Sign In or Register to comment.