feat: refine scene viewport gizmos and controls
This commit is contained in:
@@ -107,6 +107,70 @@ inline bool ProjectSceneViewportAxisDirection(
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ProjectSceneViewportAxisDirectionAtPoint(
|
||||
const SceneViewportOverlayData& overlay,
|
||||
float viewportWidth,
|
||||
float viewportHeight,
|
||||
const Math::Vector3& worldPoint,
|
||||
const Math::Vector3& worldAxis,
|
||||
Math::Vector2& outScreenDirection,
|
||||
float sampleDistance = 1.0f) {
|
||||
const Math::Vector3 axis = worldAxis.Normalized();
|
||||
if (!overlay.valid ||
|
||||
viewportWidth <= 1.0f ||
|
||||
viewportHeight <= 1.0f ||
|
||||
axis.SqrMagnitude() <= Math::EPSILON ||
|
||||
sampleDistance <= Math::EPSILON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Math::Matrix4x4 viewProjection =
|
||||
BuildSceneViewportViewProjectionMatrix(overlay, viewportWidth, viewportHeight);
|
||||
const Math::Vector4 startClip = viewProjection * Math::Vector4(worldPoint, 1.0f);
|
||||
const Math::Vector4 endClip = viewProjection * Math::Vector4(worldPoint + axis * sampleDistance, 1.0f);
|
||||
if (startClip.w <= Math::EPSILON || endClip.w <= Math::EPSILON) {
|
||||
return ProjectSceneViewportAxisDirection(overlay, axis, outScreenDirection);
|
||||
}
|
||||
|
||||
const Math::Vector3 startNdc = startClip.ToVector3() / startClip.w;
|
||||
const Math::Vector3 endNdc = endClip.ToVector3() / endClip.w;
|
||||
const Math::Vector2 startScreen(
|
||||
(startNdc.x * 0.5f + 0.5f) * viewportWidth,
|
||||
(1.0f - (startNdc.y * 0.5f + 0.5f)) * viewportHeight);
|
||||
const Math::Vector2 endScreen(
|
||||
(endNdc.x * 0.5f + 0.5f) * viewportWidth,
|
||||
(1.0f - (endNdc.y * 0.5f + 0.5f)) * viewportHeight);
|
||||
|
||||
const Math::Vector2 screenDirection = endScreen - startScreen;
|
||||
if (screenDirection.SqrMagnitude() <= Math::EPSILON) {
|
||||
return ProjectSceneViewportAxisDirection(overlay, axis, outScreenDirection);
|
||||
}
|
||||
|
||||
outScreenDirection = screenDirection.Normalized();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ProjectSceneViewportWorldPointClamped(
|
||||
const SceneViewportOverlayData& overlay,
|
||||
float viewportWidth,
|
||||
float viewportHeight,
|
||||
const Math::Vector3& worldPoint,
|
||||
float edgePadding,
|
||||
SceneViewportProjectedPoint& outProjectedPoint) {
|
||||
outProjectedPoint = ProjectSceneViewportWorldPoint(overlay, viewportWidth, viewportHeight, worldPoint);
|
||||
if (!overlay.valid || viewportWidth <= 1.0f || viewportHeight <= 1.0f || outProjectedPoint.ndcDepth < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const float minX = edgePadding;
|
||||
const float minY = edgePadding;
|
||||
const float maxX = viewportWidth - edgePadding;
|
||||
const float maxY = viewportHeight - edgePadding;
|
||||
outProjectedPoint.screenPosition.x = std::clamp(outProjectedPoint.screenPosition.x, minX, maxX);
|
||||
outProjectedPoint.screenPosition.y = std::clamp(outProjectedPoint.screenPosition.y, minY, maxY);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline float DistanceToSegmentSquared(
|
||||
const Math::Vector2& point,
|
||||
const Math::Vector2& segmentStart,
|
||||
|
||||
Reference in New Issue
Block a user