Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/subdiv/patch_eval_grid.h
9913 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "patch.h"
7
#include "feature_adaptive_eval_grid.h"
8
9
namespace embree
10
{
11
namespace isa
12
{
13
struct PatchEvalGrid
14
{
15
typedef Patch3fa Patch;
16
typedef Patch::Ref Ref;
17
typedef GeneralCatmullClarkPatch3fa GeneralCatmullClarkPatch;
18
typedef CatmullClarkPatch3fa CatmullClarkPatch;
19
typedef BSplinePatch3fa BSplinePatch;
20
typedef BezierPatch3fa BezierPatch;
21
typedef GregoryPatch3fa GregoryPatch;
22
typedef BilinearPatch3fa BilinearPatch;
23
24
private:
25
const unsigned x0,x1;
26
const unsigned y0,y1;
27
const unsigned swidth,sheight;
28
const float rcp_swidth, rcp_sheight;
29
float* const Px;
30
float* const Py;
31
float* const Pz;
32
float* const U;
33
float* const V;
34
float* const Nx;
35
float* const Ny;
36
float* const Nz;
37
const unsigned dwidth,dheight;
38
unsigned count;
39
40
public:
41
42
PatchEvalGrid (Ref patch, unsigned subPatch,
43
const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
44
float* Px, float* Py, float* Pz, float* U, float* V,
45
float* Nx, float* Ny, float* Nz,
46
const unsigned dwidth, const unsigned dheight)
47
: x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
48
Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), dheight(dheight), count(0)
49
{
50
assert(swidth < (2<<20) && sheight < (2<<20));
51
const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(float(swidth-1),float(sheight-1)));
52
const BBox2f erange(Vec2f(float(x0),float(y0)),Vec2f((float)x1,(float)y1));
53
bool done MAYBE_UNUSED = eval(patch,subPatch,srange,erange);
54
assert(done);
55
assert(count == (x1-x0+1)*(y1-y0+1));
56
}
57
58
template<typename Patch>
59
__forceinline void evalLocalGrid(const Patch* patch, const BBox2f& srange, const int lx0, const int lx1, const int ly0, const int ly1)
60
{
61
const float scale_x = rcp(srange.upper.x-srange.lower.x);
62
const float scale_y = rcp(srange.upper.y-srange.lower.y);
63
count += (lx1-lx0)*(ly1-ly0);
64
65
#if 0
66
for (unsigned iy=ly0; iy<ly1; iy++) {
67
for (unsigned ix=lx0; ix<lx1; ix++) {
68
const float lu = select(ix == swidth -1, float(1.0f), (float(ix)-srange.lower.x)*scale_x);
69
const float lv = select(iy == sheight-1, float(1.0f), (float(iy)-srange.lower.y)*scale_y);
70
const Vec3fa p = patch->patch.eval(lu,lv);
71
const float u = float(ix)*rcp_swidth;
72
const float v = float(iy)*rcp_sheight;
73
const int ofs = (iy-y0)*dwidth+(ix-x0);
74
Px[ofs] = p.x;
75
Py[ofs] = p.y;
76
Pz[ofs] = p.z;
77
U[ofs] = u;
78
V[ofs] = v;
79
}
80
}
81
#else
82
foreach2(lx0,lx1,ly0,ly1,[&](const vboolx& valid, const vintx& ix, const vintx& iy) {
83
const vfloatx lu = select(ix == swidth -1, vfloatx(1.0f), (vfloatx(ix)-srange.lower.x)*scale_x);
84
const vfloatx lv = select(iy == sheight-1, vfloatx(1.0f), (vfloatx(iy)-srange.lower.y)*scale_y);
85
const Vec3vfx p = patch->patch.eval(lu,lv);
86
Vec3vfx n = zero;
87
if (unlikely(Nx != nullptr)) n = normalize_safe(patch->patch.normal(lu,lv));
88
const vfloatx u = vfloatx(ix)*rcp_swidth;
89
const vfloatx v = vfloatx(iy)*rcp_sheight;
90
const vintx ofs = (iy-y0)*dwidth+(ix-x0);
91
if (likely(all(valid)) && all(iy==iy[0])) {
92
const unsigned ofs2 = ofs[0];
93
vfloatx::storeu(Px+ofs2,p.x);
94
vfloatx::storeu(Py+ofs2,p.y);
95
vfloatx::storeu(Pz+ofs2,p.z);
96
vfloatx::storeu(U+ofs2,u);
97
vfloatx::storeu(V+ofs2,v);
98
if (unlikely(Nx != nullptr)) {
99
vfloatx::storeu(Nx+ofs2,n.x);
100
vfloatx::storeu(Ny+ofs2,n.y);
101
vfloatx::storeu(Nz+ofs2,n.z);
102
}
103
} else {
104
foreach_unique_index(valid,iy,[&](const vboolx& valid, const int iy0, const int j) {
105
const unsigned ofs2 = ofs[j]-j;
106
vfloatx::storeu(valid,Px+ofs2,p.x);
107
vfloatx::storeu(valid,Py+ofs2,p.y);
108
vfloatx::storeu(valid,Pz+ofs2,p.z);
109
vfloatx::storeu(valid,U+ofs2,u);
110
vfloatx::storeu(valid,V+ofs2,v);
111
if (unlikely(Nx != nullptr)) {
112
vfloatx::storeu(valid,Nx+ofs2,n.x);
113
vfloatx::storeu(valid,Ny+ofs2,n.y);
114
vfloatx::storeu(valid,Nz+ofs2,n.z);
115
}
116
});
117
}
118
});
119
#endif
120
}
121
122
bool eval(Ref This, const BBox2f& srange, const BBox2f& erange, const unsigned depth)
123
{
124
if (erange.empty())
125
return true;
126
127
const int lx0 = (int) ceilf(erange.lower.x);
128
const int lx1 = (int) ceilf(erange.upper.x) + (erange.upper.x == x1 && (srange.lower.x < erange.upper.x || erange.upper.x == 0));
129
const int ly0 = (int) ceilf(erange.lower.y);
130
const int ly1 = (int) ceilf(erange.upper.y) + (erange.upper.y == y1 && (srange.lower.y < erange.upper.y || erange.upper.y == 0));
131
if (lx0 >= lx1 || ly0 >= ly1)
132
return true;
133
134
if (!This)
135
return false;
136
137
switch (This.type())
138
{
139
case Patch::BILINEAR_PATCH: {
140
evalLocalGrid((Patch::BilinearPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
141
return true;
142
}
143
case Patch::BSPLINE_PATCH: {
144
evalLocalGrid((Patch::BSplinePatch*)This.object(),srange,lx0,lx1,ly0,ly1);
145
return true;
146
}
147
case Patch::BEZIER_PATCH: {
148
evalLocalGrid((Patch::BezierPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
149
return true;
150
}
151
case Patch::GREGORY_PATCH: {
152
evalLocalGrid((Patch::GregoryPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
153
return true;
154
}
155
case Patch::SUBDIVIDED_QUAD_PATCH:
156
{
157
const Vec2f c = srange.center();
158
const BBox2f srange0(srange.lower,c);
159
const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
160
const BBox2f srange2(c,srange.upper);
161
const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
162
163
Patch::SubdividedQuadPatch* patch = (Patch::SubdividedQuadPatch*)This.object();
164
eval(patch->child[0],srange0,intersect(srange0,erange),depth+1);
165
eval(patch->child[1],srange1,intersect(srange1,erange),depth+1);
166
eval(patch->child[2],srange2,intersect(srange2,erange),depth+1);
167
eval(patch->child[3],srange3,intersect(srange3,erange),depth+1);
168
return true;
169
}
170
case Patch::EVAL_PATCH: {
171
CatmullClarkPatch patch; patch.deserialize(This.object());
172
FeatureAdaptiveEvalGrid(patch,srange,erange,depth,x0,x1,y0,y1,swidth,sheight,Px,Py,Pz,U,V,Nx,Ny,Nz,dwidth,dheight);
173
count += (lx1-lx0)*(ly1-ly0);
174
return true;
175
}
176
default:
177
assert(false);
178
return false;
179
}
180
}
181
182
bool eval(Ref This, unsigned subPatch, const BBox2f& srange, const BBox2f& erange)
183
{
184
if (!This)
185
return false;
186
187
switch (This.type())
188
{
189
case Patch::SUBDIVIDED_GENERAL_PATCH: {
190
Patch::SubdividedGeneralPatch* patch = (Patch::SubdividedGeneralPatch*)This.object();
191
assert(subPatch < patch->N);
192
return eval(patch->child[subPatch],srange,erange,1);
193
}
194
default:
195
assert(subPatch == 0);
196
return eval(This,srange,erange,0);
197
}
198
}
199
};
200
201
__forceinline unsigned patch_eval_subdivision_count (const HalfEdge* h)
202
{
203
const unsigned N = h->numEdges();
204
if (N == 4) return 1;
205
else return N;
206
}
207
208
template<typename Tessellator>
209
inline void patch_eval_subdivision (const HalfEdge* h, Tessellator tessellator)
210
{
211
const unsigned N = h->numEdges();
212
int neighborSubdiv[GeneralCatmullClarkPatch3fa::SIZE]; // FIXME: use array_t
213
float levels[GeneralCatmullClarkPatch3fa::SIZE];
214
for (unsigned i=0; i<N; i++) {
215
assert(i<GeneralCatmullClarkPatch3fa::SIZE);
216
neighborSubdiv[i] = h->hasOpposite() ? h->opposite()->numEdges() != 4 : 0;
217
levels[i] = h->edge_level;
218
h = h->next();
219
}
220
if (N == 4)
221
{
222
const Vec2f uv[4] = { Vec2f(0.0f,0.0f), Vec2f(1.0f,0.0f), Vec2f(1.0f,1.0f), Vec2f(0.0f,1.0f) };
223
tessellator(uv,neighborSubdiv,levels,0);
224
}
225
else
226
{
227
for (unsigned i=0; i<N; i++)
228
{
229
assert(i<MAX_PATCH_VALENCE);
230
static_assert(MAX_PATCH_VALENCE <= 16, "MAX_PATCH_VALENCE > 16");
231
const int h = (i >> 2) & 3, l = i & 3;
232
const Vec2f subPatchID((float)l,(float)h);
233
const Vec2f uv[4] = { 2.0f*subPatchID + (0.5f+Vec2f(0.0f,0.0f)),
234
2.0f*subPatchID + (0.5f+Vec2f(1.0f,0.0f)),
235
2.0f*subPatchID + (0.5f+Vec2f(1.0f,1.0f)),
236
2.0f*subPatchID + (0.5f+Vec2f(0.0f,1.0f)) };
237
const int neighborSubdiv1[4] = { 0,0,0,0 };
238
const float levels1[4] = { 0.5f*levels[(i+0)%N], 0.5f*levels[(i+0)%N], 0.5f*levels[(i+N-1)%N], 0.5f*levels[(i+N-1)%N] };
239
tessellator(uv,neighborSubdiv1,levels1,i);
240
}
241
}
242
}
243
}
244
}
245
246
247