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.
22 #include <Standard_Assert.hxx>
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
36 #include <OpenGl_SceneGeometry.hxx>
38 //! Use this macro to output BVH profiling info
39 //#define BVH_PRINT_INFO
42 #include <OSD_Timer.hxx>
47 //! Useful constant for null floating-point 4D vector.
48 static const BVH_Vec4f ZERO_VEC_4F;
51 // =======================================================================
52 // function : OpenGl_RaytraceMaterial
53 // purpose : Creates new default material
54 // =======================================================================
55 OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial()
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)
65 // =======================================================================
66 // function : OpenGl_RaytraceMaterial
67 // purpose : Creates new material with specified properties
68 // =======================================================================
69 OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient,
70 const BVH_Vec4f& theDiffuse,
71 const BVH_Vec4f& theSpecular)
72 : Ambient (theAmbient),
74 Specular (theSpecular),
75 Emission (ZERO_VEC_4F),
76 Reflection (ZERO_VEC_4F),
77 Refraction (ZERO_VEC_4F),
78 Transparency (ZERO_VEC_4F)
83 // =======================================================================
84 // function : OpenGl_RaytraceMaterial
85 // purpose : Creates new material with specified properties
86 // =======================================================================
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)
92 : Ambient (theAmbient),
94 Specular (theSpecular),
95 Emission (theEmission),
96 Reflection (ZERO_VEC_4F),
97 Refraction (ZERO_VEC_4F),
98 Transparency (theTranspar)
103 // =======================================================================
104 // function : OpenGl_RaytraceMaterial
105 // purpose : Creates new material with specified properties
106 // =======================================================================
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)
114 : Ambient (theAmbient),
115 Diffuse (theDiffuse),
116 Specular (theSpecular),
117 Emission (theEmission),
118 Reflection (theReflection),
119 Refraction (theRefraction),
120 Transparency (theTranspar)
125 // =======================================================================
126 // function : OpenGl_LightSource
127 // purpose : Creates new light source
128 // =======================================================================
129 OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse,
130 const BVH_Vec4f& thePosition)
131 : Diffuse (theDiffuse),
132 Position (thePosition)
137 // =======================================================================
139 // purpose : Clears ray-tracing geometry
140 // =======================================================================
141 void OpenGl_RaytraceGeometry::Clear()
143 BVH_Geometry<Standard_ShortReal, 4>::BVH_Geometry::Clear();
145 std::vector<OpenGl_RaytraceLight,
146 NCollection_StdAllocator<OpenGl_RaytraceLight> > anEmptySources;
148 Sources.swap (anEmptySources);
150 std::vector<OpenGl_RaytraceMaterial,
151 NCollection_StdAllocator<OpenGl_RaytraceMaterial> > anEmptyMaterials;
153 Materials.swap (anEmptyMaterials);
158 struct OpenGL_BVHParallelBuilder
160 BVH_ObjectSet<Standard_ShortReal, 4>* Set;
162 OpenGL_BVHParallelBuilder (BVH_ObjectSet<Standard_ShortReal, 4>* theSet)
168 void operator() (const tbb::blocked_range<size_t>& theRange) const
170 for (size_t anObjectIdx = theRange.begin(); anObjectIdx != theRange.end(); ++anObjectIdx)
172 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
173 Set->Objects().ChangeValue (static_cast<Standard_Integer> (anObjectIdx)).operator->());
175 if (aTriangleSet != NULL)
185 // =======================================================================
186 // function : ProcessAcceleration
187 // purpose : Performs post-processing of high-level BVH
188 // =======================================================================
189 Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration()
191 #ifdef BVH_PRINT_INFO
195 MarkDirty(); // force BVH rebuilding
197 #ifdef BVH_PRINT_INFO
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));
209 for (Standard_Integer anObjectIdx = 0; anObjectIdx < Size(); ++anObjectIdx)
211 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
212 myObjects.ChangeValue (anObjectIdx).operator->());
214 Standard_ASSERT_RETURN (aTriangleSet != NULL,
215 "Error! Failed to get triangulation of OpenGL element", Standard_False);
217 Standard_ASSERT_RETURN (!aTriangleSet->BVH().IsNull(),
218 "Error! Failed to update bottom-level BVH of OpenGL element", Standard_False);
221 #ifdef BVH_PRINT_INFO
224 std::cout << "Updating bottom-level BVHs (sec): " <<
225 aTimer.ElapsedTime() << std::endl;
228 #ifdef BVH_PRINT_INFO
233 NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVH = BVH();
235 #ifdef BVH_PRINT_INFO
238 std::cout << "Updating high-level BVH (sec): " <<
239 aTimer.ElapsedTime() << std::endl;
242 Standard_ASSERT_RETURN (!aBVH.IsNull(),
243 "Error! Failed to update high-level BVH of ray-tracing scene", Standard_False);
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->PArray()->type >= TelPolygonsArrayType;
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_ListOfGroup::Iterator anItg (theStructure->Groups());
376 anItg.More(); anItg.Next())
378 if (anItg.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;