You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

98 lines
3.8 KiB

// David Eberly, Geometric Tools, Redmond WA 98052
// Copyright (c) 1998-2021
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
// https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
// Version: 4.0.2019.08.13
#pragma once
#include <Mathematics/AlignedBox.h>
#include <Mathematics/Vector4.h>
#include <cstdint>
#include <vector>
namespace gte
{
template <typename Real>
class ConvexPolyhedron3
{
public:
// Construction. The convex polyhedra represented by this class has
// triangle faces that are counterclockwise ordered when viewed from
// outside the polyhedron. No attempt is made to verify that the
// polyhedron is convex; the caller is responsible for enforcing this.
// The constructors move (not copy!) the input arrays. The
// constructor succeeds when the number of vertices is at least 4 and
// the number of indices is at least 12. If the constructor fails,
// no move occurs and the member arrays have no elements.
//
// To support geometric algorithms that are formulated using convex
// quadratic programming (such as computing the distance from a point
// to a convex polyhedron), it is necessary to know the planes of the
// faces and an axis-aligned bounding box. If you want either the
// faces or the box, pass 'true' to the appropriate parameters. When
// planes are generated, the normals are not created to be unit length
// in order to support queries using exact rational arithmetic. If a
// normal to a face is N = (n0,n1,n2) and V is a vertex of the face,
// the plane is Dot(N,X-V) = 0 and is stored as
// Dot(n0,n1,n2,-Dot(N,V)). The normals are computed to be outer
// pointing.
ConvexPolyhedron3() = default;
ConvexPolyhedron3(std::vector<Vector3<Real>>&& inVertices, std::vector<int>&& inIndices,
bool wantPlanes, bool wantAlignedBox)
{
if (inVertices.size() >= 4 && inIndices.size() >= 12)
{
vertices = std::move(inVertices);
indices = std::move(inIndices);
if (wantPlanes)
{
GeneratePlanes();
}
if (wantAlignedBox)
{
GenerateAlignedBox();
}
}
}
// If you modifty the vertices or indices and you want the new face
// planes or aligned box computed, call these functions.
void GeneratePlanes()
{
if (vertices.size() > 0 && indices.size() > 0)
{
uint32_t const numTriangles = static_cast<uint32_t>(indices.size()) / 3;
planes.resize(numTriangles);
for (uint32_t t = 0, i = 0; t < numTriangles; ++t)
{
Vector3<Real> V0 = vertices[indices[i++]];
Vector3<Real> V1 = vertices[indices[i++]];
Vector3<Real> V2 = vertices[indices[i++]];
Vector3<Real> E1 = V1 - V0;
Vector3<Real> E2 = V2 - V0;
Vector3<Real> N = Cross(E1, E2);
planes[t] = HLift(N, -Dot(N, V0));
}
}
}
void GenerateAlignedBox()
{
if (vertices.size() > 0 && indices.size() > 0)
{
ComputeExtremes(static_cast<int>(vertices.size()), vertices.data(),
alignedBox.min, alignedBox.max);
}
}
std::vector<Vector3<Real>> vertices;
std::vector<int> indices;
std::vector<Vector4<Real>> planes;
AlignedBox3<Real> alignedBox;
};
}