fix(Core/Vmaps): Stop M2s from occluding for spellcast LoS. Original autho… (#11341)

* Core/Vmaps: Stop M2s from occluding for spellcast LoS. Original authors: @Shauren & @HelloKitty

Fixes #11293

* buildfix.

Co-Authored-By: HelloKitty <5829095+HelloKitty@users.noreply.github.com>
This commit is contained in:
UltraNix
2022-04-10 14:24:35 +02:00
committed by GitHub
parent 6efc08f42e
commit 47790c9714
27 changed files with 295 additions and 101 deletions

View File

@@ -18,6 +18,7 @@
#include "GameObjectModel.h"
#include "Log.h"
#include "MapTree.h"
#include "ModelInstance.h"
#include "Timer.h"
#include "VMapDefinitions.h"
#include "VMapFactory.h"
@@ -123,7 +124,8 @@ bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> model
return false;
}
iModel = VMAP::VMapFactory::createOrGetVMapMgr()->acquireModelInstance(dataPath + "vmaps/", it->second.name);
iModel = VMAP::VMapFactory::createOrGetVMapMgr()->acquireModelInstance(dataPath + "vmaps/", it->second.name,
it->second.isWmo ? VMAP::ModelFlags::MOD_WORLDSPAWN : VMAP::ModelFlags::MOD_M2);
if (!iModel)
{
@@ -174,7 +176,7 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas
return mdl;
}
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const
{
if (!(phasemask & ph_mask) || !owner->IsSpawned())
{
@@ -191,7 +193,7 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale;
Ray modRay(p, iInvRot * ray.direction());
float distance = MaxDist * iInvScale;
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit);
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit, ignoreFlags);
if (hit)
{
distance *= iScale;

View File

@@ -29,6 +29,7 @@ namespace VMAP
class WorldModel;
struct AreaInfo;
struct LocationInfo;
enum class ModelIgnoreFlags : uint32;
}
class GameObject;
@@ -68,7 +69,7 @@ public:
[[nodiscard]] bool isEnabled() const { return phasemask != 0; }
[[nodiscard]] bool IsMapObject() const { return isWmo; }
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const;
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const;
void IntersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const;
bool GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const;
bool GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const;

View File

@@ -0,0 +1,37 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ModelIgnoreFlags_h__
#define ModelIgnoreFlags_h__
#include "Define.h"
namespace VMAP
{
enum class ModelIgnoreFlags : uint32
{
Nothing = 0x00,
M2 = 0x01
};
inline ModelIgnoreFlags operator&(ModelIgnoreFlags left, ModelIgnoreFlags right)
{
return ModelIgnoreFlags(uint32(left) & uint32(right));
}
}
#endif // ModelIgnoreFlags_h__

View File

@@ -30,7 +30,7 @@ namespace VMAP
iInvScale = 1.f / iScale;
}
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
if (!iModel)
{
@@ -54,7 +54,7 @@ namespace VMAP
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
Ray modRay(p, iInvRot * pRay.direction());
float distance = pMaxDist * iInvScale;
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit);
bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit, ignoreFlags);
if (hit)
{
distance *= iScale;

View File

@@ -29,6 +29,7 @@ namespace VMAP
class WorldModel;
struct AreaInfo;
struct LocationInfo;
enum class ModelIgnoreFlags : uint32;
enum ModelFlags
{
@@ -64,7 +65,7 @@ namespace VMAP
ModelInstance() { }
ModelInstance(const ModelSpawn& spawn, WorldModel* model);
void setUnloaded() { iModel = nullptr; }
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const;
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
void intersectPoint(const G3D::Vector3& p, AreaInfo& info) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;

View File

@@ -17,6 +17,7 @@
#include "WorldModel.h"
#include "MapTree.h"
#include "ModelIgnoreFlags.h"
#include "ModelInstance.h"
#include "VMapDefinitions.h"
@@ -485,8 +486,18 @@ namespace VMAP
bool hit;
};
bool WorldModel::IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const
bool WorldModel::IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const
{
// If the caller asked us to ignore certain objects we should check flags
if ((ignoreFlags & ModelIgnoreFlags::M2) != ModelIgnoreFlags::Nothing)
{
// M2 models are not taken into account for LoS calculation if caller requested their ignoring.
if (Flags & MOD_M2)
{
return false;
}
}
// small M2 workaround, maybe better make separate class with virtual intersection funcs
// in any case, there's no need to use a bound tree if we only have one submodel
if (groupModels.size() == 1)

View File

@@ -30,6 +30,7 @@ namespace VMAP
class TreeNode;
struct AreaInfo;
struct LocationInfo;
enum class ModelIgnoreFlags : uint32;
class MeshTriangle
{
@@ -108,12 +109,13 @@ namespace VMAP
//! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
void setGroupModels(std::vector<GroupModel>& models);
void setRootWmoID(uint32 id) { RootWMOID = id; }
bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const;
bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
bool IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const;
bool GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const;
bool writeFile(const std::string& filename);
bool readFile(const std::string& filename);
void GetGroupModels(std::vector<GroupModel>& outGroupModels);
uint32 Flags;
protected:
uint32 RootWMOID{0};
std::vector<GroupModel> groupModels;