diff --git a/ReadMe.md b/ReadMe.md index 85467ec..7172d58 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -21,11 +21,6 @@ pub fn main() anyerror!void // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update your variables here - //---------------------------------------------------------------------------------- - // Draw //---------------------------------------------------------------------------------- BeginDrawing(); @@ -45,6 +40,9 @@ pub fn main() anyerror!void } ``` +## Technical restrictions +Due to zig being a relatively new language it does [not have full C ABI support](https://github.com/ziglang/zig/issues/1481) at the moment. For use that mainly means we can't use any functions that returns structs that are less then 16 bytes large. + ## Building the examples To build all available examples simply `zig build examples`. To list available examples run `zig build --help`. If you want to run and examples, say `basic_window` run `zig build basic_window` diff --git a/build.zig b/build.zig index 1ed5769..d7d7297 100644 --- a/build.zig +++ b/build.zig @@ -11,16 +11,27 @@ pub fn build(b: *Builder) void { const mode = b.standardReleaseOptions(); - var basicWindow = b.addExecutable("BasicWindow", "examples/core/BasicWindow.zig"); - basicWindow.setBuildMode(mode); - basicWindow.linkSystemLibrary("raylib"); - basicWindow.addPackagePath("raylib", "lib/raylib-zig.zig"); + var basicWindow = b.addExecutable("BasicWindow", "examples/core/basic_window.zig"); + basicWindow.setBuildMode(mode); + basicWindow.linkSystemLibrary("raylib"); + basicWindow.addPackagePath("raylib", "lib/raylib-zig.zig"); + + var modelsLoading = b.addExecutable("BasicWindow", "examples/models/models_loading.zig"); + modelsLoading.setBuildMode(mode); + modelsLoading.linkSystemLibrary("raylib"); + modelsLoading.addPackagePath("raylib", "lib/raylib-zig.zig"); const examplesStep = b.step("examples", "Builds all the examples"); - examplesStep.dependOn(&basicWindow.step); + examplesStep.dependOn(&basicWindow.step); + examplesStep.dependOn(&modelsLoading.step); const runBasicWindow = basicWindow.run(); - runBasicWindow.step.dependOn(b.getInstallStep()); + runBasicWindow.step.dependOn(b.getInstallStep()); const basicWindowStep = b.step("basic_window", "Creates a basic window with text"); - basicWindowStep.dependOn(&runBasicWindow.step); + basicWindowStep.dependOn(&runBasicWindow.step); + + const runModelsLoading= modelsLoading.run(); + runModelsLoading.step.dependOn(b.getInstallStep()); + const modelsLoadingStep = b.step("models_loading", "Loads a model and renders it"); + modelsLoadingStep.dependOn(&runModelsLoading.step); } diff --git a/examples/ReadMe.md b/examples/ReadMe.md index a93a4bd..07ba826 100644 --- a/examples/ReadMe.md +++ b/examples/ReadMe.md @@ -6,6 +6,14 @@ Making raylib bindings in zig is pretty straight forward since zig has a built-i Examples using raylib core platform functionality like window creation, inputs, drawing modes and system functionality. -| ## | example | image | developer | new | -|----|----------|--------|:----------:|:---:| -| 01 | [core_basic_window](core/BasicWindow.zig) | core_basic_window | ray \ No newline at end of file +| ## | example | developer | +|----|----------|:----------:| +| 01 | [core_basic_window](core/basic_window.zig) | ray + +### category: models + +Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib models module. + +| ## | example | developer | +|----|----------|:----------:| +| 74 | [models_loading](models/models_loading.c) ([Won't build](https://github.com/G3bE/raylib-zig#Technical-restrictions)) | ray diff --git a/examples/core/BasicWindow.zig b/examples/core/basic_window.zig similarity index 100% rename from examples/core/BasicWindow.zig rename to examples/core/basic_window.zig diff --git a/examples/models/models_loading.zig b/examples/models/models_loading.zig new file mode 100644 index 0000000..6b52804 --- /dev/null +++ b/examples/models/models_loading.zig @@ -0,0 +1,134 @@ +// +// ModelsLoading +// Zig version: +// Author: Nikolas Wipper +// Date: 2020-02-15 +// + +usingnamespace @import("raylib"); + +pub fn main() anyerror!void +{ + // Initialization + //-------------------------------------------------------------------------------------- + const screenWidth = 800; + const screenHeight = 450; + + InitWindow(screenWidth, screenHeight, c"raylib [models] example - models loading"); + + // Define the camera to look into our 3d world + var camera = Camera { + .position = Vector3 { .x = 50.0, .y = 50.0, .z = 50.0 }, // Camera position + .target = Vector3 { .x = 0.0, .y = 10.0, .z = 0.0 }, // Camera looking at point + .up = Vector3 { .x = 0.0, .y = 1.0, .z = 0.0 }, // Camera up vector (rotation towards target) + .fovy = 45.0, // Camera field-of-view Y + .type = CameraType.CAMERA_PERSPECTIVE // Camera mode type + }; + + var model = LoadModel(c"resources/models/castle.obj"); // Load model + var texture = LoadTexture(c"resources/models/castle_diffuse.png"); // Load model texture + model.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture; // Set map diffuse texture + + var position = Vector3 { .x = 0.0, .y = 0.0, .z = 0.0 }; // Set model position + + var bounds = MeshBoundingBox(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 + + SetCameraMode(camera, CameraMode.CAMERA_FREE); // Set a free camera mode + + var 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); + + // Load new models/textures on drag&drop + if (IsFileDropped()) + { + var count: c_int = 0; + var droppedFiles = GetDroppedFiles(&count); + + if (count == 1) // Only support one file dropped + { + if (IsFileExtension(droppedFiles[0], c".obj") or + IsFileExtension(droppedFiles[0], c".gltf") or + IsFileExtension(droppedFiles[0], c".iqm")) // Model file formats supported + { + UnloadModel(model); // Unload previous model + model = LoadModel(droppedFiles[0]); // Load new model + model.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture; // Set current map diffuse texture + + bounds = MeshBoundingBox(model.meshes[0]); + + // TODO: Move camera position from target enough distance to visualize model properly + } + else if (IsFileExtension(droppedFiles[0], c".png")) // Texture file formats supported + { + // Unload current model texture and load new one + UnloadTexture(texture); + texture = LoadTexture(droppedFiles[0]); + model.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture; + } + } + + ClearDroppedFiles(); // Clear internal buffers + } + + // Select model on mouse click + if (IsMouseButtonPressed(MouseButton.MOUSE_LEFT_BUTTON)) + { + // Check collision between ray and box + if (CheckCollisionRayBox(GetMouseRay(GetMousePosition(), camera), bounds)) + { + selected = !selected; + } + else + { + selected = false; + } + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + DrawModel(model, position, 1.0, WHITE); // Draw 3d model with texture + + DrawGrid(20, 10.0); // Draw a grid + + if (selected) DrawBoundingBox(bounds, GREEN); // Draw selection box + + EndMode3D(); + + DrawText(c"Drag & drop model to load mesh/texture.", 10, GetScreenHeight() - 20, 10, DARKGRAY); + if (selected) DrawText(c"MODEL SELECTED", GetScreenWidth() - 110, 10, 10, GREEN); + + DrawText(c"(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 + //-------------------------------------------------------------------------------------- +} diff --git a/lib/raylib-zig.zig b/lib/raylib-zig.zig index 81560d2..674a304 100644 --- a/lib/raylib-zig.zig +++ b/lib/raylib-zig.zig @@ -93,7 +93,7 @@ pub const Image = extern struct { format: c_int, }; -pub const struct_Texture2D = extern struct { +pub const Texture2D = extern struct { id: c_uint, width: c_int, height: c_int, @@ -142,7 +142,7 @@ pub const Camera3D = extern struct { target: Vector3, up: Vector3, fovy: f32, - type: c_int, + type: CameraType, }; pub const Camera = Camera3D; @@ -167,12 +167,12 @@ pub const Mesh = extern struct { animNormals: [*c]f32, boneIds: [*c]c_int, boneWeights: [*c]f32, - vaoId: uc_int, - vboId: [7]uc_int, + vaoId: c_uint, + vboId: [7]c_uint, }; pub const Shader = extern struct { - id: uc_int, + id: c_uint, locs: [32]c_int, }; @@ -236,17 +236,17 @@ pub const BoundingBox = extern struct { }; pub const Wave = extern struct { - sampleCount: uc_int, - sampleRate: uc_int, - sampleSize: uc_int, - channels: uc_int, + sampleCount: c_uint, + sampleRate: c_uint, + sampleSize: c_uint, + channels: c_uint, data: ?*c_void, }; pub const Sound = extern struct { audioBuffer: ?*c_void, - source: uc_int, - buffer: uc_int, + source: c_uint, + buffer: c_uint, format: c_int, }; @@ -254,13 +254,13 @@ pub const MusicData = @OpaqueType(); pub const Music = ?*MusicData; pub const AudioStream = extern struct { - sampleRate: uc_int, - sampleSize: uc_int, - channels: uc_int, + sampleRate: c_uint, + sampleSize: c_uint, + channels: c_uint, audioBuffer: ?*c_void, format: c_int, - source: uc_int, - buffers: [2]uc_int, + source: c_uint, + buffers: [2]c_uint, }; pub const VrDeviceInfo = extern struct { @@ -698,10 +698,10 @@ pub extern fn IsGamepadButtonUp(gamepad: c_int, button: c_int) bool; pub extern fn GetGamepadButtonPressed() c_int; pub extern fn GetGamepadAxisCount(gamepad: c_int) c_int; pub extern fn GetGamepadAxisMovement(gamepad: c_int, axis: c_int) f32; -pub extern fn IsMouseButtonPressed(button: c_int) bool; -pub extern fn IsMouseButtonDown(button: c_int) bool; -pub extern fn IsMouseButtonReleased(button: c_int) bool; -pub extern fn IsMouseButtonUp(button: c_int) bool; +pub extern fn IsMouseButtonPressed(button: MouseButton) bool; +pub extern fn IsMouseButtonDown(button: MouseButton) bool; +pub extern fn IsMouseButtonReleased(button: MouseButton) bool; +pub extern fn IsMouseButtonUp(button: MouseButton) bool; pub extern fn GetMouseX() c_int; pub extern fn GetMouseY() c_int; pub extern fn GetMousePosition() Vector2; @@ -721,7 +721,7 @@ pub extern fn GetGestureDragVector() Vector2; pub extern fn GetGestureDragAngle() f32; pub extern fn GetGesturePinchVector() Vector2; pub extern fn GetGesturePinchAngle() f32; -pub extern fn SetCameraMode(camera: Camera, mode: c_int) void; +pub extern fn SetCameraMode(camera: Camera, mode: CameraMode) void; pub extern fn UpdateCamera(camera: [*c]Camera) void; pub extern fn SetCameraPanControl(panKey: c_int) void; pub extern fn SetCameraAltControl(altKey: c_int) void; @@ -1005,13 +1005,13 @@ pub extern fn StopAudioStream(stream: AudioStream) void; pub extern fn SetAudioStreamVolume(stream: AudioStream, volume: f32) void; pub extern fn SetAudioStreamPitch(stream: AudioStream, pitch: f32) void; +pub const MAP_DIFFUSE = MaterialMapType.MAP_ALBEDO; +pub const MAP_SPECULAR = MaterialMapType.MAP_METALNESS; pub const LOC_MAP_SPECULAR = LOC_MAP_METALNESS; -pub const MAP_DIFFUSE = MAP_ALBEDO; pub const LOC_MAP_DIFFUSE = LOC_MAP_ALBEDO; pub const MAX_TOUCH_POINTS = 10; pub const ShowWindow = UnhideWindow; pub const FormatText = TextFormat; -pub const MAP_SPECULAR = MAP_METALNESS; pub const PI = 3.141593; pub const CLITERAL = Color; pub const MAX_SHADER_LOCATIONS = 32; diff --git a/projectSetup.sh b/projectSetup.sh index e854d29..5c47142 100755 --- a/projectSetup.sh +++ b/projectSetup.sh @@ -28,5 +28,5 @@ pub fn build(b: *Builder) void { mkdir src mkdir raylib-zig cp ../lib/* raylib-zig -cp ../examples/core/BasicWindow.zig src -mv src/BasicWindow.zig src/main.zig \ No newline at end of file +cp ../examples/core/basic_window.zig src +mv src/basic_window.zig src/main.zig \ No newline at end of file