Gitignore zig crap

This commit is contained in:
2026-05-05 23:14:53 +02:00
parent c7897e55a8
commit 823d0ae29b
1533 changed files with 19 additions and 642271 deletions

View File

@ -1,331 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - animation blend custom
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by dmitrii-brand (@dmitrii-brand) and reviewed by Ramon Santamaria (@raysan5)
*
* DETAILS: Example demonstrates per-bone animation blending, allowing smooth transitions
* between two animations by interpolating bone transforms. This is useful for:
* - Blending movement animations (walk/run) with action animations (jump/attack)
* - Creating smooth animation transitions
* - Layering animations (e.g., upper body attack while lower body walks)
*
* WARNING: GPU skinning must be enabled in raylib with a compilation flag,
* if not enabled, CPU skinning will be used instead
*
* 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) 2026 dmitrii-brand (@dmitrii-brand)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include "rlgl.h" // Requried for: rlUpdateVertexBuffer() (CPU-skinning)
#include <string.h> // Required for: memcpy()
#include <stdlib.h> // Required for: NULL
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static bool IsUpperBodyBone(const char *boneName);
static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim1, int frame1,
ModelAnimation *anim2, int frame2, float blend, bool upperBodyBlend);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - animation blend custom");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 4.0f, 4.0f, 4.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load gltf model
Model model = LoadModel("resources/models/gltf/greenman.glb");
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
// Load skinning shader
// WARNING: GPU skinning must be enabled in raylib with a compilation flag,
// if not enabled, CPU skinning will be used instead
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
model.materials[1].shader = skinningShader;
// Load gltf model animations
int animCount = 0;
ModelAnimation *anims = LoadModelAnimations("resources/models/gltf/greenman.glb", &animCount);
// Use specific animation indices: 2-walk/move, 3-attack
int animIndex0 = 2; // Walk/Move animation (index 2)
int animIndex1 = 3; // Attack animation (index 3)
int animCurrentFrame0 = 0;
int animCurrentFrame1 = 0;
// Validate indices
if (animIndex0 >= animCount) animIndex0 = 0;
if (animIndex1 >= animCount) animIndex1 = (animCount > 1) ? 1 : 0;
bool upperBodyBlend = true; // Toggle: true = upper/lower body blending, false = uniform blending (50/50)
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Toggle upper/lower body blending mode (SPACE key)
if (IsKeyPressed(KEY_SPACE)) upperBodyBlend = !upperBodyBlend;
// Update animation frames
ModelAnimation anim0 = anims[animIndex0];
ModelAnimation anim1 = anims[animIndex1];
animCurrentFrame0 = (animCurrentFrame0 + 1)%anim0.keyframeCount;
animCurrentFrame1 = (animCurrentFrame1 + 1)%anim1.keyframeCount;
// Blend the two animations
// When upperBodyBlend is ON: upper body = attack (1.0), lower body = walk (0.0)
// When upperBodyBlend is OFF: uniform blend at 0.5 (50% walk, 50% attack)
float blendFactor = (upperBodyBlend? 1.0f : 0.5f);
UpdateModelAnimationBones(&model, &anim0, animCurrentFrame0,
&anim1, animCurrentFrame1, blendFactor, upperBodyBlend);
// raylib provided animation blending function
//UpdateModelAnimationEx(model, anim0, (float)animCurrentFrame0,
// anim1, (float)animCurrentFrame1, blendFactor);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, position, 1.0f, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
// Draw UI
DrawText(TextFormat("ANIM 0: %s", anim0.name), 10, 10, 20, GRAY);
DrawText(TextFormat("ANIM 1: %s", anim1.name), 10, 40, 20, GRAY);
DrawText(TextFormat("[SPACE] Toggle blending mode: %s",
upperBodyBlend? "Upper/Lower Body Blending" : "Uniform Blending"),
10, GetScreenHeight() - 30, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(anims, animCount); // Unload model animation
UnloadModel(model); // Unload model and meshes/material
UnloadShader(skinningShader); // Unload GPU skinning shader
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Check if a bone is part of upper body (for selective blending)
static bool IsUpperBodyBone(const char *boneName)
{
// Common upper body bone names (adjust based on your model)
if (TextIsEqual(boneName, "spine") || TextIsEqual(boneName, "spine1") || TextIsEqual(boneName, "spine2") ||
TextIsEqual(boneName, "chest") || TextIsEqual(boneName, "upperChest") ||
TextIsEqual(boneName, "neck") || TextIsEqual(boneName, "head") ||
TextIsEqual(boneName, "shoulder") || TextIsEqual(boneName, "shoulder_L") || TextIsEqual(boneName, "shoulder_R") ||
TextIsEqual(boneName, "upperArm") || TextIsEqual(boneName, "upperArm_L") || TextIsEqual(boneName, "upperArm_R") ||
TextIsEqual(boneName, "lowerArm") || TextIsEqual(boneName, "lowerArm_L") || TextIsEqual(boneName, "lowerArm_R") ||
TextIsEqual(boneName, "hand") || TextIsEqual(boneName, "hand_L") || TextIsEqual(boneName, "hand_R") ||
TextIsEqual(boneName, "clavicle") || TextIsEqual(boneName, "clavicle_L") || TextIsEqual(boneName, "clavicle_R"))
{
return true;
}
// Check if bone name contains upper body keywords
if (strstr(boneName, "spine") != NULL || strstr(boneName, "chest") != NULL ||
strstr(boneName, "neck") != NULL || strstr(boneName, "head") != NULL ||
strstr(boneName, "shoulder") != NULL || strstr(boneName, "arm") != NULL ||
strstr(boneName, "hand") != NULL || strstr(boneName, "clavicle") != NULL)
{
return true;
}
return false;
}
// Blend two animations per-bone with selective upper/lower body blending
static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim0, int frame0,
ModelAnimation *anim1, int frame1, float blend, bool upperBodyBlend)
{
// Validate inputs
if ((anim0->boneCount != 0) && (anim0->keyframePoses != NULL) &&
(anim1->boneCount != 0) && (anim1->keyframePoses != NULL) &&
(model->skeleton.boneCount != 0) && (model->skeleton.bindPose != NULL))
{
// Clamp blend factor to [0, 1]
blend = fminf(1.0f, fmaxf(0.0f, blend));
// Ensure frame indices are valid
if (frame0 >= anim0->keyframeCount) frame0 = anim0->keyframeCount - 1;
if (frame1 >= anim1->keyframeCount) frame1 = anim1->keyframeCount - 1;
if (frame0 < 0) frame0 = 0;
if (frame1 < 0) frame1 = 0;
// Get bone count (use minimum of all to be safe)
int boneCount = model->skeleton.boneCount;
if (anim0->boneCount < boneCount) boneCount = anim0->boneCount;
if (anim1->boneCount < boneCount) boneCount = anim1->boneCount;
// Blend each bone
for (int boneIndex = 0; boneIndex < boneCount; boneIndex++)
{
// Determine blend factor for this bone
float boneBlendFactor = blend;
// If upper body blending is enabled, use different blend factors for upper vs lower body
if (upperBodyBlend)
{
const char *boneName = model->skeleton.bones[boneIndex].name;
bool isUpperBody = IsUpperBodyBone(boneName);
// Upper body: use anim1 (attack), Lower body: use anim0 (walk)
// blend = 0.0 means full anim0 (walk), 1.0 means full anim1 (attack)
if (isUpperBody) boneBlendFactor = blend; // Upper body: blend towards anim1 (attack)
else boneBlendFactor = 1.0f - blend; // Lower body: blend towards anim0 (walk) - invert the blend
}
// Get transforms from both animations
Transform *bindTransform = &model->skeleton.bindPose[boneIndex];
Transform *animTransform0 = &anim0->keyframePoses[frame0][boneIndex];
Transform *animTransform1 = &anim1->keyframePoses[frame1][boneIndex];
// Blend the transforms
Transform blended = { 0 };
blended.translation = Vector3Lerp(animTransform0->translation, animTransform1->translation, boneBlendFactor);
blended.rotation = QuaternionSlerp(animTransform0->rotation, animTransform1->rotation, boneBlendFactor);
blended.scale = Vector3Lerp(animTransform0->scale, animTransform1->scale, boneBlendFactor);
// Convert bind pose to matrix
Matrix bindMatrix = MatrixMultiply(MatrixMultiply(
MatrixScale(bindTransform->scale.x, bindTransform->scale.y, bindTransform->scale.z),
QuaternionToMatrix(bindTransform->rotation)),
MatrixTranslate(bindTransform->translation.x, bindTransform->translation.y, bindTransform->translation.z));
// Convert blended transform to matrix
Matrix blendedMatrix = MatrixMultiply(MatrixMultiply(
MatrixScale(blended.scale.x, blended.scale.y, blended.scale.z),
QuaternionToMatrix(blended.rotation)),
MatrixTranslate(blended.translation.x, blended.translation.y, blended.translation.z));
// Calculate final bone matrix (similar to UpdateModelAnimationBones)
model->boneMatrices[boneIndex] = MatrixMultiply(MatrixInvert(bindMatrix), blendedMatrix);
}
// CPU skinning, updates CPU buffers and uploads them to GPU (if available)
// NOTE: Fallback in case GPU skinning is not supported or enabled
for (int m = 0; m < model->meshCount; m++)
{
Mesh mesh = model->meshes[m];
Vector3 animVertex = { 0 };
Vector3 animNormal = { 0 };
const int vertexValuesCount = mesh.vertexCount*3;
int boneIndex = 0;
int boneCounter = 0;
float boneWeight = 0.0f;
bool bufferUpdateRequired = false; // Flag to check when anim vertex information is updated
// Skip if missing bone data or missing anim buffers initialization
if ((mesh.boneWeights == NULL) || (mesh.boneIndices == NULL) ||
(mesh.animVertices == NULL) || (mesh.animNormals == NULL)) continue;
for (int vCounter = 0; vCounter < vertexValuesCount; vCounter += 3)
{
mesh.animVertices[vCounter] = 0;
mesh.animVertices[vCounter + 1] = 0;
mesh.animVertices[vCounter + 2] = 0;
if (mesh.animNormals != NULL)
{
mesh.animNormals[vCounter] = 0;
mesh.animNormals[vCounter + 1] = 0;
mesh.animNormals[vCounter + 2] = 0;
}
// Iterates over 4 bones per vertex
for (int j = 0; j < 4; j++, boneCounter++)
{
boneWeight = mesh.boneWeights[boneCounter];
boneIndex = mesh.boneIndices[boneCounter];
// Early stop when no transformation will be applied
if (boneWeight == 0.0f) continue;
animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] };
animVertex = Vector3Transform(animVertex, model->boneMatrices[boneIndex]);
mesh.animVertices[vCounter] += animVertex.x*boneWeight;
mesh.animVertices[vCounter + 1] += animVertex.y*boneWeight;
mesh.animVertices[vCounter + 2] += animVertex.z*boneWeight;
bufferUpdateRequired = true;
// Normals processing
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
if ((mesh.normals != NULL) && (mesh.animNormals != NULL ))
{
animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] };
animNormal = Vector3Transform(animNormal, MatrixTranspose(MatrixInvert(model->boneMatrices[boneIndex])));
mesh.animNormals[vCounter] += animNormal.x*boneWeight;
mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight;
mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight;
}
}
}
if (bufferUpdateRequired)
{
// Update GPU vertex buffers with updated data (position + normals)
rlUpdateVertexBuffer(mesh.vboId[SHADER_LOC_VERTEX_POSITION], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0);
if (mesh.normals != NULL) rlUpdateVertexBuffer(mesh.vboId[SHADER_LOC_VERTEX_NORMAL], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0);
}
}
}
}

View File

@ -1,278 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - animation blending
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 5.5, last time updated with raylib 6.0
*
* Example contributed by Kirandeep (@Kirandeep-Singh-Khehra) and reviewed by Ramon Santamaria (@raysan5)
*
* WARNING: GPU skinning must be enabled in raylib with a compilation flag,
* if not enabled, CPU skinning will be used instead
*
* 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) 2024-2026 Kirandeep (@Kirandeep-Singh-Khehra) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for: UI controls
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - animation blending");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 6.0f, 6.0f, 6.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load model
Model model = LoadModel("resources/models/gltf/robot.glb"); // Load character model
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model world position
// Load skinning shader
// WARNING: It requires SUPPORT_GPU_SKINNING enabled on raylib (disabled by default)
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
// Assign skinning shader to all materials shaders
//for (int i = 0; i < model.materialCount; i++) model.materials[i].shader = skinningShader;
// Load model animations
int animCount = 0;
ModelAnimation *anims = LoadModelAnimations("resources/models/gltf/robot.glb", &animCount);
// Animation playing variables
// NOTE: Two animations are played with a smooth transition between them
int currentAnimPlaying = 0; // Current animation playing (0 o 1)
int nextAnimToPlay = 1; // Next animation to play (to transition)
bool animTransition = false; // Flag to register anim transition state
int animIndex0 = 10; // Current animation playing (walking)
float animCurrentFrame0 = 0.0f; // Current animation frame (supporting interpolated frames)
float animFrameSpeed0 = 0.5f; // Current animation play speed
int animIndex1 = 6; // Next animation to play (running)
float animCurrentFrame1 = 0.0f; // Next animation frame (supporting interpolated frames)
float animFrameSpeed1 = 0.5f; // Next animation play speed
float animBlendFactor = 0.0f; // Blend factor from anim0[frame0] --> anim1[frame1], [0.0f..1.0f]
// NOTE: 0.0f results in full anim0[] and 1.0f in full anim1[]
float animBlendTime = 2.0f; // Time to blend from one playing animation to another (in seconds)
float animBlendTimeCounter = 0.0f; // Time counter (delta time)
bool animPause = false; // Pause animation
// UI required variables
char *animNames[64] = { 0 }; // Pointers to animation names for dropdown box
for (int i = 0; i < animCount; i++) animNames[i] = anims[i].name;
bool dropdownEditMode0 = false;
bool dropdownEditMode1 = false;
float animFrameProgress0 = 0.0f;
float animFrameProgress1 = 0.0f;
float animBlendProgress = 0.0f;
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
if (IsKeyPressed(KEY_P)) animPause = !animPause;
if (!animPause)
{
// Start transition from anim0[] to anim1[]
if (IsKeyPressed(KEY_SPACE) && !animTransition)
{
if (currentAnimPlaying == 0)
{
// Transition anim0 --> anim1
nextAnimToPlay = 1;
animCurrentFrame1 = 0.0f;
}
else
{
// Transition anim1 --> anim0
nextAnimToPlay = 0;
animCurrentFrame0 = 0.0f;
}
// Set animation transition
animTransition = true;
animBlendTimeCounter = 0.0f;
animBlendFactor = 0.0f;
}
if (animTransition)
{
// Playing anim0 and anim1 at the same time
animCurrentFrame0 += animFrameSpeed0;
if (animCurrentFrame0 >= anims[animIndex0].keyframeCount) animCurrentFrame0 = 0.0f;
animCurrentFrame1 += animFrameSpeed1;
if (animCurrentFrame1 >= anims[animIndex1].keyframeCount) animCurrentFrame1 = 0.0f;
// Increment blend factor over time to transition from anim0 --> anim1 over time
// NOTE: Time blending could be other than linear, using some easing
animBlendFactor = animBlendTimeCounter/animBlendTime;
animBlendTimeCounter += GetFrameTime();
animBlendProgress = animBlendFactor;
// Update model with animations blending
if (nextAnimToPlay == 1)
{
// Blend anim0 --> anim1
UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0,
anims[animIndex1], animCurrentFrame1, animBlendFactor);
}
else
{
// Blend anim1 --> anim0
UpdateModelAnimationEx(model, anims[animIndex1], animCurrentFrame1,
anims[animIndex0], animCurrentFrame0, animBlendFactor);
}
// Check if transition completed
if (animBlendFactor > 1.0f)
{
// Reset frame states
if (currentAnimPlaying == 0) animCurrentFrame0 = 0.0f;
else if (currentAnimPlaying == 1) animCurrentFrame1 = 0.0f;
currentAnimPlaying = nextAnimToPlay; // Update current animation playing
animBlendFactor = 0.0f; // Reset blend factor
animTransition = false; // Exit transition mode
animBlendTimeCounter = 0.0f;
}
}
else
{
// Play only one anim, the current one
if (currentAnimPlaying == 0)
{
// Playing anim0 at defined speed
animCurrentFrame0 += animFrameSpeed0;
if (animCurrentFrame0 >= anims[animIndex0].keyframeCount) animCurrentFrame0 = 0.0f;
UpdateModelAnimation(model, anims[animIndex0], animCurrentFrame0);
//UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0,
// anims[animIndex1], animCurrentFrame1, 0.0f); // Same as above, first animation frame blend
}
else if (currentAnimPlaying == 1)
{
// Playing anim1 at defined speed
animCurrentFrame1 += animFrameSpeed1;
if (animCurrentFrame1 >= anims[animIndex1].keyframeCount) animCurrentFrame1 = 0.0f;
UpdateModelAnimation(model, anims[animIndex1], animCurrentFrame1);
//UpdateModelAnimationEx(model, anims[animIndex0], animCurrentFrame0,
// anims[animIndex1], animCurrentFrame1, 1.0f); // Same as above, second animation frame blend
}
}
}
// Update progress bars values with current frame for each animation
animFrameProgress0 = animCurrentFrame0;
animFrameProgress1 = animCurrentFrame1;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, position, 1.0f, WHITE); // Draw animated model
DrawGrid(10, 1.0f);
EndMode3D();
if (animTransition) DrawText("ANIM TRANSITION BLENDING!", 170, 50, 30, BLUE);
// Draw UI elements
//---------------------------------------------------------------------------------------------
if (dropdownEditMode0) GuiDisable();
GuiSlider((Rectangle){ 10, 38, 160, 12 },
NULL, TextFormat("x%.1f", animFrameSpeed0), &animFrameSpeed0, 0.1f, 2.0f);
GuiEnable();
if (dropdownEditMode1) GuiDisable();
GuiSlider((Rectangle){ GetScreenWidth() - 170.0f, 38, 160, 12 },
TextFormat("%.1fx", animFrameSpeed1), NULL, &animFrameSpeed1, 0.1f, 2.0f);
GuiEnable();
// Draw animation selectors for blending transition
// NOTE: Transition does not start until requested
GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 1);
if (GuiDropdownBox((Rectangle){ 10, 10, 160, 24 }, TextJoin(animNames, animCount, ";"),
&animIndex0, dropdownEditMode0)) dropdownEditMode0 = !dropdownEditMode0;
// Blending process progress bar
if (nextAnimToPlay == 1) GuiSetStyle(PROGRESSBAR, PROGRESS_SIDE, 0); // Left-->Right
else GuiSetStyle(PROGRESSBAR, PROGRESS_SIDE, 1); // Right-->Left
GuiProgressBar((Rectangle){ 180, 14, 440, 16 }, NULL, NULL, &animBlendProgress, 0.0f, 1.0f);
GuiSetStyle(PROGRESSBAR, PROGRESS_SIDE, 0); // Reset to Left-->Right
if (GuiDropdownBox((Rectangle){ GetScreenWidth() - 170.0f, 10, 160, 24 }, TextJoin(animNames, animCount, ";"),
&animIndex1, dropdownEditMode1)) dropdownEditMode1 = !dropdownEditMode1;
// Draw playing timeline with keyframes for anim0[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 60.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 0",
TextFormat("FRAME: %.2f / %i", animFrameProgress0, anims[animIndex0].keyframeCount),
&animFrameProgress0, 0.0f, (float)anims[animIndex0].keyframeCount);
for (int i = 0; i < anims[animIndex0].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i),
GetScreenHeight() - 60, 1, 20, BLUE);
// Draw playing timeline with keyframes for anim1[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 30.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 1",
TextFormat("FRAME: %.2f / %i", animFrameProgress1, anims[animIndex1].keyframeCount),
&animFrameProgress1, 0.0f, (float)anims[animIndex1].keyframeCount);
for (int i = 0; i < anims[animIndex1].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i),
GetScreenHeight() - 30, 1, 20, BLUE);
//---------------------------------------------------------------------------------------------
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(anims, animCount); // Unload model animation
UnloadModel(model); // Unload model and meshes/material
UnloadShader(skinningShader); // Unload GPU skinning shader
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,120 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - animation gpu skinning
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 4.5, last time updated with raylib 4.5
*
* Example contributed by Daniel Holden (@orangeduck) and reviewed by Ramon Santamaria (@raysan5)
*
* WARNING: GPU skinning must be enabled in raylib with a compilation flag,
* if not enabled, CPU skinning will be used instead
*
* 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) 2024-2025 Daniel Holden (@orangeduck)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - animation gpu skinning");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load gltf model
Model model = LoadModel("resources/models/gltf/greenman.glb"); // Load character model
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
// Load skinning shader
// WARNING: GPU skinning must be enabled in raylib with a compilation flag,
// if not enabled, CPU skinning will be used instead
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
model.materials[1].shader = skinningShader;
// Load gltf model animations
int animCount = 0;
ModelAnimation *anims = LoadModelAnimations("resources/models/gltf/greenman.glb", &animCount);
// Animation playing variables
unsigned int animIndex = 0; // Current animation playing
unsigned int animCurrentFrame = 0; // Current animation frame
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Select current animation
if (IsKeyPressed(KEY_RIGHT)) animIndex = (animIndex + 1)%animCount;
else if (IsKeyPressed(KEY_LEFT)) animIndex = (animIndex + animCount - 1)%animCount;
// Update model animation
animCurrentFrame = (animCurrentFrame + 1)%anims[animIndex].keyframeCount;
UpdateModelAnimation(model, anims[animIndex], (float)animCurrentFrame);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, position, 1.0f, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText(TextFormat("Current animation: %s", anims[animIndex].name), 10, 40, 20, MAROON);
DrawText("Use the LEFT/RIGHT keys to switch animation", 10, 10, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(anims, animCount); // Unload model animation
UnloadModel(model); // Unload model and meshes/material
UnloadShader(skinningShader); // Unload GPU skinning shader
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,133 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - animation timing
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* 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) 2026 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for: UI controls
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - animation timing");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 6.0f, 6.0f, 6.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load model
Model model = LoadModel("resources/models/gltf/robot.glb");
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model world position
// Load model animations
int animCount = 0;
ModelAnimation *anims = LoadModelAnimations("resources/models/gltf/robot.glb", &animCount);
// Animation playing variables
int animIndex = 10; // Current animation playing
float animCurrentFrame = 0.0f; // Current animation frame (supporting interpolated frames)
float animFrameSpeed = 0.5f; // Animation play speed
bool animPause = false; // Pause animation
// UI required variables
char *animNames[64] = { 0 };
for (int i = 0; i < animCount; i++) animNames[i] = anims[i].name;
bool dropdownEditMode = false;
float animFrameProgress = 0.0f;
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
if (IsKeyPressed(KEY_P)) animPause = !animPause;
if (!animPause && (animIndex < animCount))
{
// Update model animation
animCurrentFrame += animFrameSpeed;
if (animCurrentFrame >= anims[animIndex].keyframeCount) animCurrentFrame = 0.0f;
UpdateModelAnimation(model, anims[animIndex], animCurrentFrame);
}
// NOTE: Animation and playing speed selected through UI
// Update progressbar value with current frame
animFrameProgress = animCurrentFrame;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, position, 1.0f, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
// Draw UI, select anim and playing speed
GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 1);
if (GuiDropdownBox((Rectangle){ 10, 10, 140, 24 }, TextJoin(animNames, animCount, ";"),
&animIndex, dropdownEditMode)) dropdownEditMode = !dropdownEditMode;
GuiSlider((Rectangle){ 260, 10, 500, 24 }, "FRAME SPEED: ", TextFormat("x%.1f", animFrameSpeed),
&animFrameSpeed, 0.1f, 2.0f);
// Draw playing timeline with keyframes
GuiLabel((Rectangle){ 10, GetScreenHeight() - 64.0f, GetScreenWidth() - 20.0f, 24 },
TextFormat("CURRENT FRAME: %.2f / %i", animFrameProgress, anims[animIndex].keyframeCount));
GuiProgressBar((Rectangle){ 10, GetScreenHeight() - 40.0f, GetScreenWidth() - 20.0f, 24 }, NULL, NULL,
&animFrameProgress, 0.0f, (float)anims[animIndex].keyframeCount);
for (int i = 0; i < anims[animIndex].keyframeCount; i++)
DrawRectangle(10 + (int)(((float)(GetScreenWidth() - 20)/(float)anims[animIndex].keyframeCount)*(float)i),
GetScreenHeight() - 40, 1, 24, BLUE);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(anims, animCount); // Unload model animation
UnloadModel(model); // Unload model and meshes/material
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,169 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - basic voxel
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.5
*
* Example contributed by Tim Little (@timlittle) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2025 Tim Little (@timlittle)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define WORLD_SIZE 8 // Size of our voxel world (8x8x8 cubes)
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - basic voxel");
DisableCursor(); // Lock mouse to window center
// Define the camera to look into our 3d world (first person)
Camera3D camera = { 0 };
camera.position = (Vector3){ -2.0f, 0.0f, -2.0f }; // Camera position at ground level
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Create a cube model
Mesh cubeMesh = GenMeshCube(1.0f, 1.0f, 1.0f); // Create a unit cube mesh
Model cubeModel = LoadModelFromMesh(cubeMesh); // Convert mesh to a model
cubeModel.materials[0].maps[MATERIAL_MAP_DIFFUSE].color = BEIGE;
// Initialize voxel world - fill with voxels
bool voxels[WORLD_SIZE][WORLD_SIZE][WORLD_SIZE] = { false };
for (int x = 0; x < WORLD_SIZE; x++)
{
for (int y = 0; y < WORLD_SIZE; y++)
{
for (int z = 0; z < WORLD_SIZE; z++)
{
voxels[x][y][z] = true;
}
}
}
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_FIRST_PERSON);
// Handle voxel removal with mouse click
// This method is quite inefficient. Ray marching through the voxel grid using DDA would be faster, but more complex.
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
// Cast a ray from the screen center (where crosshair would be)
Vector2 screenCenter = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
Ray ray = GetMouseRay(screenCenter, camera);
// Check ray collision with all voxels
float closestDistance = 99999.0f;
Vector3 closestVoxelPosition = { -1, -1, -1 };
bool voxelFound = false;
for (int x = 0; x < WORLD_SIZE; x++)
{
for (int y = 0; y < WORLD_SIZE; y++)
{
for (int z = 0; z < WORLD_SIZE; z++)
{
if (!voxels[x][y][z]) continue; // Skip empty voxels
// Build a bounding box for this voxel
Vector3 position = { (float)x, (float)y, (float)z };
BoundingBox box = {
(Vector3){ position.x - 0.5f, position.y - 0.5f, position.z - 0.5f },
(Vector3){ position.x + 0.5f, position.y + 0.5f, position.z + 0.5f }
};
// Check ray-box collision
RayCollision collision = GetRayCollisionBox(ray, box);
if (collision.hit && (collision.distance < closestDistance))
{
closestDistance = collision.distance;
closestVoxelPosition = (Vector3){ x, y, z };
voxelFound = true;
}
}
}
}
// Remove the closest voxel if one was hit
if (voxelFound)
{
voxels[(int)closestVoxelPosition.x]
[(int)closestVoxelPosition.y]
[(int)closestVoxelPosition.z] = false;
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawGrid(10, 1.0f);
// Draw all voxels
for (int x = 0; x < WORLD_SIZE; x++)
{
for (int y = 0; y < WORLD_SIZE; y++)
{
for (int z = 0; z < WORLD_SIZE; z++)
{
if (!voxels[x][y][z]) continue;
Vector3 position = { (float)x, (float)y, (float)z };
DrawModel(cubeModel, position, 1.0f, BEIGE);
DrawCubeWires(position, 1.0f, 1.0f, 1.0f, BLACK);
}
}
}
EndMode3D();
// Draw reference point for raycasting to delete blocks
DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 4, RED);
DrawText("Left-click a voxel to remove it!", 10, 10, 20, DARKGRAY);
DrawText("WASD to move, mouse to look around", 10, 35, 10, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(cubeModel);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,115 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - billboard rendering
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 1.3, 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - billboard rendering");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 5.0f, 4.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Texture2D bill = LoadTexture("resources/billboard.png"); // Our billboard texture
Vector3 billPositionStatic = { 0.0f, 2.0f, 0.0f }; // Position of static billboard
Vector3 billPositionRotating = { 1.0f, 2.0f, 1.0f }; // Position of rotating billboard
// Entire billboard texture, source is used to take a segment from a larger texture
Rectangle source = { 0.0f, 0.0f, (float)bill.width, (float)bill.height };
// NOTE: Billboard locked on axis-Y
Vector3 billUp = { 0.0f, 1.0f, 0.0f };
// Set the height of the rotating billboard to 1.0 with the aspect ratio fixed
Vector2 size = { source.width/source.height, 1.0f };
// Rotate around origin
// Here we choose to rotate around the image center
Vector2 origin = Vector2Scale(size, 0.5f);
// Distance is needed for the correct billboard draw order
// Larger distance (further away from the camera) should be drawn prior to smaller distance
float distanceStatic;
float distanceRotating;
float rotation = 0.0f;
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
rotation += 0.4f;
distanceStatic = Vector3Distance(camera.position, billPositionStatic);
distanceRotating = Vector3Distance(camera.position, billPositionRotating);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawGrid(10, 1.0f); // Draw a grid
// Draw order matters!
if (distanceStatic > distanceRotating)
{
DrawBillboard(camera, bill, billPositionStatic, 2.0f, WHITE);
DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, size, origin, rotation, WHITE);
}
else
{
DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, size, origin, rotation, WHITE);
DrawBillboard(camera, bill, billPositionStatic, 2.0f, WHITE);
}
EndMode3D();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(bill); // Unload texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,179 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - bone socket
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 4.5, last time updated with raylib 4.5
*
* Example contributed by iP (@ipzaur) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2024-2025 iP (@ipzaur)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define BONE_SOCKETS 3
#define BONE_SOCKET_HAT 0
#define BONE_SOCKET_HAND_R 1
#define BONE_SOCKET_HAND_L 2
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - bone socket");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load gltf model
Model characterModel = LoadModel("resources/models/gltf/greenman.glb"); // Load character model
Model equipModel[BONE_SOCKETS] = {
LoadModel("resources/models/gltf/greenman_hat.glb"), // Index for the hat model is the same as BONE_SOCKET_HAT
LoadModel("resources/models/gltf/greenman_sword.glb"), // Index for the sword model is the same as BONE_SOCKET_HAND_R
LoadModel("resources/models/gltf/greenman_shield.glb") // Index for the shield model is the same as BONE_SOCKET_HAND_L
};
bool showEquip[3] = { true, true, true }; // Toggle on/off equip
// Load gltf model animations
int animsCount = 0;
unsigned int animIndex = 0;
unsigned int animCurrentFrame = 0;
ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/greenman.glb", &animsCount);
// Indices of bones for sockets
int boneSocketIndex[BONE_SOCKETS] = { -1, -1, -1 };
// Search bones for sockets
for (int i = 0; i < characterModel.skeleton.boneCount; i++)
{
if (TextIsEqual(characterModel.skeleton.bones[i].name, "socket_hat"))
{
boneSocketIndex[BONE_SOCKET_HAT] = i;
continue;
}
if (TextIsEqual(characterModel.skeleton.bones[i].name, "socket_hand_R"))
{
boneSocketIndex[BONE_SOCKET_HAND_R] = i;
continue;
}
if (TextIsEqual(characterModel.skeleton.bones[i].name, "socket_hand_L"))
{
boneSocketIndex[BONE_SOCKET_HAND_L] = i;
continue;
}
}
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
unsigned short angle = 0; // Set angle for rotate character
DisableCursor(); // Limit cursor to relative movement inside the window
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Rotate character
if (IsKeyDown(KEY_F)) angle = (angle + 1)%360;
else if (IsKeyDown(KEY_H)) angle = (360 + angle - 1)%360;
// Select current animation
if (IsKeyPressed(KEY_T)) animIndex = (animIndex + 1)%animsCount;
else if (IsKeyPressed(KEY_G)) animIndex = (animIndex + animsCount - 1)%animsCount;
// Toggle shown of equip
if (IsKeyPressed(KEY_ONE)) showEquip[BONE_SOCKET_HAT] = !showEquip[BONE_SOCKET_HAT];
if (IsKeyPressed(KEY_TWO)) showEquip[BONE_SOCKET_HAND_R] = !showEquip[BONE_SOCKET_HAND_R];
if (IsKeyPressed(KEY_THREE)) showEquip[BONE_SOCKET_HAND_L] = !showEquip[BONE_SOCKET_HAND_L];
// Update model animation
ModelAnimation anim = modelAnimations[animIndex];
animCurrentFrame = (animCurrentFrame + 1)%anim.keyframeCount;
UpdateModelAnimation(characterModel, anim, (float)animCurrentFrame);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw character
Quaternion characterRotate = QuaternionFromAxisAngle((Vector3){ 0.0f, 1.0f, 0.0f }, angle*DEG2RAD);
characterModel.transform = MatrixMultiply(QuaternionToMatrix(characterRotate), MatrixTranslate(position.x, position.y, position.z));
UpdateModelAnimation(characterModel, anim, (float)animCurrentFrame);
DrawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform);
// Draw equipments (hat, sword, shield)
for (int i = 0; i < BONE_SOCKETS; i++)
{
if (!showEquip[i]) continue;
Transform *transform = &anim.keyframePoses[animCurrentFrame][boneSocketIndex[i]];
Quaternion inRotation = characterModel.skeleton.bindPose[boneSocketIndex[i]].rotation;
Quaternion outRotation = transform->rotation;
// Calculate socket rotation (angle between bone in initial pose and same bone in current animation frame)
Quaternion rotate = QuaternionMultiply(outRotation, QuaternionInvert(inRotation));
Matrix matrixTransform = QuaternionToMatrix(rotate);
// Translate socket to its position in the current animation
matrixTransform = MatrixMultiply(matrixTransform, MatrixTranslate(transform->translation.x, transform->translation.y, transform->translation.z));
// Transform the socket using the transform of the character (angle and translate)
matrixTransform = MatrixMultiply(matrixTransform, characterModel.transform);
// Draw mesh at socket position with socket angle rotation
DrawMesh(equipModel[i].meshes[0], equipModel[i].materials[1], matrixTransform);
}
DrawGrid(10, 1.0f);
EndMode3D();
DrawText("Use the T/G to switch animation", 10, 10, 20, GRAY);
DrawText("Use the F/H to rotate character left/right", 10, 35, 20, GRAY);
DrawText("Use the 1,2,3 to toggle shown of hat, sword and shield", 10, 60, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(modelAnimations, animsCount);
UnloadModel(characterModel); // Unload character model and meshes/material
// Unload equipment model and meshes/material
for (int i = 0; i < BONE_SOCKETS; i++) UnloadModel(equipModel[i]);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,128 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - box collisions
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 1.3, 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - box collisions");
// Define the camera to look into our 3d world
Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
Vector3 playerPosition = { 0.0f, 1.0f, 2.0f };
Vector3 playerSize = { 1.0f, 2.0f, 1.0f };
Color playerColor = GREEN;
Vector3 enemyBoxPos = { -4.0f, 1.0f, 0.0f };
Vector3 enemyBoxSize = { 2.0f, 2.0f, 2.0f };
Vector3 enemySpherePos = { 4.0f, 0.0f, 0.0f };
float enemySphereSize = 1.5f;
bool collision = false;
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
//----------------------------------------------------------------------------------
// Move player
if (IsKeyDown(KEY_RIGHT)) playerPosition.x += 0.2f;
else if (IsKeyDown(KEY_LEFT)) playerPosition.x -= 0.2f;
else if (IsKeyDown(KEY_DOWN)) playerPosition.z += 0.2f;
else if (IsKeyDown(KEY_UP)) playerPosition.z -= 0.2f;
collision = false;
// Check collisions player vs enemy-box
if (CheckCollisionBoxes(
(BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2,
playerPosition.y - playerSize.y/2,
playerPosition.z - playerSize.z/2 },
(Vector3){ playerPosition.x + playerSize.x/2,
playerPosition.y + playerSize.y/2,
playerPosition.z + playerSize.z/2 }},
(BoundingBox){(Vector3){ enemyBoxPos.x - enemyBoxSize.x/2,
enemyBoxPos.y - enemyBoxSize.y/2,
enemyBoxPos.z - enemyBoxSize.z/2 },
(Vector3){ enemyBoxPos.x + enemyBoxSize.x/2,
enemyBoxPos.y + enemyBoxSize.y/2,
enemyBoxPos.z + enemyBoxSize.z/2 }})) collision = true;
// Check collisions player vs enemy-sphere
if (CheckCollisionBoxSphere(
(BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2,
playerPosition.y - playerSize.y/2,
playerPosition.z - playerSize.z/2 },
(Vector3){ playerPosition.x + playerSize.x/2,
playerPosition.y + playerSize.y/2,
playerPosition.z + playerSize.z/2 }},
enemySpherePos, enemySphereSize)) collision = true;
if (collision) playerColor = RED;
else playerColor = GREEN;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw enemy-box
DrawCube(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, GRAY);
DrawCubeWires(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, DARKGRAY);
// Draw enemy-sphere
DrawSphere(enemySpherePos, enemySphereSize, GRAY);
DrawSphereWires(enemySpherePos, enemySphereSize, 16, 16, DARKGRAY);
// Draw player
DrawCubeV(playerPosition, playerSize, playerColor);
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D();
DrawText("Move player with arrow keys to collide", 220, 40, 20, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,101 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - cubicmap rendering
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.8, 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - cubicmap rendering");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 16.0f, 14.0f, 16.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM)
Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM)
Mesh mesh = GenMeshCubicmap(image, (Vector3){ 1.0f, 1.0f, 1.0f });
Model model = LoadModelFromMesh(mesh);
// NOTE: By default each cube is mapped to one part of texture atlas
Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position
UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM
bool pause = false; // Pause camera orbital rotation (and zoom)
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
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_P)) pause = !pause;
if (!pause) UpdateCamera(&camera, CAMERA_ORBITAL);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, mapPosition, 1.0f, WHITE);
EndMode3D();
DrawTextureEx(cubicmap, (Vector2){ screenWidth - cubicmap.width*4.0f - 20, 20.0f }, 0.0f, 4.0f, WHITE);
DrawRectangleLines(screenWidth - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN);
DrawText("cubicmap image used to", 658, 90, 10, GRAY);
DrawText("generate map 3d model", 658, 104, 10, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(cubicmap); // Unload cubicmap texture
UnloadTexture(texture); // Unload map texture
UnloadModel(model); // Unload map model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,605 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - decals
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5)
* Based on previous work by @mrdoob
*
* 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) 2025 JP Mortiboys (@themushroompirates) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include <string.h> // Required for: memcpy()
#undef FLT_MAX
#define FLT_MAX 340282346638528859811704183484516925440.0f // Maximum value of a float, from bit pattern 01111111011111111111111111111111
#define MAX_DECALS 256
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct MeshBuilder {
int vertexCount;
int vertexCapacity;
Vector3 *vertices;
Vector2 *uvs;
} MeshBuilder;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]);
static void FreeMeshBuilder(MeshBuilder *mb);
static Mesh BuildMesh(MeshBuilder *mb);
static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset);
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s);
static void FreeDecalMeshData(void) { GenMeshDecal((Model){ .meshCount = -1 }, (Matrix){ 0 }, 0.0f, 0.0f); }
static bool GuiButton(Rectangle rec, const char *label);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [models] example - decals");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.6f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load character model
Model model = LoadModel("resources/models/obj/character.obj");
// Apply character skin
Texture2D modelTexture = LoadTexture("resources/models/obj/character_diffuse.png");
SetTextureFilter(modelTexture, TEXTURE_FILTER_BILINEAR);
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture;
BoundingBox modelBBox = GetMeshBoundingBox(model.meshes[0]); // Get mesh bounding box
camera.target = Vector3Lerp(modelBBox.min, modelBBox.max, 0.5f);
camera.position = Vector3Scale(modelBBox.max, 1.0f);
camera.position.x *= 0.1f;
float modelSize = fminf(
fminf(fabsf(modelBBox.max.x - modelBBox.min.x), fabsf(modelBBox.max.y - modelBBox.min.y)),
fabsf(modelBBox.max.z - modelBBox.min.z));
camera.position = (Vector3){ 0.0f, modelBBox.max.y*1.2f, modelSize*3.0f };
float decalSize = modelSize*0.25f;
float decalOffset = 0.01f;
Model placementCube = LoadModelFromMesh(GenMeshCube(decalSize, decalSize, decalSize));
placementCube.materials[0].maps[0].color = LIME;
Material decalMaterial = LoadMaterialDefault();
decalMaterial.maps[0].color = YELLOW;
Image decalImage = LoadImage("resources/raylib_logo.png");
ImageResizeNN(&decalImage, decalImage.width/4, decalImage.height/4);
Texture decalTexture = LoadTextureFromImage(decalImage);
UnloadImage(decalImage);
SetTextureFilter(decalTexture, TEXTURE_FILTER_BILINEAR);
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].texture = decalTexture;
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
bool showModel = true;
static Model decalModels[MAX_DECALS] = { 0 };
int decalCount = 0;
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
//----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Display information about closest hit
RayCollision collision = { 0 };
collision.distance = FLT_MAX;
collision.hit = false;
// Get mouse ray
Ray ray = GetScreenToWorldRay(GetMousePosition(), camera);
// Check ray collision against bounding box first, before trying the full ray-mesh test
RayCollision boxHitInfo = GetRayCollisionBox(ray, modelBBox);
if ((boxHitInfo.hit) && (decalCount < MAX_DECALS))
{
// Check ray collision against model meshes
RayCollision meshHitInfo = { 0 };
for (int m = 0; m < model.meshCount; m++)
{
// NOTE: We consider the model.transform for the collision check but
// it can be checked against any transform Matrix, used when checking against same
// model drawn multiple times with multiple transforms
meshHitInfo = GetRayCollisionMesh(ray, model.meshes[m], model.transform);
if (meshHitInfo.hit)
{
// Save the closest hit mesh
if (!collision.hit || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo;
}
}
if (meshHitInfo.hit) collision = meshHitInfo;
}
// Add decal to mesh on hit point
if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (decalCount < MAX_DECALS))
{
// Create the transformation to project the decal
Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f));
Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){ 0.0f, 1.0f, 0.0f });
// Spin the placement around a bit
splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD*((float)GetRandomValue(-180, 180))));
Mesh decalMesh = GenMeshDecal(model, splat, decalSize, decalOffset);
if (decalMesh.vertexCount > 0)
{
int decalIndex = decalCount++;
decalModels[decalIndex] = LoadModelFromMesh(decalMesh);
decalModels[decalIndex].materials[0].maps[0] = decalMaterial.maps[0];
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw the model at the origin and default scale
if (showModel) DrawModel(model, (Vector3){0.0f, 0.0f, 0.0f}, 1.0f, WHITE);
// Draw the decal models
for (int i = 0; i < decalCount; i++) DrawModel(decalModels[i], (Vector3){ 0 }, 1.0f, WHITE);
// If we hit the mesh, draw the box for the decal
if (collision.hit)
{
Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f));
Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){0,1,0});
placementCube.transform = MatrixInvert(splat);
DrawModel(placementCube, (Vector3){ 0 }, 1.0f, Fade(WHITE, 0.5f));
}
DrawGrid(10, 10.0f);
EndMode3D();
float yPos = 10;
float x0 = GetScreenWidth() - 300.0f;
float x1 = x0 + 100;
float x2 = x1 + 100;
DrawText("Vertices", (int)x1, (int)yPos, 10, LIME);
DrawText("Triangles", (int)x2, (int)yPos, 10, LIME);
yPos += 15;
int vertexCount = 0;
int triangleCount = 0;
for (int i = 0; i < model.meshCount; i++)
{
vertexCount += model.meshes[i].vertexCount;
triangleCount += model.meshes[i].triangleCount;
}
DrawText("Main model", (int)x0, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", vertexCount), (int)x1, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", triangleCount), (int)x2, (int)yPos, 10, LIME);
yPos += 15;
for (int i = 0; i < decalCount; i++)
{
if (i == 20)
{
DrawText("...", (int)x0, (int)yPos, 10, LIME);
yPos += 15;
}
if (i < 20)
{
DrawText(TextFormat("Decal #%d", i+1), (int)x0, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), (int)x1, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), (int)x2, (int)yPos, 10, LIME);
yPos += 15;
}
vertexCount += decalModels[i].meshes[0].vertexCount;
triangleCount += decalModels[i].meshes[0].triangleCount;
}
DrawText("TOTAL", (int)x0, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", vertexCount), (int)x1, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", triangleCount), (int)x2, (int)yPos, 10, LIME);
yPos += 15;
DrawText("Hold RMB to move camera", 10, 430, 10, GRAY);
DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY);
// UI elements
if (GuiButton((Rectangle){ 10, screenHeight - 1000.f, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel;
if (GuiButton((Rectangle){ 10 + 110, screenHeight - 100.0f, 100, 60 }, "Clear Decals"))
{
// Clear decals, unload all decal models
for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]);
decalCount = 0;
}
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model);
UnloadTexture(modelTexture);
// Unload decal models
for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]);
UnloadTexture(decalTexture);
FreeDecalMeshData(); // Free the data for decal generation
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Add triangles to mesh builder (dynamic array manager)
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3])
{
// Reallocate and copy if we need to
if (mb->vertexCapacity <= (mb->vertexCount + 3))
{
int newVertexCapacity = (1 + (mb->vertexCapacity/256))*256;
Vector3 *newVertices = (Vector3 *)MemAlloc(newVertexCapacity*sizeof(Vector3));
if (mb->vertexCapacity > 0)
{
memcpy(newVertices, mb->vertices, mb->vertexCount*sizeof(Vector3));
MemFree(mb->vertices);
}
mb->vertices = newVertices;
mb->vertexCapacity = newVertexCapacity;
}
// Add 3 vertices
int index = mb->vertexCount;
mb->vertexCount += 3;
for (int i = 0; i < 3; i++) mb->vertices[index+i] = vertices[i];
}
// Free mesh builder
static void FreeMeshBuilder(MeshBuilder *mb)
{
MemFree(mb->vertices);
if (mb->uvs) MemFree(mb->uvs);
*mb = (MeshBuilder){ 0 };
}
// Build a Mesh from MeshBuilder data
static Mesh BuildMesh(MeshBuilder *mb)
{
Mesh outMesh = { 0 };
outMesh.vertexCount = mb->vertexCount;
outMesh.triangleCount = mb->vertexCount/3;
outMesh.vertices = MemAlloc(outMesh.vertexCount*3*sizeof(float));
if (mb->uvs) outMesh.texcoords = MemAlloc(outMesh.vertexCount*2*sizeof(float));
for (int i = 0; i < mb->vertexCount; i++)
{
outMesh.vertices[3*i+0] = mb->vertices[i].x;
outMesh.vertices[3*i+1] = mb->vertices[i].y;
outMesh.vertices[3*i+2] = mb->vertices[i].z;
if (mb->uvs)
{
outMesh.texcoords[2*i+0] = mb->uvs[i].x;
outMesh.texcoords[2*i+1] = mb->uvs[i].y;
}
}
UploadMesh(&outMesh, false);
return outMesh;
}
// Clip segment
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s)
{
float d0 = Vector3DotProduct(v0, p) - s;
float d1 = Vector3DotProduct(v1, p) - s;
float s0 = d0/(d0 - d1);
Vector3 position = Vector3Lerp(v0, v1, s0);
return position;
}
// Generate mesh decals for provided model
static Mesh GenMeshDecal(Model target, Matrix projection, float decalSize, float decalOffset)
{
// We're going to use these to build up our decal meshes
// They'll resize automatically as we go, we'll free them at the end
static MeshBuilder meshBuilders[2] = { 0 };
// Ugly way of telling us to free the static MeshBuilder data
if (target.meshCount == -1)
{
FreeMeshBuilder(&meshBuilders[0]);
FreeMeshBuilder(&meshBuilders[1]);
return (Mesh){ 0 };
}
// We're going to need the inverse matrix
Matrix invProj = MatrixInvert(projection);
// Reset the mesh builders
meshBuilders[0].vertexCount = 0;
meshBuilders[1].vertexCount = 0;
// We'll be flip-flopping between the two mesh builders
// Reading from one and writing to the other, then swapping
int mbIndex = 0;
// First pass, just get any triangle inside the bounding box (for each mesh of the model)
for (int meshIndex = 0; meshIndex < target.meshCount; meshIndex++)
{
Mesh mesh = target.meshes[meshIndex];
for (int tri = 0; tri < mesh.triangleCount; tri++)
{
Vector3 vertices[3] = { 0 };
// The way we calculate the vertices of the mesh triangle
// depend on whether the mesh vertices are indexed or not
if (mesh.indices == 0)
{
for (int v = 0; v < 3; v++)
{
vertices[v] = (Vector3){
mesh.vertices[3*3*tri + 3*v + 0],
mesh.vertices[3*3*tri + 3*v + 1],
mesh.vertices[3*3*tri + 3*v + 2]
};
}
}
else
{
for (int v = 0; v < 3; v++)
{
vertices[v] = (Vector3){
mesh.vertices[ 3*mesh.indices[3*tri+0] + v],
mesh.vertices[ 3*mesh.indices[3*tri+1] + v],
mesh.vertices[ 3*mesh.indices[3*tri+2] + v]
};
}
}
// Transform all 3 vertices of the triangle
// and check if they are inside our decal box
int insideCount = 0;
for (int i = 0; i < 3; i++)
{
// To projection space
Vector3 v = Vector3Transform(vertices[i], projection);
if ((fabsf(v.x) < decalSize) || (fabsf(v.y) <= decalSize) || (fabsf(v.z) <= decalSize)) insideCount++;
// We need to keep the transformed vertex
vertices[i] = v;
}
// If any of them are inside, we add the triangle - we'll clip it later
if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices);
}
}
// Clipping time! We need to clip against all 6 directions
Vector3 planes[6] = {
{ 1, 0, 0 },
{ -1, 0, 0 },
{ 0, 1, 0 },
{ 0, -1, 0 },
{ 0, 0, 1 },
{ 0, 0, -1 }
};
for (int face = 0; face < 6; face++)
{
// Swap current model builder (so we read from the one we just wrote to)
mbIndex = 1 - mbIndex;
MeshBuilder *inMesh = &meshBuilders[1 - mbIndex];
MeshBuilder *outMesh = &meshBuilders[mbIndex];
// Reset write builder
outMesh->vertexCount = 0;
float s = 0.5f*decalSize;
for (int i = 0; i < inMesh->vertexCount; i += 3)
{
Vector3 nV1, nV2, nV3, nV4;
float d1 = Vector3DotProduct(inMesh->vertices[ i + 0 ], planes[face] ) - s;
float d2 = Vector3DotProduct(inMesh->vertices[ i + 1 ], planes[face] ) - s;
float d3 = Vector3DotProduct(inMesh->vertices[ i + 2 ], planes[face] ) - s;
int v1Out = (d1 > 0);
int v2Out = (d2 > 0);
int v3Out = (d3 > 0);
// Calculate, how many vertices of the face lie outside of the clipping plane
int total = v1Out + v2Out + v3Out;
switch (total)
{
case 0:
{
// The entire face lies inside of the plane, no clipping needed
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){inMesh->vertices[i], inMesh->vertices[i+1], inMesh->vertices[i+2]});
} break;
case 1:
{
// One vertex lies outside of the plane, perform clipping
if (v1Out)
{
nV1 = inMesh->vertices[i + 1];
nV2 = inMesh->vertices[i + 2];
nV3 = ClipSegment(inMesh->vertices[i], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i], nV2, planes[face], s);
}
if (v2Out)
{
nV1 = inMesh->vertices[i];
nV2 = inMesh->vertices[i + 2];
nV3 = ClipSegment(inMesh->vertices[i + 1], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i + 1], nV2, planes[face], s);
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV3, nV2, nV1});
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV2, nV3, nV4});
break;
}
if (v3Out)
{
nV1 = inMesh->vertices[i];
nV2 = inMesh->vertices[i + 1];
nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s);
}
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3});
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV4, nV3, nV2});
} break;
case 2:
{
// Two vertices lies outside of the plane, perform clipping
if (!v1Out)
{
nV1 = inMesh->vertices[i];
nV2 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3});
}
if (!v2Out)
{
nV1 = inMesh->vertices[i + 1];
nV2 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3});
}
if (!v3Out)
{
nV1 = inMesh->vertices[i + 2];
nV2 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3});
}
} break;
case 3: // The entire face lies outside of the plane, so let's discard the corresponding vertices
default: break;
}
}
}
// Now we just need to re-transform the vertices
MeshBuilder *theMesh = &meshBuilders[mbIndex];
// Allocate room for UVs
if (theMesh->vertexCount > 0)
{
theMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*theMesh->vertexCount);
for (int i = 0; i < theMesh->vertexCount; i++)
{
// Calculate the UVs based on the projected coords
// They are clipped to (-decalSize .. decalSize) and we want them (0..1)
theMesh->uvs[i].x = (theMesh->vertices[i].x/decalSize + 0.5f);
theMesh->uvs[i].y = (theMesh->vertices[i].y/decalSize + 0.5f);
// Tiny nudge in the normal direction so it renders properly over the mesh
theMesh->vertices[i].z -= decalOffset;
// From projection space to world space
theMesh->vertices[i] = Vector3Transform(theMesh->vertices[i], invProj);
}
// Decal model data ready, create the mesh and return it
return BuildMesh(theMesh);
}
else
{
// Return a blank mesh as there's nothing to add
return (Mesh){ 0 };
}
}
// Button UI element
static bool GuiButton(Rectangle rec, const char *label)
{
Color bgColor = GRAY;
bool pressed = false;
if (CheckCollisionPointRec(GetMousePosition(), rec))
{
bgColor = LIGHTGRAY;
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) pressed = true;
}
DrawRectangleRec(rec, bgColor);
DrawRectangleLinesEx(rec, 2.0f, DARKGRAY);
int fontSize = 10;
int textWidth = MeasureText(label, fontSize);
DrawText(label, (int)(rec.x + rec.width*0.5f - textWidth*0.5f), (int)(rec.y + rec.height*0.5f - fontSize*0.5f), fontSize, DARKGRAY);
return pressed;
}

View File

@ -1,118 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - directional billboard
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2025 Robin (@RobinsAviary)
* Killbot art by patvanmackelberg https://opengameart.org/content/killbot-8-directional under CC0
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include <stdlib.h>
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - directional billboard");
// Set up the camera
Camera camera = { 0 };
camera.position = (Vector3){ 2.0f, 1.0f, 2.0f }; // Starting position
camera.target = (Vector3){ 0.0f, 0.5f, 0.0f }; // Target position
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Up vector
camera.fovy = 45.0f; // FOV
camera.projection = CAMERA_PERSPECTIVE; // Projection type (Standard 3D perspective)
// Load billboard texture
Texture skillbot = LoadTexture("resources/skillbot.png");
// Timer to update animation
float anim_timer = 0.0f;
// Animation frame
unsigned int anim = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Update timer with delta time
anim_timer += GetFrameTime();
// Update frame index after a certain amount of time (half a second)
if (anim_timer > 0.5f)
{
anim_timer = 0.0f;
anim += 1;
}
// Reset frame index to zero on overflow
if (anim >= 4) anim = 0;
// Find the current direction frame based on the camera position to the billboard object
float dir = (float)floor(((Vector2Angle((Vector2){ 2.0f, 0.0f }, (Vector2){ camera.position.x, camera.position.z })/PI)*4.0f) + 0.25f);
// Correct frame index if angle is negative
if (dir < 0.0f)
{
dir = 8.0f - (float)abs((int)dir);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawGrid(10, 1.0f);
// Draw billboard pointing straight up to the sky, rotated relative to the camera and offset from the bottom
DrawBillboardPro(camera, skillbot, (Rectangle){ 0.0f + (anim*24.0f), 0.0f + (dir*24.0f), 24.0f, 24.0f }, Vector3Zero(), (Vector3){ 0.0f, 1.0f, 0.0f }, Vector2One(), (Vector2){ 0.5f, 0.0f }, 0, WHITE);
EndMode3D();
// Render various variables for reference
DrawText(TextFormat("animation: %d", anim), 10, 10, 20, DARKGRAY);
DrawText(TextFormat("direction frame: %.0f", dir), 10, 40, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// Unload billboard texture
UnloadTexture(skillbot);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,139 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - first person maze
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 2.5, 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) 2019-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h> // Required for: free()
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - first person maze");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 0.2f, 0.4f, 0.2f }; // Camera position
camera.target = (Vector3){ 0.185f, 0.4f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Image imMap = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM)
Texture2D cubicmap = LoadTextureFromImage(imMap); // Convert image to texture to display (VRAM)
Mesh mesh = GenMeshCubicmap(imMap, (Vector3){ 1.0f, 1.0f, 1.0f });
Model model = LoadModelFromMesh(mesh);
// NOTE: By default each cube is mapped to one part of texture atlas
Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
// Get map image data to be used for collision detection
Color *mapPixels = LoadImageColors(imMap);
UnloadImage(imMap); // Unload image from RAM
Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position
DisableCursor(); // Limit cursor to relative movement inside the window
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
//----------------------------------------------------------------------------------
Vector3 oldCamPos = camera.position; // Store old camera position
UpdateCamera(&camera, CAMERA_FIRST_PERSON);
// Check player collision (we simplify to 2D collision detection)
Vector2 playerPos = { camera.position.x, camera.position.z };
float playerRadius = 0.1f; // Collision radius (player is modelled as a cilinder for collision)
int playerCellX = (int)(playerPos.x - mapPosition.x + 0.5f);
int playerCellY = (int)(playerPos.y - mapPosition.z + 0.5f);
// Out-of-limits security check
if (playerCellX < 0) playerCellX = 0;
else if (playerCellX >= cubicmap.width) playerCellX = cubicmap.width - 1;
if (playerCellY < 0) playerCellY = 0;
else if (playerCellY >= cubicmap.height) playerCellY = cubicmap.height - 1;
// Check map collisions using image data and player position against surrounding cells only
for (int y = playerCellY - 1; y <= playerCellY + 1; y++)
{
// Avoid map accessing out of bounds
if ((y >= 0) && (y < cubicmap.height))
{
for (int x = playerCellX - 1; x <= playerCellX + 1; x++)
{
// NOTE: Collision: Only checking R channel for white pixel
if (((x >= 0) && (x < cubicmap.width)) &&
(mapPixels[y*cubicmap.width + x].r == 255) &&
(CheckCollisionCircleRec(playerPos, playerRadius,
(Rectangle){ mapPosition.x - 0.5f + x*1.0f, mapPosition.z - 0.5f + y*1.0f, 1.0f, 1.0f })))
{
// Collision detected, reset camera position
camera.position = oldCamPos;
}
}
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, mapPosition, 1.0f, WHITE); // Draw maze map
EndMode3D();
DrawTextureEx(cubicmap, (Vector2){ GetScreenWidth() - cubicmap.width*4.0f - 20, 20.0f }, 0.0f, 4.0f, WHITE);
DrawRectangleLines(GetScreenWidth() - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN);
// Draw player position radar
DrawRectangle(GetScreenWidth() - cubicmap.width*4 - 20 + playerCellX*4, 20 + playerCellY*4, 4, 4, RED);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadImageColors(mapPixels); // Unload color array
UnloadTexture(cubicmap); // Unload cubicmap texture
UnloadTexture(texture); // Unload map texture
UnloadModel(model); // Unload map model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,90 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - geometric shapes
*
* Example complexity rating: [★☆☆☆] 1/4
*
* 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-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes");
// 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
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawCube((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, RED);
DrawCubeWires((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, GOLD);
DrawCubeWires((Vector3){-4.0f, 0.0f, -2.0f}, 3.0f, 6.0f, 2.0f, MAROON);
DrawSphere((Vector3){-1.0f, 0.0f, -2.0f}, 1.0f, GREEN);
DrawSphereWires((Vector3){1.0f, 0.0f, 2.0f}, 2.0f, 16, 16, LIME);
DrawCylinder((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, SKYBLUE);
DrawCylinderWires((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, DARKBLUE);
DrawCylinderWires((Vector3){4.5f, -1.0f, 2.0f}, 1.0f, 1.0f, 2.0f, 6, BROWN);
DrawCylinder((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, GOLD);
DrawCylinderWires((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, PINK);
DrawCapsule ((Vector3){-3.0f, 1.5f, -4.0f}, (Vector3){-4.0f, -1.0f, -4.0f}, 1.2f, 8, 8, VIOLET);
DrawCapsuleWires((Vector3){-3.0f, 1.5f, -4.0f}, (Vector3){-4.0f, -1.0f, -4.0f}, 1.2f, 8, 8, PURPLE);
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,92 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - heightmap rendering
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 1.8, 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) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap rendering");
// Define our custom camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 18.0f, 21.0f, 18.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM)
Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM)
Mesh mesh = GenMeshHeightmap(image, (Vector3){ 16, 8, 16 }); // Generate heightmap mesh (RAM and VRAM)
Model model = LoadModelFromMesh(mesh); // Load model from generated mesh
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Define model position
UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, mapPosition, 1.0f, RED);
DrawGrid(20, 1.0f);
EndMode3D();
DrawTexture(texture, screenWidth - texture.width - 20, 20, WHITE);
DrawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, GREEN);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,156 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - loading
*
* Example complexity rating: [★☆☆☆] 1/4
*
* NOTE: raylib supports multiple models file formats:
*
* - OBJ > Text file format. Must include vertex position-texcoords-normals information,
* if .obj references some .mtl materials file, it will be tried to be loaded
* - GLTF/GLB > Text/binary file formats. Includes lot of information and it could
* also reference external files, mesh and materials data will be tried to be loaded
* - IQM > Binary file format. Includes mesh vertex data but also animation data,
* meshes and animation data can be loaded
* - VOX > Binary file format. MagikaVoxel mesh format:
* https://github.com/ephtracy/voxel-model/blob/master/MagicaVoxel-file-format-vox.txt
* - M3D > Binary file format. Model 3D format:
* https://bztsrc.gitlab.io/model3d
*
* Example originally created with raylib 2.0, last time updated with raylib 4.2
*
* 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-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - loading");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 50.0f, 50.0f, 50.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 12.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera mode type
Model model = LoadModel("resources/models/obj/castle.obj"); // Load model
Texture2D texture = LoadTexture("resources/models/obj/castle_diffuse.png"); // Load model texture
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
BoundingBox bounds = GetMeshBoundingBox(model.meshes[0]); // Set model bounds
// NOTE: bounds are calculated from the original size of the model,
// if model is scaled on drawing, bounds must be also scaled
bool selected = false; // Selected object flag
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Load new models/textures on drag&drop
if (IsFileDropped())
{
FilePathList droppedFiles = LoadDroppedFiles();
if (droppedFiles.count == 1) // Only support one file dropped
{
if (IsFileExtension(droppedFiles.paths[0], ".obj") ||
IsFileExtension(droppedFiles.paths[0], ".gltf") ||
IsFileExtension(droppedFiles.paths[0], ".glb") ||
IsFileExtension(droppedFiles.paths[0], ".vox") ||
IsFileExtension(droppedFiles.paths[0], ".iqm") ||
IsFileExtension(droppedFiles.paths[0], ".m3d")) // Model file formats supported
{
UnloadModel(model); // Unload previous model
model = LoadModel(droppedFiles.paths[0]); // Load new model
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set current map diffuse texture
bounds = GetMeshBoundingBox(model.meshes[0]);
// Move camera position from target enough distance to visualize model properly
camera.position.x = bounds.max.x + 10.0f;
camera.position.y = bounds.max.y + 10.0f;
camera.position.z = bounds.max.z + 10.0f;
}
else if (IsFileExtension(droppedFiles.paths[0], ".png")) // Texture file formats supported
{
// Unload current model texture and load new one
UnloadTexture(texture);
texture = LoadTexture(droppedFiles.paths[0]);
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;
}
}
UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory
}
// Select model on mouse click
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{
// Check collision between ray and box
if (GetRayCollisionBox(GetScreenToWorldRay(GetMousePosition(), camera), bounds).hit) selected = !selected;
else selected = false;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, position, 1.0f, WHITE); // Draw 3d model with texture
DrawGrid(20, 10.0f); // Draw a grid
if (selected) DrawBoundingBox(bounds, GREEN); // Draw selection box
EndMode3D();
DrawText("Drag & drop model to load mesh/texture.", 10, GetScreenHeight() - 20, 10, DARKGRAY);
if (selected) DrawText("MODEL SELECTED", GetScreenWidth() - 110, 10, 10, GREEN);
DrawText("(c) Castle 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,109 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - loading gltf
*
* Example complexity rating: [★☆☆☆] 1/4
*
* LIMITATIONS:
* - Only supports 1 armature per file, and skips loading it if there are multiple armatures
* - Only supports linear interpolation (default method in Blender when checked
* "Always Sample Animations" when exporting a GLTF file)
* - Only supports translation/rotation/scale animation channel.path,
* weights not considered (i.e. morph targets)
*
* Example originally created with raylib 3.7, last time updated with raylib 4.2
*
* 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) 2020-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - loading gltf");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 6.0f, 6.0f, 6.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load model
Model model = LoadModel("resources/models/gltf/robot.glb");
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model world position
// Load model animations
int animCount = 0;
ModelAnimation *anims = LoadModelAnimations("resources/models/gltf/robot.glb", &animCount);
// Animation playing variables
unsigned int animIndex = 0; // Current animation playing
unsigned int animCurrentFrame = 0; // Current animation frame
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Select current animation
if (IsKeyPressed(KEY_RIGHT)) animIndex = (animIndex + 1)%animCount;
else if (IsKeyPressed(KEY_LEFT)) animIndex = (animIndex + animCount - 1)%animCount;
// Update model animation
animCurrentFrame = (animCurrentFrame + 1)%anims[animIndex].keyframeCount;
UpdateModelAnimation(model, anims[animIndex], (float)animCurrentFrame);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, position, 1.0f, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText(TextFormat("Current animation: %s", anims[animIndex].name), 10, 40, 20, MAROON);
DrawText("Use the LEFT/RIGHT keys to switch animation", 10, 10, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(anims, animCount); // Unload model animations data
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,104 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - loading iqm
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 2.5, last time updated with raylib 3.5
*
* Example contributed by Culacant (@culacant) and reviewed by Ramon Santamaria (@raysan5)
*
* NOTES: To export an IQM model from blender, make sure it is not posed, the vertices need
* to be in the same position as they would be in edit mode and the scale of the models is
* set to 0; scaling can be set from the export menu
*
* 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) 2019-2025 Culacant (@culacant) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - loading iqm");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 4.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera mode type
Model model = LoadModel("resources/models/iqm/guy.iqm"); // Load the animated model mesh and basic data
Texture2D texture = LoadTexture("resources/models/iqm/guytex.png"); // Load model texture and set material
SetMaterialTexture(&model.materials[0], MATERIAL_MAP_DIFFUSE, texture); // Set model material map texture
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
// Load animation data
int animCount = 0;
ModelAnimation *anims = LoadModelAnimations("resources/models/iqm/guyanim.iqm", &animCount);
// Animation playing variables
unsigned int animIndex = 0; // Current animation playing
float animCurrentFrame = 0.0f; // Current animation frame (supporting interpolated frames)
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Play animation when spacebar is held down
animCurrentFrame += 1.0f;
UpdateModelAnimation(model, anims[0], animCurrentFrame);
if (animCurrentFrame >= anims[0].keyframeCount) animCurrentFrame = 0;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModelEx(model, position, (Vector3){ 1.0f, 0.0f, 0.0f }, -90.0f, (Vector3){ 1.0f, 1.0f, 1.0f }, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText(TextFormat("Current animation: %s", anims[animIndex].name), 10, 10, 20, MAROON);
DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModelAnimations(anims, animCount); // Unload model animations data
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,132 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - loading m3d
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 4.5, last time updated with raylib 4.5
*
* Example contributed by bzt (@bztsrc) and reviewed by Ramon Santamaria (@raysan5)
*
* NOTES:
* - Model3D (M3D) fileformat specs: https://gitlab.com/bztsrc/model3d
* - Bender M3D exported: https://gitlab.com/bztsrc/model3d/-/tree/master/blender
*
* 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) 2022-2025 bzt (@bztsrc)
*
********************************************************************************************/
#include "raylib.h"
static void DrawModelSkeleton(ModelSkeleton skeleton, ModelAnimPose pose, float scale, Color color);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - loading m3d");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 1.5f, 1.5f, 1.5f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.4f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load model
Model model = LoadModel("resources/models/m3d/cesium_man.m3d"); // Load the animated model mesh and basic data
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
// Load animation data
int animCount = 0;
ModelAnimation *anims = LoadModelAnimations("resources/models/m3d/cesium_man.m3d", &animCount);
// Animation playing variables
unsigned int animIndex = 0; // Current animation playing
float animCurrentFrame = 0.0f; // Current animation frame (supporting interpolated frames)
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
// Select current animation
if (IsKeyPressed(KEY_RIGHT)) animIndex = (animIndex + 1)%animCount;
else if (IsKeyPressed(KEY_LEFT)) animIndex = (animIndex + animCount - 1)%animCount;
// Update model animation
animCurrentFrame += 1.0f;
if (animCurrentFrame >= anims[animIndex].keyframeCount) animCurrentFrame = 0.0f;
UpdateModelAnimation(model, anims[animIndex], animCurrentFrame);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw 3d model with texture
if (!IsKeyDown(KEY_SPACE)) DrawModel(model, position, 1.0f, WHITE);
else
{
// Draw the animated skeleton
DrawModelSkeleton(model.skeleton, anims[animIndex].keyframePoses[(int)animCurrentFrame], 1.0f, RED);
}
DrawGrid(10, 1.0f);
EndMode3D();
DrawText(TextFormat("Current animation: %s", anims[animIndex].name), 10, 10, 20, LIGHTGRAY);
DrawText("Press SPACE to draw skeleton", 10, 40, 20, MAROON);
DrawText("(c) CesiumMan model by KhronosGroup", GetScreenWidth() - 210, GetScreenHeight() - 20, 10, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModelAnimations(anims, animCount); // Unload model animations data
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
// Draw model skeleton
static void DrawModelSkeleton(ModelSkeleton skeleton, ModelAnimPose pose, float scale, Color color)
{
// Loop to (boneCount - 1) because the last one is a special "no bone" bone,
// needed to workaround buggy models without a -1, a cube is always drawn at the origin
for (int i = 0; i < skeleton.boneCount - 1; i++)
{
// Display the frame-pose skeleton
DrawCube(pose[i].translation, scale*0.05f, scale*0.05f, scale*0.05f, color);
if (skeleton.bones[i].parent >= 0)
{
DrawLine3D(pose[i].translation, pose[skeleton.bones[i].parent].translation, color);
}
}
}

View File

@ -1,192 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - loading vox
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 4.0, last time updated with raylib 4.0
*
* Example contributed by Johann Nadalutti (@procfxgen) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2021-2025 Johann Nadalutti (@procfxgen) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h" // Required for: MatrixTranslate()
#define MAX_VOX_FILES 4
#define RLIGHTS_IMPLEMENTATION
#include "rlights.h"
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
const char *voxFileNames[] = {
"resources/models/vox/chr_knight.vox",
"resources/models/vox/chr_sword.vox",
"resources/models/vox/monu9.vox",
"resources/models/vox/fez.vox"
};
InitWindow(screenWidth, screenHeight, "raylib [models] example - loading vox");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load MagicaVoxel files
Model models[MAX_VOX_FILES] = { 0 };
for (int i = 0; i < MAX_VOX_FILES; i++)
{
// Load VOX file and measure time
double t0 = GetTime()*1000.0;
models[i] = LoadModel(voxFileNames[i]);
double t1 = GetTime()*1000.0;
TraceLog(LOG_INFO, TextFormat("[%s] Model file loaded in %.3f ms", voxFileNames[i], t1 - t0));
// Compute model translation matrix to center model on draw position (0, 0 , 0)
BoundingBox bb = GetModelBoundingBox(models[i]);
Vector3 center = { 0 };
center.x = bb.min.x + (((bb.max.x - bb.min.x)/2));
center.z = bb.min.z + (((bb.max.z - bb.min.z)/2));
Matrix matTranslate = MatrixTranslate(-center.x, 0, -center.z);
models[i].transform = matTranslate;
}
int currentModel = 0;
Vector3 modelpos = { 0 };
Vector3 camerarot = { 0 };
// Load voxel shader
Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/voxel_lighting.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/voxel_lighting.fs", GLSL_VERSION));
// Get some required shader locations
shader.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
// NOTE: "matModel" location name is automatically assigned on shader loading,
// no need to get the location again if using that uniform name
//shader.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel");
// Ambient light level (some basic lighting)
int ambientLoc = GetShaderLocation(shader, "ambient");
SetShaderValue(shader, ambientLoc, (float[4]) { 0.1f, 0.1f, 0.1f, 1.0f }, SHADER_UNIFORM_VEC4);
// Assign out lighting shader to model
for (int i = 0; i < MAX_VOX_FILES; i++)
{
for (int j = 0; j < models[i].materialCount; j++) models[i].materials[j].shader = shader;
}
// Create lights
Light lights[MAX_LIGHTS] = { 0 };
lights[0] = CreateLight(LIGHT_POINT, (Vector3) { -20, 20, -20 }, Vector3Zero(), GRAY, shader);
lights[1] = CreateLight(LIGHT_POINT, (Vector3) { 20, -20, 20 }, Vector3Zero(), GRAY, shader);
lights[2] = CreateLight(LIGHT_POINT, (Vector3) { -20, 20, 20 }, Vector3Zero(), GRAY, shader);
lights[3] = CreateLight(LIGHT_POINT, (Vector3) { 20, -20, -20 }, Vector3Zero(), GRAY, shader);
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
//----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))
{
const Vector2 mouseDelta = GetMouseDelta();
camerarot.x = mouseDelta.x*0.05f;
camerarot.y = mouseDelta.y*0.05f;
}
else
{
camerarot.x = 0;
camerarot.y = 0;
}
// Update camere movement, custom controls
UpdateCameraPro(&camera,
(Vector3){ (IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - (IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f, // Move forward-backward
(IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f - (IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f, // Move right-left
0.0f }, // Move up-down
camerarot, // Camera rotation
GetMouseWheelMove()*-2.0f); // Move to target (zoom)
// Cycle between models on mouse click
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) currentModel = (currentModel + 1)%MAX_VOX_FILES;
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };
SetShaderValue(shader, shader.locs[SHADER_LOC_VECTOR_VIEW], cameraPos, SHADER_UNIFORM_VEC3);
// Update light values (actually, only enable/disable them)
for (int i = 0; i < MAX_LIGHTS; i++) UpdateLightValues(shader, lights[i]);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw 3D model
BeginMode3D(camera);
DrawModel(models[currentModel], modelpos, 1.0f, WHITE);
DrawGrid(10, 1.0);
// Draw spheres to show where the lights are
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lights[i].color);
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lights[i].color, 0.3f));
}
EndMode3D();
// Display info
DrawRectangle(10, 40, 340, 70, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(10, 40, 340, 70, Fade(DARKBLUE, 0.5f));
DrawText("- MOUSE LEFT BUTTON: CYCLE VOX MODELS", 20, 50, 10, BLUE);
DrawText("- MOUSE MIDDLE BUTTON: ZOOM OR ROTATE CAMERA", 20, 70, 10, BLUE);
DrawText("- UP-DOWN-LEFT-RIGHT KEYS: MOVE CAMERA", 20, 90, 10, BLUE);
DrawText(TextFormat("VOX model file: %s", GetFileName(voxFileNames[currentModel])), 10, 10, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// Unload models data (GPU VRAM)
for (int i = 0; i < MAX_VOX_FILES; i++) UnloadModel(models[i]);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,189 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - mesh generation
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.8, last time updated with raylib 4.0
*
* 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) 2017-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define NUM_MODELS 9 // Parametric 3d shapes to generate
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static Mesh GenMeshCustom(void); // Generate a simple triangle mesh from code
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh generation");
// We generate a checked image for texturing
Image checked = GenImageChecked(2, 2, 1, 1, RED, GREEN);
Texture2D texture = LoadTextureFromImage(checked);
UnloadImage(checked);
Model models[NUM_MODELS] = { 0 };
models[0] = LoadModelFromMesh(GenMeshPlane(2, 2, 4, 3));
models[1] = LoadModelFromMesh(GenMeshCube(2.0f, 1.0f, 2.0f));
models[2] = LoadModelFromMesh(GenMeshSphere(2, 32, 32));
models[3] = LoadModelFromMesh(GenMeshHemiSphere(2, 16, 16));
models[4] = LoadModelFromMesh(GenMeshCylinder(1, 2, 16));
models[5] = LoadModelFromMesh(GenMeshTorus(0.25f, 4.0f, 16, 32));
models[6] = LoadModelFromMesh(GenMeshKnot(1.0f, 2.0f, 16, 128));
models[7] = LoadModelFromMesh(GenMeshPoly(5, 2.0f));
models[8] = LoadModelFromMesh(GenMeshCustom());
// NOTE: Generated meshes could be exported using ExportMesh()
// Set checked texture as default diffuse component for all models material
for (int i = 0; i < NUM_MODELS; i++) models[i].materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;
// Define the camera to look into our 3d world
Camera camera = { { 5.0f, 5.0f, 5.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
// Model drawing position
Vector3 position = { 0.0f, 0.0f, 0.0f };
int currentModel = 0;
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{
currentModel = (currentModel + 1)%NUM_MODELS; // Cycle between the textures
}
if (IsKeyPressed(KEY_RIGHT))
{
currentModel++;
if (currentModel >= NUM_MODELS) currentModel = 0;
}
else if (IsKeyPressed(KEY_LEFT))
{
currentModel--;
if (currentModel < 0) currentModel = NUM_MODELS - 1;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(models[currentModel], position, 1.0f, WHITE);
DrawGrid(10, 1.0);
EndMode3D();
DrawRectangle(30, 400, 310, 30, Fade(SKYBLUE, 0.5f));
DrawRectangleLines(30, 400, 310, 30, Fade(DARKBLUE, 0.5f));
DrawText("MOUSE LEFT BUTTON to CYCLE PROCEDURAL MODELS", 40, 410, 10, BLUE);
switch (currentModel)
{
case 0: DrawText("PLANE", 680, 10, 20, DARKBLUE); break;
case 1: DrawText("CUBE", 680, 10, 20, DARKBLUE); break;
case 2: DrawText("SPHERE", 680, 10, 20, DARKBLUE); break;
case 3: DrawText("HEMISPHERE", 640, 10, 20, DARKBLUE); break;
case 4: DrawText("CYLINDER", 680, 10, 20, DARKBLUE); break;
case 5: DrawText("TORUS", 680, 10, 20, DARKBLUE); break;
case 6: DrawText("KNOT", 680, 10, 20, DARKBLUE); break;
case 7: DrawText("POLY", 680, 10, 20, DARKBLUE); break;
case 8: DrawText("Custom (triangle)", 580, 10, 20, DARKBLUE); break;
default: break;
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
// Unload models data (GPU VRAM)
for (int i = 0; i < NUM_MODELS; i++) UnloadModel(models[i]);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
// Generate a simple triangle mesh from code
static Mesh GenMeshCustom(void)
{
Mesh mesh = { 0 };
mesh.triangleCount = 1;
mesh.vertexCount = mesh.triangleCount*3;
mesh.vertices = (float *)MemAlloc(mesh.vertexCount*3*sizeof(float)); // 3 vertices, 3 coordinates each (x, y, z)
mesh.texcoords = (float *)MemAlloc(mesh.vertexCount*2*sizeof(float)); // 3 vertices, 2 coordinates each (x, y)
mesh.normals = (float *)MemAlloc(mesh.vertexCount*3*sizeof(float)); // 3 vertices, 3 coordinates each (x, y, z)
// Vertex at (0, 0, 0)
mesh.vertices[0] = 0;
mesh.vertices[1] = 0;
mesh.vertices[2] = 0;
mesh.normals[0] = 0;
mesh.normals[1] = 1;
mesh.normals[2] = 0;
mesh.texcoords[0] = 0;
mesh.texcoords[1] = 0;
// Vertex at (1, 0, 2)
mesh.vertices[3] = 1;
mesh.vertices[4] = 0;
mesh.vertices[5] = 2;
mesh.normals[3] = 0;
mesh.normals[4] = 1;
mesh.normals[5] = 0;
mesh.texcoords[2] = 0.5f;
mesh.texcoords[3] = 1.0f;
// Vertex at (2, 0, 0)
mesh.vertices[6] = 2;
mesh.vertices[7] = 0;
mesh.vertices[8] = 0;
mesh.normals[6] = 0;
mesh.normals[7] = 1;
mesh.normals[8] = 0;
mesh.texcoords[4] = 1;
mesh.texcoords[5] =0;
// Upload mesh data from CPU (RAM) to GPU (VRAM) memory
UploadMesh(&mesh, false);
return mesh;
}

View File

@ -1,249 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - mesh picking
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 1.7, last time updated with raylib 4.0
*
* Example contributed by Joel Davis (@joeld42) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2017-2025 Joel Davis (@joeld42) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#undef FLT_MAX
#define FLT_MAX 340282346638528859811704183484516925440.0f // Maximum value of a float, from bit pattern 01111111011111111111111111111111
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh picking");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 20.0f, 20.0f, 20.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 8.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.6f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Ray ray = { 0 }; // Picking ray
Model tower = LoadModel("resources/models/obj/turret.obj"); // Load OBJ model
Texture2D texture = LoadTexture("resources/models/obj/turret_diffuse.png"); // Load model texture
tower.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set model diffuse texture
Vector3 towerPos = { 0.0f, 0.0f, 0.0f }; // Set model position
BoundingBox towerBBox = GetMeshBoundingBox(tower.meshes[0]); // Get mesh bounding box
// Ground quad
Vector3 g0 = (Vector3){ -50.0f, 0.0f, -50.0f };
Vector3 g1 = (Vector3){ -50.0f, 0.0f, 50.0f };
Vector3 g2 = (Vector3){ 50.0f, 0.0f, 50.0f };
Vector3 g3 = (Vector3){ 50.0f, 0.0f, -50.0f };
// Test triangle
Vector3 ta = (Vector3){ -25.0f, 0.5f, 0.0f };
Vector3 tb = (Vector3){ -4.0f, 2.5f, 1.0f };
Vector3 tc = (Vector3){ -8.0f, 6.5f, 0.0f };
Vector3 bary = { 0.0f, 0.0f, 0.0f };
// Test sphere
Vector3 sp = (Vector3){ -30.0f, 5.0f, 5.0f };
float sr = 4.0f;
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
//----------------------------------------------------------------------------------
if (IsCursorHidden()) UpdateCamera(&camera, CAMERA_FIRST_PERSON); // Update camera
// Toggle camera controls
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
{
if (IsCursorHidden()) EnableCursor();
else DisableCursor();
}
// Display information about closest hit
RayCollision collision = { 0 };
const char *hitObjectName = "None";
collision.distance = FLT_MAX;
collision.hit = false;
Color cursorColor = WHITE;
// Get ray and test against objects
ray = GetScreenToWorldRay(GetMousePosition(), camera);
// Check ray collision against ground quad
RayCollision groundHitInfo = GetRayCollisionQuad(ray, g0, g1, g2, g3);
if ((groundHitInfo.hit) && (groundHitInfo.distance < collision.distance))
{
collision = groundHitInfo;
cursorColor = GREEN;
hitObjectName = "Ground";
}
// Check ray collision against test triangle
RayCollision triHitInfo = GetRayCollisionTriangle(ray, ta, tb, tc);
if ((triHitInfo.hit) && (triHitInfo.distance < collision.distance))
{
collision = triHitInfo;
cursorColor = PURPLE;
hitObjectName = "Triangle";
bary = Vector3Barycenter(collision.point, ta, tb, tc);
}
// Check ray collision against test sphere
RayCollision sphereHitInfo = GetRayCollisionSphere(ray, sp, sr);
if ((sphereHitInfo.hit) && (sphereHitInfo.distance < collision.distance))
{
collision = sphereHitInfo;
cursorColor = ORANGE;
hitObjectName = "Sphere";
}
// Check ray collision against bounding box first, before trying the full ray-mesh test
RayCollision boxHitInfo = GetRayCollisionBox(ray, towerBBox);
if ((boxHitInfo.hit) && (boxHitInfo.distance < collision.distance))
{
collision = boxHitInfo;
cursorColor = ORANGE;
hitObjectName = "Box";
// Check ray collision against model meshes
RayCollision meshHitInfo = { 0 };
for (int m = 0; m < tower.meshCount; m++)
{
// NOTE: We consider the model.transform for the collision check but
// it can be checked against any transform Matrix, used when checking against same
// model drawn multiple times with multiple transforms
meshHitInfo = GetRayCollisionMesh(ray, tower.meshes[m], tower.transform);
if (meshHitInfo.hit)
{
// Save the closest hit mesh
if ((!collision.hit) || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo;
break; // Stop once one mesh collision is detected, the colliding mesh is m
}
}
if (meshHitInfo.hit)
{
collision = meshHitInfo;
cursorColor = ORANGE;
hitObjectName = "Mesh";
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw the tower
// WARNING: If scale is different than 1.0f,
// not considered by GetRayCollisionModel()
DrawModel(tower, towerPos, 1.0f, WHITE);
// Draw the test triangle
DrawLine3D(ta, tb, PURPLE);
DrawLine3D(tb, tc, PURPLE);
DrawLine3D(tc, ta, PURPLE);
// Draw the test sphere
DrawSphereWires(sp, sr, 8, 8, PURPLE);
// Draw the mesh bbox if we hit it
if (boxHitInfo.hit) DrawBoundingBox(towerBBox, LIME);
// If we hit something, draw the cursor at the hit point
if (collision.hit)
{
DrawCube(collision.point, 0.3f, 0.3f, 0.3f, cursorColor);
DrawCubeWires(collision.point, 0.3f, 0.3f, 0.3f, RED);
Vector3 normalEnd;
normalEnd.x = collision.point.x + collision.normal.x;
normalEnd.y = collision.point.y + collision.normal.y;
normalEnd.z = collision.point.z + collision.normal.z;
DrawLine3D(collision.point, normalEnd, RED);
}
DrawRay(ray, MAROON);
DrawGrid(10, 10.0f);
EndMode3D();
// Draw some debug GUI text
DrawText(TextFormat("Hit Object: %s", hitObjectName), 10, 50, 10, BLACK);
if (collision.hit)
{
int ypos = 70;
DrawText(TextFormat("Distance: %3.2f", collision.distance), 10, ypos, 10, BLACK);
DrawText(TextFormat("Hit Pos: %3.2f %3.2f %3.2f",
collision.point.x,
collision.point.y,
collision.point.z), 10, ypos + 15, 10, BLACK);
DrawText(TextFormat("Hit Norm: %3.2f %3.2f %3.2f",
collision.normal.x,
collision.normal.y,
collision.normal.z), 10, ypos + 30, 10, BLACK);
if (triHitInfo.hit && TextIsEqual(hitObjectName, "Triangle"))
DrawText(TextFormat("Barycenter: %3.2f %3.2f %3.2f", bary.x, bary.y, bary.z), 10, ypos + 45, 10, BLACK);
}
DrawText("Right click mouse to toggle camera controls", 10, 430, 10, GRAY);
DrawText("(c) Turret 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(tower); // Unload model
UnloadTexture(texture); // Unload texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,104 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - orthographic projection
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 2.0, last time updated with raylib 3.7
*
* Example contributed by Max Danielsson (@autious) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2018-2025 Max Danielsson (@autious) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define FOVY_PERSPECTIVE 45.0f
#define WIDTH_ORTHOGRAPHIC 10.0f
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - orthographic projection");
// Define the camera to look into our 3d world
Camera camera = { { 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, FOVY_PERSPECTIVE, 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
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_SPACE))
{
if (camera.projection == CAMERA_PERSPECTIVE)
{
camera.fovy = WIDTH_ORTHOGRAPHIC;
camera.projection = CAMERA_ORTHOGRAPHIC;
}
else
{
camera.fovy = FOVY_PERSPECTIVE;
camera.projection = CAMERA_PERSPECTIVE;
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawCube((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, RED);
DrawCubeWires((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, GOLD);
DrawCubeWires((Vector3){-4.0f, 0.0f, -2.0f}, 3.0f, 6.0f, 2.0f, MAROON);
DrawSphere((Vector3){-1.0f, 0.0f, -2.0f}, 1.0f, GREEN);
DrawSphereWires((Vector3){1.0f, 0.0f, 2.0f}, 2.0f, 16, 16, LIME);
DrawCylinder((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, SKYBLUE);
DrawCylinderWires((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, DARKBLUE);
DrawCylinderWires((Vector3){4.5f, -1.0f, 2.0f}, 1.0f, 1.0f, 2.0f, 6, BROWN);
DrawCylinder((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, GOLD);
DrawCylinderWires((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, PINK);
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D();
DrawText("Press Spacebar to switch camera type", 10, GetScreenHeight() - 30, 20, DARKGRAY);
if (camera.projection == CAMERA_ORTHOGRAPHIC) DrawText("ORTHOGRAPHIC", 10, 40, 20, BLACK);
else if (camera.projection == CAMERA_PERSPECTIVE) DrawText("PERSPECTIVE", 10, 40, 20, BLACK);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,215 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - point rendering
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 5.0, last time updated with raylib 5.0
*
* Example contributed by Reese Gallagher (@satchelfrost) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2024-2025 Reese Gallagher (@satchelfrost)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
#include <stdlib.h> // Required for: rand()
#include <math.h> // Required for: cosf(), sinf()
#define MAX_POINTS 10000000 // 10 million
#define MIN_POINTS 1000 // 1 thousand
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static Mesh GenMeshPoints(int numPoints); // Generate mesh using points
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - point rendering");
Camera camera = {
.position = { 3.0f, 3.0f, 3.0f },
.target = { 0.0f, 0.0f, 0.0f },
.up = { 0.0f, 1.0f, 0.0f },
.fovy = 45.0f,
.projection = CAMERA_PERSPECTIVE
};
Vector3 position = { 0.0f, 0.0f, 0.0f };
bool useDrawModelPoints = true;
bool numPointsChanged = false;
int numPoints = 1000;
Mesh mesh = GenMeshPoints(numPoints);
Model model = LoadModelFromMesh(mesh);
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose())
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
if (IsKeyPressed(KEY_SPACE)) useDrawModelPoints = !useDrawModelPoints;
if (IsKeyPressed(KEY_UP))
{
numPoints = (numPoints*10 > MAX_POINTS)? MAX_POINTS : numPoints*10;
numPointsChanged = true;
}
if (IsKeyPressed(KEY_DOWN))
{
numPoints = (numPoints/10 < MIN_POINTS)? MIN_POINTS : numPoints/10;
numPointsChanged = true;
}
// Upload a different point cloud size
if (numPointsChanged)
{
UnloadModel(model);
mesh = GenMeshPoints(numPoints);
model = LoadModelFromMesh(mesh);
numPointsChanged = false;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(BLACK);
BeginMode3D(camera);
// The new method only uploads the points once to the GPU
if (useDrawModelPoints) DrawModelPoints(model, position, 1.0f, WHITE);
else
{
// The old method must continually draw the "points" (lines)
for (int i = 0; i < numPoints; i++)
{
Vector3 pos = {
.x = mesh.vertices[i*3 + 0],
.y = mesh.vertices[i*3 + 1],
.z = mesh.vertices[i*3 + 2],
};
Color color = {
.r = mesh.colors[i*4 + 0],
.g = mesh.colors[i*4 + 1],
.b = mesh.colors[i*4 + 2],
.a = mesh.colors[i*4 + 3],
};
DrawPoint3D(pos, color);
}
}
// Draw a unit sphere for reference
DrawSphereWires(position, 1.0f, 10, 10, YELLOW);
EndMode3D();
// Draw UI text
DrawText(TextFormat("Point Count: %d", numPoints), 10, screenHeight - 50, 40, WHITE);
DrawText("UP - Increase points", 10, 40, 20, WHITE);
DrawText("DOWN - Decrease points", 10, 70, 20, WHITE);
DrawText("SPACE - Drawing function", 10, 100, 20, WHITE);
if (useDrawModelPoints) DrawText("Using: DrawModelPoints()", 10, 130, 20, GREEN);
else DrawText("Using: DrawPoint3D()", 10, 130, 20, RED);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model);
CloseWindow();
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
// Generate a spherical point cloud
static Mesh GenMeshPoints(int numPoints)
{
Mesh mesh = {
.triangleCount = 1,
.vertexCount = numPoints,
.vertices = (float *)MemAlloc(numPoints*3*sizeof(float)),
.colors = (unsigned char*)MemAlloc(numPoints*4*sizeof(unsigned char)),
};
// REF: https://en.wikipedia.org/wiki/Spherical_coordinate_system
for (int i = 0; i < numPoints; i++)
{
float theta = ((float)PI*rand())/((float)RAND_MAX);
float phi = (2.0f*PI*rand())/((float)RAND_MAX);
float r = (10.0f*rand())/((float)RAND_MAX);
mesh.vertices[i*3 + 0] = r*sinf(theta)*cosf(phi);
mesh.vertices[i*3 + 1] = r*sinf(theta)*sinf(phi);
mesh.vertices[i*3 + 2] = r*cosf(theta);
Color color = ColorFromHSV(r*360.0f, 1.0f, 1.0f);
mesh.colors[i*4 + 0] = color.r;
mesh.colors[i*4 + 1] = color.g;
mesh.colors[i*4 + 2] = color.b;
mesh.colors[i*4 + 3] = color.a;
}
// Upload mesh data from CPU (RAM) to GPU (VRAM) memory
UploadMesh(&mesh, false);
return mesh;
}
// Draw a model points
// WARNING: OpenGL ES 2.0 does not support point mode drawing
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
{
rlEnablePointMode();
rlDisableBackfaceCulling();
DrawModel(model, position, scale, tint);
rlEnableBackfaceCulling();
rlDisablePointMode();
}
// Draw a model points
// WARNING: OpenGL ES 2.0 does not support point mode drawing
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
{
rlEnablePointMode();
rlDisableBackfaceCulling();
DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
rlEnableBackfaceCulling();
rlDisablePointMode();
}

View File

@ -1,171 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - rlgl solar system
*
* Example complexity rating: [★★★★] 4/4
*
* NOTE: This example uses [rlgl] module functionality (pseudo-OpenGL 1.1 style coding)
*
* Example originally created with raylib 2.5, last time updated with raylib 4.0
*
* 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) 2018-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
#include <math.h> // Required for: cosf(), sinf()
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
void DrawSphereBasic(Color color); // Draw sphere without any matrix transformation
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
const float sunRadius = 4.0f;
const float earthRadius = 0.6f;
const float earthOrbitRadius = 8.0f;
const float moonRadius = 0.16f;
const float moonOrbitRadius = 1.5f;
InitWindow(screenWidth, screenHeight, "raylib [models] example - rlgl solar system");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 16.0f, 16.0f, 16.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
float rotationSpeed = 0.2f; // General system rotation speed
float earthRotation = 0.0f; // Rotation of earth around itself (days) in degrees
float earthOrbitRotation = 0.0f; // Rotation of earth around the Sun (years) in degrees
float moonRotation = 0.0f; // Rotation of moon around itself
float moonOrbitRotation = 0.0f; // Rotation of moon around earth in degrees
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
//----------------------------------------------------------------------------------
earthRotation += (5.0f*rotationSpeed);
earthOrbitRotation += (365/360.0f*(5.0f*rotationSpeed)*rotationSpeed);
moonRotation += (2.0f*rotationSpeed);
moonOrbitRotation += (8.0f*rotationSpeed);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
rlPushMatrix();
rlScalef(sunRadius, sunRadius, sunRadius); // Scale Sun
DrawSphereBasic(GOLD); // Draw the Sun
rlPopMatrix();
rlPushMatrix();
rlRotatef(earthOrbitRotation, 0.0f, 1.0f, 0.0f); // Rotation for Earth orbit around Sun
rlTranslatef(earthOrbitRadius, 0.0f, 0.0f); // Translation for Earth orbit
rlPushMatrix();
rlRotatef(earthRotation, 0.25, 1.0, 0.0); // Rotation for Earth itself
rlScalef(earthRadius, earthRadius, earthRadius);// Scale Earth
DrawSphereBasic(BLUE); // Draw the Earth
rlPopMatrix();
rlRotatef(moonOrbitRotation, 0.0f, 1.0f, 0.0f); // Rotation for Moon orbit around Earth
rlTranslatef(moonOrbitRadius, 0.0f, 0.0f); // Translation for Moon orbit
rlRotatef(moonRotation, 0.0f, 1.0f, 0.0f); // Rotation for Moon itself
rlScalef(moonRadius, moonRadius, moonRadius); // Scale Moon
DrawSphereBasic(LIGHTGRAY); // Draw the Moon
rlPopMatrix();
// Some reference elements (not affected by previous matrix transformations)
DrawCircle3D((Vector3){ 0.0f, 0.0f, 0.0f }, earthOrbitRadius, (Vector3){ 1, 0, 0 }, 90.0f, Fade(RED, 0.5f));
DrawGrid(20, 1.0f);
EndMode3D();
DrawText("EARTH ORBITING AROUND THE SUN!", 400, 10, 20, MAROON);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//--------------------------------------------------------------------------------------------
// Module Functions Definition
//--------------------------------------------------------------------------------------------
// Draw sphere without any matrix transformation
// NOTE: Sphere is drawn in world position ( 0, 0, 0 ) with radius 1.0f
void DrawSphereBasic(Color color)
{
int rings = 16;
int slices = 16;
// Make sure there is enough space in the internal render batch
// buffer to store all required vertex, batch is reseted if required
rlCheckRenderBatchLimit((rings + 2)*slices*6);
rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i < (rings + 2); i++)
{
for (int j = 0; j < slices; j++)
{
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*sinf(DEG2RAD*(j*360.0f/slices)),
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*i)),
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*cosf(DEG2RAD*(j*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360.0f/slices)),
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*sinf(DEG2RAD*(j*360.0f/slices)),
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*i)),
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*cosf(DEG2RAD*(j*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i))),
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
}
}
rlEnd();
}

View File

@ -1,94 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - rotating cube
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Jopestpe (@jopestpe)
*
* 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) 2025 Jopestpe (@jopestpe)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - rotating cube");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 0.0f, 3.0f, 3.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;
// Load image to create texture for the cube
Model model = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
Image img = LoadImage("resources/cubicmap_atlas.png");
Image crop = ImageFromImage(img, (Rectangle){0, img.height/2.0f, img.width/2.0f, img.height/2.0f});
Texture2D texture = LoadTextureFromImage(crop);
UnloadImage(img);
UnloadImage(crop);
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;
float rotation = 0.0f;
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
//----------------------------------------------------------------------------------
rotation += 1.0f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw model defining: position, size, rotation-axis, rotation (degrees), size, and tint-color
DrawModelEx(model, (Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.5f, 1.0f, 0.0f },
rotation, (Vector3){ 1.0f, 1.0f, 1.0f }, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,282 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - skybox rendering
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.8, last time updated with raylib 4.0
*
* 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) 2017-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
#include "raymath.h" // Required for: MatrixPerspective(), MatrixLookAt()
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
// Generate cubemap (6 faces) from equirectangular (panorama) texture
static TextureCubemap GenTextureCubemap(Shader shader, Texture2D panorama, int size, int format);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - skybox rendering");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 1.0f, 1.0f, 1.0f }; // Camera position
camera.target = (Vector3){ 4.0f, 1.0f, 4.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Load skybox model
Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);
Model skybox = LoadModelFromMesh(cube);
// Set this to true to use an HDR Texture
// NOTE: raylib must be built with HDR Support for this to work: SUPPORT_FILEFORMAT_HDR
bool useHDR = false;
// Load skybox shader and set required locations
// NOTE: Some locations are automatically set at shader loading
skybox.materials[0].shader = LoadShader(TextFormat("resources/shaders/glsl%i/skybox.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/skybox.fs", GLSL_VERSION));
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "environmentMap"), (int[1]){ MATERIAL_MAP_CUBEMAP }, SHADER_UNIFORM_INT);
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "doGamma"), (int[1]){ useHDR? 1 : 0 }, SHADER_UNIFORM_INT);
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "vflipped"), (int[1]){ useHDR? 1 : 0 }, SHADER_UNIFORM_INT);
// Load cubemap shader and setup required shader locations
Shader shdrCubemap = LoadShader(TextFormat("resources/shaders/glsl%i/cubemap.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/cubemap.fs", GLSL_VERSION));
SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, SHADER_UNIFORM_INT);
char skyboxFileName[256] = { 0 };
if (useHDR)
{
TextCopy(skyboxFileName, "resources/dresden_square_2k.hdr");
// Load HDR panorama (sphere) texture
Texture2D panorama = LoadTexture(skyboxFileName);
// Generate cubemap (texture with 6 quads-cube-mapping) from panorama HDR texture
// NOTE 1: New texture is generated rendering to texture, shader calculates the sphere->cube coordinates mapping
// NOTE 2: It seems on some Android devices WebGL, fbo does not properly support a FLOAT-based attachment,
// despite texture can be successfully created.. so using PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 instead of PIXELFORMAT_UNCOMPRESSED_R32G32B32A32
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, panorama, 1024, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
UnloadTexture(panorama); // Texture not required anymore, cubemap already generated
}
else
{
// TODO: WARNING: On PLATFORM_WEB it requires a big amount of memory to process input image
// and generate the required cubemap image to be passed to rlLoadTextureCubemap()
Image image = LoadImage("resources/skybox.png");
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(image, CUBEMAP_LAYOUT_AUTO_DETECT);
UnloadImage(image);
}
DisableCursor(); // Limit cursor to relative movement inside the window
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_FIRST_PERSON);
// Load new cubemap texture on drag&drop
if (IsFileDropped())
{
FilePathList droppedFiles = LoadDroppedFiles();
if (droppedFiles.count == 1) // Only support one file dropped
{
if (IsFileExtension(droppedFiles.paths[0], ".png;.jpg;.hdr;.bmp;.tga"))
{
// Unload current cubemap texture to load new one
UnloadTexture(skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture);
if (useHDR)
{
// Load HDR panorama (sphere) texture
Texture2D panorama = LoadTexture(droppedFiles.paths[0]);
// Generate cubemap from panorama texture
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, panorama, 1024, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
UnloadTexture(panorama); // Texture not required anymore, cubemap already generated
}
else
{
Image image = LoadImage(droppedFiles.paths[0]);
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(image, CUBEMAP_LAYOUT_AUTO_DETECT);
UnloadImage(image);
}
TextCopy(skyboxFileName, droppedFiles.paths[0]);
}
}
UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// We are inside the cube, we need to disable backface culling!
rlDisableBackfaceCulling();
rlDisableDepthMask();
DrawModel(skybox, (Vector3){0, 0, 0}, 1.0f, WHITE);
rlEnableBackfaceCulling();
rlEnableDepthMask();
DrawGrid(10, 1.0f);
EndMode3D();
if (useHDR) DrawText(TextFormat("Panorama image from hdrihaven.com: %s", GetFileName(skyboxFileName)), 10, GetScreenHeight() - 20, 10, BLACK);
else DrawText(TextFormat(": %s", GetFileName(skyboxFileName)), 10, GetScreenHeight() - 20, 10, BLACK);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(skybox.materials[0].shader);
UnloadTexture(skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture);
UnloadModel(skybox); // Unload skybox model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
// Generate cubemap texture from HDR texture
static TextureCubemap GenTextureCubemap(Shader shader, Texture2D panorama, int size, int format)
{
TextureCubemap cubemap = { 0 };
rlDisableBackfaceCulling(); // Disable backface culling to render inside the cube
// STEP 1: Setup framebuffer
//------------------------------------------------------------------------------------------
unsigned int rbo = rlLoadTextureDepth(size, size, true);
cubemap.id = rlLoadTextureCubemap(0, size, format, 1);
unsigned int fbo = rlLoadFramebuffer();
rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0);
rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X, 0);
// Check if framebuffer is complete with attachments (valid)
if (rlFramebufferComplete(fbo)) TraceLog(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", fbo);
//------------------------------------------------------------------------------------------
// STEP 2: Draw to framebuffer
//------------------------------------------------------------------------------------------
// NOTE: Shader is used to convert HDR equirectangular environment map to cubemap equivalent (6 faces)
rlEnableShader(shader.id);
// Define projection matrix and send it to shader
Matrix matFboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, rlGetCullDistanceNear(), rlGetCullDistanceFar());
rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], matFboProjection);
// Define view matrix for every side of the cubemap
Matrix fboViews[6] = {
MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }),
MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }),
MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }),
MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }),
MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }),
MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f })
};
rlViewport(0, 0, size, size); // Set viewport to current fbo dimensions
// Activate and enable texture for drawing to cubemap faces
rlActiveTextureSlot(0);
rlEnableTexture(panorama.id);
for (int i = 0; i < 6; i++)
{
// Set the view matrix for the current cube face
rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], fboViews[i]);
// Select the current cubemap face attachment for the fbo
// WARNING: This function by default enables->attach->disables fbo!!!
rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X + i, 0);
rlEnableFramebuffer(fbo);
// Load and draw a cube, it uses the current enabled texture
rlClearScreenBuffers();
rlLoadDrawCube();
// ALTERNATIVE: Try to use internal batch system to draw the cube instead of rlLoadDrawCube
// for some reason this method does not work, maybe due to cube triangles definition? normals pointing out?
// TODO: Investigate this issue...
//rlSetTexture(panorama.id); // WARNING: It must be called after enabling current framebuffer if using internal batch system!
//rlClearScreenBuffers();
//DrawCubeV(Vector3Zero(), Vector3One(), WHITE);
//rlDrawRenderBatchActive();
}
//------------------------------------------------------------------------------------------
// STEP 3: Unload framebuffer and reset state
//------------------------------------------------------------------------------------------
rlDisableShader(); // Unbind shader
rlDisableTexture(); // Unbind texture
rlDisableFramebuffer(); // Unbind framebuffer
rlUnloadFramebuffer(fbo); // Unload framebuffer (and automatically attached depth texture/renderbuffer)
// Reset viewport dimensions to default
rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight());
rlEnableBackfaceCulling();
//------------------------------------------------------------------------------------------
cubemap.width = size;
cubemap.height = size;
cubemap.mipmaps = 1;
cubemap.format = format;
return cubemap;
}

View File

@ -1,128 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - tesseract view
*
* NOTE: This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?)
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Timothy van der Valk (@arceryz) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2024-2025 Timothy van der Valk (@arceryz) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - tesseract view");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 4.0f, 4.0f, 4.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 0.0f, 1.0f }; // Camera up vector (rotation towards target)
camera.fovy = 50.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera mode type
// Find the coordinates by setting XYZW to +-1
Vector4 tesseract[16] = {
{ 1, 1, 1, 1 }, { 1, 1, 1, -1 },
{ 1, 1, -1, 1 }, { 1, 1, -1, -1 },
{ 1, -1, 1, 1 }, { 1, -1, 1, -1 },
{ 1, -1, -1, 1 }, { 1, -1, -1, -1 },
{ -1, 1, 1, 1 }, { -1, 1, 1, -1 },
{ -1, 1, -1, 1 }, { -1, 1, -1, -1 },
{ -1, -1, 1, 1 }, { -1, -1, 1, -1 },
{ -1, -1, -1, 1 }, { -1, -1, -1, -1 },
};
float rotation = 0.0f;
Vector3 transformed[16] = { 0 };
float wValues[16] = { 0 };
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
//----------------------------------------------------------------------------------
rotation = DEG2RAD*45.0f*(float)GetTime();
for (int i = 0; i < 16; i++)
{
Vector4 p = tesseract[i];
// Rotate the XW part of the vector
Vector2 rotXW = Vector2Rotate((Vector2){ p.x, p.w }, rotation);
p.x = rotXW.x;
p.w = rotXW.y;
// Projection from XYZW to XYZ from perspective point (0, 0, 0, 3)
// NOTE: Trace a ray from (0, 0, 0, 3) > p and continue until W = 0
float c = 3.0f/(3.0f - p.w);
p.x = c*p.x;
p.y = c*p.y;
p.z = c*p.z;
// Split XYZ coordinate and W values later for drawing
transformed[i] = (Vector3){ p.x, p.y, p.z };
wValues[i] = p.w;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
for (int i = 0; i < 16; i++)
{
// Draw spheres to indicate the W value
DrawSphere(transformed[i], fabsf(wValues[i]*0.1f), RED);
for (int j = 0; j < 16; j++)
{
// Two lines are connected if they differ by 1 coordinate
// This way we dont have to keep an edge list
Vector4 v1 = tesseract[i];
Vector4 v2 = tesseract[j];
int diff = (int)(v1.x == v2.x) + (int)(v1.y == v2.y) + (int)(v1.z == v2.z) + (int)(v1.w == v2.w);
// Draw only differing by 1 coordinate and the lower index only (duplicate lines)
if (diff == 3 && i < j) DrawLine3D(transformed[i], transformed[j], MAROON);
}
}
EndMode3D();
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,247 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - textured cube
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 4.5, last time updated with raylib 4.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) 2022-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h" // Required to define vertex data (immediate-mode style)
//------------------------------------------------------------------------------------
// Custom Functions Declaration
//------------------------------------------------------------------------------------
void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color); // Draw cube textured
void DrawCubeTextureRec(Texture2D texture, Rectangle source, Vector3 position, float width, float height, float length, Color color); // Draw cube with a region of a texture
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - textured cube");
// 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;
// Load texture to be applied to the cubes sides
Texture2D texture = LoadTexture("resources/cubicmap_atlas.png");
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
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw cube with an applied texture
DrawCubeTexture(texture, (Vector3){ -2.0f, 2.0f, 0.0f }, 2.0f, 4.0f, 2.0f, WHITE);
// Draw cube with an applied texture, but only a defined rectangle piece of the texture
DrawCubeTextureRec(texture, (Rectangle){ 0.0f, texture.height/2.0f, texture.width/2.0f, texture.height/2.0f },
(Vector3){ 2.0f, 1.0f, 0.0f }, 2.0f, 2.0f, 2.0f, WHITE);
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Custom Functions Definition
//------------------------------------------------------------------------------------
// Draw cube textured
// NOTE: Cube position is the center position
void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color)
{
float x = position.x;
float y = position.y;
float z = position.z;
// Set desired texture to be enabled while drawing following vertex data
rlSetTexture(texture.id);
// Vertex data transformation can be defined with the commented lines,
// but in this example we calculate the transformed vertex data directly when calling rlVertex3f()
//rlPushMatrix();
// NOTE: Transformation is applied in inverse order (scale -> rotate -> translate)
//rlTranslatef(2.0f, 0.0f, 0.0f);
//rlRotatef(45, 0, 1, 0);
//rlScalef(2.0f, 2.0f, 2.0f);
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
// Front Face
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
// Back Face
rlNormal3f(0.0f, 0.0f, - 1.0f); // Normal Pointing Away From Viewer
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
// Top Face
rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
// Bottom Face
rlNormal3f(0.0f, - 1.0f, 0.0f); // Normal Pointing Down
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
// Right face
rlNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
// Left Face
rlNormal3f( - 1.0f, 0.0f, 0.0f); // Normal Pointing Left
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlEnd();
//rlPopMatrix();
rlSetTexture(0);
}
// Draw cube with texture piece applied to all faces
void DrawCubeTextureRec(Texture2D texture, Rectangle source, Vector3 position, float width, float height, float length, Color color)
{
float x = position.x;
float y = position.y;
float z = position.z;
float texWidth = (float)texture.width;
float texHeight = (float)texture.height;
// Set desired texture to be enabled while drawing following vertex data
rlSetTexture(texture.id);
// We calculate the normalized texture coordinates for the desired texture-source-rectangle
// It means converting from (tex.width, tex.height) coordinates to [0.0f, 1.0f] equivalent
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
// Front face
rlNormal3f(0.0f, 0.0f, 1.0f);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z + length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z + length/2);
// Back face
rlNormal3f(0.0f, 0.0f, - 1.0f);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z - length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z - length/2);
// Top face
rlNormal3f(0.0f, 1.0f, 0.0f);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y + height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y + height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z - length/2);
// Bottom face
rlNormal3f(0.0f, - 1.0f, 0.0f);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y - height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y - height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z + length/2);
// Right face
rlNormal3f(1.0f, 0.0f, 0.0f);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z - length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z - length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x + width/2, y + height/2, z + length/2);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x + width/2, y - height/2, z + length/2);
// Left face
rlNormal3f( - 1.0f, 0.0f, 0.0f);
rlTexCoord2f(source.x/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z - length/2);
rlTexCoord2f((source.x + source.width)/texWidth, (source.y + source.height)/texHeight);
rlVertex3f(x - width/2, y - height/2, z + length/2);
rlTexCoord2f((source.x + source.width)/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z + length/2);
rlTexCoord2f(source.x/texWidth, source.y/texHeight);
rlVertex3f(x - width/2, y + height/2, z - length/2);
rlEnd();
rlSetTexture(0);
}

View File

@ -1,121 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - waving cubes
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 2.5, last time updated with raylib 3.7
*
* Example contributed by Codecat (@codecat) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2019-2025 Codecat (@codecat) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h> // Required for: sinf()
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - waving cubes");
// Initialize the camera
Camera3D camera = { 0 };
camera.position = (Vector3){ 30.0f, 20.0f, 30.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 70.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
// Specify the amount of blocks in each direction
const int numBlocks = 15;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
double time = GetTime();
// Calculate time scale for cube position and size
float scale = (2.0f + (float)sin(time))*0.7f;
// Move camera around the scene
double cameraTime = time*0.3;
camera.position.x = (float)cos(cameraTime)*40.0f;
camera.position.z = (float)sin(cameraTime)*40.0f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawGrid(10, 5.0f);
for (int x = 0; x < numBlocks; x++)
{
for (int y = 0; y < numBlocks; y++)
{
for (int z = 0; z < numBlocks; z++)
{
// Scale of the blocks depends on x/y/z positions
float blockScale = (x + y + z)/30.0f;
// Scatter makes the waving effect by adding blockScale over time
float scatter = sinf(blockScale*20.0f + (float)(time*4.0f));
// Calculate the cube position
Vector3 cubePos = {
(float)(x - (float)numBlocks/2)*(scale*3.0f) + scatter,
(float)(y - (float)numBlocks/2)*(scale*2.0f) + scatter,
(float)(z - (float)numBlocks/2)*(scale*3.0f) + scatter
};
// Pick a color with a hue depending on cube position for the rainbow color effect
// NOTE: This function is quite costly to be done per cube and frame,
// pre-catching the results into a separate array could improve performance
Color cubeColor = ColorFromHSV((float)(((x + y + z)*18)%360), 0.75f, 0.9f);
// Calculate cube size
float cubeSize = (2.4f - scale)*blockScale;
// And finally, draw the cube!
DrawCube(cubePos, cubeSize, cubeSize, cubeSize, cubeColor);
}
}
}
EndMode3D();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,128 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - yaw pitch roll
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.8, last time updated with raylib 4.0
*
* Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5)
*
* 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) 2017-2025 Berni (@Berni8k) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h" // Required for: MatrixRotateXYZ()
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
//SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI);
InitWindow(screenWidth, screenHeight, "raylib [models] example - yaw pitch roll");
Camera camera = { 0 };
camera.position = (Vector3){ 0.0f, 50.0f, -120.0f };// Camera position perspective
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 30.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera type
Model model = LoadModel("resources/models/obj/plane.obj"); // Load model
Texture2D texture = LoadTexture("resources/models/obj/plane_diffuse.png"); // Load model texture
SetTextureWrap(texture, TEXTURE_WRAP_REPEAT); // Force Repeat to avoid issue on Web version
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
float pitch = 0.0f;
float roll = 0.0f;
float yaw = 0.0f;
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
//----------------------------------------------------------------------------------
// Plane pitch (x-axis) controls
if (IsKeyDown(KEY_DOWN)) pitch += 0.6f;
else if (IsKeyDown(KEY_UP)) pitch -= 0.6f;
else
{
if (pitch > 0.3f) pitch -= 0.3f;
else if (pitch < -0.3f) pitch += 0.3f;
}
// Plane yaw (y-axis) controls
if (IsKeyDown(KEY_S)) yaw -= 1.0f;
else if (IsKeyDown(KEY_A)) yaw += 1.0f;
else
{
if (yaw > 0.0f) yaw -= 0.5f;
else if (yaw < 0.0f) yaw += 0.5f;
}
// Plane roll (z-axis) controls
if (IsKeyDown(KEY_LEFT)) roll -= 1.0f;
else if (IsKeyDown(KEY_RIGHT)) roll += 1.0f;
else
{
if (roll > 0.0f) roll -= 0.5f;
else if (roll < 0.0f) roll += 0.5f;
}
// Tranformation matrix for rotations
model.transform = MatrixRotateXYZ((Vector3){ DEG2RAD*pitch, DEG2RAD*yaw, DEG2RAD*roll });
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw 3D model (recomended to draw 3D always before 2D)
BeginMode3D(camera);
DrawModel(model, (Vector3){ 0.0f, -8.0f, 0.0f }, 1.0f, WHITE); // Draw 3d model with texture
DrawGrid(10, 10.0f);
EndMode3D();
// Draw controls info
DrawRectangle(30, 370, 260, 70, Fade(GREEN, 0.5f));
DrawRectangleLines(30, 370, 260, 70, Fade(DARKGREEN, 0.5f));
DrawText("Pitch controlled with: KEY_UP / KEY_DOWN", 40, 380, 10, DARKGRAY);
DrawText("Roll controlled with: KEY_LEFT / KEY_RIGHT", 40, 400, 10, DARKGRAY);
DrawText("Yaw controlled with: KEY_A / KEY_S", 40, 420, 10, DARKGRAY);
DrawText("(c) WWI Plane Model created by GiaHanLam", screenWidth - 240, screenHeight - 20, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model); // Unload model data
UnloadTexture(texture); // Unload texture data
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -1,22 +0,0 @@
| resource | author | licence | notes |
| :------------------- | :---------: | :------ | :---- |
| models/obj/castle.obj,<br>models/obj/castle_diffuse.png | [Alberto Cano](https://www.artstation.com/albertocano) | [CC-BY-NC](https://creativecommons.org/licenses/by-nc/4.0/legalcode) | - |
| models/obj/bridge.obj,<br>models/obj/bridge_diffuse.png | [Alberto Cano](https://www.artstation.com/albertocano) | [CC-BY-NC](https://creativecommons.org/licenses/by-nc/4.0/legalcode) | - |
| models/obj/house.obj,<br>models/obj/house_diffuse.png | [Alberto Cano](https://www.artstation.com/albertocano) | [CC-BY-NC](https://creativecommons.org/licenses/by-nc/4.0/legalcode) | - |
| models/obj/market.obj,<br>models/obj/market_diffuse.png | [Alberto Cano](https://www.artstation.com/albertocano) | [CC-BY-NC](https://creativecommons.org/licenses/by-nc/4.0/legalcode) | - |
| models/obj/turret.obj,<br>models/obj/turret_diffuse.png | [Alberto Cano](https://www.artstation.com/albertocano) | [CC-BY-NC](https://creativecommons.org/licenses/by-nc/4.0/legalcode) | - |
| models/obj/well.obj,<br>models/obj/well_diffuse.png | [Alberto Cano](https://www.artstation.com/albertocano) | [CC-BY-NC](https://creativecommons.org/licenses/by-nc/4.0/legalcode) | - |
| models/obj/cube.obj,<br>models/obj/cube_diffuse.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
| models/obj/plane.obj,<br>models/obj/plane_diffuse.png | [GiaHanLam](https://sketchfab.com/GiaHanLam) | [CC-BY](https://creativecommons.org/licenses/by/4.0/) | Used by: [`models_yaw_pitch_roll.c`](https://github.com/raysan5/raylib/blob/master/examples/models/models_yaw_pitch_roll.c)
| models/iqm/guy.iqm,<br>models/iqm/guyanim.iqm,<br>models/iqm/guytex.png,<br>models/iqm/guy.blend | [@culacant](https://github.com/culacant) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
| models/gltf/robot.glb,<br>models/gltf/robot.blend | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
| models/vox/chr_knight.vox | ❔ | ❔ | - |
| models/vox/chr_sword.vox | ❔ | ❔ | - |
| models/vox/monu9.vox | ❔ | ❔ | - |
| billboard.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
| cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
| cubicmap_atlas.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
| heightmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
| dresden_square_1k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
| dresden_square_2k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
| skybox.png | ❔ | ❔ | - |

View File

@ -1,5 +0,0 @@
robot.glb model by @Quaternius (https://www.patreon.com/quaternius)
Licensed under CC0 1.0 Universal (CC0 1.0) - Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/)
greenman.glb, greenman_hat.glb, greenman_sword.glb, greenman_shield.glb models by @iP (https://github.com/ipzaur)
Licensed under CC0 1.0 Universal (CC0 1.0) - Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/)

View File

@ -1,12 +0,0 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl skin
Ns 86.470579
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 0.000000
illum 9

View File

@ -1,68 +0,0 @@
# reference material
#mtllib cube.mtl
# object box
# vertex (XZY)
v 5.5 0 1.5
v 8.5 0 1.5
v 5.5 0 -1.5
v 8.5 0 -1.5
v 5.5 3 1.5
v 8.5 3 1.5
v 5.5 3 -1.5
v 8.5 3 -1.5
# normals (XYZ)
vn 0 -1 0
vn 0 1 0
vn 0 0 1
vn 1 0 0
vn 0 0 -1
vn -1 0 0
# UVs (XY)
vt 0.5 0 0
vt 1 0 0
vt 1 0.5 0
vt 0.5 0.5 0
vt 0.5 0.5 0
vt 1 0.5 0
vt 0.5 1 0
vt 1 1 0
vt 0 0.5 0
vt 1 0.5 0
vt 1 0 0
vt 0 0 0
vt 0 0.5 0
vt 1 0.5 0
vt 1 1 0
vt 0 1 0
vt 0.5 0 0
vt 0 0 0
vt 0 0.5 0
vt 0.5 0.5 0
vt 0 0.5 0
vt 0.5 0.5 0
vt 0.5 1 0
vt 0 1 0
# merger
g box
# reference material
#usemtl mat01
# faces
f 1/9/1 3/10/1 4/11/1
f 4/11/1 2/12/1 1/9/1
f 5/13/2 6/14/2 8/15/2
f 8/15/2 7/16/2 5/13/2
f 1/17/6 2/18/6 6/19/6
f 6/19/6 5/20/6 1/17/6
f 2/6/1 4/5/1 8/7/1
f 8/7/1 6/8/1 2/6/1
f 4/2/3 3/1/3 7/4/3
f 7/4/3 8/3/3 4/2/3
f 3/22/5 1/21/5 5/24/5
f 5/24/5 7/23/5 3/22/5

Some files were not shown because too many files have changed in this diff Show More