diff --git a/examples/models/models_transformations.c b/examples/models/models_transformations.c new file mode 100644 index 000000000..1dcd85f72 --- /dev/null +++ b/examples/models/models_transformations.c @@ -0,0 +1,190 @@ +/******************************************************************************************* + * + * raylib [models] example - Draw some basic geometric shapes (cube, sphere, cylinder...) + * + * Example originally created with raylib 1.0, last time updated with raylib 3.5 + * + * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, + * BSD-like license that allows static linking with closed source software + * + * Copyright (c) 2014-2023 Ramon Santamaria (@raysan5) + * + ********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +// Transforms of the cube +Vector3 position = (Vector3){0.0f, 0.0f, 0.0f}; +Vector3 scale = (Vector3){1.0f, 1.0f, 1.0f}; +Vector3 rotation = (Vector3){0.0f, 0.0f, 0.0f}; + +// Define movement speed +const float translationSpeed = 0.2f; +const float scaleSpeed = 0.1f; +const float rotationSpeed = 2.0f; + +bool left() +{ + return IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT); +} + +bool right() +{ + return IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT); +} + +bool up() +{ + return IsKeyDown(KEY_W) || IsKeyDown(KEY_UP); +} + +bool down() +{ + return IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN); +} + +bool in() +{ + return IsKeyDown(KEY_E) || IsKeyDown(KEY_PAGE_DOWN); +} + +bool out() +{ + return IsKeyDown(KEY_Q) || IsKeyDown(KEY_PAGE_UP); +} + +bool shouldScale() +{ + return IsKeyDown(KEY_LEFT_CONTROL); +} + +bool shouldMove() +{ + return IsKeyDown(KEY_LEFT_SHIFT); +} + +void handleInput() +{ + if (shouldMove()) + { + if (left()) + position.x -= translationSpeed; + else if (right()) + position.x += translationSpeed; + if (down()) + position.y -= translationSpeed; + else if (up()) + position.y += translationSpeed; + if (out()) + position.z += translationSpeed; + else if (in()) + position.z -= translationSpeed; + } + else if (shouldScale()) + { + if (left()) + scale.x -= scaleSpeed; + else if (right()) + scale.x += scaleSpeed; + if (down()) + scale.y -= scaleSpeed; + else if (up()) + scale.y += scaleSpeed; + if (out()) + scale.z += scaleSpeed; + else if (in()) + scale.z -= scaleSpeed; + } + else + { + if (left()) + rotation.x -= rotationSpeed; + else if (right()) + rotation.x += rotationSpeed; + if (down()) + rotation.y -= rotationSpeed; + else if (up()) + rotation.y += rotationSpeed; + if (out()) + rotation.z += rotationSpeed; + else if (in()) + rotation.z -= rotationSpeed; + } +} +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - model transformations"); + + // Generate a cube shaped model to play with + Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 2.0f, 2.0f)); + + // Define the camera to look into our 3d world + Camera camera = {0}; + camera.position = (Vector3){0.0f, 10.0f, 10.0f}; + camera.target = (Vector3){0.0f, 0.0f, 0.0f}; + camera.up = (Vector3){0.0f, 1.0f, 0.0f}; + camera.fovy = 45.0f; + camera.projection = CAMERA_PERSPECTIVE; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + handleInput(); + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + // Set translation matrix + Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); + + // Multiply rotation matrices with each other, to rotate around each axis. + Matrix matRotX = MatrixRotate((Vector3){1.0f, 0.0f, 0.0f}, rotation.x * DEG2RAD); + Matrix matRotY = MatrixRotate((Vector3){0.0f, 1.0f, 0.0f}, rotation.y * DEG2RAD); + Matrix matRotZ = MatrixRotate((Vector3){0.0f, 0.0f, 1.0f}, rotation.z * DEG2RAD); + Matrix matRotCombined = MatrixMultiply(matRotX, matRotY); + matRotCombined = MatrixMultiply(matRotCombined, matRotZ); + + // Set scale matrix + Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); + + DrawModelPro(cube, matTranslation, matRotCombined, matScale, RED); + DrawModelWiresPro(cube, matTranslation, matRotCombined, matScale, BLUE); + DrawGrid(10, 1.0f); // Draw a grid + + EndMode3D(); + + DrawFPS(10, 10); + + DrawText("Left Shift + W/A/S/D to translate", 10, 40, 20, BLUE); + DrawText("Left Ctrl + W/A/S/D to scale", 10, 70, 20, BLUE); + DrawText("W/A/S/D to rotate", 10, 100, 20, BLUE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/models/models_transformations.png b/examples/models/models_transformations.png new file mode 100644 index 000000000..338b3383e Binary files /dev/null and b/examples/models/models_transformations.png differ diff --git a/src/raylib.h b/src/raylib.h index f52f3460d..f6354ae76 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1469,8 +1469,10 @@ RLAPI BoundingBox GetModelBoundingBox(Model model); // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters +RLAPI void DrawModelPro(Model model, Matrix translation, Matrix rotation, Matrix scale, Color tint); // Draw a model with pro parameters RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +RLAPI void DrawModelWiresPro(Model model, Matrix translation, Matrix rotation, Matrix scale, Color tint); // Draw a model wires (with texture if set) with pro parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source diff --git a/src/rmodels.c b/src/rmodels.c index f9ceec137..66ea07dee 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -3430,7 +3430,13 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); - Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); + DrawModelPro(model, matTranslation, matRotation, matScale, tint); +} + +// Draw a model with pro parameters +void DrawModelPro(Model model, Matrix translation, Matrix rotation, Matrix scale, Color tint) +{ + Matrix matTransform = MatrixMultiply(MatrixMultiply(scale, rotation), translation); // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform) model.transform = MatrixMultiply(model.transform, matTransform); @@ -3471,6 +3477,16 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rlDisableWireMode(); } +// Draw a model wires (with texture if set) with pro parameters +void DrawModelWiresPro(Model model, Matrix translation, Matrix rotation, Matrix scale, Color tint) +{ + rlEnableWireMode(); + + DrawModelPro(model, translation, rotation, scale, tint); + + rlDisableWireMode(); +} + // Draw a billboard void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint) {