summaryrefslogtreecommitdiff
path: root/src/common/Collision/Models
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/Collision/Models')
-rw-r--r--src/common/Collision/Models/GameObjectModel.cpp35
-rw-r--r--src/common/Collision/Models/GameObjectModel.h11
-rw-r--r--src/common/Collision/Models/ModelIgnoreFlags.h10
-rw-r--r--src/common/Collision/Models/ModelInstance.cpp54
-rw-r--r--src/common/Collision/Models/ModelInstance.h11
-rw-r--r--src/common/Collision/Models/WorldModel.cpp135
-rw-r--r--src/common/Collision/Models/WorldModel.h20
7 files changed, 115 insertions, 161 deletions
diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp
index 683dd0c1a9..eebc7e62d2 100644
--- a/src/common/Collision/Models/GameObjectModel.cpp
+++ b/src/common/Collision/Models/GameObjectModel.cpp
@@ -1,14 +1,14 @@
/*
* 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
@@ -203,27 +203,6 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
return hit;
}
-void GameObjectModel::IntersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const
-{
- if (!(phasemask & ph_mask) || !owner->IsSpawned() || !IsMapObject())
- return;
-
- if (!iBound.contains(point))
- return;
-
- // child bounds are defined in object space:
- Vector3 pModel = iInvRot * (point - iPos) * iInvScale;
- Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
- float zDist;
- if (iModel->IntersectPoint(pModel, zDirModel, zDist, info))
- {
- Vector3 modelGround = pModel + zDist * zDirModel;
- float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
- if (info.ground_Z < world_Z)
- info.ground_Z = world_Z;
- }
-}
-
bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const
{
if (!(phasemask & ph_mask) || !owner->IsSpawned() || !IsMapObject())
@@ -236,7 +215,9 @@ bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationI
Vector3 pModel = iInvRot * (point - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist;
- if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info))
+
+ VMAP::GroupLocationInfo groupInfo;
+ if (iModel->GetLocationInfo(pModel, zDirModel, zDist, groupInfo))
{
Vector3 modelGround = pModel + zDist * zDirModel;
float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h
index d0f8e35f4a..5938a5c1d0 100644
--- a/src/common/Collision/Models/GameObjectModel.h
+++ b/src/common/Collision/Models/GameObjectModel.h
@@ -1,14 +1,14 @@
/*
* 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
@@ -70,7 +70,6 @@ public:
[[nodiscard]] bool IsMapObject() const { return isWmo; }
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;
diff --git a/src/common/Collision/Models/ModelIgnoreFlags.h b/src/common/Collision/Models/ModelIgnoreFlags.h
index f54da68ef5..2a7ccfe737 100644
--- a/src/common/Collision/Models/ModelIgnoreFlags.h
+++ b/src/common/Collision/Models/ModelIgnoreFlags.h
@@ -1,14 +1,14 @@
/*
* 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
diff --git a/src/common/Collision/Models/ModelInstance.cpp b/src/common/Collision/Models/ModelInstance.cpp
index a18d5d4f9f..c5b6fbfdb0 100644
--- a/src/common/Collision/Models/ModelInstance.cpp
+++ b/src/common/Collision/Models/ModelInstance.cpp
@@ -1,14 +1,14 @@
/*
* 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
@@ -63,44 +63,6 @@ namespace VMAP
return hit;
}
- void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo& info) const
- {
- if (!iModel)
- {
-#ifdef VMAP_DEBUG
- std::cout << "<object not loaded>\n";
-#endif
- return;
- }
-
- // M2 files don't contain area info, only WMO files
- if (flags & MOD_M2)
- {
- return;
- }
- if (!iBound.contains(p))
- {
- return;
- }
- // child bounds are defined in object space:
- Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
- Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
- float zDist;
- if (iModel->IntersectPoint(pModel, zDirModel, zDist, info))
- {
- Vector3 modelGround = pModel + zDist * zDirModel;
- // Transform back to world space. Note that:
- // Mat * vec == vec * Mat.transpose()
- // and for rotation matrices: Mat.inverse() == Mat.transpose()
- float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
- if (info.ground_Z < world_Z)
- {
- info.ground_Z = world_Z;
- info.adtId = adtId;
- }
- }
- }
-
bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const
{
if (!iModel)
@@ -124,7 +86,9 @@ namespace VMAP
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist;
- if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info))
+
+ GroupLocationInfo groupInfo;
+ if (iModel->GetLocationInfo(pModel, zDirModel, zDist, groupInfo))
{
Vector3 modelGround = pModel + zDist * zDirModel;
// Transform back to world space. Note that:
@@ -133,6 +97,8 @@ namespace VMAP
float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection?
{
+ info.rootId = groupInfo.rootId;
+ info.hitModel = groupInfo.hitModel;
info.ground_Z = world_Z;
info.hitInstance = this;
return true;
diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h
index 25987f3fd6..3476a514d5 100644
--- a/src/common/Collision/Models/ModelInstance.h
+++ b/src/common/Collision/Models/ModelInstance.h
@@ -1,14 +1,14 @@
/*
* 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
@@ -66,7 +66,6 @@ namespace VMAP
ModelInstance(const ModelSpawn& spawn, WorldModel* model);
void setUnloaded() { iModel = nullptr; }
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;
WorldModel* getWorldModel() { return iModel; }
diff --git a/src/common/Collision/Models/WorldModel.cpp b/src/common/Collision/Models/WorldModel.cpp
index 99375e294a..53bd55a2d2 100644
--- a/src/common/Collision/Models/WorldModel.cpp
+++ b/src/common/Collision/Models/WorldModel.cpp
@@ -1,14 +1,14 @@
/*
* 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
@@ -20,9 +20,9 @@
#include "ModelIgnoreFlags.h"
#include "ModelInstance.h"
#include "VMapDefinitions.h"
+#include <array>
using G3D::Vector3;
-using G3D::Ray;
template<> struct BoundsTrait<VMAP::GroupModel>
{
@@ -451,21 +451,46 @@ namespace VMAP
return callback.hit;
}
- bool GroupModel::IsInsideObject(const Vector3& pos, const Vector3& down, float& z_dist) const
+ inline bool IsInsideOrAboveBound(G3D::AABox const& bounds, const G3D::Point3& point)
{
- if (triangles.empty() || !iBound.contains(pos))
+ return point.x >= bounds.low().x
+ && point.y >= bounds.low().y
+ && point.z >= bounds.low().z
+ && point.x <= bounds.high().x
+ && point.y <= bounds.high().y;
+ }
+
+ GroupModel::InsideResult GroupModel::IsInsideObject(G3D::Ray const& ray, float& z_dist) const
+ {
+ if (triangles.empty() || !IsInsideOrAboveBound(iBound, ray.origin()))
+ return OUT_OF_BOUNDS;
+
+ if (meshTree.bound().high().z >= ray.origin().z)
{
- return false;
+ float dist = G3D::finf();
+ if (IntersectRay(ray, dist, false))
+ {
+ z_dist = dist - 0.1f;
+ return INSIDE;
+ }
+ if (meshTree.bound().contains(ray.origin()))
+ return MAYBE_INSIDE;
}
- Vector3 rPos = pos - 0.1f * down;
- float dist = G3D::inf();
- G3D::Ray ray(rPos, down);
- bool hit = IntersectRay(ray, dist, false);
- if (hit)
+ else
{
- z_dist = dist - 0.1f;
+ // some group models don't have any floor to intersect with
+ // so we should attempt to intersect with a model part below this group
+ // then find back where we originated from (in WorldModel::GetLocationInfo)
+ float dist = G3D::finf();
+ float delta = ray.origin().z - meshTree.bound().high().z;
+ if (IntersectRay(ray.bumpedRay(delta), dist, false))
+ {
+ z_dist = dist - 0.1f + delta;
+ return ABOVE;
+ }
}
- return hit;
+
+ return OUT_OF_BOUNDS;
}
bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const
@@ -541,76 +566,58 @@ namespace VMAP
class WModelAreaCallback
{
public:
- WModelAreaCallback(const std::vector<GroupModel>& vals, const Vector3& down):
- prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) { }
- std::vector<GroupModel>::const_iterator prims;
- std::vector<GroupModel>::const_iterator hit;
- float minVol;
- float zDist;
- Vector3 zVec;
- void operator()(const Vector3& point, uint32 entry)
+ WModelAreaCallback(std::vector<GroupModel> const& vals) :
+ prims(vals), hit() { }
+ std::vector<GroupModel> const& prims;
+ std::array<GroupModel const*, 3> hit;
+ bool operator()(G3D::Ray const& ray, uint32 entry, float& distance, bool /*stopAtFirstHit*/)
{
float group_Z;
- //float pVol = prims[entry].GetBound().volume();
- //if (pVol < minVol)
- //{
- /* if (prims[entry].iBound.contains(point)) */
- if (prims[entry].IsInsideObject(point, zVec, group_Z))
+ if (GroupModel::InsideResult result = prims[entry].IsInsideObject(ray, group_Z); result != GroupModel::OUT_OF_BOUNDS)
{
- //minVol = pVol;
- //hit = prims + entry;
- if (group_Z < zDist)
+ if (result != GroupModel::MAYBE_INSIDE)
{
- zDist = group_Z;
- hit = prims + entry;
+ if (group_Z < distance)
+ {
+ distance = group_Z;
+ hit[result] = &prims[entry];
+ return true;
+ }
}
-#ifdef VMAP_DEBUG
- const GroupModel& gm = prims[entry];
- printf("%10u %8X %7.3f, %7.3f, %7.3f | %7.3f, %7.3f, %7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(),
- gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z,
- gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z);
-#endif
+ else
+ hit[result] = &prims[entry];
}
- //}
- //std::cout << "trying to intersect '" << prims[entry].name << "'\n";
+ return false;
}
};
- bool WorldModel::IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const
+ bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, GroupLocationInfo& info) const
{
if (groupModels.empty())
{
return false;
}
- WModelAreaCallback callback(groupModels, down);
- groupTree.intersectPoint(p, callback);
- if (callback.hit != groupModels.end())
+ WModelAreaCallback callback(groupModels);
+ G3D::Ray r(p - down * 0.1f, down);
+ float zDist = groupTree.bound().extent().length();
+ groupTree.intersectRay(r, callback, zDist, false);
+ if (callback.hit[GroupModel::INSIDE])
{
info.rootId = RootWMOID;
- info.groupId = callback.hit->GetWmoID();
- info.flags = callback.hit->GetMogpFlags();
- info.result = true;
- dist = callback.zDist;
+ info.hitModel = callback.hit[GroupModel::INSIDE];
+ dist = zDist;
return true;
}
- return false;
- }
-
- bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const
- {
- if (groupModels.empty())
- {
- return false;
- }
- WModelAreaCallback callback(groupModels, down);
- groupTree.intersectPoint(p, callback);
- if (callback.hit != groupModels.end())
+ // some group models don't have any floor to intersect with
+ // so we should attempt to intersect with a model part below the group `p` is in (stored in GroupModel::ABOVE)
+ // then find back where we originated from (GroupModel::MAYBE_INSIDE)
+ if (callback.hit[GroupModel::MAYBE_INSIDE] && callback.hit[GroupModel::ABOVE])
{
info.rootId = RootWMOID;
- info.hitModel = &(*callback.hit);
- dist = callback.zDist;
+ info.hitModel = callback.hit[GroupModel::MAYBE_INSIDE];
+ dist = zDist;
return true;
}
return false;
diff --git a/src/common/Collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h
index df1bd47512..2d5d8126b1 100644
--- a/src/common/Collision/Models/WorldModel.h
+++ b/src/common/Collision/Models/WorldModel.h
@@ -1,14 +1,14 @@
/*
* 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
@@ -29,6 +29,7 @@ namespace VMAP
class TreeNode;
struct AreaInfo;
struct LocationInfo;
+ struct GroupLocationInfo;
enum class ModelIgnoreFlags : uint32;
class MeshTriangle
@@ -81,12 +82,14 @@ namespace VMAP
void setMeshData(std::vector<G3D::Vector3>& vert, std::vector<MeshTriangle>& tri);
void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = nullptr; }
bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const;
- bool IsInsideObject(const G3D::Vector3& pos, const G3D::Vector3& down, float& z_dist) const;
+ enum InsideResult { INSIDE = 0, MAYBE_INSIDE = 1, ABOVE = 2, OUT_OF_BOUNDS = -1 };
+ InsideResult IsInsideObject(G3D::Ray const& ray, float& z_dist) const;
bool GetLiquidLevel(const G3D::Vector3& pos, float& liqHeight) const;
[[nodiscard]] uint32 GetLiquidType() const;
bool writeToFile(FILE* wf);
bool readFromFile(FILE* rf);
- [[nodiscard]] const G3D::AABox& GetBound() const { return iBound; }
+ [[nodiscard]] G3D::AABox const& GetBound() const { return iBound; }
+ [[nodiscard]] G3D::AABox const& GetMeshTreeBound() const { return meshTree.bound(); }
[[nodiscard]] uint32 GetMogpFlags() const { return iMogpFlags; }
[[nodiscard]] uint32 GetWmoID() const { return iGroupWMOID; }
void GetMeshData(std::vector<G3D::Vector3>& outVertices, std::vector<MeshTriangle>& outTriangles, WmoLiquid*& liquid);
@@ -109,8 +112,7 @@ namespace VMAP
void setGroupModels(std::vector<GroupModel>& models);
void setRootWmoID(uint32 id) { RootWMOID = id; }
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 GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, GroupLocationInfo& info) const;
bool writeFile(const std::string& filename);
bool readFile(const std::string& filename);
void GetGroupModels(std::vector<GroupModel>& outGroupModels);