Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GuiTraceRay from theater ray intersection instead of camera position. #1782

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions rts/Game/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "System/float3.h"
#include "System/Matrix44f.h"
#include "System/Config/ConfigHandler.h"
#include "Sim/Units/UnitHandler.h"

#include "System/Misc/TracyDefs.h"

Expand Down Expand Up @@ -773,6 +774,39 @@ float3 CCamera::GetMoveVectorFromState(bool fromKeyState) const
return v;
}

float3 CCamera::PointToMaxUnitAltitude(const float3& point, const float rayLength, const float maxAltitude) const
{
const float3 dir = (point-pos).Normalize();
float dist = CGround::LinePlaneCol(pos, dir, rayLength, maxAltitude);
if (dist > 0.0)
return pos + dir*dist;
return point;
}

float3 CCamera::NearTheaterIntersection(const float3& dir, const float rayLength) const
{
const float maxAltitude = std::max(unitHandler.MaxUnitAltitude(), readMap->GetCurrMaxHeight());
if (pos.y < maxAltitude)
return pos;
const float3 fv1 = PointToMaxUnitAltitude(GetFrustumVert(CCamera::FRUSTUM_POINT_FBL), rayLength, maxAltitude);
const float3 fv2 = PointToMaxUnitAltitude(GetFrustumVert(CCamera::FRUSTUM_POINT_FBR), rayLength, maxAltitude);
float3 midFv = (fv1+fv2)/2.0;
midFv.y = pos.y;

// vertical plane from frustum intersection to max height
const float3 p = fv1;
const float3 norm = midFv-pos;
const float d = -(norm.x*p.x+norm.y*p.y+norm.z*p.z);
saurtron marked this conversation as resolved.
Show resolved Hide resolved
const float4 nearTheaterPlane = float4(norm.x, norm.y, norm.z, d);

// intersection
float3 intersection;
const bool res = RayAndPlaneIntersection(pos, pos+dir*rayLength, nearTheaterPlane, false, intersection);
if (res)
return intersection;
return pos;
}

// http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-points-and-spheres/
bool CCamera::Frustum::IntersectSphere(float3 p, float radius, uint8_t testMask) const
{
Expand Down
3 changes: 3 additions & 0 deletions rts/Game/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ class CCamera {
return (forward.dot(objPos - pos));
}

float3 PointToMaxUnitAltitude(const float3& point, const float rayLength, const float maxAltitude) const;
float3 NearTheaterIntersection(const float3& dir, const float rayLength) const;

/*
float ProjectedDistanceShadow(const float3& objPos, const float3& sunDir) const {
// FIXME: fix it, cap it for shallow shadows?
Expand Down
39 changes: 26 additions & 13 deletions rts/Game/UI/GuiHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1155,8 +1155,9 @@ bool CGuiHandler::TryTarget(const SCommandDescription& cmdDesc) const
const CFeature* targetFeature = nullptr;

const float viewRange = camera->GetFarPlaneDist() * 1.4f;
const float dist = TraceRay::GuiTraceRay(camera->GetPos(), mouse->dir, viewRange, NULL, targetUnit, targetFeature, true);
const float3 groundPos = camera->GetPos() + mouse->dir * dist;
const float3 rayOrigin = camera->NearTheaterIntersection(mouse->dir, viewRange);
const float dist = TraceRay::GuiTraceRay(rayOrigin, mouse->dir, viewRange, NULL, targetUnit, targetFeature, true);
const float3 groundPos = rayOrigin + mouse->dir * dist;

if (dist <= 0.0f)
return false;
Expand Down Expand Up @@ -1685,8 +1686,11 @@ int CGuiHandler::GetDefaultCommand(int x, int y, const float3& cameraPos, const
unit = minimap->GetSelectUnit(minimap->GetMapPosition(x, y));
} else {
const float viewRange = camera->GetFarPlaneDist() * 1.4f;
const float dist = TraceRay::GuiTraceRay(cameraPos, mouseDir, viewRange, nullptr, unit, feature, true);
const float3 hit = cameraPos + mouseDir * dist;

const float3 rayOrigin = camera->NearTheaterIntersection(mouseDir, viewRange);
const float dist = TraceRay::GuiTraceRay(rayOrigin, mouseDir, viewRange, nullptr, unit, feature, true);

const float3 hit = rayOrigin + mouseDir * dist;

// make sure the ray hit in the map
if (unit == nullptr && feature == nullptr && !hit.IsInBounds())
Expand Down Expand Up @@ -2265,7 +2269,9 @@ Command CGuiHandler::GetCommand(int mouseX, int mouseY, int buttonHint, bool pre
const CUnit* unit = nullptr;
const CFeature* feature = nullptr;

TraceRay::GuiTraceRay(cameraPos, mouseDir, camera->GetFarPlaneDist() * 1.4f, nullptr, unit, feature, true);
const float viewRange = camera->GetFarPlaneDist() * 1.4f;
const float3 rayOrigin = camera->NearTheaterIntersection(mouseDir, viewRange);
TraceRay::GuiTraceRay(rayOrigin, mouseDir, viewRange, nullptr, unit, feature, true);

if (unit == nullptr)
return defaultRet;
Expand All @@ -2282,7 +2288,8 @@ Command CGuiHandler::GetCommand(int mouseX, int mouseY, int buttonHint, bool pre
const CFeature* feature = nullptr;

const float traceDist = camera->GetFarPlaneDist() * 1.4f;
const float isectDist = TraceRay::GuiTraceRay(cameraPos, mouseDir, traceDist, nullptr, unit, feature, true);
const float3 rayOrigin = camera->NearTheaterIntersection(mouseDir, traceDist);
const float isectDist = TraceRay::GuiTraceRay(rayOrigin, mouseDir, traceDist, nullptr, unit, feature, true);

if (isectDist > (traceDist - 300.0f))
return defaultRet;
Expand All @@ -2292,7 +2299,7 @@ Command CGuiHandler::GetCommand(int mouseX, int mouseY, int buttonHint, bool pre
c.PushParam(unit->id);
} else {
// clicked in map
c.PushPos(cameraPos + (mouseDir * isectDist));
c.PushPos(rayOrigin + (mouseDir * isectDist));
}
return CheckCommand(c);
}
Expand Down Expand Up @@ -2345,7 +2352,9 @@ Command CGuiHandler::GetCommand(int mouseX, int mouseY, int buttonHint, bool pre
if (mouse->buttons[button].movement <= mouse->dragCircleCommandThreshold) {
const CUnit* unit = nullptr;
const CFeature* feature = nullptr;
const float dist2 = TraceRay::GuiTraceRay(cameraPos, mouseDir, camera->GetFarPlaneDist() * 1.4f, NULL, unit, feature, true);
const float viewRange = camera->GetFarPlaneDist() * 1.4f;
const float3 rayOrigin = camera->NearTheaterIntersection(mouseDir, viewRange);
const float dist2 = TraceRay::GuiTraceRay(rayOrigin, mouseDir, viewRange, NULL, unit, feature, true);
saurtron marked this conversation as resolved.
Show resolved Hide resolved

if (dist2 > (camera->GetFarPlaneDist() * 1.4f - 300) && (commands[tempInCommand].type != CMDTYPE_ICON_UNIT_FEATURE_OR_AREA))
return defaultRet;
Expand All @@ -2362,7 +2371,7 @@ Command CGuiHandler::GetCommand(int mouseX, int mouseY, int buttonHint, bool pre
if (explicitCommand < 0 || !ZeroRadiusAllowed(c))
return defaultRet;

c.PushPos(cameraPos + (mouseDir * dist2));
c.PushPos(rayOrigin + (mouseDir * dist2));
c.PushParam(0); // zero radius

if (c.GetID() == CMD_UNLOAD_UNITS)
Expand Down Expand Up @@ -2408,7 +2417,8 @@ Command CGuiHandler::GetCommand(int mouseX, int mouseY, int buttonHint, bool pre
const CFeature* feature = nullptr;

const float traceDist = camera->GetFarPlaneDist() * 1.4f;
const float outerDist = TraceRay::GuiTraceRay(cameraPos, mouseDir, traceDist, nullptr, unit, feature, true);
const float3 rayOrigin = camera->NearTheaterIntersection(mouseDir, traceDist);
const float outerDist = TraceRay::GuiTraceRay(rayOrigin, mouseDir, traceDist, nullptr, unit, feature, true);

if (outerDist > (traceDist - 300.0f))
return defaultRet;
Expand All @@ -2421,7 +2431,7 @@ Command CGuiHandler::GetCommand(int mouseX, int mouseY, int buttonHint, bool pre
if (explicitCommand < 0)
return defaultRet;

c.PushPos(cameraPos + (mouseDir * outerDist));
c.PushPos(rayOrigin + (mouseDir * outerDist));
}
} else {
// create rectangular area-command
Expand Down Expand Up @@ -2503,7 +2513,9 @@ size_t CGuiHandler::GetBuildPositions(const BuildInfo& startInfo, const BuildInf
const CUnit* unit = nullptr;
const CFeature* feature = nullptr;

TraceRay::GuiTraceRay(cameraPos, mouseDir, camera->GetFarPlaneDist() * 1.4f, nullptr, unit, feature, startInfo.def->floatOnWater);
const float viewRange = camera->GetFarPlaneDist() * 1.4f;
const float3 rayOrigin = camera->NearTheaterIntersection(mouseDir, viewRange);
TraceRay::GuiTraceRay(rayOrigin, mouseDir, viewRange, nullptr, unit, feature, startInfo.def->floatOnWater);

if (unit != nullptr) {
other.def = unit->unitDef;
Expand Down Expand Up @@ -3710,7 +3722,8 @@ void CGuiHandler::DrawMapStuff(bool onMiniMap)
unit = minimap->GetSelectUnit(tracePos);
} else {
// ignore the returned distance, we don't care about it here
TraceRay::GuiTraceRay(tracePos, traceDir, maxTraceDist, nullptr, unit, feature, false);
const float3 rayOrigin = camera->NearTheaterIntersection(traceDir, maxTraceDist);
TraceRay::GuiTraceRay(rayOrigin, traceDir, maxTraceDist, nullptr, unit, feature, false);
}

if (unit != nullptr && (gu->spectatingFullView || unit->IsInLosForAllyTeam(gu->myAllyTeam))) {
Expand Down
9 changes: 6 additions & 3 deletions rts/Game/UI/MouseHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,9 @@ void CMouseHandler::MouseRelease(int x, int y, int button)
const CUnit* unit = nullptr;
const CFeature* feature = nullptr;

TraceRay::GuiTraceRay(camera->GetPos(), dir, camera->GetFarPlaneDist() * 1.4f, nullptr, unit, feature, false);
const float viewRange = camera->GetFarPlaneDist() * 1.4f;
const float3 rayOrigin = camera->NearTheaterIntersection(dir, viewRange);
TraceRay::GuiTraceRay(rayOrigin, dir, viewRange, nullptr, unit, feature, false);
lastClicked = unit;

const bool selectType = (bp.lastRelease >= (gu->gameTime - doubleClickTime) && unit == _lastClicked);
Expand Down Expand Up @@ -701,8 +703,9 @@ std::string CMouseHandler::GetCurrentTooltip() const
const CUnit* unit = nullptr;
const CFeature* feature = nullptr;

const float3 rayOrigin = camera->NearTheaterIntersection(dir, range);
{
dist = TraceRay::GuiTraceRay(camera->GetPos(), dir, range, nullptr, unit, feature, true, false, true);
dist = TraceRay::GuiTraceRay(rayOrigin, dir, range, nullptr, unit, feature, true, false, true);

if (unit != nullptr) return CTooltipConsole::MakeUnitString(unit);
if (feature != nullptr) return CTooltipConsole::MakeFeatureString(feature);
Expand All @@ -714,7 +717,7 @@ std::string CMouseHandler::GetCurrentTooltip() const
return selTip;

if (dist <= range)
return CTooltipConsole::MakeGroundString(camera->GetPos() + (dir * dist));
return CTooltipConsole::MakeGroundString(rayOrigin + (dir * dist));

return "";
}
Expand Down
2 changes: 2 additions & 0 deletions rts/Lua/LuaSyncedCtrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3261,6 +3261,7 @@ int LuaSyncedCtrl::SetUnitMidAndAimPos(lua_State* L)

if (updateQuads) {
quadField.MovedUnit(unit);
unitHandler.MovedUnit(unit);
}

lua_pushboolean(L, true);
Expand Down Expand Up @@ -3296,6 +3297,7 @@ int LuaSyncedCtrl::SetUnitRadiusAndHeight(lua_State* L)

if (updateQuads) {
quadField.MovedUnit(unit);
unitHandler.MovedUnit(unit);
}

lua_pushboolean(L, true);
Expand Down
11 changes: 8 additions & 3 deletions rts/Lua/LuaUnsyncedRead.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2952,10 +2952,15 @@ int LuaUnsyncedRead::TraceScreenRay(lua_State* L)
const float3 pxlDir = camera->CalcPixelDir(wx, wy);

// trace for player's allyteam
const float traceDist = TraceRay::GuiTraceRay(camPos, pxlDir, rawRange, nullptr, unit, feature, true, onlyCoords, ignoreWater);
float3 rayOrigin;
if (onlyCoords)
rayOrigin = camPos;
else
rayOrigin = camera->NearTheaterIntersection(pxlDir, rawRange);
const float traceDist = TraceRay::GuiTraceRay(rayOrigin, pxlDir, rawRange, nullptr, unit, feature, true, onlyCoords, ignoreWater);
const float planeDist = CGround::LinePlaneCol(camPos, pxlDir, rawRange, luaL_optnumber(L, newArgIdx, 0.0f));

const float3 tracePos = camPos + (pxlDir * traceDist);
const float3 tracePos = rayOrigin + (pxlDir * traceDist);
const float3 planePos = camPos + (pxlDir * planeDist); // backup (for includeSky and onlyCoords)

if ((traceDist < 0.0f || traceDist > badRange) && unit == nullptr && feature == nullptr) {
Expand Down Expand Up @@ -4890,4 +4895,4 @@ int LuaUnsyncedRead::SolveNURBSCurve(lua_State* L)
lua_rawseti(L, -2, ++i);
}
return 1;
}
}
5 changes: 3 additions & 2 deletions rts/Rendering/UniformConstants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,10 @@ void UniformConstants::UpdateParamsImpl(UniformParamsBuffer* updateBuffer)
const float3 pxlDir = camPlayer->CalcPixelDir(wx, wy);

// trace for player's allyteam
const float traceDist = TraceRay::GuiTraceRay(camPos, pxlDir, rawRange, nullptr, unit, feature, true, false, true);
const float3 rayOrigin = camPlayer->NearTheaterIntersection(pxlDir, rawRange);
const float traceDist = TraceRay::GuiTraceRay(rayOrigin, pxlDir, rawRange, nullptr, unit, feature, true, false, true);

const float3 tracePos = camPos + (pxlDir * traceDist);
const float3 tracePos = rayOrigin + (pxlDir * traceDist);

if (unit)
updateBuffer->mouseWorldPos = float4{ unit->drawPos, 1.0f };
Expand Down
2 changes: 2 additions & 0 deletions rts/Sim/Units/Unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ void CUnit::ForcedMove(const float3& newPos)

eventHandler.UnitMoved(this);
quadField.MovedUnit(this);
unitHandler.MovedUnit(this);
}


Expand Down Expand Up @@ -741,6 +742,7 @@ void CUnit::UpdateTransportees()
// see ::AttachUnit
if (transportee->IsStunned()) {
quadField.MovedUnit(transportee);
unitHandler.MovedUnit(transportee);
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions rts/Sim/Units/UnitHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ CR_REG_METADATA(CUnitHandler, (

CR_MEMBER(maxUnits),
CR_MEMBER(maxUnitRadius),
CR_MEMBER_UN(maxUnitAltitude),

CR_MEMBER(inUpdateCall)
))
Expand Down Expand Up @@ -115,6 +116,7 @@ void CUnitHandler::Init() {
// other team in the respective allyteam
maxUnits = CalcMaxUnits();
maxUnitRadius = 0.0f;
maxUnitAltitude = 0.0f;
}
{
activeSlowUpdateUnit = 0;
Expand Down Expand Up @@ -170,6 +172,7 @@ void CUnitHandler::Kill()
{
maxUnits = 0;
maxUnitRadius = 0.0f;
maxUnitAltitude = 0.0f;
}
}

Expand Down Expand Up @@ -236,6 +239,7 @@ bool CUnitHandler::AddUnit(CUnit* unit)
spring::VectorInsertUnique(GetUnitsByTeamAndDef(unit->team, unit->unitDef->id), unit, false);

maxUnitRadius = std::max(unit->radius, maxUnitRadius);
MovedUnit(unit);
return true;
}

Expand Down Expand Up @@ -408,13 +412,15 @@ void CUnitHandler::UpdateUnits()
{
SCOPED_TIMER("Sim::Unit::Update");

maxUnitAltitude = 0.0f;
saurtron marked this conversation as resolved.
Show resolved Hide resolved
size_t activeUnitCount = activeUnits.size();
for (size_t i = 0; i < activeUnitCount; ++i) {
CUnit* unit = activeUnits[i];

unit->SanityCheck();
unit->Update();
unit->moveType->UpdateCollisionMap();
MovedUnit(unit);
// unsynced; done on-demand when drawing unit
// unit->UpdateLocalModel();
unit->SanityCheck();
Expand Down Expand Up @@ -514,3 +520,7 @@ unsigned int CUnitHandler::CalcMaxUnits() const
return n;
}

void CUnitHandler::MovedUnit(CUnit* unit)
{
maxUnitAltitude = std::max(unit->pos.y + unit->radius, maxUnitAltitude);
}
6 changes: 6 additions & 0 deletions rts/Sim/Units/UnitHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class CUnitHandler

void Update();
bool AddUnit(CUnit* unit);
void MovedUnit(CUnit* unit);

bool CanAddUnit(int id) const {
// do we want to be assigned a random ID and are any left in pool?
Expand All @@ -46,6 +47,7 @@ class CUnitHandler
unsigned int CalcMaxUnits() const;

float MaxUnitRadius() const { return maxUnitRadius; }
float MaxUnitAltitude() const { return maxUnitAltitude; }

/// Returns true if a unit of type unitID can be built, false otherwise
bool CanBuildUnit(const UnitDef* unitdef, int team) const;
Expand Down Expand Up @@ -115,6 +117,10 @@ class CUnitHandler
///< spatial query filters in GameHelper use this)
float maxUnitRadius = 0.0f;

///< highest altitude of any unit added so far
///< (ray tracing uses this in some cases)
float maxUnitAltitude = 0.0f;

bool inUpdateCall = false;
};

Expand Down