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;
3233namespace gl = celestia::gl;
3334namespace math = celestia::math;
3435
35- // draw a simple circle or annulus
36- # define DRAW_ANNULUS 0
36+ namespace
37+ {
3738
3839constexpr float shaftLength = 0 .85f ;
3940constexpr float headLength = 0 .10f ;
4041constexpr float shaftRadius = 0 .010f ;
4142constexpr 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}
0 commit comments