master
John Montagu, the 4th Earl of Sandvich 2026-02-15 23:39:05 -08:00
parent 85512eb243
commit 9c95672bee
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
3 changed files with 207 additions and 0 deletions

16
as2/CMakeLists.txt 100644
View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.18)
project(as2 CXX)
set(CMAKE_CXX_STANDARD 20)
# adding this option to make clangd work
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_subdirectory(../raylib-cpp raylib)
add_executable(as2 as2.cpp)
target_link_libraries(as2 PUBLIC raylib raylib_cpp)
configure_file(../assets/models/penguin.glb models/penguin.glb COPYONLY)
configure_file(../assets/models/eagle.glb models/eagle.glb COPYONLY)

65
as2/README.md 100644
View File

@ -0,0 +1,65 @@
# Building and Running
Clone the repository, navigate to the root of the project, and initialize the
submodules:
```sh
git clone https://github.com/humanoidsandvichdispenser/cs381.git
cd cs381
git submodule update --init --recursive
```
Navigate to the `as2` directory, create a build directory, and run CMake to
generate the build files:
```sh
cd as2
mkdir -p build
cd build
cmake ..
```
Compile the code using `make`:
```sh
make
```
This should create an executable named `as2` in the `build` directory. You can
run the executable with the following command:
```sh
./as2
```
# Extra credit
The models spin at a rate of 10 degrees per second.
# Readme Question
The `DrawBoundedModel` function takes a model and transformer lambda function
as parameters. We use this because the lambda defines the transformation for
this particular draw call without affecting the model's original transformation
matrix. This allows us to apply different transformations to the same model
when drawing it multiple times. It also consistently draws the model with a
bounding box that respects the transformations. The function does both of these
operations atomically, so you don't have to worry about forgetting to apply the
transform or draw the bounding box separately.
The same function could be used in the future after the model has been loaded
to apply transforms that are not known at load time and temporary transforms
that only apply under specific conditions. For example, we could make the model
spin by constantly applying a transformation on the identity transform with a
rotation value that changes over time that only applies if a specific key is
being held.
The same function can also be used for transforms relative to the parent. In
the lambda, we could multiply the transform passed to the function by a parent
transform to get a final transform that is relative to the parent.
The leftmost penguin looks funny because the model only has half of the
penguin. In its default orientation, the faces of the model are away from the
camera (the surface normal points away), so the back faces are culled and the
model almost appears invisible. When the model is rotated, the faces are no
longer culled and the model looks normal.

126
as2/as2.cpp 100644
View File

@ -0,0 +1,126 @@
#include "Color.hpp"
#include "Keyboard.hpp"
#include "Matrix.hpp"
#include "Model.hpp"
#include "raylib.h"
#include <raylib-cpp.hpp>
#include <iostream>
static bool scaleModel = false;
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());
// default scale doesn't render correctly, so scale the model by 10 if the
// spacebar is pressed
if (scaleModel) {
transform = transform.Scale(10);
}
// 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);
}
int main() {
raylib::Window window(800, 600, "CS381 - Assignment 2");
window.SetState(FLAG_WINDOW_RESIZABLE);
raylib::Model penguin("models/penguin.glb");
raylib::Model eagle("models/eagle.glb");
raylib::Camera3D camera(
{ 0, 120, 500 },
{ 0, 0, -1 },
{ 0, 1, 0 },
45.0f);
window.SetTargetFPS(60); // save cpu cycles
while (!window.ShouldClose()) {
window.BeginDrawing();
window.ClearBackground(raylib::Color::Gray());
camera.BeginMode();
if (raylib::Keyboard::IsKeyPressed(KEY_SPACE)) {
scaleModel = !scaleModel;
}
// in addition to the required transforms, the models will rotate 10
// degrees per second (extra credit), and the penguin is scaled by 30
// eagle scaled by 10
// Draw one eagle located at (0, 0, 0), default scale, and with default
// orientation (10 points).
DrawBoundedModel(eagle, [](raylib::Matrix transform) {
return transform
.RotateY(GetTime() * raylib::Degree(10.0f))
.Scale(10.0);
});
// Draw one eagle located at (100, 100, 0), scaled by (1, 1, 1), and
// yawed by 180 degrees (10 points).
DrawBoundedModel(eagle, [](raylib::Matrix transform) {
return transform
.Translate(-100.0f, 100.0f, 0.0f)
.Scale(1.0f, -1.0f, 1.0f)
.RotateY(raylib::Degree(180.0f))
.Scale(10.0)
.RotateY(GetTime() * raylib::Degree(10.0f));
});
// Draw one penguin located at (200, 0, 0) with default orientation (10
// points).
DrawBoundedModel(penguin, [](raylib::Matrix transform) {
return transform
.Translate(-200.0f, 0.0f, 0.0f)
.Scale(30.0f);
});
// Draw one penguin located at (200, 0, 0) and be yawed 90 degrees (10
// points).
DrawBoundedModel(penguin, [](raylib::Matrix transform) {
return transform
.Translate(200.0f, 0.0f, 0.0f)
.RotateY(raylib::Degree(90.0f))
.Scale(30.0)
.RotateY(GetTime() * raylib::Degree(10.0f));
});
// Penguin 3: at (100,100,0), scaled by (1,2,1) and yawed 270 degrees
DrawBoundedModel(penguin, [](raylib::Matrix transform) {
return transform
.Translate(100.0f, 100.0f, 0.0f)
.Scale(1.0f, 2.0f, 1.0f)
.RotateY(raylib::Degree(270.0f))
.Scale(30.0)
.RotateY(GetTime() * raylib::Degree(10.0f));
});
camera.EndMode();
window.EndDrawing();
}
return 0;
}