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.

283 lines
11 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib [models] example - rlgl module usage with push/pop matrix transformations
  4. *
  5. * This example uses [rlgl] module funtionality (pseudo-OpenGL 1.1 style coding)
  6. *
  7. * This example has been created using raylib 2.5 (www.raylib.com)
  8. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  9. *
  10. * Copyright (c) 2018 Ramon Santamaria (@raysan5)
  11. * Copyright (c) 2019 Aldrin Martoq (@aldrinmartoq)
  12. *
  13. ********************************************************************************************/
  14. #include "raylib.h"
  15. #include "rlgl.h"
  16. #define MAX_BODY_CHILDREN 10
  17. float rotationSpeed = 0.2;
  18. // A celestial body that has children bodies orbiting around
  19. typedef struct Body {
  20. const char *label; // label of the body, for ex: moon
  21. float radius; // object radius
  22. float orbitRadius; // orbit average radius
  23. float orbitPeriod; // time the body takes to do a full loop
  24. Color color; // color of the body
  25. float orbitPosition; // current orbit 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, Color color, const char *label); // 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 DrawSphereBasic(Color color); // Draw sphere without any matrix transformation
  36. void DrawBody(Body *body, Camera *camera); // Draw body and its children, updating labelPosition
  37. void DrawLabels(Body *body); // Draw body label and its children labels
  38. //------------------------------------------------------------------------------------
  39. // Program main entry point
  40. //------------------------------------------------------------------------------------
  41. int main(void)
  42. {
  43. // Initialization
  44. //--------------------------------------------------------------------------------------
  45. const int screenWidth = 1024;
  46. const int screenHeight = 768;
  47. const char *text;
  48. bool gridEnabled = true;
  49. bool helpEnabled = false;
  50. bool labelEnabled = true;
  51. bool cameraParametersEnabled = true;
  52. InitWindow(screenWidth, screenHeight, "raylib [models] example - rlgl module usage with push/pop matrix transformations");
  53. // Define the camera to look into our 3d world
  54. Camera camera = { 0 };
  55. camera.position = (Vector3){ 8.0f, 8.0f, 8.0f };
  56. camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
  57. camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
  58. camera.fovy = 45.0f;
  59. camera.type = CAMERA_PERSPECTIVE;
  60. SetCameraMode(camera, CAMERA_FREE);
  61. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  62. //--------------------------------------------------------------------------------------
  63. // Create Bodies
  64. Body sun = CreateBody(0.2, 0.0, 0, GOLD, "sun");
  65. Body moon = CreateBody(0.05, 0.200, 24, GRAY, "moon");
  66. Body mercury = CreateBody(0.05, 0.396, 90, GRAY, "mercury");
  67. Body venus = CreateBody(0.05, 0.723, 210, MAGENTA, "venus");
  68. Body earth = CreateBody(0.05, 1.000, 365, BLUE, "earth");
  69. Body mars = CreateBody(0.05, 1.523, 690, RED, "mars");
  70. Body jupiter = CreateBody(0.05, 5.200, 4260, BROWN, "jupiter");
  71. Body saturn = CreateBody(0.05, 9.532, 10620, GREEN, "saturn");
  72. Body uranus = CreateBody(0.05, 19.180, 30270, SKYBLUE, "uranus");
  73. Body neptune = CreateBody(0.05, 30.056, 59370, PURPLE, "neptune");
  74. Body pluto = CreateBody(0.05, 39.463, 89310, DARKGREEN, "pluto");
  75. AddBodyChildren(&sun, &mercury);
  76. AddBodyChildren(&sun, &venus);
  77. AddBodyChildren(&sun, &earth);
  78. AddBodyChildren(&sun, &mars);
  79. AddBodyChildren(&sun, &jupiter);
  80. AddBodyChildren(&sun, &saturn);
  81. AddBodyChildren(&sun, &uranus);
  82. AddBodyChildren(&sun, &neptune);
  83. AddBodyChildren(&sun, &pluto);
  84. AddBodyChildren(&earth, &moon);
  85. // Main game loop
  86. while (!WindowShouldClose()) // Detect window close button or ESC key
  87. {
  88. // Update
  89. //----------------------------------------------------------------------------------
  90. UpdateCamera(&camera);
  91. if (IsKeyPressed(KEY_G)) {
  92. gridEnabled = !gridEnabled;
  93. }
  94. if (IsKeyPressed(KEY_H)) {
  95. helpEnabled = !helpEnabled;
  96. }
  97. if (IsKeyPressed(KEY_L)) {
  98. labelEnabled = !labelEnabled;
  99. }
  100. if (IsKeyPressed(KEY_P)) {
  101. cameraParametersEnabled = !cameraParametersEnabled;
  102. }
  103. if (IsKeyPressed(KEY_LEFT)) {
  104. rotationSpeed -= 0.1;
  105. }
  106. if (IsKeyPressed(KEY_RIGHT)) {
  107. rotationSpeed += 0.1;
  108. }
  109. // Draw
  110. //----------------------------------------------------------------------------------
  111. BeginDrawing();
  112. ClearBackground(RAYWHITE);
  113. BeginMode3D(camera);
  114. DrawBody(&sun, &camera);
  115. // Some reference elements (not affected by previous matrix transformations)
  116. if (gridEnabled) {
  117. DrawGrid(80, 1.0f);
  118. }
  119. EndMode3D();
  120. if (labelEnabled) {
  121. DrawLabels(&sun);
  122. }
  123. DrawText("FULL SOLAR SYSTEM", 400, 10, 20, MAROON);
  124. text = FormatText("SPEED: %2.2f", rotationSpeed);
  125. DrawText(text, 1024 / 2 - MeasureText(text, 20) / 2, 30, 20, MAROON);
  126. if (cameraParametersEnabled) {
  127. text = FormatText("Camera\nposition: [%3.3f, %3.3f, %3.3f]\ntarget: [%3.3f, %3.3f, %3.3f]\nup: [%3.3f, %3.3f, %3.3f]",
  128. camera.position.x, camera.position.y, camera.position.z,
  129. camera.target.x, camera.target.y, camera.target.z,
  130. camera.up.x, camera.up.y, camera.up.z);
  131. DrawText(text, 10, 50, 20, MAROON);
  132. }
  133. if (helpEnabled) {
  134. 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, MAROON);
  135. } else {
  136. DrawText("press [h] for help", 1016 - MeasureText("press [h] for help", 20), 740, 20, MAROON);
  137. }
  138. DrawFPS(10, 10);
  139. EndDrawing();
  140. //----------------------------------------------------------------------------------
  141. }
  142. // De-Initialization
  143. //--------------------------------------------------------------------------------------
  144. CloseWindow(); // Close window and OpenGL context
  145. //--------------------------------------------------------------------------------------
  146. return 0;
  147. }
  148. //--------------------------------------------------------------------------------------------
  149. // Module Functions Definitions (local)
  150. //--------------------------------------------------------------------------------------------
  151. // Creates a new body
  152. Body CreateBody(float radius, float orbitRadius, float orbitPeriod, Color color, const char *label)
  153. {
  154. Body body;
  155. body.label = label;
  156. body.radius = radius;
  157. body.orbitRadius = orbitRadius;
  158. body.orbitPeriod = orbitPeriod;
  159. body.color = color;
  160. body.childrenCount = 0;
  161. body.orbitPosition = 0.0;
  162. return body;
  163. }
  164. void AddBodyChildren(Body *parent, Body *children) {
  165. if (parent->childrenCount >= MAX_BODY_CHILDREN) {
  166. TraceLog(LOG_ERROR, "BODY HAS TOO MANY CHILDREN");
  167. } else {
  168. parent->children[parent->childrenCount] = children;
  169. parent->childrenCount++;
  170. }
  171. }
  172. // Draw body and its children
  173. void DrawBody(Body *body, Camera *camera)
  174. {
  175. rlPushMatrix();
  176. rlScalef(body->radius, body->radius, body->radius); // Scale Sun
  177. DrawSphereBasic(body->color); // Draw the body
  178. rlPopMatrix();
  179. body->labelPosition = GetWorldToScreen((Vector3) { body->orbitRadius, body->radius, 0.0 }, *camera);
  180. for (int i = 0; i < body->childrenCount; i++) {
  181. Body *child = body->children[i];
  182. child->orbitPosition += rotationSpeed * 360 / child->orbitPeriod;
  183. rlPushMatrix();
  184. rlRotatef(child->orbitPosition, 0.0, 1.0, 0.0);
  185. rlTranslatef(child->orbitRadius, 0.0, 0.0);
  186. rlRotatef(-child->orbitPosition, 0.0, 1.0, 0.0);
  187. DrawBody(child, camera);
  188. rlPopMatrix();
  189. DrawCircle3D((Vector3){ 0.0f, 0.0f, 0.0f }, child->orbitRadius, (Vector3){ 1.0f, 0.0f, 0.0f }, 90.0f, child->color);
  190. }
  191. }
  192. // Draw body label and its children labels
  193. void DrawLabels(Body *body)
  194. {
  195. DrawText(body->label, body->labelPosition.x - MeasureText(body->label, 20) / 2, body->labelPosition.y, 20, BLACK);
  196. for (int i = 0; i < body->childrenCount; i++) {
  197. Body *child = body->children[i];
  198. DrawLabels(child);
  199. }
  200. }
  201. // Draw sphere without any matrix transformation
  202. // NOTE: Sphere is drawn in world position ( 0, 0, 0 ) with radius 1.0f
  203. void DrawSphereBasic(Color color)
  204. {
  205. int rings = 16;
  206. int slices = 16;
  207. rlBegin(RL_TRIANGLES);
  208. rlColor4ub(color.r, color.g, color.b, color.a);
  209. for (int i = 0; i < (rings + 2); i++)
  210. {
  211. for (int j = 0; j < slices; j++)
  212. {
  213. rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
  214. sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
  215. cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
  216. rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
  217. sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
  218. cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
  219. rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)),
  220. sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
  221. cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices)));
  222. rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)),
  223. sinf(DEG2RAD*(270+(180/(rings + 1))*i)),
  224. cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices)));
  225. rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360/slices)),
  226. sinf(DEG2RAD*(270+(180/(rings + 1))*(i))),
  227. cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360/slices)));
  228. rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)),
  229. sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))),
  230. cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices)));
  231. }
  232. }
  233. rlEnd();
  234. }