models_basic_voxel.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*******************************************************************************************
  2. *
  3. * raylib [models] example - basic voxel
  4. *
  5. * Example complexity rating: [★★☆☆] 2/4
  6. *
  7. * Example originally created with raylib 5.5, last time updated with raylib 5.5
  8. *
  9. * Example contributed by Tim Little (@timlittle) and reviewed by Ramon Santamaria (@raysan5)
  10. *
  11. * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
  12. * BSD-like license that allows static linking with closed source software
  13. *
  14. * Copyright (c) 2025 Tim Little (@timlittle)
  15. *
  16. ********************************************************************************************/
  17. #include "raylib.h"
  18. #include "raymath.h"
  19. #define WORLD_SIZE 8 // Size of our voxel world (8x8x8 cubes)
  20. //------------------------------------------------------------------------------------
  21. // Program main entry point
  22. //------------------------------------------------------------------------------------
  23. int main(void)
  24. {
  25. // Initialization
  26. //--------------------------------------------------------------------------------------
  27. const int screenWidth = 800;
  28. const int screenHeight = 450;
  29. InitWindow(screenWidth, screenHeight, "raylib [models] example - basic voxel");
  30. DisableCursor(); // Lock mouse to window center
  31. // Define the camera to look into our 3d world (first person)
  32. Camera3D camera = { 0 };
  33. camera.position = (Vector3){ -2.0f, 0.0f, -2.0f }; // Camera position at ground level
  34. camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
  35. camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector
  36. camera.fovy = 45.0f; // Camera field-of-view Y
  37. camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
  38. // Create a cube model
  39. Mesh cubeMesh = GenMeshCube(1.0f, 1.0f, 1.0f); // Create a unit cube mesh
  40. Model cubeModel = LoadModelFromMesh(cubeMesh); // Convert mesh to a model
  41. cubeModel.materials[0].maps[MATERIAL_MAP_DIFFUSE].color = BEIGE;
  42. // Initialize voxel world - fill with voxels
  43. bool voxels[WORLD_SIZE][WORLD_SIZE][WORLD_SIZE] = { false };
  44. for (int x = 0; x < WORLD_SIZE; x++)
  45. {
  46. for (int y = 0; y < WORLD_SIZE; y++)
  47. {
  48. for (int z = 0; z < WORLD_SIZE; z++)
  49. {
  50. voxels[x][y][z] = true;
  51. }
  52. }
  53. }
  54. SetTargetFPS(60);
  55. //--------------------------------------------------------------------------------------
  56. // Main game loop
  57. while (!WindowShouldClose()) // Detect window close button or ESC key
  58. {
  59. // Update
  60. //----------------------------------------------------------------------------------
  61. UpdateCamera(&camera, CAMERA_FIRST_PERSON);
  62. // Handle voxel removal with mouse click
  63. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
  64. {
  65. // Cast a ray from the screen center (where crosshair would be)
  66. Vector2 screenCenter = { screenWidth/2.0f, screenHeight/2.0f };
  67. Ray ray = GetMouseRay(screenCenter, camera);
  68. // Check ray collision with all voxels
  69. bool voxelRemoved = false;
  70. for (int x = 0; (x < WORLD_SIZE) && !voxelRemoved; x++)
  71. {
  72. for (int y = 0; (y < WORLD_SIZE) && !voxelRemoved; y++)
  73. {
  74. for (int z = 0; (z < WORLD_SIZE) && !voxelRemoved; z++)
  75. {
  76. if (!voxels[x][y][z]) continue; // Skip empty voxels
  77. // Build a bounding box for this voxel
  78. Vector3 position = { (float)x, (float)y, (float)z };
  79. BoundingBox box = {
  80. (Vector3){ position.x - 0.5f, position.y - 0.5f, position.z - 0.5f },
  81. (Vector3){ position.x + 0.5f, position.y + 0.5f, position.z + 0.5f }
  82. };
  83. // Check ray-box collision
  84. RayCollision collision = GetRayCollisionBox(ray, box);
  85. if (collision.hit)
  86. {
  87. voxels[x][y][z] = false; // Remove this voxel
  88. voxelRemoved = true; // Exit all loops
  89. }
  90. }
  91. }
  92. }
  93. }
  94. //----------------------------------------------------------------------------------
  95. // Draw
  96. //----------------------------------------------------------------------------------
  97. BeginDrawing();
  98. ClearBackground(RAYWHITE);
  99. BeginMode3D(camera);
  100. DrawGrid(10, 1.0f);
  101. // Draw all voxels
  102. for (int x = 0; x < WORLD_SIZE; x++)
  103. {
  104. for (int y = 0; y < WORLD_SIZE; y++)
  105. {
  106. for (int z = 0; z < WORLD_SIZE; z++)
  107. {
  108. if (!voxels[x][y][z]) continue;
  109. Vector3 position = { (float)x, (float)y, (float)z };
  110. DrawModel(cubeModel, position, 1.0f, BEIGE);
  111. DrawCubeWires(position, 1.0f, 1.0f, 1.0f, BLACK);
  112. }
  113. }
  114. }
  115. EndMode3D();
  116. DrawText("Left-click a voxel to remove it!", 10, 10, 20, DARKGRAY);
  117. DrawText("WASD to move, mouse to look around", 10, 35, 10, GRAY);
  118. EndDrawing();
  119. //----------------------------------------------------------------------------------
  120. }
  121. // De-Initialization
  122. //--------------------------------------------------------------------------------------
  123. UnloadModel(cubeModel);
  124. CloseWindow();
  125. //--------------------------------------------------------------------------------------
  126. return 0;
  127. }