Skip to content

Commit 49247a0

Browse files
authored
--add drawCoordinateAxes and drawCone to debug line renderer (#2506)
1 parent d7da048 commit 49247a0

3 files changed

Lines changed: 104 additions & 11 deletions

File tree

src/esp/bindings/GfxBindings.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,20 @@ void initGfxBindings(
255255
R"(Draw a circle in world-space or local-space (see pushTransform). The circle is an approximation; see numSegments.)",
256256
"translation"_a, "radius"_a, "color"_a, "num_segments"_a = 24,
257257
"normal"_a = Magnum::Vector3{0.0, 1.0, 0.0})
258+
.def("draw_cone", &DebugLineRender::drawCone,
259+
R"(Draw a cone in world-space or local-space (see pushTransform).
260+
The cone is a segmented circle (see drawCircle) with each segment endpoint
261+
having a line drawn to the given apex.)",
262+
"translation"_a, "apex"_a, "radius"_a, "color"_a,
263+
"num_segments"_a = 12, "normal"_a = Magnum::Vector3{0.0, 1.0, 0.0})
264+
.def(
265+
"draw_axes", &DebugLineRender::drawCoordinateAxes,
266+
R"(Draw a set of coordinate axes at the given XYZ translation and with
267+
XYZ scaling in world-space or local-space (see pushTransform).
268+
These axes are color-mapped such that XYZ->RGB and each positive axis
269+
as a connical 'arrow head' of given radius.)",
270+
"translation"_a, "scale"_a = Magnum::Vector3{1.0, 1.0, 1.0},
271+
"radius"_a = 0.05)
258272
.def(
259273
"draw_transformed_line",
260274
py::overload_cast<const Magnum::Vector3&, const Magnum::Vector3&,

src/esp/gfx/DebugLineRender.cpp

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -238,33 +238,89 @@ void DebugLineRender::drawBox(const Magnum::Vector3& min,
238238
Mn::Vector3(max.x(), max.y(), max.z()), color);
239239
}
240240

241+
namespace {
242+
// Get a vector that is perpendicular to the given normalized vector
243+
Mn::Vector3 getRandomPerpVec(const Magnum::Vector3& normal) {
244+
// https://stackoverflow.com/questions/11132681/what-is-a-formula-to-get-a-vector-perpendicular-to-another-vector
245+
// account for normal == (0, 0, -1)
246+
return fabs(normal.z()) < fabs(normal.x())
247+
? Mn::Vector3(normal.y(), -normal.x(), 0)
248+
: Mn::Vector3(0, -normal.z(), normal.y());
249+
}
250+
} // namespace
251+
241252
void DebugLineRender::drawCircle(const Magnum::Vector3& pos,
242253
float radius,
243254
const Magnum::Color4& color,
244255
int numSegments,
245256
const Magnum::Vector3& normal) {
246-
// https://stackoverflow.com/questions/11132681/what-is-a-formula-to-get-a-vector-perpendicular-to-another-vector
247-
// account for normal == (0, 0, -1)
248-
auto randomPerpVec = fabs(normal.z()) < fabs(normal.x())
249-
? Mn::Vector3(normal.y(), -normal.x(), 0)
250-
: Mn::Vector3(0, -normal.z(), normal.y());
257+
auto randomPerpVec = getRandomPerpVec(normal);
251258

252259
pushTransform(Mn::Matrix4::lookAt(pos, pos + normal, randomPerpVec) *
253260
Mn::Matrix4::scaling(Mn::Vector3(radius, radius, 0.f)));
254261

255-
Mn::Vector3 prevPt;
256-
for (int seg = 0; seg <= numSegments; ++seg) {
257-
Mn::Deg angle = Mn::Deg(360.f * float(seg) / numSegments);
262+
Mn::Vector3 prevPt(1.0f, 0.0f, 0.0f);
263+
float degScale = 360.f / numSegments;
264+
for (int seg = 1; seg <= numSegments; ++seg) {
265+
Mn::Deg angle = Mn::Deg(degScale * float(seg));
258266
Mn::Vector3 pt(Mn::Math::cos(angle), Mn::Math::sin(angle), 0.f);
259-
if (seg > 0) {
260-
drawTransformedLine(prevPt, pt, color);
261-
}
267+
drawTransformedLine(prevPt, pt, color);
262268
prevPt = pt;
263269
}
264270

265271
popTransform();
266272
}
267273

274+
void DebugLineRender::drawCone(const Magnum::Vector3& pos,
275+
const Magnum::Vector3& apex,
276+
float radius,
277+
const Magnum::Color4& color,
278+
int numSegments,
279+
const Magnum::Vector3& normal) {
280+
auto randomPerpVec = getRandomPerpVec(normal);
281+
const Mn::Matrix4 lookAtTrans =
282+
Mn::Matrix4::lookAt(pos, pos + normal, randomPerpVec) *
283+
Mn::Matrix4::scaling(Mn::Vector3(radius, radius, 1.0f));
284+
// transform the apex to be relative to transformation
285+
Mn::Vector3 lclApex = lookAtTrans.invertedRigid().transformPoint(apex);
286+
pushTransform(lookAtTrans);
287+
288+
Mn::Vector3 prevPt(1.0f, 0.0f, 0.0f);
289+
float degScale = 360.f / numSegments;
290+
for (int seg = 1; seg <= numSegments; ++seg) {
291+
Mn::Deg angle = Mn::Deg(degScale * float(seg));
292+
Mn::Vector3 pt(Mn::Math::cos(angle), Mn::Math::sin(angle), 0.0f);
293+
drawTransformedLine(pt, lclApex, color);
294+
drawTransformedLine(prevPt, pt, color);
295+
prevPt = pt;
296+
}
297+
298+
popTransform();
299+
} // DebugLineRender::drawCone
300+
301+
void DebugLineRender::drawCoordinateAxes(const Magnum::Vector3& pos,
302+
const Magnum::Vector3& scale,
303+
float radius) {
304+
auto buildAxis = [&](const Magnum::Vector3& pos, const Magnum::Vector3& axis,
305+
const Magnum::Color4& color, float radius) {
306+
// Draw line centered at pos along given axis of specified length, with a
307+
// cone of given radius to act as a directional arrow
308+
drawTransformedLine(pos - axis, pos + axis, color);
309+
drawCone(pos + axis * 0.9, pos + axis, radius, color, 24,
310+
axis.normalized());
311+
};
312+
313+
// Red x axis and positive endpoint circle indicator
314+
buildAxis(pos, Magnum::Vector3::xAxis(scale.x()), Magnum::Color4::red(),
315+
radius);
316+
// Green y axis and positive endpoint circle indicator
317+
buildAxis(pos, Magnum::Vector3::yAxis(scale.y()), Magnum::Color4::green(),
318+
radius);
319+
// Blue z axis and positive endpoint circle indicator
320+
buildAxis(pos, Magnum::Vector3::zAxis(scale.z()), Magnum::Color4::blue(),
321+
radius);
322+
} // DebugLineRender::drawCoordinateAxes
323+
268324
void DebugLineRender::drawPathWithEndpointCircles(
269325
Mn::Containers::ArrayView<const Mn::Vector3> points,
270326
float radius,

src/esp/gfx/DebugLineRender.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,29 @@ class DebugLineRender {
132132
1.0,
133133
0.0));
134134

135+
/**
136+
* @brief Draw a cone in world-space or local-space (see pushTransform).
137+
* The cone is a circle (see drawCircle) with each segment endpoint having a
138+
* line drawn to the given apex.
139+
*/
140+
void drawCone(const Magnum::Vector3& pos,
141+
const Magnum::Vector3& apex,
142+
float radius,
143+
const Magnum::Color4& color,
144+
int numSegments = 24,
145+
const Magnum::Vector3& normal = Magnum::Vector3(0.0, 1.0, 0.0));
146+
147+
/**
148+
* @brief Draw RGB->XYZ coordinate axes at given location with given
149+
* scaling. A circle will be placed near the end of each positive axis.
150+
* @param pos The location in world space to place the axes
151+
* @param scale The length of each axis
152+
* @param radius The radius of the positive-direction circle indicators
153+
*/
154+
void drawCoordinateAxes(const Magnum::Vector3& pos,
155+
const Magnum::Vector3& scale = {1.0f, 1.0f, 1.0f},
156+
float radius = 0.05);
157+
135158
/**
136159
* @brief Draw a sequence of line segments with circles at the two endpoints.
137160
* In world-space or local-space (see pushTransform).

0 commit comments

Comments
 (0)