|
@@ -1,23 +1,32 @@
|
|
|
#include "arrow.h"
|
|
#include "arrow.h"
|
|
|
#include "../gl/mesh.h"
|
|
#include "../gl/mesh.h"
|
|
|
|
|
+#include "../entity/registry.h"
|
|
|
|
|
+#include "../gl/renderer.h"
|
|
|
|
|
+#include "../gl/resources.h"
|
|
|
|
|
+#include "../../game/systems/arrow_system.h"
|
|
|
|
|
+
|
|
|
#include <vector>
|
|
#include <vector>
|
|
|
#include <cmath>
|
|
#include <cmath>
|
|
|
|
|
+#include <algorithm>
|
|
|
#include <QVector3D>
|
|
#include <QVector3D>
|
|
|
|
|
+#include <QMatrix4x4>
|
|
|
|
|
+
|
|
|
|
|
|
|
|
-namespace Render::Geom {
|
|
|
|
|
|
|
+namespace Render {
|
|
|
|
|
+namespace Geom {
|
|
|
|
|
|
|
|
-static Render::GL::Mesh* createArrowMesh() {
|
|
|
|
|
- using Render::GL::Vertex;
|
|
|
|
|
- std::vector<Vertex> verts;
|
|
|
|
|
|
|
+static GL::Mesh* createArrowMesh() {
|
|
|
|
|
+ using GL::Vertex;
|
|
|
|
|
+ std::vector<GL::Vertex> verts;
|
|
|
std::vector<unsigned int> idx;
|
|
std::vector<unsigned int> idx;
|
|
|
- // Parameters for a simple arrow of length 1 along +Z
|
|
|
|
|
|
|
+
|
|
|
const int radial = 12;
|
|
const int radial = 12;
|
|
|
const float shaftRadius = 0.05f;
|
|
const float shaftRadius = 0.05f;
|
|
|
- const float shaftLen = 0.85f; // 85% shaft, 15% tip
|
|
|
|
|
|
|
+ const float shaftLen = 0.85f;
|
|
|
const float tipLen = 0.15f;
|
|
const float tipLen = 0.15f;
|
|
|
const float tipStartZ = shaftLen;
|
|
const float tipStartZ = shaftLen;
|
|
|
- const float tipEndZ = shaftLen + tipLen; // should be 1.0
|
|
|
|
|
- // Shaft cylinder: two rings at z=0 and z=shaftLen
|
|
|
|
|
|
|
+ const float tipEndZ = shaftLen + tipLen;
|
|
|
|
|
+
|
|
|
int baseIndex = 0;
|
|
int baseIndex = 0;
|
|
|
for (int ring = 0; ring < 2; ++ring) {
|
|
for (int ring = 0; ring < 2; ++ring) {
|
|
|
float z = (ring == 0) ? 0.0f : shaftLen;
|
|
float z = (ring == 0) ? 0.0f : shaftLen;
|
|
@@ -30,7 +39,7 @@ static Render::GL::Mesh* createArrowMesh() {
|
|
|
verts.push_back({{x, y, z}, {n.x(), n.y(), n.z()}, {float(i)/radial, z}});
|
|
verts.push_back({{x, y, z}, {n.x(), n.y(), n.z()}, {float(i)/radial, z}});
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- // Shaft indices (quads split into triangles)
|
|
|
|
|
|
|
+
|
|
|
for (int i = 0; i < radial; ++i) {
|
|
for (int i = 0; i < radial; ++i) {
|
|
|
int next = (i + 1) % radial;
|
|
int next = (i + 1) % radial;
|
|
|
int a = baseIndex + i;
|
|
int a = baseIndex + i;
|
|
@@ -40,31 +49,77 @@ static Render::GL::Mesh* createArrowMesh() {
|
|
|
idx.push_back(a); idx.push_back(b); idx.push_back(c);
|
|
idx.push_back(a); idx.push_back(b); idx.push_back(c);
|
|
|
idx.push_back(c); idx.push_back(d); idx.push_back(a);
|
|
idx.push_back(c); idx.push_back(d); idx.push_back(a);
|
|
|
}
|
|
}
|
|
|
- // Tip cone: triangle fan from tip apex to ring at tipStartZ
|
|
|
|
|
|
|
+
|
|
|
int ringStart = verts.size();
|
|
int ringStart = verts.size();
|
|
|
for (int i = 0; i < radial; ++i) {
|
|
for (int i = 0; i < radial; ++i) {
|
|
|
float a = (float(i) / radial) * 6.2831853f;
|
|
float a = (float(i) / radial) * 6.2831853f;
|
|
|
- float x = std::cos(a) * shaftRadius * 1.4f; // slightly larger base for tip
|
|
|
|
|
- float y = std::sin(a) * shaftRadius * 1.4f;
|
|
|
|
|
|
|
+ float x = std::cos(a) * shaftRadius * 1.4f;
|
|
|
|
|
+ float y = std::sin(a) * shaftRadius * 1.4f;
|
|
|
QVector3D n(x, y, 0.2f);
|
|
QVector3D n(x, y, 0.2f);
|
|
|
n.normalize();
|
|
n.normalize();
|
|
|
verts.push_back({{x, y, tipStartZ}, {n.x(), n.y(), n.z()}, {float(i)/radial, 0.0f}});
|
|
verts.push_back({{x, y, tipStartZ}, {n.x(), n.y(), n.z()}, {float(i)/radial, 0.0f}});
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
int apexIndex = verts.size();
|
|
int apexIndex = verts.size();
|
|
|
verts.push_back({{0.0f, 0.0f, tipEndZ}, {0.0f, 0.0f, 1.0f}, {0.5f, 1.0f}});
|
|
verts.push_back({{0.0f, 0.0f, tipEndZ}, {0.0f, 0.0f, 1.0f}, {0.5f, 1.0f}});
|
|
|
for (int i = 0; i < radial; ++i) {
|
|
for (int i = 0; i < radial; ++i) {
|
|
|
int next = (i + 1) % radial;
|
|
int next = (i + 1) % radial;
|
|
|
- int a = ringStart + i;
|
|
|
|
|
- int b = ringStart + next;
|
|
|
|
|
- int apex = apexIndex;
|
|
|
|
|
- idx.push_back(a); idx.push_back(apex); idx.push_back(b);
|
|
|
|
|
|
|
+ idx.push_back(ringStart + i);
|
|
|
|
|
+ idx.push_back(apexIndex);
|
|
|
|
|
+ idx.push_back(ringStart + next);
|
|
|
}
|
|
}
|
|
|
- return new Render::GL::Mesh(verts, idx);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return new GL::Mesh(verts, idx);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-Render::GL::Mesh* Arrow::get() {
|
|
|
|
|
- static Render::GL::Mesh* mesh = createArrowMesh();
|
|
|
|
|
|
|
+GL::Mesh* Arrow::get() {
|
|
|
|
|
+ static GL::Mesh* mesh = createArrowMesh();
|
|
|
return mesh;
|
|
return mesh;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-} // namespace Render::Geom
|
|
|
|
|
|
|
+} // namespace Geom
|
|
|
|
|
+
|
|
|
|
|
+namespace GL {
|
|
|
|
|
+
|
|
|
|
|
+void renderArrows(Renderer* renderer,
|
|
|
|
|
+ ResourceManager* resources,
|
|
|
|
|
+ const Game::Systems::ArrowSystem& arrowSystem) {
|
|
|
|
|
+ if (!renderer || !resources) return;
|
|
|
|
|
+ auto* arrowMesh = resources->arrow();
|
|
|
|
|
+ if (!arrowMesh) return;
|
|
|
|
|
+
|
|
|
|
|
+ const auto& arrows = arrowSystem.arrows();
|
|
|
|
|
+ for (const auto& arrow : arrows) {
|
|
|
|
|
+ if (!arrow.active) continue;
|
|
|
|
|
+
|
|
|
|
|
+ const QVector3D delta = arrow.end - arrow.start;
|
|
|
|
|
+ const float dist = std::max(0.001f, delta.length());
|
|
|
|
|
+ QVector3D pos = arrow.start + delta * arrow.t;
|
|
|
|
|
+ float h = arrow.arcHeight * 4.0f * arrow.t * (1.0f - arrow.t);
|
|
|
|
|
+ pos.setY(pos.y() + h);
|
|
|
|
|
+
|
|
|
|
|
+ QMatrix4x4 model;
|
|
|
|
|
+ model.translate(pos.x(), pos.y(), pos.z());
|
|
|
|
|
+
|
|
|
|
|
+ QVector3D dir = delta.normalized();
|
|
|
|
|
+ float yawDeg = std::atan2(dir.x(), dir.z()) * 180.0f / 3.14159265f;
|
|
|
|
|
+ model.rotate(yawDeg, QVector3D(0,1,0));
|
|
|
|
|
+
|
|
|
|
|
+ float vy = (arrow.end.y() - arrow.start.y()) / dist;
|
|
|
|
|
+ float pitchDeg = -std::atan2(
|
|
|
|
|
+ vy - (8.0f * arrow.arcHeight * (arrow.t - 0.5f) / dist),
|
|
|
|
|
+ 1.0f
|
|
|
|
|
+ ) * 180.0f / 3.14159265f;
|
|
|
|
|
+ model.rotate(pitchDeg, QVector3D(1,0,0));
|
|
|
|
|
+
|
|
|
|
|
+ const float zScale = 0.40f;
|
|
|
|
|
+ const float xyScale = 0.26f;
|
|
|
|
|
+ model.translate(0.0f, 0.0f, -zScale * 0.5f);
|
|
|
|
|
+ model.scale(xyScale, xyScale, zScale);
|
|
|
|
|
+
|
|
|
|
|
+ renderer->drawMeshColored(arrowMesh, model, arrow.color);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+} // namespace GL
|
|
|
|
|
+} // namespace Render
|