main.c (4472B)
1 #include <float.h> 2 #include <math.h> 3 #include <raylib.h> 4 #include <raymath.h> 5 #include <stdlib.h> 6 7 #include "config.h" 8 #include "physics.h" 9 #include "player.h" 10 #define SQR(x) ((x) * (x)) 11 12 Triangle *BuildTriangleCache(Model *model, int *outCount) { 13 int total = 0; 14 for (int m = 0; m < model->meshCount; m++) 15 total += model->meshes[m].triangleCount; 16 17 Triangle *tris = malloc(sizeof(Triangle) * total); 18 int t = 0; 19 20 for (int m = 0; m < model->meshCount; m++) { 21 Mesh mesh = model->meshes[m]; 22 float *v = mesh.vertices; 23 unsigned short *idx = mesh.indices; 24 25 for (int i = 0; i < mesh.triangleCount; i++) { 26 Vector3 a = {v[idx[i * 3 + 0] * 3 + 0], v[idx[i * 3 + 0] * 3 + 1], 27 v[idx[i * 3 + 0] * 3 + 2]}; 28 Vector3 b = {v[idx[i * 3 + 1] * 3 + 0], v[idx[i * 3 + 1] * 3 + 1], 29 v[idx[i * 3 + 1] * 3 + 2]}; 30 Vector3 c = {v[idx[i * 3 + 2] * 3 + 0], v[idx[i * 3 + 2] * 3 + 1], 31 v[idx[i * 3 + 2] * 3 + 2]}; 32 33 Vector3 normal = Vector3Normalize( 34 Vector3CrossProduct(Vector3Subtract(b, a), Vector3Subtract(c, a))); 35 36 Vector3 min = {fminf(a.x, fminf(b.x, c.x)), fminf(a.y, fminf(b.y, c.y)), 37 fminf(a.z, fminf(b.z, c.z))}; 38 Vector3 max = {fmaxf(a.x, fmaxf(b.x, c.x)), fmaxf(a.y, fmaxf(b.y, c.y)), 39 fmaxf(a.z, fmaxf(b.z, c.z))}; 40 41 tris[t++] = (Triangle){a, b, c, normal, min, max}; 42 } 43 } 44 45 *outCount = total; 46 return tris; 47 } 48 49 void UpdatePlayerCamera(Camera3D *c, Player *p, float deltaTime) { 50 static float smoothHeight = 0.0f; 51 smoothHeight += (p->height - smoothHeight) * CROUCH_LERP_SPEED * deltaTime; 52 53 Vector3 eyePos = {p->pos.x, p->pos.y + smoothHeight, p->pos.z}; 54 c->position = eyePos; 55 56 Vector3 forward = {cosf(p->rot.y) * sinf(p->rot.z), sinf(p->rot.y), 57 cosf(p->rot.y) * cosf(p->rot.z)}; 58 59 c->target = Vector3Add(eyePos, forward); 60 61 Vector3 targetUp = Vector3RotateByAxisAngle(UP, forward, p->rot.x); 62 float upLerpSpeed = 0.1f; 63 c->up = Vector3Lerp(c->up, targetUp, upLerpSpeed); 64 } 65 66 int main(void) { 67 InitWindow(WIDTH, HEIGHT, "Sphere Character Controller"); 68 DisableCursor(); 69 SetTargetFPS(TARGET_FPS); 70 SetConfigFlags(FLAG_VSYNC_HINT); 71 72 Camera3D camera = {.position = {0, 0, 0}, 73 .target = {0, 0, 1}, 74 .up = UP, 75 .fovy = BASE_FOV, 76 .projection = CAMERA_PERSPECTIVE}; 77 78 Model model = LoadModel("assets/level.glb"); 79 80 int triCount = 0; 81 Triangle *triangles = BuildTriangleCache(&model, &triCount); 82 83 static Player player; 84 static enum Input input; 85 player.vel = Vector3Zero(); 86 player.pos = Vector3Zero(); 87 player.height = PLAYER_HEIGHT; 88 player.radius = PLAYER_RADIUS; 89 player.grounded = false; 90 91 while (!WindowShouldClose()) { 92 float dt = GetFrameTime(); 93 Vector2 md = GetMouseDelta(); 94 95 player.rot.z -= md.x * MOUSE_SENSITIVITY; 96 player.rot.y -= md.y * MOUSE_SENSITIVITY; 97 player.rot.y = Clamp(player.rot.y, -MAX_PITCH, MAX_PITCH); 98 99 input = 0; 100 if (IsKeyDown(KEY_W)) 101 input |= INPUT_FORWARD; 102 if (IsKeyDown(KEY_S)) 103 input |= INPUT_BACKWARD; 104 if (IsKeyDown(KEY_A)) 105 input |= INPUT_LEFT; 106 if (IsKeyDown(KEY_D)) 107 input |= INPUT_RIGHT; 108 if (IsKeyDown(KEY_C)) 109 input |= INPUT_CROUCH; 110 if (IsKeyDown(KEY_LEFT_SHIFT)) 111 input |= INPUT_SPRINT; 112 if (IsKeyDown(KEY_SPACE)) 113 input |= INPUT_JUMP; 114 115 if (IsKeyPressed(KEY_R)) 116 player.pos = player.vel = Vector3Zero(); 117 118 PlayerUpdate(&player, input, dt); 119 player.vel.y -= GRAVITY * dt; 120 PlayerApplyFriction(&player, dt); 121 PlayerApplyAcceleration(&player, input, dt); 122 player.pos = Vector3Add(player.pos, Vector3Scale(player.vel, dt)); 123 ResolveCollisions(&player, triangles, triCount); 124 UpdatePlayerCamera(&camera, &player, dt); 125 126 BeginDrawing(); 127 ClearBackground(RAYWHITE); 128 BeginMode3D(camera); 129 130 DrawModel(model, Vector3Zero(), 1.0f, WHITE); 131 132 EndMode3D(); 133 134 DrawText(TextFormat("Pos: %.2f %.2f %.2f", player.pos.x, player.pos.y, 135 player.pos.z), 136 10, 10, 20, BLACK); 137 138 DrawText(TextFormat("Vel: %.4f %.4f %.4f", player.vel.x, player.vel.y, 139 player.vel.z), 140 10, 30, 20, BLACK); 141 142 DrawText(TextFormat("Grounded: %b", player.grounded), 10, 50, 20, BLACK); 143 144 EndDrawing(); 145 } 146 147 UnloadModel(model); 148 free(triangles); 149 CloseWindow(); 150 return 0; 151 }