3d picking
There is no browser build of this example yet.
Is it the same as C?
- Desktop:verified The Zig version renders a final frame that is byte-identical to the C example.
- Browser:not checked yet The browser comparison does not cover this example yet.
//! raylib [core] example - 3d picking
//!
//! Zig-API translation of examples/core/core_3d_picking.c (raylib 6.2).
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
const rl = @import("raylib");
pub fn main() void {
// Initialization
const screen_width = 800;
const screen_height = 450;
rl.initWindow(screen_width, screen_height, "raylib [core] example - 3d picking");
defer rl.closeWindow(); // Close window and OpenGL context
// Define the camera to look into our 3d world
var camera: rl.Camera = .{
.position = .{ .x = 10.0, .y = 10.0, .z = 10.0 }, // Camera position
.target = .{ .x = 0.0, .y = 0.0, .z = 0.0 }, // Camera looking at point
.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 }, // Camera up vector (rotation towards target)
.fovy = 45.0, // Camera field-of-view Y
.projection = .perspective, // Camera projection type
};
const cube_position: rl.Vector3 = .{ .x = 0.0, .y = 1.0, .z = 0.0 };
const cube_size: rl.Vector3 = .{ .x = 2.0, .y = 2.0, .z = 2.0 };
var ray: rl.Ray = .{ .position = .{ .x = 0, .y = 0, .z = 0 }, .direction = .{ .x = 0, .y = 0, .z = 0 } }; // Picking line ray
var collision: rl.RayCollision = .{ // Ray collision hit info
.hit = false,
.distance = 0,
.point = .{ .x = 0, .y = 0, .z = 0 },
.normal = .{ .x = 0, .y = 0, .z = 0 },
};
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
// Main game loop
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
// Update
if (rl.isCursorHidden()) rl.updateCamera(&camera, .first_person);
// Toggle camera controls
if (rl.isMouseButtonPressed(.right)) {
if (rl.isCursorHidden()) rl.enableCursor() else rl.disableCursor();
}
if (rl.isMouseButtonPressed(.left)) {
if (!collision.hit) {
ray = rl.getScreenToWorldRay(rl.getMousePosition(), camera);
// Check collision between ray and box
collision = rl.getRayCollisionBox(ray, .{
.min = .{
.x = cube_position.x - cube_size.x / 2,
.y = cube_position.y - cube_size.y / 2,
.z = cube_position.z - cube_size.z / 2,
},
.max = .{
.x = cube_position.x + cube_size.x / 2,
.y = cube_position.y + cube_size.y / 2,
.z = cube_position.z + cube_size.z / 2,
},
});
} else collision.hit = false;
}
// Draw
rl.beginDrawing();
defer rl.endDrawing();
rl.clearBackground(.ray_white);
{
rl.beginMode3D(camera);
defer rl.endMode3D();
if (collision.hit) {
rl.drawCube(cube_position, cube_size.x, cube_size.y, cube_size.z, .red);
rl.drawCubeWires(cube_position, cube_size.x, cube_size.y, cube_size.z, .maroon);
rl.drawCubeWires(cube_position, cube_size.x + 0.2, cube_size.y + 0.2, cube_size.z + 0.2, .green);
} else {
rl.drawCube(cube_position, cube_size.x, cube_size.y, cube_size.z, .gray);
rl.drawCubeWires(cube_position, cube_size.x, cube_size.y, cube_size.z, .dark_gray);
}
rl.drawRay(ray, .maroon);
rl.drawGrid(10, 1.0);
}
rl.drawText("Try clicking on the box with your mouse!", 240, 10, 20, .dark_gray);
if (collision.hit) {
const text_y: i32 = @intFromFloat(@as(f32, screen_height) * 0.1);
rl.drawText("BOX SELECTED", @divTrunc(screen_width - rl.measureText("BOX SELECTED", 30), 2), text_y, 30, .green);
}
rl.drawText("Right click mouse to toggle camera controls", 10, 430, 10, .gray);
rl.drawFPS(10, 10);
}
}/*******************************************************************************************
*
* raylib [core] example - 3d picking
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 1.3, 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) 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 [core] example - 3d picking");
// 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
Vector3 cubePosition = { 0.0f, 1.0f, 0.0f };
Vector3 cubeSize = { 2.0f, 2.0f, 2.0f };
Ray ray = { 0 }; // Picking line ray
RayCollision collision = { 0 }; // Ray collision hit info
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);
// Toggle camera controls
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
{
if (IsCursorHidden()) EnableCursor();
else DisableCursor();
}
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{
if (!collision.hit)
{
ray = GetScreenToWorldRay(GetMousePosition(), camera);
// Check collision between ray and box
collision = GetRayCollisionBox(ray,
(BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 },
(Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }});
}
else collision.hit = false;
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
if (collision.hit)
{
DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED);
DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON);
DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN);
}
else
{
DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY);
DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY);
}
DrawRay(ray, MAROON);
DrawGrid(10, 1.0f);
EndMode3D();
DrawText("Try clicking on the box with your mouse!", 240, 10, 20, DARKGRAY);
if (collision.hit) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30))/2, (int)(screenHeight*0.1f), 30, GREEN);
DrawText("Right click mouse to toggle camera controls", 10, 430, 10, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}From raylib 6.2. The original on GitHub.