e276548b |
1 | // Created on: 2013-08-27 |
2 | // Created by: Denis BOGOLEPOV |
3 | // Copyright (c) 2013 OPEN CASCADE SAS |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
e276548b |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
e276548b |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
e276548b |
15 | |
16 | #ifdef HAVE_CONFIG_H |
17 | #include <config.h> |
18 | #endif |
19 | |
20 | #ifdef HAVE_OPENCL |
21 | |
265d4508 |
22 | #include <Standard_Assert.hxx> |
e276548b |
23 | |
265d4508 |
24 | #ifdef HAVE_TBB |
be8d29f5 |
25 | // On Windows, function TryEnterCriticalSection has appeared in Windows NT |
26 | // and is surrounded by #ifdef in MS VC++ 7.1 headers. |
27 | // Thus to use it we need to define appropriate macro saying that we wil |
28 | // run on Windows NT 4.0 at least |
29 | #if ((defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN32_WINNT)) |
30 | #define _WIN32_WINNT 0x0501 |
31 | #endif |
32 | |
265d4508 |
33 | #include <tbb/tbb.h> |
34 | #endif |
e276548b |
35 | |
265d4508 |
36 | #include <OpenGl_SceneGeometry.hxx> |
e276548b |
37 | |
265d4508 |
38 | //! Use this macro to output BVH profiling info |
39 | //#define BVH_PRINT_INFO |
e276548b |
40 | |
265d4508 |
41 | #ifdef BVH_PRINT_INFO |
42 | #include <OSD_Timer.hxx> |
43 | #endif |
e276548b |
44 | |
265d4508 |
45 | namespace |
46 | { |
e276548b |
47 | //! Useful constant for null floating-point 4D vector. |
265d4508 |
48 | static const BVH_Vec4f ZERO_VEC_4F; |
e276548b |
49 | }; |
50 | |
51 | // ======================================================================= |
64c759f8 |
52 | // function : OpenGl_RaytraceMaterial |
e276548b |
53 | // purpose : Creates new default material |
54 | // ======================================================================= |
55 | OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial() |
265d4508 |
56 | : Ambient (ZERO_VEC_4F), |
57 | Diffuse (ZERO_VEC_4F), |
58 | Specular (ZERO_VEC_4F), |
59 | Emission (ZERO_VEC_4F), |
60 | Reflection (ZERO_VEC_4F), |
61 | Refraction (ZERO_VEC_4F), |
62 | Transparency (ZERO_VEC_4F) |
e276548b |
63 | { } |
64 | |
65 | // ======================================================================= |
64c759f8 |
66 | // function : OpenGl_RaytraceMaterial |
e276548b |
67 | // purpose : Creates new material with specified properties |
68 | // ======================================================================= |
265d4508 |
69 | OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient, |
70 | const BVH_Vec4f& theDiffuse, |
71 | const BVH_Vec4f& theSpecular) |
e276548b |
72 | : Ambient (theAmbient), |
73 | Diffuse (theDiffuse), |
74 | Specular (theSpecular), |
265d4508 |
75 | Emission (ZERO_VEC_4F), |
76 | Reflection (ZERO_VEC_4F), |
77 | Refraction (ZERO_VEC_4F), |
78 | Transparency (ZERO_VEC_4F) |
e276548b |
79 | { |
80 | // |
81 | } |
82 | |
83 | // ======================================================================= |
64c759f8 |
84 | // function : OpenGl_RaytraceMaterial |
e276548b |
85 | // purpose : Creates new material with specified properties |
86 | // ======================================================================= |
265d4508 |
87 | OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient, |
88 | const BVH_Vec4f& theDiffuse, |
89 | const BVH_Vec4f& theSpecular, |
90 | const BVH_Vec4f& theEmission, |
91 | const BVH_Vec4f& theTranspar) |
e276548b |
92 | : Ambient (theAmbient), |
93 | Diffuse (theDiffuse), |
94 | Specular (theSpecular), |
95 | Emission (theEmission), |
265d4508 |
96 | Reflection (ZERO_VEC_4F), |
97 | Refraction (ZERO_VEC_4F), |
e276548b |
98 | Transparency (theTranspar) |
99 | { |
100 | // |
101 | } |
102 | |
103 | // ======================================================================= |
64c759f8 |
104 | // function : OpenGl_RaytraceMaterial |
e276548b |
105 | // purpose : Creates new material with specified properties |
106 | // ======================================================================= |
265d4508 |
107 | OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient, |
108 | const BVH_Vec4f& theDiffuse, |
109 | const BVH_Vec4f& theSpecular, |
110 | const BVH_Vec4f& theEmission, |
111 | const BVH_Vec4f& theTranspar, |
112 | const BVH_Vec4f& theReflection, |
113 | const BVH_Vec4f& theRefraction) |
e276548b |
114 | : Ambient (theAmbient), |
115 | Diffuse (theDiffuse), |
116 | Specular (theSpecular), |
117 | Emission (theEmission), |
118 | Reflection (theReflection), |
119 | Refraction (theRefraction), |
120 | Transparency (theTranspar) |
121 | { |
122 | // |
123 | } |
124 | |
125 | // ======================================================================= |
126 | // function : OpenGl_LightSource |
127 | // purpose : Creates new light source |
128 | // ======================================================================= |
265d4508 |
129 | OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse, |
130 | const BVH_Vec4f& thePosition) |
e276548b |
131 | : Diffuse (theDiffuse), |
132 | Position (thePosition) |
133 | { |
134 | // |
135 | } |
136 | |
e276548b |
137 | // ======================================================================= |
138 | // function : Clear |
265d4508 |
139 | // purpose : Clears ray-tracing geometry |
e276548b |
140 | // ======================================================================= |
265d4508 |
141 | void OpenGl_RaytraceGeometry::Clear() |
e276548b |
142 | { |
265d4508 |
143 | BVH_Geometry<Standard_ShortReal, 4>::BVH_Geometry::Clear(); |
e276548b |
144 | |
265d4508 |
145 | std::vector<OpenGl_RaytraceLight, |
146 | NCollection_StdAllocator<OpenGl_RaytraceLight> > anEmptySources; |
e276548b |
147 | |
265d4508 |
148 | Sources.swap (anEmptySources); |
e276548b |
149 | |
150 | std::vector<OpenGl_RaytraceMaterial, |
265d4508 |
151 | NCollection_StdAllocator<OpenGl_RaytraceMaterial> > anEmptyMaterials; |
e276548b |
152 | |
153 | Materials.swap (anEmptyMaterials); |
154 | } |
155 | |
265d4508 |
156 | #ifdef HAVE_TBB |
e276548b |
157 | |
265d4508 |
158 | struct OpenGL_BVHParallelBuilder |
e276548b |
159 | { |
265d4508 |
160 | BVH_ObjectSet<Standard_ShortReal, 4>* Set; |
e276548b |
161 | |
265d4508 |
162 | OpenGL_BVHParallelBuilder (BVH_ObjectSet<Standard_ShortReal, 4>* theSet) |
163 | : Set (theSet) |
e276548b |
164 | { |
265d4508 |
165 | // |
e276548b |
166 | } |
e276548b |
167 | |
265d4508 |
168 | void operator() (const tbb::blocked_range<size_t>& theRange) const |
169 | { |
170 | for (size_t anObjectIdx = theRange.begin(); anObjectIdx != theRange.end(); ++anObjectIdx) |
171 | { |
172 | OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> ( |
173 | Set->Objects().ChangeValue (static_cast<Standard_Integer> (anObjectIdx)).operator->()); |
5322131b |
174 | |
265d4508 |
175 | if (aTriangleSet != NULL) |
176 | { |
177 | aTriangleSet->BVH(); |
178 | } |
179 | } |
180 | } |
181 | }; |
e276548b |
182 | |
e276548b |
183 | #endif |
184 | |
185 | // ======================================================================= |
265d4508 |
186 | // function : ProcessAcceleration |
187 | // purpose : Performs post-processing of high-level BVH |
e276548b |
188 | // ======================================================================= |
265d4508 |
189 | Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration() |
e276548b |
190 | { |
265d4508 |
191 | #ifdef BVH_PRINT_INFO |
192 | OSD_Timer aTimer; |
e276548b |
193 | #endif |
5322131b |
194 | |
265d4508 |
195 | MarkDirty(); // force BVH rebuilding |
e276548b |
196 | |
265d4508 |
197 | #ifdef BVH_PRINT_INFO |
198 | aTimer.Reset(); |
199 | aTimer.Start(); |
e276548b |
200 | #endif |
201 | |
265d4508 |
202 | #ifdef HAVE_TBB |
203 | // If Intel TBB is available, perform the preliminary |
204 | // construction of bottom-level scene BVHs |
205 | tbb::parallel_for (tbb::blocked_range<size_t> (0, Size()), |
206 | OpenGL_BVHParallelBuilder (this)); |
207 | #endif |
5322131b |
208 | |
265d4508 |
209 | for (Standard_Integer anObjectIdx = 0; anObjectIdx < Size(); ++anObjectIdx) |
e276548b |
210 | { |
265d4508 |
211 | OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> ( |
212 | myObjects.ChangeValue (anObjectIdx).operator->()); |
213 | |
214 | Standard_ASSERT_RETURN (aTriangleSet != NULL, |
215 | "Error! Failed to get triangulation of OpenGL element", Standard_False); |
5322131b |
216 | |
265d4508 |
217 | Standard_ASSERT_RETURN (!aTriangleSet->BVH().IsNull(), |
218 | "Error! Failed to update bottom-level BVH of OpenGL element", Standard_False); |
e276548b |
219 | } |
220 | |
265d4508 |
221 | #ifdef BVH_PRINT_INFO |
222 | aTimer.Stop(); |
e276548b |
223 | |
265d4508 |
224 | std::cout << "Updating bottom-level BVHs (sec): " << |
225 | aTimer.ElapsedTime() << std::endl; |
226 | #endif |
e276548b |
227 | |
265d4508 |
228 | #ifdef BVH_PRINT_INFO |
229 | aTimer.Reset(); |
230 | aTimer.Start(); |
231 | #endif |
e276548b |
232 | |
265d4508 |
233 | NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVH = BVH(); |
e276548b |
234 | |
265d4508 |
235 | #ifdef BVH_PRINT_INFO |
236 | aTimer.Stop(); |
e276548b |
237 | |
265d4508 |
238 | std::cout << "Updating high-level BVH (sec): " << |
239 | aTimer.ElapsedTime() << std::endl; |
e276548b |
240 | #endif |
241 | |
265d4508 |
242 | Standard_ASSERT_RETURN (!aBVH.IsNull(), |
243 | "Error! Failed to update high-level BVH of ray-tracing scene", Standard_False); |
e276548b |
244 | |
265d4508 |
245 | Standard_Integer aVerticesOffset = 0; |
246 | Standard_Integer aElementsOffset = 0; |
247 | Standard_Integer aBVHNodesOffset = 0; |
e276548b |
248 | |
265d4508 |
249 | for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx) |
e276548b |
250 | { |
265d4508 |
251 | if (!aBVH->IsOuter (aNodeIdx)) |
e276548b |
252 | continue; |
253 | |
265d4508 |
254 | Standard_ASSERT_RETURN (aBVH->BegPrimitive (aNodeIdx) == aBVH->EndPrimitive (aNodeIdx), |
255 | "Error! Invalid leaf node in high-level BVH (contains several objects)", Standard_False); |
e276548b |
256 | |
265d4508 |
257 | Standard_Integer anObjectIdx = aBVH->BegPrimitive (aNodeIdx); |
e276548b |
258 | |
265d4508 |
259 | Standard_ASSERT_RETURN (anObjectIdx < myObjects.Size(), |
260 | "Error! Invalid leaf node in high-level BVH (contains out-of-range object)", Standard_False); |
e276548b |
261 | |
265d4508 |
262 | OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> ( |
263 | myObjects.ChangeValue (anObjectIdx).operator->()); |
e276548b |
264 | |
265d4508 |
265 | // Note: We overwrite node info record to store parameters |
266 | // of bottom-level BVH and triangulation of OpenGL element |
e276548b |
267 | |
265d4508 |
268 | aBVH->NodeInfoBuffer().at (aNodeIdx) = BVH_Vec4i ( |
269 | anObjectIdx + 1 /* to keep leaf flag */, aBVHNodesOffset, aVerticesOffset, aElementsOffset); |
e276548b |
270 | |
d5f74e42 |
271 | aVerticesOffset += (int)aTriangleSet->Vertices.size(); |
272 | aElementsOffset += (int)aTriangleSet->Elements.size(); |
265d4508 |
273 | aBVHNodesOffset += aTriangleSet->BVH()->Length(); |
e276548b |
274 | } |
e276548b |
275 | |
265d4508 |
276 | return Standard_True; |
277 | } |
e276548b |
278 | |
265d4508 |
279 | // ======================================================================= |
280 | // function : AccelerationOffset |
281 | // purpose : Returns offset of bottom-level BVH for given leaf node |
282 | // ======================================================================= |
283 | Standard_Integer OpenGl_RaytraceGeometry::AccelerationOffset (Standard_Integer theNodeIdx) |
284 | { |
285 | const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH(); |
e276548b |
286 | |
265d4508 |
287 | if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx)) |
288 | return INVALID_OFFSET; |
e276548b |
289 | |
265d4508 |
290 | return aBVH->NodeInfoBuffer().at (theNodeIdx).y(); |
e276548b |
291 | } |
292 | |
293 | // ======================================================================= |
265d4508 |
294 | // function : VerticesOffset |
295 | // purpose : Returns offset of triangulation vertices for given leaf node |
e276548b |
296 | // ======================================================================= |
265d4508 |
297 | Standard_Integer OpenGl_RaytraceGeometry::VerticesOffset (Standard_Integer theNodeIdx) |
e276548b |
298 | { |
265d4508 |
299 | const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH(); |
e276548b |
300 | |
265d4508 |
301 | if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx)) |
302 | return INVALID_OFFSET; |
e276548b |
303 | |
265d4508 |
304 | return aBVH->NodeInfoBuffer().at (theNodeIdx).z(); |
305 | } |
e276548b |
306 | |
265d4508 |
307 | // ======================================================================= |
308 | // function : ElementsOffset |
309 | // purpose : Returns offset of triangulation elements for given leaf node |
310 | // ======================================================================= |
311 | Standard_Integer OpenGl_RaytraceGeometry::ElementsOffset (Standard_Integer theNodeIdx) |
312 | { |
313 | const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH(); |
e276548b |
314 | |
265d4508 |
315 | if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx)) |
316 | return INVALID_OFFSET; |
e276548b |
317 | |
265d4508 |
318 | return aBVH->NodeInfoBuffer().at (theNodeIdx).w(); |
e276548b |
319 | } |
320 | |
321 | // ======================================================================= |
265d4508 |
322 | // function : TriangleSet |
323 | // purpose : Returns triangulation data for given leaf node |
e276548b |
324 | // ======================================================================= |
265d4508 |
325 | OpenGl_TriangleSet* OpenGl_RaytraceGeometry::TriangleSet (Standard_Integer theNodeIdx) |
e276548b |
326 | { |
265d4508 |
327 | const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH(); |
e276548b |
328 | |
265d4508 |
329 | if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx)) |
330 | return NULL; |
e276548b |
331 | |
265d4508 |
332 | if (aBVH->NodeInfoBuffer().at (theNodeIdx).x() > myObjects.Size()) |
333 | return NULL; |
5322131b |
334 | |
265d4508 |
335 | return dynamic_cast<OpenGl_TriangleSet*> (myObjects.ChangeValue ( |
336 | aBVH->NodeInfoBuffer().at (theNodeIdx).x() - 1).operator->()); |
e276548b |
337 | } |
338 | |
339 | namespace OpenGl_Raytrace |
340 | { |
341 | // ======================================================================= |
342 | // function : IsRaytracedElement |
343 | // purpose : Checks to see if the element contains ray-trace geometry |
344 | // ======================================================================= |
345 | Standard_Boolean IsRaytracedElement (const OpenGl_ElementNode* theNode) |
346 | { |
5322131b |
347 | OpenGl_PrimitiveArray* anArray = dynamic_cast< OpenGl_PrimitiveArray* > (theNode->elem); |
348 | return anArray != NULL |
349 | && anArray->PArray()->type >= TelPolygonsArrayType; |
e276548b |
350 | } |
351 | |
352 | // ======================================================================= |
353 | // function : IsRaytracedGroup |
354 | // purpose : Checks to see if the group contains ray-trace geometry |
355 | // ======================================================================= |
356 | Standard_Boolean IsRaytracedGroup (const OpenGl_Group *theGroup) |
357 | { |
358 | const OpenGl_ElementNode* aNode; |
359 | for (aNode = theGroup->FirstNode(); aNode != NULL; aNode = aNode->next) |
360 | { |
361 | if (IsRaytracedElement (aNode)) |
362 | { |
363 | return Standard_True; |
364 | } |
365 | } |
366 | return Standard_False; |
367 | } |
368 | |
369 | // ======================================================================= |
370 | // function : IsRaytracedStructure |
371 | // purpose : Checks to see if the structure contains ray-trace geometry |
372 | // ======================================================================= |
373 | Standard_Boolean IsRaytracedStructure (const OpenGl_Structure *theStructure) |
374 | { |
375 | for (OpenGl_ListOfGroup::Iterator anItg (theStructure->Groups()); |
376 | anItg.More(); anItg.Next()) |
377 | { |
378 | if (anItg.Value()->IsRaytracable()) |
379 | return Standard_True; |
380 | } |
381 | for (OpenGl_ListOfStructure::Iterator anIts (theStructure->ConnectedStructures()); |
382 | anIts.More(); anIts.Next()) |
383 | { |
384 | if (IsRaytracedStructure (anIts.Value())) |
385 | return Standard_True; |
386 | } |
387 | return Standard_False; |
388 | } |
389 | } |
390 | |
391 | #endif |