You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Editor/RenderHelpers/AxisHelperShared.inl

848 lines
24 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "AxisHelper.h"
#include "Objects/DisplayContext.h"
#include "Include/IDisplayViewport.h"
#include "Include/HitContext.h"
#include "Util/Math.h"
#include "IObjectManager.h"
#include <Cry_Geo.h>
const float kPlaneScale = 0.3f;
const float kBoldLine3D = 4.f;
const float kBoldLine2D = 2.f;
const float kSelectionBallScale = 0.05f;
const float kRotateCircleRadiusScale = 0.2f;
//////////////////////////////////////////////////////////////////////////
CAxisHelper::CAxisHelper()
: m_matrix(IDENTITY)
{
m_nModeFlags = MOVE_MODE;
m_currentMode = MOVE_MODE;
m_highlightMode = 1;
m_highlightAxis = 0;
m_bHighlightRotationCircle = false;
m_bNeedX = true;
m_bNeedY = true;
m_bNeedZ = true;
}
//////////////////////////////////////////////////////////////////////////
void CAxisHelper::SetMode(int nModeFlags)
{
m_nModeFlags = nModeFlags;
}
//////////////////////////////////////////////////////////////////////////
void CAxisHelper::Prepare(const Matrix34& worldTM, const SGizmoParameters& setup, IDisplayViewport* view)
{
m_fScreenScale = view->GetScreenScaleFactor(worldTM.GetTranslation());
m_size = setup.axisGizmoScale * m_fScreenScale;
m_bNeedX = true;
m_bNeedY = true;
m_bNeedZ = true;
IDisplayViewport::EAxis axis = IDisplayViewport::AXIS_NONE;
bool b2D = false;
view->GetPerpendicularAxis(&axis, &b2D);
switch (axis)
{
case static_cast<IDisplayViewport::EAxis>(AXIS_X):
m_bNeedX = false;
break;
case static_cast<IDisplayViewport::EAxis>(AXIS_Y):
m_bNeedY = false;
break;
case static_cast<IDisplayViewport::EAxis>(AXIS_Z):
m_bNeedZ = false;
break;
}
m_matrix = worldTM;
RefCoordSys refCoordSys = setup.referenceCoordSys;
if (b2D && refCoordSys == COORDS_VIEW)
{
m_matrix = view->GetViewTM();
m_matrix.SetTranslation(worldTM.GetTranslation());
}
m_matrix.OrthonormalizeFast();
}
//////////////////////////////////////////////////////////////////////////
void CAxisHelper::DrawDome(const Matrix34& worldTM, const SGizmoParameters& setup, DisplayContext& dc, AABB& objectBox)
{
Prepare(worldTM, setup, dc.view);
Vec3 x(m_size, 0, 0);
Vec3 y(0, m_size, 0);
Vec3 z(0, 0, m_size);
int prevRState = dc.GetState();
if (!(dc.flags & DISPLAY_2D))
{
dc.DepthTestOff();
}
dc.PushMatrix(m_matrix);
dc.SetDrawInFrontMode(true);
float radius = objectBox.GetRadius();
dc.DrawCircle(Vec3(0, 0, 0), radius);
dc.DrawCircle(Vec3(0, 0, 0), radius / 3.0f);
dc.DrawArc(Vec3(0, 0, 0), radius, 0.0f, 180.0f, 1, Vec3(0, -1, 0));
dc.DrawArc(Vec3(0, 0, 0), radius, 90.0f, 180.0f, 1, Vec3(1, 0, 0));
dc.PopMatrix();
if (!(dc.flags & DISPLAY_2D))
{
dc.DepthTestOn();
}
dc.SetState(prevRState);
}
//////////////////////////////////////////////////////////////////////////
void CAxisHelper::DrawAxis(const Matrix34& worldTM, const SGizmoParameters& setup, DisplayContext& dc)
{
Prepare(worldTM, setup, dc.view);
Vec3 x(m_size, 0, 0);
Vec3 y(0, m_size, 0);
Vec3 z(0, 0, m_size);
int prevRState = dc.GetState();
if (!(dc.flags & DISPLAY_2D))
{
dc.DepthTestOff();
}
dc.PushMatrix(m_matrix);
dc.SetDrawInFrontMode(true);
Vec3 colSelected(1, 1, 0);
Vec3 axisColor(1, 1, 1);
Vec3 disabledColor(0.75, 0.75, 0.75);
Matrix34 worldTMWithoutScale(worldTM);
worldTMWithoutScale.OrthonormalizeFast();
float textSize = 1.4f;
if (!(m_nModeFlags & ROTATE_CIRCLE_MODE))
{
dc.SetColor(setup.enabled ? axisColor : disabledColor);
if (m_bNeedX && setup.axisGizmoText)
{
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(x), textSize, "x");
}
if (m_bNeedY && setup.axisGizmoText)
{
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(y), textSize, "y");
}
if (m_bNeedZ && setup.axisGizmoText)
{
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(z), textSize, "z");
}
}
int axis = setup.axisConstraint;
if (m_highlightAxis)
{
axis = m_highlightAxis;
}
float lineWidth = kBoldLine3D;
if (dc.flags & DISPLAY_2D)
{
lineWidth = kBoldLine2D;
}
float linew[3];
linew[0] = linew[1] = linew[2] = 0;
Vec3 colX, colY, colZ;
if (setup.enabled)
{
colX = Vec3(1, 0, 0);
colY = Vec3(0, 1, 0);
colZ = Vec3(0, 0, 1);
}
else
{
colX = colY = colZ = disabledColor;
}
Vec3 colXArrow = colX, colYArrow = colY, colZArrow = colZ;
if (!(m_nModeFlags & ROTATE_CIRCLE_MODE))
{
if (axis)
{
if (axis == AXIS_X || axis == AXIS_XY || axis == AXIS_XZ || axis == AXIS_XYZ)
{
colX = colSelected;
dc.SetColor(colSelected);
if (m_bNeedX && setup.axisGizmoText)
{
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(x), textSize, "x");
}
linew[0] = lineWidth;
}
if (axis == AXIS_Y || axis == AXIS_XY || axis == AXIS_YZ || axis == AXIS_XYZ)
{
colY = colSelected;
dc.SetColor(colSelected);
if (m_bNeedY && setup.axisGizmoText)
{
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(y), textSize, "y");
}
linew[1] = lineWidth;
}
if (axis == AXIS_Z || axis == AXIS_XZ || axis == AXIS_YZ || axis == AXIS_XYZ)
{
colZ = colSelected;
dc.SetColor(colSelected);
if (m_bNeedZ && setup.axisGizmoText)
{
dc.DrawTextLabel(worldTMWithoutScale.TransformPoint(z), textSize, "z");
}
linew[2] = lineWidth;
}
}
}
//////////////////////////////////////////////////////////////////////////
// Calc sizes.
//////////////////////////////////////////////////////////////////////////
float headOfs[8];
float headScl[8];
headOfs[MOVE_MODE] = 0;
headScl[MOVE_MODE] = 0.07f * m_fScreenScale;
headOfs[ROTATE_MODE] = 0;
headScl[ROTATE_MODE] = 0.01f * m_fScreenScale;
headOfs[SCALE_MODE] = 0;
headScl[SCALE_MODE] = 0.01f * m_fScreenScale;
if (m_nModeFlags == (MOVE_MODE | ROTATE_MODE | SCALE_MODE))
{
headOfs[ROTATE_MODE] += 0.05f * m_fScreenScale;
headOfs[SCALE_MODE] += 0.1f * m_fScreenScale;
}
//////////////////////////////////////////////////////////////////////////
if (!(m_nModeFlags & ROTATE_CIRCLE_MODE))
{
if (m_bNeedX)
{
dc.SetColor(colX);
dc.SetLineWidth(linew[0]);
dc.DrawLine(Vec3(0, 0, 0), x + Vec3(headOfs[SCALE_MODE], 0, 0));
}
if (m_bNeedY)
{
dc.SetColor(colY);
dc.SetLineWidth(linew[1]);
dc.DrawLine(Vec3(0, 0, 0), y + Vec3(0, headOfs[SCALE_MODE], 0));
}
if (m_bNeedZ)
{
dc.SetColor(colZ);
dc.SetLineWidth(linew[2]);
dc.DrawLine(Vec3(0, 0, 0), z + Vec3(0, 0, headOfs[SCALE_MODE]));
}
}
//////////////////////////////////////////////////////////////////////////
// Draw Move Arrows.
//////////////////////////////////////////////////////////////////////////
if (m_nModeFlags & MOVE_MODE)
{
if (m_bNeedX)
{
if (m_highlightMode == 1)
{
dc.SetColor(colX);
}
else
{
dc.SetColor(colXArrow);
}
dc.DrawArrow(x - x * 0.1f, x, headScl[MOVE_MODE]);
}
if (m_bNeedY)
{
if (m_highlightMode == 1)
{
dc.SetColor(colY);
}
else
{
dc.SetColor(colYArrow);
}
dc.DrawArrow(y - y * 0.1f, y, headScl[MOVE_MODE]);
}
if (m_bNeedZ)
{
if (m_highlightMode == 1)
{
dc.SetColor(colZ);
}
else
{
dc.SetColor(colZArrow);
}
dc.DrawArrow(z - z * 0.1f, z, headScl[MOVE_MODE]);
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Draw Scale Boxes.
//////////////////////////////////////////////////////////////////////////
if (m_nModeFlags & SCALE_MODE)
{
dc.SetColor(QColor(128, 128, 0));
Vec3 boxsz = Vec3(headScl[SCALE_MODE], headScl[SCALE_MODE], headScl[SCALE_MODE]);
dc.DrawSolidBox(-boxsz, boxsz);
if (m_bNeedX)
{
if (m_highlightMode == 3)
{
dc.SetColor(colX);
}
else
{
dc.SetColor(colXArrow);
}
dc.DrawSolidBox(x + boxsz + Vec3(headOfs[SCALE_MODE], 0, 0), x - boxsz + Vec3(headOfs[SCALE_MODE], 0, 0));
}
if (m_bNeedY)
{
if (m_highlightMode == 3)
{
dc.SetColor(colY);
}
else
{
dc.SetColor(colYArrow);
}
dc.DrawSolidBox(y + boxsz + Vec3(0, headOfs[SCALE_MODE], 0), y - boxsz + Vec3(0, headOfs[SCALE_MODE], 0));
}
if (m_bNeedZ)
{
if (m_highlightMode == 3)
{
dc.SetColor(colZ);
}
else
{
dc.SetColor(colZArrow);
}
dc.DrawSolidBox(z + boxsz + Vec3(0, 0, headOfs[SCALE_MODE]), z - boxsz + Vec3(0, 0, headOfs[SCALE_MODE]));
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Draw Rotate Circle
//////////////////////////////////////////////////////////////////////////
if (m_nModeFlags & ROTATE_CIRCLE_MODE)
{
if (m_bHighlightRotationCircle)
{
dc.SetLineWidth(5);
dc.SetColor(colSelected);
}
else
{
dc.SetLineWidth(0);
dc.SetColor(axisColor);
}
dc.DrawCircle(Vec3(0, 0, 0), kRotateCircleRadiusScale * m_fScreenScale, 0);
}
dc.SetLineWidth(0);
// If only in move mode.
if (m_nModeFlags == MOVE_MODE)
{
//////////////////////////////////////////////////////////////////////////
// Draw axis planes.
//////////////////////////////////////////////////////////////////////////
Vec3 colXY[2];
Vec3 colXZ[2];
Vec3 colYZ[2];
if (setup.enabled)
{
colX = Vec3(1, 0, 0);
colY = Vec3(0, 1, 0);
colZ = Vec3(0, 0, 1);
}
else
{
colX = colY = colZ = disabledColor;
}
colXY[0] = colX;
colXY[1] = colY;
colXZ[0] = colX;
colXZ[1] = colZ;
colYZ[0] = colY;
colYZ[1] = colZ;
linew[0] = linew[1] = linew[2] = 0;
if (axis)
{
if (axis == AXIS_XY)
{
colXY[0] = colSelected;
colXY[1] = colSelected;
linew[0] = lineWidth;
}
else if (axis == AXIS_XZ)
{
colXZ[0] = colSelected;
colXZ[1] = colSelected;
linew[1] = lineWidth;
}
else if (axis == AXIS_YZ)
{
colYZ[0] = colSelected;
colYZ[1] = colSelected;
linew[2] = lineWidth;
}
}
if (!(dc.flags & DISPLAY_2D))
{
if (axis == AXIS_TERRAIN)
{
dc.SetColor(colSelected, 0.4f);
}
else
{
dc.SetColor(QColor(128, 32, 32), 0.4f);
}
dc.DrawBall(Vec3(0.0f), m_size * kSelectionBallScale);
}
dc.SetColor(QColor(255, 255, 0), 0.5f);
float sz = m_size * kPlaneScale;
Vec3 p1(sz, sz, 0);
Vec3 p2(sz, 0, sz);
Vec3 p3(0, sz, sz);
float colAlpha = 1.0f;
x *= kPlaneScale;
y *= kPlaneScale;
z *= kPlaneScale;
// XY
if (m_bNeedX && m_bNeedY)
{
dc.SetLineWidth(linew[0]);
dc.SetColor(colXY[0], colAlpha);
dc.DrawLine(p1, p1 - x);
dc.SetColor(colXY[1], colAlpha);
dc.DrawLine(p1, p1 - y);
}
// XZ
if (m_bNeedX && m_bNeedZ)
{
dc.SetLineWidth(linew[1]);
dc.SetColor(colXZ[0], colAlpha);
dc.DrawLine(p2, p2 - x);
dc.SetColor(colXZ[1], colAlpha);
dc.DrawLine(p2, p2 - z);
}
// YZ
if (m_bNeedY && m_bNeedZ)
{
dc.SetLineWidth(linew[2]);
dc.SetColor(colYZ[0], colAlpha);
dc.DrawLine(p3, p3 - y);
dc.SetColor(colYZ[1], colAlpha);
dc.DrawLine(p3, p3 - z);
}
dc.SetLineWidth(0);
colAlpha = 0.25f;
if (axis == AXIS_XY && m_bNeedX && m_bNeedY)
{
dc.CullOff();
dc.SetColor(colSelected, colAlpha);
dc.DrawQuad(p1, p1 - x, p1 - x - y, p1 - y);
dc.CullOn();
}
else if (axis == AXIS_XZ && m_bNeedX && m_bNeedZ)
{
dc.CullOff();
dc.SetColor(colSelected, colAlpha);
dc.DrawQuad(p2, p2 - x, p2 - x - z, p2 - z);
dc.CullOn();
}
else if (axis == AXIS_YZ && m_bNeedY && m_bNeedZ)
{
dc.CullOff();
dc.SetColor(colSelected, colAlpha);
dc.DrawQuad(p3, p3 - y, p3 - y - z, p3 - z);
dc.CullOn();
}
}
dc.PopMatrix();
if (!(dc.flags & DISPLAY_2D))
{
dc.DepthTestOn();
}
dc.SetState(prevRState);
}
//////////////////////////////////////////////////////////////////////////
bool CAxisHelper::HitTestForRotationCircle(const Matrix34& worldTM, IDisplayViewport* view, const QPoint& pos, float fHitWidth, Vec3* pOutHitPos, Vec3* pOutHitNormal)
{
Ray ray;
view->ViewToWorldRay(pos, ray.origin, ray.direction);
const float fCircleRadius = kRotateCircleRadiusScale * m_fScreenScale;
std::vector<Vec3> vList;
float step = 30.0f / 180 * gf_PI;
for (float angle = 0; angle < 360.0f / 180 * gf_PI + step; angle += step)
{
Vec3 p(0, fCircleRadius * sin(angle), fCircleRadius * cos(angle));
vList.push_back(worldTM.TransformPoint(p));
}
Vec3 vDir0 = (vList[0] - vList[1]).GetNormalized();
Vec3 vDir1 = (vList[2] - vList[1]).GetNormalized();
Vec3 vNormal = vDir1.Cross(vDir0).GetNormalized();
if (pOutHitNormal)
{
*pOutHitNormal = vNormal;
}
Vec3 vShortestHitPos;
float shortestDist = 3e11f;
for (int i = 0, iCount(static_cast<int>(vList.size())); i < iCount; ++i)
{
const Vec3& v0 = vList[i];
const Vec3& v1 = vList[(i + 1) % iCount];
Vec3 vRight = (v1 - v0).Cross(vNormal).GetNormalized() * m_fScreenScale * fHitWidth;
Vec3 p_v0 = v0 + vRight;
Vec3 p_v1 = v1 + vRight;
Vec3 p_v2 = v1 - vRight;
Vec3 p_v3 = v0 - vRight;
Vec3 hitPos;
if (Intersect::Ray_Triangle(ray, p_v0, p_v1, p_v2, hitPos) || Intersect::Ray_Triangle(ray, p_v0, p_v2, p_v3, hitPos) ||
Intersect::Ray_Triangle(ray, p_v0, p_v2, p_v1, hitPos) || Intersect::Ray_Triangle(ray, p_v0, p_v3, p_v2, hitPos))
{
Vec3 hitPosToEdge;
if (PointToLineDistance(v0, v1, hitPos, hitPosToEdge))
{
if (!pOutHitPos)
{
return true;
}
float hitDistance = hitPosToEdge.GetDistance(hitPos);
if (hitDistance < shortestDist)
{
vShortestHitPos = hitPosToEdge;
shortestDist = hitDistance;
}
}
}
}
if (shortestDist < 3e10f)
{
if (pOutHitPos)
{
*pOutHitPos = vShortestHitPos;
}
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
bool CAxisHelper::HitTest(const Matrix34& worldTM, const SGizmoParameters& setup, HitContext& hc)
{
if (hc.distanceTolerance != 0)
{
return 0;
}
Prepare(worldTM, setup, hc.view);
m_bHighlightRotationCircle = false;
hc.manipulatorMode = 0;
if (m_nModeFlags == ROTATE_CIRCLE_MODE)
{
if (HitTestForRotationCircle(m_matrix, hc.view, hc.point2d, 0.05f))
{
m_bHighlightRotationCircle = true;
hc.manipulatorMode = 4;
return true;
}
return false;
}
Vec3 x(m_size, 0, 0);
Vec3 y(0, m_size, 0);
Vec3 z(0, 0, m_size);
Vec3 pos = m_matrix.GetTranslation();
Vec3 intPoint;
hc.view->ViewToWorldRay(hc.point2d, hc.raySrc, hc.rayDir);
Ray ray(hc.raySrc, hc.rayDir);
Sphere sphere(pos, m_size + 0.1f * m_fScreenScale);
if (!Intersect::Ray_SphereFirst(ray, sphere, intPoint))
{
m_highlightAxis = 0;
return false;
}
x = m_matrix.TransformVector(x);
y = m_matrix.TransformVector(y);
z = m_matrix.TransformVector(z);
float sz = m_size * kPlaneScale;
Vec3 p1(sz, sz, 0);
Vec3 p2(sz, 0, sz);
Vec3 p3(0, sz, sz);
p1 = m_matrix.TransformPoint(p1);
p2 = m_matrix.TransformPoint(p2);
p3 = m_matrix.TransformPoint(p3);
Vec3 planeX = x * kPlaneScale;
Vec3 planeY = y * kPlaneScale;
Vec3 planeZ = z * kPlaneScale;
int axis = 0;
Sphere testSphere(pos, m_size * kSelectionBallScale);
if (!hc.b2DViewport && m_nModeFlags == MOVE_MODE && Intersect::Ray_SphereFirst(ray, testSphere, intPoint))
{
axis = AXIS_TERRAIN;
}
else
{
// Start the closestAxis value at the maximum selection radius based on the user's settings
float closestAxis = aznumeric_cast<float>(GetIEditor()->GetObjectManager()->GetAxisHelperHitRadius());
float distanceToAxis = hc.view->GetDistanceToLine(pos, pos + x, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_X;
closestAxis = distanceToAxis;
}
distanceToAxis = hc.view->GetDistanceToLine(pos, pos + y, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_Y;
closestAxis = distanceToAxis;
}
distanceToAxis = hc.view->GetDistanceToLine(pos, pos + z, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_Z;
closestAxis = distanceToAxis;
}
if (m_nModeFlags == MOVE_MODE)
{
// If only in move mode.
distanceToAxis = hc.view->GetDistanceToLine(p1, p1 - planeX, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_XY;
closestAxis = distanceToAxis;
}
distanceToAxis = hc.view->GetDistanceToLine(p1, p1 - planeY, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_XY;
closestAxis = distanceToAxis;
}
distanceToAxis = hc.view->GetDistanceToLine(p2, p2 - planeX, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_XZ;
closestAxis = distanceToAxis;
}
distanceToAxis = hc.view->GetDistanceToLine(p2, p2 - planeZ, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_XZ;
closestAxis = distanceToAxis;
}
distanceToAxis = hc.view->GetDistanceToLine(p3, p3 - planeY, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_YZ;
closestAxis = distanceToAxis;
}
distanceToAxis = hc.view->GetDistanceToLine(p3, p3 - planeZ, hc.point2d);
if(distanceToAxis < closestAxis)
{
axis = AXIS_YZ;
closestAxis = distanceToAxis;
}
if (axis != 0)
{
hc.manipulatorMode = 1;
}
}
}
//////////////////////////////////////////////////////////////////////////
// Calc sizes.
//////////////////////////////////////////////////////////////////////////
float headOfs[8];
float headScl[8];
headOfs[MOVE_MODE] = 0;
headScl[MOVE_MODE] = 0.07f * m_fScreenScale;
headOfs[ROTATE_MODE] = 0;
headScl[ROTATE_MODE] = 0.01f * m_fScreenScale;
headOfs[SCALE_MODE] = 0;
headScl[SCALE_MODE] = 0.01f * m_fScreenScale;
if (m_nModeFlags == (MOVE_MODE | ROTATE_MODE | SCALE_MODE))
{
headOfs[ROTATE_MODE] += 0.05f * m_fScreenScale;
headOfs[SCALE_MODE] += 0.1f * m_fScreenScale;
}
//////////////////////////////////////////////////////////////////////////
if (axis == 0 && (m_nModeFlags & ROTATE_MODE))
{
Vec3 x2(m_size, 0, 0);
Vec3 y2(0, m_size, 0);
Vec3 z2(0, 0, m_size);
int hitr = 10;
if (m_bNeedX)
{
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(x2 + Vec3(headOfs[ROTATE_MODE], 0, 0))) < hitr)
{
axis = AXIS_X;
hc.manipulatorMode = 2;
}
}
if (m_bNeedY)
{
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(y2 + Vec3(0, headOfs[ROTATE_MODE], 0))) < hitr)
{
axis = AXIS_Y;
hc.manipulatorMode = 2;
}
}
if (m_bNeedZ)
{
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(z2 + Vec3(0, 0, headOfs[ROTATE_MODE]))) < hitr)
{
axis = AXIS_Z;
hc.manipulatorMode = 2;
}
}
}
if (m_nModeFlags & SCALE_MODE)
{
Vec3 x2(m_size, 0, 0);
Vec3 y2(0, m_size, 0);
Vec3 z2(0, 0, m_size);
int hitr = 14;
if (GetDistance2D(hc.view, hc.point2d, m_matrix.GetTranslation()) < hitr + 2)
{
axis = AXIS_XYZ;
hc.manipulatorMode = 3;
}
if (axis == 0)
{
if (m_bNeedX)
{
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(x2 + Vec3(headOfs[SCALE_MODE], 0, 0))) < hitr)
{
axis = AXIS_X;
hc.manipulatorMode = 3;
}
}
if (m_bNeedY)
{
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(y2 + Vec3(0, headOfs[SCALE_MODE], 0))) < hitr)
{
axis = AXIS_Y;
hc.manipulatorMode = 3;
}
}
if (m_bNeedZ)
{
if (GetDistance2D(hc.view, hc.point2d, m_matrix.TransformPoint(z2 + Vec3(0, 0, headOfs[SCALE_MODE]))) < hitr)
{
axis = AXIS_Z;
hc.manipulatorMode = 3;
}
}
}
}
if (axis != 0)
{
if (hc.manipulatorMode == 0)
{
if (m_nModeFlags & MOVE_MODE)
{
hc.manipulatorMode = 1;
}
else if (m_nModeFlags & ROTATE_MODE)
{
hc.manipulatorMode = 2;
}
else if (m_nModeFlags & SCALE_MODE)
{
hc.manipulatorMode = 3;
}
}
hc.axis = axis;
hc.dist = 0;
m_highlightMode = hc.manipulatorMode;
}
m_highlightAxis = axis;
return axis != 0;
}
//////////////////////////////////////////////////////////////////////////
float CAxisHelper::GetDistance2D(IDisplayViewport* view, const QPoint& p, const Vec3& wp)
{
QPoint vp = view->WorldToView(wp);
float dx = static_cast<float>(p.x() - vp.x());
float dy = static_cast<float>(p.y() - vp.y());
return sqrtf(dx * dx + dy * dy);
}