1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "primitive.h" |
7 | |
8 | namespace embree |
9 | { |
10 | /* Stores the vertices of M triangles in struct of array layout */ |
11 | template<int M> |
12 | struct TriangleMvMB |
13 | { |
14 | public: |
15 | struct Type : public PrimitiveType |
16 | { |
17 | const char* name() const; |
18 | size_t sizeActive(const char* This) const; |
19 | size_t sizeTotal(const char* This) const; |
20 | size_t getBytes(const char* This) const; |
21 | }; |
22 | |
23 | static Type type; |
24 | |
25 | public: |
26 | |
27 | /* primitive supports single time segments */ |
28 | static const bool singleTimeSegment = true; |
29 | |
30 | /* Returns maximum number of stored triangles */ |
31 | static __forceinline size_t max_size() { return M; } |
32 | |
33 | /* Returns required number of primitive blocks for N primitives */ |
34 | static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); } |
35 | |
36 | public: |
37 | |
38 | /* Default constructor */ |
39 | __forceinline TriangleMvMB() {} |
40 | |
41 | /* Construction from vertices and IDs */ |
42 | __forceinline TriangleMvMB(const Vec3vf<M>& a0, const Vec3vf<M>& a1, |
43 | const Vec3vf<M>& b0, const Vec3vf<M>& b1, |
44 | const Vec3vf<M>& c0, const Vec3vf<M>& c1, |
45 | const vuint<M>& geomIDs, const vuint<M>& primIDs) |
46 | : v0(a0), v1(b0), v2(c0), dv0(a1-a0), dv1(b1-b0), dv2(c1-c0), geomIDs(geomIDs), primIDs(primIDs) {} |
47 | |
48 | /* Returns a mask that tells which triangles are valid */ |
49 | __forceinline vbool<M> valid() const { return geomIDs != vuint<M>(-1); } |
50 | |
51 | /* Returns if the specified triangle is valid */ |
52 | __forceinline bool valid(const size_t i) const { assert(i<M); return geomIDs[i] != -1; } |
53 | |
54 | /* Returns the number of stored triangles */ |
55 | __forceinline size_t size() const { return bsf(~movemask(valid())); } |
56 | |
57 | /* Returns the geometry IDs */ |
58 | __forceinline vuint<M>& geomID() { return geomIDs; } |
59 | __forceinline const vuint<M>& geomID() const { return geomIDs; } |
60 | __forceinline unsigned int geomID(const size_t i) const { assert(i<M); return geomIDs[i]; } |
61 | |
62 | /* Returns the primitive IDs */ |
63 | __forceinline vuint<M>& primID() { return primIDs; } |
64 | __forceinline const vuint<M>& primID() const { return primIDs; } |
65 | __forceinline unsigned int primID(const size_t i) const { assert(i<M); return primIDs[i]; } |
66 | |
67 | /* Calculate the bounds of the triangles at t0 */ |
68 | __forceinline BBox3fa bounds0() const |
69 | { |
70 | Vec3vf<M> lower = min(v0,v1,v2); |
71 | Vec3vf<M> upper = max(v0,v1,v2); |
72 | const vbool<M> mask = valid(); |
73 | lower.x = select(mask,lower.x,vfloat<M>(pos_inf)); |
74 | lower.y = select(mask,lower.y,vfloat<M>(pos_inf)); |
75 | lower.z = select(mask,lower.z,vfloat<M>(pos_inf)); |
76 | upper.x = select(mask,upper.x,vfloat<M>(neg_inf)); |
77 | upper.y = select(mask,upper.y,vfloat<M>(neg_inf)); |
78 | upper.z = select(mask,upper.z,vfloat<M>(neg_inf)); |
79 | return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)), |
80 | Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z))); |
81 | } |
82 | |
83 | /* Calculate the bounds of the triangles at t1 */ |
84 | __forceinline BBox3fa bounds1() const |
85 | { |
86 | const Vec3vf<M> p0 = v0+dv0; |
87 | const Vec3vf<M> p1 = v1+dv1; |
88 | const Vec3vf<M> p2 = v2+dv2; |
89 | Vec3vf<M> lower = min(p0,p1,p2); |
90 | Vec3vf<M> upper = max(p0,p1,p2); |
91 | const vbool<M> mask = valid(); |
92 | lower.x = select(mask,lower.x,vfloat<M>(pos_inf)); |
93 | lower.y = select(mask,lower.y,vfloat<M>(pos_inf)); |
94 | lower.z = select(mask,lower.z,vfloat<M>(pos_inf)); |
95 | upper.x = select(mask,upper.x,vfloat<M>(neg_inf)); |
96 | upper.y = select(mask,upper.y,vfloat<M>(neg_inf)); |
97 | upper.z = select(mask,upper.z,vfloat<M>(neg_inf)); |
98 | return BBox3fa(Vec3fa(reduce_min(lower.x),reduce_min(lower.y),reduce_min(lower.z)), |
99 | Vec3fa(reduce_max(upper.x),reduce_max(upper.y),reduce_max(upper.z))); |
100 | } |
101 | |
102 | /* Calculate the linear bounds of the primitive */ |
103 | __forceinline LBBox3fa linearBounds() const { |
104 | return LBBox3fa(bounds0(),bounds1()); |
105 | } |
106 | |
107 | /* Fill triangle from triangle list */ |
108 | __forceinline LBBox3fa fillMB(const PrimRef* prims, size_t& begin, size_t end, Scene* scene, size_t itime) |
109 | { |
110 | vuint<M> vgeomID = -1, vprimID = -1; |
111 | Vec3vf<M> va0 = zero, vb0 = zero, vc0 = zero; |
112 | Vec3vf<M> va1 = zero, vb1 = zero, vc1 = zero; |
113 | |
114 | BBox3fa bounds0 = empty; |
115 | BBox3fa bounds1 = empty; |
116 | |
117 | for (size_t i=0; i<M && begin<end; i++, begin++) |
118 | { |
119 | const PrimRef& prim = prims[begin]; |
120 | const unsigned geomID = prim.geomID(); |
121 | const unsigned primID = prim.primID(); |
122 | const TriangleMesh* __restrict__ const mesh = scene->get<TriangleMesh>(i: geomID); |
123 | const TriangleMesh::Triangle& tri = mesh->triangle(i: primID); |
124 | const Vec3fa& a0 = mesh->vertex(i: tri.v[0],itime: itime+0); bounds0.extend(other: a0); |
125 | const Vec3fa& a1 = mesh->vertex(i: tri.v[0],itime: itime+1); bounds1.extend(other: a1); |
126 | const Vec3fa& b0 = mesh->vertex(i: tri.v[1],itime: itime+0); bounds0.extend(other: b0); |
127 | const Vec3fa& b1 = mesh->vertex(i: tri.v[1],itime: itime+1); bounds1.extend(other: b1); |
128 | const Vec3fa& c0 = mesh->vertex(i: tri.v[2],itime: itime+0); bounds0.extend(other: c0); |
129 | const Vec3fa& c1 = mesh->vertex(i: tri.v[2],itime: itime+1); bounds1.extend(other: c1); |
130 | vgeomID [i] = geomID; |
131 | vprimID [i] = primID; |
132 | va0.x[i] = a0.x; va0.y[i] = a0.y; va0.z[i] = a0.z; |
133 | va1.x[i] = a1.x; va1.y[i] = a1.y; va1.z[i] = a1.z; |
134 | vb0.x[i] = b0.x; vb0.y[i] = b0.y; vb0.z[i] = b0.z; |
135 | vb1.x[i] = b1.x; vb1.y[i] = b1.y; vb1.z[i] = b1.z; |
136 | vc0.x[i] = c0.x; vc0.y[i] = c0.y; vc0.z[i] = c0.z; |
137 | vc1.x[i] = c1.x; vc1.y[i] = c1.y; vc1.z[i] = c1.z; |
138 | } |
139 | new (this) TriangleMvMB(va0,va1,vb0,vb1,vc0,vc1,vgeomID,vprimID); |
140 | return LBBox3fa(bounds0,bounds1); |
141 | } |
142 | |
143 | /* Fill triangle from triangle list */ |
144 | __forceinline LBBox3fa fillMB(const PrimRefMB* prims, size_t& begin, size_t end, Scene* scene, const BBox1f time_range) |
145 | { |
146 | vuint<M> vgeomID = -1, vprimID = -1; |
147 | Vec3vf<M> va0 = zero, vb0 = zero, vc0 = zero; |
148 | Vec3vf<M> va1 = zero, vb1 = zero, vc1 = zero; |
149 | |
150 | LBBox3fa allBounds = empty; |
151 | for (size_t i=0; i<M && begin<end; i++, begin++) |
152 | { |
153 | const PrimRefMB& prim = prims[begin]; |
154 | const unsigned geomID = prim.geomID(); |
155 | const unsigned primID = prim.primID(); |
156 | const TriangleMesh* const mesh = scene->get<TriangleMesh>(i: geomID); |
157 | const range<int> itime_range = mesh->timeSegmentRange(range: time_range); |
158 | assert(itime_range.size() == 1); |
159 | const int ilower = itime_range.begin(); |
160 | const TriangleMesh::Triangle& tri = mesh->triangle(i: primID); |
161 | allBounds.extend(other: mesh->linearBounds(primID, dt: time_range)); |
162 | const Vec3fa& a0 = mesh->vertex(i: tri.v[0],itime: ilower+0); |
163 | const Vec3fa& a1 = mesh->vertex(i: tri.v[0],itime: ilower+1); |
164 | const Vec3fa& b0 = mesh->vertex(i: tri.v[1],itime: ilower+0); |
165 | const Vec3fa& b1 = mesh->vertex(i: tri.v[1],itime: ilower+1); |
166 | const Vec3fa& c0 = mesh->vertex(i: tri.v[2],itime: ilower+0); |
167 | const Vec3fa& c1 = mesh->vertex(i: tri.v[2],itime: ilower+1); |
168 | const BBox1f time_range_v(mesh->timeStep(i: ilower+0),mesh->timeStep(i: ilower+1)); |
169 | auto a01 = globalLinear(v: std::make_pair(x: a0,y: a1),dt: time_range_v); |
170 | auto b01 = globalLinear(v: std::make_pair(x: b0,y: b1),dt: time_range_v); |
171 | auto c01 = globalLinear(v: std::make_pair(x: c0,y: c1),dt: time_range_v); |
172 | vgeomID [i] = geomID; |
173 | vprimID [i] = primID; |
174 | va0.x[i] = a01.first .x; va0.y[i] = a01.first .y; va0.z[i] = a01.first .z; |
175 | va1.x[i] = a01.second.x; va1.y[i] = a01.second.y; va1.z[i] = a01.second.z; |
176 | vb0.x[i] = b01.first .x; vb0.y[i] = b01.first .y; vb0.z[i] = b01.first .z; |
177 | vb1.x[i] = b01.second.x; vb1.y[i] = b01.second.y; vb1.z[i] = b01.second.z; |
178 | vc0.x[i] = c01.first .x; vc0.y[i] = c01.first .y; vc0.z[i] = c01.first .z; |
179 | vc1.x[i] = c01.second.x; vc1.y[i] = c01.second.y; vc1.z[i] = c01.second.z; |
180 | } |
181 | new (this) TriangleMvMB(va0,va1,vb0,vb1,vc0,vc1,vgeomID,vprimID); |
182 | return allBounds; |
183 | } |
184 | |
185 | public: |
186 | Vec3vf<M> v0; // 1st vertex of the triangles |
187 | Vec3vf<M> v1; // 2nd vertex of the triangles |
188 | Vec3vf<M> v2; // 3rd vertex of the triangles |
189 | Vec3vf<M> dv0; // difference vector between time steps t0 and t1 for first vertex |
190 | Vec3vf<M> dv1; // difference vector between time steps t0 and t1 for second vertex |
191 | Vec3vf<M> dv2; // difference vector between time steps t0 and t1 for third vertex |
192 | private: |
193 | vuint<M> geomIDs; // geometry ID |
194 | vuint<M> primIDs; // primitive ID |
195 | }; |
196 | |
197 | template<int M> |
198 | typename TriangleMvMB<M>::Type TriangleMvMB<M>::type; |
199 | |
200 | typedef TriangleMvMB<4> Triangle4vMB; |
201 | } |
202 | |