1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "catmullclark_patch.h"
7#include "bezier_curve.h"
8
9namespace embree
10{
11 template<typename Vertex, typename Vertex_t = Vertex>
12 class __aligned(64) BilinearPatchT
13 {
14 typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
15 typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
16
17 public:
18 Vertex v[4];
19
20 public:
21
22 __forceinline BilinearPatchT () {}
23
24 __forceinline BilinearPatchT (const HalfEdge* edge, const BufferView<Vertex>& vertices) {
25 init(edge,vertices.getPtr(),vertices.getStride());
26 }
27
28 __forceinline BilinearPatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
29 init(edge,vertices,stride);
30 }
31
32 __forceinline void init (const HalfEdge* edge, const char* vertices, size_t stride)
33 {
34 v[0] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
35 v[1] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
36 v[2] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
37 v[3] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
38 }
39
40 __forceinline BilinearPatchT (const CatmullClarkPatch& patch)
41 {
42 v[0] = patch.ring[0].getLimitVertex();
43 v[1] = patch.ring[1].getLimitVertex();
44 v[2] = patch.ring[2].getLimitVertex();
45 v[3] = patch.ring[3].getLimitVertex();
46 }
47
48 __forceinline BBox<Vertex> bounds() const
49 {
50
51 BBox<Vertex> bounds (v[0]);
52 bounds.extend(v[1]);
53 bounds.extend(v[2]);
54 bounds.extend(v[3]);
55 return bounds;
56 }
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
62 __forceinline Vertex eval_du(const float uu, const float vv) const {
63 return lerp(v[1]-v[0],v[2]-v[3],vv);
64 }
65
66 __forceinline Vertex eval_dv(const float uu, const float vv) const {
67 return lerp(v[3]-v[0],v[2]-v[1],uu);
68 }
69
70 __forceinline Vertex eval_dudu(const float uu, const float vv) const {
71 return Vertex(zero);
72 }
73
74 __forceinline Vertex eval_dvdv(const float uu, const float vv) const {
75 return Vertex(zero);
76 }
77
78 __forceinline Vertex eval_dudv(const float uu, const float vv) const {
79 return (v[2]-v[3]) - (v[1]-v[0]);
80 }
81
82 __forceinline Vertex normal(const float uu, const float vv) const {
83 return cross(eval_du(uu,vv),eval_dv(uu,vv));
84 }
85
86 __forceinline void eval(const float u, const float v,
87 Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
88 const float dscale = 1.0f) const
89 {
90 if (P) {
91 *P = eval(u,v);
92 }
93 if (dPdu) {
94 assert(dPdu); *dPdu = eval_du(u,v)*dscale;
95 assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
96 }
97 if (ddPdudu) {
98 assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
99 assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
100 assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
101 }
102 }
103
104 template<class vfloat>
105 __forceinline Vec3<vfloat> eval(const vfloat& uu, const vfloat& vv) const
106 {
107 const vfloat x = lerp(lerp(v[0].x,v[1].x,uu),lerp(v[3].x,v[2].x,uu),vv);
108 const vfloat y = lerp(lerp(v[0].y,v[1].y,uu),lerp(v[3].y,v[2].y,uu),vv);
109 const vfloat z = lerp(lerp(v[0].z,v[1].z,uu),lerp(v[3].z,v[2].z,uu),vv);
110 return Vec3<vfloat>(x,y,z);
111 }
112
113 template<class vfloat>
114 __forceinline Vec3<vfloat> eval_du(const vfloat& uu, const vfloat& vv) const
115 {
116 const vfloat x = lerp(v[1].x-v[0].x,v[2].x-v[3].x,vv);
117 const vfloat y = lerp(v[1].y-v[0].y,v[2].y-v[3].y,vv);
118 const vfloat z = lerp(v[1].z-v[0].z,v[2].z-v[3].z,vv);
119 return Vec3<vfloat>(x,y,z);
120 }
121
122 template<class vfloat>
123 __forceinline Vec3<vfloat> eval_dv(const vfloat& uu, const vfloat& vv) const
124 {
125 const vfloat x = lerp(v[3].x-v[0].x,v[2].x-v[1].x,uu);
126 const vfloat y = lerp(v[3].y-v[0].y,v[2].y-v[1].y,uu);
127 const vfloat z = lerp(v[3].z-v[0].z,v[2].z-v[1].z,uu);
128 return Vec3<vfloat>(x,y,z);
129 }
130
131 template<typename vfloat>
132 __forceinline Vec3<vfloat> normal(const vfloat& uu, const vfloat& vv) const {
133 return cross(eval_du(uu,vv),eval_dv(uu,vv));
134 }
135
136 template<class vfloat>
137 __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv) const {
138 return lerp(lerp(v[0][i],v[1][i],uu),lerp(v[3][i],v[2][i],uu),vv);
139 }
140
141 template<class vfloat>
142 __forceinline vfloat eval_du(const size_t i, const vfloat& uu, const vfloat& vv) const {
143 return lerp(v[1][i]-v[0][i],v[2][i]-v[3][i],vv);
144 }
145
146 template<class vfloat>
147 __forceinline vfloat eval_dv(const size_t i, const vfloat& uu, const vfloat& vv) const {
148 return lerp(v[3][i]-v[0][i],v[2][i]-v[1][i],uu);
149 }
150
151 template<class vfloat>
152 __forceinline vfloat eval_dudu(const size_t i, const vfloat& uu, const vfloat& vv) const {
153 return vfloat(zero);
154 }
155
156 template<class vfloat>
157 __forceinline vfloat eval_dvdv(const size_t i, const vfloat& uu, const vfloat& vv) const {
158 return vfloat(zero);
159 }
160
161 template<class vfloat>
162 __forceinline vfloat eval_dudv(const size_t i, const vfloat& uu, const vfloat& vv) const {
163 return (v[2][i]-v[3][i]) - (v[1][i]-v[0][i]);
164 }
165
166 template<typename vbool, typename vfloat>
167 __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
168 float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
169 const float dscale, const size_t dstride, const size_t N) const
170 {
171 if (P) {
172 for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv));
173 }
174 if (dPdu) {
175 for (size_t i=0; i<N; i++) {
176 assert(dPdu); vfloat::store(valid,dPdu+i*dstride,eval_du(i,uu,vv)*dscale);
177 assert(dPdv); vfloat::store(valid,dPdv+i*dstride,eval_dv(i,uu,vv)*dscale);
178 }
179 }
180 if (ddPdudu) {
181 for (size_t i=0; i<N; i++) {
182 assert(ddPdudu); vfloat::store(valid,ddPdudu+i*dstride,eval_dudu(i,uu,vv)*sqr(dscale));
183 assert(ddPdvdv); vfloat::store(valid,ddPdvdv+i*dstride,eval_dvdv(i,uu,vv)*sqr(dscale));
184 assert(ddPdudv); vfloat::store(valid,ddPdudv+i*dstride,eval_dudv(i,uu,vv)*sqr(dscale));
185 }
186 }
187 }
188 };
189
190 typedef BilinearPatchT<Vec3fa,Vec3fa_t> BilinearPatch3fa;
191}
192