BezierPatch.hpp
1 /*
2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
5 */
6
7 #ifndef CAFU_MATH_BEZIERPATCH_HPP_INCLUDED
8 #define CAFU_MATH_BEZIERPATCH_HPP_INCLUDED
9
10 #include "Math3D/Vector3.hpp"
11 #include "Templates/Array.hpp"
12
13 #include <cassert>
14
15
16 namespace cf
17 {
18  namespace math
19  {
20  /* class ControlDataT
21  {
22  public:
23
24  unsigned long Width;
25  unsigned long Height;
26
27  ArrayT< Vector3T<T> > Coords;
28  ArrayT< Vector3T<T> > TexCoords;
29  }; */
30
31
32  /// This class represents a mesh that approximates a Bezier patch.
33  /// Two invariants are possible:
34  /// a) Before one of the Subdivide() methods has been called, the mesh is considered to be a control mesh.
35  /// A control mesh consists alternatingly of interpolation and approximation vertices which are quasi a
36  /// composition of 3x3 sub-patches with shared borders. The width and height therefore must be odd numbers >= 3.
37  /// b) After one of the Subdivide() methods has been called, the mesh is just an approximation of the Bezier patch.
38  /// Contrary to a), all it's vertices lie on the patch curve.
39  template<class T>
41  {
42  public:
43
44  /// Represents a single vertex.
45  struct VertexT
46  {
47  Vector3T<T> Coord; ///< Vertex coordinate.
48  Vector3T<T> TexCoord; ///< Vertex texture coordinates.
49  Vector3T<T> Normal; ///< Vertex normal.
50  Vector3T<T> TangentS; ///< DOCTODO.
51  Vector3T<T> TangentT; ///< DOCTODO.
52
53  /// Computes the values of this vertex as the average of the given vertices A and B.
54  void Average(const VertexT& A, const VertexT& B);
55  };
56
57
58  /// Constructor for creating an empty Bezier patch.
59  BezierPatchT();
60
61  /// Constructor for creating a patch from given coordinates.
62  BezierPatchT(unsigned long Width_, unsigned long Height_, const ArrayT< Vector3T<T> >& Coords_);
63
64  /// Constructor for creating a patch from given coordinates and texture-coordinates.
65  BezierPatchT(unsigned long Width_, unsigned long Height_, const ArrayT< Vector3T<T> >& Coords_, const ArrayT< Vector3T<T> >& TexCoords_);
66
67  /// (Re-)computes the tangent space vectors (normal and tangents) for each vertex of the mesh.
68  /// This method must only be called *before* any of the Subdivide() methods is called, it does not work thereafter.
69  void ComputeTangentSpace();
70
71  /// (Re-)computes the tangent space vectors (normal and tangents) for each vertex of the mesh.
72  /// This method is supposed to be called before one of the Subdivide() methods is called, but it is actually independent of it.
73  /// That is, it does not matter whether this method is called first and Subdivide() second, or vice versa - both orders are
74  /// possible and valid, and they should even yield the same result.
75  /// OBSOLETE NOTE: This method does not really work reliable, the tangent space axes that it generates are frequently questionable...
76  /// Instead of debugging its code, I rather provide a completely new implementation in a seperate method.
78
79  /// This method subdivides the patch "automatically", that is, by the given maximal error and length bounds.
80  /// @param MaxError The maximum allowed spatial distance between the computed approximation mesh and the true mathematical curve.
81  /// @param MaxLength The maximum side length that one mesh element may have.
82  /// @param OptimizeFlat If true unnecessary vertices from flat substrips are removed.
83  void Subdivide(T MaxError, T MaxLength, bool OptimizeFlat=true);
84
85  /// Subdivides the patch "manually", that is, as often as explicitly stated by the parameter values.
86  /// @param SubDivsHorz The number of horizontal subdivisions that each 3x3 sub-patch is subdivided into.
87  /// @param SubDivsVert The number of vertical subdivisions that each 3x3 sub-patch is subdivided into.
88  /// @param OptimizeFlat If true unnecessary vertices from flat substrips are removed.
89  void Subdivide(unsigned long SubDivsHorz, unsigned long SubDivsVert, bool OptimizeFlat=true);
90
91  /// Intended to be called *after* one of the Subdivide() methods has been called,
92  /// this methods linearly subdivides the rows and columns of the mesh so that the MaxLength is never exceeded.
93  /// This is useful/intended for obtaining meshes for lightmap computation purposes.
94  /// Note that this method quasi does the very opposite from what OptimizeFlatRowAndColumnStrips() does:
95  /// it inserts "flat" (linear) rows and columns of vertices.
96  /// Q: Couldn't we just call Subdivide(LargeNum, MaxLength, false); to achieve the same result?
97  /// A: No!! Two counter examples, both observed with the handrails in the TechDemo map:
98  /// a) The end pads are small 3x3 patches with sides shorter than MaxLength. However they are not
99  /// reduced to 2x2 meshes when Subdivide() is called with OptimizeFlat being set to false.
100  /// b) The rails themselves suffer from the same problem (at each of the four cylindrical sides),
101  /// *plus* they rely on their explicitly stated number of subdivisions for ignoring their central
102  /// interpolating control vertex, whose consideration would deform the handrail!
103  /// @param MaxLength Maximum length of the subdivisions.
104  void ForceLinearMaxLength(T MaxLength);
105
106  /// Returns the area of the Bezier patch surface around vertex (i, j).
107  T GetSurfaceAreaAtVertex(unsigned long i, unsigned long j) const;
108
109  /// Returns the const mesh vertex at (i, j).
110  const VertexT& GetVertex(unsigned long i, unsigned long j) const { assert(i<Width && j<Height); return Mesh[j*Width+i]; }
111
112  /// Returns the (non-const) mesh vertex at (i, j).
113  VertexT& GetVertex(unsigned long i, unsigned long j) { assert(i<Width && j<Height); return Mesh[j*Width+i]; }
114
115  bool WrapsHorz() const; ///< Returns whether the left and right borders are identical.
116  bool WrapsVert() const; ///< Returns whether the top and bottom borders are identical.
117
118
119  // The mesh is a regular array of Width*Height components, stored as a series of rows.
120  // The GetMesh() methods are provided for convenient access.
121  // TODO: Make private and provide const get methods instead?
122  unsigned long Width; ///< Number of vertices in width direction.
123  unsigned long Height; ///< Number of vertices in height direction.
124  ArrayT<VertexT> Mesh; ///< Array of Width*Heights vertices that build up the bezier patch.
125
126
127  private:
128
129  // Helper methods for the Subdivide() methods.
130  void SetMeshSize(unsigned long NewWidth, unsigned long NewHeight);
131  VertexT SampleSinglePatchPoint(const VertexT SubPatch[3][3], const T u, const T v) const;
132  void SampleSinglePatch(const VertexT SubPatch[3][3], unsigned long baseCol, unsigned long baseRow, unsigned long TargetWidth, unsigned long SubDivsHorz, unsigned long SubDivsVert, ArrayT<VertexT>& TargetMesh) const;
133  Vector3T<T> ProjectPointOntoVector(const Vector3T<T>& Point, const Vector3T<T>& Start, const Vector3T<T>& End) const;
134  void OptimizeFlatRowAndColumnStrips();
135  bool ComputeTangentSpaceInSubPatch(unsigned long sp_i, unsigned long sp_j, const T s, const T t, Vector3T<T> Axes[3]) const;
136  };
137  }
138 }
139
140 #endif
Vector3T< T > Normal
Vertex normal.
Definition: BezierPatch.hpp:49
Vector3T< T > Coord
Vertex coordinate.
Definition: BezierPatch.hpp:47
bool WrapsHorz() const
Returns whether the left and right borders are identical.
Definition: BezierPatch.cpp:888
Vector3T< T > TangentS
DOCTODO.
Definition: BezierPatch.hpp:50
void Subdivide(T MaxError, T MaxLength, bool OptimizeFlat=true)
This method subdivides the patch "automatically", that is, by the given maximal error and length boun...
Definition: BezierPatch.cpp:356
T GetSurfaceAreaAtVertex(unsigned long i, unsigned long j) const
Returns the area of the Bezier patch surface around vertex (i, j).
Definition: BezierPatch.cpp:657
Represents a single vertex.
Definition: BezierPatch.hpp:45
This class represents a polymorphic 3-dimensional vector.
Definition: Misc.hpp:11
BezierPatchT()
Constructor for creating an empty Bezier patch.
Definition: BezierPatch.cpp:66
const VertexT & GetVertex(unsigned long i, unsigned long j) const
Returns the const mesh vertex at (i, j).
Definition: BezierPatch.hpp:110
VertexT & GetVertex(unsigned long i, unsigned long j)
Returns the (non-const) mesh vertex at (i, j).
Definition: BezierPatch.hpp:113
unsigned long Width
Number of vertices in width direction.
Definition: BezierPatch.hpp:122
void ForceLinearMaxLength(T MaxLength)
Intended to be called after one of the Subdivide() methods has been called, this methods linearly sub...
Definition: BezierPatch.cpp:585
ArrayT< VertexT > Mesh
Array of Width*Heights vertices that build up the bezier patch.
Definition: BezierPatch.hpp:124
unsigned long Height
Number of vertices in height direction.
Definition: BezierPatch.hpp:123
void Average(const VertexT &A, const VertexT &B)
Computes the values of this vertex as the average of the given vertices A and B.
Definition: BezierPatch.cpp:54
void ComputeTangentSpace_Obsolete()
(Re-)computes the tangent space vectors (normal and tangents) for each vertex of the mesh...
Definition: BezierPatch.cpp:192
Vector3T< T > TexCoord
Vertex texture coordinates.
Definition: BezierPatch.hpp:48
bool WrapsVert() const
Returns whether the top and bottom borders are identical.
Definition: BezierPatch.cpp:899
Definition: Renderer.hpp:16
void ComputeTangentSpace()
(Re-)computes the tangent space vectors (normal and tangents) for each vertex of the mesh...
Definition: BezierPatch.cpp:100
This class represents a mesh that approximates a Bezier patch.
Definition: BezierPatch.hpp:40
Vector3T< T > TangentT
DOCTODO.
Definition: BezierPatch.hpp:51