1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#include "geometry.h"
5#include "scene.h"
6
7namespace embree
8{
9 const char* Geometry::gtype_names[Geometry::GTY_END] =
10 {
11 "flat_linear_curve",
12 "round_linear_curve",
13 "oriented_linear_curve",
14 "",
15 "flat_bezier_curve",
16 "round_bezier_curve",
17 "oriented_bezier_curve",
18 "",
19 "flat_bspline_curve",
20 "round_bspline_curve",
21 "oriented_bspline_curve",
22 "",
23 "flat_hermite_curve",
24 "round_hermite_curve",
25 "oriented_hermite_curve",
26 "",
27 "flat_catmull_rom_curve",
28 "round_catmull_rom_curve",
29 "oriented_catmull_rom_curve",
30 "",
31 "triangles",
32 "quads",
33 "grid",
34 "subdivs",
35 "",
36 "sphere",
37 "disc",
38 "oriented_disc",
39 "",
40 "usergeom",
41 "instance_cheap",
42 "instance_expensive",
43 };
44
45 Geometry::Geometry (Device* device, GType gtype, unsigned int numPrimitives, unsigned int numTimeSteps)
46 : device(device), userPtr(nullptr),
47 numPrimitives(numPrimitives), numTimeSteps(unsigned(numTimeSteps)), fnumTimeSegments(float(numTimeSteps-1)), time_range(0.0f,1.0f),
48 mask(-1),
49 gtype(gtype),
50 gsubtype(GTY_SUBTYPE_DEFAULT),
51 quality(RTC_BUILD_QUALITY_MEDIUM),
52 state((unsigned)State::MODIFIED),
53 enabled(true),
54 intersectionFilterN(nullptr), occlusionFilterN(nullptr), pointQueryFunc(nullptr)
55 {
56 device->refInc();
57 }
58
59 Geometry::~Geometry()
60 {
61 device->refDec();
62 }
63
64 void Geometry::setNumPrimitives(unsigned int numPrimitives_in)
65 {
66 if (numPrimitives_in == numPrimitives) return;
67
68 numPrimitives = numPrimitives_in;
69
70 Geometry::update();
71 }
72
73 void Geometry::setNumTimeSteps (unsigned int numTimeSteps_in)
74 {
75 if (numTimeSteps_in == numTimeSteps) {
76 return;
77 }
78
79 numTimeSteps = numTimeSteps_in;
80 fnumTimeSegments = float(numTimeSteps_in-1);
81
82 Geometry::update();
83 }
84
85 void Geometry::setTimeRange (const BBox1f range)
86 {
87 time_range = range;
88 Geometry::update();
89 }
90
91 void Geometry::update()
92 {
93 ++modCounter_; // FIXME: required?
94 state = (unsigned)State::MODIFIED;
95 }
96
97 void Geometry::commit()
98 {
99 ++modCounter_;
100 state = (unsigned)State::COMMITTED;
101 }
102
103 void Geometry::preCommit()
104 {
105 if (State::MODIFIED == (State)state)
106 throw_RTCError(RTC_ERROR_INVALID_OPERATION,"geometry not committed");
107 }
108
109 void Geometry::postCommit()
110 {
111 }
112
113 void Geometry::enable ()
114 {
115 if (isEnabled())
116 return;
117
118 enabled = true;
119 ++modCounter_;
120 }
121
122 void Geometry::disable ()
123 {
124 if (isDisabled())
125 return;
126
127 enabled = false;
128 ++modCounter_;
129 }
130
131 void Geometry::setUserData (void* ptr)
132 {
133 userPtr = ptr;
134 }
135
136 void Geometry::setIntersectionFilterFunctionN (RTCFilterFunctionN filter)
137 {
138 if (!(getTypeMask() & (MTY_TRIANGLE_MESH | MTY_QUAD_MESH | MTY_CURVES | MTY_SUBDIV_MESH | MTY_USER_GEOMETRY | MTY_GRID_MESH)))
139 throw_RTCError(RTC_ERROR_INVALID_OPERATION,"filter functions not supported for this geometry");
140
141 intersectionFilterN = filter;
142 }
143
144 void Geometry::setOcclusionFilterFunctionN (RTCFilterFunctionN filter)
145 {
146 if (!(getTypeMask() & (MTY_TRIANGLE_MESH | MTY_QUAD_MESH | MTY_CURVES | MTY_SUBDIV_MESH | MTY_USER_GEOMETRY | MTY_GRID_MESH)))
147 throw_RTCError(RTC_ERROR_INVALID_OPERATION,"filter functions not supported for this geometry");
148
149 occlusionFilterN = filter;
150 }
151
152 void Geometry::setPointQueryFunction (RTCPointQueryFunction func)
153 {
154 pointQueryFunc = func;
155 }
156
157 void Geometry::interpolateN(const RTCInterpolateNArguments* const args)
158 {
159 const void* valid_i = args->valid;
160 const unsigned* primIDs = args->primIDs;
161 const float* u = args->u;
162 const float* v = args->v;
163 unsigned int N = args->N;
164 RTCBufferType bufferType = args->bufferType;
165 unsigned int bufferSlot = args->bufferSlot;
166 float* P = args->P;
167 float* dPdu = args->dPdu;
168 float* dPdv = args->dPdv;
169 float* ddPdudu = args->ddPdudu;
170 float* ddPdvdv = args->ddPdvdv;
171 float* ddPdudv = args->ddPdudv;
172 unsigned int valueCount = args->valueCount;
173
174 if (valueCount > 256) throw_RTCError(RTC_ERROR_INVALID_OPERATION,"maximally 256 floating point values can be interpolated per vertex");
175 const int* valid = (const int*) valid_i;
176
177 __aligned(64) float P_tmp[256];
178 __aligned(64) float dPdu_tmp[256];
179 __aligned(64) float dPdv_tmp[256];
180 __aligned(64) float ddPdudu_tmp[256];
181 __aligned(64) float ddPdvdv_tmp[256];
182 __aligned(64) float ddPdudv_tmp[256];
183
184 float* Pt = P ? P_tmp : nullptr;
185 float* dPdut = nullptr, *dPdvt = nullptr;
186 if (dPdu) { dPdut = dPdu_tmp; dPdvt = dPdv_tmp; }
187 float* ddPdudut = nullptr, *ddPdvdvt = nullptr, *ddPdudvt = nullptr;
188 if (ddPdudu) { ddPdudut = ddPdudu_tmp; ddPdvdvt = ddPdvdv_tmp; ddPdudvt = ddPdudv_tmp; }
189
190 for (unsigned int i=0; i<N; i++)
191 {
192 if (valid && !valid[i]) continue;
193
194 RTCInterpolateArguments iargs;
195 iargs.primID = primIDs[i];
196 iargs.u = u[i];
197 iargs.v = v[i];
198 iargs.bufferType = bufferType;
199 iargs.bufferSlot = bufferSlot;
200 iargs.P = Pt;
201 iargs.dPdu = dPdut;
202 iargs.dPdv = dPdvt;
203 iargs.ddPdudu = ddPdudut;
204 iargs.ddPdvdv = ddPdvdvt;
205 iargs.ddPdudv = ddPdudvt;
206 iargs.valueCount = valueCount;
207 interpolate(&iargs);
208
209 if (likely(P)) {
210 for (unsigned int j=0; j<valueCount; j++)
211 P[j*N+i] = Pt[j];
212 }
213 if (likely(dPdu))
214 {
215 for (unsigned int j=0; j<valueCount; j++) {
216 dPdu[j*N+i] = dPdut[j];
217 dPdv[j*N+i] = dPdvt[j];
218 }
219 }
220 if (likely(ddPdudu))
221 {
222 for (unsigned int j=0; j<valueCount; j++) {
223 ddPdudu[j*N+i] = ddPdudut[j];
224 ddPdvdv[j*N+i] = ddPdvdvt[j];
225 ddPdudv[j*N+i] = ddPdudvt[j];
226 }
227 }
228 }
229 }
230
231 bool Geometry::pointQuery(PointQuery* query, PointQueryContext* context)
232 {
233 assert(context->primID < size());
234
235 RTCPointQueryFunctionArguments args;
236 args.query = (RTCPointQuery*)context->query_ws;
237 args.userPtr = context->userPtr;
238 args.primID = context->primID;
239 args.geomID = context->geomID;
240 args.context = context->userContext;
241 args.similarityScale = context->similarityScale;
242
243 bool update = false;
244 if(context->func) update |= context->func(&args);
245 if(pointQueryFunc) update |= pointQueryFunc(&args);
246
247 if (update && context->userContext->instStackSize > 0)
248 {
249 // update point query
250 if (context->query_type == POINT_QUERY_TYPE_AABB) {
251 context->updateAABB();
252 } else {
253 assert(context->similarityScale > 0.f);
254 query->radius = context->query_ws->radius * context->similarityScale;
255 }
256 }
257 return update;
258 }
259}
260