You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
9.6 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib [models] example - full solar system
  4. *
  5. * This example has been created using raylib 2.5 (www.raylib.com)
  6. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  7. *
  8. * Copyright (c) 2019 Aldrin Martoq (@aldrinmartoq)
  9. *
  10. ********************************************************************************************/
  11. #include "raylib.h"
  12. #include "rlgl.h"
  13. #define MAX_BODY_CHILDREN 10
  14. float rotationSpeed = 0.2;
  15. // A celestial body that has children bodies orbiting around
  16. typedef struct Body {
  17. const char *label; // label of the body, for ex: moon
  18. float radius; // object radius
  19. float orbitRadius; // orbit average radius
  20. float orbitPeriod; // time the body takes to do a full orbit loop
  21. float rotationPeriod; // time the body takes to do a full rotation on itself
  22. Texture2D texture; // texture of the body
  23. Model model; // model of the body
  24. float orbitPosition; // current orbit position
  25. float rotationPosition; // current rotation position
  26. Vector2 labelPosition; // label position in screen
  27. struct Body *children[MAX_BODY_CHILDREN]; // children array
  28. int childrenCount; // children count
  29. } Body;
  30. //------------------------------------------------------------------------------------
  31. // Module Functions Declaration
  32. //------------------------------------------------------------------------------------
  33. Body CreateBody(float radius, float orbitRadius, float orbitPeriod, const char *label, const char *texture); // Initializes a new Body with the given parameters
  34. void AddBodyChildren(Body *parent, Body *children); // Add a children body to the parent body
  35. void DrawBody(Body *body, Camera *camera); // Draw body and its children, updating labelPosition
  36. void DrawLabels(Body *body); // Draw body label and its children labels
  37. //------------------------------------------------------------------------------------
  38. // Program main entry point
  39. //------------------------------------------------------------------------------------
  40. int main(void)
  41. {
  42. // Initialization
  43. //--------------------------------------------------------------------------------------
  44. const int screenWidth = 1024;
  45. const int screenHeight = 768;
  46. const char *text;
  47. bool gridEnabled = true;
  48. bool helpEnabled = false;
  49. bool labelEnabled = true;
  50. bool cameraParametersEnabled = true;
  51. InitWindow(screenWidth, screenHeight, "raylib [models] example - solar system");
  52. // Define the camera to look into our 3d world
  53. Camera camera = { 0 };
  54. camera.position = (Vector3){ 16.0f, 16.0f, 16.0f };
  55. camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
  56. camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
  57. camera.fovy = 45.0f;
  58. camera.type = CAMERA_PERSPECTIVE;
  59. SetCameraMode(camera, CAMERA_FREE);
  60. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  61. //--------------------------------------------------------------------------------------
  62. // Create Bodies
  63. Body sun = CreateBody(0.2, 0.0, 0, "sun", "2k_sun");
  64. Body moon = CreateBody(0.05, 0.200, 24, "moon", "2k_moon");
  65. Body mercury = CreateBody(0.05, 0.396, 90, "mercury", "2k_mercury");
  66. Body venus = CreateBody(0.05, 0.723, 210, "venus", "2k_venus_atmosphere");
  67. Body earth = CreateBody(0.05, 1.000, 365, "earth", "2k_earth_daymap");
  68. Body mars = CreateBody(0.05, 1.523, 690, "mars", "2k_mars");
  69. Body jupiter = CreateBody(0.05, 5.200, 4260, "jupiter", "2k_jupiter");
  70. Body saturn = CreateBody(0.05, 9.532, 10620, "saturn", "2k_saturn");
  71. Body uranus = CreateBody(0.05, 19.180, 30270, "uranus", "2k_uranus");
  72. Body neptune = CreateBody(0.05, 30.056, 59370, "neptune", "2k_neptune");
  73. Body pluto = CreateBody(0.05, 39.463, 89310, "pluto", "2k_eris_fictional");
  74. AddBodyChildren(&sun, &mercury);
  75. // AddBodyChildren(&sun, &venus);
  76. AddBodyChildren(&sun, &earth);
  77. // AddBodyChildren(&sun, &mars);
  78. // AddBodyChildren(&sun, &jupiter);
  79. // AddBodyChildren(&sun, &saturn);
  80. // AddBodyChildren(&sun, &uranus);
  81. // AddBodyChildren(&sun, &neptune);
  82. // AddBodyChildren(&sun, &pluto);
  83. AddBodyChildren(&earth, &moon);
  84. // Main game loop
  85. while (!WindowShouldClose()) // Detect window close button or ESC key
  86. {
  87. // Update
  88. //----------------------------------------------------------------------------------
  89. UpdateCamera(&camera);
  90. if (IsKeyPressed(KEY_G)) {
  91. gridEnabled = !gridEnabled;
  92. }
  93. if (IsKeyPressed(KEY_H)) {
  94. helpEnabled = !helpEnabled;
  95. }
  96. if (IsKeyPressed(KEY_L)) {
  97. labelEnabled = !labelEnabled;
  98. }
  99. if (IsKeyPressed(KEY_P)) {
  100. cameraParametersEnabled = !cameraParametersEnabled;
  101. }
  102. if (IsKeyPressed(KEY_LEFT)) {
  103. rotationSpeed -= 0.1;
  104. }
  105. if (IsKeyPressed(KEY_RIGHT)) {
  106. rotationSpeed += 0.1;
  107. }
  108. // Draw
  109. //----------------------------------------------------------------------------------
  110. BeginDrawing();
  111. ClearBackground(BLACK);
  112. BeginMode3D(camera);
  113. DrawBody(&sun, &camera);
  114. // Some reference elements (not affected by previous matrix transformations)
  115. if (gridEnabled) {
  116. DrawGrid(80, 1.0f);
  117. }
  118. EndMode3D();
  119. if (labelEnabled) {
  120. DrawLabels(&sun);
  121. }
  122. DrawText("FULL SOLAR SYSTEM", 400, 10, 20, YELLOW);
  123. text = FormatText("SPEED: %2.2f", rotationSpeed);
  124. DrawText(text, 1024 / 2 - MeasureText(text, 20) / 2, 30, 20, YELLOW);
  125. if (cameraParametersEnabled) {
  126. text = FormatText("Camera\nposition: [%3.3f, %3.3f, %3.3f]\ntarget: [%3.3f, %3.3f, %3.3f]\nup: [%3.3f, %3.3f, %3.3f]",
  127. camera.position.x, camera.position.y, camera.position.z,
  128. camera.target.x, camera.target.y, camera.target.z,
  129. camera.up.x, camera.up.y, camera.up.z);
  130. DrawText(text, 10, 50, 20, YELLOW);
  131. }
  132. if (helpEnabled) {
  133. DrawText("Keys:\n- [g] toggle grid\n- [h] toggle help\n- [l] toggle labels\n- [p] toggle camera parameters\n- [left/right arrows] increase/decrease speed by 0.1", 200, 200, 20, YELLOW);
  134. } else {
  135. DrawText("press [h] for help", 1016 - MeasureText("press [h] for help", 20), 740, 20, YELLOW);
  136. }
  137. DrawFPS(10, 10);
  138. EndDrawing();
  139. //----------------------------------------------------------------------------------
  140. }
  141. // De-Initialization
  142. //--------------------------------------------------------------------------------------
  143. CloseWindow(); // Close window and OpenGL context
  144. //--------------------------------------------------------------------------------------
  145. return 0;
  146. }
  147. //--------------------------------------------------------------------------------------------
  148. // Module Functions Definitions (local)
  149. //--------------------------------------------------------------------------------------------
  150. // Creates a new body
  151. Body CreateBody(float radius, float orbitRadius, float orbitPeriod, const char *label, const char *texture_name)
  152. {
  153. Body body;
  154. Texture2D texture = LoadTexture(FormatText("resources/solar_system/%s.png", texture_name));
  155. GenTextureMipmaps(&texture);
  156. body.label = label;
  157. body.radius = radius * 10;
  158. body.orbitRadius = orbitRadius * 10;
  159. body.orbitPeriod = orbitPeriod;
  160. body.model = LoadModel("resources/solar_system/sphere.obj");
  161. body.model.materials[0].maps[MAP_DIFFUSE].texture = texture;
  162. body.childrenCount = 0;
  163. body.orbitPosition = 0.0;
  164. return body;
  165. }
  166. void AddBodyChildren(Body *parent, Body *children) {
  167. if (parent->childrenCount >= MAX_BODY_CHILDREN) {
  168. TraceLog(LOG_ERROR, "BODY HAS TOO MANY CHILDREN");
  169. } else {
  170. parent->children[parent->childrenCount] = children;
  171. parent->childrenCount++;
  172. }
  173. }
  174. // Draw body and its children
  175. void DrawBody(Body *body, Camera *camera)
  176. {
  177. DrawModel(body->model, (Vector3) { 0.0f, 0.0f, 0.0f}, body->radius, WHITE);
  178. body->labelPosition = GetWorldToScreen((Vector3) { body->orbitRadius, body->radius, 0.0 }, *camera);
  179. for (int i = 0; i < body->childrenCount; i++) {
  180. Body *child = body->children[i];
  181. child->orbitPosition += rotationSpeed * 360 / child->orbitPeriod;
  182. rlPushMatrix();
  183. rlRotatef(child->orbitPosition, 0.0, 1.0, 0.0);
  184. rlTranslatef(child->orbitRadius, 0.0, 0.0);
  185. rlRotatef(-child->orbitPosition, 0.0, 1.0, 0.0);
  186. DrawBody(child, camera);
  187. rlPopMatrix();
  188. DrawCircle3D((Vector3){ 0.0f, 0.0f, 0.0f }, child->orbitRadius, (Vector3){ 1.0f, 0.0f, 0.0f }, 90.0f, GRAY);
  189. }
  190. }
  191. // Draw body label and its children labels
  192. void DrawLabels(Body *body)
  193. {
  194. DrawText(body->label, body->labelPosition.x - MeasureText(body->label, 20) / 2, body->labelPosition.y, 20, WHITE);
  195. for (int i = 0; i < body->childrenCount; i++) {
  196. Body *child = body->children[i];
  197. DrawLabels(child);
  198. }
  199. }