Upgrade checkline by using two triangles testing
This commit is contained in:
parent
49910c4cea
commit
05f029abc0
@ -29,6 +29,8 @@
|
|||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
#include "network/network_string.hpp"
|
#include "network/network_string.hpp"
|
||||||
#include "race/race_manager.hpp"
|
#include "race/race_manager.hpp"
|
||||||
|
#include "tracks/graph.hpp"
|
||||||
|
#include "tracks/quad.hpp"
|
||||||
|
|
||||||
#include "irrlicht.h"
|
#include "irrlicht.h"
|
||||||
|
|
||||||
@ -57,23 +59,68 @@ CheckLine::CheckLine(const XMLNode &node, unsigned int index)
|
|||||||
p1_string = "target-p1";
|
p1_string = "target-p1";
|
||||||
p2_string = "target-p2";
|
p2_string = "target-p2";
|
||||||
}
|
}
|
||||||
|
float min_height = 0.0f;
|
||||||
|
Vec3 normal(0, 1, 0);
|
||||||
|
Vec3 center;
|
||||||
core::vector2df p1, p2;
|
core::vector2df p1, p2;
|
||||||
if(node.get(p1_string, &p1) &&
|
if(node.get(p1_string, &p1) &&
|
||||||
node.get(p2_string, &p2) &&
|
node.get(p2_string, &p2) &&
|
||||||
node.get("min-height", &m_min_height))
|
node.get("min-height", &min_height))
|
||||||
{
|
{
|
||||||
m_left_point = Vec3(p1.X, m_min_height, p1.Y);
|
m_left_point = Vec3(p1.X, min_height, p1.Y);
|
||||||
m_right_point = Vec3(p2.X, m_min_height, p2.Y);
|
m_right_point = Vec3(p2.X, min_height, p2.Y);
|
||||||
|
center = (m_left_point + m_right_point) * 0.5f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node.get(p1_string, &m_left_point);
|
node.get(p1_string, &m_left_point);
|
||||||
p1 = core::vector2df(m_left_point.getX(), m_left_point.getZ());
|
|
||||||
node.get(p2_string, &m_right_point);
|
node.get(p2_string, &m_right_point);
|
||||||
p2 = core::vector2df(m_right_point.getX(), m_right_point.getZ());
|
center = (m_left_point + m_right_point) * 0.5f;
|
||||||
m_min_height = std::min(m_left_point.getY(), m_right_point.getY());
|
int sector = -1;
|
||||||
|
if (Graph::get())
|
||||||
|
Graph::get()->findRoadSector(center, §or);
|
||||||
|
if (sector != -1)
|
||||||
|
normal = Graph::get()->getQuad(sector)->getNormal();
|
||||||
}
|
}
|
||||||
m_line.setLine(p1, p2);
|
|
||||||
|
// How much a kart is allowed to be under the minimum height of a
|
||||||
|
// quad and still considered to be able to cross it.
|
||||||
|
float under_min_height = 1.0f;
|
||||||
|
|
||||||
|
// How much a kart is allowed to be over the minimum height of a
|
||||||
|
// quad and still considered to be able to cross it.
|
||||||
|
float over_min_height = 4.0f;
|
||||||
|
|
||||||
|
m_check_plane[0].pointA = Vec3(m_left_point + (normal *
|
||||||
|
under_min_height * -1.0f)).toIrrVector();
|
||||||
|
m_check_plane[0].pointB = Vec3(m_right_point + (normal *
|
||||||
|
under_min_height * -1.0f)).toIrrVector();
|
||||||
|
m_check_plane[0].pointC = Vec3(m_left_point + (normal *
|
||||||
|
over_min_height)).toIrrVector();
|
||||||
|
m_check_plane[1].pointA = Vec3(m_left_point + (normal *
|
||||||
|
over_min_height)).toIrrVector();
|
||||||
|
m_check_plane[1].pointB = Vec3(m_right_point + (normal *
|
||||||
|
under_min_height * -1.0f)).toIrrVector();
|
||||||
|
m_check_plane[1].pointC = Vec3(m_right_point + (normal *
|
||||||
|
over_min_height)).toIrrVector();
|
||||||
|
|
||||||
|
// 2, 3 are scaled for testing ignoring height (used only by basketball atm)
|
||||||
|
// Only scale upwards a little because basket ball cannot be too high
|
||||||
|
// Also to avoid check plane overlapping
|
||||||
|
over_min_height = 10.0f;
|
||||||
|
m_check_plane[2].pointA = Vec3(m_left_point + (normal *
|
||||||
|
under_min_height * -1.0f)).toIrrVector();
|
||||||
|
m_check_plane[2].pointB = Vec3(m_right_point + (normal *
|
||||||
|
under_min_height * -1.0f)).toIrrVector();
|
||||||
|
m_check_plane[2].pointC = Vec3(m_left_point + (normal *
|
||||||
|
over_min_height)).toIrrVector();
|
||||||
|
m_check_plane[3].pointA = Vec3(m_left_point + (normal *
|
||||||
|
over_min_height)).toIrrVector();
|
||||||
|
m_check_plane[3].pointB = Vec3(m_right_point + (normal *
|
||||||
|
under_min_height * -1.0f)).toIrrVector();
|
||||||
|
m_check_plane[3].pointC = Vec3(m_right_point + (normal *
|
||||||
|
over_min_height)).toIrrVector();
|
||||||
|
|
||||||
if(UserConfigParams::m_check_debug && !GUIEngine::isNoGraphics())
|
if(UserConfigParams::m_check_debug && !GUIEngine::isNoGraphics())
|
||||||
{
|
{
|
||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
@ -84,14 +131,10 @@ CheckLine::CheckLine(const XMLNode &node, unsigned int index)
|
|||||||
SP::addDynamicDrawCall(m_debug_dy_dc);
|
SP::addDynamicDrawCall(m_debug_dy_dc);
|
||||||
m_debug_dy_dc->getVerticesVector().resize(4);
|
m_debug_dy_dc->getVerticesVector().resize(4);
|
||||||
auto& vertices = m_debug_dy_dc->getVerticesVector();
|
auto& vertices = m_debug_dy_dc->getVerticesVector();
|
||||||
vertices[0].m_position = core::vector3df(p1.X,
|
vertices[0].m_position = m_check_plane[0].pointA;
|
||||||
m_min_height - m_under_min_height, p1.Y);
|
vertices[1].m_position = m_check_plane[0].pointB;
|
||||||
vertices[1].m_position = core::vector3df(p2.X,
|
vertices[2].m_position = m_check_plane[0].pointC;
|
||||||
m_min_height - m_under_min_height, p2.Y);
|
vertices[3].m_position = m_check_plane[1].pointC;
|
||||||
vertices[2].m_position = core::vector3df(p1.X,
|
|
||||||
m_min_height + m_over_min_height, p1.Y);
|
|
||||||
vertices[3].m_position = core::vector3df(p2.X,
|
|
||||||
m_min_height + m_over_min_height, p2.Y);
|
|
||||||
for(unsigned int i = 0; i < 4; i++)
|
for(unsigned int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
vertices[i].m_color = m_active_at_reset
|
vertices[i].m_color = m_active_at_reset
|
||||||
@ -119,8 +162,9 @@ void CheckLine::reset(const Track &track)
|
|||||||
|
|
||||||
for (unsigned int i = 0; i<m_previous_sign.size(); i++)
|
for (unsigned int i = 0; i<m_previous_sign.size(); i++)
|
||||||
{
|
{
|
||||||
core::vector2df p = m_previous_position[i].toIrrVector2d();
|
m_previous_sign[i] = m_previous_position[i].sideofPlane(
|
||||||
m_previous_sign[i] = m_line.getPointOrientation(p) >= 0;
|
m_check_plane[0].pointA,
|
||||||
|
m_check_plane[0].pointB, m_check_plane[0].pointC) >= 0;
|
||||||
}
|
}
|
||||||
} // reset
|
} // reset
|
||||||
|
|
||||||
@ -158,53 +202,44 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
|||||||
int kart_index)
|
int kart_index)
|
||||||
{
|
{
|
||||||
World* w = World::getWorld();
|
World* w = World::getWorld();
|
||||||
core::vector2df p=new_pos.toIrrVector2d();
|
// Sign here is for old client (<= 1.2) in networking, it's not used
|
||||||
bool sign = m_line.getPointOrientation(p)>=0;
|
// anymore now
|
||||||
bool result;
|
bool sign = new_pos.sideofPlane(m_check_plane[0].pointA,
|
||||||
|
m_check_plane[0].pointB, m_check_plane[0].pointC) >= 0;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
bool previous_sign;
|
bool ignore_height = m_ignore_height;
|
||||||
|
bool check_line_debug = false;
|
||||||
if (kart_index < 0)
|
start:
|
||||||
|
irr::core::triangle3df* check_plane =
|
||||||
|
ignore_height ? &m_check_plane[2] : &m_check_plane[0];
|
||||||
|
core::line3df test(old_pos.toIrrVector(), new_pos.toIrrVector());
|
||||||
|
core::vector3df intersect;
|
||||||
|
if (check_plane[0].getIntersectionWithLimitedLine(test, intersect) ||
|
||||||
|
check_plane[1].getIntersectionWithLimitedLine(test, intersect))
|
||||||
{
|
{
|
||||||
core::vector2df p = old_pos.toIrrVector2d();
|
if (UserConfigParams::m_check_debug && check_line_debug)
|
||||||
previous_sign = (m_line.getPointOrientation(p) >= 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
previous_sign = m_previous_sign[kart_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the sign has changed, i.e. the infinite line was crossed somewhere,
|
|
||||||
// check if the finite line was actually crossed:
|
|
||||||
core::vector2df cross_point;
|
|
||||||
if (sign != previous_sign &&
|
|
||||||
m_line.intersectWith(core::line2df(old_pos.toIrrVector2d(),
|
|
||||||
new_pos.toIrrVector2d()),
|
|
||||||
cross_point) )
|
|
||||||
{
|
|
||||||
// Now check the minimum height: the kart position must be within a
|
|
||||||
// reasonable distance in the Z axis - 'reasonable' for now to be
|
|
||||||
// between -1 and 4 units (negative numbers are unlikely, but help
|
|
||||||
// in case that the kart is 'somewhat' inside of the track, or the
|
|
||||||
// checklines are a bit off in Z direction.
|
|
||||||
result = m_ignore_height ||
|
|
||||||
(new_pos.getY()-m_min_height<m_over_min_height &&
|
|
||||||
new_pos.getY()-m_min_height>-m_under_min_height );
|
|
||||||
if (UserConfigParams::m_check_debug && !result)
|
|
||||||
{
|
{
|
||||||
if (kart_index >= 0)
|
if (kart_index >= 0)
|
||||||
Log::info("CheckLine", "Kart %s crosses line, but wrong height "
|
{
|
||||||
"(%f vs %f).",
|
Log::info("CheckLine", "Kart %s crosses line, but wrong height.",
|
||||||
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
|
World::getWorld()->getKart(kart_index)->getIdent().c_str());
|
||||||
new_pos.getY(), m_min_height);
|
}
|
||||||
else if (!result)
|
else
|
||||||
Log::info("CheckLine", "Object crosses line, but wrong height "
|
{
|
||||||
"(%f vs %f).",
|
Log::info("CheckLine", "Object crosses line, but wrong height.");
|
||||||
new_pos.getY(), m_min_height);
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else if (UserConfigParams::m_check_debug && !ignore_height &&
|
||||||
|
!check_line_debug)
|
||||||
|
{
|
||||||
|
check_line_debug = true;
|
||||||
|
ignore_height = true;
|
||||||
|
goto start;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
result = false;
|
|
||||||
|
|
||||||
if (kart_index >= 0)
|
if (kart_index >= 0)
|
||||||
{
|
{
|
||||||
|
@ -20,9 +20,8 @@
|
|||||||
#define HEADER_CHECK_LINE_HPP
|
#define HEADER_CHECK_LINE_HPP
|
||||||
|
|
||||||
#include <ISceneNode.h>
|
#include <ISceneNode.h>
|
||||||
#include <line2d.h>
|
|
||||||
#include <vector2d.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
using namespace irr;
|
using namespace irr;
|
||||||
|
|
||||||
#include "tracks/check_structure.hpp"
|
#include "tracks/check_structure.hpp"
|
||||||
@ -50,17 +49,11 @@ namespace SP
|
|||||||
class CheckLine : public CheckStructure
|
class CheckLine : public CheckStructure
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/** The line that is tested for being crossed. */
|
|
||||||
core::line2df m_line;
|
|
||||||
|
|
||||||
/** True if this line should ignore the height test. This is required
|
/** True if this line should ignore the height test. This is required
|
||||||
* e.g. for basketball cannons, since the ball can be too height to
|
* e.g. for basketball cannons, since the ball can be too high to
|
||||||
* otherwise trigger the cannon. */
|
* otherwise trigger the cannon. */
|
||||||
bool m_ignore_height;
|
bool m_ignore_height;
|
||||||
|
|
||||||
/** The minimum height of the checkline. */
|
|
||||||
float m_min_height;
|
|
||||||
|
|
||||||
/** The actual (or estimated) left and right end points in 3d. This is
|
/** The actual (or estimated) left and right end points in 3d. This is
|
||||||
* used by the cannon. If the xml file stores only the min_height, those
|
* used by the cannon. If the xml file stores only the min_height, those
|
||||||
* points are set from the 2d points and the min height. */
|
* points are set from the 2d points and the min height. */
|
||||||
@ -74,14 +67,8 @@ private:
|
|||||||
/** Used to display debug information about checklines. */
|
/** Used to display debug information about checklines. */
|
||||||
std::shared_ptr<SP::SPDynamicDrawCall> m_debug_dy_dc;
|
std::shared_ptr<SP::SPDynamicDrawCall> m_debug_dy_dc;
|
||||||
|
|
||||||
/** How much a kart is allowed to be under the minimum height of a
|
/** The planes that are tested for being crossed. */
|
||||||
* quad and still considered to be able to cross it. */
|
irr::core::triangle3df m_check_plane[4];
|
||||||
static const int m_under_min_height = 1;
|
|
||||||
|
|
||||||
/** How much a kart is allowed to be over the minimum height of a
|
|
||||||
* quad and still considered to be able to cross it. */
|
|
||||||
static const int m_over_min_height = 4;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CheckLine(const XMLNode &node, unsigned int index);
|
CheckLine(const XMLNode &node, unsigned int index);
|
||||||
virtual ~CheckLine();
|
virtual ~CheckLine();
|
||||||
@ -94,9 +81,6 @@ public:
|
|||||||
virtual void changeDebugColor(bool is_active) OVERRIDE;
|
virtual void changeDebugColor(bool is_active) OVERRIDE;
|
||||||
virtual bool triggeringCheckline() const OVERRIDE { return true; }
|
virtual bool triggeringCheckline() const OVERRIDE { return true; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the actual line data for this checkpoint. */
|
|
||||||
const core::line2df &getLine2D() const {return m_line;}
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
/** Sets if this check line should not do a height test for testing
|
/** Sets if this check line should not do a height test for testing
|
||||||
* if a line is crossed. Used for basket calls in cannon (the ball can
|
* if a line is crossed. Used for basket calls in cannon (the ball can
|
||||||
* be too heigh to otherwise trigger he cannon). */
|
* be too heigh to otherwise trigger he cannon). */
|
||||||
|
Loading…
Reference in New Issue
Block a user