Impl. randomized environment
All checks were successful
Build and Publish WASM version of demo / Build-And-Deploy (push) Successful in 15s

This commit is contained in:
Stephen Seo 2023-08-08 11:33:07 +09:00
parent 0d36747031
commit 4a5b3073c3
3 changed files with 172 additions and 30 deletions

View file

@ -11,7 +11,7 @@ EM_JS(int, canvas_get_width, (),
EM_JS(int, canvas_get_height, (),
{ return document.getElementById("canvas").clientHeight; });
EM_JS(int, js_get_random, (), { return Math.random(); });
EM_JS(float, js_get_random, (), { return Math.random(); });
int call_js_get_canvas_width() { return canvas_get_width(); }

View file

@ -3,6 +3,7 @@
// standard library includes
#include <cassert>
#include <cmath>
#include <queue>
#ifndef NDEBUG
#include <iostream>
@ -14,12 +15,11 @@
TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
: Screen(stack),
surface(),
camera{Vector3{0.0F, 1.0F, 0.5F}, Vector3{0.0F, 0.0F, 0.0F},
Vector3{0.0F, 1.0F, 0.0F}, 80.0F, CAMERA_PERSPECTIVE},
flags(),
default_material(LoadMaterialDefault()),
TEMP_cube_model(LoadModel("res/test_cube.obj")),
plane_mesh(GenMeshPlane(1.0F, 1.0F, 2, 2)),
TEMP_cube_texture(LoadTexture("res/test_cube_texture.png")),
TEMP_matrix(get_identity_matrix()),
camera_pos{0.0F, 4.0F, 4.0F},
@ -32,13 +32,136 @@ TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
TEMP_cube_model.transform = TEMP_cube_model.transform *
scale_matrix_xyz(0.5F, 0.5F, 0.5F) *
translate_matrix_y(0.5F);
// Initialize surface.
#ifndef NDEBUG
std::cout << "Initializing surface...\n";
#endif
std::queue<unsigned int> to_update;
to_update.push(SURFACE_UNIT_WIDTH / 2 +
(SURFACE_UNIT_HEIGHT / 2) * SURFACE_UNIT_WIDTH);
while (!to_update.empty()) {
unsigned int idx = to_update.front();
to_update.pop();
if (surface.at(idx).has_value()) {
continue;
}
SurfaceUnit current{0.0F, 0.0F, 0.0F, 0.0F};
// 0000 0001 - nw set
// 0000 0010 - ne set
// 0000 0100 - sw set
// 0000 1000 - se set
unsigned char flags = 0;
// Check adjacent.
if (idx % SURFACE_UNIT_WIDTH > 0) {
if (surface.at(idx - 1).has_value()) {
if ((flags & 1) == 0) {
current.nw = surface.at(idx - 1).value().ne;
flags |= 1;
}
if ((flags & 4) == 0) {
current.sw = surface.at(idx - 1).value().se;
flags |= 4;
}
} else {
to_update.push(idx - 1);
}
}
if (idx % SURFACE_UNIT_WIDTH < SURFACE_UNIT_WIDTH - 1) {
if (surface.at(idx + 1).has_value()) {
if ((flags & 2) == 0) {
current.ne = surface.at(idx + 1).value().nw;
flags |= 2;
}
if ((flags & 8) == 0) {
current.se = surface.at(idx + 1).value().sw;
flags |= 8;
}
} else {
to_update.push(idx + 1);
}
}
if (idx / SURFACE_UNIT_WIDTH > 0) {
if (surface.at(idx - SURFACE_UNIT_WIDTH).has_value()) {
if ((flags & 1) == 0) {
current.nw = surface.at(idx - SURFACE_UNIT_WIDTH).value().sw;
flags |= 1;
}
if ((flags & 2) == 0) {
current.ne = surface.at(idx - SURFACE_UNIT_WIDTH).value().se;
flags |= 2;
}
} else {
to_update.push(idx - SURFACE_UNIT_WIDTH);
}
}
if (idx / SURFACE_UNIT_WIDTH < SURFACE_UNIT_HEIGHT - 1) {
if (surface.at(idx + SURFACE_UNIT_WIDTH).has_value()) {
if ((flags & 4) == 0) {
current.sw = surface.at(idx + SURFACE_UNIT_WIDTH).value().nw;
flags |= 4;
}
if ((flags & 8) == 0) {
current.se = surface.at(idx + SURFACE_UNIT_WIDTH).value().ne;
flags |= 8;
}
} else {
to_update.push(idx + SURFACE_UNIT_WIDTH);
}
}
// Calculate remaining values.
float avg = 0.0F;
unsigned int count = 0;
if ((flags & 1) != 0) {
avg += current.nw;
++count;
}
if ((flags & 2) != 0) {
avg += current.ne;
++count;
}
if ((flags & 4) != 0) {
avg += current.sw;
++count;
}
if ((flags & 8) != 0) {
avg += current.se;
++count;
}
if (count != 0) {
avg = avg / (float)count;
}
if ((flags & 1) == 0) {
current.nw = avg + call_js_get_random() * SURFACE_HEIGHT_INTERVAL -
SURFACE_HEIGHT_INTERVAL / 2.0F;
}
if ((flags & 2) == 0) {
current.ne = avg + call_js_get_random() * SURFACE_HEIGHT_INTERVAL -
SURFACE_HEIGHT_INTERVAL / 2.0F;
}
if ((flags & 4) == 0) {
current.sw = avg + call_js_get_random() * SURFACE_HEIGHT_INTERVAL -
SURFACE_HEIGHT_INTERVAL / 2.0F;
}
if ((flags & 8) == 0) {
current.se = avg + call_js_get_random() * SURFACE_HEIGHT_INTERVAL -
SURFACE_HEIGHT_INTERVAL / 2.0F;
}
surface.at(idx) = current;
}
#ifndef NDEBUG
std::cout << "Screen finished init.\n";
#endif
}
TRunnerScreen::~TRunnerScreen() {
UnloadTexture(TEMP_cube_texture);
UnloadMesh(plane_mesh);
UnloadModel(TEMP_cube_model);
UnloadMaterial(default_material);
}
bool TRunnerScreen::update(float dt) {
@ -77,33 +200,38 @@ bool TRunnerScreen::draw() {
ClearBackground(PixelToColor(Pixel::PIXEL_SKY));
BeginMode3D(camera);
for (int z = -25; z <= 25; ++z) {
for (int x = -25; x <= 25; ++x) {
if (x == (int)(mouse_px > 0.0F ? mouse_px + 0.5F : mouse_px - 0.5F) &&
z == (int)(mouse_pz > 0.0F ? mouse_pz + 0.5F : mouse_pz - 0.5F)) {
default_material.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
} else {
default_material.maps[MATERIAL_MAP_DIFFUSE].color =
Color{(unsigned char)(200 + x * 2), (unsigned char)(150 + z * 2),
for (unsigned int idx = 0; idx < SURFACE_UNIT_WIDTH * SURFACE_UNIT_HEIGHT;
++idx) {
int x = idx % SURFACE_UNIT_WIDTH;
int y = idx / SURFACE_UNIT_WIDTH;
int ox = x - SURFACE_UNIT_WIDTH / 2;
int oy = y - SURFACE_UNIT_HEIGHT / 2;
float xf = (float)(x)-SURFACE_X_OFFSET;
float zf = (float)(y)-SURFACE_Y_OFFSET;
Color color{(unsigned char)(200 + ox * 2), (unsigned char)(150 + oy * 2),
20, 255};
}
DrawMesh(plane_mesh, default_material, translate_matrix_xyz(x, 0.0F, z));
}
auto &current = surface[idx];
DrawTriangle3D(Vector3{xf - 0.5F, current->nw, zf - 0.5F},
Vector3{xf - 0.5F, current->sw, zf + 0.5F},
Vector3{xf + 0.5F, current->ne, zf - 0.5F}, color);
DrawTriangle3D(Vector3{xf + 0.5F, current->se, zf + 0.5F},
Vector3{xf + 0.5F, current->ne, zf - 0.5F},
Vector3{xf - 0.5F, current->sw, zf + 0.5F}, color);
}
DrawModel(Model{.transform = TEMP_cube_model.transform * TEMP_matrix,
.meshCount = TEMP_cube_model.meshCount,
.materialCount = TEMP_cube_model.materialCount,
.meshes = TEMP_cube_model.meshes,
.materials = TEMP_cube_model.materials,
.meshMaterial = TEMP_cube_model.meshMaterial,
.boneCount = TEMP_cube_model.boneCount,
.bones = TEMP_cube_model.bones,
.bindPose = TEMP_cube_model.bindPose},
Vector3{0.0F, 0.0F, -4.0F}, 1.0F, WHITE);
// DrawModel(Model{.transform = TEMP_cube_model.transform * TEMP_matrix,
// .meshCount = TEMP_cube_model.meshCount,
// .materialCount = TEMP_cube_model.materialCount,
// .meshes = TEMP_cube_model.meshes,
// .materials = TEMP_cube_model.materials,
// .meshMaterial = TEMP_cube_model.meshMaterial,
// .boneCount = TEMP_cube_model.boneCount,
// .bones = TEMP_cube_model.bones,
// .bindPose = TEMP_cube_model.bindPose},
// Vector3{0.0F, 0.0F, -4.0F}, 1.0F, WHITE);
// TODO DEBUG
DrawLine3D(Vector3{0.0F, 0.0F, 0.0F}, Vector3{mouse_px, 0.0F, mouse_pz},
DrawLine3D(Vector3{0.0F, 3.0F, 0.0F}, Vector3{mouse_px, 0.0F, mouse_pz},
BLACK);
EndMode3D();

View file

@ -6,6 +6,7 @@
// standard library includes
#include <array>
#include <bitset>
#include <optional>
// third party includes
#include <raylib.h>
@ -13,6 +14,14 @@
constexpr float POS_VALUE_INC_RATE = 0.2F;
constexpr float CAMERA_UPDATE_RATE = 1.0F;
constexpr unsigned int SURFACE_UNIT_WIDTH = 51;
constexpr unsigned int SURFACE_UNIT_HEIGHT = 51;
constexpr float SURFACE_X_OFFSET = (float)SURFACE_UNIT_WIDTH / 2.0F;
constexpr float SURFACE_Y_OFFSET = (float)SURFACE_UNIT_HEIGHT / 2.0F;
constexpr float SURFACE_HEIGHT_INTERVAL = 0.5F;
class TRunnerScreen : public Screen {
public:
TRunnerScreen(std::weak_ptr<ScreenStack> stack);
@ -38,13 +47,18 @@ class TRunnerScreen : public Screen {
PIXEL_WHITE
};
struct SurfaceUnit {
float nw, ne, sw, se;
};
static Color PixelToColor(Pixel p);
std::array<std::optional<SurfaceUnit>,
SURFACE_UNIT_WIDTH * SURFACE_UNIT_HEIGHT>
surface;
Camera3D camera;
std::bitset<64> flags;
Material default_material;
Model TEMP_cube_model;
Mesh plane_mesh;
Texture2D TEMP_cube_texture;
Matrix TEMP_matrix;
Vector3 camera_pos;