|
const std = @import("std"); |
|
const rl = @import("raylib"); |
|
|
|
// Import Box3D headers mapped via your build.zig layout |
|
const c = @cImport({ |
|
@cInclude("box3d/box3d.h"); |
|
}); |
|
|
|
/// Helper utility to convert a Box3D vector into a Raylib Vector3 structure |
|
fn toRlVec3(v: c.b3Vec3) rl.Vector3 { |
|
return rl.Vector3.init(v.x, v.y, v.z); |
|
} |
|
|
|
pub fn main() !void { |
|
// 1. Initialize Raylib 3D Application Window Context |
|
const screen_width = 1280; |
|
const screen_height = 720; |
|
rl.initWindow(screen_width, screen_height, "Zig + Box3D Physics Simulation Workspace"); |
|
defer rl.closeWindow(); |
|
|
|
// Configure camera positioning in 3D dimensional space |
|
var camera = rl.Camera3D{ |
|
.position = rl.Vector3.init(0.0, 12.0, 18.0), // Elevated overview position |
|
.target = rl.Vector3.init(0.0, 2.0, 0.0), // Tracking target center point |
|
.up = rl.Vector3.init(0.0, 1.0, 0.0), // Standard vertical orientation axis |
|
.fovy = 45.0, // Field of view angle degree |
|
.projection = .perspective, |
|
}; |
|
|
|
rl.setTargetFPS(60); |
|
|
|
// 2. Configure and Instatiate Box3D Physics Simulation Environment |
|
var world_def = c.b3DefaultWorldDef(); |
|
world_def.gravity = c.b3Vec3{ .x = 0.0, .y = -9.81, .z = 0.0 }; // Standard Earth downward gravity acceleration |
|
|
|
const world_id = c.b3CreateWorld(&world_def); |
|
if (c.b3World_IsValid(world_id) == false) { |
|
std.debug.print("Failed to initialize Box3D physics world context.\n", .{}); |
|
return error.PhysicsInitializationFailed; |
|
} |
|
defer c.b3DestroyWorld(world_id); |
|
|
|
// 3. Create Static Ground Plane Platform Body |
|
var ground_body_def = c.b3DefaultBodyDef(); |
|
ground_body_def.type = c.b3_staticBody; |
|
ground_body_def.position = c.b3Vec3{ .x = 0.0, .y = 0.0, .z = 0.0 }; |
|
const ground_body_id = c.b3CreateBody(world_id, &ground_body_def); |
|
|
|
var ground_shape_def = c.b3DefaultShapeDef(); |
|
// Define half-extents parameters for a flat platform using the correct box hull helper |
|
var ground_box = c.b3MakeBoxHull(8.0, 0.5, 8.0); |
|
_ = c.b3CreateHullShape(ground_body_id, &ground_shape_def, &ground_box.base); |
|
|
|
// 4. Create Dynamic Falling Sphere Body |
|
var sphere_body_def = c.b3DefaultBodyDef(); |
|
sphere_body_def.type = c.b3_dynamicBody; |
|
sphere_body_def.position = c.b3Vec3{ .x = -1.5, .y = 8.0, .z = 0.0 }; // Left side high offset |
|
const sphere_body_id = c.b3CreateBody(world_id, &sphere_body_def); |
|
|
|
var sphere_shape_def = c.b3DefaultShapeDef(); |
|
sphere_shape_def.density = 1.0; |
|
sphere_shape_def.baseMaterial.restitution = 0.4; // Set restitution via baseMaterial nested field |
|
|
|
var sphere = c.b3Sphere{ .radius = 0.6 }; |
|
_ = c.b3CreateSphereShape(sphere_body_id, &sphere_shape_def, &sphere); |
|
|
|
// 5. Create Dynamic Dropping Box Cube Body |
|
var box_body_def = c.b3DefaultBodyDef(); |
|
box_body_def.type = c.b3_dynamicBody; |
|
box_body_def.position = c.b3Vec3{ .x = 1.5, .y = 10.0, .z = 0.5 }; // Right side higher offset |
|
const box_body_id = c.b3CreateBody(world_id, &box_body_def); |
|
|
|
var box_shape_def = c.b3DefaultShapeDef(); |
|
box_shape_def.density = 1.2; |
|
box_shape_def.baseMaterial.friction = 0.3; // Set friction via baseMaterial nested field |
|
|
|
// Define half-extents parameters for a box: 0.75m x 0.75m x 0.75m (Translates into a 1.5m solid cube) |
|
var box_hull = c.b3MakeBoxHull(0.75, 0.75, 0.75); |
|
_ = c.b3CreateHullShape(box_body_id, &box_shape_def, &box_hull.base); |
|
|
|
// Real-Time Frame Update Logic & Graphics Rendering Loop |
|
const time_step: f32 = 1.0 / 60.0; // Fixed update time step mapping 60Hz |
|
const sub_step_count: i32 = 4; // Constraint sub-stepping engine iteration accuracy pass |
|
|
|
while (!rl.windowShouldClose()) { |
|
// Handle simulation state reset commands |
|
if (rl.isKeyPressed(.r)) { |
|
// Reset Sphere body to its launch configuration definition properties |
|
c.b3Body_SetTransform(sphere_body_id, sphere_body_def.position, sphere_body_def.rotation); |
|
c.b3Body_SetLinearVelocity(sphere_body_id, c.b3Vec3{ .x = 0.0, .y = 0.0, .z = 0.0 }); |
|
c.b3Body_SetAngularVelocity(sphere_body_id, c.b3Vec3{ .x = 0.0, .y = 0.0, .z = 0.0 }); |
|
|
|
// Reset Box body to its launch configuration definition properties |
|
c.b3Body_SetTransform(box_body_id, box_body_def.position, box_body_def.rotation); |
|
c.b3Body_SetLinearVelocity(box_body_id, c.b3Vec3{ .x = 0.0, .y = 0.0, .z = 0.0 }); |
|
c.b3Body_SetAngularVelocity(box_body_id, c.b3Vec3{ .x = 0.0, .y = 0.0, .z = 0.0 }); |
|
} |
|
|
|
// Step the internal physics world forward in time matching target update frames |
|
c.b3World_Step(world_id, time_step, sub_step_count); |
|
|
|
// Allow orbital camera manipulation directly via mouse mechanics |
|
rl.updateCamera(&camera, .orbital); |
|
|
|
// Graphics Render Phase Execution |
|
rl.beginDrawing(); |
|
defer rl.endDrawing(); |
|
|
|
rl.clearBackground(rl.Color.ray_white); |
|
|
|
{ |
|
camera.begin(); |
|
defer camera.end(); |
|
|
|
// Draw a base layout configuration grid for measurement comparisons |
|
rl.drawGrid(20, 1.0); |
|
|
|
// Render Static Ground Platform (Dimensions convert half-extents to full sizing dimensions) |
|
const ground_pos = toRlVec3(c.b3Body_GetPosition(ground_body_id)); |
|
rl.drawCube(ground_pos, 16.0, 1.0, 16.0, rl.Color.gray); |
|
rl.drawCubeWires(ground_pos, 16.0, 1.0, 16.0, rl.Color.dark_gray); |
|
|
|
// Render Dynamic Falling Sphere |
|
const sphere_pos = toRlVec3(c.b3Body_GetPosition(sphere_body_id)); |
|
rl.drawSphere(sphere_pos, 0.6, rl.Color.red); |
|
rl.drawSphereWires(sphere_pos, 0.6, 16, 16, rl.Color.maroon); |
|
|
|
// Render Dynamic Dropping Box Cube |
|
const box_pos = toRlVec3(c.b3Body_GetPosition(box_body_id)); |
|
rl.drawCube(box_pos, 1.5, 1.5, 1.5, rl.Color.blue); |
|
rl.drawCubeWires(box_pos, 1.5, 1.5, 1.5, rl.Color.dark_blue); |
|
} |
|
|
|
// Display Real-Time Overlay Diagnostics Text HUD Information |
|
rl.drawFPS(10, 10); |
|
rl.drawText("Box3D Physics + Raylib-Zig Render Workspace", 10, 35, 20, rl.Color.dark_gray); |
|
rl.drawText("Use Mouse to Rotate Camera Perspective", 10, 60, 16, rl.Color.gray); |
|
rl.drawText("Red Entity: Sphere | Blue Entity: Box/Hull Cube | Gray: Static Platform Ground", 10, 85, 16, rl.Color.dark_gray); |
|
rl.drawText("Press [R] to Reset Objects to Spawn State", 10, 110, 16, rl.Color.red); |
|
} |
|
} |