Unravel Engine C++ Reference
Loading...
Searching...
No Matches
debugdraw.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2011-2023 Branimir Karadzic. All rights reserved.
3 * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
4 */
5
6#include "debugdraw.h"
7#include "../bgfx_utils.h"
8#include "../packrect.h"
9#include <bgfx/bgfx.h>
10#include <bgfx/embedded_shader.h>
11
12#include <bx/debug.h>
13#include <bx/handlealloc.h>
14#include <bx/math.h>
15#include <bx/mutex.h>
16#include <bx/sort.h>
17
18#ifndef DEBUG_DRAW_CONFIG_MAX_GEOMETRY
19#define DEBUG_DRAW_CONFIG_MAX_GEOMETRY 256
20#endif // DEBUG_DRAW_CONFIG_MAX_GEOMETRY
21
23{
24 float m_x;
25 float m_y;
26 float m_z;
27 float m_len;
28 uint32_t m_abgr;
29
30 static void init()
31 {
32 ms_layout.begin()
33 .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
34 .add(bgfx::Attrib::TexCoord0, 1, bgfx::AttribType::Float)
35 .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
36 .end();
37 }
38
39 static bgfx::VertexLayout ms_layout;
40};
41
42bgfx::VertexLayout DebugVertex::ms_layout;
43
45{
46 float m_x;
47 float m_y;
48 float m_z;
49 float m_u;
50 float m_v;
51 uint32_t m_abgr;
52
53 static void init()
54 {
55 ms_layout.begin()
56 .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
57 .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
58 .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
59 .end();
60 }
61
62 static bgfx::VertexLayout ms_layout;
63};
64
65bgfx::VertexLayout DebugUvVertex::ms_layout;
66
68{
69 float m_x;
70 float m_y;
71 float m_z;
72 uint8_t m_indices[4];
73
74 static void init()
75 {
76 ms_layout.begin()
77 .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
78 .add(bgfx::Attrib::Indices, 4, bgfx::AttribType::Uint8)
79 .end();
80 }
81
82 static bgfx::VertexLayout ms_layout;
83};
84
85bgfx::VertexLayout DebugShapeVertex::ms_layout;
86
88{
89 float m_x;
90 float m_y;
91 float m_z;
92
93 static void init()
94 {
95 ms_layout.begin().add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float).end();
96 }
97
98 static bgfx::VertexLayout ms_layout;
99};
100
101bgfx::VertexLayout DebugMeshVertex::ms_layout;
102
104 {-1.0f, 0.0f, 1.0f, {0, 0, 0, 0}},
105 {1.0f, 0.0f, 1.0f, {0, 0, 0, 0}},
106 {-1.0f, 0.0f, -1.0f, {0, 0, 0, 0}},
107 {1.0f, 0.0f, -1.0f, {0, 0, 0, 0}},
108
109};
110
111static const uint16_t s_quadIndices[6] = {
112 0,
113 1,
114 2,
115 1,
116 3,
117 2,
118};
119
121 {-1.0f, 1.0f, 1.0f, {0, 0, 0, 0}},
122 {1.0f, 1.0f, 1.0f, {0, 0, 0, 0}},
123 {-1.0f, -1.0f, 1.0f, {0, 0, 0, 0}},
124 {1.0f, -1.0f, 1.0f, {0, 0, 0, 0}},
125 {-1.0f, 1.0f, -1.0f, {0, 0, 0, 0}},
126 {1.0f, 1.0f, -1.0f, {0, 0, 0, 0}},
127 {-1.0f, -1.0f, -1.0f, {0, 0, 0, 0}},
128 {1.0f, -1.0f, -1.0f, {0, 0, 0, 0}},
129};
130
131static const uint16_t s_cubeIndices[36] = {
132 0, 1, 2, // 0
133 1, 3, 2, 4, 6, 5, // 2
134 5, 6, 7, 0, 2, 4, // 4
135 4, 2, 6, 1, 5, 3, // 6
136 5, 7, 3, 0, 4, 1, // 8
137 4, 5, 1, 2, 3, 6, // 10
138 6, 3, 7,
139};
140
141static const uint8_t s_circleLod[] = {
142 37,
143 29,
144 23,
145 17,
146 11,
147};
148
149static uint8_t getCircleLod(uint8_t _lod)
150{
151 _lod = _lod > BX_COUNTOF(s_circleLod) - 1 ? BX_COUNTOF(s_circleLod) - 1 : _lod;
152 return s_circleLod[_lod];
153}
154
155static void circle(float* _out, float _angle)
156{
157 float sa = bx::sin(_angle);
158 float ca = bx::cos(_angle);
159 _out[0] = sa;
160 _out[1] = ca;
161}
162
163static void squircle(float* _out, float _angle)
164{
165 float sa = bx::sin(_angle);
166 float ca = bx::cos(_angle);
167 _out[0] = bx::sqrt(bx::abs(sa)) * bx::sign(sa);
168 _out[1] = bx::sqrt(bx::abs(ca)) * bx::sign(ca);
169}
170
171uint32_t genSphere(uint8_t _subdiv0,
172 void* _pos0 = NULL,
173 uint16_t _posStride0 = 0,
174 void* _normals0 = NULL,
175 uint16_t _normalStride0 = 0)
176{
177 if(NULL != _pos0)
178 {
179 struct Gen
180 {
181 Gen(void* _pos, uint16_t _posStride, void* _normals, uint16_t _normalStride, uint8_t _subdiv)
182 : m_pos((uint8_t*)_pos)
183 , m_normals((uint8_t*)_normals)
184 , m_posStride(_posStride)
185 , m_normalStride(_normalStride)
186 {
187 static const float scale = 1.0f;
188 static const float golden = 1.6180339887f;
189 static const float len = bx::sqrt(golden * golden + 1.0f);
190 static const float ss = 1.0f / len * scale;
191 static const float ll = ss * golden;
192
193 static const bx::Vec3 vv[] = {
194 {-ll, 0.0f, -ss},
195 {ll, 0.0f, -ss},
196 {ll, 0.0f, ss},
197 {-ll, 0.0f, ss},
198
199 {-ss, ll, 0.0f},
200 {ss, ll, 0.0f},
201 {ss, -ll, 0.0f},
202 {-ss, -ll, 0.0f},
203
204 {0.0f, -ss, ll},
205 {0.0f, ss, ll},
206 {0.0f, ss, -ll},
207 {0.0f, -ss, -ll},
208 };
209
210 m_numVertices = 0;
211
212 triangle(vv[0], vv[4], vv[3], scale, _subdiv);
213 triangle(vv[0], vv[10], vv[4], scale, _subdiv);
214 triangle(vv[4], vv[10], vv[5], scale, _subdiv);
215 triangle(vv[5], vv[10], vv[1], scale, _subdiv);
216 triangle(vv[5], vv[1], vv[2], scale, _subdiv);
217 triangle(vv[5], vv[2], vv[9], scale, _subdiv);
218 triangle(vv[5], vv[9], vv[4], scale, _subdiv);
219 triangle(vv[3], vv[4], vv[9], scale, _subdiv);
220
221 triangle(vv[0], vv[3], vv[7], scale, _subdiv);
222 triangle(vv[0], vv[7], vv[11], scale, _subdiv);
223 triangle(vv[11], vv[7], vv[6], scale, _subdiv);
224 triangle(vv[11], vv[6], vv[1], scale, _subdiv);
225 triangle(vv[1], vv[6], vv[2], scale, _subdiv);
226 triangle(vv[2], vv[6], vv[8], scale, _subdiv);
227 triangle(vv[8], vv[6], vv[7], scale, _subdiv);
228 triangle(vv[8], vv[7], vv[3], scale, _subdiv);
229
230 triangle(vv[0], vv[11], vv[10], scale, _subdiv);
231 triangle(vv[1], vv[10], vv[11], scale, _subdiv);
232 triangle(vv[2], vv[8], vv[9], scale, _subdiv);
233 triangle(vv[3], vv[9], vv[8], scale, _subdiv);
234 }
235
236 void addVert(const bx::Vec3& _v)
237 {
238 bx::store(m_pos, _v);
239 m_pos += m_posStride;
240
241 if(NULL != m_normals)
242 {
243 const bx::Vec3 normal = bx::normalize(_v);
244 bx::store(m_normals, normal);
245
246 m_normals += m_normalStride;
247 }
248
249 m_numVertices++;
250 }
251
252 void triangle(const bx::Vec3& _v0, const bx::Vec3& _v1, const bx::Vec3& _v2, float _scale, uint8_t _subdiv)
253 {
254 if(0 == _subdiv)
255 {
256 addVert(_v0);
257 addVert(_v1);
258 addVert(_v2);
259 }
260 else
261 {
262 const bx::Vec3 v01 = bx::mul(bx::normalize(bx::add(_v0, _v1)), _scale);
263 const bx::Vec3 v12 = bx::mul(bx::normalize(bx::add(_v1, _v2)), _scale);
264 const bx::Vec3 v20 = bx::mul(bx::normalize(bx::add(_v2, _v0)), _scale);
265
266 --_subdiv;
267 triangle(_v0, v01, v20, _scale, _subdiv);
268 triangle(_v1, v12, v01, _scale, _subdiv);
269 triangle(_v2, v20, v12, _scale, _subdiv);
270 triangle(v01, v12, v20, _scale, _subdiv);
271 }
272 }
273
274 uint8_t* m_pos;
275 uint8_t* m_normals;
276 uint16_t m_posStride;
277 uint16_t m_normalStride;
278 uint32_t m_numVertices;
279
280 } gen(_pos0, _posStride0, _normals0, _normalStride0, _subdiv0);
281 }
282
283 uint32_t numVertices = 20 * 3 * bx::max(1, (uint32_t)bx::pow(4.0f, _subdiv0));
284 return numVertices;
285}
286
287bx::Vec3 getPoint(Axis::Enum _axis, float _x, float _y)
288{
289 switch(_axis)
290 {
291 case Axis::X:
292 return {0.0f, _x, _y};
293 case Axis::Y:
294 return {_y, 0.0f, _x};
295 default:
296 break;
297 }
298
299 return {_x, _y, 0.0f};
300}
301
314
315static const bgfx::EmbeddedShader s_embeddedShaders[] = {BGFX_EMBEDDED_SHADER(vs_debugdraw_lines),
316 BGFX_EMBEDDED_SHADER(fs_debugdraw_lines),
317 BGFX_EMBEDDED_SHADER(vs_debugdraw_lines_stipple),
318 BGFX_EMBEDDED_SHADER(fs_debugdraw_lines_stipple),
319 BGFX_EMBEDDED_SHADER(vs_debugdraw_fill),
320 BGFX_EMBEDDED_SHADER(vs_debugdraw_fill_mesh),
321 BGFX_EMBEDDED_SHADER(fs_debugdraw_fill),
322 BGFX_EMBEDDED_SHADER(vs_debugdraw_fill_lit),
323 BGFX_EMBEDDED_SHADER(vs_debugdraw_fill_lit_mesh),
324 BGFX_EMBEDDED_SHADER(fs_debugdraw_fill_lit),
325 BGFX_EMBEDDED_SHADER(vs_debugdraw_fill_texture),
326 BGFX_EMBEDDED_SHADER(fs_debugdraw_fill_texture),
327
328 BGFX_EMBEDDED_SHADER_END()};
329
330#define SPRITE_TEXTURE_SIZE 1024
331
332template<uint16_t MaxHandlesT = 256, uint16_t TextureSizeT = 1024>
334{
335 SpriteT() : m_ra(TextureSizeT, TextureSizeT)
336 {
337 }
338
339 SpriteHandle create(uint16_t _width, uint16_t _height)
340 {
341 bx::MutexScope lock(m_lock);
342
343 SpriteHandle handle = {bx::kInvalidHandle};
344
345 if(m_handleAlloc.getNumHandles() < m_handleAlloc.getMaxHandles())
346 {
347 Pack2D pack;
348 if(m_ra.find(_width, _height, pack))
349 {
350 handle.idx = m_handleAlloc.alloc();
351
352 if(isValid(handle))
353 {
354 m_pack[handle.idx] = pack;
355 }
356 else
357 {
358 m_ra.clear(pack);
359 }
360 }
361 }
362
363 return handle;
364 }
365
366 void destroy(SpriteHandle _sprite)
367 {
368 const Pack2D& pack = m_pack[_sprite.idx];
369 m_ra.clear(pack);
370 m_handleAlloc.free(_sprite.idx);
371 }
372
373 const Pack2D& get(SpriteHandle _sprite) const
374 {
375 return m_pack[_sprite.idx];
376 }
377
378 bx::Mutex m_lock;
379 bx::HandleAllocT<MaxHandlesT> m_handleAlloc;
380 Pack2D m_pack[MaxHandlesT];
382};
383
384template<uint16_t MaxHandlesT = DEBUG_DRAW_CONFIG_MAX_GEOMETRY>
386{
388 {
389 }
390
391 GeometryHandle create(uint32_t _numVertices,
392 const DdVertex* _vertices,
393 uint32_t _numIndices,
394 const void* _indices,
395 bool _index32)
396 {
397 BX_UNUSED(_numVertices, _vertices, _numIndices, _indices, _index32);
398
400 {
401 bx::MutexScope lock(m_lock);
402 handle = {m_handleAlloc.alloc()};
403 }
404
405 if(isValid(handle))
406 {
407 Geometry& geometry = m_geometry[handle.idx];
408 geometry.m_vbh = bgfx::createVertexBuffer(bgfx::copy(_vertices, _numVertices * sizeof(DdVertex)),
410
411 geometry.m_topologyNumIndices[0] = _numIndices;
412 geometry.m_topologyNumIndices[1] = bgfx::topologyConvert(bgfx::TopologyConvert::TriListToLineList,
413 NULL,
414 0,
415 _indices,
416 _numIndices,
417 _index32);
418
419 const uint32_t indexSize = _index32 ? sizeof(uint32_t) : sizeof(uint16_t);
420
421 const uint32_t numIndices = 0 + geometry.m_topologyNumIndices[0] + geometry.m_topologyNumIndices[1];
422 const bgfx::Memory* mem = bgfx::alloc(numIndices * indexSize);
423 uint8_t* indexData = mem->data;
424
425 bx::memCopy(indexData, _indices, _numIndices * indexSize);
426 bgfx::topologyConvert(bgfx::TopologyConvert::TriListToLineList,
427 &indexData[geometry.m_topologyNumIndices[0] * indexSize],
428 geometry.m_topologyNumIndices[1] * indexSize,
429 _indices,
430 _numIndices,
431 _index32);
432
433 geometry.m_ibh = bgfx::createIndexBuffer(mem, _index32 ? BGFX_BUFFER_INDEX32 : BGFX_BUFFER_NONE);
434 }
435
436 return handle;
437 }
438
440 {
441 bx::MutexScope lock(m_lock);
442 Geometry& geometry = m_geometry[_handle.idx];
443 bgfx::destroy(geometry.m_vbh);
444 bgfx::destroy(geometry.m_ibh);
445
446 m_handleAlloc.free(_handle.idx);
447 }
448
449 struct Geometry
450 {
452 {
453 m_vbh.idx = bx::kInvalidHandle;
454 m_ibh.idx = bx::kInvalidHandle;
457 }
458
459 bgfx::VertexBufferHandle m_vbh;
460 bgfx::IndexBufferHandle m_ibh;
462 };
463
464 bx::Mutex m_lock;
465 bx::HandleAllocT<MaxHandlesT> m_handleAlloc;
466 Geometry m_geometry[MaxHandlesT];
467};
468
469struct Attrib
470{
471 uint64_t m_state;
473 float m_offset;
474 float m_scale;
475 float m_spin;
476 uint32_t m_abgr;
479 uint8_t m_lod;
480};
481
497
539
542
544{
545 void init(bx::AllocatorI* _allocator)
546 {
547 if(NULL == _allocator)
548 {
549 static bx::DefaultAllocator allocator;
550 m_allocator = &allocator;
551 }
552 else
553 {
554 m_allocator = _allocator;
555 }
556
561
562 bgfx::RendererType::Enum type = bgfx::getRendererType();
563
565 bgfx::createProgram(bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_debugdraw_lines"),
566 bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_debugdraw_lines"),
567 true);
568
570 bgfx::createProgram(bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_debugdraw_lines_stipple"),
571 bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_debugdraw_lines_stipple"),
572 true);
573
575 bgfx::createProgram(bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_debugdraw_fill"),
576 bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_debugdraw_fill"),
577 true);
578
580 bgfx::createProgram(bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_debugdraw_fill_mesh"),
581 bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_debugdraw_fill"),
582 true);
583
585 bgfx::createProgram(bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_debugdraw_fill_lit"),
586 bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_debugdraw_fill_lit"),
587 true);
588
590 bgfx::createProgram(bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_debugdraw_fill_lit_mesh"),
591 bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_debugdraw_fill_lit"),
592 true);
593
595 bgfx::createProgram(bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_debugdraw_fill_texture"),
596 bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_debugdraw_fill_texture"),
597 true);
598
599 u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, 4);
600 s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Sampler);
601 m_texture =
602 bgfx::createTexture2D(SPRITE_TEXTURE_SIZE, SPRITE_TEXTURE_SIZE, false, 1, bgfx::TextureFormat::BGRA8);
603
604 void* vertices[DebugMesh::Count] = {};
605 uint16_t* indices[DebugMesh::Count] = {};
606 uint16_t stride = DebugShapeVertex::ms_layout.getStride();
607
608 uint32_t startVertex = 0;
609 uint32_t startIndex = 0;
610
611 for(uint32_t mesh = 0; mesh < 4; ++mesh)
612 {
614
615 const uint8_t tess = uint8_t(3 - mesh);
616 const uint32_t numVertices = genSphere(tess);
617 const uint32_t numIndices = numVertices;
618
619 vertices[id] = bx::alloc(m_allocator, numVertices * stride);
620 bx::memSet(vertices[id], 0, numVertices * stride);
621 genSphere(tess, vertices[id], stride);
622
623 uint16_t* trilist = (uint16_t*)bx::alloc(m_allocator, numIndices * sizeof(uint16_t));
624 for(uint32_t ii = 0; ii < numIndices; ++ii)
625 {
626 trilist[ii] = uint16_t(ii);
627 }
628
629 uint32_t numLineListIndices =
630 bgfx::topologyConvert(bgfx::TopologyConvert::TriListToLineList, NULL, 0, trilist, numIndices, false);
631 indices[id] = (uint16_t*)bx::alloc(m_allocator, (numIndices + numLineListIndices) * sizeof(uint16_t));
632 uint16_t* indicesOut = indices[id];
633 bx::memCopy(indicesOut, trilist, numIndices * sizeof(uint16_t));
634
635 bgfx::topologyConvert(bgfx::TopologyConvert::TriListToLineList,
636 &indicesOut[numIndices],
637 numLineListIndices * sizeof(uint16_t),
638 trilist,
639 numIndices,
640 false);
641
642 m_mesh[id].m_startVertex = startVertex;
643 m_mesh[id].m_numVertices = numVertices;
644 m_mesh[id].m_startIndex[0] = startIndex;
645 m_mesh[id].m_numIndices[0] = numIndices;
646 m_mesh[id].m_startIndex[1] = startIndex + numIndices;
647 m_mesh[id].m_numIndices[1] = numLineListIndices;
648
649 startVertex += numVertices;
650 startIndex += numIndices + numLineListIndices;
651
652 bx::free(m_allocator, trilist);
653 }
654
655 for(uint32_t mesh = 0; mesh < 4; ++mesh)
656 {
658
659 const uint32_t num = getCircleLod(uint8_t(mesh));
660 const float step = bx::kPi * 2.0f / num;
661
662 const uint32_t numVertices = num + 1;
663 const uint32_t numIndices = num * 6;
664 const uint32_t numLineListIndices = num * 4;
665
666 vertices[id] = bx::alloc(m_allocator, numVertices * stride);
667 indices[id] = (uint16_t*)bx::alloc(m_allocator, (numIndices + numLineListIndices) * sizeof(uint16_t));
668 bx::memSet(indices[id], 0, (numIndices + numLineListIndices) * sizeof(uint16_t));
669
670 DebugShapeVertex* vertex = (DebugShapeVertex*)vertices[id];
671 uint16_t* index = indices[id];
672
673 vertex[num].m_x = 0.0f;
674 vertex[num].m_y = 0.0f;
675 vertex[num].m_z = 0.0f;
676 vertex[num].m_indices[0] = 1;
677
678 for(uint32_t ii = 0; ii < num; ++ii)
679 {
680 const float angle = step * ii;
681
682 float xy[2];
683 circle(xy, angle);
684
685 vertex[ii].m_x = xy[1];
686 vertex[ii].m_y = 0.0f;
687 vertex[ii].m_z = xy[0];
688 vertex[ii].m_indices[0] = 0;
689
690 index[ii * 3 + 0] = uint16_t(num);
691 index[ii * 3 + 1] = uint16_t((ii + 1) % num);
692 index[ii * 3 + 2] = uint16_t(ii);
693
694 index[num * 3 + ii * 3 + 0] = 0;
695 index[num * 3 + ii * 3 + 1] = uint16_t(ii);
696 index[num * 3 + ii * 3 + 2] = uint16_t((ii + 1) % num);
697
698 index[numIndices + ii * 2 + 0] = uint16_t(ii);
699 index[numIndices + ii * 2 + 1] = uint16_t(num);
700
701 index[numIndices + num * 2 + ii * 2 + 0] = uint16_t(ii);
702 index[numIndices + num * 2 + ii * 2 + 1] = uint16_t((ii + 1) % num);
703 }
704
705 m_mesh[id].m_startVertex = startVertex;
706 m_mesh[id].m_numVertices = numVertices;
707 m_mesh[id].m_startIndex[0] = startIndex;
708 m_mesh[id].m_numIndices[0] = numIndices;
709 m_mesh[id].m_startIndex[1] = startIndex + numIndices;
710 m_mesh[id].m_numIndices[1] = numLineListIndices;
711
712 startVertex += numVertices;
713 startIndex += numIndices + numLineListIndices;
714 }
715
716 for(uint32_t mesh = 0; mesh < 4; ++mesh)
717 {
719
720 const uint32_t num = getCircleLod(uint8_t(mesh));
721 const float step = bx::kPi * 2.0f / num;
722
723 const uint32_t numVertices = num * 2;
724 const uint32_t numIndices = num * 12;
725 const uint32_t numLineListIndices = num * 6;
726
727 vertices[id] = bx::alloc(m_allocator, numVertices * stride);
728 indices[id] = (uint16_t*)bx::alloc(m_allocator, (numIndices + numLineListIndices) * sizeof(uint16_t));
729 bx::memSet(indices[id], 0, (numIndices + numLineListIndices) * sizeof(uint16_t));
730
731 DebugShapeVertex* vertex = (DebugShapeVertex*)vertices[id];
732 uint16_t* index = indices[id];
733
734 for(uint32_t ii = 0; ii < num; ++ii)
735 {
736 const float angle = step * ii;
737
738 float xy[2];
739 circle(xy, angle);
740
741 vertex[ii].m_x = xy[1];
742 vertex[ii].m_y = 0.0f;
743 vertex[ii].m_z = xy[0];
744 vertex[ii].m_indices[0] = 0;
745
746 vertex[ii + num].m_x = xy[1];
747 vertex[ii + num].m_y = 0.0f;
748 vertex[ii + num].m_z = xy[0];
749 vertex[ii + num].m_indices[0] = 1;
750
751 index[ii * 6 + 0] = uint16_t(ii + num);
752 index[ii * 6 + 1] = uint16_t((ii + 1) % num);
753 index[ii * 6 + 2] = uint16_t(ii);
754 index[ii * 6 + 3] = uint16_t(ii + num);
755 index[ii * 6 + 4] = uint16_t((ii + 1) % num + num);
756 index[ii * 6 + 5] = uint16_t((ii + 1) % num);
757
758 index[num * 6 + ii * 6 + 0] = uint16_t(0);
759 index[num * 6 + ii * 6 + 1] = uint16_t(ii);
760 index[num * 6 + ii * 6 + 2] = uint16_t((ii + 1) % num);
761 index[num * 6 + ii * 6 + 3] = uint16_t(num);
762 index[num * 6 + ii * 6 + 4] = uint16_t((ii + 1) % num + num);
763 index[num * 6 + ii * 6 + 5] = uint16_t(ii + num);
764
765 index[numIndices + ii * 2 + 0] = uint16_t(ii);
766 index[numIndices + ii * 2 + 1] = uint16_t(ii + num);
767
768 index[numIndices + num * 2 + ii * 2 + 0] = uint16_t(ii);
769 index[numIndices + num * 2 + ii * 2 + 1] = uint16_t((ii + 1) % num);
770
771 index[numIndices + num * 4 + ii * 2 + 0] = uint16_t(num + ii);
772 index[numIndices + num * 4 + ii * 2 + 1] = uint16_t(num + (ii + 1) % num);
773 }
774
775 m_mesh[id].m_startVertex = startVertex;
776 m_mesh[id].m_numVertices = numVertices;
777 m_mesh[id].m_startIndex[0] = startIndex;
778 m_mesh[id].m_numIndices[0] = numIndices;
779 m_mesh[id].m_startIndex[1] = startIndex + numIndices;
780 m_mesh[id].m_numIndices[1] = numLineListIndices;
781
782 startVertex += numVertices;
783 startIndex += numIndices + numLineListIndices;
784 }
785
786 for(uint32_t mesh = 0; mesh < 4; ++mesh)
787 {
789
790 const uint32_t num = getCircleLod(uint8_t(mesh));
791 const float step = bx::kPi * 2.0f / num;
792
793 const uint32_t numVertices = num * 2;
794 const uint32_t numIndices = num * 6;
795 const uint32_t numLineListIndices = num * 6;
796
797 vertices[id] = bx::alloc(m_allocator, numVertices * stride);
798 indices[id] = (uint16_t*)bx::alloc(m_allocator, (numIndices + numLineListIndices) * sizeof(uint16_t));
799 bx::memSet(indices[id], 0, (numIndices + numLineListIndices) * sizeof(uint16_t));
800
801 DebugShapeVertex* vertex = (DebugShapeVertex*)vertices[id];
802 uint16_t* index = indices[id];
803
804 for(uint32_t ii = 0; ii < num; ++ii)
805 {
806 const float angle = step * ii;
807
808 float xy[2];
809 circle(xy, angle);
810
811 vertex[ii].m_x = xy[1];
812 vertex[ii].m_y = 0.0f;
813 vertex[ii].m_z = xy[0];
814 vertex[ii].m_indices[0] = 0;
815
816 vertex[ii + num].m_x = xy[1];
817 vertex[ii + num].m_y = 0.0f;
818 vertex[ii + num].m_z = xy[0];
819 vertex[ii + num].m_indices[0] = 1;
820
821 index[ii * 6 + 0] = uint16_t(ii + num);
822 index[ii * 6 + 1] = uint16_t((ii + 1) % num);
823 index[ii * 6 + 2] = uint16_t(ii);
824 index[ii * 6 + 3] = uint16_t(ii + num);
825 index[ii * 6 + 4] = uint16_t((ii + 1) % num + num);
826 index[ii * 6 + 5] = uint16_t((ii + 1) % num);
827
828 // index[num*6+ii*6+0] = uint16_t(0);
829 // index[num*6+ii*6+1] = uint16_t(ii);
830 // index[num*6+ii*6+2] = uint16_t( (ii+1)%num);
831 // index[num*6+ii*6+3] = uint16_t(num);
832 // index[num*6+ii*6+4] = uint16_t( (ii+1)%num+num);
833 // index[num*6+ii*6+5] = uint16_t(ii+num);
834
835 index[numIndices + ii * 2 + 0] = uint16_t(ii);
836 index[numIndices + ii * 2 + 1] = uint16_t(ii + num);
837
838 index[numIndices + num * 2 + ii * 2 + 0] = uint16_t(ii);
839 index[numIndices + num * 2 + ii * 2 + 1] = uint16_t((ii + 1) % num);
840
841 index[numIndices + num * 4 + ii * 2 + 0] = uint16_t(num + ii);
842 index[numIndices + num * 4 + ii * 2 + 1] = uint16_t(num + (ii + 1) % num);
843 }
844
845 m_mesh[id].m_startVertex = startVertex;
846 m_mesh[id].m_numVertices = numVertices;
847 m_mesh[id].m_startIndex[0] = startIndex;
848 m_mesh[id].m_numIndices[0] = numIndices;
849 m_mesh[id].m_startIndex[1] = startIndex + numIndices;
850 m_mesh[id].m_numIndices[1] = numLineListIndices;
851
852 startVertex += numVertices;
853 startIndex += numIndices + numLineListIndices;
854 }
855
856 m_mesh[DebugMesh::Quad].m_startVertex = startVertex;
858 m_mesh[DebugMesh::Quad].m_startIndex[0] = startIndex;
862 startVertex += BX_COUNTOF(s_quadVertices);
863 startIndex += BX_COUNTOF(s_quadIndices);
864
865 m_mesh[DebugMesh::Cube].m_startVertex = startVertex;
867 m_mesh[DebugMesh::Cube].m_startIndex[0] = startIndex;
871 startVertex += m_mesh[DebugMesh::Cube].m_numVertices;
872 startIndex += m_mesh[DebugMesh::Cube].m_numIndices[0];
873
874 const bgfx::Memory* vb = bgfx::alloc(startVertex * stride);
875 const bgfx::Memory* ib = bgfx::alloc(startIndex * sizeof(uint16_t));
876
877 for(uint32_t mesh = DebugMesh::Sphere0; mesh < DebugMesh::Quad; ++mesh)
878 {
880 bx::memCopy(&vb->data[m_mesh[id].m_startVertex * stride], vertices[id], m_mesh[id].m_numVertices * stride);
881
882 bx::memCopy(&ib->data[m_mesh[id].m_startIndex[0] * sizeof(uint16_t)],
883 indices[id],
884 (m_mesh[id].m_numIndices[0] + m_mesh[id].m_numIndices[1]) * sizeof(uint16_t));
885
886 bx::free(m_allocator, vertices[id]);
887 bx::free(m_allocator, indices[id]);
888 }
889
890 bx::memCopy(&vb->data[m_mesh[DebugMesh::Quad].m_startVertex * stride], s_quadVertices, sizeof(s_quadVertices));
891
892 bx::memCopy(&ib->data[m_mesh[DebugMesh::Quad].m_startIndex[0] * sizeof(uint16_t)],
894 sizeof(s_quadIndices));
895
896 bx::memCopy(&vb->data[m_mesh[DebugMesh::Cube].m_startVertex * stride], s_cubeVertices, sizeof(s_cubeVertices));
897
898 bx::memCopy(&ib->data[m_mesh[DebugMesh::Cube].m_startIndex[0] * sizeof(uint16_t)],
900 sizeof(s_cubeIndices));
901
902 m_vbh = bgfx::createVertexBuffer(vb, DebugShapeVertex::ms_layout);
903 m_ibh = bgfx::createIndexBuffer(ib);
904 }
905
906 void shutdown()
907 {
908 bgfx::destroy(m_ibh);
909 bgfx::destroy(m_vbh);
910 for(uint32_t ii = 0; ii < Program::Count; ++ii)
911 {
912 bgfx::destroy(m_program[ii]);
913 }
914 bgfx::destroy(u_params);
915 bgfx::destroy(s_texColor);
916 bgfx::destroy(m_texture);
917 }
918
919 SpriteHandle createSprite(uint16_t _width, uint16_t _height, const void* _data)
920 {
921 SpriteHandle handle = m_sprite.create(_width, _height);
922
923 if(isValid(handle))
924 {
925 const Pack2D& pack = m_sprite.get(handle);
926 bgfx::updateTexture2D(m_texture,
927 0,
928 0,
929 pack.m_x,
930 pack.m_y,
931 pack.m_width,
932 pack.m_height,
933 bgfx::copy(_data, pack.m_width * pack.m_height * 4));
934 }
935
936 return handle;
937 }
938
939 void destroy(SpriteHandle _handle)
940 {
941 m_sprite.destroy(_handle);
942 }
943
944 GeometryHandle createGeometry(uint32_t _numVertices,
945 const DdVertex* _vertices,
946 uint32_t _numIndices,
947 const void* _indices,
948 bool _index32)
949 {
950 return m_geometry.create(_numVertices, _vertices, _numIndices, _indices, _index32);
951 }
952
954 {
955 m_geometry.destroy(_handle);
956 }
957
958 bx::AllocatorI* m_allocator;
959
962
964
965 bgfx::UniformHandle s_texColor;
966 bgfx::TextureHandle m_texture;
967 bgfx::ProgramHandle m_program[Program::Count];
968 bgfx::UniformHandle u_params;
969
970 bgfx::VertexBufferHandle m_vbh;
971 bgfx::IndexBufferHandle m_ibh;
972};
973
975
977{
979 {
980 bx::memSet(&m_cache, 0, sizeof(m_cache));
981 bx::memSet(&m_cacheQuad, 0, sizeof(m_cacheQuad));
982 bx::memSet(&m_indices, 0, sizeof(m_indices));
983 }
984
985 void init(bgfx::Encoder* _encoder)
986 {
987 m_defaultEncoder = _encoder;
989 }
990
991 void shutdown()
992 {
993 }
994
995 void begin(bgfx::ViewId _viewId, bool _depthTestLess, bgfx::Encoder* _encoder)
996 {
997 BX_ASSERT(State::Count == m_state, "");
998
999 m_viewId = _viewId;
1000 m_encoder = _encoder == NULL ? m_defaultEncoder : _encoder;
1002 m_stack = 0;
1003 m_depthTestLess = _depthTestLess;
1004
1005 m_pos = 0;
1006 m_indexPos = 0;
1007 m_vertexPos = 0;
1008 m_posQuad = 0;
1009
1010 Attrib& attrib = m_attrib[0];
1011 attrib.m_state = 0 | BGFX_STATE_WRITE_RGB |
1012 (m_depthTestLess ? BGFX_STATE_DEPTH_TEST_LESS : BGFX_STATE_DEPTH_TEST_GREATER) |
1013 BGFX_STATE_CULL_CW | BGFX_STATE_WRITE_Z;
1014 attrib.m_scale = 1.0f;
1015 attrib.m_spin = 0.0f;
1016 attrib.m_offset = 0.0f;
1017 attrib.m_abgr = UINT32_MAX;
1018 attrib.m_stipple = false;
1019 attrib.m_wireframe = false;
1020 attrib.m_lod = 0;
1021 attrib.m_alphaBlend = true;
1022
1025
1027 for(auto& program : m_programStack)
1028 {
1029 program = {bgfx::kInvalidHandle};
1030 }
1031 }
1032
1033 void end()
1034 {
1035 BX_ASSERT(0 == m_stack, "Invalid stack %d.", m_stack);
1036
1037 flushQuad();
1038 flush();
1039
1040 m_encoder = NULL;
1042 }
1043
1044 void push()
1045 {
1046 BX_ASSERT(State::Count != m_state, "");
1047 ++m_stack;
1049 }
1050
1051 void pop()
1052 {
1053 BX_ASSERT(State::Count != m_state, "");
1054 const Attrib& curr = m_attrib[m_stack];
1055 const Attrib& prev = m_attrib[m_stack - 1];
1056 if(curr.m_stipple != prev.m_stipple || curr.m_state != prev.m_state)
1057 {
1058 flush();
1059 }
1060 --m_stack;
1061 }
1062
1063 void setDepthTestLess(bool _depthTestLess)
1064 {
1065 BX_ASSERT(State::Count != m_state, "");
1066 if(m_depthTestLess != _depthTestLess)
1067 {
1068 m_depthTestLess = _depthTestLess;
1069 Attrib& attrib = m_attrib[m_stack];
1070 if(attrib.m_state & BGFX_STATE_DEPTH_TEST_MASK)
1071 {
1072 flush();
1073 attrib.m_state &= ~BGFX_STATE_DEPTH_TEST_MASK;
1074 attrib.m_state |= _depthTestLess ? BGFX_STATE_DEPTH_TEST_LESS : BGFX_STATE_DEPTH_TEST_GREATER;
1075 }
1076 }
1077 }
1078
1079 void setTransform(const void* _mtx, uint16_t _num = 1, bool _flush = true)
1080 {
1081 BX_ASSERT(State::Count != m_state, "");
1082 if(_flush)
1083 {
1084 flush();
1085 }
1086
1088
1089 if(NULL == _mtx)
1090 {
1091 stack.reset();
1092 return;
1093 }
1094
1095 bgfx::Transform transform;
1096 stack.mtx = m_encoder->allocTransform(&transform, _num);
1097 stack.num = _num;
1098 stack.data = transform.data;
1099 bx::memCopy(transform.data, _mtx, _num * 64);
1100 }
1101
1102 void setTranslate(float _x, float _y, float _z)
1103 {
1104 float mtx[16];
1105 bx::mtxTranslate(mtx, _x, _y, _z);
1106 setTransform(mtx);
1107 }
1108
1109 void setTranslate(const float* _pos)
1110 {
1111 setTranslate(_pos[0], _pos[1], _pos[2]);
1112 }
1113
1114 void pushTransform(const void* _mtx, uint16_t _num, bool _flush = true)
1115 {
1116 BX_ASSERT(m_mtxStackCurrent < BX_COUNTOF(m_mtxStack), "Out of matrix stack!");
1117 BX_ASSERT(State::Count != m_state, "");
1118 if(_flush)
1119 {
1120 flush();
1121 }
1122
1123 float* mtx = NULL;
1124
1126
1127 if(NULL == stack.data)
1128 {
1129 mtx = (float*)_mtx;
1130 }
1131 else
1132 {
1133 mtx = (float*)BX_STACK_ALLOC(_num*64);
1134 for(uint16_t ii = 0; ii < _num; ++ii)
1135 {
1136 const float* mtxTransform = (const float*)_mtx;
1137 bx::mtxMul(&mtx[ii * 16], &mtxTransform[ii * 16], stack.data);
1138 }
1139 }
1140
1142 setTransform(mtx, _num, _flush);
1143 }
1144
1145 void popTransform(bool _flush = true)
1146 {
1147 BX_ASSERT(State::Count != m_state, "");
1148 if(_flush)
1149 {
1150 flush();
1151 }
1152
1154 }
1155
1156
1157 void pushProgram(bgfx::ProgramHandle _handle)
1158 {
1159 BX_ASSERT(State::Count != m_state, "");
1160
1162
1164 }
1165
1167 {
1168 BX_ASSERT(State::Count != m_state, "");
1169 BX_ASSERT(m_programStackCurrent > -1, "");
1170
1172 }
1173
1174 void pushTranslate(float _x, float _y, float _z)
1175 {
1176 float mtx[16];
1177 bx::mtxTranslate(mtx, _x, _y, _z);
1178 pushTransform(mtx, 1);
1179 }
1180
1181 void pushTranslate(const bx::Vec3& _pos)
1182 {
1183 pushTranslate(_pos.x, _pos.y, _pos.z);
1184 }
1185
1186 void setState(bool _depthTest, bool _depthWrite, bool _clockwise, bool _alphaWrite, bool _alphaBlend)
1187 {
1188 const uint64_t depthTest = m_depthTestLess ? BGFX_STATE_DEPTH_TEST_LESS : BGFX_STATE_DEPTH_TEST_GREATER;
1189
1190 uint64_t state = m_attrib[m_stack].m_state & ~(0 | BGFX_STATE_DEPTH_TEST_MASK | BGFX_STATE_WRITE_Z |
1191 BGFX_STATE_CULL_CW | BGFX_STATE_CULL_CCW);
1192
1193 state |= _depthTest ? depthTest : 0;
1194
1195 state |= _depthWrite ? BGFX_STATE_WRITE_Z : 0;
1196
1197 state |= _alphaWrite ? BGFX_STATE_WRITE_A : 0;
1198
1199 state |= _clockwise ? BGFX_STATE_CULL_CW : BGFX_STATE_CULL_CCW;
1200
1201 if(m_attrib[m_stack].m_state != state || m_attrib[m_stack].m_alphaBlend != _alphaBlend)
1202 {
1203 flush();
1204 }
1205
1206 m_attrib[m_stack].m_state = state;
1207 m_attrib[m_stack].m_alphaBlend = _alphaBlend;
1208 }
1209
1210 void setColor(uint32_t _abgr)
1211 {
1212 BX_ASSERT(State::Count != m_state, "");
1213 m_attrib[m_stack].m_abgr = _abgr;
1214 }
1215
1216 void setLod(uint8_t _lod)
1217 {
1218 BX_ASSERT(State::Count != m_state, "");
1219 m_attrib[m_stack].m_lod = _lod;
1220 }
1221
1222 void setWireframe(bool _wireframe)
1223 {
1224 BX_ASSERT(State::Count != m_state, "");
1225 m_attrib[m_stack].m_wireframe = _wireframe;
1226 }
1227
1228 void setStipple(bool _stipple, float _scale = 1.0f, float _offset = 0.0f)
1229 {
1230 BX_ASSERT(State::Count != m_state, "");
1231
1232 Attrib& attrib = m_attrib[m_stack];
1233
1234 if(attrib.m_stipple != _stipple)
1235 {
1236 flush();
1237 }
1238
1239 attrib.m_stipple = _stipple;
1240 attrib.m_offset = _offset;
1241 attrib.m_scale = _scale;
1242 }
1243
1244 void setSpin(float _spin)
1245 {
1246 Attrib& attrib = m_attrib[m_stack];
1247 attrib.m_spin = _spin;
1248 }
1249
1250 void moveTo(float _x, float _y, float _z = 0.0f)
1251 {
1252 BX_ASSERT(State::Count != m_state, "");
1253
1254 softFlush();
1255
1257
1258 DebugVertex& vertex = m_cache[m_pos];
1259 vertex.m_x = _x;
1260 vertex.m_y = _y;
1261 vertex.m_z = _z;
1262
1263 Attrib& attrib = m_attrib[m_stack];
1264 vertex.m_abgr = attrib.m_abgr;
1265 vertex.m_len = attrib.m_offset;
1266
1268 }
1269
1270 void moveTo(const bx::Vec3& _pos)
1271 {
1272 BX_ASSERT(State::Count != m_state, "");
1273 moveTo(_pos.x, _pos.y, _pos.z);
1274 }
1275
1276 void moveTo(Axis::Enum _axis, float _x, float _y)
1277 {
1278 moveTo(getPoint(_axis, _x, _y));
1279 }
1280
1281 void lineTo(float _x, float _y, float _z = 0.0f)
1282 {
1283 BX_ASSERT(State::Count != m_state, "");
1284 if(State::None == m_state)
1285 {
1286 moveTo(_x, _y, _z);
1287 return;
1288 }
1289
1290 if(m_pos + 2 > uint16_t(BX_COUNTOF(m_cache)))
1291 {
1292 uint32_t pos = m_pos;
1293 uint32_t vertexPos = m_vertexPos;
1294
1295 flush();
1296
1297 bx::memCopy(&m_cache[0], &m_cache[vertexPos], sizeof(DebugVertex));
1298 if(vertexPos == pos)
1299 {
1300 m_pos = 1;
1301 }
1302 else
1303 {
1304 bx::memCopy(&m_cache[1], &m_cache[pos - 1], sizeof(DebugVertex));
1305 m_pos = 2;
1306 }
1307
1309 }
1310 else if(State::MoveTo == m_state)
1311 {
1312 ++m_pos;
1314 }
1315
1316 uint16_t prev = m_pos - 1;
1317 uint16_t curr = m_pos++;
1318 DebugVertex& vertex = m_cache[curr];
1319 vertex.m_x = _x;
1320 vertex.m_y = _y;
1321 vertex.m_z = _z;
1322
1323 Attrib& attrib = m_attrib[m_stack];
1324 vertex.m_abgr = attrib.m_abgr;
1325 vertex.m_len = attrib.m_offset;
1326
1327 float len = bx::length(bx::sub(bx::load<bx::Vec3>(&vertex.m_x), bx::load<bx::Vec3>(&m_cache[prev].m_x))) *
1328 attrib.m_scale;
1329 vertex.m_len = m_cache[prev].m_len + len;
1330
1331 m_indices[m_indexPos++] = prev;
1332 m_indices[m_indexPos++] = curr;
1333 }
1334
1335 void lineTo(const bx::Vec3& _pos)
1336 {
1337 BX_ASSERT(State::Count != m_state, "");
1338 lineTo(_pos.x, _pos.y, _pos.z);
1339 }
1340
1341 void lineTo(Axis::Enum _axis, float _x, float _y)
1342 {
1343 lineTo(getPoint(_axis, _x, _y));
1344 }
1345
1346 void close()
1347 {
1348 BX_ASSERT(State::Count != m_state, "");
1349 DebugVertex& vertex = m_cache[m_vertexPos];
1350 lineTo(vertex.m_x, vertex.m_y, vertex.m_z);
1351
1353 }
1354
1355 void draw(const bx::Aabb& _aabb)
1356 {
1357 const Attrib& attrib = m_attrib[m_stack];
1358 if(attrib.m_wireframe)
1359 {
1360 moveTo(_aabb.min.x, _aabb.min.y, _aabb.min.z);
1361 lineTo(_aabb.max.x, _aabb.min.y, _aabb.min.z);
1362 lineTo(_aabb.max.x, _aabb.max.y, _aabb.min.z);
1363 lineTo(_aabb.min.x, _aabb.max.y, _aabb.min.z);
1364 close();
1365
1366 moveTo(_aabb.min.x, _aabb.min.y, _aabb.max.z);
1367 lineTo(_aabb.max.x, _aabb.min.y, _aabb.max.z);
1368 lineTo(_aabb.max.x, _aabb.max.y, _aabb.max.z);
1369 lineTo(_aabb.min.x, _aabb.max.y, _aabb.max.z);
1370 close();
1371
1372 moveTo(_aabb.min.x, _aabb.min.y, _aabb.min.z);
1373 lineTo(_aabb.min.x, _aabb.min.y, _aabb.max.z);
1374
1375 moveTo(_aabb.max.x, _aabb.min.y, _aabb.min.z);
1376 lineTo(_aabb.max.x, _aabb.min.y, _aabb.max.z);
1377
1378 moveTo(_aabb.min.x, _aabb.max.y, _aabb.min.z);
1379 lineTo(_aabb.min.x, _aabb.max.y, _aabb.max.z);
1380
1381 moveTo(_aabb.max.x, _aabb.max.y, _aabb.min.z);
1382 lineTo(_aabb.max.x, _aabb.max.y, _aabb.max.z);
1383 }
1384 else
1385 {
1386 bx::Obb obb;
1387 toObb(obb, _aabb);
1388 draw(DebugMesh::Cube, obb.mtx, 1, false);
1389 }
1390 }
1391
1392 void draw(const bx::Cylinder& _cylinder, bool _capsule)
1393 {
1394 drawCylinder(_cylinder.pos, _cylinder.end, _cylinder.radius, _capsule);
1395 }
1396
1397 void draw(const bx::Disk& _disk)
1398 {
1399 drawCircle(_disk.normal, _disk.center, _disk.radius, 0.0f);
1400 }
1401
1402 void draw(const bx::Obb& _obb)
1403 {
1404 const Attrib& attrib = m_attrib[m_stack];
1405 if(attrib.m_wireframe)
1406 {
1407 pushTransform(_obb.mtx, 1);
1408
1409 moveTo(-1.0f, -1.0f, -1.0f);
1410 lineTo(1.0f, -1.0f, -1.0f);
1411 lineTo(1.0f, 1.0f, -1.0f);
1412 lineTo(-1.0f, 1.0f, -1.0f);
1413 close();
1414
1415 moveTo(-1.0f, 1.0f, 1.0f);
1416 lineTo(1.0f, 1.0f, 1.0f);
1417 lineTo(1.0f, -1.0f, 1.0f);
1418 lineTo(-1.0f, -1.0f, 1.0f);
1419 close();
1420
1421 moveTo(1.0f, -1.0f, -1.0f);
1422 lineTo(1.0f, -1.0f, 1.0f);
1423
1424 moveTo(1.0f, 1.0f, -1.0f);
1425 lineTo(1.0f, 1.0f, 1.0f);
1426
1427 moveTo(-1.0f, 1.0f, -1.0f);
1428 lineTo(-1.0f, 1.0f, 1.0f);
1429
1430 moveTo(-1.0f, -1.0f, -1.0f);
1431 lineTo(-1.0f, -1.0f, 1.0f);
1432
1433 popTransform();
1434 }
1435 else
1436 {
1437 draw(DebugMesh::Cube, _obb.mtx, 1, false);
1438 }
1439 }
1440
1441 void draw(const bx::Sphere& _sphere)
1442 {
1443 const Attrib& attrib = m_attrib[m_stack];
1444 float mtx[16];
1445 bx::mtxSRT(mtx,
1446 _sphere.radius,
1447 _sphere.radius,
1448 _sphere.radius,
1449 0.0f,
1450 0.0f,
1451 0.0f,
1452 _sphere.center.x,
1453 _sphere.center.y,
1454 _sphere.center.z);
1455 uint8_t lod = attrib.m_lod > DebugMesh::SphereMaxLod ? uint8_t(DebugMesh::SphereMaxLod) : attrib.m_lod;
1456 draw(DebugMesh::Enum(DebugMesh::Sphere0 + lod), mtx, 1, attrib.m_wireframe);
1457 }
1458
1459 void draw(const bx::Triangle& _triangle)
1460 {
1461 Attrib& attrib = m_attrib[m_stack];
1462 if(attrib.m_wireframe)
1463 {
1464 moveTo(_triangle.v0);
1465 lineTo(_triangle.v1);
1466 lineTo(_triangle.v2);
1467 close();
1468 }
1469 else
1470 {
1471 static_assert(sizeof(DdVertex) == sizeof(bx::Vec3), "");
1472
1473 uint64_t old = attrib.m_state;
1474 attrib.m_state &= ~BGFX_STATE_CULL_MASK;
1475
1476 draw(false, 3, reinterpret_cast<const DdVertex*>(&_triangle.v0.x), 0, NULL);
1477
1478 attrib.m_state = old;
1479 }
1480 }
1481
1482 void setUParams(const Attrib& _attrib, bool _wireframe)
1483 {
1484 const float flip = 0 == (_attrib.m_state & BGFX_STATE_CULL_CCW) ? 1.0f : -1.0f;
1485 const uint8_t alpha = _attrib.m_abgr >> 24;
1486 bool alphaBlend = _attrib.m_alphaBlend;
1487
1488 float params[4][4] = {
1489 {
1490 // lightDir
1491 0.0f * flip,
1492 -1.0f * flip,
1493 0.0f * flip,
1494 3.0f, // shininess
1495 },
1496 {
1497 // skyColor
1498 1.0f,
1499 0.9f,
1500 0.8f,
1501 0.0f, // unused
1502 },
1503 {
1504 // groundColor.xyz0
1505 0.2f,
1506 0.22f,
1507 0.5f,
1508 0.0f, // unused
1509 },
1510 {
1511 // matColor
1512 ((_attrib.m_abgr) & 0xff) / 255.0f,
1513 ((_attrib.m_abgr >> 8) & 0xff) / 255.0f,
1514 ((_attrib.m_abgr >> 16) & 0xff) / 255.0f,
1515 (alpha) / 255.0f,
1516 },
1517 };
1518
1519 bx::store(params[0], bx::normalize(bx::load<bx::Vec3>(params[0])));
1520 m_encoder->setUniform(s_dds.u_params, params, 4);
1521
1522 uint32_t blendFlags = alphaBlend ? BGFX_STATE_BLEND_ALPHA : 0;
1523 m_encoder->setState(0 | _attrib.m_state |
1524 (_wireframe ? BGFX_STATE_PT_LINES | BGFX_STATE_LINEAA | blendFlags
1525 : (alpha < 0xff) ? blendFlags
1526 : 0));
1527 }
1528
1529 void draw(GeometryHandle _handle)
1530 {
1531 const Geometry::Geometry& geometry = s_dds.m_geometry.m_geometry[_handle.idx];
1532 m_encoder->setVertexBuffer(0, geometry.m_vbh);
1533
1534 const Attrib& attrib = m_attrib[m_stack];
1535 const bool wireframe = attrib.m_wireframe;
1536 setUParams(attrib, wireframe);
1537
1538 if(wireframe)
1539 {
1540 m_encoder->setIndexBuffer(geometry.m_ibh,
1541 geometry.m_topologyNumIndices[0],
1542 geometry.m_topologyNumIndices[1]);
1543 }
1544 else if(0 != geometry.m_topologyNumIndices[0])
1545 {
1546 m_encoder->setIndexBuffer(geometry.m_ibh, 0, geometry.m_topologyNumIndices[0]);
1547 }
1548
1549 m_encoder->setTransform(m_mtxStack[m_mtxStackCurrent].mtx);
1550 bgfx::ProgramHandle program = s_dds.m_program[wireframe ? Program::FillMesh : Program::FillLitMesh];
1551 m_encoder->submit(m_viewId, program);
1552 }
1553
1554 void draw(bool _lineList,
1555 uint32_t _numVertices,
1556 const DdVertex* _vertices,
1557 uint32_t _numIndices,
1558 const uint16_t* _indices)
1559 {
1560 flush();
1561
1562 if(_numVertices == bgfx::getAvailTransientVertexBuffer(_numVertices, DebugMeshVertex::ms_layout))
1563 {
1564 bgfx::TransientVertexBuffer tvb;
1565 bgfx::allocTransientVertexBuffer(&tvb, _numVertices, DebugMeshVertex::ms_layout);
1566 bx::memCopy(tvb.data, _vertices, _numVertices * DebugMeshVertex::ms_layout.m_stride);
1567 m_encoder->setVertexBuffer(0, &tvb);
1568
1569 const Attrib& attrib = m_attrib[m_stack];
1570 const bool wireframe = _lineList || attrib.m_wireframe;
1571 setUParams(attrib, wireframe);
1572
1573 if(0 < _numIndices)
1574 {
1575 uint32_t numIndices = _numIndices;
1576 bgfx::TransientIndexBuffer tib;
1577 if(!_lineList && wireframe)
1578 {
1579 numIndices = bgfx::topologyConvert(bgfx::TopologyConvert::TriListToLineList,
1580 NULL,
1581 0,
1582 _indices,
1583 _numIndices,
1584 false);
1585
1586 bgfx::allocTransientIndexBuffer(&tib, numIndices);
1587 bgfx::topologyConvert(bgfx::TopologyConvert::TriListToLineList,
1588 tib.data,
1589 numIndices * sizeof(uint16_t),
1590 _indices,
1591 _numIndices,
1592 false);
1593 }
1594 else
1595 {
1596 bgfx::allocTransientIndexBuffer(&tib, numIndices);
1597 bx::memCopy(tib.data, _indices, numIndices * sizeof(uint16_t));
1598 }
1599
1600 m_encoder->setIndexBuffer(&tib);
1601 }
1602
1603 m_encoder->setTransform(m_mtxStack[m_mtxStackCurrent].mtx);
1604 bgfx::ProgramHandle program = s_dds.m_program[wireframe ? Program::FillMesh : Program::FillLitMesh];
1605 m_encoder->submit(m_viewId, program);
1606 }
1607 }
1608
1609 void drawFrustum(const float* _viewProj)
1610 {
1611 bx::Plane planes[6] = {bx::InitNone, bx::InitNone, bx::InitNone, bx::InitNone, bx::InitNone, bx::InitNone};
1612 buildFrustumPlanes(planes, _viewProj, bgfx::getCaps()->homogeneousDepth);
1613
1614 const bx::Vec3 points[8] = {
1615 intersectPlanes(planes[0], planes[2], planes[4]),
1616 intersectPlanes(planes[0], planes[3], planes[4]),
1617 intersectPlanes(planes[0], planes[3], planes[5]),
1618 intersectPlanes(planes[0], planes[2], planes[5]),
1619 intersectPlanes(planes[1], planes[2], planes[4]),
1620 intersectPlanes(planes[1], planes[3], planes[4]),
1621 intersectPlanes(planes[1], planes[3], planes[5]),
1622 intersectPlanes(planes[1], planes[2], planes[5]),
1623 };
1624
1625 moveTo(points[0]);
1626 lineTo(points[1]);
1627 lineTo(points[2]);
1628 lineTo(points[3]);
1629 close();
1630
1631 moveTo(points[4]);
1632 lineTo(points[5]);
1633 lineTo(points[6]);
1634 lineTo(points[7]);
1635 close();
1636
1637 moveTo(points[0]);
1638 lineTo(points[4]);
1639
1640 moveTo(points[1]);
1641 lineTo(points[5]);
1642
1643 moveTo(points[2]);
1644 lineTo(points[6]);
1645
1646 moveTo(points[3]);
1647 lineTo(points[7]);
1648 }
1649
1650 void drawFrustum(const void* _viewProj)
1651 {
1652 drawFrustum((const float*)_viewProj);
1653 }
1654
1655 void drawArc(Axis::Enum _axis, float _x, float _y, float _z, float _radius, float _degrees)
1656 {
1657 const Attrib& attrib = m_attrib[m_stack];
1658 const uint32_t num = getCircleLod(attrib.m_lod);
1659 const float step = bx::kPi * 2.0f / num;
1660
1661 _degrees = bx::wrap(_degrees, 360.0f);
1662
1663 bx::Vec3 pos = getPoint(_axis, bx::sin(step * 0) * _radius, bx::cos(step * 0) * _radius);
1664
1665 moveTo({pos.x + _x, pos.y + _y, pos.z + _z});
1666
1667 uint32_t n = uint32_t(num * _degrees / 360.0f);
1668
1669 for(uint32_t ii = 1; ii < n + 1; ++ii)
1670 {
1671 pos = getPoint(_axis, bx::sin(step * ii) * _radius, bx::cos(step * ii) * _radius);
1672 lineTo({pos.x + _x, pos.y + _y, pos.z + _z});
1673 }
1674
1675 moveTo(_x, _y, _z);
1676 pos = getPoint(_axis, bx::sin(step * 0) * _radius, bx::cos(step * 0) * _radius);
1677 lineTo({pos.x + _x, pos.y + _y, pos.z + _z});
1678
1679 pos = getPoint(_axis, bx::sin(step * n) * _radius, bx::cos(step * n) * _radius);
1680 moveTo({pos.x + _x, pos.y + _y, pos.z + _z});
1681 lineTo(_x, _y, _z);
1682 }
1683
1684 void drawCircle(const bx::Vec3& _normal, const bx::Vec3& _center, float _radius, float _weight)
1685 {
1686 const Attrib& attrib = m_attrib[m_stack];
1687 const uint32_t num = getCircleLod(attrib.m_lod);
1688 const float step = bx::kPi * 2.0f / num;
1689 _weight = bx::clamp(_weight, 0.0f, 2.0f);
1690
1691 bx::Vec3 udir(bx::InitNone);
1692 bx::Vec3 vdir(bx::InitNone);
1693 bx::calcTangentFrame(udir, vdir, _normal, attrib.m_spin);
1694
1695 float xy0[2];
1696 float xy1[2];
1697 circle(xy0, 0.0f);
1698 squircle(xy1, 0.0f);
1699
1700 bx::Vec3 pos = bx::mul(udir, bx::lerp(xy0[0], xy1[0], _weight) * _radius);
1701 bx::Vec3 tmp0 = bx::mul(vdir, bx::lerp(xy0[1], xy1[1], _weight) * _radius);
1702 bx::Vec3 tmp1 = bx::add(pos, tmp0);
1703 bx::Vec3 tmp2 = bx::add(tmp1, _center);
1704 moveTo(tmp2);
1705
1706 for(uint32_t ii = 1; ii < num; ++ii)
1707 {
1708 float angle = step * ii;
1709 circle(xy0, angle);
1710 squircle(xy1, angle);
1711
1712 pos = bx::mul(udir, bx::lerp(xy0[0], xy1[0], _weight) * _radius);
1713 tmp0 = bx::mul(vdir, bx::lerp(xy0[1], xy1[1], _weight) * _radius);
1714 tmp1 = bx::add(pos, tmp0);
1715 tmp2 = bx::add(tmp1, _center);
1716 lineTo(tmp2);
1717 }
1718
1719 close();
1720 }
1721
1722 void drawCircle(Axis::Enum _axis, float _x, float _y, float _z, float _radius, float _weight)
1723 {
1724 const Attrib& attrib = m_attrib[m_stack];
1725 const uint32_t num = getCircleLod(attrib.m_lod);
1726 const float step = bx::kPi * 2.0f / num;
1727 _weight = bx::clamp(_weight, 0.0f, 2.0f);
1728
1729 float xy0[2];
1730 float xy1[2];
1731 circle(xy0, 0.0f);
1732 squircle(xy1, 0.0f);
1733
1734 bx::Vec3 pos =
1735 getPoint(_axis, bx::lerp(xy0[0], xy1[0], _weight) * _radius, bx::lerp(xy0[1], xy1[1], _weight) * _radius);
1736
1737 moveTo({pos.x + _x, pos.y + _y, pos.z + _z});
1738
1739 for(uint32_t ii = 1; ii < num; ++ii)
1740 {
1741 float angle = step * ii;
1742 circle(xy0, angle);
1743 squircle(xy1, angle);
1744
1745 pos = getPoint(_axis,
1746 bx::lerp(xy0[0], xy1[0], _weight) * _radius,
1747 bx::lerp(xy0[1], xy1[1], _weight) * _radius);
1748 lineTo({pos.x + _x, pos.y + _y, pos.z + _z});
1749 }
1750 close();
1751 }
1752
1753 void drawQuad(const bx::Vec3& _normal, const bx::Vec3& _center, float _size)
1754 {
1755 const Attrib& attrib = m_attrib[m_stack];
1756 if(attrib.m_wireframe)
1757 {
1758 bx::Vec3 udir(bx::InitNone);
1759 bx::Vec3 vdir(bx::InitNone);
1760 bx::calcTangentFrame(udir, vdir, _normal, attrib.m_spin);
1761
1762 const float halfExtent = _size * 0.5f;
1763
1764 const bx::Vec3 umin = bx::mul(udir, -halfExtent);
1765 const bx::Vec3 umax = bx::mul(udir, halfExtent);
1766 const bx::Vec3 vmin = bx::mul(vdir, -halfExtent);
1767 const bx::Vec3 vmax = bx::mul(vdir, halfExtent);
1768 const bx::Vec3 center = _center;
1769
1770 moveTo(bx::add(center, bx::add(umin, vmin)));
1771 lineTo(bx::add(center, bx::add(umax, vmin)));
1772 lineTo(bx::add(center, bx::add(umax, vmax)));
1773 lineTo(bx::add(center, bx::add(umin, vmax)));
1774
1775 close();
1776 }
1777 else
1778 {
1779 float mtx[16];
1780 bx::mtxFromNormal(mtx, _normal, _size * 0.5f, _center, attrib.m_spin);
1781 draw(DebugMesh::Quad, mtx, 1, false);
1782 }
1783 }
1784
1785 void drawQuad(SpriteHandle _handle, const bx::Vec3& _normal, const bx::Vec3& _center, float _size)
1786 {
1787 if(!isValid(_handle))
1788 {
1789 drawQuad(_normal, _center, _size);
1790 return;
1791 }
1792
1793 if(m_posQuad == BX_COUNTOF(m_cacheQuad))
1794 {
1795 flushQuad();
1796 }
1797
1798 const Attrib& attrib = m_attrib[m_stack];
1799
1800 bx::Vec3 udir(bx::InitNone);
1801 bx::Vec3 vdir(bx::InitNone);
1802 bx::calcTangentFrame(udir, vdir, _normal, attrib.m_spin);
1803
1804 const Pack2D& pack = s_dds.m_sprite.get(_handle);
1805 const float invTextureSize = 1.0f / SPRITE_TEXTURE_SIZE;
1806 const float us = pack.m_x * invTextureSize;
1807 const float vs = pack.m_y * invTextureSize;
1808 const float ue = (pack.m_x + pack.m_width) * invTextureSize;
1809 const float ve = (pack.m_y + pack.m_height) * invTextureSize;
1810
1811 const float aspectRatio = float(pack.m_width) / float(pack.m_height);
1812 const float halfExtentU = aspectRatio * _size * 0.5f;
1813 const float halfExtentV = 1.0f / aspectRatio * _size * 0.5f;
1814
1815 const bx::Vec3 umin = bx::mul(udir, -halfExtentU);
1816 const bx::Vec3 umax = bx::mul(udir, halfExtentU);
1817 const bx::Vec3 vmin = bx::mul(vdir, -halfExtentV);
1818 const bx::Vec3 vmax = bx::mul(vdir, halfExtentV);
1819 const bx::Vec3 center = _center;
1820
1822 m_posQuad += 4;
1823
1824 bx::store(&vertex->m_x, bx::add(center, bx::add(umin, vmin)));
1825 vertex->m_u = us;
1826 vertex->m_v = vs;
1827 vertex->m_abgr = attrib.m_abgr;
1828 ++vertex;
1829
1830 bx::store(&vertex->m_x, bx::add(center, bx::add(umax, vmin)));
1831 vertex->m_u = ue;
1832 vertex->m_v = vs;
1833 vertex->m_abgr = attrib.m_abgr;
1834 ++vertex;
1835
1836 bx::store(&vertex->m_x, bx::add(center, bx::add(umin, vmax)));
1837 vertex->m_u = us;
1838 vertex->m_v = ve;
1839 vertex->m_abgr = attrib.m_abgr;
1840 ++vertex;
1841
1842 bx::store(&vertex->m_x, bx::add(center, bx::add(umax, vmax)));
1843 vertex->m_u = ue;
1844 vertex->m_v = ve;
1845 vertex->m_abgr = attrib.m_abgr;
1846 ++vertex;
1847 }
1848
1849 void drawQuad(bgfx::TextureHandle _handle, const bx::Vec3& _normal, const bx::Vec3& _center, float _size)
1850 {
1851 // BX_UNUSED(_handle, _normal, _center, _size);
1852 if(!isValid(_handle))
1853 {
1854 drawQuad(_normal, _center, _size);
1855 return;
1856 }
1857
1858 flushQuad();
1859
1860 Attrib& attrib = m_attrib[m_stack];
1861
1862 if((attrib.m_state & BGFX_STATE_WRITE_A) == 0 && attrib.m_alphaBlend)
1863 attrib.m_state |= BGFX_STATE_BLEND_ALPHA;
1864
1865 bx::Vec3 udir(bx::InitNone);
1866 bx::Vec3 vdir(bx::InitNone);
1867 bx::calcTangentFrame(udir, vdir, _normal, attrib.m_spin);
1868
1869 const float us = 0.0f;
1870 const float vs = 0.0f;
1871 const float ue = 1.0f;
1872 const float ve = 1.0f;
1873
1874 const float aspectRatio = 1.0f;
1875 const float halfExtentU = aspectRatio * _size * 0.5f;
1876 const float halfExtentV = 1.0f / aspectRatio * _size * 0.5f;
1877
1878 const bx::Vec3 umin = bx::mul(udir, -halfExtentU);
1879 const bx::Vec3 umax = bx::mul(udir, halfExtentU);
1880 const bx::Vec3 vmin = bx::mul(vdir, -halfExtentV);
1881 const bx::Vec3 vmax = bx::mul(vdir, halfExtentV);
1882 const bx::Vec3 center = _center;
1883
1885 m_posQuad += 4;
1886
1887 bx::store(&vertex->m_x, bx::add(center, bx::add(umin, vmin)));
1888 vertex->m_u = us;
1889 vertex->m_v = vs;
1890 vertex->m_abgr = attrib.m_abgr;
1891 ++vertex;
1892
1893 bx::store(&vertex->m_x, bx::add(center, bx::add(umax, vmin)));
1894 vertex->m_u = ue;
1895 vertex->m_v = vs;
1896 vertex->m_abgr = attrib.m_abgr;
1897 ++vertex;
1898
1899 bx::store(&vertex->m_x, bx::add(center, bx::add(umin, vmax)));
1900 vertex->m_u = us;
1901 vertex->m_v = ve;
1902 vertex->m_abgr = attrib.m_abgr;
1903 ++vertex;
1904
1905 bx::store(&vertex->m_x, bx::add(center, bx::add(umax, vmax)));
1906 vertex->m_u = ue;
1907 vertex->m_v = ve;
1908 vertex->m_abgr = attrib.m_abgr;
1909 ++vertex;
1910
1911 auto original = s_dds.m_texture;
1912 s_dds.m_texture = _handle;
1913 flushQuad();
1914
1915 attrib.m_state &= ~BGFX_STATE_BLEND_ALPHA;
1916
1917 s_dds.m_texture = original;
1918 }
1919
1920 void drawCone(const bx::Vec3& _from, const bx::Vec3& _to, float _radius)
1921 {
1922 const Attrib& attrib = m_attrib[m_stack];
1923
1924 const bx::Vec3 normal = bx::normalize(bx::sub(_from, _to));
1925
1926 float mtx[2][16];
1927 bx::mtxFromNormal(mtx[0], normal, _radius, _from, attrib.m_spin);
1928
1929 bx::memCopy(mtx[1], mtx[0], 64);
1930 mtx[1][12] = _to.x;
1931 mtx[1][13] = _to.y;
1932 mtx[1][14] = _to.z;
1933
1934 uint8_t lod = attrib.m_lod > DebugMesh::ConeMaxLod ? uint8_t(DebugMesh::ConeMaxLod) : attrib.m_lod;
1935 draw(DebugMesh::Enum(DebugMesh::Cone0 + lod), mtx[0], 2, attrib.m_wireframe);
1936 }
1937
1938 void drawCylinder(const bx::Vec3& _from, const bx::Vec3& _to, float _radius, bool _capsule)
1939 {
1940 const Attrib& attrib = m_attrib[m_stack];
1941 const bx::Vec3 normal = bx::normalize(bx::sub(_from, _to));
1942
1943 float mtx[2][16];
1944 bx::mtxFromNormal(mtx[0], normal, _radius, _from, attrib.m_spin);
1945
1946 bx::memCopy(mtx[1], mtx[0], 64);
1947 mtx[1][12] = _to.x;
1948 mtx[1][13] = _to.y;
1949 mtx[1][14] = _to.z;
1950
1951 if(_capsule)
1952 {
1953 uint8_t lod = attrib.m_lod > DebugMesh::CapsuleMaxLod ? uint8_t(DebugMesh::CapsuleMaxLod) : attrib.m_lod;
1954 draw(DebugMesh::Enum(DebugMesh::Capsule0 + lod), mtx[0], 2, attrib.m_wireframe);
1955
1956 bx::Sphere sphere;
1957 sphere.center = _from;
1958 sphere.radius = _radius;
1959 draw(sphere);
1960
1961 sphere.center = _to;
1962 draw(sphere);
1963 }
1964 else
1965 {
1966 uint8_t lod = attrib.m_lod > DebugMesh::CylinderMaxLod ? uint8_t(DebugMesh::CylinderMaxLod) : attrib.m_lod;
1967 draw(DebugMesh::Enum(DebugMesh::Cylinder0 + lod), mtx[0], 2, attrib.m_wireframe);
1968 }
1969 }
1970
1971 void drawAxis(float _x, float _y, float _z, float _len, Axis::Enum _highlight, float _thickness)
1972 {
1973 push();
1974
1975 if(_thickness > 0.0f)
1976 {
1977 const bx::Vec3 from = {_x, _y, _z};
1978 bx::Vec3 mid(bx::InitNone);
1979 bx::Vec3 to(bx::InitNone);
1980
1981 setColor(Axis::X == _highlight ? 0xff00ffff : 0xff0000ff);
1982 mid = {_x + _len - _thickness, _y, _z};
1983 to = {_x + _len, _y, _z};
1984 drawCylinder(from, mid, _thickness, false);
1985 drawCone(mid, to, _thickness);
1986
1987 setColor(Axis::Y == _highlight ? 0xff00ffff : 0xff00ff00);
1988 mid = {_x, _y + _len - _thickness, _z};
1989 to = {_x, _y + _len, _z};
1990 drawCylinder(from, mid, _thickness, false);
1991 drawCone(mid, to, _thickness);
1992
1993 setColor(Axis::Z == _highlight ? 0xff00ffff : 0xffff0000);
1994 mid = {_x, _y, _z + _len - _thickness};
1995 to = {_x, _y, _z + _len};
1996 drawCylinder(from, mid, _thickness, false);
1997 drawCone(mid, to, _thickness);
1998 }
1999 else
2000 {
2001 setColor(Axis::X == _highlight ? 0xff00ffff : 0xff0000ff);
2002 moveTo(_x, _y, _z);
2003 lineTo(_x + _len, _y, _z);
2004
2005 setColor(Axis::Y == _highlight ? 0xff00ffff : 0xff00ff00);
2006 moveTo(_x, _y, _z);
2007 lineTo(_x, _y + _len, _z);
2008
2009 setColor(Axis::Z == _highlight ? 0xff00ffff : 0xffff0000);
2010 moveTo(_x, _y, _z);
2011 lineTo(_x, _y, _z + _len);
2012 }
2013
2014 pop();
2015 }
2016
2017 void drawGrid(const bx::Vec3& _normal, const bx::Vec3& _center, uint32_t _size, float _step)
2018 {
2019 const Attrib& attrib = m_attrib[m_stack];
2020
2021 bx::Vec3 udir(bx::InitNone);
2022 bx::Vec3 vdir(bx::InitNone);
2023 bx::calcTangentFrame(udir, vdir, _normal, attrib.m_spin);
2024
2025 udir = bx::mul(udir, _step);
2026 vdir = bx::mul(vdir, _step);
2027
2028 const uint32_t num = (_size / 2) * 2 + 1;
2029 const float halfExtent = float(_size / 2);
2030
2031 const bx::Vec3 umin = bx::mul(udir, -halfExtent);
2032 const bx::Vec3 umax = bx::mul(udir, halfExtent);
2033 const bx::Vec3 vmin = bx::mul(vdir, -halfExtent);
2034 const bx::Vec3 vmax = bx::mul(vdir, halfExtent);
2035
2036 bx::Vec3 xs = bx::add(_center, bx::add(umin, vmin));
2037 bx::Vec3 xe = bx::add(_center, bx::add(umax, vmin));
2038 bx::Vec3 ys = bx::add(_center, bx::add(umin, vmin));
2039 bx::Vec3 ye = bx::add(_center, bx::add(umin, vmax));
2040
2041 for(uint32_t ii = 0; ii < num; ++ii)
2042 {
2043 moveTo(xs);
2044 lineTo(xe);
2045 xs = bx::add(xs, vdir);
2046 xe = bx::add(xe, vdir);
2047
2048 moveTo(ys);
2049 lineTo(ye);
2050 ys = bx::add(ys, udir);
2051 ye = bx::add(ye, udir);
2052 }
2053 }
2054
2055 void drawGrid(Axis::Enum _axis, const bx::Vec3& _center, uint32_t _size, float _step)
2056 {
2057 push();
2058 pushTranslate(_center);
2059
2060 const uint32_t num = (_size / 2) * 2 - 1;
2061 const float halfExtent = float(_size / 2) * _step;
2062
2063 setColor(0xff606060);
2064 float yy = -halfExtent + _step;
2065 for(uint32_t ii = 0; ii < num; ++ii)
2066 {
2067 moveTo(_axis, -halfExtent, yy);
2068 lineTo(_axis, halfExtent, yy);
2069
2070 moveTo(_axis, yy, -halfExtent);
2071 lineTo(_axis, yy, halfExtent);
2072
2073 yy += _step;
2074 }
2075
2076 setColor(0xff101010);
2077 moveTo(_axis, -halfExtent, -halfExtent);
2078 lineTo(_axis, -halfExtent, halfExtent);
2079 lineTo(_axis, halfExtent, halfExtent);
2080 lineTo(_axis, halfExtent, -halfExtent);
2081 close();
2082
2083 moveTo(_axis, -halfExtent, 0.0f);
2084 lineTo(_axis, halfExtent, 0.0f);
2085
2086 moveTo(_axis, 0.0f, -halfExtent);
2087 lineTo(_axis, 0.0f, halfExtent);
2088
2089 popTransform();
2090 pop();
2091 }
2092
2093 void drawOrb(float _x, float _y, float _z, float _radius, Axis::Enum _hightlight)
2094 {
2095 push();
2096
2097 setColor(Axis::X == _hightlight ? 0xff00ffff : 0xff0000ff);
2098 drawCircle(Axis::X, _x, _y, _z, _radius, 0.0f);
2099
2100 setColor(Axis::Y == _hightlight ? 0xff00ffff : 0xff00ff00);
2101 drawCircle(Axis::Y, _x, _y, _z, _radius, 0.0f);
2102
2103 setColor(Axis::Z == _hightlight ? 0xff00ffff : 0xffff0000);
2104 drawCircle(Axis::Z, _x, _y, _z, _radius, 0.0f);
2105
2106 pop();
2107 }
2108
2109 void draw(DebugMesh::Enum _mesh, const float* _mtx, uint16_t _num, bool _wireframe)
2110 {
2111 pushTransform(_mtx, _num, false /* flush */);
2112
2113 const DebugMesh& mesh = s_dds.m_mesh[_mesh];
2114
2115 if(0 != mesh.m_numIndices[_wireframe])
2116 {
2117 m_encoder->setIndexBuffer(s_dds.m_ibh, mesh.m_startIndex[_wireframe], mesh.m_numIndices[_wireframe]);
2118 }
2119
2120 const Attrib& attrib = m_attrib[m_stack];
2121 setUParams(attrib, _wireframe);
2122
2124 m_encoder->setTransform(stack.mtx, stack.num);
2125
2126 m_encoder->setVertexBuffer(0, s_dds.m_vbh, mesh.m_startVertex, mesh.m_numVertices);
2127 m_encoder->submit(m_viewId, s_dds.m_program[_wireframe ? Program::Fill : Program::Fill]);
2128
2129 popTransform(false /* flush */);
2130 }
2131
2133 {
2134 if(m_pos == uint16_t(BX_COUNTOF(m_cache)))
2135 {
2136 flush();
2137 }
2138 }
2139
2140 void flush()
2141 {
2142 if(0 != m_pos)
2143 {
2145 {
2146 bgfx::TransientVertexBuffer tvb;
2147 bgfx::allocTransientVertexBuffer(&tvb, m_pos, DebugVertex::ms_layout);
2148 bx::memCopy(tvb.data, m_cache, m_pos * DebugVertex::ms_layout.m_stride);
2149
2150 bgfx::TransientIndexBuffer tib;
2151 bgfx::allocTransientIndexBuffer(&tib, m_indexPos);
2152 bx::memCopy(tib.data, m_indices, m_indexPos * sizeof(uint16_t));
2153
2154 const Attrib& attrib = m_attrib[m_stack];
2155
2156 m_encoder->setVertexBuffer(0, &tvb);
2157 m_encoder->setIndexBuffer(&tib);
2158 m_encoder->setState(0 | BGFX_STATE_WRITE_RGB | BGFX_STATE_PT_LINES | attrib.m_state |
2159 BGFX_STATE_LINEAA | (attrib.m_alphaBlend ? BGFX_STATE_BLEND_ALPHA : 0));
2160 m_encoder->setTransform(m_mtxStack[m_mtxStackCurrent].mtx);
2161 bgfx::ProgramHandle program = s_dds.m_program[attrib.m_stipple ? 1 : 0];
2162 m_encoder->submit(m_viewId, program);
2163 }
2164
2166 m_pos = 0;
2167 m_indexPos = 0;
2168 m_vertexPos = 0;
2169 }
2170 }
2171
2173 {
2174 if(0 != m_posQuad)
2175 {
2176 const uint32_t numIndices = m_posQuad / 4 * 6;
2178 {
2179 bgfx::TransientVertexBuffer tvb;
2180 bgfx::allocTransientVertexBuffer(&tvb, m_posQuad, DebugUvVertex::ms_layout);
2181 bx::memCopy(tvb.data, m_cacheQuad, m_posQuad * DebugUvVertex::ms_layout.m_stride);
2182
2183 bgfx::TransientIndexBuffer tib;
2184 bgfx::allocTransientIndexBuffer(&tib, numIndices);
2185 uint16_t* indices = (uint16_t*)tib.data;
2186 for(uint16_t ii = 0, num = m_posQuad / 4; ii < num; ++ii)
2187 {
2188 uint16_t startVertex = ii * 4;
2189 indices[0] = startVertex + 0;
2190 indices[1] = startVertex + 1;
2191 indices[2] = startVertex + 2;
2192 indices[3] = startVertex + 1;
2193 indices[4] = startVertex + 3;
2194 indices[5] = startVertex + 2;
2195 indices += 6;
2196 }
2197
2198 const Attrib& attrib = m_attrib[m_stack];
2199
2200 m_encoder->setVertexBuffer(0, &tvb);
2201 m_encoder->setIndexBuffer(&tib);
2202 m_encoder->setState(0 | (attrib.m_state & ~BGFX_STATE_CULL_MASK));
2203 m_encoder->setTransform(m_mtxStack[m_mtxStackCurrent].mtx);
2204 m_encoder->setTexture(0, s_dds.s_texColor, s_dds.m_texture);
2205
2206 if(m_programStackCurrent >= 0)
2207 {
2209 }
2210 else
2211 {
2213 }
2214 }
2215
2216 m_posQuad = 0;
2217 }
2218 }
2219
2220 struct State
2221 {
2222 enum Enum
2223 {
2227
2228 Count
2230 };
2231
2232 static const uint32_t kCacheSize = 1024;
2233 static const uint32_t kStackSize = 16;
2234 static const uint32_t kCacheQuadSize = 1024;
2235 static_assert(kCacheSize >= 3, "Cache must be at least 3 elements.");
2236
2239 uint16_t m_indices[kCacheSize * 2];
2240 uint16_t m_pos;
2241 uint16_t m_posQuad;
2242 uint16_t m_indexPos;
2243 uint16_t m_vertexPos;
2245
2247 {
2248 void reset()
2249 {
2250 mtx = 0;
2251 num = 1;
2252 data = NULL;
2253 }
2254
2255 uint32_t mtx;
2256 uint16_t num;
2257 float* data;
2258 };
2259
2261
2263 bgfx::ProgramHandle m_programStack[32];
2264
2265 bgfx::ViewId m_viewId;
2266 uint8_t m_stack;
2268
2270
2272
2273 bgfx::Encoder* m_encoder;
2274 bgfx::Encoder* m_defaultEncoder;
2275};
2276
2277static bool s_initted = false;
2279static_assert(sizeof(DebugDrawEncoderImpl) <= sizeof(DebugDrawEncoder), "Size must match");
2280
2281void ddInit(bx::AllocatorI* _allocator)
2282{
2283 s_initted = true;
2284 s_dds.init(_allocator);
2285 s_dde.init(bgfx::begin());
2286}
2287
2289{
2290 if(s_initted)
2291 {
2292 s_dde.shutdown();
2293 s_dds.shutdown();
2294 }
2295}
2296
2297SpriteHandle ddCreateSprite(uint16_t _width, uint16_t _height, const void* _data)
2298{
2299 return s_dds.createSprite(_width, _height, _data);
2300}
2301
2303{
2304 s_dds.destroy(_handle);
2305}
2306
2307GeometryHandle ddCreateGeometry(uint32_t _numVertices,
2308 const DdVertex* _vertices,
2309 uint32_t _numIndices,
2310 const void* _indices,
2311 bool _index32)
2312{
2313 return s_dds.createGeometry(_numVertices, _vertices, _numIndices, _indices, _index32);
2314}
2315
2317{
2318 s_dds.destroy(_handle);
2319}
2320
2321#define DEBUG_DRAW_ENCODER(_func) reinterpret_cast<DebugDrawEncoderImpl*>(this)->_func
2322
2327
2332
2333void DebugDrawEncoder::begin(uint16_t _viewId, bool _depthTestLess, bgfx::Encoder* _encoder)
2334{
2335 DEBUG_DRAW_ENCODER(begin(_viewId, _depthTestLess, _encoder));
2336}
2337
2342
2347
2352
2353void DebugDrawEncoder::setDepthTestLess(bool _depthTestLess)
2354{
2355 DEBUG_DRAW_ENCODER(setDepthTestLess(_depthTestLess));
2356}
2357
2358void DebugDrawEncoder::setState(bool _depthTest, bool _depthWrite, bool _clockwise, bool _alphaWrite, bool _alphaBlend)
2359{
2360 DEBUG_DRAW_ENCODER(setState(_depthTest, _depthWrite, _clockwise, _alphaWrite, _alphaBlend));
2361}
2362
2363void DebugDrawEncoder::setColor(uint32_t _abgr)
2364{
2366}
2367
2369{
2371}
2372
2374{
2375 DEBUG_DRAW_ENCODER(setWireframe(_wireframe));
2376}
2377
2378void DebugDrawEncoder::setStipple(bool _stipple, float _scale, float _offset)
2379{
2380 DEBUG_DRAW_ENCODER(setStipple(_stipple, _scale, _offset));
2381}
2382
2384{
2386}
2387
2389{
2391}
2392
2393void DebugDrawEncoder::setTranslate(float _x, float _y, float _z)
2394{
2395 DEBUG_DRAW_ENCODER(setTranslate(_x, _y, _z));
2396}
2397
2399{
2401}
2402
2407
2408void DebugDrawEncoder::pushProgram(bgfx::ProgramHandle handle)
2409{
2411}
2412
2417
2418void DebugDrawEncoder::moveTo(float _x, float _y, float _z)
2419{
2420 DEBUG_DRAW_ENCODER(moveTo(_x, _y, _z));
2421}
2422
2423void DebugDrawEncoder::moveTo(const bx::Vec3& _pos)
2424{
2426}
2427
2428void DebugDrawEncoder::lineTo(float _x, float _y, float _z)
2429{
2430 DEBUG_DRAW_ENCODER(lineTo(_x, _y, _z));
2431}
2432
2433void DebugDrawEncoder::lineTo(const bx::Vec3& _pos)
2434{
2436}
2437
2442
2443void DebugDrawEncoder::draw(const bx::Aabb& _aabb)
2444{
2445 DEBUG_DRAW_ENCODER(draw(_aabb));
2446}
2447
2448void DebugDrawEncoder::draw(const bx::Cylinder& _cylinder)
2449{
2450 DEBUG_DRAW_ENCODER(draw(_cylinder, false));
2451}
2452
2453void DebugDrawEncoder::draw(const bx::Capsule& _capsule)
2454{
2455 DEBUG_DRAW_ENCODER(draw(*((const bx::Cylinder*)&_capsule), true));
2456}
2457
2458void DebugDrawEncoder::draw(const bx::Disk& _disk)
2459{
2460 DEBUG_DRAW_ENCODER(draw(_disk));
2461}
2462
2463void DebugDrawEncoder::draw(const bx::Obb& _obb)
2464{
2465 DEBUG_DRAW_ENCODER(draw(_obb));
2466}
2467
2468void DebugDrawEncoder::draw(const bx::Sphere& _sphere)
2469{
2470 DEBUG_DRAW_ENCODER(draw(_sphere));
2471}
2472
2473void DebugDrawEncoder::draw(const bx::Triangle& _triangle)
2474{
2475 DEBUG_DRAW_ENCODER(draw(_triangle));
2476}
2477
2478void DebugDrawEncoder::draw(const bx::Cone& _cone)
2479{
2480 DEBUG_DRAW_ENCODER(drawCone(_cone.pos, _cone.end, _cone.radius));
2481}
2482
2484{
2485 DEBUG_DRAW_ENCODER(draw(_handle));
2486}
2487
2488void DebugDrawEncoder::drawLineList(uint32_t _numVertices,
2489 const DdVertex* _vertices,
2490 uint32_t _numIndices,
2491 const uint16_t* _indices)
2492{
2493 DEBUG_DRAW_ENCODER(draw(true, _numVertices, _vertices, _numIndices, _indices));
2494}
2495
2496void DebugDrawEncoder::drawTriList(uint32_t _numVertices,
2497 const DdVertex* _vertices,
2498 uint32_t _numIndices,
2499 const uint16_t* _indices)
2500{
2501 DEBUG_DRAW_ENCODER(draw(false, _numVertices, _vertices, _numIndices, _indices));
2502}
2503
2504void DebugDrawEncoder::drawFrustum(const void* _viewProj)
2505{
2506 DEBUG_DRAW_ENCODER(drawFrustum(_viewProj));
2507}
2508
2509void DebugDrawEncoder::drawArc(Axis::Enum _axis, float _x, float _y, float _z, float _radius, float _degrees)
2510{
2511 DEBUG_DRAW_ENCODER(drawArc(_axis, _x, _y, _z, _radius, _degrees));
2512}
2513
2514void DebugDrawEncoder::drawCircle(const bx::Vec3& _normal, const bx::Vec3& _center, float _radius, float _weight)
2515{
2516 DEBUG_DRAW_ENCODER(drawCircle(_normal, _center, _radius, _weight));
2517}
2518
2519void DebugDrawEncoder::drawCircle(Axis::Enum _axis, float _x, float _y, float _z, float _radius, float _weight)
2520{
2521 DEBUG_DRAW_ENCODER(drawCircle(_axis, _x, _y, _z, _radius, _weight));
2522}
2523
2524void DebugDrawEncoder::drawQuad(const bx::Vec3& _normal, const bx::Vec3& _center, float _size)
2525{
2526 DEBUG_DRAW_ENCODER(drawQuad(_normal, _center, _size));
2527}
2528
2529void DebugDrawEncoder::drawQuad(SpriteHandle _handle, const bx::Vec3& _normal, const bx::Vec3& _center, float _size)
2530{
2531 DEBUG_DRAW_ENCODER(drawQuad(_handle, _normal, _center, _size));
2532}
2533
2534void DebugDrawEncoder::drawQuad(bgfx::TextureHandle _handle,
2535 const bx::Vec3& _normal,
2536 const bx::Vec3& _center,
2537 float _size)
2538{
2539 DEBUG_DRAW_ENCODER(drawQuad(_handle, _normal, _center, _size));
2540}
2541
2542void DebugDrawEncoder::drawCone(const bx::Vec3& _from, const bx::Vec3& _to, float _radius)
2543{
2544 DEBUG_DRAW_ENCODER(drawCone(_from, _to, _radius));
2545}
2546
2547void DebugDrawEncoder::drawCylinder(const bx::Vec3& _from, const bx::Vec3& _to, float _radius)
2548{
2549 DEBUG_DRAW_ENCODER(drawCylinder(_from, _to, _radius, false));
2550}
2551
2552void DebugDrawEncoder::drawCapsule(const bx::Vec3& _from, const bx::Vec3& _to, float _radius)
2553{
2554 DEBUG_DRAW_ENCODER(drawCylinder(_from, _to, _radius, true));
2555}
2556
2557void DebugDrawEncoder::drawAxis(float _x, float _y, float _z, float _len, Axis::Enum _highlight, float _thickness)
2558{
2559 DEBUG_DRAW_ENCODER(drawAxis(_x, _y, _z, _len, _highlight, _thickness));
2560}
2561
2562void DebugDrawEncoder::drawGrid(const bx::Vec3& _normal, const bx::Vec3& _center, uint32_t _size, float _step)
2563{
2564 DEBUG_DRAW_ENCODER(drawGrid(_normal, _center, _size, _step));
2565}
2566
2567void DebugDrawEncoder::drawGrid(Axis::Enum _axis, const bx::Vec3& _center, uint32_t _size, float _step)
2568{
2569 DEBUG_DRAW_ENCODER(drawGrid(_axis, _center, _size, _step));
2570}
2571
2572void DebugDrawEncoder::drawOrb(float _x, float _y, float _z, float _radius, Axis::Enum _highlight)
2573{
2574 DEBUG_DRAW_ENCODER(drawOrb(_x, _y, _z, _radius, _highlight));
2575}
2576
2581
bool checkAvailTransientBuffers(uint32_t _numVertices, const bgfx::VertexLayout &_layout, uint32_t _numIndices)
Definition bgfx_utils.h:97
DebugDrawEncoderScopePush(DebugDrawEncoder &_dde)
bool find(uint16_t _width, uint16_t _height, Pack2D &_pack)
Definition packrect.h:42
void clear(const Pack2D &_pack)
Definition packrect.h:89
const char * id
math::vec3 normal
Definition defaults.cpp:53
uint16_t index
texture_job_type type
std::vector< float > scale
std::vector< uint32_t > indices
bool m_stipple
bool m_alphaBlend
float m_scale
float m_offset
uint32_t m_abgr
uint8_t m_lod
bool m_wireframe
uint64_t m_state
float m_spin
@ X
Definition debugdraw.h:17
@ Y
Definition debugdraw.h:18
@ Z
Definition debugdraw.h:19
void draw(const bx::Aabb &_aabb)
void lineTo(float _x, float _y, float _z=0.0f)
void drawQuad(const bx::Vec3 &_normal, const bx::Vec3 &_center, float _size)
void drawCone(const bx::Vec3 &_from, const bx::Vec3 &_to, float _radius)
void setSpin(float _spin)
void drawCylinder(const bx::Vec3 &_from, const bx::Vec3 &_to, float _radius)
void setColor(uint32_t _abgr)
void drawAxis(float _x, float _y, float _z, float _len=1.0f, Axis::Enum _highlight=Axis::Count, float _thickness=0.0f)
void setWireframe(bool _wireframe)
void setTransform(const void *_mtx)
void begin(uint16_t _viewId, bool _depthTestLess=true, bgfx::Encoder *_encoder=NULL)
void drawGrid(const bx::Vec3 &_normal, const bx::Vec3 &_center, uint32_t _size=20, float _step=1.0f)
void setState(bool _depthTest, bool _depthWrite, bool _clockwise, bool _alphaWrite=false, bool _alphaBlend=true)
void pushTransform(const void *_mtx)
void drawArc(Axis::Enum _axis, float _x, float _y, float _z, float _radius, float _degrees)
void drawCapsule(const bx::Vec3 &_from, const bx::Vec3 &_to, float _radius)
void drawOrb(float _x, float _y, float _z, float _radius, Axis::Enum _highlight=Axis::Count)
void drawTriList(uint32_t _numVertices, const DdVertex *_vertices, uint32_t _numIndices=0, const uint16_t *_indices=NULL)
void drawLineList(uint32_t _numVertices, const DdVertex *_vertices, uint32_t _numIndices=0, const uint16_t *_indices=NULL)
void drawFrustum(const void *_viewProj)
void pushProgram(bgfx::ProgramHandle _handle)
void moveTo(float _x, float _y, float _z=0.0f)
void drawCircle(const bx::Vec3 &_normal, const bx::Vec3 &_center, float _radius, float _weight=0.0f)
void setTranslate(float _x, float _y, float _z)
void setDepthTestLess(bool _depthTestLess)
void setStipple(bool _stipple, float _scale=1.0f, float _offset=0.0f)
void setLod(uint8_t _lod)
static const uint32_t kCacheSize
void pushTranslate(float _x, float _y, float _z)
void drawAxis(float _x, float _y, float _z, float _len, Axis::Enum _highlight, float _thickness)
void setSpin(float _spin)
static const uint32_t kCacheQuadSize
void draw(const bx::Sphere &_sphere)
void drawCone(const bx::Vec3 &_from, const bx::Vec3 &_to, float _radius)
void draw(const bx::Triangle &_triangle)
void setDepthTestLess(bool _depthTestLess)
void drawGrid(const bx::Vec3 &_normal, const bx::Vec3 &_center, uint32_t _size, float _step)
void moveTo(Axis::Enum _axis, float _x, float _y)
void drawQuad(bgfx::TextureHandle _handle, const bx::Vec3 &_normal, const bx::Vec3 &_center, float _size)
void drawOrb(float _x, float _y, float _z, float _radius, Axis::Enum _hightlight)
void setColor(uint32_t _abgr)
void draw(bool _lineList, uint32_t _numVertices, const DdVertex *_vertices, uint32_t _numIndices, const uint16_t *_indices)
void draw(const bx::Disk &_disk)
void drawGrid(Axis::Enum _axis, const bx::Vec3 &_center, uint32_t _size, float _step)
void setState(bool _depthTest, bool _depthWrite, bool _clockwise, bool _alphaWrite, bool _alphaBlend)
MatrixStack m_mtxStack[32]
void pushTranslate(const bx::Vec3 &_pos)
Attrib m_attrib[kStackSize]
void init(bgfx::Encoder *_encoder)
void lineTo(float _x, float _y, float _z=0.0f)
void pushProgram(bgfx::ProgramHandle _handle)
void draw(const bx::Aabb &_aabb)
void moveTo(float _x, float _y, float _z=0.0f)
void draw(DebugMesh::Enum _mesh, const float *_mtx, uint16_t _num, bool _wireframe)
void setStipple(bool _stipple, float _scale=1.0f, float _offset=0.0f)
void lineTo(Axis::Enum _axis, float _x, float _y)
void popTransform(bool _flush=true)
DebugVertex m_cache[kCacheSize+1]
void drawArc(Axis::Enum _axis, float _x, float _y, float _z, float _radius, float _degrees)
void pushTransform(const void *_mtx, uint16_t _num, bool _flush=true)
void setTransform(const void *_mtx, uint16_t _num=1, bool _flush=true)
bgfx::Encoder * m_encoder
void drawCircle(const bx::Vec3 &_normal, const bx::Vec3 &_center, float _radius, float _weight)
void lineTo(const bx::Vec3 &_pos)
void draw(GeometryHandle _handle)
bgfx::ViewId m_viewId
void draw(const bx::Cylinder &_cylinder, bool _capsule)
void drawCylinder(const bx::Vec3 &_from, const bx::Vec3 &_to, float _radius, bool _capsule)
void setLod(uint8_t _lod)
void setUParams(const Attrib &_attrib, bool _wireframe)
void moveTo(const bx::Vec3 &_pos)
void drawFrustum(const float *_viewProj)
bgfx::Encoder * m_defaultEncoder
void drawCircle(Axis::Enum _axis, float _x, float _y, float _z, float _radius, float _weight)
static const uint32_t kStackSize
bgfx::ProgramHandle m_programStack[32]
uint16_t m_indices[kCacheSize *2]
void drawQuad(SpriteHandle _handle, const bx::Vec3 &_normal, const bx::Vec3 &_center, float _size)
void draw(const bx::Obb &_obb)
void drawFrustum(const void *_viewProj)
void drawQuad(const bx::Vec3 &_normal, const bx::Vec3 &_center, float _size)
DebugUvVertex m_cacheQuad[kCacheQuadSize]
void setTranslate(const float *_pos)
void setTranslate(float _x, float _y, float _z)
void begin(bgfx::ViewId _viewId, bool _depthTestLess, bgfx::Encoder *_encoder)
void setWireframe(bool _wireframe)
bgfx::TextureHandle m_texture
Geometry m_geometry
SpriteHandle createSprite(uint16_t _width, uint16_t _height, const void *_data)
bgfx::VertexBufferHandle m_vbh
void destroy(SpriteHandle _handle)
GeometryHandle createGeometry(uint32_t _numVertices, const DdVertex *_vertices, uint32_t _numIndices, const void *_indices, bool _index32)
bgfx::UniformHandle u_params
void init(bx::AllocatorI *_allocator)
bgfx::ProgramHandle m_program[Program::Count]
bx::AllocatorI * m_allocator
bgfx::IndexBufferHandle m_ibh
DebugMesh m_mesh[DebugMesh::Count]
bgfx::UniformHandle s_texColor
void destroy(GeometryHandle _handle)
uint32_t m_startIndex[2]
uint32_t m_startVertex
uint32_t m_numIndices[2]
uint32_t m_numVertices
static bgfx::VertexLayout ms_layout
Definition debugdraw.cpp:98
static void init()
Definition debugdraw.cpp:93
static bgfx::VertexLayout ms_layout
Definition debugdraw.cpp:82
uint8_t m_indices[4]
Definition debugdraw.cpp:72
static void init()
Definition debugdraw.cpp:74
static void init()
Definition debugdraw.cpp:53
static bgfx::VertexLayout ms_layout
Definition debugdraw.cpp:62
uint32_t m_abgr
Definition debugdraw.cpp:51
uint32_t m_abgr
Definition debugdraw.cpp:28
static bgfx::VertexLayout ms_layout
Definition debugdraw.cpp:39
static void init()
Definition debugdraw.cpp:30
uint16_t idx
Definition debugdraw.h:41
bgfx::IndexBufferHandle m_ibh
uint32_t m_topologyNumIndices[2]
bgfx::VertexBufferHandle m_vbh
void destroy(GeometryHandle _handle)
bx::HandleAllocT< MaxHandlesT > m_handleAlloc
Geometry m_geometry[MaxHandlesT]
bx::Mutex m_lock
GeometryHandle create(uint32_t _numVertices, const DdVertex *_vertices, uint32_t _numIndices, const void *_indices, bool _index32)
uint16_t m_width
Definition packrect.h:13
uint16_t m_height
Definition packrect.h:14
uint16_t m_y
Definition packrect.h:12
uint16_t m_x
Definition packrect.h:11
uint16_t idx
Definition debugdraw.h:32
bx::Mutex m_lock
bx::HandleAllocT< MaxHandlesT > m_handleAlloc
const Pack2D & get(SpriteHandle _sprite) const
Pack2D m_pack[MaxHandlesT]
void destroy(SpriteHandle _sprite)
SpriteHandle create(uint16_t _width, uint16_t _height)
RectPack2DT< 256 > m_ra
gfx::uniform_handle handle
Definition uniform.cpp:9
uint32_t genSphere(uint8_t _subdiv0, void *_pos0=NULL, uint16_t _posStride0=0, void *_normals0=NULL, uint16_t _normalStride0=0)
#define SPRITE_TEXTURE_SIZE
static const uint8_t s_circleLod[]
#define DEBUG_DRAW_ENCODER(_func)
SpriteHandle ddCreateSprite(uint16_t _width, uint16_t _height, const void *_data)
static const uint16_t s_quadIndices[6]
static DebugDrawShared s_dds
void ddShutdown()
void ddInit(bx::AllocatorI *_allocator)
static const uint16_t s_cubeIndices[36]
SpriteT< 256, SPRITE_TEXTURE_SIZE > Sprite
bx::Vec3 getPoint(Axis::Enum _axis, float _x, float _y)
GeometryT< DEBUG_DRAW_CONFIG_MAX_GEOMETRY > Geometry
static DebugDrawEncoderImpl s_dde
static bool s_initted
static void squircle(float *_out, float _angle)
static uint8_t getCircleLod(uint8_t _lod)
static void circle(float *_out, float _angle)
static DebugShapeVertex s_cubeVertices[8]
GeometryHandle ddCreateGeometry(uint32_t _numVertices, const DdVertex *_vertices, uint32_t _numIndices, const void *_indices, bool _index32)
void ddDestroy(SpriteHandle _handle)
static DebugShapeVertex s_quadVertices[4]
static const bgfx::EmbeddedShader s_embeddedShaders[]
bool isValid(SpriteHandle _handle)
Definition debugdraw.h:34