Skip to content

Commit b3a7b5e

Browse files
committed
Use indices for drawing arrow reference marks
Save some memory by eliminating duplicate vertices
1 parent e981ecd commit b3a7b5e

File tree

2 files changed

+104
-93
lines changed

2 files changed

+104
-93
lines changed

src/celengine/axisarrow.cpp

Lines changed: 101 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// of the License, or (at your option) any later version.
1010

1111
#include <algorithm>
12+
#include <utility>
1213
#include <vector>
1314
#include <celcompat/numbers.h>
1415
#include <celephem/orbit.h>
@@ -32,124 +33,134 @@ using celestia::render::LineRenderer;
3233
namespace gl = celestia::gl;
3334
namespace math = celestia::math;
3435

35-
// draw a simple circle or annulus
36-
#define DRAW_ANNULUS 0
36+
namespace
37+
{
3738

3839
constexpr float shaftLength = 0.85f;
3940
constexpr float headLength = 0.10f;
4041
constexpr float shaftRadius = 0.010f;
4142
constexpr float headRadius = 0.025f;
42-
constexpr unsigned nSections = 30;
43+
constexpr unsigned int nSections = 30;
4344

44-
namespace
45+
std::vector<Eigen::Vector3f>
46+
GetArrowVertices()
4547
{
48+
constexpr unsigned int totalVertices = nSections * 3U + 3U;
4649

47-
gl::VertexObject&
48-
GetArrowVAO()
49-
{
50-
static bool initialized = false;
50+
std::vector<Eigen::Vector3f> vertices;
51+
vertices.reserve(totalVertices);
52+
vertices.emplace_back(Eigen::Vector3f::Zero());
53+
vertices.emplace_back(0.0f, 0.0f, shaftLength);
54+
vertices.emplace_back(0.0f, 0.0f, shaftLength + headLength);
5155

52-
static std::unique_ptr<gl::VertexObject> vo;
53-
static std::unique_ptr<gl::Buffer> bo;
56+
for (unsigned int i = 0U; i < nSections; ++i)
57+
{
58+
float s;
59+
float c;
60+
math::sincos((static_cast<float>(i) * 2.0f * celestia::numbers::pi_v<float>) / nSections, s, c);
5461

55-
if (initialized)
56-
return *vo;
62+
vertices.emplace_back(shaftRadius * s, shaftRadius * c, 0.0f);
63+
vertices.emplace_back(shaftRadius * s, shaftRadius * c, shaftLength);
64+
vertices.emplace_back(headRadius * s, headRadius * c, shaftLength);
65+
}
66+
67+
return vertices;
68+
}
69+
70+
std::vector<GLushort>
71+
GetArrowIndices()
72+
{
73+
constexpr unsigned int circleSize = (nSections + 1U) * 3U;
74+
constexpr unsigned int shaftSize = 3U + nSections * 6U;
75+
constexpr unsigned int annulusSize = (nSections + 1U) * 3U;
76+
constexpr unsigned int headSize = (nSections + 1U) * 3U;
77+
78+
constexpr unsigned int totalSize = circleSize + shaftSize + annulusSize + headSize;
5779

58-
initialized = true;
80+
std::vector<GLushort> indices(totalSize, GLushort(0));
5981

60-
vo = std::make_unique<gl::VertexObject>();
61-
bo = std::make_unique<gl::Buffer>();
82+
GLushort* const circle = indices.data();
83+
GLushort* const shaft = circle + circleSize;
84+
GLushort* const annulus = shaft + shaftSize;
85+
GLushort* const head = annulus + annulusSize;
6286

63-
// circle at bottom of a shaft
64-
std::vector<Eigen::Vector3f> circle;
65-
// arrow shaft
66-
std::vector<Eigen::Vector3f> shaft;
67-
// annulus
68-
std::vector<Eigen::Vector3f> annulus;
69-
// head of the arrow
70-
std::vector<Eigen::Vector3f> head;
87+
GLushort* circlePtr = circle;
88+
GLushort* shaftPtr = shaft;
89+
GLushort* annulusPtr = annulus;
90+
GLushort* headPtr = head;
7191

72-
for (unsigned i = 0; i <= nSections; i++)
92+
constexpr GLushort vZero = 0;
93+
constexpr GLushort v3 = 1;
94+
constexpr GLushort v4 = 2;
95+
for (unsigned int i = 0U; i <= nSections; ++i)
7396
{
74-
float c, s;
75-
math::sincos((i * 2.0f * celestia::numbers::pi_v<float>) / nSections, c, s);
97+
unsigned int idx = i < nSections ? i : 0;
98+
auto v0 = static_cast<GLushort>(3U + idx * 3U);
99+
auto v1 = static_cast<GLushort>(v0 + 1U);
100+
auto v2 = static_cast<GLushort>(v0 + 2U);
76101

77-
// circle at bottom
78-
Eigen::Vector3f v0(shaftRadius * c, shaftRadius * s, 0.0f);
102+
// Circle at bottom
79103
if (i > 0)
80-
circle.push_back(v0);
81-
circle.push_back(Eigen::Vector3f::Zero());
82-
circle.push_back(v0);
104+
*(circlePtr++) = v0;
105+
*(circlePtr++) = vZero;
106+
*(circlePtr++) = v1;
83107

84-
// shaft
85-
Eigen::Vector3f v1(shaftRadius * c, shaftRadius * s, shaftLength);
86-
Eigen::Vector3f v1prev;
108+
// Shaft
87109
if (i > 0)
88110
{
89-
shaft.push_back(v0); // left triangle
111+
*(shaftPtr++) = v0; // left triangle
90112

91-
shaft.push_back(v0); // right
92-
shaft.push_back(v1prev);
93-
shaft.push_back(v1);
113+
*(shaftPtr++) = v0; // right
114+
*(shaftPtr++) = static_cast<GLushort>(idx * 3U + 1U) ; // v1Prev
115+
*(shaftPtr++) = v1;
94116
}
95-
shaft.push_back(v0); // left
96-
shaft.push_back(v1);
97-
v1prev = v1;
98-
99-
// annulus
100-
Eigen::Vector3f v2(headRadius * c, headRadius * s, shaftLength);
101-
#if DRAW_ANNULUS
102-
Eigen::Vector3f v2prev;
103-
if (i > 0)
104-
{
105-
annulus.push_back(v2);
117+
*(shaftPtr++) = v0; // left
118+
*(shaftPtr++) = v1;
106119

107-
annulus.push_back(v2);
108-
annulus.push_back(v2prev);
109-
annulus.push_back(v1);
110-
}
111-
annulus.push_back(v2);
112-
annulus.push_back(v1);
113-
v2prev = v1;
114-
#else
115-
Eigen::Vector3f v3(0.0f, 0.0f, shaftLength);
120+
// Annulus
116121
if (i > 0)
117-
annulus.push_back(v2);
118-
annulus.push_back(v2);
119-
annulus.push_back(v3);
120-
#endif
122+
*(annulusPtr++) = v2;
123+
*(annulusPtr++) = v2;
124+
*(annulusPtr++) = v3;
121125

122-
// head
123-
Eigen::Vector3f v4(0.0f, 0.0f, shaftLength + headLength);
126+
// Head
124127
if (i > 0)
125-
head.push_back(v2);
126-
head.push_back(v4);
127-
head.push_back(v2);
128+
*(headPtr++) = v2;
129+
*(headPtr++) = v4;
130+
*(headPtr++) = v2;
128131
}
129132

130-
circle.push_back(circle[1]);
131-
shaft.push_back(shaft[0]);
132-
#if DRAW_ANNULUS
133-
annulus.push_back(annulus[0]);
134-
#else
135-
annulus.push_back(annulus[1]);
136-
#endif
137-
head.push_back(head[1]);
138-
139-
std::vector<Eigen::Vector3f> arrow;
140-
arrow.reserve(circle.size() + shaft.size() + annulus.size() + head.size());
141-
std::copy(circle.begin(), circle.end(), std::back_inserter(arrow));
142-
std::copy(shaft.begin(), shaft.end(), std::back_inserter(arrow));
143-
std::copy(annulus.begin(), annulus.end(), std::back_inserter(arrow));
144-
std::copy(head.begin(), head.end(), std::back_inserter(arrow));
145-
146-
bo->setData(arrow, gl::Buffer::BufferUsage::StaticDraw);
147-
148-
vo->setCount(static_cast<int>(arrow.size())).addVertexBuffer(
149-
*bo,
150-
CelestiaGLProgram::VertexCoordAttributeIndex,
151-
3,
152-
gl::VertexObject::DataType::Float);
133+
*circlePtr = circle[1];
134+
*shaftPtr = shaft[0];
135+
*annulusPtr = annulus[1];
136+
*headPtr = head[1];
137+
138+
return indices;
139+
}
140+
141+
gl::VertexObject&
142+
GetArrowVAO()
143+
{
144+
static gl::VertexObject* vo = nullptr;
145+
146+
if (vo)
147+
return *vo;
148+
149+
vo = std::make_unique<gl::VertexObject>().release();
150+
151+
auto vertices = GetArrowVertices();
152+
auto indices = GetArrowIndices();
153+
154+
static gl::Buffer* vertexBuffer = std::make_unique<gl::Buffer>(gl::Buffer::TargetHint::Array).release();
155+
vertexBuffer->setData(vertices, gl::Buffer::BufferUsage::StaticDraw);
156+
157+
vo->addVertexBuffer(*vertexBuffer,
158+
CelestiaGLProgram::VertexCoordAttributeIndex,
159+
3,
160+
gl::VertexObject::DataType::Float);
161+
gl::Buffer indexBuffer(gl::Buffer::TargetHint::ElementArray, indices);
162+
vo->setCount(static_cast<int>(indices.size()));
163+
vo->setIndexBuffer(std::move(indexBuffer), 0, gl::VertexObject::IndexType::UnsignedShort);
153164

154165
return *vo;
155166
}

src/celrender/gl/vertexobject.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class VertexObject
3535
*
3636
* @see @ref addVertexBuffer()
3737
*/
38-
enum class DataType
38+
enum class DataType : GLenum
3939
{
4040
Byte = GL_BYTE,
4141
UnsignedByte = GL_UNSIGNED_BYTE,
@@ -52,7 +52,7 @@ class VertexObject
5252
*
5353
* @see @ref setIndexBuffer() @ref isIndexed()
5454
*/
55-
enum class IndexType
55+
enum class IndexType : GLenum
5656
{
5757
UnsignedShort = GL_UNSIGNED_SHORT,
5858
UnsignedInt = GL_UNSIGNED_INT,
@@ -63,7 +63,7 @@ class VertexObject
6363
*
6464
* @see @ref draw() @ref draw(Primitive, int, int)
6565
*/
66-
enum class Primitive
66+
enum class Primitive : GLenum
6767
{
6868
Points = GL_POINTS,
6969
Lines = GL_LINES,

0 commit comments

Comments
 (0)