128 glDisable( GL_CULL_FACE );
132 glClear( GL_DEPTH_BUFFER_BIT );
134 glMatrixMode( GL_PROJECTION );
137 const float camDist =
m_arrowSize * GIZMO_CAMERA_DISTANCE_FACTOR;
139 gluPerspective( fov, 1.0f, camDist - clipRadius, camDist + clipRadius );
141 glMatrixMode( GL_MODELVIEW );
144 glm::mat4 TranslationMatrix = glm::translate( glm::mat4( 1.0f ),
SFVEC3F( 0.0f, 0.0f, -(
m_arrowSize * GIZMO_CAMERA_DISTANCE_FACTOR ) ) );
145 glm::mat4 ViewMatrix = TranslationMatrix * aCameraRotationMatrix;
146 glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
150 auto drawBillboardCircle =
151 [](
const glm::vec3& aCenter,
float aRadius,
const glm::vec3& aColor,
152 const glm::vec3& aCamRight,
const glm::vec3& aCamUp,
int aSegments = 64 )
154 float thickness = aRadius * 0.4f;
155 glColor3f( aColor.r, aColor.g, aColor.b );
157 glBegin( GL_TRIANGLE_STRIP );
158 for(
int i = 0; i <= aSegments; ++i )
160 float angle = 2.0f * glm::pi<float>() * i / aSegments;
161 glm::vec3 dir = cos( angle ) * aCamRight + sin( angle ) * aCamUp;
163 glm::vec3 outer = aCenter + dir * ( aRadius + thickness * 0.5f );
164 glm::vec3 inner = aCenter + dir * ( aRadius - thickness * 0.5f );
166 glVertex3f( outer.x, outer.y, outer.z );
167 glVertex3f( inner.x, inner.y, inner.z );
172 glm::vec3 camRight( aCameraRotationMatrix[0][0], aCameraRotationMatrix[1][0], aCameraRotationMatrix[2][0] );
173 glm::vec3 camUp( aCameraRotationMatrix[0][1], aCameraRotationMatrix[1][1], aCameraRotationMatrix[2][1] );
175 glEnable( GL_BLEND );
176 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
180 glColor4f( sphere.m_color.r, sphere.m_color.g, sphere.m_color.b, 0.3f );
182 glTranslatef( sphere.m_position.x, sphere.m_position.y, sphere.m_position.z );
185 gluSphere(
m_quadric, sphere.m_radius, 32, 32 );
189 drawBillboardCircle( sphere.m_position, sphere.m_radius, sphere.m_color, camRight, camUp );
194 glDisable( GL_DEPTH_TEST );
195 glDisable( GL_LIGHTING );
197 std::array<std::string, 6> labels = {
"X",
"",
"Y",
"",
"Z",
"" };
202 glm::vec3 offset = camForward * GIZMO_LABEL_CAMERA_OFFSET;
204 glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
207 [](
const glm::vec3& aPos,
float aSize,
const glm::vec3& aColor,
const glm::vec3& aCamRight,
208 const glm::vec3& aCamUp )
210 glColor3f( aColor.r, aColor.g, aColor.b );
213 float h = aSize * 0.5f;
216 glm::vec3 dir1 = ( -aCamRight + aCamUp ) * h;
217 glm::vec3 dir2 = ( -aCamRight - aCamUp ) * h;
220 glVertex3f( ( aPos - dir1 ).x, ( aPos - dir1 ).y, ( aPos - dir1 ).z );
221 glVertex3f( ( aPos + dir1 ).x, ( aPos + dir1 ).y, ( aPos + dir1 ).z );
223 glVertex3f( ( aPos - dir2 ).x, ( aPos - dir2 ).y, ( aPos - dir2 ).z );
224 glVertex3f( ( aPos + dir2 ).x, ( aPos + dir2 ).y, ( aPos + dir2 ).z );
229 [](
const glm::vec3& aPos,
float aSize,
const glm::vec3& aColor,
const glm::vec3& aCamRight,
230 const glm::vec3& aCamUp )
232 glColor3f( aColor.r, aColor.g, aColor.b );
235 float h = aSize * 0.5f;
238 glm::vec3 topLeft = aPos + aCamUp * h - aCamRight * h;
239 glm::vec3 topRight = aPos + aCamUp * h + aCamRight * h;
240 glm::vec3 bottom = aPos - aCamUp * h;
243 glVertex3f( topLeft.x, topLeft.y, topLeft.z );
244 glVertex3f( aPos.x, aPos.y, aPos.z );
246 glVertex3f( topRight.x, topRight.y, topRight.z );
247 glVertex3f( aPos.x, aPos.y, aPos.z );
249 glVertex3f( aPos.x, aPos.y, aPos.z );
250 glVertex3f( bottom.x, bottom.y, bottom.z );
255 [](
const glm::vec3& aPos,
float aSize,
const glm::vec3& aColor,
const glm::vec3& aCamRight,
256 const glm::vec3& aCamUp )
258 glColor3f( aColor.r, aColor.g, aColor.b );
261 float h = aSize * 0.5f;
264 glm::vec3 topLeft = aPos + aCamUp * h - aCamRight * h;
265 glm::vec3 topRight = aPos + aCamUp * h + aCamRight * h;
266 glm::vec3 bottomLeft = aPos - aCamUp * h - aCamRight * h;
267 glm::vec3 bottomRight = aPos - aCamUp * h + aCamRight * h;
269 glBegin( GL_LINE_STRIP );
270 glVertex3f( topLeft.x, topLeft.y, topLeft.z );
271 glVertex3f( topRight.x, topRight.y, topRight.z );
272 glVertex3f( bottomLeft.x, bottomLeft.y, bottomLeft.z );
273 glVertex3f( bottomRight.x, bottomRight.y, bottomRight.z );
277 for(
size_t i = 0; i <
m_spheres.size(); ++i )
279 if( labels[i].
empty() )
282 glm::vec3 textPos =
m_spheres[i].m_position + offset;
283 const std::string& label = labels[i];
287 drawX( textPos, GIZMO_LABEL_SIZE, glm::vec3( 0.0f ), camRight, camUp );
289 else if( label ==
"Y" )
291 drawY( textPos, GIZMO_LABEL_SIZE, glm::vec3( 0.0f ), camRight, camUp );
293 else if( label ==
"Z" )
295 drawZ( textPos, GIZMO_LABEL_SIZE, glm::vec3( 0.0f ), camRight, camUp );
299 glEnable( GL_LIGHTING );
300 glEnable( GL_DEPTH_TEST );
306 glColor3f( 0.9f, 0.0f, 0.0f );
307 glVertex3f( 0.0f, 0.0f, 0.0f );
310 glColor3f( 0.0f, 0.9f, 0.0f );
311 glVertex3f( 0.0f, 0.0f, 0.0f );
314 glColor3f( 0.0f, 0.0f, 0.9f );
315 glVertex3f( 0.0f, 0.0f, 0.0f );
320 glEnable( GL_CULL_FACE );
341 glm::mat4 TranslationMatrix = glm::translate( glm::mat4( 1.0f ),
SFVEC3F( 0.0f, 0.0f, -(
m_arrowSize * GIZMO_CAMERA_DISTANCE_FACTOR ) ) );
342 glm::mat4 ViewMatrix = TranslationMatrix * aCameraRotationMatrix;
344 const float camDist =
m_arrowSize * GIZMO_CAMERA_DISTANCE_FACTOR;
346 glm::mat4 proj = glm::perspective( glm::radians( fov ), 1.0f, camDist - clipRadius, camDist + clipRadius );
347 glm::mat4 invVP = glm::inverse( proj * ViewMatrix );
352 glm::vec4 rayStartWorld = invVP * rayStartNDC;
353 rayStartWorld /= rayStartWorld.w;
355 glm::vec4 rayEndWorld = invVP * rayEndNDC;
356 rayEndWorld /= rayEndWorld.w;
358 glm::vec3 rayOrigin = glm::vec3( rayStartWorld );
359 glm::vec3 rayDirection = glm::normalize( glm::vec3( rayEndWorld - rayStartWorld ) );
361 auto intersectDist = [](
const glm::vec3& aRayOrigin,
const glm::vec3& aRayDir,
const glm::vec3& aSphereCenter,
362 float aRadius ) ->
float
364 glm::vec3
L = aSphereCenter - aRayOrigin;
365 float tca = glm::dot(
L, aRayDir );
366 float d2 = glm::dot(
L,
L ) - tca * tca;
368 if( d2 > aRadius * aRadius )
374 int clickedIndex = -1;
375 float closestDist = std::numeric_limits<float>::max();
378 for(
size_t i = 0; i <
m_spheres.size(); ++i )
381 float dist = intersectDist( rayOrigin, rayDirection, sphere.m_position, sphere.m_radius );
383 if( dist >= 0.0f && dist < closestDist )
386 clickedIndex =
static_cast<int>( i );
391 for(
size_t i = 0; i <
m_spheres.size(); ++i )
393 if(
static_cast<int>( i ) == clickedIndex )
394 m_spheres[i].m_color = { 1.0f, 1.0f, 1.0f };