cs381/as4/as3.cpp

186 lines
5.3 KiB
C++

#include "AudioDevice.hpp"
#include "Color.hpp"
#include "Keyboard.hpp"
#include "Matrix.hpp"
#include "Mesh.hpp"
#include "Model.hpp"
#include "raylib.h"
#include <raylib-cpp.hpp>
#include <cmath>
#include <algorithm>
#include <iostream>
#define SKYBOX_IMPLEMENTATION
#include "skybox.hpp"
void DrawBoundedModel(raylib::Model &model, auto transformer) {
// store the original transform to apply a different transform to the
// model without affecting the next time we draw
raylib::Matrix oldTransform = model.GetTransform();
// apply the transform that we get from whatever the transformer callback
// gives us
raylib::Matrix transform = transformer(model.GetTransform());
// apply the transform that we got from the transformer to the model
model.SetTransform(transform);
// draw the model, passing the origin and default scale as arguments since
// the transform is already applied to the model
model.Draw({ 0, 0, 0 }, 1.0f, raylib::Color::White());
// get the bounding box of the model after applying the transform
auto box = model.GetTransformedBoundingBox();
// draw the bounding box of the model using raylib's built in function
DrawBoundingBox(box, raylib::Color::White());
// restore the model's transform to its original state so that the next time we
// draw the model, it doesn't have the previous transform applied to it
model.SetTransform(oldTransform);
}
struct Entity {
enum Type {
Penguin = 0,
Eagle = 1,
} type;
raylib::Vector3 position;
raylib::Vector3 velocity;
raylib::Degree heading;
};
int main() {
raylib::Window window(800, 600, "CS381 - Assignment 3");
window.SetState(FLAG_WINDOW_RESIZABLE);
raylib::AudioDevice audio;
raylib::Model penguin("models/penguin.glb");
// behind and above the penguin (in penguin-local space)
const float CAM_DIST = 512.0f;
const float CAM_HEIGHT = 256.0f;
const float CAM_ANGULAR_VELOCITY = 2.0f;
const float CAM_PITCH_MIN = -0.5f;
const float CAM_PITCH_MAX = 1.5f;
float camYaw = 3.14f; // offset by 90 deg so it faces in the proper direction
float camPitch = 0;
raylib::Camera3D camera(
{ 0, CAM_DIST * std::sin(camPitch), CAM_DIST * std::cos(camPitch) },
{ 0, 0, 0 },
{ 0, 1, 0 },
45.0f);
raylib::Model ground = raylib::Mesh::Plane(10000, 10000, 50, 50, 25);
raylib::Texture snowTexture("textures/snow.jpg");
ground.GetMaterials()[0].maps[MATERIAL_MAP_DIFFUSE].texture = snowTexture;
cs381::SkyBox skybox("textures/skybox.png");
std::vector<Entity> entities;
auto &e = entities.emplace_back(Entity::Penguin, raylib::Vector3 { 0, 0, 0 }, raylib::Vector3 { 0, 0, 0 }, 0);
// penguin physics
raylib::Vector3 position = { 0, 0, 0 };
raylib::Vector3 velocity = { 0, 0, 0 };
float heading = 0.0f;
float speed = 0.0f;
// units/s
const float ACCELERATION = 100.0f;
// in radians
const float ANGULAR_VELOCITY = 3.14f;
window.SetTargetFPS(60); // save cpu cycles
while (!window.ShouldClose()) {
window.BeginDrawing();
window.ClearBackground(raylib::Color::Gray());
float dt = window.GetFrameTime();
position += velocity * dt * 0.5f;
// movement for penguin
if (IsKeyDown(KEY_W)) {
speed += ACCELERATION * dt;
}
if (IsKeyDown(KEY_S)) {
speed -= ACCELERATION * dt;
}
if (IsKeyDown(KEY_A)) {
heading += ANGULAR_VELOCITY * dt;
}
if (IsKeyDown(KEY_D)) {
heading -= ANGULAR_VELOCITY * dt;
}
if (IsKeyDown(KEY_SPACE)) {
speed = 0.0f;
}
velocity = raylib::Vector3 {
std::sin(heading) * speed,
0.0f,
std::cos(heading) * speed
};
// ds = 1/2 * (v0 + v1) * dt
position += velocity * dt * 0.5f;
// movement for camera
if (IsKeyDown(KEY_LEFT)) {
camYaw += CAM_ANGULAR_VELOCITY * dt;
}
if (IsKeyDown(KEY_RIGHT)) {
camYaw -= CAM_ANGULAR_VELOCITY * dt;
}
if (IsKeyDown(KEY_UP)) {
camPitch += CAM_ANGULAR_VELOCITY * dt;
}
if (IsKeyDown(KEY_DOWN)) {
camPitch -= CAM_ANGULAR_VELOCITY * dt;
}
// clamp the angle between
camPitch = std::clamp(camPitch, CAM_PITCH_MIN, CAM_PITCH_MAX);
// x = cos(pitch) * sin(yaw)
// y = sin(pitch)
// z = cos(pitch) * cos(yaw)
float yaw = camYaw + heading; // follow penguin
raylib::Vector3 camOffset = {
CAM_DIST * std::cos(camPitch) * std::sin(yaw),
CAM_DIST * std::sin(camPitch) + CAM_HEIGHT,
CAM_DIST * std::cos(camPitch) * std::cos(yaw)
};
camera.SetPosition(position + camOffset);
camera.SetTarget(position);
camera.BeginMode();
skybox.Draw();
ground.Draw({ 0, 0, 0 }, 1.0f, raylib::Color::White());
DrawBoundedModel(penguin, [&position, &heading](raylib::Matrix transform) {
return transform
.RotateY(heading)
.Scale(40, 40, 40)
.Translate(position);
});
camera.EndMode();
window.EndDrawing();
}
return 0;
}