1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "buffer.h"
7#include "default.h"
8#include "geometry.h"
9
10namespace embree
11{
12 /*! represents an array of points */
13 struct Points : public Geometry
14 {
15 /*! type of this geometry */
16 static const Geometry::GTypeMask geom_type = Geometry::MTY_POINTS;
17
18 public:
19 /*! line segments construction */
20 Points(Device* device, Geometry::GType gtype);
21
22 public:
23 void setMask(unsigned mask);
24 void setNumTimeSteps(unsigned int numTimeSteps);
25 void setVertexAttributeCount(unsigned int N);
26 void setBuffer(RTCBufferType type,
27 unsigned int slot,
28 RTCFormat format,
29 const Ref<Buffer>& buffer,
30 size_t offset,
31 size_t stride,
32 unsigned int num);
33 void* getBuffer(RTCBufferType type, unsigned int slot);
34 void updateBuffer(RTCBufferType type, unsigned int slot);
35 void commit();
36 bool verify();
37 void setMaxRadiusScale(float s);
38 void addElementsToCount (GeometryCounts & counts) const;
39
40 public:
41 /*! returns the number of vertices */
42 __forceinline size_t numVertices() const {
43 return vertices[0].size();
44 }
45
46 /*! returns i'th vertex of the first time step */
47 __forceinline Vec3ff vertex(size_t i) const {
48 return vertices0[i];
49 }
50
51 /*! returns i'th vertex of the first time step */
52 __forceinline const char* vertexPtr(size_t i) const {
53 return vertices0.getPtr(i);
54 }
55
56 /*! returns i'th normal of the first time step */
57 __forceinline Vec3fa normal(size_t i) const {
58 return normals0[i];
59 }
60
61 /*! returns i'th radius of the first time step */
62 __forceinline float radius(size_t i) const {
63 return vertices0[i].w;
64 }
65
66 /*! returns i'th vertex of itime'th timestep */
67 __forceinline Vec3ff vertex(size_t i, size_t itime) const {
68 return vertices[itime][i];
69 }
70
71 /*! returns i'th vertex of itime'th timestep */
72 __forceinline const char* vertexPtr(size_t i, size_t itime) const {
73 return vertices[itime].getPtr(i);
74 }
75
76 /*! returns i'th normal of itime'th timestep */
77 __forceinline Vec3fa normal(size_t i, size_t itime) const {
78 return normals[itime][i];
79 }
80
81 /*! returns i'th radius of itime'th timestep */
82 __forceinline float radius(size_t i, size_t itime) const {
83 return vertices[itime][i].w;
84 }
85
86 /*! calculates bounding box of i'th line segment */
87 __forceinline BBox3fa bounds(const Vec3ff& v0) const {
88 return enlarge(BBox3fa(v0), maxRadiusScale*Vec3fa(v0.w));
89 }
90
91 /*! calculates bounding box of i'th line segment */
92 __forceinline BBox3fa bounds(size_t i) const
93 {
94 const Vec3ff v0 = vertex(i);
95 return bounds(v0);
96 }
97
98 /*! calculates bounding box of i'th line segment for the itime'th time step */
99 __forceinline BBox3fa bounds(size_t i, size_t itime) const
100 {
101 const Vec3ff v0 = vertex(i, itime);
102 return bounds(v0);
103 }
104
105 /*! calculates bounding box of i'th line segment */
106 __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i) const
107 {
108 const Vec3ff v0 = vertex(i);
109 const Vec3ff w0(xfmVector(space, (Vec3fa)v0), v0.w);
110 return bounds(w0);
111 }
112
113 /*! calculates bounding box of i'th line segment for the itime'th time step */
114 __forceinline BBox3fa bounds(const LinearSpace3fa& space, size_t i, size_t itime) const
115 {
116 const Vec3ff v0 = vertex(i, itime);
117 const Vec3ff w0(xfmVector(space, (Vec3fa)v0), v0.w);
118 return bounds(w0);
119 }
120
121 /*! check if the i'th primitive is valid at the itime'th timestep */
122 __forceinline bool valid(size_t i, size_t itime) const {
123 return valid(i, make_range(itime, itime));
124 }
125
126 /*! check if the i'th primitive is valid between the specified time range */
127 __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
128 {
129 const unsigned int index = (unsigned int)i;
130 if (index >= numVertices())
131 return false;
132
133 for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++) {
134 const Vec3ff v0 = vertex(index + 0, itime);
135 if (unlikely(!isvalid4(v0)))
136 return false;
137 if (v0.w < 0.0f)
138 return false;
139 }
140 return true;
141 }
142
143 /*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */
144 __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {
145 return LBBox3fa(bounds(i, itime + 0), bounds(i, itime + 1));
146 }
147
148 /*! calculates the build bounds of the i'th primitive, if it's valid */
149 __forceinline bool buildBounds(size_t i, BBox3fa* bbox) const
150 {
151 if (!valid(i, 0))
152 return false;
153 *bbox = bounds(i);
154 return true;
155 }
156
157 /*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */
158 __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
159 {
160 if (!valid(i, itime + 0) || !valid(i, itime + 1))
161 return false;
162 bbox = bounds(i, itime); // use bounds of first time step in builder
163 return true;
164 }
165
166 /*! calculates the linear bounds of the i'th primitive for the specified time range */
167 __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
168 return LBBox3fa([&](size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
169 }
170
171 /*! calculates the linear bounds of the i'th primitive for the specified time range */
172 __forceinline LBBox3fa linearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& dt) const {
173 return LBBox3fa([&](size_t itime) { return bounds(space, primID, itime); }, dt, time_range, fnumTimeSegments);
174 }
175
176 /*! calculates the linear bounds of the i'th primitive for the specified time range */
177 __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const
178 {
179 if (!valid(i, timeSegmentRange(time_range))) return false;
180 bbox = linearBounds(i, time_range);
181 return true;
182 }
183
184 /*! get fast access to first vertex buffer */
185 __forceinline float * getCompactVertexArray () const {
186 return (float*) vertices0.getPtr();
187 }
188
189 public:
190 BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer
191 BufferView<Vec3fa> normals0; //!< fast access to first normal buffer
192 vector<BufferView<Vec3ff>> vertices; //!< vertex array for each timestep
193 vector<BufferView<Vec3fa>> normals; //!< normal array for each timestep
194 vector<BufferView<char>> vertexAttribs; //!< user buffers
195 float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii
196 };
197
198 namespace isa
199 {
200 struct PointsISA : public Points
201 {
202 PointsISA(Device* device, Geometry::GType gtype) : Points(device, gtype) {}
203
204 Vec3fa computeDirection(unsigned int primID) const
205 {
206 return Vec3fa(1, 0, 0);
207 }
208
209 Vec3fa computeDirection(unsigned int primID, size_t time) const
210 {
211 return Vec3fa(1, 0, 0);
212 }
213
214 PrimInfo createPrimRefArray(mvector<PrimRef>& prims, const range<size_t>& r, size_t k, unsigned int geomID) const
215 {
216 PrimInfo pinfo(empty);
217 for (size_t j = r.begin(); j < r.end(); j++) {
218 BBox3fa bounds = empty;
219 if (!buildBounds(j, &bounds))
220 continue;
221 const PrimRef prim(bounds, geomID, unsigned(j));
222 pinfo.add_center2(prim);
223 prims[k++] = prim;
224 }
225 return pinfo;
226 }
227
228 PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const
229 {
230 PrimInfo pinfo(empty);
231 for (size_t j = r.begin(); j < r.end(); j++) {
232 BBox3fa bounds = empty;
233 if (!buildBounds(j, itime, bounds))
234 continue;
235 const PrimRef prim(bounds, geomID, unsigned(j));
236 pinfo.add_center2(prim);
237 prims[k++] = prim;
238 }
239 return pinfo;
240 }
241
242 PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims,
243 const BBox1f& t0t1,
244 const range<size_t>& r,
245 size_t k,
246 unsigned int geomID) const
247 {
248 PrimInfoMB pinfo(empty);
249 for (size_t j = r.begin(); j < r.end(); j++) {
250 if (!valid(j, timeSegmentRange(t0t1)))
251 continue;
252 const PrimRefMB prim(linearBounds(j, t0t1), this->numTimeSegments(), this->time_range, this->numTimeSegments(), geomID, unsigned(j));
253 pinfo.add_primref(prim);
254 prims[k++] = prim;
255 }
256 return pinfo;
257 }
258
259 BBox3fa vbounds(size_t i) const
260 {
261 return bounds(i);
262 }
263
264 BBox3fa vbounds(const LinearSpace3fa& space, size_t i) const
265 {
266 return bounds(space, i);
267 }
268
269 LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const
270 {
271 return linearBounds(primID, time_range);
272 }
273
274 LBBox3fa vlinearBounds(const LinearSpace3fa& space, size_t primID, const BBox1f& time_range) const
275 {
276 return linearBounds(space, primID, time_range);
277 }
278 };
279 } // namespace isa
280
281 DECLARE_ISA_FUNCTION(Points*, createPoints, Device* COMMA Geometry::GType);
282} // namespace embree
283