|
|
@ -0,0 +1,283 @@ |
|
|
|
/******************************************************************************************* |
|
|
|
* |
|
|
|
* raylib [models] example - rlgl module usage with push/pop matrix transformations |
|
|
|
* |
|
|
|
* This example uses [rlgl] module funtionality (pseudo-OpenGL 1.1 style coding) |
|
|
|
* |
|
|
|
* 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) 2018 Ramon Santamaria (@raysan5) |
|
|
|
* 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 loop |
|
|
|
Color color; // color of the body |
|
|
|
float orbitPosition; // current orbit 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, Color color, const char *label); // Initializes a new Body with the given parameters |
|
|
|
void AddBodyChildren(Body *parent, Body *children); // Add a children body to the parent body |
|
|
|
void DrawSphereBasic(Color color); // Draw sphere without any matrix transformation |
|
|
|
void DrawBody(Body *body, Camera *camera); // Draw body and its children, updating labelPosition |
|
|
|
void DrawLabels(Body *body); // Draw body label and its children labels |
|
|
|
|
|
|
|
//------------------------------------------------------------------------------------ |
|
|
|
// Program main entry point |
|
|
|
//------------------------------------------------------------------------------------ |
|
|
|
int main(void) |
|
|
|
{ |
|
|
|
// Initialization |
|
|
|
//-------------------------------------------------------------------------------------- |
|
|
|
const int screenWidth = 1024; |
|
|
|
const int screenHeight = 768; |
|
|
|
const char *text; |
|
|
|
bool gridEnabled = true; |
|
|
|
bool helpEnabled = false; |
|
|
|
bool labelEnabled = true; |
|
|
|
bool cameraParametersEnabled = true; |
|
|
|
|
|
|
|
InitWindow(screenWidth, screenHeight, "raylib [models] example - rlgl module usage with push/pop matrix transformations"); |
|
|
|
|
|
|
|
// Define the camera to look into our 3d world |
|
|
|
Camera camera = { 0 }; |
|
|
|
camera.position = (Vector3){ 8.0f, 8.0f, 8.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); |
|
|
|
|
|
|
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second |
|
|
|
//-------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
// Create Bodies |
|
|
|
Body sun = CreateBody(0.2, 0.0, 0, GOLD, "sun"); |
|
|
|
Body moon = CreateBody(0.05, 0.200, 24, GRAY, "moon"); |
|
|
|
Body mercury = CreateBody(0.05, 0.396, 90, GRAY, "mercury"); |
|
|
|
Body venus = CreateBody(0.05, 0.723, 210, MAGENTA, "venus"); |
|
|
|
Body earth = CreateBody(0.05, 1.000, 365, BLUE, "earth"); |
|
|
|
Body mars = CreateBody(0.05, 1.523, 690, RED, "mars"); |
|
|
|
Body jupiter = CreateBody(0.05, 5.200, 4260, BROWN, "jupiter"); |
|
|
|
Body saturn = CreateBody(0.05, 9.532, 10620, GREEN, "saturn"); |
|
|
|
Body uranus = CreateBody(0.05, 19.180, 30270, SKYBLUE, "uranus"); |
|
|
|
Body neptune = CreateBody(0.05, 30.056, 59370, PURPLE, "neptune"); |
|
|
|
Body pluto = CreateBody(0.05, 39.463, 89310, DARKGREEN, "pluto"); |
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
// Main game loop |
|
|
|
while (!WindowShouldClose()) // Detect window close button or ESC key |
|
|
|
{ |
|
|
|
// Update |
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|
UpdateCamera(&camera); |
|
|
|
|
|
|
|
if (IsKeyPressed(KEY_G)) { |
|
|
|
gridEnabled = !gridEnabled; |
|
|
|
} |
|
|
|
|
|
|
|
if (IsKeyPressed(KEY_H)) { |
|
|
|
helpEnabled = !helpEnabled; |
|
|
|
} |
|
|
|
|
|
|
|
if (IsKeyPressed(KEY_L)) { |
|
|
|
labelEnabled = !labelEnabled; |
|
|
|
} |
|
|
|
|
|
|
|
if (IsKeyPressed(KEY_P)) { |
|
|
|
cameraParametersEnabled = !cameraParametersEnabled; |
|
|
|
} |
|
|
|
|
|
|
|
if (IsKeyPressed(KEY_LEFT)) { |
|
|
|
rotationSpeed -= 0.1; |
|
|
|
} |
|
|
|
|
|
|
|
if (IsKeyPressed(KEY_RIGHT)) { |
|
|
|
rotationSpeed += 0.1; |
|
|
|
} |
|
|
|
|
|
|
|
// Draw |
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|
BeginDrawing(); |
|
|
|
|
|
|
|
ClearBackground(RAYWHITE); |
|
|
|
|
|
|
|
BeginMode3D(camera); |
|
|
|
|
|
|
|
DrawBody(&sun, &camera); |
|
|
|
|
|
|
|
// Some reference elements (not affected by previous matrix transformations) |
|
|
|
if (gridEnabled) { |
|
|
|
DrawGrid(80, 1.0f); |
|
|
|
} |
|
|
|
|
|
|
|
EndMode3D(); |
|
|
|
|
|
|
|
if (labelEnabled) { |
|
|
|
DrawLabels(&sun); |
|
|
|
} |
|
|
|
|
|
|
|
DrawText("FULL SOLAR SYSTEM", 400, 10, 20, MAROON); |
|
|
|
text = FormatText("SPEED: %2.2f", rotationSpeed); |
|
|
|
DrawText(text, 1024 / 2 - MeasureText(text, 20) / 2, 30, 20, MAROON); |
|
|
|
|
|
|
|
if (cameraParametersEnabled) { |
|
|
|
text = FormatText("Camera\nposition: [%3.3f, %3.3f, %3.3f]\ntarget: [%3.3f, %3.3f, %3.3f]\nup: [%3.3f, %3.3f, %3.3f]", |
|
|
|
camera.position.x, camera.position.y, camera.position.z, |
|
|
|
camera.target.x, camera.target.y, camera.target.z, |
|
|
|
camera.up.x, camera.up.y, camera.up.z); |
|
|
|
DrawText(text, 10, 50, 20, MAROON); |
|
|
|
} |
|
|
|
|
|
|
|
if (helpEnabled) { |
|
|
|
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); |
|
|
|
} else { |
|
|
|
DrawText("press [h] for help", 1016 - MeasureText("press [h] for help", 20), 740, 20, MAROON); |
|
|
|
} |
|
|
|
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, Color color, const char *label) |
|
|
|
{ |
|
|
|
Body body; |
|
|
|
|
|
|
|
body.label = label; |
|
|
|
body.radius = radius; |
|
|
|
body.orbitRadius = orbitRadius; |
|
|
|
body.orbitPeriod = orbitPeriod; |
|
|
|
body.color = color; |
|
|
|
body.childrenCount = 0; |
|
|
|
body.orbitPosition = 0.0; |
|
|
|
return body; |
|
|
|
} |
|
|
|
|
|
|
|
void AddBodyChildren(Body *parent, Body *children) { |
|
|
|
if (parent->childrenCount >= MAX_BODY_CHILDREN) { |
|
|
|
TraceLog(LOG_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) |
|
|
|
{ |
|
|
|
rlPushMatrix(); |
|
|
|
rlScalef(body->radius, body->radius, body->radius); // Scale Sun |
|
|
|
DrawSphereBasic(body->color); // Draw the body |
|
|
|
rlPopMatrix(); |
|
|
|
|
|
|
|
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, child->color); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Draw body label and its children labels |
|
|
|
void DrawLabels(Body *body) |
|
|
|
{ |
|
|
|
DrawText(body->label, body->labelPosition.x - MeasureText(body->label, 20) / 2, body->labelPosition.y, 20, BLACK); |
|
|
|
|
|
|
|
for (int i = 0; i < body->childrenCount; i++) { |
|
|
|
Body *child = body->children[i]; |
|
|
|
|
|
|
|
DrawLabels(child); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Draw sphere without any matrix transformation |
|
|
|
// NOTE: Sphere is drawn in world position ( 0, 0, 0 ) with radius 1.0f |
|
|
|
void DrawSphereBasic(Color color) |
|
|
|
{ |
|
|
|
int rings = 16; |
|
|
|
int slices = 16; |
|
|
|
|
|
|
|
rlBegin(RL_TRIANGLES); |
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a); |
|
|
|
|
|
|
|
for (int i = 0; i < (rings + 2); i++) |
|
|
|
{ |
|
|
|
for (int j = 0; j < slices; j++) |
|
|
|
{ |
|
|
|
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), |
|
|
|
sinf(DEG2RAD*(270+(180/(rings + 1))*i)), |
|
|
|
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); |
|
|
|
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), |
|
|
|
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), |
|
|
|
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); |
|
|
|
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)), |
|
|
|
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), |
|
|
|
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices))); |
|
|
|
|
|
|
|
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), |
|
|
|
sinf(DEG2RAD*(270+(180/(rings + 1))*i)), |
|
|
|
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); |
|
|
|
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360/slices)), |
|
|
|
sinf(DEG2RAD*(270+(180/(rings + 1))*(i))), |
|
|
|
cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360/slices))); |
|
|
|
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), |
|
|
|
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), |
|
|
|
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); |
|
|
|
} |
|
|
|
} |
|
|
|
rlEnd(); |
|
|
|
} |