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
9namespace 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