Skip to content

Commit cb450ba

Browse files
committed
allow cameras orientation to be controlled with raw input pitch/yaw/roll degrees world scalars & still respect manipulate constraints; mark TODOs for orbit camera, we need another gimbal to control its target nicely
1 parent 61b5db0 commit cb450ba

File tree

4 files changed

+61
-63
lines changed

4 files changed

+61
-63
lines changed

61_UI/main.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,25 +2062,12 @@ class UISampleApp final : public examples::SimpleWindowedApplication
20622062
ImGuiInputTextFlags flags = 0;
20632063

20642064
ImGui::InputFloat3("Tr", &matrixTranslation[0], "%.3f", flags);
2065-
2066-
if (boundCameraToManipulate) // TODO: cameras are WiP here, imguizmo controller only works with translate manipulation + abs are banned currently
2067-
{
2068-
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(1.0f, 0.0f, 0.0f, 0.5f));
2069-
flags |= ImGuiInputTextFlags_ReadOnly;
2070-
}
2071-
20722065
ImGui::InputFloat3("Rt", &matrixRotation[0], "%.3f", flags);
20732066
ImGui::InputFloat3("Sc", &matrixScale[0], "%.3f", flags);
2074-
2075-
if(boundCameraToManipulate)
2076-
ImGui::PopStyleColor();
20772067
}
20782068
ImGuizmo::RecomposeMatrixFromComponents(&matrixTranslation[0], &matrixRotation[0], &matrixScale[0], m16TRSmatrix);
20792069
recomposed = *reinterpret_cast<float32_t4x4*>(m16TRSmatrix);
20802070

2081-
// TODO AND NOTE: I only take care of translate part temporary!
2082-
imguizmoModel.outDeltaTRS[3] = recomposed[3] - decomposed[3];
2083-
20842071
if (mCurrentGizmoOperation != ImGuizmo::SCALE)
20852072
{
20862073
if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
@@ -2110,6 +2097,19 @@ class UISampleApp final : public examples::SimpleWindowedApplication
21102097
// generate virtual events given delta TRS matrix
21112098
if (boundCameraToManipulate)
21122099
{
2100+
const float pmSpeed = boundCameraToManipulate->getMoveSpeedScale();
2101+
const float prSpeed = boundCameraToManipulate->getRotationSpeedScale();
2102+
2103+
boundCameraToManipulate->setMoveSpeedScale(1);
2104+
boundCameraToManipulate->setRotationSpeedScale(1);
2105+
2106+
auto referenceFrame = getCastedMatrix<float64_t>(imguizmoModel.outTRS);
2107+
boundCameraToManipulate->manipulate({}, &referenceFrame);
2108+
2109+
boundCameraToManipulate->setMoveSpeedScale(pmSpeed);
2110+
boundCameraToManipulate->setRotationSpeedScale(prSpeed);
2111+
2112+
/*
21132113
{
21142114
static std::vector<CVirtualGimbalEvent> virtualEvents(0x45);
21152115
@@ -2141,13 +2141,15 @@ class UISampleApp final : public examples::SimpleWindowedApplication
21412141
boundCameraToManipulate->setMoveSpeedScale(1);
21422142
boundCameraToManipulate->setRotationSpeedScale(1);
21432143
2144-
boundCameraToManipulate->manipulate({ virtualEvents.data(), vCount });
2144+
auto referenceFrame = getCastedMatrix<float64_t>(imguizmoModel.outTRS);
2145+
boundCameraToManipulate->manipulate({ virtualEvents.data(), vCount }, &referenceFrame);
21452146
21462147
boundCameraToManipulate->setMoveSpeedScale(pmSpeed);
21472148
boundCameraToManipulate->setRotationSpeedScale(prSpeed);
21482149
}
21492150
}
21502151
}
2152+
*/
21512153
}
21522154
else
21532155
{

common/include/camera/CFPSCamera.hpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,30 +50,44 @@ class CFPSCamera final : public ICamera
5050

5151
virtual bool manipulate(std::span<const CVirtualGimbalEvent> virtualEvents, const float64_t4x4 const* referenceFrame = nullptr) override
5252
{
53-
if (!virtualEvents.size())
53+
// TODO: note, for FPS camera its assumed tilt is performed with respect to "world" up vector which is (0,1,0)
54+
// but in reality its all about where -(gravity force) vector is, we can just add it and construct yaw quat with respect to this new custom vector instead
55+
56+
if (not virtualEvents.size() and not referenceFrame)
5457
return false;
5558

5659
CReferenceTransform reference;
5760
if (not m_gimbal.extractReferenceTransform(&reference, referenceFrame))
5861
return false;
5962

63+
auto validateReference = [&]()
64+
{
65+
if (referenceFrame)
66+
{
67+
// invalidate roll
68+
auto euler = glm::eulerAngles(reference.orientation) * 180.f / core::PI<float>();
69+
auto roll = std::abs(euler.z);
70+
constexpr float epsilon = 1.e-4f;
71+
72+
if (not (glm::epsilonEqual(roll, 0.f, epsilon) || glm::epsilonEqual(roll, 180.f, epsilon)))
73+
return false;
74+
}
75+
76+
return true;
77+
};
78+
6079
auto impulse = m_gimbal.accumulate<AllowedVirtualEvents>(virtualEvents);
6180

6281
bool manipulated = true;
6382

6483
m_gimbal.begin();
6584
{
66-
if (impulse.dVirtualRotation.x or impulse.dVirtualRotation.y or impulse.dVirtualRotation.z)
67-
{
68-
const auto rForward = glm::vec3(reference.frame[2]);
69-
const float rPitch = atan2(glm::length(glm::vec2(rForward.x, rForward.z)), rForward.y) - glm::half_pi<float>(), gYaw = atan2(rForward.x, rForward.z);
70-
const float newPitch = std::clamp<float>(rPitch + impulse.dVirtualRotation.x * m_rotationSpeedScale, MinVerticalAngle, MaxVerticalAngle), newYaw = gYaw + impulse.dVirtualRotation.y * m_rotationSpeedScale;
71-
72-
m_gimbal.setOrientation(glm::quat(glm::vec3(newPitch, newYaw, 0.0f)));
73-
}
85+
const auto rForward = glm::vec3(reference.frame[2]);
86+
const float rPitch = atan2(glm::length(glm::vec2(rForward.x, rForward.z)), rForward.y) - glm::half_pi<float>(), gYaw = atan2(rForward.x, rForward.z);
87+
const float newPitch = std::clamp<float>(rPitch + impulse.dVirtualRotation.x * m_rotationSpeedScale, MinVerticalAngle, MaxVerticalAngle), newYaw = gYaw + impulse.dVirtualRotation.y * m_rotationSpeedScale;
7488

75-
if (impulse.dVirtualTranslate.x or impulse.dVirtualTranslate.y or impulse.dVirtualTranslate.z)
76-
m_gimbal.setPosition(glm::vec3(reference.frame[3]) + reference.orientation * glm::vec3(impulse.dVirtualTranslate));
89+
if(validateReference()) m_gimbal.setOrientation(glm::quat(glm::vec3(newPitch, newYaw, 0.0f)));
90+
m_gimbal.setPosition(glm::vec3(reference.frame[3]) + reference.orientation * glm::vec3(impulse.dVirtualTranslate));
7791
}
7892
m_gimbal.end();
7993

common/include/camera/CFreeLockCamera.hpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class CFreeCamera final : public ICamera
8686

8787
virtual bool manipulate(std::span<const CVirtualGimbalEvent> virtualEvents, const float64_t4x4 const* referenceFrame = nullptr) override
8888
{
89-
if (!virtualEvents.size())
89+
if (not virtualEvents.size() and not referenceFrame)
9090
return false;
9191

9292
CReferenceTransform reference;
@@ -107,17 +107,12 @@ class CFreeCamera final : public ICamera
107107

108108
m_gimbal.begin();
109109
{
110-
if (impulse.dVirtualRotation.x or impulse.dVirtualRotation.y or impulse.dVirtualRotation.z)
111-
{
112-
glm::quat pitch = glm::angleAxis<float>(impulse.dVirtualRotation.x, glm::vec3(reference.frame[0]));
113-
glm::quat yaw = glm::angleAxis<float>(impulse.dVirtualRotation.y, glm::vec3(reference.frame[1]));
114-
glm::quat roll = glm::angleAxis<float>(impulse.dVirtualRotation.z, glm::vec3(reference.frame[2]));
110+
glm::quat pitch = glm::angleAxis<float>(impulse.dVirtualRotation.x, glm::vec3(reference.frame[0]));
111+
glm::quat yaw = glm::angleAxis<float>(impulse.dVirtualRotation.y, glm::vec3(reference.frame[1]));
112+
glm::quat roll = glm::angleAxis<float>(impulse.dVirtualRotation.z, glm::vec3(reference.frame[2]));
115113

116-
m_gimbal.setOrientation(yaw * pitch * roll * reference.orientation);
117-
}
118-
119-
if(impulse.dVirtualTranslate.x or impulse.dVirtualTranslate.y or impulse.dVirtualTranslate.z)
120-
m_gimbal.setPosition(glm::vec3(reference.frame[3]) + reference.orientation * glm::vec3(impulse.dVirtualTranslate));
114+
m_gimbal.setOrientation(yaw * pitch * roll * reference.orientation);
115+
m_gimbal.setPosition(glm::vec3(reference.frame[3]) + reference.orientation * glm::vec3(impulse.dVirtualTranslate));
121116
}
122117
m_gimbal.end();
123118

common/include/camera/COrbitCamera.hpp

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class COrbitCamera final : public ICamera
3939

4040
virtual bool manipulate(std::span<const CVirtualGimbalEvent> virtualEvents, const float64_t4x4 const* referenceFrame = nullptr) override
4141
{
42+
// TODO: it must work differently, we should take another gimbal to control target
43+
4244
// position on the sphere
4345
auto S = [&](double u, double v) -> float64_t3
4446
{
@@ -63,23 +65,19 @@ class COrbitCamera final : public ICamera
6365
};
6466
*/
6567

66-
double deltaU = {}, deltaV = {}, deltaDistance = {};
67-
68-
for (const auto& it : virtualEvents)
68+
// partial derivative of S with respect to v
69+
auto Sdv = [&](double u, double v) -> float64_t3
6970
{
70-
if (it.type == it.MoveForward)
71-
deltaDistance += it.magnitude;
72-
else if (it.type == it.MoveBackward)
73-
deltaDistance -= it.magnitude;
74-
else if (it.type == it.MoveUp)
75-
deltaU += it.magnitude;
76-
else if (it.type == it.MoveDown)
77-
deltaU -= it.magnitude;
78-
else if (it.type == it.MoveRight)
79-
deltaV += it.magnitude;
80-
else if (it.type == it.MoveLeft)
81-
deltaV -= it.magnitude;
82-
}
71+
return float64_t3
72+
{
73+
-std::sin(v) * std::cos(u),
74+
-std::sin(v) * std::sin(u),
75+
std::cos(v)
76+
} *(double)m_distance;
77+
};
78+
79+
auto impulse = m_gimbal.accumulate<AllowedVirtualEvents>(virtualEvents);
80+
double deltaU = impulse.dVirtualTranslate.y, deltaV = impulse.dVirtualTranslate.x, deltaDistance = impulse.dVirtualTranslate.z;
8381

8482
// TODO!
8583
constexpr auto nastyScalar = 0.01;
@@ -91,17 +89,6 @@ class COrbitCamera final : public ICamera
9189

9290
m_distance = std::clamp<float>(m_distance += deltaDistance * nastyScalar, MinDistance, MaxDistance);
9391

94-
// partial derivative of S with respect to v
95-
auto Sdv = [&](double u, double v) -> float64_t3
96-
{
97-
return float64_t3
98-
{
99-
-std::sin(v) * std::cos(u),
100-
-std::sin(v) * std::sin(u),
101-
std::cos(v)
102-
} * (double) m_distance;
103-
};
104-
10592
const auto localSpherePostion = S(u, v);
10693
const auto newPosition = localSpherePostion + m_targetPosition;
10794

0 commit comments

Comments
 (0)