Fix issue in Rocket.lua script.
[Cafu-Engine.git] / Libs / Math3D / BezierPatch.hpp
blobd7300c5c708cb8ff5751c96e0a4b2b5458aae74e
1 /*
2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
5 */
7 #ifndef CAFU_MATH_BEZIERPATCH_HPP_INCLUDED
8 #define CAFU_MATH_BEZIERPATCH_HPP_INCLUDED
10 #include "Math3D/Vector3.hpp"
11 #include "Templates/Array.hpp"
13 #include <cassert>
16 namespace cf
18 namespace math
20 /* class ControlDataT
22 public:
24 unsigned long Width;
25 unsigned long Height;
27 ArrayT< Vector3T<T> > Coords;
28 ArrayT< Vector3T<T> > TexCoords;
29 }; */
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>
40 class BezierPatchT
42 public:
44 /// Represents a single vertex.
45 struct VertexT
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.
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);
58 /// Constructor for creating an empty Bezier patch.
59 BezierPatchT();
61 /// Constructor for creating a patch from given coordinates.
62 BezierPatchT(unsigned long Width_, unsigned long Height_, const ArrayT< Vector3T<T> >& Coords_);
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_);
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();
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.
77 void ComputeTangentSpace_Obsolete();
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);
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);
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);
106 /// Returns the area of the Bezier patch surface around vertex (i, j).
107 T GetSurfaceAreaAtVertex(unsigned long i, unsigned long j) const;
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]; }
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]; }
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.
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.
127 private:
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;
140 #endif