trackgen: add getTerrainHeight
git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@8902 30fe4595-0a0c-4342-8851-515496e4dcbd Former-commit-id: dad989768b994abd1f5fd2b006b58f8e4b14f32e Former-commit-id: 3f61673e9ea2e1bc755e121d2a4378553dfdbc3d
This commit is contained in:
parent
da4fac882c
commit
90968ea8c6
2 changed files with 207 additions and 12 deletions
|
@ -53,6 +53,18 @@ double Ac3d::V3d::length() const
|
|||
return sqrt((*this)[0] * (*this)[0] + (*this)[1] * (*this)[1] + (*this)[2] * (*this)[2]);
|
||||
}
|
||||
|
||||
double Ac3d::V3d::dot(const V3d &other) const
|
||||
{
|
||||
return (*this)[0] * other[0] + (*this)[1] * other[1] + (*this)[2] * other[2];
|
||||
}
|
||||
|
||||
Ac3d::V3d Ac3d::V3d::cross(const V3d &other) const
|
||||
{
|
||||
return V3d{ (*this)[1] * other[2] - (*this)[2] * other[1],
|
||||
(*this)[2] * other[0] - (*this)[0] * other[2],
|
||||
(*this)[0] * other[1] - (*this)[1] * other[0] };
|
||||
}
|
||||
|
||||
//----------------------------------- Color -----------------------------------
|
||||
|
||||
//---------------------------------- Material ---------------------------------
|
||||
|
@ -490,6 +502,22 @@ void Ac3d::BoundingBox::extend(const V3d &vertex)
|
|||
}
|
||||
}
|
||||
|
||||
void Ac3d::BoundingBox::extend(const BoundingBox &boundingBox)
|
||||
{
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
if (boundingBox.max[i] > max[i])
|
||||
max[i] = boundingBox.max[i];
|
||||
if (boundingBox.min[i] < min[i])
|
||||
min[i] = boundingBox.min[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool Ac3d::BoundingBox::pointInside(double x, double y) const
|
||||
{
|
||||
return x <= max[0] && x >= min[0] && y <= max[1] && y >= min[1];
|
||||
}
|
||||
|
||||
//------------------------------- Boundingsphere ------------------------------
|
||||
|
||||
void Ac3d::BoundingSphere::extend(const BoundingBox &boundingBox)
|
||||
|
@ -769,21 +797,36 @@ void Ac3d::Object::flipAxes(bool in)
|
|||
}
|
||||
}
|
||||
|
||||
Ac3d::BoundingBox Ac3d::Object::getBoundingBox() const
|
||||
const Ac3d::BoundingBox &Ac3d::Object::getBoundingBox() const
|
||||
{
|
||||
BoundingBox bb;
|
||||
if (type == "poly")
|
||||
{
|
||||
if (!hasBoundingBox)
|
||||
{
|
||||
for (const auto &vertex : vertices)
|
||||
boundingBox.extend(vertex);
|
||||
|
||||
for (const auto &vertex : vertices)
|
||||
bb.extend(vertex);
|
||||
hasBoundingBox = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto &kid : kids)
|
||||
boundingBox.extend(kid.getBoundingBox());
|
||||
}
|
||||
|
||||
return bb;
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
Ac3d::BoundingSphere Ac3d::Object::getBoundingSphere() const
|
||||
const Ac3d::BoundingSphere &Ac3d::Object::getBoundingSphere() const
|
||||
{
|
||||
BoundingSphere bs;
|
||||
bs.extend(getBoundingBox());
|
||||
return bs;
|
||||
if (!hasBoundingSphere)
|
||||
{
|
||||
boundingSphere.extend(getBoundingBox());
|
||||
hasBoundingSphere = true;
|
||||
}
|
||||
|
||||
return boundingSphere;
|
||||
}
|
||||
|
||||
void Ac3d::Object::remapMaterials(const MaterialMap &materialMap)
|
||||
|
@ -800,6 +843,113 @@ void Ac3d::Object::remapMaterials(const MaterialMap &materialMap)
|
|||
}
|
||||
}
|
||||
|
||||
void Ac3d::Object::generateTriangles()
|
||||
{
|
||||
if (type == "poly")
|
||||
{
|
||||
for (std::list<Surface>::iterator it = surfaces.begin(); it != surfaces.end(); ++it)
|
||||
{
|
||||
if (it->refs.size() == 4)
|
||||
{
|
||||
Surface surface;
|
||||
surface.mat = it->mat;
|
||||
surface.surf = it->surf;
|
||||
surface.refs.resize(3);
|
||||
surface.refs[0] = it->refs[0];
|
||||
surface.refs[1] = it->refs[2];
|
||||
surface.refs[2] = it->refs[3];
|
||||
it->refs.resize(3);
|
||||
surfaces.insert(++it, surface);
|
||||
}
|
||||
else if (it->refs.size() != 3)
|
||||
{
|
||||
throw Exception("Not implemented yet");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto &kid : kids)
|
||||
kid.generateTriangles();
|
||||
}
|
||||
}
|
||||
|
||||
void Ac3d::Object::getTerrainHeight(double x, double y, double &terrainHeight, V3d &normal) const
|
||||
{
|
||||
if (getBoundingBox().pointInside(x, y))
|
||||
{
|
||||
if (type == "poly")
|
||||
{
|
||||
for (const auto &surface : surfaces)
|
||||
{
|
||||
double z;
|
||||
V3d n;
|
||||
|
||||
if (pointInside(surface, x, y, z, n))
|
||||
{
|
||||
if (z > terrainHeight)
|
||||
{
|
||||
terrainHeight = z;
|
||||
normal = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto &kid : kids)
|
||||
kid.getTerrainHeight(x, y, terrainHeight, normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Ac3d::Object::pointInside(const Surface &surface, double x, double y, double &z, V3d &normal) const
|
||||
{
|
||||
if (surface.refs.size() != 3)
|
||||
return false;
|
||||
|
||||
const double ax = vertices[surface.refs[0].index][0];
|
||||
const double ay = vertices[surface.refs[0].index][1];
|
||||
|
||||
const double as_x = x - ax;
|
||||
const double as_y = y - ay;
|
||||
|
||||
const double bx = vertices[surface.refs[1].index][0];
|
||||
const double by = vertices[surface.refs[1].index][1];
|
||||
|
||||
const bool s_ab = (bx - ax) * as_y - (by - ay) * as_x > 0;
|
||||
|
||||
const double cx = vertices[surface.refs[2].index][0];
|
||||
const double cy = vertices[surface.refs[2].index][1];
|
||||
|
||||
if ((cx - ax) * as_y - (cy - ay) * as_x > 0 == s_ab)
|
||||
return false;
|
||||
|
||||
if ((cx - bx) * (y - by) - (cy - by) * (x - bx) > 0 != s_ab)
|
||||
return false;
|
||||
|
||||
const V3d v1 = vertices[surface.refs[1].index] - vertices[surface.refs[0].index];
|
||||
const V3d v2 = vertices[surface.refs[2].index] - vertices[surface.refs[0].index];
|
||||
|
||||
const V3d n(v1.cross(v2));
|
||||
|
||||
const double d = n.dot(vertices[surface.refs[0].index]);
|
||||
|
||||
const V3d ray(0, 0, 1);
|
||||
|
||||
const double ndr = n.dot(ray);
|
||||
|
||||
if (ndr == 0)
|
||||
return false; // No intersection, the line is parallel to the plane
|
||||
|
||||
const V3d rayOrigin(x, y, 0);
|
||||
|
||||
z = (d - n.dot(rayOrigin)) / ndr;
|
||||
normal = n;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------ Ac3d -----------------------------------
|
||||
|
||||
Ac3d::Ac3d()
|
||||
|
@ -951,3 +1101,32 @@ void Ac3d::flipAxes(bool in)
|
|||
{
|
||||
root.flipAxes(in);
|
||||
}
|
||||
|
||||
void Ac3d::generateTriangles()
|
||||
{
|
||||
root.generateTriangles();
|
||||
}
|
||||
|
||||
double Ac3d::getTerrainHeight(double x, double y) const
|
||||
{
|
||||
double terrainHeight = -1000000;
|
||||
V3d terrainNormal;
|
||||
|
||||
root.getTerrainHeight(x, y, terrainHeight, terrainNormal);
|
||||
|
||||
return terrainHeight;
|
||||
}
|
||||
|
||||
double Ac3d::getTerrainAngle(double x, double y) const
|
||||
{
|
||||
double terrainHeight = -1000000;
|
||||
V3d terrainNormal;
|
||||
double angle = 0;
|
||||
|
||||
root.getTerrainHeight(x, y, terrainHeight, terrainNormal);
|
||||
|
||||
if (terrainHeight != -1000000)
|
||||
angle = 180.0 - atan2(terrainNormal[0], terrainNormal[1]) * 180.0 / PI;
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ struct Ac3d
|
|||
V3d operator+(const V3d &other) const;
|
||||
V3d operator-(const V3d &other) const;
|
||||
V3d operator/(double scalar) const;
|
||||
double dot(const V3d &other) const;
|
||||
V3d cross(const V3d &other) const;
|
||||
double length() const;
|
||||
};
|
||||
|
||||
|
@ -187,6 +189,8 @@ struct Ac3d
|
|||
-std::numeric_limits<double>::max() };
|
||||
|
||||
void extend(const V3d &vertex);
|
||||
void extend(const BoundingBox &boundingBox);
|
||||
bool pointInside(double x, double y) const;
|
||||
};
|
||||
|
||||
struct BoundingSphere
|
||||
|
@ -216,9 +220,15 @@ struct Ac3d
|
|||
bool locked = false;
|
||||
bool folded = false;
|
||||
std::vector<V3d> vertices;
|
||||
std::vector<Surface> surfaces;
|
||||
std::list<Surface> surfaces;
|
||||
std::list<Object> kids;
|
||||
|
||||
// not part of AC3D file
|
||||
mutable bool hasBoundingBox = false;
|
||||
mutable BoundingBox boundingBox;
|
||||
mutable bool hasBoundingSphere = false;
|
||||
mutable BoundingSphere boundingSphere;
|
||||
|
||||
Object() = default;
|
||||
Object(const std::string &type, const std::string &name) : type(type), name(name) { }
|
||||
explicit Object(std::ifstream &fin);
|
||||
|
@ -226,9 +236,12 @@ struct Ac3d
|
|||
void write(std::ofstream &fout) const;
|
||||
void transform(const Matrix &matrix);
|
||||
void flipAxes(bool in);
|
||||
BoundingBox getBoundingBox() const;
|
||||
BoundingSphere getBoundingSphere() const;
|
||||
const BoundingBox &getBoundingBox() const;
|
||||
const BoundingSphere &getBoundingSphere() const;
|
||||
void remapMaterials(const MaterialMap &materialMap);
|
||||
void generateTriangles();
|
||||
void getTerrainHeight(double x, double y, double &terrainHeight, V3d &normal) const;
|
||||
bool pointInside(const Surface &surface, double x, double y, double &z, V3d &normal) const;
|
||||
};
|
||||
|
||||
bool versionC = false;
|
||||
|
@ -244,7 +257,10 @@ struct Ac3d
|
|||
void flattenGeometry();
|
||||
void transform(const Matrix &matrix);
|
||||
void flipAxes(bool in);
|
||||
void generateTriangles();
|
||||
void merge(const Ac3d &ac3d);
|
||||
double getTerrainHeight(double x, double y) const;
|
||||
double getTerrainAngle(double x, double y) const;
|
||||
};
|
||||
|
||||
#endif /* _AC3D_H_ */
|
||||
|
|
Loading…
Reference in a new issue