Files
Viano-Core/src/server/game/Entities/Object/Position.cpp
T

225 lines
6.9 KiB
C++

/*
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
*
* 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 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/>.
*/
#include "Position.h"
#include "ByteBuffer.h"
#include "GridDefines.h"
#include <G3D/g3dmath.h>
#include <G3D/Vector3.h>
Position::Position(G3D::Vector3 const& vect)
{
Relocate(vect.x, vect.y, vect.z, 0.f);
}
Position::operator G3D::Vector3() const
{
return { m_positionX, m_positionY, m_positionZ };
}
bool Position::operator==(Position const &a)
{
return (G3D::fuzzyEq(a.m_positionX, m_positionX) &&
G3D::fuzzyEq(a.m_positionY, m_positionY) &&
G3D::fuzzyEq(a.m_positionZ, m_positionZ) &&
G3D::fuzzyEq(a.m_orientation, m_orientation));
}
void Position::RelocateOffset(const Position & offset)
{
m_positionX = GetPositionX() + (offset.GetPositionX() * std::cos(GetOrientation()) + offset.GetPositionY() * std::sin(GetOrientation() + float(M_PI)));
m_positionY = GetPositionY() + (offset.GetPositionY() * std::cos(GetOrientation()) + offset.GetPositionX() * std::sin(GetOrientation()));
m_positionZ = GetPositionZ() + offset.GetPositionZ();
SetOrientation(GetOrientation() + offset.GetOrientation());
}
bool Position::IsPositionValid() const
{
return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation);
}
void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const
{
float dx = endPos.GetPositionX() - GetPositionX();
float dy = endPos.GetPositionY() - GetPositionY();
retOffset.m_positionX = dx * std::cos(GetOrientation()) + dy * std::sin(GetOrientation());
retOffset.m_positionY = dy * std::cos(GetOrientation()) - dx * std::sin(GetOrientation());
retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ();
retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation());
}
Position Position::GetPositionWithOffset(Position const& offset) const
{
Position ret(*this);
ret.RelocateOffset(offset);
return ret;
}
float Position::GetAngle(Position const* pos) const
{
if (!pos)
return 0;
return GetAngle(pos->GetPositionX(), pos->GetPositionY());
}
// Return angle in range 0..2*pi
float Position::GetAngle(float x, float y) const
{
float dx = x - GetPositionX();
float dy = y - GetPositionY();
float ang = std::atan2(dy, dx);
ang = (ang >= 0) ? ang : 2 * float(M_PI) + ang;
return ang;
}
void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) const
{
float dx = GetPositionX() - x;
float dy = GetPositionY() - y;
if (std::fabs(dx) < 0.001f && std::fabs(dy) < 0.001f)
{
float angle = (float)rand_norm()*static_cast<float>(2 * M_PI);
vcos = std::cos(angle);
vsin = std::sin(angle);
}
else
{
float dist = std::sqrt((dx*dx) + (dy*dy));
vcos = dx / dist;
vsin = dy / dist;
}
}
bool Position::IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const
{
// rotate the WorldObject position instead of rotating the whole cube, that way we can make a simplified
// is-in-cube check and we have to calculate only one point instead of 4
// 2PI = 360*, keep in mind that ingame orientation is counter-clockwise
double rotation = 2 * M_PI - center.GetOrientation();
double sinVal = std::sin(rotation);
double cosVal = std::cos(rotation);
float BoxDistX = GetPositionX() - center.GetPositionX();
float BoxDistY = GetPositionY() - center.GetPositionY();
float rotX = float(center.GetPositionX() + BoxDistX * cosVal - BoxDistY*sinVal);
float rotY = float(center.GetPositionY() + BoxDistY * cosVal + BoxDistX*sinVal);
// box edges are parallel to coordiante axis, so we can treat every dimension independently :D
float dz = GetPositionZ() - center.GetPositionZ();
float dx = rotX - center.GetPositionX();
float dy = rotY - center.GetPositionY();
if ((std::fabs(dx) > xradius) ||
(std::fabs(dy) > yradius) ||
(std::fabs(dz) > zradius))
return false;
return true;
}
bool Position::HasInArc(float arc, const Position* obj, float border) const
{
// always have self in arc
if (obj == this)
return true;
// move arc to range 0.. 2*pi
arc = NormalizeOrientation(arc);
float angle = GetAngle(obj);
angle -= m_orientation;
// move angle to range -pi ... +pi
angle = NormalizeOrientation(angle);
if (angle > float(M_PI))
angle -= 2.0f * float(M_PI);
float lborder = -1 * (arc / border); // in range -pi..0
float rborder = (arc / border); // in range 0..pi
return ((angle >= lborder) && (angle <= rborder));
}
bool Position::HasInLine(Position const* pos, float width) const
{
if (!HasInArc(float(M_PI), pos))
return false;
float angle = GetRelativeAngle(pos);
return std::fabs(std::sin(angle)) * GetExactDist2d(pos->GetPositionX(), pos->GetPositionY()) < width;
}
std::string Position::ToString() const
{
std::stringstream sstr;
sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << m_orientation;
return sstr.str();
}
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer)
{
buf << streamer.Pos->GetPositionX();
buf << streamer.Pos->GetPositionY();
return buf;
}
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer)
{
float x, y;
buf >> x >> y;
streamer.Pos->Relocate(x, y);
return buf;
}
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
{
buf << streamer.Pos->GetPositionX();
buf << streamer.Pos->GetPositionY();
buf << streamer.Pos->GetPositionZ();
return buf;
}
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
{
float x, y, z;
buf >> x >> y >> z;
streamer.Pos->Relocate(x, y, z);
return buf;
}
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
{
buf << streamer.Pos->GetPositionX();
buf << streamer.Pos->GetPositionY();
buf << streamer.Pos->GetPositionZ();
buf << streamer.Pos->GetOrientation();
return buf;
}
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
{
float x, y, z, o;
buf >> x >> y >> z >> o;
streamer.Pos->Relocate(x, y, z, o);
return buf;
}