Files
stk-code_catmod/src/tracks/terrain_info.cpp
2020-09-12 14:31:32 -04:00

144 lines
5.7 KiB
C++

//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007-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/terrain_info.hpp"
#include "physics/triangle_mesh.hpp"
#include "race/race_manager.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
#include "tracks/track_object_manager.hpp"
#include "utils/constants.hpp"
#include <math.h>
/** Constructor to initialise terrain data.
*/
TerrainInfo::TerrainInfo()
{
m_last_material = NULL;
m_material = NULL;
} // TerrainInfo
//-----------------------------------------------------------------------------
/** Constructor to initialise terrain data at a given position
* \param pos The position to get the data from.
*/
TerrainInfo::TerrainInfo(const Vec3 &pos)
{
// initialise HoT
m_last_material = NULL;
m_material = NULL;
update(pos);
} // TerrainInfo
//-----------------------------------------------------------------------------
/** Update the terrain information based on the latest position.
* \param Position from which to start the raycast from.
*/
void TerrainInfo::update(const Vec3 &from)
{
m_last_material = m_material;
btVector3 to(from);
to.setY(-10000.0f);
const TriangleMesh &tm = Track::getCurrentTrack()->getTriangleMesh();
tm.castRay(from, to, &m_hit_point, &m_material, &m_normal,
/*interpolate*/false);
// Now also raycast against all track objects (that are driveable).
Track::getCurrentTrack()->getTrackObjectManager()
->castRay(from, to, &m_hit_point, &m_material,
&m_normal, /*interpolate*/false);
} // update
//-----------------------------------------------------------------------------
/** Update the terrain information based on the latest position.
* \param tran The transform ov the kart
* \param from World coordinates from which to start the raycast.
*/
void TerrainInfo::update(const btMatrix3x3 &rotation, const Vec3 &from)
{
m_last_material = m_material;
// Save the origin for debug drawing
m_origin_ray = from;
// Compute the 'to' vector by rotating a long 'down' vectory by the
// kart rotation, and adding the start point to it.
btVector3 to(0, -10000.0f, 0);
to = from + rotation*to;
const TriangleMesh &tm = Track::getCurrentTrack()->getTriangleMesh();
tm.castRay(from, to, &m_hit_point, &m_material, &m_normal,
/*interpolate*/true);
// Now also raycast against all track objects (that are driveable). If
// there should be a closer result (than the one against the main track
// mesh), its data will be returned.
Track::getCurrentTrack()->getTrackObjectManager()
->castRay(from, to, &m_hit_point, &m_material,
&m_normal, /*interpolate*/true);
} // update
//-----------------------------------------------------------------------------
/** Update the terrain information based on the latest position.
* \param Position from which to start the rayast from.
*/
void TerrainInfo::update(const Vec3 &from, const Vec3 &towards)
{
m_last_material = m_material;
Vec3 direction = towards.normalized();
btVector3 to = from + 10000.0f*direction;
const TriangleMesh &tm = Track::getCurrentTrack()->getTriangleMesh();
tm.castRay(from, to, &m_hit_point, &m_material, &m_normal);
} // update
// -----------------------------------------------------------------------------
/** Does a raycast upwards from the given position
If the raycast indicated that the kart is 'under something' (i.e. a
* specially marked terrain), to another raycast up to detect under whic
* mesh the kart is. This is using the special gfx effect mesh only.
* This is used e.g. to detect if a kart is under water, and then to
* get the proper position for water effects. Note that the TerrainInfo
* objects keeps track of the previous raycast position.
*/
bool TerrainInfo::getSurfaceInfo(const Vec3 &from, Vec3 *position,
const Material **material)
{
Vec3 to=from+Vec3(0, 10000, 0);
const TriangleMesh &tm = Track::getCurrentTrack()->getGFXEffectMesh();
return tm.castRay(from, to, position, material);
} // getSurfaceInfo
// -----------------------------------------------------------------------------
/** Returns the pitch of the terrain depending on the heading
*/
float TerrainInfo::getTerrainPitch(float heading) const {
if(!m_material) return 0.0f;
const float X = sinf(heading);
const float Z = cosf(heading);
// Compute the angle between the normal of the plane and the line to
// (x,0,z). (x,0,z) is normalised, so are the coordinates of the plane,
// simplifying the computation of the scalar product.
float pitch = ( m_normal.getX()*X + m_normal.getZ()*Z ); // use (x, 0, z)
// The actual angle computed above is between the normal and the (x, 0, z)
// line, so to compute the actual angles 90 degrees must be subtracted.
pitch = -acosf(pitch) + NINETY_DEGREE_RAD;
return pitch;
} // getTerrainPitch