Pick objects by cursor (#1296)

* Initial Commit
* Move GetRayFrom2DPosition to los.cpp
* Quick formatting
* Reogranize conversions a bit
* Update ViewHandler.cpp
* Remove unued temp variables
* Update Changes.txt

---------

Co-authored-by: Sezz <sezzary@outlook.com>
This commit is contained in:
Lwmte 2023-12-25 10:15:57 +02:00 committed by GitHub
parent dacc2c8f6a
commit 14fa1d39aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 96 additions and 32 deletions

View file

@ -32,8 +32,9 @@ Version 1.3
Lua API changes:
* Add Lara:GetInteractedMoveable() which returns currently interacted moveable by Lara.
* Add Moveable:SetStatus() to set the current status of the moveable.
* Add View:GetCameraPosition(), View:GetCameraTarget() and View:GetCameraRoom() functions.
* Add Room:GetColor() to get room's ambient light color.
* Add Util.PickMoveableByDisplayPosition() and Util.PickStaticByDisplayPosition() functions.
* Add View.GetCameraPosition(), View.GetCameraTarget() and View:GetCameraRoom() functions.
Version 1.2
===========

View file

@ -633,52 +633,55 @@ static bool DoRayBox(const GameVector& origin, const GameVector& target, const G
return true;
}
int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INFO** mesh, GAME_OBJECT_ID priorityObject)
int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INFO** mesh, GAME_OBJECT_ID priorityObjectID)
{
ClosestItem = NO_LOS_ITEM;
ClosestDist = SQUARE(target->x - origin->x) + SQUARE(target->y - origin->y) + SQUARE(target->z - origin->z);
for (int r = 0; r < NumberLosRooms; ++r)
{
auto* room = &g_Level.Rooms[LosRooms[r]];
auto& room = g_Level.Rooms[LosRooms[r]];
auto pose = Pose::Zero;
for (int m = 0; m < room->mesh.size(); m++)
if (mesh)
{
auto* meshp = &room->mesh[m];
if (meshp->flags & StaticMeshFlags::SM_VISIBLE)
for (int m = 0; m < room.mesh.size(); m++)
{
auto bounds = GetBoundsAccurate(*meshp, false);
pose = Pose(meshp->pos.Position, EulerAngles(0, meshp->pos.Orientation.y, 0));
auto& meshp = room.mesh[m];
if (DoRayBox(*origin, *target, bounds, pose, *vec, -1 - meshp->staticNumber))
if (meshp.flags & StaticMeshFlags::SM_VISIBLE)
{
*mesh = meshp;
target->RoomNumber = LosRooms[r];
auto bounds = GetBoundsAccurate(meshp, false);
pose = Pose(meshp.pos.Position, EulerAngles(0, meshp.pos.Orientation.y, 0));
if (DoRayBox(*origin, *target, bounds, pose, *vec, -1 - meshp.staticNumber))
{
*mesh = &meshp;
target->RoomNumber = LosRooms[r];
}
}
}
}
for (short linkNumber = room->itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem)
for (short linkNumber = room.itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem)
{
auto* item = &g_Level.Items[linkNumber];
const auto& item = g_Level.Items[linkNumber];
if ((item->Status == ITEM_DEACTIVATED) || (item->Status == ITEM_INVISIBLE))
if (item.Status == ITEM_DEACTIVATED || item.Status == ITEM_INVISIBLE)
continue;
if ((priorityObject != GAME_OBJECT_ID::ID_NO_OBJECT) && (item->ObjectNumber != priorityObject))
if (priorityObjectID != GAME_OBJECT_ID::ID_NO_OBJECT && item.ObjectNumber != priorityObjectID)
continue;
if ((item->ObjectNumber != ID_LARA) && (Objects[item->ObjectNumber].collision == nullptr))
if (item.ObjectNumber != ID_LARA && Objects[item.ObjectNumber].collision == nullptr)
continue;
if ((item->ObjectNumber == ID_LARA) && (priorityObject != ID_LARA))
if (item.ObjectNumber == ID_LARA && priorityObjectID != ID_LARA)
continue;
auto bounds = GameBoundingBox(item);
pose = Pose(item->Pose.Position, EulerAngles(0, item->Pose.Orientation.y, 0));
auto bounds = GameBoundingBox(&item);
pose = Pose(item.Pose.Position, EulerAngles(0, item.Pose.Orientation.y, 0));
if (DoRayBox(*origin, *target, bounds, pose, *vec, linkNumber))
target->RoomNumber = LosRooms[r];
@ -808,3 +811,14 @@ std::optional<Vector3> GetStaticObjectLos(const Vector3& origin, int roomNumber,
return std::nullopt;
}
std::pair<GameVector, GameVector> GetRayFrom2DPosition(Vector2 screenPos)
{
auto pos = g_Renderer.GetRay(screenPos);
auto origin = GameVector(pos.first, Camera.pos.RoomNumber);
auto target = GameVector(pos.second, Camera.pos.RoomNumber);
LOS(&origin, &target);
return std::pair<GameVector, GameVector>(origin, target);
}

View file

@ -7,7 +7,8 @@ constexpr auto NO_LOS_ITEM = INT_MAX;
bool LOS(const GameVector* origin, GameVector* target);
bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, bool isFiring);
int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INFO** mesh, GAME_OBJECT_ID priorityObject = GAME_OBJECT_ID::ID_NO_OBJECT);
int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INFO** mesh, GAME_OBJECT_ID priorityObjectID = GAME_OBJECT_ID::ID_NO_OBJECT);
bool LOSAndReturnTarget(GameVector* origin, GameVector* target, int push);
std::optional<Vector3> GetStaticObjectLos(const Vector3& origin, int roomNumber, const Vector3& dir, float dist, bool onlySolid);
std::pair<GameVector, GameVector> GetRayFrom2DPosition(Vector2 screenPos);

View file

@ -259,8 +259,7 @@ namespace TEN::Entities::Creatures::TR3
TriggerDynamicLight(origin.x, origin.y, origin.z, 20, 0, 255, 255);
auto hitPos = Vector3i::Zero;
MESH_INFO* mesh = nullptr;
if (ObjectOnLOS2(&origin, &target, &hitPos, &mesh, ID_LARA) == creature.Enemy->Index)
if (ObjectOnLOS2(&origin, &target, &hitPos, nullptr, ID_LARA) == creature.Enemy->Index)
{
if (creature.Enemy->HitPoints <= PUNA_LIGHTNING_DAMAGE)
{

View file

@ -169,9 +169,8 @@ namespace TEN::Entities::Creatures::TR5
auto origin2 = GameVector(origin, item.RoomNumber);
auto target2 = GameVector(target);
auto hitPos = Vector3i::Zero;
MESH_INFO* hitJoint = nullptr;
if (ObjectOnLOS2(&origin2, &target2, &hitPos, &hitJoint, ID_LARA) == creature.Enemy->Index)
if (ObjectOnLOS2(&origin2, &target2, &hitPos, nullptr, ID_LARA) == creature.Enemy->Index)
{
if (LaraItem->HitPoints <= HEAVY_GUARD_RAYGUN_PLAYER_BURN_HEALTH)
{

View file

@ -400,13 +400,12 @@ namespace TEN::Entities::Creatures::TR5
farAway = 2;
auto hitPos = Vector3i::Zero;
MESH_INFO* hitMesh = nullptr;
auto start = GameVector(guardian->fireArcs[i]->pos1.x, guardian->fireArcs[i]->pos1.y, guardian->fireArcs[i]->pos1.z);
start.RoomNumber = item->RoomNumber;
auto end = GameVector(guardian->fireArcs[i]->pos4.x, guardian->fireArcs[i]->pos4.y, guardian->fireArcs[i]->pos4.z, 0);
if (ObjectOnLOS2(&start, &end, &hitPos, &hitMesh, ID_LARA) == LaraItem->Index)
if (ObjectOnLOS2(&start, &end, &hitPos, nullptr, ID_LARA) == LaraItem->Index)
{
if (LaraItem->Effect.Type != EffectType::Smoke)
{

View file

@ -759,9 +759,10 @@ namespace TEN::Renderer
void SetTextureOrDefault(Texture2D& texture, std::wstring path);
std::string GetDefaultAdapterName();
Vector2i GetScreenResolution() const;
Vector2i GetScreenResolution() const;
std::optional<Vector2> Get2DPosition(const Vector3& pos) const;
Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero);
std::pair<Vector3, Vector3> GetRay(const Vector2& pos) const;
Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero);
void AddDisplaySprite(const RendererSprite& sprite, const Vector2& pos2D, short orient, const Vector2& size, const Vector4& color,
int priority, BLEND_MODES blendMode, const Vector2& aspectCorrection, RenderView& renderView);

View file

@ -553,6 +553,14 @@ namespace TEN::Renderer
return TEN::Utils::ConvertNDCTo2DPosition(Vector2(point));
}
std::pair<Vector3, Vector3> Renderer11::GetRay(const Vector2& pos) const
{
auto nearPoint = m_viewportToolkit.Unproject(Vector3(pos.x, pos.y, 0.0f), gameCamera.Camera.Projection, gameCamera.Camera.View, Matrix::Identity);
auto farPoint = m_viewportToolkit.Unproject(Vector3(pos.x, pos.y, 1.0f), gameCamera.Camera.Projection, gameCamera.Camera.View, Matrix::Identity);
return std::pair<Vector3, Vector3>(nearPoint, farPoint);
}
Vector3 Renderer11::GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset)
{
auto* rendererItem = &m_items[itemNumber];

View file

@ -320,6 +320,8 @@ static constexpr char ScriptReserved_ThrowAwayTorch[] = "ThrowAwayTorch";
static constexpr char ScriptReserved_SetWeaponType[] = "SetWeaponType";
static constexpr char ScriptReserved_TorchIsLit[] = "TorchIsLit";
static constexpr char ScriptReserved_PrintLog[] = "PrintLog";
static constexpr char ScriptReserved_PickMoveable[] = "PickMoveableByDisplayPosition";
static constexpr char ScriptReserved_PickStatic[] = "PickStaticByDisplayPosition";
static constexpr char ScriptReserved_GetDisplayPosition[] = "GetDisplayPosition";
static constexpr char ScriptReserved_GetCursorDisplayPosition[] = "GetCursorDisplayPosition"; // Deprecated
static constexpr char ScriptReserved_GetMouseDisplayPosition[] = "GetMouseDisplayPosition";

View file

@ -10,6 +10,8 @@
#include "Scripting/Internal/ReservedScriptNames.h"
#include "Scripting/Internal/ScriptAssert.h"
#include "Scripting/Internal/ScriptUtil.h"
#include "Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h"
#include "Scripting/Internal/TEN/Objects/Static/StaticObject.h"
#include "Scripting/Internal/TEN/Util/LevelLog.h"
#include "Scripting/Internal/TEN/Vec2/Vec2.h"
#include "Scripting/Internal/TEN/Vec3/Vec3.h"
@ -39,10 +41,9 @@ namespace TEN::Scripting::Util
auto vector0 = posA.ToGameVector();
auto vector1 = posB.ToGameVector();
MESH_INFO* meshPtr = nullptr;
auto vector = Vector3i::Zero;
return (LOS(&vector0, &vector1) &&
ObjectOnLOS2(&vector0, &vector1, &vector, &meshPtr) == NO_LOS_ITEM);
ObjectOnLOS2(&vector0, &vector1, &vector, nullptr) == NO_LOS_ITEM);
}
///Calculate the distance between two positions.
@ -129,6 +130,43 @@ namespace TEN::Scripting::Util
return std::make_tuple(resX, resY);
}
/// Pick a moveable by the given display position.
// @function PickMoveableByDisplayPosition
// @tparam Vec2 Display space position in percent.
// @treturn Objects.Moveable Picked moveable (nil if no moveable was found under the cursor).
static sol::optional <std::unique_ptr<Moveable>> PickMoveable(const Vec2& screenPos)
{
auto realScreenPos = PercentToScreen(screenPos.x, screenPos.y);
auto ray = GetRayFrom2DPosition(Vector2(int(std::get<0>(realScreenPos)), int(std::get<1>(realScreenPos))));
auto vector = Vector3i::Zero;
int itemNumber = ObjectOnLOS2(&ray.first, &ray.second, &vector, nullptr, GAME_OBJECT_ID::ID_LARA);
if (itemNumber == NO_LOS_ITEM || itemNumber < 0)
return sol::nullopt;
return std::make_unique<Moveable>(itemNumber);
}
/// Pick a static mesh by the given display position.
// @function PickStaticByDisplayPosition
// @tparam Vec2 Display space position in percent.
// @treturn Objects.Static Picked static mesh (nil if no static mesh was found under the cursor).
static sol::optional <std::unique_ptr<Static>> PickStatic(const Vec2& screenPos)
{
auto realScreenPos = PercentToScreen(screenPos.x, screenPos.y);
auto ray = GetRayFrom2DPosition(Vector2(int(std::get<0>(realScreenPos)), int(std::get<1>(realScreenPos))));
MESH_INFO* mesh = nullptr;
auto vector = Vector3i::Zero;
int itemNumber = ObjectOnLOS2(&ray.first, &ray.second, &vector, &mesh, GAME_OBJECT_ID::ID_LARA);
if (itemNumber == NO_LOS_ITEM || itemNumber >= 0)
return sol::nullopt;
return std::make_unique<Static>(*mesh);
}
/// Write messages within the Log file
//@advancedDesc
//For native Lua handling of errors, see the official Lua website:
@ -162,6 +200,8 @@ namespace TEN::Scripting::Util
tableUtil.set_function(ScriptReserved_CalculateDistance, &CalculateDistance);
tableUtil.set_function(ScriptReserved_CalculateHorizontalDistance, &CalculateHorizontalDistance);
tableUtil.set_function(ScriptReserved_GetDisplayPosition, &GetDisplayPosition);
tableUtil.set_function(ScriptReserved_PickMoveable, &PickMoveable);
tableUtil.set_function(ScriptReserved_PickStatic, &PickStatic);
tableUtil.set_function(ScriptReserved_PercentToScreen, &PercentToScreen);
tableUtil.set_function(ScriptReserved_ScreenToPercent, &ScreenToPercent);
tableUtil.set_function(ScriptReserved_PrintLog, &PrintLog);

View file

@ -141,7 +141,7 @@ namespace TEN::Scripting::View
//@tparam float angle in degrees (clamped to [10, 170])
tableView.set_function(ScriptReserved_SetFOV, &SetFOV);
//Get field of view.
///Get field of view.
//@function GetFOV
//@treturn float current FOV angle in degrees
tableView.set_function(ScriptReserved_GetFOV, &GetFOV);