]> git.seodisparate.com - jumpartifact.com_demo_0/commitdiff
Rework electricity effect (again)
authorStephen Seo <seo.disparate@gmail.com>
Fri, 25 Aug 2023 09:29:18 +0000 (18:29 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 25 Aug 2023 09:29:18 +0000 (18:29 +0900)
Should be more efficient as a quad is generated instead of a cylinder
per draw.

src/3d_helpers.cc
src/3d_helpers.h
src/electricity_effect.cc
src/electricity_effect.h
src/screen_trunner.cc

index 9d17173f6501304de85129d644a0941b51f86087..4057a95b83921c58731bcf1173485cbea4589f76 100644 (file)
@@ -181,6 +181,21 @@ Vector3 from_edge_to_sphere_random(Vector3 center, Vector3 point,
                       (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) {
   return Vector3{a.x + b.x, a.y + b.y, a.z + b.z};
 }
index b4cfcd49622dbc3e8eeab3e6d462627edeb8e411..e0f0190a93bd8c4ffa243b663b0e29346b6ae76d 100644 (file)
@@ -2,6 +2,7 @@
 #define JUMPARTIFACT_DOT_COM_DEMO_0_3D_HELPERS_H_
 
 // standard library includes
+#include <array>
 #include <optional>
 
 // 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,
                                           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
 // weirdness regarding column-major matrices.
 // extern Vector4 operator*(const Matrix &m, const Vector4 &v);
index ea9435d9b198eb73477c1675668e230adf2d81ef..0a160e992cf2ac9adfa2384250c9f6513b7b5b33 100644 (file)
 
 ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
                                      int line_count, float lifetime)
-    : cylinders(),
+    : end_points(),
       center(center),
       radius(radius),
       lifetime(lifetime),
       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::tuple<Vector3, int> next;
   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) {
-    cylinders.push_back(Cylinder{.next_idx = -1,
-                                 .point = center,
-                                 .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,
-                                 })});
-    positions.push({center, cylinders.size() - 1});
+    end_points.push_back(EndPoint{.next_idx = -1,
+                                  .point = center,
+                                  .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,
+                                  })});
+    positions.push({center, end_points.size() - 1});
   }
   while (line_count-- > 0 && !positions.empty()) {
     next = positions.front();
@@ -57,7 +57,7 @@ ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
           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),
         .point = coll.point,
         .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})});
 
     dir = Vector3Normalize(center - coll.point);
-    coll.point = coll.point + dir * (radius * CYLINDER_EDGE_OFFSET);
-    for (unsigned int idx = 0; idx < CYLINDER_SPLIT_COUNT; ++idx) {
-      positions.push({coll.point, cylinders.size() - 1});
+    coll.point = coll.point + dir * (radius * QUAD_EDGE_OFFSET);
+    for (unsigned int idx = 0; idx < QUAD_SPLIT_COUNT; ++idx) {
+      positions.push({coll.point, end_points.size() - 1});
     }
   }
 }
@@ -75,27 +75,29 @@ ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
 bool ElectricityEffect::update(float dt) {
   timer += dt;
 
-  for (auto &cylinder : cylinders) {
-    cylinder.point = cylinder.point + cylinder.mdir * (dt * CYLINDER_MOVE_RATE);
-    if (Vector3Distance(cylinder.point, center) > radius) {
-      cylinder.point =
-          cylinder.point - cylinder.mdir * (dt * CYLINDER_MOVE_RATE);
-      cylinder.mdir =
-          from_edge_to_sphere_random(center, cylinder.point, radius);
+  for (auto &end_point : end_points) {
+    end_point.point = end_point.point + end_point.mdir * (dt * QUAD_MOVE_RATE);
+    if (Vector3Distance(end_point.point, center) > radius) {
+      end_point.point =
+          end_point.point - end_point.mdir * (dt * QUAD_MOVE_RATE);
+      end_point.mdir =
+          from_edge_to_sphere_random(center, end_point.point, radius);
     }
   }
 
   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;
 
-  for (const auto &cylinder : cylinders) {
-    if (cylinder.next_idx >= 0) {
-      DrawCylinderEx(cylinder.point, cylinders.at(cylinder.next_idx).point,
-                     CYLINDER_MAX_RADIUS * ratio, CYLINDER_MAX_RADIUS * ratio,
-                     CYLINDER_SIDES, color);
+  for (const auto &end_point : end_points) {
+    if (end_point.next_idx >= 0) {
+      std::array<Vector3, 4> quad = get_quad_from_start_end(
+          end_point.point, end_points[end_point.next_idx].point,
+          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);
     }
   }
 }
index e82d63a0621672e91bb5ce34ebeb014915f35caa..da49892efa58002043308bd355bd927534f86c6d 100644 (file)
@@ -7,12 +7,11 @@
 // third party includes
 #include <raylib.h>
 
-constexpr int CYLINDER_SPLIT_COUNT = 3;
-constexpr int CYLINDER_SIDES = 3;
-constexpr float CYLINDER_MAX_RADIUS = 0.03F;
-constexpr float CYLINDER_EDGE_OFFSET = 0.01F;
-constexpr float CYLINDER_LINE_MAX_LENGTH_RATIO = 0.85F;
-constexpr float CYLINDER_MOVE_RATE = 0.05F;
+constexpr int QUAD_SPLIT_COUNT = 3;
+constexpr float QUAD_MAX_WIDTH = 0.06F;
+constexpr float QUAD_EDGE_OFFSET = 0.01F;
+constexpr float QUAD_LINE_MAX_LENGTH_RATIO = 0.85F;
+constexpr float QUAD_MOVE_RATE = 0.05F;
 
 class ElectricityEffect {
  public:
@@ -22,15 +21,15 @@ class ElectricityEffect {
   /// Returns true if lifetime ended.
   bool update(float dt);
   /// Assumes draw mode is active.
-  void draw(Color color);
+  void draw(Color color, Vector3 camera_pos);
 
  private:
-  struct Cylinder {
+  struct EndPoint {
     int next_idx;
     Vector3 point, mdir;
   };
 
-  std::vector<Cylinder> cylinders;
+  std::vector<EndPoint> end_points;
   Vector3 center;
   float radius;
   float lifetime;
index dd36e1a59e52911b78107b79ed4ca18cfaea409f..2c2ce5d298b22a8f7724704d8cf882212ab24ef6 100644 (file)
@@ -72,7 +72,7 @@ TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
   // Initialize surface.
   generate_surface();
 
-  // Set up render textures
+  // Set up render textures.
   bgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
   fgRenderTexture = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
 
@@ -365,7 +365,7 @@ bool TRunnerScreen::draw(RenderTexture *render_texture) {
   }
 
   for (auto &ee : electricityEffects) {
-    ee.draw(GREEN);
+    ee.draw(GREEN, camera.position);
   }
 
   for (auto &se : sparkEffects) {