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]);
|
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 -----------------------------------
|
//----------------------------------- Color -----------------------------------
|
||||||
|
|
||||||
//---------------------------------- Material ---------------------------------
|
//---------------------------------- 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 ------------------------------
|
//------------------------------- Boundingsphere ------------------------------
|
||||||
|
|
||||||
void Ac3d::BoundingSphere::extend(const BoundingBox &boundingBox)
|
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
|
||||||
|
{
|
||||||
|
if (type == "poly")
|
||||||
|
{
|
||||||
|
if (!hasBoundingBox)
|
||||||
{
|
{
|
||||||
BoundingBox bb;
|
|
||||||
|
|
||||||
for (const auto &vertex : vertices)
|
for (const auto &vertex : vertices)
|
||||||
bb.extend(vertex);
|
boundingBox.extend(vertex);
|
||||||
|
|
||||||
return bb;
|
hasBoundingBox = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const auto &kid : kids)
|
||||||
|
boundingBox.extend(kid.getBoundingBox());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ac3d::BoundingSphere Ac3d::Object::getBoundingSphere() const
|
return boundingBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Ac3d::BoundingSphere &Ac3d::Object::getBoundingSphere() const
|
||||||
{
|
{
|
||||||
BoundingSphere bs;
|
if (!hasBoundingSphere)
|
||||||
bs.extend(getBoundingBox());
|
{
|
||||||
return bs;
|
boundingSphere.extend(getBoundingBox());
|
||||||
|
hasBoundingSphere = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return boundingSphere;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ac3d::Object::remapMaterials(const MaterialMap &materialMap)
|
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::Ac3d()
|
Ac3d::Ac3d()
|
||||||
|
@ -951,3 +1101,32 @@ void Ac3d::flipAxes(bool in)
|
||||||
{
|
{
|
||||||
root.flipAxes(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-(const V3d &other) const;
|
V3d operator-(const V3d &other) const;
|
||||||
V3d operator/(double scalar) const;
|
V3d operator/(double scalar) const;
|
||||||
|
double dot(const V3d &other) const;
|
||||||
|
V3d cross(const V3d &other) const;
|
||||||
double length() const;
|
double length() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -187,6 +189,8 @@ struct Ac3d
|
||||||
-std::numeric_limits<double>::max() };
|
-std::numeric_limits<double>::max() };
|
||||||
|
|
||||||
void extend(const V3d &vertex);
|
void extend(const V3d &vertex);
|
||||||
|
void extend(const BoundingBox &boundingBox);
|
||||||
|
bool pointInside(double x, double y) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BoundingSphere
|
struct BoundingSphere
|
||||||
|
@ -216,9 +220,15 @@ struct Ac3d
|
||||||
bool locked = false;
|
bool locked = false;
|
||||||
bool folded = false;
|
bool folded = false;
|
||||||
std::vector<V3d> vertices;
|
std::vector<V3d> vertices;
|
||||||
std::vector<Surface> surfaces;
|
std::list<Surface> surfaces;
|
||||||
std::list<Object> kids;
|
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() = default;
|
||||||
Object(const std::string &type, const std::string &name) : type(type), name(name) { }
|
Object(const std::string &type, const std::string &name) : type(type), name(name) { }
|
||||||
explicit Object(std::ifstream &fin);
|
explicit Object(std::ifstream &fin);
|
||||||
|
@ -226,9 +236,12 @@ struct Ac3d
|
||||||
void write(std::ofstream &fout) const;
|
void write(std::ofstream &fout) const;
|
||||||
void transform(const Matrix &matrix);
|
void transform(const Matrix &matrix);
|
||||||
void flipAxes(bool in);
|
void flipAxes(bool in);
|
||||||
BoundingBox getBoundingBox() const;
|
const BoundingBox &getBoundingBox() const;
|
||||||
BoundingSphere getBoundingSphere() const;
|
const BoundingSphere &getBoundingSphere() const;
|
||||||
void remapMaterials(const MaterialMap &materialMap);
|
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;
|
bool versionC = false;
|
||||||
|
@ -244,7 +257,10 @@ struct Ac3d
|
||||||
void flattenGeometry();
|
void flattenGeometry();
|
||||||
void transform(const Matrix &matrix);
|
void transform(const Matrix &matrix);
|
||||||
void flipAxes(bool in);
|
void flipAxes(bool in);
|
||||||
|
void generateTriangles();
|
||||||
void merge(const Ac3d &ac3d);
|
void merge(const Ac3d &ac3d);
|
||||||
|
double getTerrainHeight(double x, double y) const;
|
||||||
|
double getTerrainAngle(double x, double y) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _AC3D_H_ */
|
#endif /* _AC3D_H_ */
|
||||||
|
|
Loading…
Reference in a new issue