1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "../common/scene.h" |
7 | #include "../common/primref.h" |
8 | |
9 | namespace embree |
10 | { |
11 | namespace isa |
12 | { |
13 | template<size_t N> |
14 | __forceinline void splitPolygon(const BBox3fa& bounds, |
15 | const size_t dim, |
16 | const float pos, |
17 | const Vec3fa (&v)[N+1], |
18 | const Vec3fa (&inv_length)[N], |
19 | BBox3fa& left_o, |
20 | BBox3fa& right_o) |
21 | { |
22 | BBox3fa left = empty, right = empty; |
23 | /* clip triangle to left and right box by processing all edges */ |
24 | for (size_t i=0; i<N; i++) |
25 | { |
26 | const Vec3fa &v0 = v[i]; |
27 | const Vec3fa &v1 = v[i+1]; |
28 | const float v0d = v0[dim]; |
29 | const float v1d = v1[dim]; |
30 | |
31 | if (v0d <= pos) left. extend(other: v0); // this point is on left side |
32 | if (v0d >= pos) right.extend(other: v0); // this point is on right side |
33 | |
34 | if ((v0d < pos && pos < v1d) || (v1d < pos && pos < v0d)) // the edge crosses the splitting location |
35 | { |
36 | assert((v1d-v0d) != 0.0f); |
37 | const Vec3fa c = madd(a: Vec3fa((pos-v0d)*inv_length[i][dim]),b: v1-v0,c: v0); |
38 | left.extend(other: c); |
39 | right.extend(other: c); |
40 | } |
41 | } |
42 | |
43 | /* clip against current bounds */ |
44 | left_o = intersect(a: left,b: bounds); |
45 | right_o = intersect(a: right,b: bounds); |
46 | } |
47 | |
48 | template<size_t N> |
49 | __forceinline void splitPolygon(const PrimRef& prim, |
50 | const size_t dim, |
51 | const float pos, |
52 | const Vec3fa (&v)[N+1], |
53 | PrimRef& left_o, |
54 | PrimRef& right_o) |
55 | { |
56 | BBox3fa left = empty, right = empty; |
57 | for (size_t i=0; i<N; i++) |
58 | { |
59 | const Vec3fa &v0 = v[i]; |
60 | const Vec3fa &v1 = v[i+1]; |
61 | const float v0d = v0[dim]; |
62 | const float v1d = v1[dim]; |
63 | |
64 | if (v0d <= pos) left. extend(other: v0); // this point is on left side |
65 | if (v0d >= pos) right.extend(other: v0); // this point is on right side |
66 | |
67 | if ((v0d < pos && pos < v1d) || (v1d < pos && pos < v0d)) // the edge crosses the splitting location |
68 | { |
69 | assert((v1d-v0d) != 0.0f); |
70 | const float inv_length = 1.0f/(v1d-v0d); |
71 | const Vec3fa c = madd(a: Vec3fa((pos-v0d)*inv_length),b: v1-v0,c: v0); |
72 | left.extend(other: c); |
73 | right.extend(other: c); |
74 | } |
75 | } |
76 | |
77 | /* clip against current bounds */ |
78 | new (&left_o ) PrimRef(intersect(a: left ,b: prim.bounds()),prim.geomID(), prim.primID()); |
79 | new (&right_o) PrimRef(intersect(a: right,b: prim.bounds()),prim.geomID(), prim.primID()); |
80 | } |
81 | |
82 | struct TriangleSplitter |
83 | { |
84 | __forceinline TriangleSplitter(const Scene* scene, const PrimRef& prim) |
85 | { |
86 | const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS; |
87 | const TriangleMesh* mesh = (const TriangleMesh*) scene->get(i: prim.geomID() & mask ); |
88 | TriangleMesh::Triangle tri = mesh->triangle(i: prim.primID()); |
89 | v[0] = mesh->vertex(i: tri.v[0]); |
90 | v[1] = mesh->vertex(i: tri.v[1]); |
91 | v[2] = mesh->vertex(i: tri.v[2]); |
92 | v[3] = mesh->vertex(i: tri.v[0]); |
93 | inv_length[0] = Vec3fa(1.0f) / (v[1]-v[0]); |
94 | inv_length[1] = Vec3fa(1.0f) / (v[2]-v[1]); |
95 | inv_length[2] = Vec3fa(1.0f) / (v[0]-v[2]); |
96 | } |
97 | |
98 | __forceinline void operator() (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const { |
99 | splitPolygon<3>(prim,dim,pos,v,left_o,right_o); |
100 | } |
101 | |
102 | __forceinline void operator() (const BBox3fa& prim, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const { |
103 | splitPolygon<3>(bounds: prim,dim,pos,v,inv_length,left_o,right_o); |
104 | } |
105 | |
106 | private: |
107 | Vec3fa v[4]; |
108 | Vec3fa inv_length[3]; |
109 | }; |
110 | |
111 | struct TriangleSplitterFactory |
112 | { |
113 | __forceinline TriangleSplitterFactory(const Scene* scene) |
114 | : scene(scene) {} |
115 | |
116 | __forceinline TriangleSplitter operator() (const PrimRef& prim) const { |
117 | return TriangleSplitter(scene,prim); |
118 | } |
119 | |
120 | private: |
121 | const Scene* scene; |
122 | }; |
123 | |
124 | struct QuadSplitter |
125 | { |
126 | __forceinline QuadSplitter(const Scene* scene, const PrimRef& prim) |
127 | { |
128 | const unsigned int mask = 0xFFFFFFFF >> RESERVED_NUM_SPATIAL_SPLITS_GEOMID_BITS; |
129 | const QuadMesh* mesh = (const QuadMesh*) scene->get(i: prim.geomID() & mask ); |
130 | QuadMesh::Quad quad = mesh->quad(i: prim.primID()); |
131 | v[0] = mesh->vertex(i: quad.v[0]); |
132 | v[1] = mesh->vertex(i: quad.v[1]); |
133 | v[2] = mesh->vertex(i: quad.v[2]); |
134 | v[3] = mesh->vertex(i: quad.v[3]); |
135 | v[4] = mesh->vertex(i: quad.v[0]); |
136 | inv_length[0] = Vec3fa(1.0f) / (v[1]-v[0]); |
137 | inv_length[1] = Vec3fa(1.0f) / (v[2]-v[1]); |
138 | inv_length[2] = Vec3fa(1.0f) / (v[3]-v[2]); |
139 | inv_length[3] = Vec3fa(1.0f) / (v[0]-v[3]); |
140 | } |
141 | |
142 | __forceinline void operator() (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const { |
143 | splitPolygon<4>(prim,dim,pos,v,left_o,right_o); |
144 | } |
145 | |
146 | __forceinline void operator() (const BBox3fa& prim, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const { |
147 | splitPolygon<4>(bounds: prim,dim,pos,v,inv_length,left_o,right_o); |
148 | } |
149 | |
150 | private: |
151 | Vec3fa v[5]; |
152 | Vec3fa inv_length[4]; |
153 | }; |
154 | |
155 | struct QuadSplitterFactory |
156 | { |
157 | __forceinline QuadSplitterFactory(const Scene* scene) |
158 | : scene(scene) {} |
159 | |
160 | __forceinline QuadSplitter operator() (const PrimRef& prim) const { |
161 | return QuadSplitter(scene,prim); |
162 | } |
163 | |
164 | private: |
165 | const Scene* scene; |
166 | }; |
167 | |
168 | |
169 | struct DummySplitter |
170 | { |
171 | __forceinline DummySplitter(const Scene* scene, const PrimRef& prim) |
172 | { |
173 | } |
174 | }; |
175 | |
176 | struct DummySplitterFactory |
177 | { |
178 | __forceinline DummySplitterFactory(const Scene* scene) |
179 | : scene(scene) {} |
180 | |
181 | __forceinline DummySplitter operator() (const PrimRef& prim) const { |
182 | return DummySplitter(scene,prim); |
183 | } |
184 | |
185 | private: |
186 | const Scene* scene; |
187 | }; |
188 | |
189 | } |
190 | } |
191 | |
192 | |