Start to clean up quad and graph node
This commit is contained in:
parent
35ce9a39ce
commit
21dc569f70
@ -1,5 +1,5 @@
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
||||
|
@ -457,7 +457,7 @@ void SlipStream::update(float dt)
|
||||
}
|
||||
// Real test: if in slipstream quad of other kart
|
||||
if(m_target_kart->getSlipstream()->m_slipstream_quad
|
||||
->pointInQuad(m_kart->getXYZ()))
|
||||
->pointInside(m_kart->getXYZ()))
|
||||
{
|
||||
is_sstreaming = true;
|
||||
break;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
@ -63,7 +64,7 @@ Bowling::Bowling(AbstractKart *kart)
|
||||
{
|
||||
unsigned int sector = ((LinearWorld*)World::getWorld())->
|
||||
getTrackSector(kart->getWorldKartId()).getCurrentGraphNode();
|
||||
quadNormal = QuadGraph::get()->getQuadOfNode(sector).getNormal();
|
||||
quadNormal = QuadGraph::get()->getNode(sector).getNormal();
|
||||
}
|
||||
else
|
||||
quadNormal = btVector3(.0f, 1.0f, .0f);
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "modes/easter_egg_hunt.hpp"
|
||||
#include "modes/three_strikes_battle.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
@ -32,8 +32,9 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/battle_graph.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
@ -162,7 +163,7 @@ ItemManager::ItemManager()
|
||||
m_items_in_quads = new std::vector<AllItemTypes>;
|
||||
// Entries 0 to n-1 are for the quads, entry
|
||||
// n is for all items that are not on a quad.
|
||||
m_items_in_quads->resize(QuadSet::get()->getNumberOfQuads()+1);
|
||||
m_items_in_quads->resize(QuadGraph::get()->getNumNodes()+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -227,7 +228,7 @@ void ItemManager::insertItem(Item *item)
|
||||
// If the item is on the driveline, store it at the appropriate index
|
||||
if(graph_node > -1)
|
||||
{
|
||||
int sector = QuadGraph::get()->getNode(graph_node).getQuadIndex();
|
||||
int sector = QuadGraph::get()->getNode(graph_node).getNodeIndex();
|
||||
(*m_items_in_quads)[sector].push_back(item);
|
||||
}
|
||||
else // otherwise store it in the 'outside' index
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
#include "utils/log.hpp" //TODO: remove after debugging is done
|
||||
@ -97,7 +99,8 @@ RubberBall::RubberBall(AbstractKart *kart)
|
||||
|
||||
// initialises the current graph node
|
||||
TrackSector::update(getXYZ());
|
||||
Vec3 normal = QuadGraph::get()->getQuadOfNode(getCurrentGraphNode()).getNormal();
|
||||
const Vec3& normal =
|
||||
QuadGraph::get()->getNode(getCurrentGraphNode()).getNormal();
|
||||
TerrainInfo::update(getXYZ(), -normal);
|
||||
initializeControlPoints(m_owner->getXYZ());
|
||||
|
||||
@ -133,7 +136,7 @@ void RubberBall::initializeControlPoints(const Vec3 &xyz)
|
||||
// left or right when firing the ball off track.
|
||||
getNextControlPoint();
|
||||
m_control_points[2] =
|
||||
QuadGraph::get()->getQuadOfNode(m_last_aimed_graph_node).getCenter();
|
||||
QuadGraph::get()->getNode(m_last_aimed_graph_node).getCenter();
|
||||
|
||||
// This updates m_last_aimed_graph_node, and sets m_control_points[3]
|
||||
getNextControlPoint();
|
||||
@ -234,7 +237,7 @@ void RubberBall::getNextControlPoint()
|
||||
m_last_aimed_graph_node = next;
|
||||
m_length_cp_2_3 = dist;
|
||||
const Quad &quad =
|
||||
QuadGraph::get()->getQuadOfNode(m_last_aimed_graph_node);
|
||||
QuadGraph::get()->getNode(m_last_aimed_graph_node);
|
||||
m_control_points[3] = quad.getCenter();
|
||||
} // getNextControlPoint
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/controller/ai_properties.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "states_screens/race_result_gui.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -214,7 +215,7 @@ void EndController::handleSteering(float dt)
|
||||
0.5f* QuadGraph::get()->getNode(m_track_node).getPathWidth()+0.5f )
|
||||
{
|
||||
const int next = m_next_node_index[m_track_node];
|
||||
target_point = QuadGraph::get()->getQuadOfNode(next).getCenter();
|
||||
target_point = QuadGraph::get()->getNode(next).getCenter();
|
||||
#ifdef AI_DEBUG
|
||||
Log::debug("end_controller.cpp", "- Outside of road: steer to center point.");
|
||||
#endif
|
||||
@ -274,7 +275,7 @@ void EndController::findNonCrashingPoint(Vec3 *result)
|
||||
target_sector = m_next_node_index[sector];
|
||||
|
||||
//direction is a vector from our kart to the sectors we are testing
|
||||
direction = QuadGraph::get()->getQuadOfNode(target_sector).getCenter()
|
||||
direction = QuadGraph::get()->getNode(target_sector).getCenter()
|
||||
- m_kart->getXYZ();
|
||||
|
||||
float len=direction.length_2d();
|
||||
@ -301,7 +302,7 @@ void EndController::findNonCrashingPoint(Vec3 *result)
|
||||
if ( distance + m_kart_width * 0.5f
|
||||
> QuadGraph::get()->getNode(sector).getPathWidth()*0.5f )
|
||||
{
|
||||
*result = QuadGraph::get()->getQuadOfNode(sector).getCenter();
|
||||
*result = QuadGraph::get()->getNode(sector).getCenter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -224,10 +224,7 @@ void SkiddingAI::update(float dt)
|
||||
// This is used to enable firing an item backwards.
|
||||
m_controls->m_look_back = false;
|
||||
m_controls->m_nitro = false;
|
||||
|
||||
//Vec3 gravity = m_kart->getBody()->getGravity();
|
||||
//Log::info("Sector", "%f %f %f %d", gravity[0], gravity[1], gravity[2],m_track_node);
|
||||
|
||||
|
||||
// Don't do anything if there is currently a kart animations shown.
|
||||
if(m_kart->getKartAnimation())
|
||||
return;
|
||||
@ -378,7 +375,7 @@ void SkiddingAI::update(float dt)
|
||||
m_controls->m_fire = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*And obviously general kart stuff*/
|
||||
AIBaseLapController::update(dt);
|
||||
} // update
|
||||
@ -481,11 +478,11 @@ void SkiddingAI::handleSteering(float dt)
|
||||
if( fabsf(side_dist) >
|
||||
0.5f* QuadGraph::get()->getNode(m_track_node).getPathWidth()+0.5f )
|
||||
{
|
||||
steer_angle = steerToPoint(QuadGraph::get()->getQuadOfNode(next)
|
||||
steer_angle = steerToPoint(QuadGraph::get()->getNode(next)
|
||||
.getCenter());
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere[0]->setPosition(QuadGraph::get()->getQuadOfNode(next)
|
||||
m_debug_sphere[0]->setPosition(QuadGraph::get()->getNode(next)
|
||||
.getCenter().toIrrVector());
|
||||
Log::debug(getControllerName().c_str(),
|
||||
"Outside of road: steer to center point.");
|
||||
@ -622,10 +619,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
#ifdef AI_DEBUG
|
||||
m_item_sphere->setVisible(false);
|
||||
#endif
|
||||
// Angle of line from kart to aim_point
|
||||
float kart_aim_angle = atan2(aim_point->getX()-m_kart->getXYZ().getX(),
|
||||
aim_point->getZ()-m_kart->getXYZ().getZ());
|
||||
|
||||
// Angle to aim_point
|
||||
Vec3 kart_aim_direction = *aim_point - m_kart->getXYZ();
|
||||
|
||||
// Make sure we have a valid last_node
|
||||
@ -642,9 +636,9 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
const float max_item_lookahead_distance = 30.f;
|
||||
while(distance < max_item_lookahead_distance)
|
||||
{
|
||||
int q_index= QuadGraph::get()->getNode(node).getQuadIndex();
|
||||
int n_index= QuadGraph::get()->getNode(node).getNodeIndex();
|
||||
const std::vector<Item *> &items_ahead =
|
||||
ItemManager::get()->getItemsInQuads(q_index);
|
||||
ItemManager::get()->getItemsInQuads(n_index);
|
||||
for(unsigned int i=0; i<items_ahead.size(); i++)
|
||||
{
|
||||
evaluateItems(items_ahead[i], kart_aim_direction,
|
||||
@ -659,14 +653,9 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
|
||||
m_avoid_item_close = items_to_avoid.size()>0;
|
||||
|
||||
core::line2df line_to_target(aim_point->getX(),
|
||||
aim_point->getZ(),
|
||||
m_kart->getXYZ().getX(),
|
||||
m_kart->getXYZ().getZ());
|
||||
|
||||
core::line3df line_to_target_3d((*aim_point).toIrrVector(),
|
||||
core::line3df line_to_target_3d((*aim_point).toIrrVector(),
|
||||
m_kart->getXYZ().toIrrVector());
|
||||
|
||||
|
||||
// 2) If the kart is aiming for an item, but (suddenly) detects
|
||||
// some close-by items to avoid (e.g. behind the item, which was too
|
||||
// far away to be considered earlier, or because the item was switched
|
||||
@ -792,7 +781,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
// so that it can potentially become a permanent target.
|
||||
Vec3 xyz = item_to_collect->getXYZ();
|
||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||
Vec3 plane_normal = QuadGraph::get()->getQuadOfNode(m_track_node)
|
||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node)
|
||||
.getNormal();
|
||||
float dist_to_plane = item_direction.dot(plane_normal);
|
||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||
@ -840,7 +829,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
bool SkiddingAI::hitBadItemWhenAimAt(const Item *item,
|
||||
const std::vector<const Item *> &items_to_avoid)
|
||||
{
|
||||
core::line3df to_item(m_kart->getXYZ().toIrrVector(),
|
||||
core::line3df to_item(m_kart->getXYZ().toIrrVector(),
|
||||
item->getXYZ().toIrrVector());
|
||||
for(unsigned int i=0; i<items_to_avoid.size(); i++)
|
||||
{
|
||||
@ -873,11 +862,10 @@ bool SkiddingAI::handleSelectedItem(Vec3 kart_aim_direction, Vec3 *aim_point)
|
||||
// Project the item's location onto the plane of the current quad.
|
||||
// This is necessary because the kart's aim point may not be on the track
|
||||
// in 3D curves. So we project the item's location onto the plane in which
|
||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||
const Vec3 &xyz = m_item_to_collect->getXYZ();
|
||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||
Vec3 plane_normal = QuadGraph::get()->getQuadOfNode(m_track_node)
|
||||
.getNormal();
|
||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node).getNormal();
|
||||
float dist_to_plane = item_direction.dot(plane_normal);
|
||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||
|
||||
@ -936,12 +924,9 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
|
||||
// Check if we would drive left of the leftmost or right of the
|
||||
// rightmost point - if so, nothing to do.
|
||||
|
||||
//core::vector2df left(items_to_avoid[index_left_most]->getXYZ().getX(),
|
||||
// items_to_avoid[index_left_most]->getXYZ().getZ());
|
||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
||||
Vec3 normal = QuadGraph::get()->getQuadOfNode(node_index).getNormal();
|
||||
Vec3 normal = QuadGraph::get()->getNode(node_index).getNormal();
|
||||
Vec3 p1 = line_to_target.start,
|
||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||
p3 = line_to_target.end;
|
||||
@ -959,11 +944,9 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
}
|
||||
else
|
||||
{
|
||||
//core::vector2df right(items_to_avoid[index_right_most]->getXYZ().getX(),
|
||||
// items_to_avoid[index_right_most]->getXYZ().getZ());
|
||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
||||
Vec3 normal = QuadGraph::get()->getQuadOfNode(node_index).getNormal();
|
||||
Vec3 normal = QuadGraph::get()->getNode(node_index).getNormal();
|
||||
Vec3 p1 = line_to_target.start,
|
||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||
p3 = line_to_target.end;
|
||||
@ -1121,11 +1104,10 @@ void SkiddingAI::evaluateItems(const Item *item, Vec3 kart_aim_direction,
|
||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||
const Vec3 &xyz = item->getXYZ();
|
||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||
Vec3 plane_normal = QuadGraph::get()->getQuadOfNode(m_track_node)
|
||||
.getNormal();
|
||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node).getNormal();
|
||||
float dist_to_plane = item_direction.dot(plane_normal);
|
||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||
|
||||
|
||||
float angle_to_item = (projected_xyz - m_kart->getXYZ())
|
||||
.angle(kart_aim_direction);
|
||||
|
||||
@ -1879,23 +1861,23 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
*last_node = m_next_node_index[m_track_node];
|
||||
const core::vector2df xz = m_kart->getXYZ().toIrrVector2d();
|
||||
|
||||
const Quad &q = QuadGraph::get()->getQuadOfNode(*last_node);
|
||||
const GraphNode &g = QuadGraph::get()->getNode(*last_node);
|
||||
|
||||
// Index of the left and right end of a quad.
|
||||
const unsigned int LEFT_END_POINT = 0;
|
||||
const unsigned int RIGHT_END_POINT = 1;
|
||||
core::line2df left (xz, q[LEFT_END_POINT ].toIrrVector2d());
|
||||
core::line2df right(xz, q[RIGHT_END_POINT].toIrrVector2d());
|
||||
core::line2df left (xz, g[LEFT_END_POINT ].toIrrVector2d());
|
||||
core::line2df right(xz, g[RIGHT_END_POINT].toIrrVector2d());
|
||||
|
||||
#if defined(AI_DEBUG) && defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||
const Vec3 eps1(0,0.5f,0);
|
||||
m_curve[CURVE_LEFT]->clear();
|
||||
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
||||
m_curve[CURVE_LEFT]->addPoint(q[LEFT_END_POINT]+eps1);
|
||||
m_curve[CURVE_LEFT]->addPoint(g[LEFT_END_POINT]+eps1);
|
||||
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
||||
m_curve[CURVE_RIGHT]->clear();
|
||||
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
||||
m_curve[CURVE_RIGHT]->addPoint(q[RIGHT_END_POINT]+eps1);
|
||||
m_curve[CURVE_RIGHT]->addPoint(g[RIGHT_END_POINT]+eps1);
|
||||
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
||||
#endif
|
||||
#if defined(AI_DEBUG_KART_HEADING) || defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||
@ -1908,13 +1890,13 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
while(1)
|
||||
{
|
||||
unsigned int next_sector = m_next_node_index[*last_node];
|
||||
const Quad &q_next = QuadGraph::get()->getQuadOfNode(next_sector);
|
||||
const GraphNode &g_next = QuadGraph::get()->getNode(next_sector);
|
||||
// Test if the next left point is to the right of the left
|
||||
// line. If so, a new left line is defined.
|
||||
if(left.getPointOrientation(q_next[LEFT_END_POINT].toIrrVector2d())
|
||||
if(left.getPointOrientation(g_next[LEFT_END_POINT].toIrrVector2d())
|
||||
< 0 )
|
||||
{
|
||||
core::vector2df p = q_next[LEFT_END_POINT].toIrrVector2d();
|
||||
core::vector2df p = g_next[LEFT_END_POINT].toIrrVector2d();
|
||||
// Stop if the new point is to the right of the right line
|
||||
if(right.getPointOrientation(p)<0)
|
||||
break;
|
||||
@ -1930,10 +1912,10 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
|
||||
// Test if new right point is to the left of the right line. If
|
||||
// so, a new right line is defined.
|
||||
if(right.getPointOrientation(q_next[RIGHT_END_POINT].toIrrVector2d())
|
||||
if(right.getPointOrientation(g_next[RIGHT_END_POINT].toIrrVector2d())
|
||||
> 0 )
|
||||
{
|
||||
core::vector2df p = q_next[RIGHT_END_POINT].toIrrVector2d();
|
||||
core::vector2df p = g_next[RIGHT_END_POINT].toIrrVector2d();
|
||||
// Break if new point is to the left of left line
|
||||
if(left.getPointOrientation(p)>0)
|
||||
break;
|
||||
@ -1955,7 +1937,7 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
// 0.5f*(left.end.Y+right.end.Y));
|
||||
//*result = ppp;
|
||||
|
||||
*result = QuadGraph::get()->getQuadOfNode(*last_node).getCenter();
|
||||
*result = QuadGraph::get()->getNode(*last_node).getCenter();
|
||||
} // findNonCrashingPointNew
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1992,10 +1974,10 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
target_sector = m_next_node_index[*last_node];
|
||||
|
||||
//direction is a vector from our kart to the sectors we are testing
|
||||
direction = QuadGraph::get()->getQuadOfNode(target_sector).getCenter()
|
||||
direction = QuadGraph::get()->getNode(target_sector).getCenter()
|
||||
- m_kart->getXYZ();
|
||||
|
||||
float len=direction.length_2d();
|
||||
float len=direction.length();
|
||||
unsigned int steps = (unsigned int)( len / m_kart_length );
|
||||
if( steps < 3 ) steps = 3;
|
||||
|
||||
@ -2024,20 +2006,28 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
if ( distance + m_kart_width * 0.5f
|
||||
> QuadGraph::get()->getNode(*last_node).getPathWidth()*0.5f )
|
||||
{
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(*last_node)
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node)
|
||||
.getCenter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
*last_node = target_sector;
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(*last_node).getCenter();
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node).getCenter();
|
||||
} // findNonCrashingPointFixed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This is basically the original AI algorithm. It is clearly buggy:
|
||||
* 1. the test:
|
||||
*
|
||||
* distance + m_kart_width * 0.5f
|
||||
* > QuadGraph::get()->getNode(*last_node).getPathWidth() )
|
||||
*
|
||||
* is incorrect, it should compare with getPathWith*0.5f (since distance
|
||||
* is the distance from the center, i.e. it is half the path width if
|
||||
* the point is at the edge).
|
||||
* 2. the test:
|
||||
*
|
||||
* QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
* *last_node );
|
||||
* in the for loop tests always against distance from the same
|
||||
@ -2050,17 +2040,10 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
* which takes some time - so it is actually mostly on track.
|
||||
* Since this algoritm (so far) ends up with by far the best AI behaviour,
|
||||
* it is for now the default).
|
||||
*
|
||||
* GSoC 2014: This algorithm has been updated so that the AI can drive on
|
||||
* upside-down tracks. Because steering only works in 2D, you can steer left and
|
||||
* right but not up and down, but the track might not be 2D. So for every quad,
|
||||
* we have a set of k unrolled quads starting from the current quad. The AI uses
|
||||
* these unrolled quads to search for a suitable aim point.
|
||||
*
|
||||
* \param aim_position On exit contains the point the AI should aim at.
|
||||
* \param last_node On exit contais the graph node the AI is aiming at.
|
||||
*/
|
||||
void SkiddingAI::findNonCrashingPoint(Vec3 *aim_position, int *last_node)
|
||||
void SkiddingAI::findNonCrashingPoint(Vec3 *aim_position, int *last_node)
|
||||
{
|
||||
#ifdef AI_DEBUG_KART_HEADING
|
||||
const Vec3 eps(0,0.5f,0);
|
||||
@ -2069,7 +2052,7 @@ void SkiddingAI::findNonCrashingPoint(Vec3 *aim_position, int *last_node)
|
||||
Vec3 forw(0, 0, 50);
|
||||
m_curve[CURVE_KART]->addPoint(m_kart->getTrans()(forw)+eps);
|
||||
#endif
|
||||
*last_node = m_track_node;
|
||||
*last_node = m_next_node_index[m_track_node];
|
||||
float angle = QuadGraph::get()->getAngleToNext(m_track_node,
|
||||
m_successor_index[m_track_node]);
|
||||
int target_sector;
|
||||
@ -2078,30 +2061,14 @@ void SkiddingAI::findNonCrashingPoint(Vec3 *aim_position, int *last_node)
|
||||
Vec3 step_track_coord;
|
||||
|
||||
float angle1;
|
||||
|
||||
// We need to find out if there is an alternate path that the kart might take.
|
||||
// This is done in advance so that the right set of unrolled quads are used
|
||||
// and the AI finds aim_points on the alternate path. future_successor_idx
|
||||
// is successor index of a future node. 0 is the default, but if there is an
|
||||
// alternate path coming up, this will be set to 1.
|
||||
int future_successor_idx = 0;
|
||||
int current = m_track_node;
|
||||
for (unsigned int j = 0; j < QuadGraph::get()->getNumberOfUnrolledQuads(); j++)
|
||||
{
|
||||
if (m_successor_index[current] != 0)
|
||||
future_successor_idx = m_successor_index[current];
|
||||
|
||||
current = m_next_node_index[current];
|
||||
}
|
||||
|
||||
// This for loop runs till it runs out of unrolled quads or breaks when the
|
||||
// aim point is outside one of the unrolled quads.
|
||||
for(unsigned int j=0; j<QuadGraph::get()->getNumberOfUnrolledQuads(); j++)
|
||||
// The original while(1) loop is replaced with a for loop to avoid
|
||||
// infinite loops (which we had once or twice). Usually the number
|
||||
// of iterations in the while loop is less than 7.
|
||||
for(unsigned int j=0; j<100; j++)
|
||||
{
|
||||
// target_sector is the sector at the longest distance that we can
|
||||
// drive to without crashing with the track.
|
||||
target_sector = m_next_node_index[*last_node];
|
||||
|
||||
angle1 = QuadGraph::get()->getAngleToNext(target_sector,
|
||||
m_successor_index[target_sector]);
|
||||
// In very sharp turns this algorithm tends to aim at off track points,
|
||||
@ -2110,17 +2077,16 @@ void SkiddingAI::findNonCrashingPoint(Vec3 *aim_position, int *last_node)
|
||||
float diff = normalizeAngle(angle1-angle);
|
||||
if(fabsf(diff)>1.5f)
|
||||
{
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(target_sector)
|
||||
.getCenter();
|
||||
*aim_position = QuadGraph::get()->getNode(target_sector)
|
||||
.getCenter();
|
||||
return;
|
||||
}
|
||||
|
||||
Quad target_quad_unrolled = QuadGraph::get()->getNode(m_track_node).
|
||||
getUnrolledQuad(future_successor_idx,j + 1);
|
||||
//direction is a vector from our kart to the sectors we are testing
|
||||
direction = QuadGraph::get()->getNode(target_sector).getCenter()
|
||||
- m_kart->getXYZ();
|
||||
|
||||
direction = target_quad_unrolled.getCenter() - m_kart->getXYZ();
|
||||
|
||||
float len = direction.length();
|
||||
float len=direction.length();
|
||||
unsigned int steps = (unsigned int)( len / m_kart_length );
|
||||
if( steps < 3 ) steps = 3;
|
||||
|
||||
@ -2130,38 +2096,34 @@ void SkiddingAI::findNonCrashingPoint(Vec3 *aim_position, int *last_node)
|
||||
if( steps>1000) steps = 1000;
|
||||
|
||||
// Protection against having vel_normal with nan values
|
||||
if(len>0.0f)
|
||||
{
|
||||
if(len>0.0f) {
|
||||
direction*= 1.0f/len;
|
||||
}
|
||||
|
||||
Vec3 step_coord;
|
||||
//Test if we crash if we drive towards the target sector (unrolled set)
|
||||
//Test if we crash if we drive towards the target sector
|
||||
for(unsigned int i = 2; i < steps; ++i )
|
||||
{
|
||||
step_coord = m_kart->getXYZ()+direction*m_kart_length * float(i);
|
||||
|
||||
QuadGraph::get()->spatialToTrackUnrolled(&step_track_coord, step_coord,
|
||||
m_track_node, j, future_successor_idx);
|
||||
QuadGraph::get()->spatialToTrack(&step_track_coord, step_coord,
|
||||
*last_node );
|
||||
|
||||
float distance = step_track_coord[0];
|
||||
float distance = fabsf(step_track_coord[0]);
|
||||
|
||||
//If we are outside, the previous node is what we are looking for
|
||||
if ( distance + m_kart_width * 0.5f
|
||||
> QuadGraph::get()->getNode((*last_node+j)%QuadGraph::get()->getNumNodes() ).getPathWidth()*0.5f )
|
||||
> QuadGraph::get()->getNode(*last_node).getPathWidth() )
|
||||
{
|
||||
*aim_position = QuadGraph::get()->getUnrolledQuadOfNode(m_track_node,future_successor_idx,j+1)
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node)
|
||||
.getCenter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
angle = angle1;
|
||||
*last_node = target_sector;
|
||||
}
|
||||
// If we are inside entire unrolled set then set the aim_point to be center of the last unrolled quad
|
||||
*aim_position = QuadGraph::get()->getNode(m_track_node).
|
||||
getUnrolledQuad(future_successor_idx,QuadGraph::get()->getNumberOfUnrolledQuads()).getCenter();
|
||||
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node).getCenter();
|
||||
} // findNonCrashingPoint
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2176,9 +2138,9 @@ void SkiddingAI::determineTrackDirection()
|
||||
|
||||
//float angle_to_track = qg->getNode(m_track_node).getAngleToSuccessor(succ)
|
||||
// - m_kart->getHeading();
|
||||
Vec3 track_direction = -qg->getQuadOfNode(m_track_node).getCenter()
|
||||
+ qg->getQuadOfNode(next).getCenter();
|
||||
//Vec3 kart_direction = qg->getQuadOfNode(m_track_node).getCenter() + m_kart->getVelocity();
|
||||
Vec3 track_direction = -qg->getNode(m_track_node).getCenter()
|
||||
+ qg->getNode(next).getCenter();
|
||||
//Vec3 kart_direction = qg->getNode(m_track_node).getCenter() + m_kart->getVelocity();
|
||||
|
||||
float angle_to_track = 0;
|
||||
if (m_kart->getVelocity().length() > 0.0f)
|
||||
@ -2203,8 +2165,6 @@ void SkiddingAI::determineTrackDirection()
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
qg->getNode(next).getDirectionData(m_successor_index[next],
|
||||
&m_current_track_direction,
|
||||
&m_last_direction_node);
|
||||
@ -2265,10 +2225,10 @@ void SkiddingAI::handleCurve()
|
||||
// Pick either the lower left or right point:
|
||||
int index = m_current_track_direction==GraphNode::DIR_LEFT
|
||||
? 0 : 1;
|
||||
float r = (m_curve_center - qg->getQuadOfNode(i)[index]).length();
|
||||
float r = (m_curve_center - qg->getNode(i)[index]).length();
|
||||
if(m_current_curve_radius < r)
|
||||
{
|
||||
last_xyz = qg->getQuadOfNode(i)[index];
|
||||
last_xyz = qg->getNode(i)[index];
|
||||
determineTurnRadius(xyz, tangent, last_xyz,
|
||||
&m_curve_center, &m_current_curve_radius);
|
||||
m_last_direction_node = i;
|
||||
|
@ -31,15 +31,15 @@
|
||||
|
||||
#ifdef DEBUG
|
||||
// Enable AI graphical debugging
|
||||
# undef AI_DEBUG
|
||||
# define AI_DEBUG
|
||||
// Shows left and right lines when using new findNonCrashing function
|
||||
# undef AI_DEBUG_NEW_FIND_NON_CRASHING
|
||||
# define AI_DEBUG_NEW_FIND_NON_CRASHING
|
||||
// Show the predicted turn circles
|
||||
# undef AI_DEBUG_CIRCLES
|
||||
# define AI_DEBUG_CIRCLES
|
||||
// Show the heading of the kart
|
||||
# undef AI_DEBUG_KART_HEADING
|
||||
# define AI_DEBUG_KART_HEADING
|
||||
// Shows line from kart to its aim point
|
||||
# undef AI_DEBUG_KART_AIM
|
||||
# define AI_DEBUG_KART_AIM
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -484,11 +484,11 @@ void SkiddingAI::handleSteering(float dt)
|
||||
if( fabsf(side_dist) >
|
||||
0.5f* QuadGraph::get()->getNode(m_track_node).getPathWidth()+0.5f )
|
||||
{
|
||||
steer_angle = steerToPoint(QuadGraph::get()->getQuadOfNode(next)
|
||||
steer_angle = steerToPoint(QuadGraph::get()->getNode(next)
|
||||
.getCenter());
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
m_debug_sphere[0]->setPosition(QuadGraph::get()->getQuadOfNode(next)
|
||||
m_debug_sphere[0]->setPosition(QuadGraph::get()->getNode(next)
|
||||
.getCenter().toIrrVector());
|
||||
Log::debug(getControllerName().c_str(),
|
||||
"Outside of road: steer to center point.");
|
||||
@ -621,13 +621,12 @@ void SkiddingAI::handleSteering(float dt)
|
||||
*/
|
||||
void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
int last_node)
|
||||
{/*
|
||||
{
|
||||
#ifdef AI_DEBUG
|
||||
m_item_sphere->setVisible(false);
|
||||
#endif
|
||||
// Angle of line from kart to aim_point
|
||||
float kart_aim_angle = atan2(aim_point->getX()-m_kart->getXYZ().getX(),
|
||||
aim_point->getZ()-m_kart->getXYZ().getZ());
|
||||
// Angle to aim_point
|
||||
Vec3 kart_aim_direction = *aim_point - m_kart->getXYZ();
|
||||
|
||||
// Make sure we have a valid last_node
|
||||
if(last_node==QuadGraph::UNKNOWN_SECTOR)
|
||||
@ -643,12 +642,12 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
const float max_item_lookahead_distance = 30.f;
|
||||
while(distance < max_item_lookahead_distance)
|
||||
{
|
||||
int q_index= QuadGraph::get()->getNode(node).getQuadIndex();
|
||||
int n_index= QuadGraph::get()->getNode(node).getNodeIndex();
|
||||
const std::vector<Item *> &items_ahead =
|
||||
ItemManager::get()->getItemsInQuads(q_index);
|
||||
ItemManager::get()->getItemsInQuads(n_index);
|
||||
for(unsigned int i=0; i<items_ahead.size(); i++)
|
||||
{
|
||||
evaluateItems(items_ahead[i], kart_aim_angle,
|
||||
evaluateItems(items_ahead[i], kart_aim_direction,
|
||||
&items_to_avoid, &items_to_collect);
|
||||
} // for i<items_ahead;
|
||||
distance += QuadGraph::get()->getDistanceToNext(node,
|
||||
@ -660,10 +659,8 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
|
||||
m_avoid_item_close = items_to_avoid.size()>0;
|
||||
|
||||
core::line2df line_to_target(aim_point->getX(),
|
||||
aim_point->getZ(),
|
||||
m_kart->getXYZ().getX(),
|
||||
m_kart->getXYZ().getZ());
|
||||
core::line3df line_to_target_3d((*aim_point).toIrrVector(),
|
||||
m_kart->getXYZ().toIrrVector());
|
||||
|
||||
// 2) If the kart is aiming for an item, but (suddenly) detects
|
||||
// some close-by items to avoid (e.g. behind the item, which was too
|
||||
@ -676,7 +673,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
for(unsigned int i=0; i< items_to_avoid.size(); i++)
|
||||
{
|
||||
Vec3 d = items_to_avoid[i]->getXYZ()-m_item_to_collect->getXYZ();
|
||||
if( d.length2_2d()>m_ai_properties->m_bad_item_closeness_2)
|
||||
if( d.length2()>m_ai_properties->m_bad_item_closeness_2)
|
||||
continue;
|
||||
// It could make sense to also test if the bad item would
|
||||
// actually be hit, not only if it is close (which can result
|
||||
@ -696,7 +693,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
// -------------------------------------
|
||||
if(m_item_to_collect)
|
||||
{
|
||||
if(handleSelectedItem(kart_aim_angle, aim_point))
|
||||
if(handleSelectedItem(kart_aim_direction, aim_point))
|
||||
{
|
||||
// Still aim at the previsouly selected item.
|
||||
*aim_point = m_item_to_collect->getXYZ();
|
||||
@ -721,7 +718,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
{
|
||||
// If we need to steer to avoid an item, this takes priority,
|
||||
// ignore items to collect and return the new aim_point.
|
||||
if(steerToAvoid(items_to_avoid, line_to_target, aim_point))
|
||||
if(steerToAvoid(items_to_avoid, line_to_target_3d, aim_point))
|
||||
{
|
||||
#ifdef AI_DEBUG
|
||||
m_item_sphere->setVisible(true);
|
||||
@ -770,7 +767,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
// it's on a good enough driveline, so make this item a permanent
|
||||
// target. Otherwise only try to get closer (till hopefully this
|
||||
// item s on our driveline)
|
||||
if(item_to_collect->hitLine(line_to_target, m_kart))
|
||||
if(item_to_collect->hitLine(line_to_target_3d, m_kart))
|
||||
{
|
||||
#ifdef AI_DEBUG
|
||||
m_item_sphere->setVisible(true);
|
||||
@ -789,9 +786,15 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
// Kart will not hit item, try to get closer to this item
|
||||
// so that it can potentially become a permanent target.
|
||||
Vec3 xyz = item_to_collect->getXYZ();
|
||||
float item_angle = atan2(xyz.getX() - m_kart->getXYZ().getX(),
|
||||
xyz.getZ() - m_kart->getXYZ().getZ());
|
||||
float angle = normalizeAngle(kart_aim_angle - item_angle);
|
||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node)
|
||||
.getNormal();
|
||||
float dist_to_plane = item_direction.dot(plane_normal);
|
||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||
|
||||
float angle_to_item = (projected_xyz - m_kart->getXYZ())
|
||||
.angle(kart_aim_direction);
|
||||
float angle = normalizeAngle(angle_to_item);
|
||||
|
||||
if(fabsf(angle) < 0.3)
|
||||
{
|
||||
@ -818,7 +821,7 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
} // kart will not hit item
|
||||
} // does hit hit bad item
|
||||
} // if item to consider was found
|
||||
*/
|
||||
|
||||
} // handleItemCollectionAndAvoidance
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -832,13 +835,13 @@ void SkiddingAI::handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
bool SkiddingAI::hitBadItemWhenAimAt(const Item *item,
|
||||
const std::vector<const Item *> &items_to_avoid)
|
||||
{
|
||||
/* core::line2df to_item(m_kart->getXYZ().getX(), m_kart->getXYZ().getZ(),
|
||||
item->getXYZ().getX(), item->getXYZ().getZ() );
|
||||
core::line3df to_item(m_kart->getXYZ().toIrrVector(),
|
||||
item->getXYZ().toIrrVector());
|
||||
for(unsigned int i=0; i<items_to_avoid.size(); i++)
|
||||
{
|
||||
if(items_to_avoid[i]->hitLine(to_item, m_kart))
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
return false;
|
||||
} // hitBadItemWhenAimAt
|
||||
|
||||
@ -854,7 +857,7 @@ bool SkiddingAI::hitBadItemWhenAimAt(const Item *item,
|
||||
* \param last_node
|
||||
* \return True if th AI should still aim for the pre-selected item.
|
||||
*/
|
||||
bool SkiddingAI::handleSelectedItem(float kart_aim_angle, Vec3 *aim_point)
|
||||
bool SkiddingAI::handleSelectedItem(Vec3 kart_aim_direction, Vec3 *aim_point)
|
||||
{
|
||||
// If the item is unavailable keep on testing. It is not necessary
|
||||
// to test if an item has turned bad, this was tested before this
|
||||
@ -862,11 +865,21 @@ bool SkiddingAI::handleSelectedItem(float kart_aim_angle, Vec3 *aim_point)
|
||||
if(m_item_to_collect->getDisableTime()>0)
|
||||
return false;
|
||||
|
||||
// Project the item's location onto the plane of the current quad.
|
||||
// This is necessary because the kart's aim point may not be on the track
|
||||
// in 3D curves. So we project the item's location onto the plane in which
|
||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||
const Vec3 &xyz = m_item_to_collect->getXYZ();
|
||||
float item_angle = atan2(xyz.getX() - m_kart->getXYZ().getX(),
|
||||
xyz.getZ() - m_kart->getXYZ().getZ());
|
||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node).getNormal();
|
||||
float dist_to_plane = item_direction.dot(plane_normal);
|
||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||
|
||||
float angle_to_item = (projected_xyz - m_kart->getXYZ())
|
||||
.angle(kart_aim_direction);
|
||||
|
||||
float angle = normalizeAngle(angle_to_item);
|
||||
|
||||
float angle = normalizeAngle(kart_aim_angle - item_angle);
|
||||
if(fabsf(angle)>1.5)
|
||||
{
|
||||
// We (likely) have passed the item we were aiming for
|
||||
@ -891,10 +904,10 @@ bool SkiddingAI::handleSelectedItem(float kart_aim_angle, Vec3 *aim_point)
|
||||
* \return True if steering is necessary to avoid an item.
|
||||
*/
|
||||
bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
const core::line2df &line_to_target,
|
||||
const core::line3df &line_to_target,
|
||||
Vec3 *aim_point)
|
||||
{
|
||||
/* // First determine the left-most and right-most item.
|
||||
// First determine the left-most and right-most item.
|
||||
float left_most = items_to_avoid[0]->getDistanceFromCenter();
|
||||
float right_most = items_to_avoid[0]->getDistanceFromCenter();
|
||||
int index_left_most = 0;
|
||||
@ -917,14 +930,19 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
|
||||
// Check if we would drive left of the leftmost or right of the
|
||||
// rightmost point - if so, nothing to do.
|
||||
core::vector2df left(items_to_avoid[index_left_most]->getXYZ().getX(),
|
||||
items_to_avoid[index_left_most]->getXYZ().getZ());
|
||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
||||
Vec3 normal = QuadGraph::get()->getNode(node_index).getNormal();
|
||||
Vec3 p1 = line_to_target.start,
|
||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||
p3 = line_to_target.end;
|
||||
|
||||
int item_index = -1;
|
||||
bool is_left = false;
|
||||
|
||||
// >=0 means the point is to the right of the line, or the line is
|
||||
// to the left of the point.
|
||||
if(line_to_target.getPointOrientation(left)>=0)
|
||||
if(left.sideofPlane(p1,p2,p3) <= 0)
|
||||
{
|
||||
// Left of leftmost point
|
||||
item_index = index_left_most;
|
||||
@ -932,9 +950,14 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
}
|
||||
else
|
||||
{
|
||||
core::vector2df right(items_to_avoid[index_right_most]->getXYZ().getX(),
|
||||
items_to_avoid[index_right_most]->getXYZ().getZ());
|
||||
if(line_to_target.getPointOrientation(right)<=0)
|
||||
Vec3 left(items_to_avoid[index_left_most]->getXYZ());
|
||||
int node_index = items_to_avoid[index_left_most]->getGraphNode();
|
||||
Vec3 normal = QuadGraph::get()->getNode(node_index).getNormal();
|
||||
Vec3 p1 = line_to_target.start,
|
||||
p2 = line_to_target.getMiddle() + normal.toIrrVector(),
|
||||
p3 = line_to_target.end;
|
||||
|
||||
if (left.sideofPlane(p1, p2, p3) >= 0)
|
||||
{
|
||||
// Right of rightmost point
|
||||
item_index = index_right_most;
|
||||
@ -975,20 +998,20 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
|
||||
float min_distance[2] = {99999.9f, 99999.9f};
|
||||
int index[2] = {-1, -1};
|
||||
core::vector2df closest2d[2];
|
||||
core::vector3df closest3d[2];
|
||||
for(unsigned int i=0; i<items_to_avoid.size(); i++)
|
||||
{
|
||||
const Vec3 &xyz = items_to_avoid[i]->getXYZ();
|
||||
core::vector2df item2d = xyz.toIrrVector2d();
|
||||
core::vector2df point2d = line_to_target.getClosestPoint(item2d);
|
||||
float d = (xyz.toIrrVector2d() - point2d).getLengthSQ();
|
||||
float direction = line_to_target.getPointOrientation(item2d);
|
||||
int ind = direction<0 ? 0 : 1;
|
||||
core::vector3df point3d = line_to_target.getClosestPoint(xyz.toIrrVector());
|
||||
float d = (xyz.toIrrVector() - point3d).getLengthSQ();
|
||||
float direction = xyz.sideofPlane(p1,p2,p3);
|
||||
int ind = direction<0 ? 1 : 0;
|
||||
if(d<min_distance[ind])
|
||||
{
|
||||
min_distance[ind] = d;
|
||||
index[ind] = i;
|
||||
closest2d[ind] = point2d;
|
||||
closest3d[ind] = point3d;
|
||||
}
|
||||
}
|
||||
|
||||
@ -998,25 +1021,24 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
|
||||
// We are driving between item_to_avoid[index[0]] and ...[1].
|
||||
// If we don't hit any of them, just keep on driving as normal
|
||||
bool hit_left = items_to_avoid[index[0]]->hitKart(closest2d[0], m_kart);
|
||||
bool hit_right = items_to_avoid[index[1]]->hitKart(closest2d[1], m_kart);
|
||||
bool hit_left = items_to_avoid[index[0]]->hitKart(closest3d[0], m_kart);
|
||||
bool hit_right = items_to_avoid[index[1]]->hitKart(closest3d[1], m_kart);
|
||||
if( !hit_left && !hit_right)
|
||||
return false;
|
||||
*/
|
||||
|
||||
// If we hit the left item, aim at the right avoidance point
|
||||
// of the left item. We might still hit the right item ... this might
|
||||
// still be better than going too far off track
|
||||
//if(hit_left)
|
||||
//{
|
||||
// *aim_point =
|
||||
// *(items_to_avoid[index[0]]->getAvoidancePoint(/*left*/false));
|
||||
// return true;
|
||||
//}
|
||||
if(hit_left)
|
||||
{
|
||||
*aim_point =
|
||||
*(items_to_avoid[index[0]]->getAvoidancePoint(/*left*/false));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now we must be hitting the right item, so try aiming at the left
|
||||
// avoidance point of the right item.
|
||||
//*aim_point = *(items_to_avoid[index[1]]->getAvoidancePoint(/*left*/true));
|
||||
|
||||
*aim_point = *(items_to_avoid[index[1]]->getAvoidancePoint(/*left*/true));
|
||||
return true;
|
||||
} // steerToAvoid
|
||||
|
||||
@ -1034,7 +1056,7 @@ bool SkiddingAI::steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
* (NULL if no item was avoided so far).
|
||||
* \param item_to_collect A pointer to a previously selected item to collect.
|
||||
*/
|
||||
void SkiddingAI::evaluateItems(const Item *item, float kart_aim_angle,
|
||||
void SkiddingAI::evaluateItems(const Item *item, Vec3 kart_aim_direction,
|
||||
std::vector<const Item *> *items_to_avoid,
|
||||
std::vector<const Item *> *items_to_collect)
|
||||
{
|
||||
@ -1082,13 +1104,20 @@ void SkiddingAI::evaluateItems(const Item *item, float kart_aim_angle,
|
||||
// to avoid are collected).
|
||||
if(!avoid)
|
||||
{
|
||||
// item_angle The angle of the item (relative to the forward axis,
|
||||
// so 0 means straight ahead in world coordinates!).
|
||||
// Project the item's location onto the plane of the current quad.
|
||||
// This is necessary because the kart's aim point may not be on the track
|
||||
// in 3D curves. So we project the item's location onto the plane in which
|
||||
// the kart is. The current quad provides a good estimate of the kart's plane.
|
||||
const Vec3 &xyz = item->getXYZ();
|
||||
float item_angle = atan2(xyz.getX() - m_kart->getXYZ().getX(),
|
||||
xyz.getZ() - m_kart->getXYZ().getZ());
|
||||
Vec3 item_direction = xyz - m_kart->getXYZ();
|
||||
Vec3 plane_normal = QuadGraph::get()->getNode(m_track_node).getNormal();
|
||||
float dist_to_plane = item_direction.dot(plane_normal);
|
||||
Vec3 projected_xyz = xyz - dist_to_plane*plane_normal;
|
||||
|
||||
float diff = normalizeAngle(kart_aim_angle-item_angle);
|
||||
float angle_to_item = (projected_xyz - m_kart->getXYZ())
|
||||
.angle(kart_aim_direction);
|
||||
|
||||
float diff = normalizeAngle(angle_to_item);
|
||||
|
||||
// The kart is driving at high speed, when the current max speed
|
||||
// is higher than the max speed of the kart (which is caused by
|
||||
@ -1117,14 +1146,14 @@ void SkiddingAI::evaluateItems(const Item *item, float kart_aim_angle,
|
||||
else
|
||||
list = items_to_collect;
|
||||
|
||||
float new_distance = (item->getXYZ() - m_kart->getXYZ()).length2_2d();
|
||||
float new_distance = (item->getXYZ() - m_kart->getXYZ()).length2();
|
||||
|
||||
// This list is usually very short, so use a simple bubble sort
|
||||
list->push_back(item);
|
||||
int i;
|
||||
for(i=(int)list->size()-2; i>=0; i--)
|
||||
{
|
||||
float d = ((*list)[i]->getXYZ() - m_kart->getXYZ()).length2_2d();
|
||||
float d = ((*list)[i]->getXYZ() - m_kart->getXYZ()).length2();
|
||||
if(d<=new_distance)
|
||||
{
|
||||
break;
|
||||
@ -1881,23 +1910,23 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
*last_node = m_next_node_index[m_track_node];
|
||||
const core::vector2df xz = m_kart->getXYZ().toIrrVector2d();
|
||||
|
||||
const Quad &q = QuadGraph::get()->getQuadOfNode(*last_node);
|
||||
const GraphNode &g = QuadGraph::get()->getNode(*last_node);
|
||||
|
||||
// Index of the left and right end of a quad.
|
||||
const unsigned int LEFT_END_POINT = 0;
|
||||
const unsigned int RIGHT_END_POINT = 1;
|
||||
core::line2df left (xz, q[LEFT_END_POINT ].toIrrVector2d());
|
||||
core::line2df right(xz, q[RIGHT_END_POINT].toIrrVector2d());
|
||||
core::line2df left (xz, g[LEFT_END_POINT ].toIrrVector2d());
|
||||
core::line2df right(xz, g[RIGHT_END_POINT].toIrrVector2d());
|
||||
|
||||
#if defined(AI_DEBUG) && defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||
const Vec3 eps1(0,0.5f,0);
|
||||
m_curve[CURVE_LEFT]->clear();
|
||||
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
||||
m_curve[CURVE_LEFT]->addPoint(q[LEFT_END_POINT]+eps1);
|
||||
m_curve[CURVE_LEFT]->addPoint(g[LEFT_END_POINT]+eps1);
|
||||
m_curve[CURVE_LEFT]->addPoint(m_kart->getXYZ()+eps1);
|
||||
m_curve[CURVE_RIGHT]->clear();
|
||||
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
||||
m_curve[CURVE_RIGHT]->addPoint(q[RIGHT_END_POINT]+eps1);
|
||||
m_curve[CURVE_RIGHT]->addPoint(g[RIGHT_END_POINT]+eps1);
|
||||
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
|
||||
#endif
|
||||
#if defined(AI_DEBUG_KART_HEADING) || defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
|
||||
@ -1910,13 +1939,13 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
while(1)
|
||||
{
|
||||
unsigned int next_sector = m_next_node_index[*last_node];
|
||||
const Quad &q_next = QuadGraph::get()->getQuadOfNode(next_sector);
|
||||
const GraphNode &g_next = QuadGraph::get()->getNode(next_sector);
|
||||
// Test if the next left point is to the right of the left
|
||||
// line. If so, a new left line is defined.
|
||||
if(left.getPointOrientation(q_next[LEFT_END_POINT].toIrrVector2d())
|
||||
if(left.getPointOrientation(g_next[LEFT_END_POINT].toIrrVector2d())
|
||||
< 0 )
|
||||
{
|
||||
core::vector2df p = q_next[LEFT_END_POINT].toIrrVector2d();
|
||||
core::vector2df p = g_next[LEFT_END_POINT].toIrrVector2d();
|
||||
// Stop if the new point is to the right of the right line
|
||||
if(right.getPointOrientation(p)<0)
|
||||
break;
|
||||
@ -1932,10 +1961,10 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
|
||||
// Test if new right point is to the left of the right line. If
|
||||
// so, a new right line is defined.
|
||||
if(right.getPointOrientation(q_next[RIGHT_END_POINT].toIrrVector2d())
|
||||
if(right.getPointOrientation(g_next[RIGHT_END_POINT].toIrrVector2d())
|
||||
> 0 )
|
||||
{
|
||||
core::vector2df p = q_next[RIGHT_END_POINT].toIrrVector2d();
|
||||
core::vector2df p = g_next[RIGHT_END_POINT].toIrrVector2d();
|
||||
// Break if new point is to the left of left line
|
||||
if(left.getPointOrientation(p)>0)
|
||||
break;
|
||||
@ -1957,7 +1986,7 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
|
||||
// 0.5f*(left.end.Y+right.end.Y));
|
||||
//*result = ppp;
|
||||
|
||||
*result = QuadGraph::get()->getQuadOfNode(*last_node).getCenter();
|
||||
*result = QuadGraph::get()->getNode(*last_node).getCenter();
|
||||
} // findNonCrashingPointNew
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1994,10 +2023,10 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
target_sector = m_next_node_index[*last_node];
|
||||
|
||||
//direction is a vector from our kart to the sectors we are testing
|
||||
direction = QuadGraph::get()->getQuadOfNode(target_sector).getCenter()
|
||||
direction = QuadGraph::get()->getNode(target_sector).getCenter()
|
||||
- m_kart->getXYZ();
|
||||
|
||||
float len=direction.length_2d();
|
||||
float len=direction.length();
|
||||
unsigned int steps = (unsigned int)( len / m_kart_length );
|
||||
if( steps < 3 ) steps = 3;
|
||||
|
||||
@ -2026,14 +2055,14 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
if ( distance + m_kart_width * 0.5f
|
||||
> QuadGraph::get()->getNode(*last_node).getPathWidth()*0.5f )
|
||||
{
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(*last_node)
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node)
|
||||
.getCenter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
*last_node = target_sector;
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(*last_node).getCenter();
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node).getCenter();
|
||||
} // findNonCrashingPointFixed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2097,16 +2126,16 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
float diff = normalizeAngle(angle1-angle);
|
||||
if(fabsf(diff)>1.5f)
|
||||
{
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(target_sector)
|
||||
.getCenter();
|
||||
*aim_position = QuadGraph::get()->getNode(target_sector)
|
||||
.getCenter();
|
||||
return;
|
||||
}
|
||||
|
||||
//direction is a vector from our kart to the sectors we are testing
|
||||
direction = QuadGraph::get()->getQuadOfNode(target_sector).getCenter()
|
||||
direction = QuadGraph::get()->getNode(target_sector).getCenter()
|
||||
- m_kart->getXYZ();
|
||||
|
||||
float len=direction.length_2d();
|
||||
float len=direction.length();
|
||||
unsigned int steps = (unsigned int)( len / m_kart_length );
|
||||
if( steps < 3 ) steps = 3;
|
||||
|
||||
@ -2135,7 +2164,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
if ( distance + m_kart_width * 0.5f
|
||||
> QuadGraph::get()->getNode(*last_node).getPathWidth() )
|
||||
{
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(*last_node)
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node)
|
||||
.getCenter();
|
||||
return;
|
||||
}
|
||||
@ -2143,7 +2172,7 @@ void SkiddingAI::findNonCrashingPointFixed(Vec3 *aim_position, int *last_node)
|
||||
angle = angle1;
|
||||
*last_node = target_sector;
|
||||
} // for i<100
|
||||
*aim_position = QuadGraph::get()->getQuadOfNode(*last_node).getCenter();
|
||||
*aim_position = QuadGraph::get()->getNode(*last_node).getCenter();
|
||||
} // findNonCrashingPoint
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2154,8 +2183,18 @@ void SkiddingAI::determineTrackDirection()
|
||||
{
|
||||
const QuadGraph *qg = QuadGraph::get();
|
||||
unsigned int succ = m_successor_index[m_track_node];
|
||||
float angle_to_track = qg->getNode(m_track_node).getAngleToSuccessor(succ)
|
||||
- m_kart->getHeading();
|
||||
unsigned int next = qg->getNode(m_track_node).getSuccessor(succ);
|
||||
|
||||
//float angle_to_track = qg->getNode(m_track_node).getAngleToSuccessor(succ)
|
||||
// - m_kart->getHeading();
|
||||
Vec3 track_direction = -qg->getNode(m_track_node).getCenter()
|
||||
+ qg->getNode(next).getCenter();
|
||||
//Vec3 kart_direction = qg->getNode(m_track_node).getCenter() + m_kart->getVelocity();
|
||||
|
||||
float angle_to_track = 0;
|
||||
if (m_kart->getVelocity().length() > 0.0f)
|
||||
angle_to_track = track_direction.angle(m_kart->getVelocity().normalized());
|
||||
|
||||
angle_to_track = normalizeAngle(angle_to_track);
|
||||
|
||||
// In certain circumstances (esp. S curves) it is possible that the
|
||||
@ -2175,8 +2214,6 @@ void SkiddingAI::determineTrackDirection()
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int next = qg->getNode(m_track_node).getSuccessor(succ);
|
||||
|
||||
qg->getNode(next).getDirectionData(m_successor_index[next],
|
||||
&m_current_track_direction,
|
||||
&m_last_direction_node);
|
||||
@ -2237,10 +2274,10 @@ void SkiddingAI::handleCurve()
|
||||
// Pick either the lower left or right point:
|
||||
int index = m_current_track_direction==GraphNode::DIR_LEFT
|
||||
? 0 : 1;
|
||||
float r = (m_curve_center - qg->getQuadOfNode(i)[index]).length();
|
||||
float r = (m_curve_center - qg->getNode(i)[index]).length();
|
||||
if(m_current_curve_radius < r)
|
||||
{
|
||||
last_xyz = qg->getQuadOfNode(i)[index];
|
||||
last_xyz = qg->getNode(i)[index];
|
||||
determineTurnRadius(xyz, tangent, last_xyz,
|
||||
&m_curve_center, &m_current_curve_radius);
|
||||
m_last_direction_node = i;
|
||||
|
@ -66,7 +66,6 @@ namespace irr
|
||||
* stage) identical to the Skidding AI.
|
||||
\ingroup controller
|
||||
*/
|
||||
|
||||
class TestAI : public AIBaseLapController
|
||||
{
|
||||
private:
|
||||
@ -205,13 +204,13 @@ private:
|
||||
void computeNearestKarts();
|
||||
void handleItemCollectionAndAvoidance(Vec3 *aim_point,
|
||||
int last_node);
|
||||
bool handleSelectedItem(float kart_aim_angle, Vec3 *aim_point);
|
||||
bool handleSelectedItem(Vec3 kart_aim_direction, Vec3 *aim_point);
|
||||
bool steerToAvoid(const std::vector<const Item *> &items_to_avoid,
|
||||
const core::line2df &line_to_target,
|
||||
const core::line3df &line_to_target,
|
||||
Vec3 *aim_point);
|
||||
bool hitBadItemWhenAimAt(const Item *item,
|
||||
const std::vector<const Item *> &items_to_avoid);
|
||||
void evaluateItems(const Item *item, float kart_aim_angle,
|
||||
void evaluateItems(const Item *item, Vec3 kart_aim_direction,
|
||||
std::vector<const Item *> *items_to_avoid,
|
||||
std::vector<const Item *> *items_to_collect);
|
||||
|
||||
|
@ -64,6 +64,8 @@
|
||||
#include "physics/physics.hpp"
|
||||
#include "race/history.hpp"
|
||||
#include "tracks/terrain_info.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -1292,7 +1294,7 @@ void Kart::update(float dt)
|
||||
if (QuadGraph::get())
|
||||
{
|
||||
sector = ((LinearWorld*)World::getWorld())->getTrackSector(getWorldKartId()).getCurrentGraphNode();
|
||||
quadNormal = QuadGraph::get()->getQuadOfNode(sector).getNormal();
|
||||
quadNormal = QuadGraph::get()->getNode(sector).getNormal();
|
||||
btQuaternion q = getTrans().getRotation();
|
||||
float roll = quadNormal.angle((Vec3(0, 1, 0).rotate(q.getAxis(), q.getAngle())));
|
||||
|
||||
@ -1374,7 +1376,7 @@ void Kart::update(float dt)
|
||||
// We do this for now because dist_to_sector is not defined
|
||||
float dist_to_sector;
|
||||
if (QuadGraph::get())
|
||||
dist_to_sector = getXYZ().distance(QuadGraph::get()->getQuadOfNode(sector).getCenter());
|
||||
dist_to_sector = getXYZ().distance(QuadGraph::get()->getNode(sector).getCenter());
|
||||
else
|
||||
dist_to_sector = 0;
|
||||
|
||||
@ -2421,7 +2423,7 @@ void Kart::updateSliding()
|
||||
if (QuadGraph::get())
|
||||
{
|
||||
int sector = ((LinearWorld*)World::getWorld())->getTrackSector(getWorldKartId()).getCurrentGraphNode();
|
||||
Vec3 quadNormal = QuadGraph::get()->getQuadOfNode(sector).getNormal();
|
||||
Vec3 quadNormal = QuadGraph::get()->getNode(sector).getNormal();
|
||||
Vec3 kart_up = m.getColumn(1);
|
||||
distanceFromUp = kart_up.dot(quadNormal);
|
||||
}
|
||||
|
@ -26,9 +26,12 @@
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/controller/controller.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "race/history.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/track_sector.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -644,8 +647,8 @@ unsigned int LinearWorld::getRescuePositionIndex(AbstractKart *kart)
|
||||
// ------------------------------------------------------------------------
|
||||
btTransform LinearWorld::getRescueTransform(unsigned int index) const
|
||||
{
|
||||
const Vec3 &xyz = QuadGraph::get()->getQuadOfNode(index).getCenter();
|
||||
const Vec3 &normal = QuadGraph::get()->getQuadOfNode(index).getNormal();
|
||||
const Vec3 &xyz = QuadGraph::get()->getNode(index).getCenter();
|
||||
const Vec3 &normal = QuadGraph::get()->getNode(index).getNormal();
|
||||
btTransform pos;
|
||||
pos.setOrigin(xyz);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
using namespace irr;
|
||||
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "graphics/mesh_tools.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
|
@ -22,8 +22,10 @@
|
||||
#include <string>
|
||||
#include <angelscript.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
#include "scriptengine/script_utils.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
class TrackObjectPresentation;
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2015 Joerg Henrichs
|
||||
@ -223,7 +224,7 @@ void BattleGraph::findItemsOnGraphNodes()
|
||||
|
||||
for (unsigned int j = 0; j < this->getNumNodes(); ++j)
|
||||
{
|
||||
if (getQuadOfNode(j).pointInQuad(xyz, false))
|
||||
if (getQuadOfNode(j).pointInside(xyz, false))
|
||||
polygon = j;
|
||||
}
|
||||
|
||||
@ -248,7 +249,7 @@ int BattleGraph::pointToNode(const int cur_node,
|
||||
for (unsigned int node = 0; node < this->getNumNodes(); node++)
|
||||
{
|
||||
const Quad& quad = this->getQuadOfNode(node);
|
||||
if (quad.pointInQuad(cur_point, ignore_vertical))
|
||||
if (quad.pointInside(cur_point, ignore_vertical))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
@ -258,7 +259,7 @@ int BattleGraph::pointToNode(const int cur_node,
|
||||
{
|
||||
// Check if the point is still on the same node
|
||||
const Quad& cur_quad = this->getQuadOfNode(cur_node);
|
||||
if (cur_quad.pointInQuad(cur_point, ignore_vertical)) return cur_node;
|
||||
if (cur_quad.pointInside(cur_point, ignore_vertical)) return cur_node;
|
||||
|
||||
// If not then check all nearby quads (8 quads)
|
||||
// Skip the same node
|
||||
@ -267,7 +268,7 @@ int BattleGraph::pointToNode(const int cur_node,
|
||||
{
|
||||
const int test_node = m_nearby_quads[cur_node][i];
|
||||
const Quad& quad = this->getQuadOfNode(test_node);
|
||||
if (quad.pointInQuad(cur_point, ignore_vertical))
|
||||
if (quad.pointInside(cur_point, ignore_vertical))
|
||||
{
|
||||
return test_node;
|
||||
}
|
||||
@ -465,9 +466,3 @@ void BattleGraph::set3DVerticesOfGraph(int i, video::S3DVertex *v,
|
||||
{
|
||||
NavMesh::get()->getQuad(i).getVertices(v, color);
|
||||
} // set3DVerticesOfGraph
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
const bool BattleGraph::isNodeInvisible(int n) const
|
||||
{
|
||||
return NavMesh::get()->getQuad(n).isInvisible();
|
||||
} // isNodeInvisible
|
||||
|
@ -76,7 +76,7 @@ private:
|
||||
virtual void getGraphBoundingBox(Vec3 *min, Vec3 *max) const
|
||||
{ NavMesh::get()->getBoundingBox(min, max); }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual const bool isNodeInvisible(int n) const;
|
||||
virtual const bool isNodeInvisible(int n) const { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual const bool hasLapLine() const
|
||||
{ return false; }
|
||||
|
@ -28,7 +28,8 @@
|
||||
#include "tracks/check_lap.hpp"
|
||||
#include "tracks/check_line.hpp"
|
||||
#include "tracks/check_structure.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
CheckManager *CheckManager::m_check_manager = NULL;
|
||||
|
||||
|
@ -22,51 +22,44 @@
|
||||
#include "io/xml_node.hpp"
|
||||
#include "matrix4.h"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/quad_set.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor. Saves the quad index which belongs to this graph node.
|
||||
* \param index Index of the quad to use for this node (in QuadSet).
|
||||
*/
|
||||
GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index)
|
||||
GraphNode::GraphNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||
const Vec3 &p3, const Vec3 &normal,
|
||||
unsigned int node_index, bool invisible,
|
||||
bool ai_ignore)
|
||||
:Quad(p0, p1, p2, p3)
|
||||
{
|
||||
if (quad_index >= QuadSet::get()->getNumberOfQuads())
|
||||
Log::fatal("GraphNode", "No driveline found, or empty driveline.");
|
||||
|
||||
m_quad_index = quad_index;
|
||||
m_invisible = invisible;
|
||||
m_ai_ignore = ai_ignore;
|
||||
m_normal = normal;
|
||||
m_node_index = node_index;
|
||||
m_distance_from_start = -1.0f;
|
||||
|
||||
const Quad &quad = QuadSet::get()->getQuad(m_quad_index);
|
||||
// The following values should depend on the actual orientation
|
||||
// of the quad. ATM we always assume that indices 0,1 are the lower end,
|
||||
// and 2,3 are the upper end (or the reverse if reverse mode is selected).
|
||||
// The width is the average width at the beginning and at the end.
|
||||
m_right_unit_vector = ( quad[0]-quad[1]
|
||||
+quad[3]-quad[2]) * 0.5f;
|
||||
m_right_unit_vector = ( m_p[0]-m_p[1]
|
||||
+m_p[3]-m_p[2]) * 0.5f;
|
||||
m_right_unit_vector.normalize();
|
||||
|
||||
m_width = ( (quad[1]-quad[0]).length()
|
||||
+ (quad[3]-quad[2]).length() ) * 0.5f;
|
||||
m_width = ( (m_p[1]-m_p[0]).length()
|
||||
+ (m_p[3]-m_p[2]).length() ) * 0.5f;
|
||||
|
||||
if(QuadGraph::get()->isReverse())
|
||||
{
|
||||
m_lower_center = (quad[2]+quad[3]) * 0.5f;
|
||||
m_upper_center = (quad[0]+quad[1]) * 0.5f;
|
||||
m_lower_center = (m_p[2]+m_p[3]) * 0.5f;
|
||||
m_upper_center = (m_p[0]+m_p[1]) * 0.5f;
|
||||
m_right_unit_vector *= -1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lower_center = (quad[0]+quad[1]) * 0.5f;
|
||||
m_upper_center = (quad[2]+quad[3]) * 0.5f;
|
||||
m_lower_center = (m_p[0]+m_p[1]) * 0.5f;
|
||||
m_upper_center = (m_p[2]+m_p[3]) * 0.5f;
|
||||
}
|
||||
m_line = core::line3df(m_lower_center.toIrrVector(),
|
||||
m_upper_center.toIrrVector());
|
||||
// Only this 2d point is needed later
|
||||
m_lower_center_2d = core::vector2df(m_lower_center.getX(),
|
||||
m_lower_center.getZ() );
|
||||
|
||||
|
||||
} // GraphNode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -78,28 +71,25 @@ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index)
|
||||
void GraphNode::addSuccessor(unsigned int to)
|
||||
{
|
||||
m_successor_nodes.push_back(to);
|
||||
// m_quad_index is the quad index
|
||||
const Quad &this_quad = QuadSet::get()->getQuad(m_quad_index);
|
||||
// to is the graph node
|
||||
GraphNode &gn = QuadGraph::get()->getNode(to);
|
||||
const Quad &next_quad = QuadGraph::get()->getQuadOfNode(to);
|
||||
GraphNode &gn_to = QuadGraph::get()->getNode(to);
|
||||
|
||||
// Note that the first predecessor is (because of the way the quad graph
|
||||
// is exported) the most 'natural' one, i.e. the one on the main
|
||||
// driveline.
|
||||
gn.m_predecessor_nodes.push_back(m_node_index);
|
||||
gn_to.m_predecessor_nodes.push_back(m_node_index);
|
||||
|
||||
Vec3 d = m_lower_center - QuadGraph::get()->getNode(to).m_lower_center;
|
||||
Vec3 d = m_lower_center - gn_to.m_lower_center;
|
||||
m_distance_to_next.push_back(d.length());
|
||||
|
||||
Vec3 diff = next_quad.getCenter() - this_quad.getCenter();
|
||||
|
||||
|
||||
Vec3 diff = gn_to.getCenter() - getCenter();
|
||||
|
||||
core::CMatrix4<float> m;
|
||||
m.buildRotateFromTo(this_quad.getNormal().toIrrVector(),
|
||||
m.buildRotateFromTo(getNormal().toIrrVector(),
|
||||
Vec3(0, 1, 0).toIrrVector());
|
||||
core::vector3df diffRotated;
|
||||
m.rotateVect(diffRotated, diff.toIrrVector());
|
||||
|
||||
|
||||
m_angle_to_next.push_back(atan2(diffRotated.X, diffRotated.Z));
|
||||
|
||||
} // addSuccessor
|
||||
@ -183,197 +173,17 @@ void GraphNode::setDirectionData(unsigned int successor, DirectionType dir,
|
||||
} // setDirectionData
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the distance a point has from this quad in forward and sidewards
|
||||
* direction, i.e. how far forwards the point is from the beginning of the
|
||||
* quad, and how far to the side from the line connecting the center points
|
||||
* is it.
|
||||
* \param xyz The coordinates of the point.
|
||||
* \param result The X coordinate contains the sidewards distance, the
|
||||
* Z coordinate the forward distance.
|
||||
*/
|
||||
void GraphNode::getDistances(const Vec3 &xyz, Vec3 *result)
|
||||
{
|
||||
core::vector3df xyz_irr = xyz.toIrrVector();
|
||||
core::vector3df closest = m_line.getClosestPoint(xyz.toIrrVector());
|
||||
core::vector3df normal = getQuad().getNormal().toIrrVector();
|
||||
|
||||
if(xyz.sideofPlane(closest, closest+normal, m_line.end)<0)
|
||||
result->setX( (closest-xyz_irr).getLength()); // to the right
|
||||
else
|
||||
result->setX(-(closest-xyz_irr).getLength()); // to the left
|
||||
result->setZ( m_distance_from_start +
|
||||
(closest-m_lower_center.toIrrVector()).getLength());
|
||||
} // getDistances
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the distance a point has from an unrolled quad in forward and sidewards
|
||||
* direction, i.e. how far forwards the point is from the beginning of the
|
||||
* quad, and how far to the side from the line connecting the center points
|
||||
* is it.
|
||||
* \param xyz The coordinates of the point.
|
||||
* \param fork_number The fork on which the unrolled quad lies.
|
||||
* \param quad_idx The index of the unrolled quad to find distances from.
|
||||
* \param result The X coordinate contains the sidewards distance, the
|
||||
* Z coordinate the forward distance.
|
||||
*/
|
||||
void GraphNode::getDistancesUnrolled(const Vec3 &xyz, const int fork_number, unsigned int quad_idx, Vec3 *result)
|
||||
{
|
||||
|
||||
const Quad& unrolled = getUnrolledQuad(fork_number,quad_idx);
|
||||
Vec3 upper_center, lower_center;
|
||||
if (!QuadGraph::get()->isReverse())
|
||||
{
|
||||
upper_center = 0.5f*(unrolled[2] + unrolled[3]),
|
||||
lower_center = 0.5f*(unrolled[0] + unrolled[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
upper_center = 0.5f*(unrolled[0] + unrolled[1]),
|
||||
lower_center = 0.5f*(unrolled[2] + unrolled[3]);
|
||||
}
|
||||
// center_line is from A to B, or lower_center to upper_center
|
||||
core::vector3df A = lower_center.toIrrVector(), B = upper_center.toIrrVector();
|
||||
result->setX(((B - A).crossProduct(xyz.toIrrVector() - A)).getLength() / (B - A).getLength());
|
||||
|
||||
result->setZ(QuadGraph::get()->getNode((m_node_index + quad_idx)%QuadGraph::get()->getNumNodes()).getDistanceFromStart()
|
||||
+ (xyz - lower_center).length());
|
||||
} // getDistancesUnrolled
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the square of the distance between the given point and any point
|
||||
* on the 'centre' line, i.e. the finite line from the middle point of the
|
||||
* lower end of the quad node to the middle point of the upper end of the
|
||||
* quad which belongs to this graph node. The value is computed in 2d only!
|
||||
* \param xyz The point for which the distance to the line is computed.
|
||||
*/
|
||||
float GraphNode::getDistance2FromPoint(const Vec3 &xyz)
|
||||
{
|
||||
core::vector3df closest = m_line.getClosestPoint(xyz.toIrrVector());
|
||||
return (closest-xyz.toIrrVector()).getLengthSQ();
|
||||
} // getDistance2FromPoint
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void GraphNode::setChecklineRequirements(int latest_checkline)
|
||||
{
|
||||
m_checkline_requirements.push_back(latest_checkline);
|
||||
}
|
||||
|
||||
|
||||
const Vec3 GraphNode::getPointTransformedToFlatQuad(Vec3 xyz)
|
||||
{
|
||||
Quad thisQuad = getQuad();
|
||||
core::CMatrix4<float> m;
|
||||
m.buildRotateFromTo(thisQuad.getNormal().toIrrVector(), core::vector3df(0, 1, 0));
|
||||
|
||||
core::vector3df result;
|
||||
// Translate the input point into the Quads frame of reference, then rotate
|
||||
m.rotateVect(result, (xyz - thisQuad.getCenter()).toIrrVector());
|
||||
|
||||
return (Vec3)result;
|
||||
}
|
||||
} // setChecklineRequirements
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** This functions builds unrolled quads for this node. This takes into account
|
||||
* if there is a fork in coming up. In this case there will be two sets of
|
||||
* unrolled quads for this node. One for each fork.
|
||||
* \param unroll_quad_count The length of the unrolled set of quads per node.
|
||||
/** Returns true if the index-successor of this node is one that the AI
|
||||
* is allowed to use.
|
||||
* \param index Index of the successor.
|
||||
*/
|
||||
void GraphNode::buildUnrolledQuads(unsigned int unroll_quad_count)
|
||||
bool GraphNode::ignoreSuccessorForAI(unsigned int i) const
|
||||
{
|
||||
m_unrolled_quads.clear();
|
||||
|
||||
unsigned int numberOfForks = 1;
|
||||
GraphNode* currentNode = this;
|
||||
for (unsigned i = 0; i < unroll_quad_count+1; i++)
|
||||
{
|
||||
unsigned int successorCount = currentNode->getNumberOfSuccessors();
|
||||
if (successorCount >= 2)
|
||||
{
|
||||
numberOfForks = successorCount;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentNode = &QuadGraph::get()->getNode(currentNode->getSuccessor(0));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
m_unrolled_quads.resize(numberOfForks);
|
||||
|
||||
for (unsigned i = 0; i < numberOfForks; i++)
|
||||
{
|
||||
Quad thisQuad = getQuad();
|
||||
m_unrolled_quads[i].push_back(thisQuad);
|
||||
GraphNode& next = QuadGraph::get()->getNode(getSuccessor(i%getNumberOfSuccessors()));
|
||||
addUnrolledQuad(next , i , unroll_quad_count);
|
||||
}
|
||||
} // buildUnrolledQuads
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** This function is called recursively to build one set of unrolled quads. Each
|
||||
* call adds one unrolled quad to the existing set.
|
||||
* \param unroll_quad_count The length of the unrolled set of quads per node.
|
||||
*/
|
||||
void GraphNode::addUnrolledQuad(const GraphNode& next_node, int fork_number, int k)
|
||||
{
|
||||
if (k == 0) return;
|
||||
|
||||
Quad next_quad = next_node.getQuad();
|
||||
Quad next_quad_to_push = next_quad.getFlattenedQuad();
|
||||
Quad last_pushed_quad = m_unrolled_quads[fork_number].back();
|
||||
|
||||
|
||||
core::CMatrix4<float> m;
|
||||
core::vector3df new_points[4];
|
||||
|
||||
// First rotate the next_quad_to_push so that it aligns with last quad
|
||||
// in the vector of unrolled quads
|
||||
m.buildRotateFromTo(next_quad_to_push.getNormal().toIrrVector(),
|
||||
last_pushed_quad.getNormal().toIrrVector());
|
||||
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
m.rotateVect(new_points[i], next_quad_to_push[i].toIrrVector());
|
||||
|
||||
Vec3 endEdge, beginEdge;
|
||||
if (!QuadGraph::get()->isReverse())
|
||||
{
|
||||
endEdge = (last_pushed_quad[2] - last_pushed_quad[3]);
|
||||
beginEdge = (new_points[1] - new_points[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
endEdge = (last_pushed_quad[1] - last_pushed_quad[0]);
|
||||
beginEdge = (new_points[2] - new_points[3]);
|
||||
}
|
||||
|
||||
m.buildRotateFromTo(beginEdge.toIrrVector(), endEdge.toIrrVector());
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
m.rotateVect(new_points[i]);
|
||||
|
||||
// Next translate the new quad to be pushed to the correct position infront
|
||||
// of the last quad in the vector of unrolled quads
|
||||
Vec3 lower_center, upper_center;
|
||||
if (!QuadGraph::get()->isReverse())
|
||||
{
|
||||
lower_center = 0.5f*(new_points[0] + new_points[1]);
|
||||
upper_center = 0.5f*(last_pushed_quad[2] + last_pushed_quad[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
lower_center = 0.5f*(new_points[2] + new_points[3]);
|
||||
upper_center = 0.5f*(last_pushed_quad[0] + last_pushed_quad[1]);
|
||||
}
|
||||
m.setTranslation((upper_center-lower_center).toIrrVector());
|
||||
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
m.translateVect(new_points[i]);
|
||||
|
||||
// Push the quad into the vector of unrolled quads
|
||||
m_unrolled_quads[fork_number].push_back(Quad(new_points[0], new_points[1], new_points[2], new_points[3]));
|
||||
k = k - 1;
|
||||
// Recurisvely build the vector of unrolled quads till k reduces to 0
|
||||
GraphNode& next = QuadGraph::get()->getNode(next_node.getSuccessor(fork_number%next_node.getNumberOfSuccessors()));
|
||||
addUnrolledQuad(next, fork_number, k);
|
||||
} // addUnrolledQuad
|
||||
return QuadGraph::get()->getNode(m_successor_nodes[i]).letAIIgnore();
|
||||
} // ignoreSuccessorForAI
|
||||
|
@ -21,22 +21,14 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <vector2d.h>
|
||||
#include <dimension2d.h>
|
||||
#include <line2d.h>
|
||||
|
||||
#include "tracks/quad.hpp"
|
||||
#include "tracks/quad_set.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
class QuadGraph;
|
||||
|
||||
/**
|
||||
* \brief This class stores a node of the graph, i.e. a list of successor
|
||||
* edges.
|
||||
* edges, it can either be 2d or 3d.
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class GraphNode
|
||||
class GraphNode : public Quad
|
||||
{
|
||||
public:
|
||||
/** To indiciate in which direction the track is going:
|
||||
@ -44,12 +36,25 @@ public:
|
||||
* AI only. */
|
||||
enum DirectionType {DIR_STRAIGHT, DIR_LEFT, DIR_RIGHT,
|
||||
DIR_UNDEFINED};
|
||||
protected:
|
||||
/** Lower center point of the graph node. */
|
||||
Vec3 m_lower_center;
|
||||
|
||||
/** Upper center point of the graph node. */
|
||||
Vec3 m_upper_center;
|
||||
|
||||
/** Distance from the start to the beginning of the graph node. */
|
||||
float m_distance_from_start;
|
||||
|
||||
private:
|
||||
/** Index of this node in the set of quads. Several graph nodes can use
|
||||
* the same quad, meaning it is possible to use a quad more than once,
|
||||
* e.g. a figure 8 like track. */
|
||||
unsigned int m_quad_index;
|
||||
/** Normal of the graph node */
|
||||
Vec3 m_normal;
|
||||
|
||||
/** Set to true if this graph node should not be shown in the minimap. */
|
||||
bool m_invisible;
|
||||
|
||||
/** Set to true if this graph node should not be used by the AI. */
|
||||
bool m_ai_ignore;
|
||||
|
||||
/** Index of this graph node. */
|
||||
unsigned int m_node_index;
|
||||
@ -66,83 +71,59 @@ private:
|
||||
/** The angle of the line from this node to each neighbour. */
|
||||
std::vector<float> m_angle_to_next;
|
||||
|
||||
/** Distance from the start to the beginning of this quad. */
|
||||
float m_distance_from_start;
|
||||
|
||||
/** Width of the track, which is the average of the width at the
|
||||
* beginning and at the end. FIXME: for now the width is independent
|
||||
* of the orientation (e.g. a quad used more than once might once
|
||||
* be used from top to bottom, one from left to right, so it should
|
||||
* have a different width then). */
|
||||
float m_width;
|
||||
* beginning and at the end. */
|
||||
float m_width;
|
||||
|
||||
/** The center point of the lower two points (e.g. points 0 and 1).
|
||||
* This saves some computations in getDistances later. Only the
|
||||
* start point is needed, and only in 2d. */
|
||||
core::vector2df m_lower_center_2d;
|
||||
/** A vector from the center of the quad to the right edge. */
|
||||
Vec3 m_center_to_right;
|
||||
|
||||
/** Lower center point of the graph node. */
|
||||
Vec3 m_lower_center;
|
||||
typedef std::vector<int> PathToNodeVector;
|
||||
/** This vector is only used if the graph node has more than one
|
||||
* successor. In this case m_path_to_node[X] will contain the index
|
||||
* of the successor to use in order to reach graph node X for this
|
||||
* graph nodes. */
|
||||
PathToNodeVector m_path_to_node;
|
||||
|
||||
/** Upper center point of the graph node. */
|
||||
Vec3 m_upper_center;
|
||||
/** The direction for each of the successors. */
|
||||
std::vector<DirectionType> m_direction;
|
||||
|
||||
/** A vector from the center of the quad to the right edge. */
|
||||
Vec3 m_center_to_right;
|
||||
/** Stores for each successor the index of the last graph node that
|
||||
* has the same direction (i.e. if index 0 curves left, this vector
|
||||
* will store the index of the last graph node that is still turning
|
||||
* left. */
|
||||
std::vector<unsigned int> m_last_index_same_direction;
|
||||
|
||||
/** Line between lower and upper center, saves computation in
|
||||
* getDistanceFromLine() later. The line is 2d only since otherwise
|
||||
* taller karts would have a larger distance from the center. It also
|
||||
* saves computation, and it is only needed to determine the distance
|
||||
* from the center of the drivelines anyway. */
|
||||
core::line3df m_line;
|
||||
|
||||
typedef std::vector<int> PathToNodeVector;
|
||||
/** This vector is only used if the graph node has more than one
|
||||
* successor. In this case m_path_to_node[X] will contain the index
|
||||
* of the successor to use in order to reach graph node X for this
|
||||
* graph nodes. */
|
||||
PathToNodeVector m_path_to_node;
|
||||
|
||||
/** The direction for each of the successors. */
|
||||
std::vector<DirectionType> m_direction;
|
||||
|
||||
/** Stores for each successor the index of the last graph node that
|
||||
* has the same direction (i.e. if index 0 curves left, this vector
|
||||
* will store the index of the last graph node that is still turning
|
||||
* left. */
|
||||
std::vector<unsigned int> m_last_index_same_direction;
|
||||
|
||||
/** A unit vector pointing from the center to the right side, orthogonal
|
||||
* to the driving direction. */
|
||||
Vec3 m_right_unit_vector;
|
||||
/** A unit vector pointing from the center to the right side, orthogonal
|
||||
* to the driving direction. */
|
||||
Vec3 m_right_unit_vector;
|
||||
|
||||
/**
|
||||
* Sets of checklines you should have activated when you are driving on
|
||||
* this node (there is a possibility of more than one set because of
|
||||
* alternate ways)
|
||||
*/
|
||||
std::vector< int > m_checkline_requirements;
|
||||
* Sets of checklines you should have activated when you are driving on
|
||||
* this node (there is a possibility of more than one set because of
|
||||
* alternate ways)
|
||||
*/
|
||||
std::vector< int > m_checkline_requirements;
|
||||
|
||||
std::vector< std::vector<Quad> >m_unrolled_quads;
|
||||
|
||||
void markAllSuccessorsToUse(unsigned int n,
|
||||
void markAllSuccessorsToUse(unsigned int n,
|
||||
PathToNodeVector *m_path_to_node);
|
||||
|
||||
void addUnrolledQuad(const GraphNode& next_node, int fork_number, int k);
|
||||
|
||||
public:
|
||||
GraphNode(unsigned int quad_index, unsigned int node_index);
|
||||
GraphNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||
const Vec3 &p3, const Vec3 &normal,
|
||||
unsigned int node_index, bool invisible,
|
||||
bool ai_ignore);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual ~GraphNode() {}
|
||||
// ------------------------------------------------------------------------
|
||||
void addSuccessor (unsigned int to);
|
||||
void getDistances(const Vec3 &xyz, Vec3 *result);
|
||||
void getDistancesUnrolled(const Vec3 &xyz, const int fork_number,
|
||||
unsigned int quad_idx, Vec3 *result);
|
||||
float getDistance2FromPoint(const Vec3 &xyz);
|
||||
// ------------------------------------------------------------------------
|
||||
void setupPathsToNode();
|
||||
// ------------------------------------------------------------------------
|
||||
void setChecklineRequirements(int latest_checkline);
|
||||
// ------------------------------------------------------------------------
|
||||
void setDirectionData(unsigned int successor, DirectionType dir,
|
||||
unsigned int last_node_index);
|
||||
void buildUnrolledQuads(unsigned int unroll_quad_count);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of successors. */
|
||||
unsigned int getNumberOfSuccessors() const
|
||||
@ -161,23 +142,15 @@ public:
|
||||
*/
|
||||
int getPredecessor(unsigned int i) const {return m_predecessor_nodes[i]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the quad_index in the quad_set of this node. */
|
||||
int getQuadIndex() const { return m_quad_index; }
|
||||
/** Returns the node index of this node. */
|
||||
unsigned int getNodeIndex() const { return m_node_index; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the quad of this graph node. */
|
||||
const Quad& getQuad() const {return QuadSet::get()->getQuad(m_quad_index);}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the i-th. point of a quad. ATM this just returns the vertices
|
||||
* from the quads, but if necessary this method will also consider
|
||||
* rotated quads. So index 0 will always be lower left point, then
|
||||
* counterclockwise. */
|
||||
const Vec3& operator[](int i) const
|
||||
{return QuadSet::get()->getQuad(m_quad_index)[i];}
|
||||
/** Returns the normal of this quad */
|
||||
const Vec3& getNormal() const { return m_normal; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the distance to the j-th. successor. */
|
||||
float getDistanceToSuccessor(unsigned int j) const
|
||||
{ return m_distance_to_next[j]; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the angle from this node to the j-th. successor. */
|
||||
float getAngleToSuccessor(unsigned int j) const
|
||||
@ -199,21 +172,11 @@ public:
|
||||
/** Returns the center point of the upper edge of this graph node. */
|
||||
const Vec3& getUpperCenter() const {return m_upper_center;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the center point of this graph node. */
|
||||
const Vec3 getCenter() const
|
||||
{return (m_upper_center + m_lower_center) / 2.0f;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the length of the quad of this node. */
|
||||
float getNodeLength() const
|
||||
{return (m_lower_center-m_upper_center).length();}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if the index-successor of this node is one that the AI
|
||||
* is allowed to use.
|
||||
* \param index Index of the successor. */
|
||||
bool ignoreSuccessorForAI(unsigned int i) const
|
||||
{
|
||||
return QuadSet::get()->getQuad(m_successor_nodes[i]).letAIIgnore();
|
||||
};
|
||||
bool ignoreSuccessorForAI(unsigned int i) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns which successor node to use in order to be able to reach the
|
||||
* given node n.
|
||||
@ -239,10 +202,18 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a unit vector pointing to the right side of the quad. */
|
||||
const Vec3 &getRightUnitVector() const { return m_right_unit_vector; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true of this node is invisible, i.e. not to be shown in
|
||||
* the minimap. */
|
||||
bool isInvisible() const { return m_invisible; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** True if this node should be ignored by the AI. */
|
||||
bool letAIIgnore() const { return m_ai_ignore; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getDistance2FromPoint(const Vec3 &xyz) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void getDistances(const Vec3 &xyz, Vec3 *result) = 0;
|
||||
|
||||
const Vec3 getPointTransformedToFlatQuad(Vec3 xyz);
|
||||
|
||||
const Quad& getUnrolledQuad(int succ_idx, int i) const { return m_unrolled_quads[succ_idx][i]; }
|
||||
}; // GraphNode
|
||||
|
||||
#endif
|
||||
|
@ -95,6 +95,14 @@ NavMesh::NavMesh(const std::string &filename)
|
||||
m_quads.push_back(new Quad(
|
||||
all_vertices[quad_index[0]], all_vertices[quad_index[1]],
|
||||
all_vertices[quad_index[2]], all_vertices[quad_index[3]]));
|
||||
|
||||
/*(AbstractNode* tn = createNode(
|
||||
all_vertices[quad_index[0]], all_vertices[quad_index[1]],
|
||||
all_vertices[quad_index[2]], all_vertices[quad_index[3]],false,false);
|
||||
|
||||
Vec3 pp(0,0,0);
|
||||
tn->pointInNode(pp);*/
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
69
src/tracks/node_2d.cpp
Normal file
69
src/tracks/node_2d.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2016 SuperTuxKart-Team
|
||||
//
|
||||
// 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 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "tracks/node_2d.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Node2D::Node2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore)
|
||||
: GraphNode(p0, p1, p2, p3, normal, node_index, invisible, ai_ignore)
|
||||
{
|
||||
m_line = core::line2df(m_upper_center.getX(), m_upper_center.getZ(),
|
||||
m_lower_center.getX(), m_lower_center.getZ());
|
||||
|
||||
// Only this 2d point is needed later
|
||||
m_lower_center_2d = core::vector2df(m_lower_center.getX(),
|
||||
m_lower_center.getZ());
|
||||
} // Node2D
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the distance a point has from this node in forward and sidewards
|
||||
* direction, i.e. how far forwards the point is from the beginning of the
|
||||
* node, and how far to the side from the line connecting the center points
|
||||
* is it. All these computations are done in 2D only.
|
||||
* \param xyz The coordinates of the point.
|
||||
* \param result The X coordinate contains the sidewards distance, the
|
||||
* Z coordinate the forward distance.
|
||||
*/
|
||||
void Node2D::getDistances(const Vec3 &xyz, Vec3 *result)
|
||||
{
|
||||
core::vector2df xyz2d(xyz.getX(), xyz.getZ());
|
||||
core::vector2df closest = m_line.getClosestPoint(xyz2d);
|
||||
if (m_line.getPointOrientation(xyz2d) > 0)
|
||||
result->setX( (closest-xyz2d).getLength()); // to the right
|
||||
else
|
||||
result->setX(-(closest-xyz2d).getLength()); // to the left
|
||||
|
||||
result->setZ(m_distance_from_start +
|
||||
(closest-m_lower_center_2d).getLength());
|
||||
} // getDistances
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the square of the distance between the given point and any point
|
||||
* on the 'centre' line, i.e. the finite line from the middle point of the
|
||||
* lower end of the node to the middle point of the upper end of the node
|
||||
* which belongs to this graph node. The value is computed in 2d only!
|
||||
* \param xyz The point for which the distance to the line is computed.
|
||||
*/
|
||||
float Node2D::getDistance2FromPoint(const Vec3 &xyz)
|
||||
{
|
||||
core::vector2df xyz2d(xyz.getX(), xyz.getZ());
|
||||
core::vector2df closest = m_line.getClosestPoint(xyz2d);
|
||||
return (closest-xyz2d).getLengthSQ();
|
||||
} // getDistance2FromPoint
|
55
src/tracks/node_2d.hpp
Normal file
55
src/tracks/node_2d.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2016 SuperTuxKart-Team
|
||||
//
|
||||
// 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 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_NODE_2D_HPP
|
||||
#define HEADER_NODE_2D_HPP
|
||||
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
#include <line2d.h>
|
||||
|
||||
/**
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class Node2D : public GraphNode
|
||||
{
|
||||
private:
|
||||
/** The center point of the lower two points (e.g. points 0 and 1).
|
||||
* This saves some computations in getDistances later. Only the
|
||||
* start point is needed, and only in 2d. */
|
||||
core::vector2df m_lower_center_2d;
|
||||
|
||||
/** Line between lower and upper center, saves computation in
|
||||
* getDistance() later. The line is 2d only since otherwise taller karts
|
||||
* would have a larger distance from the center. It also saves
|
||||
* computation, and it is only needed to determine the distance from the
|
||||
* center of the drivelines anyway. */
|
||||
core::line2df m_line;
|
||||
|
||||
public:
|
||||
Node2D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void getDistances(const Vec3 &xyz, Vec3 *result) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getDistance2FromPoint(const Vec3 &xyz) OVERRIDE;
|
||||
|
||||
};
|
||||
#endif
|
94
src/tracks/node_3d.cpp
Normal file
94
src/tracks/node_3d.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2016 SuperTuxKart-Team
|
||||
//
|
||||
// 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 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "tracks/node_3d.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Node3D::Node3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore)
|
||||
: GraphNode(p0, p1, p2, p3, normal, node_index, invisible, ai_ignore)
|
||||
{
|
||||
// Compute the node bounding box used for pointInNode
|
||||
Vec3 box_corners[8];
|
||||
float box_high = 5.0f;
|
||||
float box_low = 1.0f;
|
||||
box_corners[0] = m_p[0] + box_high * normal;
|
||||
box_corners[1] = m_p[1] + box_high * normal;
|
||||
box_corners[2] = m_p[2] + box_high * normal;
|
||||
box_corners[3] = m_p[3] + box_high * normal;
|
||||
box_corners[4] = m_p[0] - box_low * normal;
|
||||
box_corners[5] = m_p[1] - box_low * normal;
|
||||
box_corners[6] = m_p[2] - box_low * normal;
|
||||
box_corners[7] = m_p[3] - box_low * normal;
|
||||
|
||||
Vec3 box_faces[6][4] =
|
||||
{
|
||||
{ box_corners[0], box_corners[1], box_corners[2], box_corners[3] },
|
||||
{ box_corners[3], box_corners[2], box_corners[6], box_corners[7] },
|
||||
{ box_corners[7], box_corners[6], box_corners[5], box_corners[4] },
|
||||
{ box_corners[1], box_corners[0], box_corners[4], box_corners[5] },
|
||||
{ box_corners[4], box_corners[0], box_corners[3], box_corners[7] },
|
||||
{ box_corners[1], box_corners[5], box_corners[6], box_corners[2] }
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < 6 ; i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < 4; j++)
|
||||
m_box_faces[i][j] = box_faces[i][j];
|
||||
}
|
||||
|
||||
m_line = core::line3df(m_lower_center.toIrrVector(),
|
||||
m_upper_center.toIrrVector());
|
||||
} // Node3D
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the distance a point has from this node in forward and sidewards
|
||||
* direction, i.e. how far forwards the point is from the beginning of the
|
||||
* node, and how far to the side from the line connecting the center points
|
||||
* is it.
|
||||
* \param xyz The coordinates of the point.
|
||||
* \param result The X coordinate contains the sidewards distance, the
|
||||
* Z coordinate the forward distance.
|
||||
*/
|
||||
void Node3D::getDistances(const Vec3 &xyz, Vec3 *result)
|
||||
{
|
||||
core::vector3df xyz_irr = xyz.toIrrVector();
|
||||
core::vector3df closest = m_line.getClosestPoint(xyz.toIrrVector());
|
||||
core::vector3df normal = getNormal().toIrrVector();
|
||||
|
||||
if (xyz.sideofPlane(closest, closest + normal, m_line.end) < 0)
|
||||
result->setX( (closest-xyz_irr).getLength()); // to the right
|
||||
else
|
||||
result->setX(-(closest-xyz_irr).getLength()); // to the left
|
||||
result->setZ(m_distance_from_start +
|
||||
(closest-m_lower_center.toIrrVector()).getLength());
|
||||
} // getDistances
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the square of the distance between the given point and any point
|
||||
* on the 'centre' line, i.e. the finite line from the middle point of the
|
||||
* lower end of the node to the middle point of the upper end of the node
|
||||
* which belongs to this node.
|
||||
* \param xyz The point for which the distance to the line is computed.
|
||||
*/
|
||||
float Node3D::getDistance2FromPoint(const Vec3 &xyz)
|
||||
{
|
||||
core::vector3df closest = m_line.getClosestPoint(xyz.toIrrVector());
|
||||
return (closest-xyz.toIrrVector()).getLengthSQ();
|
||||
} // getDistance2FromPoint
|
64
src/tracks/node_3d.hpp
Normal file
64
src/tracks/node_3d.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2016 SuperTuxKart-Team
|
||||
//
|
||||
// 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 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_NODE_3D_HPP
|
||||
#define HEADER_NODE_3D_HPP
|
||||
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
/**
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class Node3D : public GraphNode
|
||||
{
|
||||
private:
|
||||
/** For each node, construct a 3D box to check if a point lies inside it.
|
||||
*/
|
||||
Vec3 m_box_faces[6][4];
|
||||
|
||||
/** Line between lower and upper center, saves computation in
|
||||
* getDistance() later.
|
||||
*/
|
||||
core::line3df m_line;
|
||||
|
||||
public:
|
||||
Node3D(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
const Vec3 &normal, unsigned int node_index, bool invisible,
|
||||
bool ai_ignore);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool pointInside(const Vec3& p,
|
||||
bool ignore_vertical = false) const OVERRIDE
|
||||
{
|
||||
float side = p.sideofPlane(m_box_faces[0][0], m_box_faces[0][1],
|
||||
m_box_faces[0][2]);
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
if (side * p.sideofPlane(m_box_faces[i][0], m_box_faces[i][1],
|
||||
m_box_faces[i][2]) < 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void getDistances(const Vec3 &xyz, Vec3 *result) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual float getDistance2FromPoint(const Vec3 &xyz) OVERRIDE;
|
||||
|
||||
};
|
||||
#endif
|
@ -20,56 +20,21 @@
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <matrix4.h>
|
||||
#include <S3DVertex.h>
|
||||
#include <triangle3d.h>
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
/** Constructor, takes 4 points. */
|
||||
Quad::Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
bool invisible, bool ai_ignore)
|
||||
{
|
||||
|
||||
Quad::Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3)
|
||||
{
|
||||
m_p[0]=p0; m_p[1]=p1; m_p[2]=p2; m_p[3]=p3;
|
||||
|
||||
|
||||
m_center = 0.25f*(p0+p1+p2+p3);
|
||||
m_min_height = std::min ( std::min(p0.getY(), p1.getY()),
|
||||
std::min(p2.getY(), p3.getY()) );
|
||||
m_max_height = std::max ( std::max(p0.getY(), p1.getY()),
|
||||
std::max(p2.getY(), p3.getY()) );
|
||||
m_invisible = invisible;
|
||||
m_ai_ignore = ai_ignore;
|
||||
|
||||
findNormal();
|
||||
|
||||
// Compute the quad bounding box used for pointInQuad
|
||||
Vec3 boxCorners[8];
|
||||
Vec3 normal = getNormal();
|
||||
float boxHigh = 5.0f;
|
||||
float boxLow = 1.0f;
|
||||
boxCorners[0] = m_p[0] + boxHigh*normal;
|
||||
boxCorners[1] = m_p[1] + boxHigh*normal;
|
||||
boxCorners[2] = m_p[2] + boxHigh*normal;
|
||||
boxCorners[3] = m_p[3] + boxHigh*normal;
|
||||
boxCorners[4] = m_p[0] - boxLow*normal;
|
||||
boxCorners[5] = m_p[1] - boxLow*normal;
|
||||
boxCorners[6] = m_p[2] - boxLow*normal;
|
||||
boxCorners[7] = m_p[3] - boxLow*normal;
|
||||
|
||||
Vec3 boxFaces[6][4] = {
|
||||
{ boxCorners[0], boxCorners[1], boxCorners[2], boxCorners[3] },
|
||||
{ boxCorners[3], boxCorners[2], boxCorners[6], boxCorners[7] },
|
||||
{ boxCorners[7], boxCorners[6], boxCorners[5], boxCorners[4] },
|
||||
{ boxCorners[1], boxCorners[0], boxCorners[4], boxCorners[5] },
|
||||
{ boxCorners[4], boxCorners[0], boxCorners[3], boxCorners[7] },
|
||||
{ boxCorners[1], boxCorners[5], boxCorners[6], boxCorners[2] }
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < 6 ; i++)
|
||||
for (unsigned int j = 0; j < 4; j++)
|
||||
m_box_faces[i][j] = boxFaces[i][j];
|
||||
|
||||
} // Quad
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -108,7 +73,7 @@ void Quad::getVertices(video::S3DVertex *v, const video::SColor &color) const
|
||||
} // setVertices
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool Quad::pointInQuad(const Vec3& p, bool ignore_vertical) const
|
||||
bool Quad::pointInside(const Vec3& p, bool ignore_vertical) const
|
||||
{
|
||||
// In case that a kart can validly run too high over one driveline
|
||||
// and it should not be considered to be on that driveline. Example:
|
||||
@ -136,20 +101,7 @@ bool Quad::pointInQuad(const Vec3& p, bool ignore_vertical) const
|
||||
return p.sideOfLine2D(m_p[2], m_p[3]) > 0.0 &&
|
||||
p.sideOfLine2D(m_p[3], m_p[0]) >= 0.0;
|
||||
}
|
||||
} // pointInQuad
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Checks if a given point p lies in the bounding box of this quad */
|
||||
bool Quad::pointInQuad3D(const Vec3& p) const
|
||||
{
|
||||
float side = p.sideofPlane(m_box_faces[0][0], m_box_faces[0][1], m_box_faces[0][2]);
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
if (side*p.sideofPlane(m_box_faces[i][0], m_box_faces[i][1], m_box_faces[i][2]) < 0) return false;
|
||||
}
|
||||
return true;
|
||||
} // pointInQuad3D
|
||||
|
||||
} // pointInside
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Transforms a quad by a given transform (i.e. translation+rotation). This
|
||||
@ -171,36 +123,3 @@ void Quad::transform(const btTransform &t, Quad *result) const
|
||||
std::min(result->m_p[2].getY(),
|
||||
result->m_p[3].getY()) );
|
||||
} // transform
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Find the normal of this quad by computing the normal of two triangles and taking
|
||||
* their average.
|
||||
*/
|
||||
void Quad::findNormal()
|
||||
{
|
||||
core::triangle3df tri1(m_p[0].toIrrVector(), m_p[1].toIrrVector(), m_p[2].toIrrVector());
|
||||
core::triangle3df tri2(m_p[0].toIrrVector(), m_p[2].toIrrVector(), m_p[3].toIrrVector());
|
||||
Vec3 normal1 = tri1.getNormal();
|
||||
Vec3 normal2 = tri2.getNormal();
|
||||
m_normal = -0.5f*(normal1 + normal2);
|
||||
m_normal.normalize();
|
||||
|
||||
} // findNormal
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Return a flattened version of this quad. */
|
||||
Quad Quad::getFlattenedQuad()
|
||||
{
|
||||
core::CMatrix4<float> m;
|
||||
m.buildRotateFromTo(m_normal.toIrrVector(), core::vector3df(0, 1, 0));
|
||||
Vec3 m_p_flat[4];
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
m.rotateVect(m_p_flat[i], (m_p[i] - m_center).toIrrVector());
|
||||
|
||||
m_p_flat[i].setY(0);
|
||||
}
|
||||
|
||||
return Quad(m_p_flat[0], m_p_flat[1], m_p_flat[2], m_p_flat[3]);
|
||||
|
||||
} // getFlattenedQuad
|
||||
|
@ -20,9 +20,10 @@
|
||||
#define HEADER_QUAD_HPP
|
||||
|
||||
#include <SColor.h>
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
#include <array>
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -35,9 +36,9 @@ class btTransform;
|
||||
/**
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class Quad
|
||||
class Quad : public NoCopy
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
/** The four points of a quad. */
|
||||
Vec3 m_p[4];
|
||||
|
||||
@ -45,8 +46,7 @@ private:
|
||||
* This saves some computations at runtime. */
|
||||
Vec3 m_center;
|
||||
|
||||
Vec3 m_normal;
|
||||
|
||||
private:
|
||||
/** The minimum height of the quad, used in case that several quads
|
||||
* are on top of each other when determining the sector a kart is on. */
|
||||
float m_min_height;
|
||||
@ -55,47 +55,28 @@ private:
|
||||
* to distinguish between quads which are on top of each other. */
|
||||
float m_max_height;
|
||||
|
||||
/** Set to true if this quad should not be shown in the minimap. */
|
||||
bool m_invisible;
|
||||
|
||||
/** Set if this quad should not be used by the AI. */
|
||||
bool m_ai_ignore;
|
||||
|
||||
/** For each quad, construct a 3D box to check if a point lies inside it. */
|
||||
Vec3 m_box_faces[6][4];
|
||||
|
||||
/** Find the normal of this quad */
|
||||
void findNormal();
|
||||
|
||||
public:
|
||||
Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3,
|
||||
bool invis=false, bool ai_ignore=false);
|
||||
LEAK_CHECK()
|
||||
// ------------------------------------------------------------------------
|
||||
Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual ~Quad() {}
|
||||
// ------------------------------------------------------------------------
|
||||
void getVertices(video::S3DVertex *v, const video::SColor &color) const;
|
||||
bool pointInQuad(const Vec3& p, bool ignore_vertical = false) const;
|
||||
bool pointInQuad3D(const Vec3& p) const;
|
||||
// ------------------------------------------------------------------------
|
||||
void transform(const btTransform &t, Quad *result) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the i-th. point of a quad. */
|
||||
const Vec3& operator[](int i) const {return m_p[i]; }
|
||||
const Vec3& operator[](int i) const { return m_p[i]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the center of a quad. */
|
||||
const Vec3& getCenter () const {return m_center; }
|
||||
const Vec3& getCenter () const { return m_center; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the minimum height of a quad. */
|
||||
float getMinHeight() const { return m_min_height; }
|
||||
float getMinHeight() const { return m_min_height; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true of this quad is invisible, i.e. not to be shown in
|
||||
* the minimap. */
|
||||
bool isInvisible() const { return m_invisible; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** True if this quad should be ignored by the AI. */
|
||||
bool letAIIgnore() const { return m_ai_ignore; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the normal of this quad */
|
||||
const Vec3& getNormal() const { return m_normal; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return a flattened version of this quad */
|
||||
Quad getFlattenedQuad();
|
||||
virtual bool pointInside(const Vec3& p,
|
||||
bool ignore_vertical = false) const;
|
||||
|
||||
}; // class Quad
|
||||
#endif
|
||||
|
@ -35,13 +35,47 @@
|
||||
#include "tracks/check_lap.hpp"
|
||||
#include "tracks/check_line.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/quad_set.hpp"
|
||||
#include "tracks/node_2d.hpp"
|
||||
#include "tracks/node_3d.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
|
||||
const int QuadGraph::UNKNOWN_SECTOR = -1;
|
||||
QuadGraph *QuadGraph::m_quad_graph = NULL;
|
||||
|
||||
/** Factory method to dynamic create 2d / 3d node */
|
||||
GraphNode* createNode(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2,
|
||||
const Vec3 &p3, unsigned int node_index,
|
||||
bool invisible, bool ai_ignore)
|
||||
{
|
||||
// Find the normal of this node by computing the normal of two triangles
|
||||
// and taking their average.
|
||||
core::triangle3df tri1(p0.toIrrVector(), p1.toIrrVector(),
|
||||
p2.toIrrVector());
|
||||
core::triangle3df tri2(p0.toIrrVector(), p2.toIrrVector(),
|
||||
p3.toIrrVector());
|
||||
Vec3 normal1 = tri1.getNormal();
|
||||
Vec3 normal2 = tri2.getNormal();
|
||||
Vec3 normal = -0.5f * (normal1 + normal2);
|
||||
normal.normalize();
|
||||
|
||||
// Use the angle between the normal and an up vector to choose 3d/2d node
|
||||
const float angle = normal.angle(Vec3(0, 1, 0));
|
||||
if (angle > 0.5f)
|
||||
{
|
||||
Log::debug("TrackNode", "3d node created, normal: %f, %f, %f",
|
||||
normal.x(), normal.y(), normal.z());
|
||||
return new Node3D(p0, p1, p2, p3, normal, node_index, invisible,
|
||||
ai_ignore);
|
||||
}
|
||||
|
||||
Log::debug("TrackNode", "2d node created, normal: %f, %f, %f",
|
||||
normal.x(), normal.y(), normal.z());
|
||||
return new Node2D(p0, p1, p2, p3, normal, node_index, invisible,
|
||||
ai_ignore);
|
||||
} // createNode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor, loads the graph information for a given set of quads
|
||||
* from a graph file.
|
||||
* \param quad_file_name Name of the file of all quads
|
||||
@ -52,20 +86,17 @@ QuadGraph::QuadGraph(const std::string &quad_file_name,
|
||||
const bool reverse) : m_reverse(reverse)
|
||||
{
|
||||
m_lap_length = 0;
|
||||
m_unroll_quad_count = 6;
|
||||
QuadSet::create();
|
||||
QuadSet::get()->init(quad_file_name);
|
||||
m_quad_filename = quad_file_name;
|
||||
m_quad_graph = this;
|
||||
load(graph_file_name);
|
||||
load(quad_file_name, graph_file_name);
|
||||
} // QuadGraph
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Destructor, removes all nodes of the graph. */
|
||||
QuadGraph::~QuadGraph()
|
||||
{
|
||||
QuadSet::destroy();
|
||||
for(unsigned int i=0; i<m_all_nodes.size(); i++) {
|
||||
for(unsigned int i=0; i<m_all_nodes.size(); i++)
|
||||
{
|
||||
delete m_all_nodes[i];
|
||||
}
|
||||
if(UserConfigParams::m_track_debug)
|
||||
@ -73,31 +104,98 @@ QuadGraph::~QuadGraph()
|
||||
GraphStructure::destroyRTT();
|
||||
} // ~QuadGraph
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void QuadGraph::addSuccessor(unsigned int from, unsigned int to) {
|
||||
// ----------------------------------------------------------------------------
|
||||
void QuadGraph::addSuccessor(unsigned int from, unsigned int to)
|
||||
{
|
||||
if(m_reverse)
|
||||
m_all_nodes[to]->addSuccessor(from);
|
||||
else
|
||||
m_all_nodes[from]->addSuccessor(to);
|
||||
|
||||
} // addSuccessor
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Loads a quad graph from a file.
|
||||
* \param filename Name of the file to load.
|
||||
*/
|
||||
void QuadGraph::load(const std::string &filename)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** This function interprets a point specification as an attribute in the
|
||||
xml quad file. It understands two different specifications:
|
||||
p1="n:p" : get point p from square n (n, p integers)
|
||||
p1="p1,p2,p3" : make a 3d point out of these 3 floating point values
|
||||
*/
|
||||
void QuadGraph::getPoint(const XMLNode *xml, const std::string &attribute_name,
|
||||
Vec3* result) const
|
||||
{
|
||||
std::string s;
|
||||
xml->get(attribute_name, &s);
|
||||
int pos=(int)s.find_first_of(":");
|
||||
if(pos>0) // n:p specification
|
||||
{
|
||||
std::vector<std::string> l = StringUtils::split(s, ':');
|
||||
int n=atoi(l[0].c_str());
|
||||
int p=atoi(l[1].c_str());
|
||||
*result=(*m_all_nodes[n])[p];
|
||||
}
|
||||
else
|
||||
{
|
||||
xml->get(attribute_name, result);
|
||||
}
|
||||
|
||||
} // getPoint
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads a quad graph from a file.
|
||||
* \param filename Name of the quad file to load.
|
||||
* \param filename Name of the graph file to load.
|
||||
*/
|
||||
void QuadGraph::load(const std::string &quad_file_name,
|
||||
const std::string &filename)
|
||||
{
|
||||
XMLNode *quad = file_manager->createXMLTree(quad_file_name);
|
||||
if (!quad || quad->getName() != "quads")
|
||||
{
|
||||
Log::error("Quad Graph : Quad xml '%s' not found.", filename.c_str());
|
||||
delete quad;
|
||||
return;
|
||||
}
|
||||
|
||||
m_min = Vec3( 99999, 99999, 99999);
|
||||
m_max = Vec3(-99999, -99999, -99999);
|
||||
// Each quad is part of the graph exactly once now.
|
||||
for(unsigned int i=0; i<quad->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *xml_node = quad->getNode(i);
|
||||
if(xml_node->getName()!="quad")
|
||||
{
|
||||
Log::warn("Quad Graph: Unsupported node type '%s' found in '%s' - ignored.",
|
||||
xml_node->getName().c_str(), filename.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Note that it's not easy to do the reading of the parameters here
|
||||
// in quad, since the specification in the xml can contain references
|
||||
// to previous points. E.g.:
|
||||
// <quad p0="40:3" p1="40:2" p2="25.396030 0.770338 64.796539" ...
|
||||
Vec3 p0, p1, p2, p3;
|
||||
getPoint(xml_node, "p0", &p0);
|
||||
getPoint(xml_node, "p1", &p1);
|
||||
getPoint(xml_node, "p2", &p2);
|
||||
getPoint(xml_node, "p3", &p3);
|
||||
bool invisible=false;
|
||||
xml_node->get("invisible", &invisible);
|
||||
bool ai_ignore=false;
|
||||
xml_node->get("ai-ignore", &ai_ignore);
|
||||
GraphNode* node =
|
||||
createNode(p0, p1, p2, p3, m_all_nodes.size(), invisible, ai_ignore);
|
||||
m_max.max(p0);m_max.max(p1);m_max.max(p2);m_max.max(p3);
|
||||
m_min.min(p0);m_min.min(p1);m_min.min(p2);m_min.min(p3);
|
||||
m_all_nodes.push_back(node);
|
||||
}
|
||||
delete quad;
|
||||
|
||||
const XMLNode *xml = file_manager->createXMLTree(filename);
|
||||
|
||||
if(!xml)
|
||||
{
|
||||
// No graph file exist, assume a default loop X -> X+1
|
||||
// i.e. each quad is part of the graph exactly once.
|
||||
// First create an empty graph node for each quad:
|
||||
for(unsigned int i=0; i<QuadSet::get()->getNumberOfQuads(); i++)
|
||||
m_all_nodes.push_back(new GraphNode(i, (unsigned int) m_all_nodes.size()));
|
||||
// Then set the default loop:
|
||||
// Set the default loop:
|
||||
setDefaultSuccessors();
|
||||
computeDirectionData();
|
||||
|
||||
@ -120,29 +218,13 @@ void QuadGraph::load(const std::string &filename)
|
||||
for(unsigned int node_index=0; node_index<xml->getNumNodes(); node_index++)
|
||||
{
|
||||
const XMLNode *xml_node = xml->getNode(node_index);
|
||||
// First graph node definitions:
|
||||
// -----------------------------
|
||||
// Load the definition of edges between the graph nodes:
|
||||
// -----------------------------------------------------
|
||||
if(xml_node->getName()=="node-list")
|
||||
{
|
||||
// A list of quads is connected to a list of graph nodes:
|
||||
unsigned int from, to;
|
||||
xml_node->get("from-quad", &from);
|
||||
xml_node->get("to-quad", &to);
|
||||
for(unsigned int i=from; i<=to; i++)
|
||||
{
|
||||
m_all_nodes.push_back(new GraphNode(i, (unsigned int) m_all_nodes.size()));
|
||||
}
|
||||
// Each quad is part of the graph exactly once now.
|
||||
continue;
|
||||
}
|
||||
else if(xml_node->getName()=="node")
|
||||
{
|
||||
// A single quad is connected to a single graph node.
|
||||
unsigned int id;
|
||||
xml_node->get("quad", &id);
|
||||
m_all_nodes.push_back(new GraphNode(id, (unsigned int) m_all_nodes.size()));
|
||||
}
|
||||
|
||||
// Then the definition of edges between the graph nodes:
|
||||
// -----------------------------------------------------
|
||||
else if(xml_node->getName()=="edge-loop")
|
||||
{
|
||||
// A closed loop:
|
||||
@ -202,11 +284,6 @@ void QuadGraph::load(const std::string &filename)
|
||||
m_lap_length = l;
|
||||
}
|
||||
|
||||
// Build unrolled quads
|
||||
for (unsigned int i = 0; i < m_all_nodes.size(); i++)
|
||||
{
|
||||
m_all_nodes[i]->buildUnrolledQuads(m_unroll_quad_count);
|
||||
}
|
||||
} // load
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -439,7 +516,7 @@ void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance)
|
||||
if(current_distance<new_distance)
|
||||
{
|
||||
float delta = new_distance - current_distance;
|
||||
updateDistancesForAllSuccessors(gn->getQuadIndex(), delta, 0);
|
||||
updateDistancesForAllSuccessors(gn->getNodeIndex(), delta, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -456,7 +533,7 @@ void QuadGraph::computeDistanceFromStart(unsigned int node, float new_distance)
|
||||
if(gn_next->getDistanceFromStart()==0)
|
||||
continue;
|
||||
|
||||
computeDistanceFromStart(gn_next->getQuadIndex(),
|
||||
computeDistanceFromStart(gn_next->getNodeIndex(),
|
||||
new_distance + gn->getDistanceToSuccessor(i));
|
||||
} // for i
|
||||
} // computeDistanceFromStart
|
||||
@ -631,21 +708,6 @@ void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz,
|
||||
getNode(sector).getDistances(xyz, dst);
|
||||
} // spatialToTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void QuadGraph::spatialToTrackUnrolled(Vec3 *dst, const Vec3& xyz,
|
||||
const int parent_sector,
|
||||
const int unroll_qd_idx,
|
||||
const int fork_number) const
|
||||
{
|
||||
if (parent_sector == UNKNOWN_SECTOR)
|
||||
{
|
||||
Log::warn("Quad Graph", "UNKNOWN_SECTOR in spatialToTrackUnrolled().");
|
||||
return;
|
||||
}
|
||||
getNode(parent_sector).getDistancesUnrolled(xyz, fork_number,
|
||||
unroll_qd_idx, dst);
|
||||
} // spatialToTrackUnrolled
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** findRoadSector returns in which sector on the road the position
|
||||
* xyz is. If xyz is not on top of the road, it sets UNKNOWN_SECTOR as sector.
|
||||
@ -663,7 +725,7 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
|
||||
{
|
||||
// Most likely the kart will still be on the sector it was before,
|
||||
// so this simple case is tested first.
|
||||
if(*sector!=UNKNOWN_SECTOR && getQuadOfNode(*sector).pointInQuad3D(xyz) )
|
||||
if(*sector!=UNKNOWN_SECTOR && getNode(*sector).pointInside(xyz) )
|
||||
{
|
||||
return;
|
||||
} // if still on same quad
|
||||
@ -671,9 +733,6 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
|
||||
// Now we search through all graph nodes, starting with
|
||||
// the current one
|
||||
int indx = *sector;
|
||||
// This was used to check the vertical distance of kart from sector
|
||||
// but because now karts are checked in a 3D space, this is not required
|
||||
//float min_dist = 999999.9f;
|
||||
|
||||
// If a current sector is given, and max_lookahead is specify, only test
|
||||
// the next max_lookahead graph nodes instead of testing the whole graph.
|
||||
@ -694,13 +753,9 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
|
||||
indx = (*all_sectors)[i];
|
||||
else
|
||||
indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0;
|
||||
const Quad &q = getQuadOfNode(indx);
|
||||
float dist = xyz.getY() - q.getMinHeight();
|
||||
// While negative distances are unlikely, we allow some small negative
|
||||
// numbers in case that the kart is partly in the track.
|
||||
if(q.pointInQuad3D(xyz))// && dist < min_dist && dist>-1.0f)
|
||||
const GraphNode &gn = getNode(indx);
|
||||
if(gn.pointInside(xyz))
|
||||
{
|
||||
//min_dist = dist;
|
||||
*sector = indx;
|
||||
}
|
||||
} // for i<m_all_nodes.size()
|
||||
@ -788,8 +843,8 @@ int QuadGraph::findOutOfRoadSector(const Vec3& xyz,
|
||||
float dist_2 = m_all_nodes[next_sector]->getDistance2FromPoint(xyz);
|
||||
if(dist_2<min_dist_2)
|
||||
{
|
||||
const Quad &q = getQuadOfNode(next_sector);
|
||||
float dist = xyz.getY() - q.getMinHeight();
|
||||
const GraphNode &gn = getNode(next_sector);
|
||||
float dist = xyz.getY() - gn.getMinHeight();
|
||||
// While negative distances are unlikely, we allow some small
|
||||
// negative numbers in case that the kart is partly in the
|
||||
// track. Only do the height test in phase==0, in phase==1
|
||||
@ -809,7 +864,44 @@ int QuadGraph::findOutOfRoadSector(const Vec3& xyz,
|
||||
|
||||
if(min_sector==UNKNOWN_SECTOR )
|
||||
{
|
||||
Log::info("Quad Grap", "unknown sector found.");
|
||||
Log::info("Quad Graph", "unknown sector found.");
|
||||
}
|
||||
return min_sector;
|
||||
} // findOutOfRoadSector
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void QuadGraph::set3DVerticesOfGraph(int i, video::S3DVertex *v,
|
||||
const video::SColor &color) const
|
||||
{
|
||||
m_all_nodes[i]->getVertices(v, color);
|
||||
} // set3DVerticesOfGraph
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const bool QuadGraph::isNodeInvisible(int n) const
|
||||
{
|
||||
return m_all_nodes[n]->isInvisible();
|
||||
} // isNodeInvisible
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
float QuadGraph::getDistanceToNext(int n, int j) const
|
||||
{
|
||||
return m_all_nodes[n]->getDistanceToSuccessor(j);
|
||||
} // getDistanceToNext
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
float QuadGraph::getAngleToNext(int n, int j) const
|
||||
{
|
||||
return m_all_nodes[n]->getAngleToSuccessor(j);
|
||||
} // getAngleToNext
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int QuadGraph::getNumberOfSuccessors(int n) const
|
||||
{
|
||||
return m_all_nodes[n]->getNumberOfSuccessors();
|
||||
} // getNumberOfSuccessors
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
float QuadGraph::getDistanceFromStart(int j) const
|
||||
{
|
||||
return m_all_nodes[j]->getDistanceFromStart();
|
||||
} // getDistanceFromStart
|
||||
|
@ -23,12 +23,13 @@
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/graph_structure.hpp"
|
||||
#include "tracks/quad_set.hpp"
|
||||
#include "utils/aligned_array.hpp"
|
||||
|
||||
class CheckLine;
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
class GraphNode;
|
||||
class XMLNode;
|
||||
|
||||
/**
|
||||
* \brief This class stores a graph of quads. It uses a 'simplified singleton'
|
||||
@ -46,6 +47,10 @@ class QuadGraph : public GraphStructure
|
||||
private:
|
||||
static QuadGraph *m_quad_graph;
|
||||
|
||||
/** The 2d bounding box, used for hashing. */
|
||||
Vec3 m_min;
|
||||
Vec3 m_max;
|
||||
|
||||
/** The actual graph data structure. */
|
||||
std::vector<GraphNode*> m_all_nodes;
|
||||
|
||||
@ -58,9 +63,6 @@ private:
|
||||
/** Wether the graph should be reverted or not */
|
||||
bool m_reverse;
|
||||
|
||||
/** Number of unrolled quads to compute per quad */
|
||||
unsigned int m_unroll_quad_count;
|
||||
|
||||
void setDefaultSuccessors();
|
||||
void computeChecklineRequirements(GraphNode* node, int latest_checkline);
|
||||
void computeDirectionData();
|
||||
@ -68,7 +70,9 @@ private:
|
||||
float normalizeAngle(float f);
|
||||
|
||||
void addSuccessor(unsigned int from, unsigned int to);
|
||||
void load (const std::string &filename);
|
||||
void load(const std::string &quad_file_name, const std::string &filename);
|
||||
void getPoint(const XMLNode *xml, const std::string &attribute_name,
|
||||
Vec3 *result) const;
|
||||
void computeDistanceFromStart(unsigned int start_node, float distance);
|
||||
unsigned int getStartNode() const;
|
||||
QuadGraph(const std::string &quad_file_name,
|
||||
@ -78,14 +82,12 @@ private:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void set3DVerticesOfGraph(int i, video::S3DVertex *v,
|
||||
const video::SColor &color) const
|
||||
{ m_all_nodes[i]->getQuad().getVertices(v, color); }
|
||||
const video::SColor &color) const;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void getGraphBoundingBox(Vec3 *min, Vec3 *max) const
|
||||
{ QuadSet::get()->getBoundingBox(min, max); }
|
||||
{ *min = m_min; *max = m_max; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual const bool isNodeInvisible(int n) const
|
||||
{ return m_all_nodes[n]->getQuad().isInvisible(); }
|
||||
virtual const bool isNodeInvisible(int n) const;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual const bool hasLapLine() const
|
||||
{ return true; }
|
||||
@ -101,12 +103,6 @@ public:
|
||||
bool for_ai=false) const;
|
||||
void spatialToTrack(Vec3 *dst, const Vec3& xyz,
|
||||
const int sector) const;
|
||||
void spatialToTrackUnrolled(Vec3 *dst,
|
||||
const Vec3& xyz,
|
||||
const int parent_sector,
|
||||
const int unroll_qd_idx,
|
||||
const int fork_number) const;
|
||||
|
||||
void findRoadSector(const Vec3& XYZ, int *sector,
|
||||
std::vector<int> *all_sectors=NULL) const;
|
||||
int findOutOfRoadSector(const Vec3& xyz,
|
||||
@ -124,13 +120,13 @@ public:
|
||||
unsigned int count);
|
||||
void setupPaths();
|
||||
void computeChecklineRequirements();
|
||||
// ----------------------------------------------------------------------======
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the one instance of this object. It is possible that there
|
||||
* is no instance created (e.g. in battle mode, since it doesn't have
|
||||
* a quad graph), so we don't assert that an instance exist, and we
|
||||
* also don't create one if it doesn't exists. */
|
||||
static QuadGraph *get() { return m_quad_graph; }
|
||||
// ----------------------------------------------------------------------==
|
||||
// ------------------------------------------------------------------------
|
||||
/** Creates a QuadGraph instance. */
|
||||
static void create(const std::string &quad_file_name,
|
||||
const std::string &graph_file_name,
|
||||
@ -156,45 +152,28 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of nodes in the graph. */
|
||||
virtual const unsigned int getNumNodes() const
|
||||
{ return (unsigned int)m_all_nodes.size();}
|
||||
{ return m_all_nodes.size(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the distance to the j-th successor of node n. */
|
||||
float getDistanceToNext(int n, int j) const
|
||||
{ return m_all_nodes[n]->getDistanceToSuccessor(j);}
|
||||
float getDistanceToNext(int n, int j) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the angle of the line between node n and its j-th.
|
||||
* successor. */
|
||||
float getAngleToNext(int n, int j) const
|
||||
{ return m_all_nodes[n]->getAngleToSuccessor(j); }
|
||||
float getAngleToNext(int n, int j) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of successors of a node n. */
|
||||
int getNumberOfSuccessors(int n) const
|
||||
{ return m_all_nodes[n]->getNumberOfSuccessors(); }
|
||||
int getNumberOfSuccessors(int n) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the quad that belongs to a graph node. */
|
||||
const Quad& getQuadOfNode(unsigned int j) const
|
||||
{ return QuadSet::get()->getQuad(m_all_nodes[j]->getQuadIndex()); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the quad that belongs to a graph node. */
|
||||
GraphNode& getNode(unsigned int j) const{ return *m_all_nodes[j]; }
|
||||
GraphNode& getNode(unsigned int j) const { return *m_all_nodes[j]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the distance from the start to the beginning of a quad. */
|
||||
float getDistanceFromStart(int j) const
|
||||
{ return m_all_nodes[j]->getDistanceFromStart(); }
|
||||
float getDistanceFromStart(int j) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the length of the main driveline. */
|
||||
float getLapLength() const {return m_lap_length; }
|
||||
float getLapLength() const { return m_lap_length; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isReverse() const {return m_reverse; }
|
||||
// ----------------------------------------------------------------------
|
||||
/** Returns a unrolled quad of a node. */
|
||||
const Quad& getUnrolledQuadOfNode(unsigned int node,
|
||||
unsigned int fork_number,
|
||||
unsigned int quad_number)
|
||||
{ return getNode(node).getUnrolledQuad(fork_number,quad_number); }
|
||||
// ----------------------------------------------------------------------
|
||||
/** Returns the number of forward quads that are unrolled for each quad **/
|
||||
unsigned int getNumberOfUnrolledQuads() const { return m_unroll_quad_count; }
|
||||
bool isReverse() const { return m_reverse; }
|
||||
|
||||
}; // QuadGraph
|
||||
|
||||
|
@ -1,124 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2015 Joerg Henrichs
|
||||
//
|
||||
// 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 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "tracks/quad_set.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
QuadSet *QuadSet::m_quad_set = NULL;
|
||||
|
||||
/** Constructor, loads the quad set from a file. Assigns a pointer
|
||||
* to this instance to m_quad_set, so that it can be accessed using get().
|
||||
*/
|
||||
QuadSet::QuadSet()
|
||||
{
|
||||
m_quad_set = this;
|
||||
} // QuadSet
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Destructor, frees all memory.
|
||||
*/
|
||||
QuadSet::~QuadSet()
|
||||
{
|
||||
for(unsigned int i=0; i<m_all_quads.size(); i++)
|
||||
{
|
||||
delete m_all_quads[i];
|
||||
}
|
||||
m_all_quads.clear();
|
||||
m_quad_set = NULL;
|
||||
} // ~QuadSet
|
||||
|
||||
// -----------------------------------------------------------------------------}
|
||||
/** This function interprets a point specification as an attribute in the
|
||||
xml quadset file. It understands two different specifications:
|
||||
p1="n:p" : get point p from square n (n, p integers)
|
||||
p1="p1,p2,p3" : make a 3d point out of these 3 floating point values
|
||||
*/
|
||||
void QuadSet::getPoint(const XMLNode *xml, const std::string &attribute_name,
|
||||
Vec3* result) const
|
||||
{
|
||||
std::string s;
|
||||
xml->get(attribute_name, &s);
|
||||
int pos=(int)s.find_first_of(":");
|
||||
if(pos>0) // n:p specification
|
||||
{
|
||||
std::vector<std::string> l = StringUtils::split(s, ':');
|
||||
int n=atoi(l[0].c_str());
|
||||
int p=atoi(l[1].c_str());
|
||||
*result=(*m_all_quads[n])[p];
|
||||
}
|
||||
else
|
||||
{
|
||||
xml->get(attribute_name, result);
|
||||
}
|
||||
|
||||
} // getPoint
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Loads the set of all quads from the specified filename.
|
||||
* \param filename The absolute filename to load the quad file from.
|
||||
*/
|
||||
void QuadSet::init(const std::string &filename)
|
||||
{
|
||||
m_min = Vec3( 99999, 99999, 99999);
|
||||
m_max = Vec3(-99999, -99999, -99999);
|
||||
|
||||
XMLNode *xml = file_manager->createXMLTree(filename);
|
||||
if(!xml || xml->getName()!="quads")
|
||||
{
|
||||
Log::error("[QuadSet::load] ERROR : QuadSet '%s' not found.", filename.c_str());
|
||||
delete xml;
|
||||
return;
|
||||
}
|
||||
for(unsigned int i=0; i<xml->getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *xml_node = xml->getNode(i);
|
||||
if(xml_node->getName()!="quad")
|
||||
{
|
||||
Log::warn("[QuadSet::load] WARNING: Unsupported node type '%s' found in '%s' - ignored.",
|
||||
xml_node->getName().c_str(), filename.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Note that it's not easy to do the reading of the parameters here
|
||||
// in quad, since the specification in the xml can contain references
|
||||
// to previous points. E.g.:
|
||||
// <quad p0="40:3" p1="40:2" p2="25.396030 0.770338 64.796539" ...
|
||||
Vec3 p0, p1, p2, p3;
|
||||
getPoint(xml_node, "p0", &p0);
|
||||
getPoint(xml_node, "p1", &p1);
|
||||
getPoint(xml_node, "p2", &p2);
|
||||
getPoint(xml_node, "p3", &p3);
|
||||
bool invisible=false;
|
||||
xml_node->get("invisible", &invisible);
|
||||
bool ai_ignore=false;
|
||||
xml_node->get("ai-ignore", &ai_ignore);
|
||||
Quad* q=new Quad(p0,p1,p2,p3, invisible, ai_ignore);
|
||||
m_all_quads.push_back(q);
|
||||
m_max.max(p0);m_max.max(p1);m_max.max(p2);m_max.max(p3);
|
||||
m_min.min(p0);m_min.min(p1);m_min.min(p2);m_min.min(p3);
|
||||
|
||||
}
|
||||
delete xml;
|
||||
} // load
|
||||
|
||||
// -----------------------------------------------------------------------------
|
@ -1,90 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2015 Joerg Henrichs
|
||||
//
|
||||
// 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 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_QUAD_SET_HPP
|
||||
#define HEADER_QUAD_SET_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "tracks/quad.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
class XMLNode;
|
||||
|
||||
/**
|
||||
* \ingroup tracks
|
||||
*/
|
||||
class QuadSet
|
||||
{
|
||||
private:
|
||||
/** The 2d bounding box, used for hashing. */
|
||||
Vec3 m_min;
|
||||
Vec3 m_max;
|
||||
|
||||
/** The list of all quads. */
|
||||
std::vector<Quad*> m_all_quads;
|
||||
|
||||
/** Pointer to the one instance of a quad set. */
|
||||
static QuadSet *m_quad_set;
|
||||
|
||||
void getPoint(const XMLNode *xml, const std::string &attribute_name,
|
||||
Vec3 *result) const;
|
||||
QuadSet();
|
||||
~QuadSet();
|
||||
|
||||
public:
|
||||
static const int QUAD_NONE=-1;
|
||||
|
||||
void init (const std::string &filename);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Creates one instance of the quad set. */
|
||||
static void create()
|
||||
{
|
||||
assert(m_quad_set==NULL);
|
||||
m_quad_set = new QuadSet();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Destroys the one instance of a quad set. */
|
||||
static void destroy()
|
||||
{
|
||||
delete m_quad_set; m_quad_set = NULL;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Static member function to access the QuadSet instance. */
|
||||
static QuadSet *get() { return m_quad_set; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the quad with a given index number. */
|
||||
const Quad& getQuad(int n) const {return *(m_all_quads[n]); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return the minimum and maximum coordinates of this quad set. */
|
||||
void getBoundingBox(Vec3 *min, Vec3 *max)
|
||||
{ *min=m_min; *max=m_max; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of quads. */
|
||||
unsigned int getNumberOfQuads() const
|
||||
{return (unsigned int)m_all_quads.size(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the center of quad n. */
|
||||
const Vec3& getCenterOfQuad(int n) const
|
||||
{return m_all_quads[n]->getCenter(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the n-th. quad. */
|
||||
const Quad& getQuad(int n) {return *(m_all_quads[n]); }
|
||||
}; // QuadSet
|
||||
#endif
|
@ -32,6 +32,7 @@
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/lod_node.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/material_manager.hpp"
|
||||
#include "graphics/mesh_tools.hpp"
|
||||
#include "graphics/moving_texture.hpp"
|
||||
@ -54,10 +55,10 @@
|
||||
#include "tracks/bezier_curve.hpp"
|
||||
#include "tracks/battle_graph.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
#include "tracks/model_definition_loader.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/quad_set.hpp"
|
||||
#include "tracks/track_object_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/log.hpp"
|
||||
@ -2291,8 +2292,8 @@ void Track::itemCommand(const XMLNode *node)
|
||||
// If a valid road_sector is not found
|
||||
if (road_sector == QuadGraph::UNKNOWN_SECTOR)
|
||||
road_sector = QuadGraph::get()->findOutOfRoadSector(xyz, road_sector);
|
||||
Vec3 quadnormal = QuadGraph::get()->getQuadOfNode(road_sector).getNormal();
|
||||
|
||||
const Vec3& quadnormal = QuadGraph::get()->getNode(road_sector).getNormal();
|
||||
|
||||
const Material *m;
|
||||
Vec3 hit_point;
|
||||
m_track_mesh->castRay(loc, loc + -1.0f*quadnormal, &hit_point, &m, &normal);
|
||||
@ -2384,7 +2385,7 @@ bool Track::findGround(AbstractKart *kart)
|
||||
{
|
||||
int sector = ((LinearWorld*)World::getWorld())->getTrackSector(kart->getWorldKartId()).getCurrentGraphNode();
|
||||
if (sector != QuadGraph::UNKNOWN_SECTOR)
|
||||
quadNormal = QuadGraph::get()->getQuadOfNode(sector).getNormal();
|
||||
quadNormal = QuadGraph::get()->getNode(sector).getNormal();
|
||||
}
|
||||
|
||||
to = to + -1000.0f*quadNormal;
|
||||
@ -2436,3 +2437,7 @@ bool Track::findGround(AbstractKart *kart)
|
||||
|
||||
return true;
|
||||
} // findGround
|
||||
|
||||
|
||||
float Track::getTrackLength() const {return QuadGraph::get()->getLapLength();}
|
||||
float Track::getAngle(int n) const { return QuadGraph::get()->getAngleToNext(n, 0); }
|
@ -26,31 +26,31 @@
|
||||
* objects.
|
||||
*/
|
||||
|
||||
#include <SColor.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video { class ITexture; class SColor; }
|
||||
namespace scene { class IMesh; class ILightSceneNode; }
|
||||
namespace video { class ITexture; }
|
||||
namespace scene { class IMesh; class ILightSceneNode; class ISceneNode; }
|
||||
}
|
||||
using namespace irr;
|
||||
class ModelDefinitionLoader;
|
||||
|
||||
#include "LinearMath/btTransform.h"
|
||||
|
||||
#include "graphics/material.hpp"
|
||||
#include "items/item.hpp"
|
||||
#include "scriptengine/script_engine.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "utils/aligned_array.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
class AbstractKart;
|
||||
class AnimationManager;
|
||||
class BezierCurve;
|
||||
class CheckManager;
|
||||
class FrameBuffer;
|
||||
class MovingTexture;
|
||||
class MusicInformation;
|
||||
class ParticleEmitter;
|
||||
@ -473,8 +473,7 @@ public:
|
||||
int getVersion () const {return m_version; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the length of the main driveline. */
|
||||
float getTrackLength () const
|
||||
{return QuadGraph::get()->getLapLength();}
|
||||
float getTrackLength () const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a unique identifier for this track (the directory name). */
|
||||
const std::string& getIdent () const {return m_ident; }
|
||||
@ -511,8 +510,7 @@ public:
|
||||
* in the direction of the default way on the track.
|
||||
* \param n Number of the quad for which the angle is asked.
|
||||
*/
|
||||
float getAngle(int n) const
|
||||
{ return QuadGraph::get()->getAngleToNext(n, 0); }
|
||||
float getAngle(int n) const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the 2d coordinates of a point when drawn on the mini map
|
||||
* texture.
|
||||
|
@ -20,9 +20,9 @@
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/check_structure.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_sector.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/graph_node.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Initialises the object, and sets the current graph node to be undefined.
|
||||
@ -65,7 +65,7 @@ void TrackSector::update(const Vec3 &xyz)
|
||||
{
|
||||
// keep the current quad as the latest valid one IF the player has one
|
||||
// of the required checklines
|
||||
GraphNode gn = QuadGraph::get()->getNode(m_current_graph_node);
|
||||
const GraphNode& gn = QuadGraph::get()->getNode(m_current_graph_node);
|
||||
const std::vector<int>& checkline_requirements = gn.getChecklineRequirements();
|
||||
|
||||
if (checkline_requirements.size() == 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user