bilinear_patch.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "catmullclark_patch.h"
  18. #include "bezier_curve.h"
  19. namespace embree
  20. {
  21. template<typename Vertex, typename Vertex_t = Vertex>
  22. class __aligned(64) BilinearPatchT
  23. {
  24. typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
  25. typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
  26. public:
  27. Vertex v[4];
  28. public:
  29. __forceinline BilinearPatchT () {}
  30. __forceinline BilinearPatchT (const HalfEdge* edge, const BufferRefT<Vertex>& vertices) {
  31. init(edge,vertices.getPtr(),vertices.getStride());
  32. }
  33. __forceinline BilinearPatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
  34. init(edge,vertices,stride);
  35. }
  36. __forceinline void init (const HalfEdge* edge, const char* vertices, size_t stride)
  37. {
  38. v[0] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
  39. v[1] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
  40. v[2] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
  41. v[3] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
  42. }
  43. __forceinline BilinearPatchT (const CatmullClarkPatch& patch)
  44. {
  45. v[0] = patch.ring[0].getLimitVertex();
  46. v[1] = patch.ring[1].getLimitVertex();
  47. v[2] = patch.ring[2].getLimitVertex();
  48. v[3] = patch.ring[3].getLimitVertex();
  49. }
  50. __forceinline BBox<Vertex> bounds() const
  51. {
  52. BBox<Vertex> bounds (v[0]);
  53. bounds.extend(v[1]);
  54. bounds.extend(v[2]);
  55. bounds.extend(v[3]);
  56. return bounds;
  57. }
  58. __forceinline Vertex eval(const float uu, const float vv) const {
  59. return lerp(lerp(v[0],v[1],uu),lerp(v[3],v[2],uu),vv);
  60. }
  61. __forceinline Vertex eval_du(const float uu, const float vv) const {
  62. return lerp(v[1]-v[0],v[2]-v[3],vv);
  63. }
  64. __forceinline Vertex eval_dv(const float uu, const float vv) const {
  65. return lerp(v[3]-v[0],v[2]-v[1],uu);
  66. }
  67. __forceinline Vertex eval_dudu(const float uu, const float vv) const {
  68. return Vertex(zero);
  69. }
  70. __forceinline Vertex eval_dvdv(const float uu, const float vv) const {
  71. return Vertex(zero);
  72. }
  73. __forceinline Vertex eval_dudv(const float uu, const float vv) const {
  74. return (v[2]-v[3]) - (v[1]-v[0]);
  75. }
  76. __forceinline Vertex normal(const float uu, const float vv) const {
  77. return cross(eval_dv(uu,vv),eval_du(uu,vv));
  78. }
  79. __forceinline void eval(const float u, const float v,
  80. Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
  81. const float dscale = 1.0f) const
  82. {
  83. if (P) {
  84. *P = eval(u,v);
  85. }
  86. if (dPdu) {
  87. assert(dPdu); *dPdu = eval_du(u,v)*dscale;
  88. assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
  89. }
  90. if (ddPdudu) {
  91. assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
  92. assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
  93. assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
  94. }
  95. }
  96. template<class vfloat>
  97. __forceinline Vec3<vfloat> eval(const vfloat& uu, const vfloat& vv) const
  98. {
  99. const vfloat x = lerp(lerp(v[0].x,v[1].x,uu),lerp(v[3].x,v[2].x,uu),vv);
  100. const vfloat y = lerp(lerp(v[0].y,v[1].y,uu),lerp(v[3].y,v[2].y,uu),vv);
  101. const vfloat z = lerp(lerp(v[0].z,v[1].z,uu),lerp(v[3].z,v[2].z,uu),vv);
  102. return Vec3<vfloat>(x,y,z);
  103. }
  104. template<class vfloat>
  105. __forceinline Vec3<vfloat> eval_du(const vfloat& uu, const vfloat& vv) const
  106. {
  107. const vfloat x = lerp(v[1].x-v[0].x,v[2].x-v[3].x,vv);
  108. const vfloat y = lerp(v[1].y-v[0].y,v[2].y-v[3].y,vv);
  109. const vfloat z = lerp(v[1].z-v[0].z,v[2].z-v[3].z,vv);
  110. return Vec3<vfloat>(x,y,z);
  111. }
  112. template<class vfloat>
  113. __forceinline Vec3<vfloat> eval_dv(const vfloat& uu, const vfloat& vv) const
  114. {
  115. const vfloat x = lerp(v[3].x-v[0].x,v[2].x-v[1].x,uu);
  116. const vfloat y = lerp(v[3].y-v[0].y,v[2].y-v[1].y,uu);
  117. const vfloat z = lerp(v[3].z-v[0].z,v[2].z-v[1].z,uu);
  118. return Vec3<vfloat>(x,y,z);
  119. }
  120. template<typename vfloat>
  121. __forceinline Vec3<vfloat> normal(const vfloat& uu, const vfloat& vv) const {
  122. return cross(eval_dv(uu,vv),eval_du(uu,vv));
  123. }
  124. template<class vfloat>
  125. __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv) const {
  126. return lerp(lerp(v[0][i],v[1][i],uu),lerp(v[3][i],v[2][i],uu),vv);
  127. }
  128. template<class vfloat>
  129. __forceinline vfloat eval_du(const size_t i, const vfloat& uu, const vfloat& vv) const {
  130. return lerp(v[1][i]-v[0][i],v[2][i]-v[3][i],vv);
  131. }
  132. template<class vfloat>
  133. __forceinline vfloat eval_dv(const size_t i, const vfloat& uu, const vfloat& vv) const {
  134. return lerp(v[3][i]-v[0][i],v[2][i]-v[1][i],uu);
  135. }
  136. template<class vfloat>
  137. __forceinline vfloat eval_dudu(const size_t i, const vfloat& uu, const vfloat& vv) const {
  138. return vfloat(zero);
  139. }
  140. template<class vfloat>
  141. __forceinline vfloat eval_dvdv(const size_t i, const vfloat& uu, const vfloat& vv) const {
  142. return vfloat(zero);
  143. }
  144. template<class vfloat>
  145. __forceinline vfloat eval_dudv(const size_t i, const vfloat& uu, const vfloat& vv) const {
  146. return (v[2][i]-v[3][i]) - (v[1][i]-v[0][i]);
  147. }
  148. template<typename vbool, typename vfloat>
  149. __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
  150. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
  151. const float dscale, const size_t dstride, const size_t N) const
  152. {
  153. if (P) {
  154. for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv));
  155. }
  156. if (dPdu) {
  157. for (size_t i=0; i<N; i++) {
  158. assert(dPdu); vfloat::store(valid,dPdu+i*dstride,eval_du(i,uu,vv)*dscale);
  159. assert(dPdv); vfloat::store(valid,dPdv+i*dstride,eval_dv(i,uu,vv)*dscale);
  160. }
  161. }
  162. if (ddPdudu) {
  163. for (size_t i=0; i<N; i++) {
  164. assert(ddPdudu); vfloat::store(valid,ddPdudu+i*dstride,eval_dudu(i,uu,vv)*sqr(dscale));
  165. assert(ddPdvdv); vfloat::store(valid,ddPdvdv+i*dstride,eval_dvdv(i,uu,vv)*sqr(dscale));
  166. assert(ddPdudv); vfloat::store(valid,ddPdudv+i*dstride,eval_dudv(i,uu,vv)*sqr(dscale));
  167. }
  168. }
  169. }
  170. };
  171. typedef BilinearPatchT<Vec3fa,Vec3fa_t> BilinearPatch3fa;
  172. }