BSplineSurface.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/BasisFunction.h>
  9. #include <Mathematics/ParametricSurface.h>
  10. namespace WwiseGTE
  11. {
  12. template <int N, typename Real>
  13. class BSplineSurface : public ParametricSurface<N, Real>
  14. {
  15. public:
  16. // Construction. If the input controls is non-null, a copy is made of
  17. // the controls. To defer setting the control points, pass a null
  18. // pointer and later access the control points via GetControls() or
  19. // SetControl() member functions. The input 'controls' must be stored
  20. // in row-major order, control[i0 + numControls0*i1]. As a 2D array,
  21. // this corresponds to control2D[i1][i0].
  22. BSplineSurface(BasisFunctionInput<Real> const input[2], Vector<N, Real> const* controls)
  23. :
  24. ParametricSurface<N, Real>((Real)0, (Real)1, (Real)0, (Real)1, true)
  25. {
  26. for (int i = 0; i < 2; ++i)
  27. {
  28. mNumControls[i] = input[i].numControls;
  29. mBasisFunction[i].Create(input[i]);
  30. }
  31. // The mBasisFunction stores the domain but so does
  32. // ParametricCurve.
  33. this->mUMin = mBasisFunction[0].GetMinDomain();
  34. this->mUMax = mBasisFunction[0].GetMaxDomain();
  35. this->mVMin = mBasisFunction[1].GetMinDomain();
  36. this->mVMax = mBasisFunction[1].GetMaxDomain();
  37. // The replication of control points for periodic splines is
  38. // avoided by wrapping the i-loop index in Evaluate.
  39. int numControls = mNumControls[0] * mNumControls[1];
  40. mControls.resize(numControls);
  41. if (controls)
  42. {
  43. std::copy(controls, controls + numControls, mControls.begin());
  44. }
  45. else
  46. {
  47. Vector<N, Real> zero{ (Real)0 };
  48. std::fill(mControls.begin(), mControls.end(), zero);
  49. }
  50. this->mConstructed = true;
  51. }
  52. // Member access. The index 'dim' must be in {0,1}.
  53. inline BasisFunction<Real> const& GetBasisFunction(int dim) const
  54. {
  55. return mBasisFunction[dim];
  56. }
  57. inline int GetNumControls(int dim) const
  58. {
  59. return mNumControls[dim];
  60. }
  61. inline Vector<N, Real>* GetControls()
  62. {
  63. return mControls.data();
  64. }
  65. inline Vector<N, Real> const* GetControls() const
  66. {
  67. return mControls.data();
  68. }
  69. void SetControl(int i0, int i1, Vector<N, Real> const& control)
  70. {
  71. if (0 <= i0 && i0 < GetNumControls(0)
  72. && 0 <= i1 && i1 < GetNumControls(1))
  73. {
  74. mControls[i0 + mNumControls[0] * i1] = control;
  75. }
  76. }
  77. Vector<N, Real> const& GetControl(int i0, int i1) const
  78. {
  79. if (0 <= i0 && i0 < GetNumControls(0) && 0 <= i1 && i1 < GetNumControls(1))
  80. {
  81. return mControls[i0 + mNumControls[0] * i1];
  82. }
  83. else
  84. {
  85. return mControls[0];
  86. }
  87. }
  88. // Evaluation of the surface. The function supports derivative
  89. // calculation through order 2; that is, order <= 2 is required. If
  90. // you want only the position, pass in order of 0. If you want the
  91. // position and first-order derivatives, pass in order of 1, and so
  92. // on. The output array 'jet' must have enough storage to support the
  93. // maximum order. The values are ordered as: position X; first-order
  94. // derivatives dX/du, dX/dv; second-order derivatives d2X/du2,
  95. // d2X/dudv, d2X/dv2.
  96. virtual void Evaluate(Real u, Real v, unsigned int order, Vector<N, Real>* jet) const override
  97. {
  98. unsigned int const supOrder = ParametricSurface<N, Real>::SUP_ORDER;
  99. if (!this->mConstructed || order >= supOrder)
  100. {
  101. // Return a zero-valued jet for invalid state.
  102. for (unsigned int i = 0; i < supOrder; ++i)
  103. {
  104. jet[i].MakeZero();
  105. }
  106. return;
  107. }
  108. int iumin, iumax, ivmin, ivmax;
  109. mBasisFunction[0].Evaluate(u, order, iumin, iumax);
  110. mBasisFunction[1].Evaluate(v, order, ivmin, ivmax);
  111. // Compute position.
  112. jet[0] = Compute(0, 0, iumin, iumax, ivmin, ivmax);
  113. if (order >= 1)
  114. {
  115. // Compute first-order derivatives.
  116. jet[1] = Compute(1, 0, iumin, iumax, ivmin, ivmax);
  117. jet[2] = Compute(0, 1, iumin, iumax, ivmin, ivmax);
  118. if (order >= 2)
  119. {
  120. // Compute second-order derivatives.
  121. jet[3] = Compute(2, 0, iumin, iumax, ivmin, ivmax);
  122. jet[4] = Compute(1, 1, iumin, iumax, ivmin, ivmax);
  123. jet[5] = Compute(0, 2, iumin, iumax, ivmin, ivmax);
  124. }
  125. }
  126. }
  127. private:
  128. // Support for Evaluate(...).
  129. Vector<N, Real> Compute(unsigned int uOrder, unsigned int vOrder,
  130. int iumin, int iumax, int ivmin, int ivmax) const
  131. {
  132. // The j*-indices introduce a tiny amount of overhead in order to
  133. // handle both aperiodic and periodic splines. For aperiodic
  134. // splines, j* = i* always.
  135. int const numControls0 = mNumControls[0];
  136. int const numControls1 = mNumControls[1];
  137. Vector<N, Real> result;
  138. result.MakeZero();
  139. for (int iv = ivmin; iv <= ivmax; ++iv)
  140. {
  141. Real tmpv = mBasisFunction[1].GetValue(vOrder, iv);
  142. int jv = (iv >= numControls1 ? iv - numControls1 : iv);
  143. for (int iu = iumin; iu <= iumax; ++iu)
  144. {
  145. Real tmpu = mBasisFunction[0].GetValue(uOrder, iu);
  146. int ju = (iu >= numControls0 ? iu - numControls0 : iu);
  147. result += (tmpu * tmpv) * mControls[ju + numControls0 * jv];
  148. }
  149. }
  150. return result;
  151. }
  152. std::array<BasisFunction<Real>, 2> mBasisFunction;
  153. std::array<int, 2> mNumControls;
  154. std::vector<Vector<N, Real>> mControls;
  155. };
  156. }