Skip to content

Commit

Permalink
docs(engine): cleanup and document cars sample
Browse files Browse the repository at this point in the history
  • Loading branch information
fallenatlas committed Sep 6, 2023
1 parent fcc60af commit b9d08c4
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 18 deletions.
5 changes: 4 additions & 1 deletion docs/pages/3_examples/2_engine/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@

@brief Showcases features of the @ref engine library.

@note Under construction.
The following examples have fully documented tutorials on how to use the
multiple plugins of the engine:

- @subpage examples-engine-cars - @copybrief examples-engine-cars
2 changes: 2 additions & 0 deletions engine/samples/cars/components.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

#include <glm/glm.hpp>

/// [Car component]
struct [[cubos::component("car", VecStorage)]] Car
{
glm::vec3 vel = {1.0f, 0.0f, 0.0f};
float angVel = 1.0f;
};
/// [Car component]
88 changes: 71 additions & 17 deletions engine/samples/cars/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,47 @@ using cubos::core::gl::Grid;
using cubos::core::gl::Palette;
using namespace cubos::engine;

/// [Get handles to assets]
static const Asset<Grid> CarAsset = AnyAsset("059c16e7-a439-44c7-9bdc-6e069dba0c75");
static const Asset<Palette> PaletteAsset = AnyAsset("1aa5e234-28cb-4386-99b4-39386b0fc215");
/// [Get handles to assets]

/// [Spawner resource]
struct Spawner
{
float timer = 0.0F;
int x = -1;
int y = -1;
};
/// [Spawner resource]

static void settings(Write<Settings> settings)
/// [Set settings]
static void settingsSystem(Write<Settings> settings)
{
settings->setString("assets.io.path", SAMPLE_ASSETS_FOLDER);
}
/// [Set settings]

static void setup(Commands cmds, Write<Assets> assets, Write<Renderer> renderer, Write<ActiveCameras> activeCameras)
/// [Load, add materials and set pallete]
static void setPalleteSystem(Write<Assets> assets, Write<Renderer> renderer)
{
// Load the palette asset and add two colors to it.
auto palette = assets->write(PaletteAsset);
auto black = palette->add({{0.1F, 0.1F, 0.1F, 1.0F}});
auto white = palette->add({{0.9F, 0.9F, 0.9F, 1.0F}});
palette->add({{0.1F, 0.1F, 0.1F, 1.0F}});
palette->add({{0.9F, 0.9F, 0.9F, 1.0F}});

// Set the renderer's palette to the one we just modified.
(*renderer)->setPalette(*palette);
}
/// [Load, add materials and set pallete]

/// [Create and spawn floor]
static void spawnFloorSystem(Commands cmds, Write<Assets> assets)
{
// Get the materials previously added to the palette
auto palette = assets->read(PaletteAsset);
auto black = palette->find({{0.1F, 0.1F, 0.1F, 1.0F}});
auto white = palette->find({{0.9F, 0.9F, 0.9F, 1.0F}});

// Generate a new grid asset for the floor.
auto floorGrid = Grid({256, 1, 256});
Expand All @@ -57,34 +74,56 @@ static void setup(Commands cmds, Write<Assets> assets, Write<Renderer> renderer,
auto floorAsset = assets->create(std::move(floorGrid));

// Spawn the floor entity.
cmds.create()
.add(RenderableGrid{floorAsset, floorOffset})
.add(LocalToWorld{})
.add(Scale{4.0F});
}
/// [Create and spawn floor]

cmds.create(RenderableGrid{floorAsset, floorOffset}, LocalToWorld{}, Scale{4.0F});

/// [Spawn camera]
static void spawnCameraSystem(Commands cmds, Write<ActiveCameras> activeCameras)
{
// Spawn the camera entity.
activeCameras->entities[0] =
cmds.create(Camera{60.0F, 0.1F, 1000.0F}, LocalToWorld{})
cmds.create()
.add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 1000.0F})
.add(LocalToWorld{})
.add(Position{{0.0F, 120.0F, -200.0F}})
.add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{0.0F, -1.0F, 1.0F}), glm::vec3{0.0F, 1.0F, 0.0F})})
.entity();
}
/// [Spawn camera]

/// [Spawn light]
static void spawnLightSystem(Commands cmds)
{
// Spawn the sun.
cmds.create(DirectionalLight{glm::vec3(1.0F), 1.0F}, LocalToWorld{},
Rotation{glm::quat(glm::vec3(glm::radians(45.0F), glm::radians(45.0F), 0))});
cmds.create()
.add(DirectionalLight{glm::vec3(1.0F), 1.0F})
.add(LocalToWorld{})
.add(Rotation{glm::quat(glm::vec3(glm::radians(45.0F), glm::radians(45.0F), 0))});
}
/// [Spawn light]

static void spawn(Commands cmds, Write<Spawner> spawner, Read<DeltaTime> deltaTime, Read<Assets> assets)
/// [Spawn system]
static void spawnSystem(Commands cmds, Write<Spawner> spawner, Read<DeltaTime> deltaTime, Read<Assets> assets)
{
spawner->timer += deltaTime->value;
if (spawner->timer >= 1.0F && spawner->y < 2)
{
auto car = assets->read(CarAsset);
glm::vec3 offset = glm::vec3(car->size().x, 0.0F, car->size().z) / -2.0F;

cmds.create(Car{}, RenderableGrid{CarAsset, offset}, LocalToWorld{})
cmds.create()
.add(Car{})
.add(RenderableGrid{CarAsset, offset})
.add(LocalToWorld{})
.add(Position{{80.0F * static_cast<float>(spawner->x), 0.0F, 80.0F * static_cast<float>(spawner->y)}})
.add(Rotation{});

spawner->timer = 0;
/// [Spawn system]
spawner->x += 1;
if (spawner->x == 2)
{
Expand All @@ -94,7 +133,8 @@ static void spawn(Commands cmds, Write<Spawner> spawner, Read<DeltaTime> deltaTi
}
}

static void move(Query<Write<Car>, Write<Position>, Write<Rotation>> query, Read<DeltaTime> deltaTime)
/// [Move system]
static void moveSystem(Query<Write<Car>, Write<Position>, Write<Rotation>> query, Read<DeltaTime> deltaTime)
{
for (auto [entity, car, position, rotation] : query)
{
Expand All @@ -105,20 +145,34 @@ static void move(Query<Write<Car>, Write<Position>, Write<Rotation>> query, Read
rotation->quat = glm::angleAxis(deltaTime->value * car->angVel, glm::vec3(0.0F, 1.0F, 0.0F)) * rotation->quat;
}
}
/// [Move system]

int main(int argc, char** argv)
{
Cubos cubos{argc, argv};
/// [Adding the env settings plugin]
cubos.addPlugin(envSettingsPlugin);
/// [Adding the env settings plugin]

/// [Adding the render and voxels plugin]
cubos.addPlugin(rendererPlugin);
cubos.addPlugin(voxelsPlugin);
/// [Adding the render and voxels plugin]

/// [Adding component and resource]
cubos.addComponent<Car>();
cubos.addResource<Spawner>();

cubos.startupSystem(settings).tagged("cubos.settings");
cubos.startupSystem(setup).tagged("cubos.assets").afterTag("cubos.renderer.init");
cubos.system(spawn);
cubos.system(move);
/// [Adding component and resource]

/// [Adding systems]
cubos.startupSystem(settingsSystem).tagged("cubos.settings");
cubos.startupSystem(setPalleteSystem).tagged("palette.set").afterTag("cubos.renderer.init");
cubos.startupSystem(spawnFloorSystem).afterTag("palette.set");
cubos.startupSystem(spawnCameraSystem);
cubos.startupSystem(spawnLightSystem);
cubos.system(spawnSystem);
cubos.system(moveSystem);
/// [Adding systems]

cubos.run();
}
58 changes: 58 additions & 0 deletions engine/samples/cars/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Cars {#examples-engine-cars}

@brief Sample that spawns multiple assets and updates them every frame.

This example shows how the @ref renderer-plugin plugin, @ref voxels-plugin plugin and @ref env-settings-plugin, can be used in a scene to spawn and move assets.

The first thing we're going to worry about is setting up the path for the assets we're going to use in our settings resource. In this example, the path is set in a macro defined in a CMakeLists.txt file but you can give it the path directly as a string.

@snippet cars/main.cpp Set settings

Alternatively, the path can be set from the command line arguments given when starting cubos. For this we need the @ref env-settings-plugin, included from the @ref engine/env_settings/plugin.hpp header.

@snippet cars/main.cpp Adding the env settings plugin

Each asset has an id through which we can get a handle to it. This id is specified in the .meta file associated to the asset.

@snippet cars/main.cpp Get handles to assets

Next, we are going to set up the scene.

We'll need to render and load assets.

@snippet cars/main.cpp Adding the render and voxels plugin

In our assets folder we already have a palette, let's load it and give it some more colors.

@snippet cars/main.cpp Load, add materials and set pallete

Now, let's give our scene a floor. To achieve this, we'll create a grid, assign one of the materials we added to the pallete to each voxel of that grid and then spawn it.

@snippet cars/main.cpp Create and spawn floor

To finish the setup, we need to spawn a camera and a light. On this sample we use a directional light. For more info on how to configure the @ref renderer-plugin plugin, refer to the @ref examples-renderer-sample sample.

@snippet cars/main.cpp Spawn camera
@snippet cars/main.cpp Spawn light

In this sample we want to spawn a car every second and move every car in the scene at a constant speed. To do this, we'll use 2 systems. One will spawn the cars and the other will move them.

Let's start with the spawn system. In this system, we'll need to load the asset and spawn the car at a given position, when it's time to do so.

@snippet cars/main.cpp Spawn system

For this to work, we'll need 2 more things, the Car component, which contains the car velocity and angular velocity, and the Spawner resource, used to keep track of the time and the position to spawn the car.

@snippet cars/components.hpp Car component
@snippet cars/main.cpp Spawner resource
@snippet cars/main.cpp Adding component and resource

Lastly, the move system will simply query through all the cars and change the values of their components. Note how we also use the Delta Time resource to make the speed independent from the frame rate.

@snippet cars/main.cpp Move system

Now, to make everything come to life, we just add all of these systems.

@snippet cars/main.cpp Adding systems

And voilá, you now have a screen full of cars doing ballet!

0 comments on commit b9d08c4

Please sign in to comment.