Rework electricity effect (again)
All checks were successful
Build and Publish WASM version of demo / Build-And-Deploy (push) Successful in 25s
All checks were successful
Build and Publish WASM version of demo / Build-And-Deploy (push) Successful in 25s
Should be more efficient as a quad is generated instead of a cylinder per draw.
This commit is contained in:
parent
0bd7e4bbf8
commit
4755b53deb
5 changed files with 73 additions and 41 deletions
|
@ -181,6 +181,21 @@ Vector3 from_edge_to_sphere_random(Vector3 center, Vector3 point,
|
||||||
(call_js_get_random() * radius));
|
(call_js_get_random() * radius));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<Vector3, 4> get_quad_from_start_end(Vector3 start, Vector3 end,
|
||||||
|
Vector3 normal, float width) {
|
||||||
|
std::array<Vector3, 4> quad;
|
||||||
|
Vector3 start_to_end = Vector3Normalize(end - start);
|
||||||
|
|
||||||
|
// Normalize just in case "normal" isn't actually a true normal.
|
||||||
|
quad[0] = Vector3Normalize(Vector3CrossProduct(start_to_end, normal));
|
||||||
|
quad[1] = start + quad[0] * (width / 2.0F);
|
||||||
|
quad[2] = end + quad[0] * (width / 2.0F);
|
||||||
|
quad[3] = end - quad[0] * (width / 2.0F);
|
||||||
|
quad[0] = start - quad[0] * (width / 2.0F);
|
||||||
|
|
||||||
|
return quad;
|
||||||
|
}
|
||||||
|
|
||||||
Vector3 operator+(const Vector3 &a, const Vector3 &b) {
|
Vector3 operator+(const Vector3 &a, const Vector3 &b) {
|
||||||
return Vector3{a.x + b.x, a.y + b.y, a.z + b.z};
|
return Vector3{a.x + b.x, a.y + b.y, a.z + b.z};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define JUMPARTIFACT_DOT_COM_DEMO_0_3D_HELPERS_H_
|
#define JUMPARTIFACT_DOT_COM_DEMO_0_3D_HELPERS_H_
|
||||||
|
|
||||||
// standard library includes
|
// standard library includes
|
||||||
|
#include <array>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
// third party includes
|
// third party includes
|
||||||
|
@ -30,6 +31,21 @@ extern std::optional<Vector3> ray_to_plane(const Ray &ray, const Ray &plane);
|
||||||
extern Vector3 from_edge_to_sphere_random(Vector3 center, Vector3 point,
|
extern Vector3 from_edge_to_sphere_random(Vector3 center, Vector3 point,
|
||||||
float radius);
|
float radius);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start side
|
||||||
|
* b -- a
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* c -- d
|
||||||
|
* end side
|
||||||
|
*
|
||||||
|
* (Normal facing outwards from screen.)
|
||||||
|
*/
|
||||||
|
extern std::array<Vector3, 4> get_quad_from_start_end(Vector3 start,
|
||||||
|
Vector3 end,
|
||||||
|
Vector3 normal,
|
||||||
|
float width);
|
||||||
|
|
||||||
// Unimplemented as this function isn't really needed and it exposes some
|
// Unimplemented as this function isn't really needed and it exposes some
|
||||||
// weirdness regarding column-major matrices.
|
// weirdness regarding column-major matrices.
|
||||||
// extern Vector4 operator*(const Matrix &m, const Vector4 &v);
|
// extern Vector4 operator*(const Matrix &m, const Vector4 &v);
|
||||||
|
|
|
@ -14,29 +14,29 @@
|
||||||
|
|
||||||
ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
|
ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
|
||||||
int line_count, float lifetime)
|
int line_count, float lifetime)
|
||||||
: cylinders(),
|
: end_points(),
|
||||||
center(center),
|
center(center),
|
||||||
radius(radius),
|
radius(radius),
|
||||||
lifetime(lifetime),
|
lifetime(lifetime),
|
||||||
timer(0.0F) {
|
timer(0.0F) {
|
||||||
cylinders.reserve(line_count);
|
end_points.reserve(line_count);
|
||||||
|
|
||||||
const float line_max_length = radius * CYLINDER_LINE_MAX_LENGTH_RATIO;
|
const float line_max_length = radius * QUAD_LINE_MAX_LENGTH_RATIO;
|
||||||
|
|
||||||
// Generate cylinders.
|
// Generate end_points.
|
||||||
std::queue<std::tuple<Vector3, int>> positions;
|
std::queue<std::tuple<Vector3, int>> positions;
|
||||||
std::tuple<Vector3, int> next;
|
std::tuple<Vector3, int> next;
|
||||||
Vector3 next_pos, dir;
|
Vector3 next_pos, dir;
|
||||||
for (unsigned int idx = 0; idx < CYLINDER_SPLIT_COUNT && line_count > 0;
|
for (unsigned int idx = 0; idx < QUAD_SPLIT_COUNT && line_count > 0;
|
||||||
++idx, --line_count) {
|
++idx, --line_count) {
|
||||||
cylinders.push_back(Cylinder{.next_idx = -1,
|
end_points.push_back(EndPoint{.next_idx = -1,
|
||||||
.point = center,
|
.point = center,
|
||||||
.mdir = Vector3Normalize(Vector3{
|
.mdir = Vector3Normalize(Vector3{
|
||||||
call_js_get_random() * 2.0F - 1.0F,
|
call_js_get_random() * 2.0F - 1.0F,
|
||||||
call_js_get_random() * 2.0F - 1.0F,
|
call_js_get_random() * 2.0F - 1.0F,
|
||||||
call_js_get_random() * 2.0F - 1.0F,
|
call_js_get_random() * 2.0F - 1.0F,
|
||||||
})});
|
})});
|
||||||
positions.push({center, cylinders.size() - 1});
|
positions.push({center, end_points.size() - 1});
|
||||||
}
|
}
|
||||||
while (line_count-- > 0 && !positions.empty()) {
|
while (line_count-- > 0 && !positions.empty()) {
|
||||||
next = positions.front();
|
next = positions.front();
|
||||||
|
@ -57,7 +57,7 @@ ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
|
||||||
next_pos + Vector3Normalize(coll.point - next_pos) * line_max_length;
|
next_pos + Vector3Normalize(coll.point - next_pos) * line_max_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
cylinders.push_back(Cylinder{
|
end_points.push_back(EndPoint{
|
||||||
.next_idx = std::get<int>(next),
|
.next_idx = std::get<int>(next),
|
||||||
.point = coll.point,
|
.point = coll.point,
|
||||||
.mdir = Vector3Normalize(Vector3{call_js_get_random() * 2.0F - 1.0F,
|
.mdir = Vector3Normalize(Vector3{call_js_get_random() * 2.0F - 1.0F,
|
||||||
|
@ -65,9 +65,9 @@ ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
|
||||||
call_js_get_random() * 2.0F - 1.0F})});
|
call_js_get_random() * 2.0F - 1.0F})});
|
||||||
|
|
||||||
dir = Vector3Normalize(center - coll.point);
|
dir = Vector3Normalize(center - coll.point);
|
||||||
coll.point = coll.point + dir * (radius * CYLINDER_EDGE_OFFSET);
|
coll.point = coll.point + dir * (radius * QUAD_EDGE_OFFSET);
|
||||||
for (unsigned int idx = 0; idx < CYLINDER_SPLIT_COUNT; ++idx) {
|
for (unsigned int idx = 0; idx < QUAD_SPLIT_COUNT; ++idx) {
|
||||||
positions.push({coll.point, cylinders.size() - 1});
|
positions.push({coll.point, end_points.size() - 1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,27 +75,29 @@ ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
|
||||||
bool ElectricityEffect::update(float dt) {
|
bool ElectricityEffect::update(float dt) {
|
||||||
timer += dt;
|
timer += dt;
|
||||||
|
|
||||||
for (auto &cylinder : cylinders) {
|
for (auto &end_point : end_points) {
|
||||||
cylinder.point = cylinder.point + cylinder.mdir * (dt * CYLINDER_MOVE_RATE);
|
end_point.point = end_point.point + end_point.mdir * (dt * QUAD_MOVE_RATE);
|
||||||
if (Vector3Distance(cylinder.point, center) > radius) {
|
if (Vector3Distance(end_point.point, center) > radius) {
|
||||||
cylinder.point =
|
end_point.point =
|
||||||
cylinder.point - cylinder.mdir * (dt * CYLINDER_MOVE_RATE);
|
end_point.point - end_point.mdir * (dt * QUAD_MOVE_RATE);
|
||||||
cylinder.mdir =
|
end_point.mdir =
|
||||||
from_edge_to_sphere_random(center, cylinder.point, radius);
|
from_edge_to_sphere_random(center, end_point.point, radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return timer >= lifetime;
|
return timer >= lifetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElectricityEffect::draw(Color color) {
|
void ElectricityEffect::draw(Color color, Vector3 camera_pos) {
|
||||||
float ratio = timer < lifetime ? (1.0F - timer / lifetime) : 0.0F;
|
float ratio = timer < lifetime ? (1.0F - timer / lifetime) : 0.0F;
|
||||||
|
|
||||||
for (const auto &cylinder : cylinders) {
|
for (const auto &end_point : end_points) {
|
||||||
if (cylinder.next_idx >= 0) {
|
if (end_point.next_idx >= 0) {
|
||||||
DrawCylinderEx(cylinder.point, cylinders.at(cylinder.next_idx).point,
|
std::array<Vector3, 4> quad = get_quad_from_start_end(
|
||||||
CYLINDER_MAX_RADIUS * ratio, CYLINDER_MAX_RADIUS * ratio,
|
end_point.point, end_points[end_point.next_idx].point,
|
||||||
CYLINDER_SIDES, color);
|
camera_pos - end_point.point, QUAD_MAX_WIDTH * ratio);
|
||||||
|
DrawTriangle3D(quad[0], quad[1], quad[2], color);
|
||||||
|
DrawTriangle3D(quad[0], quad[2], quad[3], color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,11 @@
|
||||||
// third party includes
|
// third party includes
|
||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
|
|
||||||
constexpr int CYLINDER_SPLIT_COUNT = 3;
|
constexpr int QUAD_SPLIT_COUNT = 3;
|
||||||
constexpr int CYLINDER_SIDES = 3;
|
constexpr float QUAD_MAX_WIDTH = 0.06F;
|
||||||
constexpr float CYLINDER_MAX_RADIUS = 0.03F;
|
constexpr float QUAD_EDGE_OFFSET = 0.01F;
|
||||||
constexpr float CYLINDER_EDGE_OFFSET = 0.01F;
|
constexpr float QUAD_LINE_MAX_LENGTH_RATIO = 0.85F;
|
||||||
constexpr float CYLINDER_LINE_MAX_LENGTH_RATIO = 0.85F;
|
constexpr float QUAD_MOVE_RATE = 0.05F;
|
||||||
constexpr float CYLINDER_MOVE_RATE = 0.05F;
|
|
||||||
|
|
||||||
class ElectricityEffect {
|
class ElectricityEffect {
|
||||||
public:
|
public:
|
||||||
|
@ -22,15 +21,15 @@ class ElectricityEffect {
|
||||||
/// Returns true if lifetime ended.
|
/// Returns true if lifetime ended.
|
||||||
bool update(float dt);
|
bool update(float dt);
|
||||||
/// Assumes draw mode is active.
|
/// Assumes draw mode is active.
|
||||||
void draw(Color color);
|
void draw(Color color, Vector3 camera_pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Cylinder {
|
struct EndPoint {
|
||||||
int next_idx;
|
int next_idx;
|
||||||
Vector3 point, mdir;
|
Vector3 point, mdir;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Cylinder> cylinders;
|
std::vector<EndPoint> end_points;
|
||||||
Vector3 center;
|
Vector3 center;
|
||||||
float radius;
|
float radius;
|
||||||
float lifetime;
|
float lifetime;
|
||||||
|
|
|
@ -72,7 +72,7 @@ TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
|
||||||
// Initialize surface.
|
// Initialize surface.
|
||||||
generate_surface();
|
generate_surface();
|
||||||
|
|
||||||
// Set up render textures
|
// Set up render textures.
|
||||||
bgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
bgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||||
fgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
fgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ bool TRunnerScreen::draw(RenderTexture *render_texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &ee : electricityEffects) {
|
for (auto &ee : electricityEffects) {
|
||||||
ee.draw(GREEN);
|
ee.draw(GREEN, camera.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &se : sparkEffects) {
|
for (auto &se : sparkEffects) {
|
||||||
|
|
Loading…
Reference in a new issue