| 394 | } |
| 395 | |
| 396 | Vector3 Tr2RotationTool::Hemisphere( int mouseX, int mouseY, Tr2Viewport& viewport, Matrix& viewMatrix, Matrix& projectionMatrix ) const |
| 397 | { |
| 398 | Matrix viewProj = viewMatrix * projectionMatrix; |
| 399 | |
| 400 | auto project = [&]( Vector3 in ) -> Vector2 { |
| 401 | Vector4 out = Vector4( in.x, in.y, in.z, 1 ) * viewProj; |
| 402 | |
| 403 | return Vector2( viewport.m_x + viewport.m_width * ( 0.5f + 0.5f * out.x / out.w ), |
| 404 | viewport.m_y + viewport.m_height * ( 0.5f - 0.5f * out.y / out.w ) ); |
| 405 | }; |
| 406 | |
| 407 | float radius = m_wwLine->m_scale; |
| 408 | |
| 409 | Vector3 center, viewSide; |
| 410 | center.x = m_worldTransform._41; |
| 411 | center.y = m_worldTransform._42; |
| 412 | center.z = m_worldTransform._43; |
| 413 | |
| 414 | viewSide.x = viewMatrix._11 * radius; |
| 415 | viewSide.y = viewMatrix._21 * radius; |
| 416 | viewSide.z = viewMatrix._31 * radius; |
| 417 | |
| 418 | Vector3 side = center - viewSide; |
| 419 | |
| 420 | Vector2 screenCenter = project( center ); |
| 421 | Vector2 screenSide = project( side ); |
| 422 | |
| 423 | Vector2 dxy = screenCenter - screenSide; |
| 424 | float radius_pixels = sqrtf( dxy.x * dxy.x + dxy.y * dxy.y ) + 16; // add the width of the cursor |
| 425 | |
| 426 | |
| 427 | float px = ( mouseX - screenCenter.x ) / radius_pixels; |
| 428 | float py = ( screenCenter.y - mouseY ) / radius_pixels; |
| 429 | float d = sqrt( px * px + py * py ); |
| 430 | float z = 0.0f; |
| 431 | if( d <= 1.0f ) |
| 432 | { |
| 433 | z = 1.0f - d; |
| 434 | } |
| 435 | |
| 436 | Vector3 result( px, py, z ); |
| 437 | |
| 438 | return Vector3( XMVector3Normalize( result ) ); |
| 439 | } |