1 // Created on: 2013-08-27
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <Standard_Assert.hxx>
19 // On Windows, function TryEnterCriticalSection has appeared in Windows NT
20 // and is surrounded by #ifdef in MS VC++ 7.1 headers.
21 // Thus to use it we need to define appropriate macro saying that we wil
22 // run on Windows NT 4.0 at least
23 #if ((defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN32_WINNT))
24 #define _WIN32_WINNT 0x0501
30 #include <OpenGl_SceneGeometry.hxx>
32 //! Use this macro to output BVH profiling info
33 //#define BVH_PRINT_INFO
36 #include <OSD_Timer.hxx>
41 //! Useful constant for null floating-point 4D vector.
42 static const BVH_Vec4f ZERO_VEC_4F;
45 // =======================================================================
46 // function : OpenGl_RaytraceMaterial
47 // purpose : Creates new default material
48 // =======================================================================
49 OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial()
50 : Ambient (ZERO_VEC_4F),
51 Diffuse (ZERO_VEC_4F),
52 Specular (ZERO_VEC_4F),
53 Emission (ZERO_VEC_4F),
54 Reflection (ZERO_VEC_4F),
55 Refraction (ZERO_VEC_4F),
56 Transparency (ZERO_VEC_4F)
59 // =======================================================================
60 // function : OpenGl_RaytraceMaterial
61 // purpose : Creates new material with specified properties
62 // =======================================================================
63 OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient,
64 const BVH_Vec4f& theDiffuse,
65 const BVH_Vec4f& theSpecular)
66 : Ambient (theAmbient),
68 Specular (theSpecular),
69 Emission (ZERO_VEC_4F),
70 Reflection (ZERO_VEC_4F),
71 Refraction (ZERO_VEC_4F),
72 Transparency (ZERO_VEC_4F)
77 // =======================================================================
78 // function : OpenGl_RaytraceMaterial
79 // purpose : Creates new material with specified properties
80 // =======================================================================
81 OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient,
82 const BVH_Vec4f& theDiffuse,
83 const BVH_Vec4f& theSpecular,
84 const BVH_Vec4f& theEmission,
85 const BVH_Vec4f& theTranspar)
86 : Ambient (theAmbient),
88 Specular (theSpecular),
89 Emission (theEmission),
90 Reflection (ZERO_VEC_4F),
91 Refraction (ZERO_VEC_4F),
92 Transparency (theTranspar)
97 // =======================================================================
98 // function : OpenGl_RaytraceMaterial
99 // purpose : Creates new material with specified properties
100 // =======================================================================
101 OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient,
102 const BVH_Vec4f& theDiffuse,
103 const BVH_Vec4f& theSpecular,
104 const BVH_Vec4f& theEmission,
105 const BVH_Vec4f& theTranspar,
106 const BVH_Vec4f& theReflection,
107 const BVH_Vec4f& theRefraction)
108 : Ambient (theAmbient),
109 Diffuse (theDiffuse),
110 Specular (theSpecular),
111 Emission (theEmission),
112 Reflection (theReflection),
113 Refraction (theRefraction),
114 Transparency (theTranspar)
119 // =======================================================================
120 // function : OpenGl_LightSource
121 // purpose : Creates new light source
122 // =======================================================================
123 OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse,
124 const BVH_Vec4f& thePosition)
125 : Diffuse (theDiffuse),
126 Position (thePosition)
131 // =======================================================================
133 // purpose : Clears ray-tracing geometry
134 // =======================================================================
135 void OpenGl_RaytraceGeometry::Clear()
137 BVH_Geometry<Standard_ShortReal, 4>::BVH_Geometry::Clear();
139 std::vector<OpenGl_RaytraceLight,
140 NCollection_StdAllocator<OpenGl_RaytraceLight> > anEmptySources;
142 Sources.swap (anEmptySources);
144 std::vector<OpenGl_RaytraceMaterial,
145 NCollection_StdAllocator<OpenGl_RaytraceMaterial> > anEmptyMaterials;
147 Materials.swap (anEmptyMaterials);
152 struct OpenGL_BVHParallelBuilder
154 BVH_ObjectSet<Standard_ShortReal, 4>* Set;
156 OpenGL_BVHParallelBuilder (BVH_ObjectSet<Standard_ShortReal, 4>* theSet)
162 void operator() (const tbb::blocked_range<size_t>& theRange) const
164 for (size_t anObjectIdx = theRange.begin(); anObjectIdx != theRange.end(); ++anObjectIdx)
166 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
167 Set->Objects().ChangeValue (static_cast<Standard_Integer> (anObjectIdx)).operator->());
169 if (aTriangleSet != NULL)
179 // =======================================================================
180 // function : ProcessAcceleration
181 // purpose : Performs post-processing of high-level BVH
182 // =======================================================================
183 Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration()
185 #ifdef BVH_PRINT_INFO
189 MarkDirty(); // force BVH rebuilding
191 #ifdef BVH_PRINT_INFO
197 // If Intel TBB is available, perform the preliminary
198 // construction of bottom-level scene BVHs
199 tbb::parallel_for (tbb::blocked_range<size_t> (0, Size()),
200 OpenGL_BVHParallelBuilder (this));
203 myBottomLevelTreeDepth = 0;
205 for (Standard_Integer anObjectIdx = 0; anObjectIdx < Size(); ++anObjectIdx)
207 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
208 myObjects.ChangeValue (anObjectIdx).operator->());
210 Standard_ASSERT_RETURN (aTriangleSet != NULL,
211 "Error! Failed to get triangulation of OpenGL element", Standard_False);
213 Standard_ASSERT_RETURN (!aTriangleSet->BVH().IsNull(),
214 "Error! Failed to update bottom-level BVH of OpenGL element", Standard_False);
216 myBottomLevelTreeDepth = Max (myBottomLevelTreeDepth, aTriangleSet->BVH()->Depth());
219 #ifdef BVH_PRINT_INFO
222 std::cout << "Updating bottom-level BVHs (sec): " <<
223 aTimer.ElapsedTime() << std::endl;
226 #ifdef BVH_PRINT_INFO
231 NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVH = BVH();
233 #ifdef BVH_PRINT_INFO
236 std::cout << "Updating high-level BVH (sec): " <<
237 aTimer.ElapsedTime() << std::endl;
240 Standard_ASSERT_RETURN (!aBVH.IsNull(),
241 "Error! Failed to update high-level BVH of ray-tracing scene", Standard_False);
243 myHighLevelTreeDepth = aBVH->Depth();
245 Standard_Integer aVerticesOffset = 0;
246 Standard_Integer aElementsOffset = 0;
247 Standard_Integer aBVHNodesOffset = 0;
249 for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
251 if (!aBVH->IsOuter (aNodeIdx))
254 Standard_ASSERT_RETURN (aBVH->BegPrimitive (aNodeIdx) == aBVH->EndPrimitive (aNodeIdx),
255 "Error! Invalid leaf node in high-level BVH (contains several objects)", Standard_False);
257 Standard_Integer anObjectIdx = aBVH->BegPrimitive (aNodeIdx);
259 Standard_ASSERT_RETURN (anObjectIdx < myObjects.Size(),
260 "Error! Invalid leaf node in high-level BVH (contains out-of-range object)", Standard_False);
262 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
263 myObjects.ChangeValue (anObjectIdx).operator->());
265 // Note: We overwrite node info record to store parameters
266 // of bottom-level BVH and triangulation of OpenGL element
268 aBVH->NodeInfoBuffer().at (aNodeIdx) = BVH_Vec4i (
269 anObjectIdx + 1 /* to keep leaf flag */, aBVHNodesOffset, aVerticesOffset, aElementsOffset);
271 aVerticesOffset += (int)aTriangleSet->Vertices.size();
272 aElementsOffset += (int)aTriangleSet->Elements.size();
273 aBVHNodesOffset += aTriangleSet->BVH()->Length();
276 return Standard_True;
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)
285 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
287 if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
288 return INVALID_OFFSET;
290 return aBVH->NodeInfoBuffer().at (theNodeIdx).y();
293 // =======================================================================
294 // function : VerticesOffset
295 // purpose : Returns offset of triangulation vertices for given leaf node
296 // =======================================================================
297 Standard_Integer OpenGl_RaytraceGeometry::VerticesOffset (Standard_Integer theNodeIdx)
299 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
301 if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
302 return INVALID_OFFSET;
304 return aBVH->NodeInfoBuffer().at (theNodeIdx).z();
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)
313 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
315 if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
316 return INVALID_OFFSET;
318 return aBVH->NodeInfoBuffer().at (theNodeIdx).w();
321 // =======================================================================
322 // function : TriangleSet
323 // purpose : Returns triangulation data for given leaf node
324 // =======================================================================
325 OpenGl_TriangleSet* OpenGl_RaytraceGeometry::TriangleSet (Standard_Integer theNodeIdx)
327 const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
329 if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
332 if (aBVH->NodeInfoBuffer().at (theNodeIdx).x() > myObjects.Size())
335 return dynamic_cast<OpenGl_TriangleSet*> (myObjects.ChangeValue (
336 aBVH->NodeInfoBuffer().at (theNodeIdx).x() - 1).operator->());
339 namespace OpenGl_Raytrace
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)
347 OpenGl_PrimitiveArray* anArray = dynamic_cast< OpenGl_PrimitiveArray* > (theNode->elem);
348 return anArray != NULL
349 && anArray->DrawMode() >= GL_TRIANGLES;
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)
358 const OpenGl_ElementNode* aNode;
359 for (aNode = theGroup->FirstNode(); aNode != NULL; aNode = aNode->next)
361 if (IsRaytracedElement (aNode))
363 return Standard_True;
366 return Standard_False;
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)
375 for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->DrawGroups());
376 aGroupIter.More(); aGroupIter.Next())
378 if (aGroupIter.Value()->IsRaytracable())
379 return Standard_True;
381 for (OpenGl_ListOfStructure::Iterator anIts (theStructure->ConnectedStructures());
382 anIts.More(); anIts.Next())
384 if (IsRaytracedStructure (anIts.Value()))
385 return Standard_True;
387 return Standard_False;