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(v0); // this point is on left side |
32 | if (v0d >= pos) right.extend(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(Vec3fa((pos-v0d)*inv_length[i][dim]),v1-v0,v0); |
38 | left.extend(c); |
39 | right.extend(c); |
40 | } |
41 | } |
42 | |
43 | /* clip against current bounds */ |
44 | left_o = intersect(left,bounds); |
45 | right_o = intersect(right,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(v0); // this point is on left side |
65 | if (v0d >= pos) right.extend(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(Vec3fa((pos-v0d)*inv_length),v1-v0,v0); |
72 | left.extend(c); |
73 | right.extend(c); |
74 | } |
75 | } |
76 | |
77 | /* clip against current bounds */ |
78 | new (&left_o ) PrimRef(intersect(left ,prim.bounds()),prim.geomID(), prim.primID()); |
79 | new (&right_o) PrimRef(intersect(right,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(prim.geomID() & mask ); |
88 | TriangleMesh::Triangle tri = mesh->triangle(prim.primID()); |
89 | v[0] = mesh->vertex(tri.v[0]); |
90 | v[1] = mesh->vertex(tri.v[1]); |
91 | v[2] = mesh->vertex(tri.v[2]); |
92 | v[3] = mesh->vertex(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>(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(prim.geomID() & mask ); |
130 | QuadMesh::Quad quad = mesh->quad(prim.primID()); |
131 | v[0] = mesh->vertex(quad.v[1]); |
132 | v[1] = mesh->vertex(quad.v[2]); |
133 | v[2] = mesh->vertex(quad.v[3]); |
134 | v[3] = mesh->vertex(quad.v[0]); |
135 | v[4] = mesh->vertex(quad.v[1]); |
136 | v[5] = mesh->vertex(quad.v[3]); |
137 | inv_length[0] = Vec3fa(1.0f) / (v[1] - v[0]); |
138 | inv_length[1] = Vec3fa(1.0f) / (v[2] - v[1]); |
139 | inv_length[2] = Vec3fa(1.0f) / (v[3] - v[2]); |
140 | inv_length[3] = Vec3fa(1.0f) / (v[4] - v[3]); |
141 | inv_length[4] = Vec3fa(1.0f) / (v[5] - v[4]); |
142 | } |
143 | |
144 | __forceinline void operator() (const PrimRef& prim, const size_t dim, const float pos, PrimRef& left_o, PrimRef& right_o) const { |
145 | splitPolygon<5>(prim,dim,pos,v,left_o,right_o); |
146 | } |
147 | |
148 | __forceinline void operator() (const BBox3fa& prim, const size_t dim, const float pos, BBox3fa& left_o, BBox3fa& right_o) const { |
149 | splitPolygon<5>(prim,dim,pos,v,inv_length,left_o,right_o); |
150 | } |
151 | |
152 | private: |
153 | Vec3fa v[6]; |
154 | Vec3fa inv_length[5]; |
155 | }; |
156 | |
157 | struct QuadSplitterFactory |
158 | { |
159 | __forceinline QuadSplitterFactory(const Scene* scene) |
160 | : scene(scene) {} |
161 | |
162 | __forceinline QuadSplitter operator() (const PrimRef& prim) const { |
163 | return QuadSplitter(scene,prim); |
164 | } |
165 | |
166 | private: |
167 | const Scene* scene; |
168 | }; |
169 | |
170 | |
171 | struct DummySplitter |
172 | { |
173 | __forceinline DummySplitter(const Scene* scene, const PrimRef& prim) |
174 | { |
175 | } |
176 | }; |
177 | |
178 | struct DummySplitterFactory |
179 | { |
180 | __forceinline DummySplitterFactory(const Scene* scene) |
181 | : scene(scene) {} |
182 | |
183 | __forceinline DummySplitter operator() (const PrimRef& prim) const { |
184 | return DummySplitter(scene,prim); |
185 | } |
186 | |
187 | private: |
188 | const Scene* scene; |
189 | }; |
190 | |
191 | } |
192 | } |
193 | |
194 | |