#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2015 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library 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
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion // CPL License
#ifndef NUCLEX_GEOMETRY_VOLUMES_TRACERS_HEIGHTFIELD3TRACER_H
#define NUCLEX_GEOMETRY_VOLUMES_TRACERS_HEIGHTFIELD3TRACER_H
#include "Nuclex/Geometry/Config.h"
#include "Nuclex/Geometry/Point3.h"
#include "Nuclex/Geometry/Vector3.h"
#include "Nuclex/Geometry/Volumes/HeightField3.h"
namespace Nuclex { namespace Geometry { namespace Volumes { namespace Tracers {
// ------------------------------------------------------------------------------------------- //
/// Detects the contacts of a line against a height field
template
class HeightField3Tracer {
/// Traces a ray through the height field
/// Height field the ray will be traced against
/// Starting location of the ray
/// Direction of the ray
///
/// The distance from the ray's origin at which the height field is hit or
/// infinity if the ray will not hit the height field.
///
public: static TScalar Trace(
const HeightField3 &heightField,
const Point3 &start, const Vector3 &direction
) {
// See whether the ray starts inside of the terrain. If so, the started in solid
// matter and we can directly return a collision at time 0.0.
TScalar heightAtStart = heightField.LinearInterpolateHeightAt(start.X, start.Y);
if(start.Z <= heightAtStart) {
return 0;
}
// If the ray is perfectly vertical, it will stay above the point it is now, so
// we can easily calculate the time of impact or conclude no impact happens.
bool isVertical = (direction.X == 0) && (direction.Y == 0);
if(isVertical) {
if(direction.Z >= 0) {
return std::numeric_limits::signaling_NaN();
} else {
return start.Z - heightAtStart;
}
}
// The ray is traveling horizontally (at least to some degree) and didn't begin
// inside solid matter, so now we can trace it.
return traceNonVerticalRay(
Point3(
start.X - heightField.Position.X,
start.Y - heightField.Position.Y,
start.Z
)
);
}
/// Traces a ray that is not traveling purely vertical
/// Height field across which the ray is traced
/// Location the ray started at in local coordinates
/// Direction in which the ray travels
/// The distance after which the ray will hit the height field
private: static TScalar traceNonVerticalRay(
const HeightField3 &heightField,
Point3 &localStart, const Vector3 &direction
) {
return 0;
}
};
// ------------------------------------------------------------------------------------------- //
}}}} // namespace Nuclex::Geometry::Volumes::Tracers
#endif // NUCLEX_GEOMETRY_VOLUMES_TRACERS_HEIGHTFIELD3TRACER_H