/******************************************************************************************* * * raylib [models] example - full solar system * * This example has been created using raylib 2.5 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2019 Aldrin Martoq (@aldrinmartoq) * ********************************************************************************************/ #include "raylib.h" #include "rlgl.h" #define MAX_BODY_CHILDREN 10 float rotationSpeed = 0.2; // A celestial body that has children bodies orbiting around typedef struct Body { const char *label; // label of the body, for ex: moon float radius; // object radius float orbitRadius; // orbit average radius float orbitPeriod; // time the body takes to do a full orbit loop float rotationPeriod; // time the body takes to do a full rotation on itself Texture2D texture; // texture of the body Model model; // model of the body float orbitPosition; // current orbit position float rotationPosition; // current rotation position Vector2 labelPosition; // label position in screen struct Body *children[MAX_BODY_CHILDREN]; // children array int childrenCount; // children count } Body; //------------------------------------------------------------------------------------ // Module Functions Declaration //------------------------------------------------------------------------------------ Body CreateBody(float radius, float orbitRadius, float orbitPeriod, const char *label, const char *texture); // Initializes a new Body with the given parameters void AddBodyChildren(Body *parent, Body *children); // Add a children body to the parent body void DrawBody(Body *body, Camera *camera); // Draw body and its children, updating labelPosition void DrawBodyLabel(Body *body); // Draw body label and its children labels //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ int main(void) { // Initialization //-------------------------------------------------------------------------------------- const int screenWidth = 800; const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [models] example - solar system"); // Define the camera to look into our 3d world Camera camera = { 0 }; camera.position = (Vector3){ 20.0f, 12.0f, 20.0f }; camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; camera.fovy = 45.0f; camera.type = CAMERA_PERSPECTIVE; SetCameraMode(camera, CAMERA_FREE); // Create Bodies Body sun = CreateBody(0.2, 0.0, 0, "sun", "2k_sun"); Body moon = CreateBody(0.02, 0.200, 24, "moon", "2k_moon"); Body mercury = CreateBody(0.05, 0.396, 90, "mercury", "2k_mercury"); Body venus = CreateBody(0.05, 0.723, 210, "venus", "2k_venus_atmosphere"); Body earth = CreateBody(0.05, 1.000, 365, "earth", "2k_earth_daymap"); Body mars = CreateBody(0.05, 1.523, 690, "mars", "2k_mars"); Body jupiter = CreateBody(0.05, 5.200, 4260, "jupiter", "2k_jupiter"); Body saturn = CreateBody(0.05, 9.532, 10620, "saturn", "2k_saturn"); Body uranus = CreateBody(0.05, 19.180, 30270, "uranus", "2k_uranus"); Body neptune = CreateBody(0.05, 30.056, 59370, "neptune", "2k_neptune"); Body pluto = CreateBody(0.05, 39.463, 89310, "pluto", "2k_eris_fictional"); AddBodyChildren(&sun, &mercury); AddBodyChildren(&sun, &venus); AddBodyChildren(&sun, &earth); AddBodyChildren(&sun, &mars); // AddBodyChildren(&sun, &jupiter); // AddBodyChildren(&sun, &saturn); // AddBodyChildren(&sun, &uranus); // AddBodyChildren(&sun, &neptune); // AddBodyChildren(&sun, &pluto); AddBodyChildren(&earth, &moon); bool showHelpMenu = false; bool showBodyLabels = true; 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); if (IsKeyPressed(KEY_H)) showHelpMenu = !showHelpMenu; if (IsKeyPressed(KEY_L)) showBodyLabels = !showBodyLabels; if (IsKeyPressed(KEY_LEFT)) rotationSpeed -= 0.1; if (IsKeyPressed(KEY_RIGHT)) rotationSpeed += 0.1; //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); ClearBackground(BLACK); BeginMode3D(camera); // NOTE: DrawBody calls recusively body childrens DrawBody(&sun, &camera); EndMode3D(); if (showBodyLabels) DrawBodyLabel(&sun); DrawText(FormatText("FULL SOLAR SYSTEM - SPEED: %2.2f", rotationSpeed), 120, 10, 20, LIME); if (showHelpMenu) DrawText("- [h] Toggle help\n- [l] Toggle labels\n- [left/right arrows] Increase/decrease rotation speed", 10, 40, 10, GREEN); else DrawText("Press [h] for help", 10, 40, 10, GREEN); DrawFPS(10, 10); EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; } //-------------------------------------------------------------------------------------------- // Module Functions Definitions (local) //-------------------------------------------------------------------------------------------- // Creates a new body Body CreateBody(float radius, float orbitRadius, float orbitPeriod, const char *label, const char *texture_name) { Body body = { 0 }; Texture2D texture = LoadTexture(FormatText("resources/solar_system/%s.png", texture_name)); // GenImageCellular() GenTextureMipmaps(&texture); body.label = label; body.radius = radius * 10; body.orbitRadius = orbitRadius * 10; body.orbitPeriod = orbitPeriod; body.model = LoadModel("resources/solar_system/sphere.obj"); // GenMeshSphere() body.model.materials[0].maps[MAP_DIFFUSE].texture = texture; body.childrenCount = 0; body.orbitPosition = 0.0; return body; } void AddBodyChildren(Body *parent, Body *children) { if (parent->childrenCount >= MAX_BODY_CHILDREN) TraceLog(LOG_ERROR, "ERROR: Body has too many children!"); else { parent->children[parent->childrenCount] = children; parent->childrenCount++; } } // Draw body and its children void DrawBody(Body *body, Camera *camera) { DrawModel(body->model, (Vector3){ 0.0f, 0.0f, 0.0f}, body->radius, WHITE); // TODO: labelPosition is not transformed to drawing position body->labelPosition = GetWorldToScreen((Vector3){ body->orbitRadius, body->radius, 0.0 }, *camera); for (int i = 0; i < body->childrenCount; i++) { Body *child = body->children[i]; child->orbitPosition += rotationSpeed*360/child->orbitPeriod; rlPushMatrix(); rlRotatef(child->orbitPosition, 0.0, 1.0, 0.0); rlTranslatef(child->orbitRadius, 0.0, 0.0); rlRotatef(-child->orbitPosition, 0.0, 1.0, 0.0); DrawBody(child, camera); rlPopMatrix(); DrawCircle3D((Vector3){ 0.0f, 0.0f, 0.0f }, child->orbitRadius, (Vector3){ 1.0f, 0.0f, 0.0f }, 90.0f, GRAY); } } // Draw body label and its children labels void DrawBodyLabel(Body *body) { DrawText(body->label, body->labelPosition.x - MeasureText(body->label, 20)/2, body->labelPosition.y, 20, WHITE); for (int i = 0; i < body->childrenCount; i++) { Body *child = body->children[i]; DrawBodyLabel(child); } }