0024739: TKOpenGl - port ray-tracing from OpenCL to GLSL for better integration and...
[occt.git] / src / OpenGl / OpenGl_SceneGeometry.cxx
CommitLineData
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
265d4508 16#include <Standard_Assert.hxx>
e276548b 17
265d4508 18#ifdef HAVE_TBB
be8d29f5 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
25 #endif
26
265d4508 27 #include <tbb/tbb.h>
28#endif
e276548b 29
265d4508 30#include <OpenGl_SceneGeometry.hxx>
e276548b 31
265d4508 32//! Use this macro to output BVH profiling info
33//#define BVH_PRINT_INFO
e276548b 34
265d4508 35#ifdef BVH_PRINT_INFO
36 #include <OSD_Timer.hxx>
37#endif
e276548b 38
265d4508 39namespace
40{
e276548b 41 //! Useful constant for null floating-point 4D vector.
265d4508 42 static const BVH_Vec4f ZERO_VEC_4F;
e276548b 43};
44
45// =======================================================================
64c759f8 46// function : OpenGl_RaytraceMaterial
e276548b 47// purpose : Creates new default material
48// =======================================================================
49OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial()
265d4508 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)
e276548b 57{ }
58
59// =======================================================================
64c759f8 60// function : OpenGl_RaytraceMaterial
e276548b 61// purpose : Creates new material with specified properties
62// =======================================================================
265d4508 63OpenGl_RaytraceMaterial::OpenGl_RaytraceMaterial (const BVH_Vec4f& theAmbient,
64 const BVH_Vec4f& theDiffuse,
65 const BVH_Vec4f& theSpecular)
e276548b 66: Ambient (theAmbient),
67 Diffuse (theDiffuse),
68 Specular (theSpecular),
265d4508 69 Emission (ZERO_VEC_4F),
70 Reflection (ZERO_VEC_4F),
71 Refraction (ZERO_VEC_4F),
72 Transparency (ZERO_VEC_4F)
e276548b 73{
74 //
75}
76
77// =======================================================================
64c759f8 78// function : OpenGl_RaytraceMaterial
e276548b 79// purpose : Creates new material with specified properties
80// =======================================================================
265d4508 81OpenGl_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)
e276548b 86: Ambient (theAmbient),
87 Diffuse (theDiffuse),
88 Specular (theSpecular),
89 Emission (theEmission),
265d4508 90 Reflection (ZERO_VEC_4F),
91 Refraction (ZERO_VEC_4F),
e276548b 92 Transparency (theTranspar)
93{
94 //
95}
96
97// =======================================================================
64c759f8 98// function : OpenGl_RaytraceMaterial
e276548b 99// purpose : Creates new material with specified properties
100// =======================================================================
265d4508 101OpenGl_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)
e276548b 108: Ambient (theAmbient),
109 Diffuse (theDiffuse),
110 Specular (theSpecular),
111 Emission (theEmission),
112 Reflection (theReflection),
113 Refraction (theRefraction),
114 Transparency (theTranspar)
115{
116 //
117}
118
119// =======================================================================
120// function : OpenGl_LightSource
121// purpose : Creates new light source
122// =======================================================================
265d4508 123OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse,
124 const BVH_Vec4f& thePosition)
e276548b 125: Diffuse (theDiffuse),
126 Position (thePosition)
127{
128 //
129}
130
131// =======================================================================
e276548b 132// function : Clear
265d4508 133// purpose : Clears ray-tracing geometry
e276548b 134// =======================================================================
265d4508 135void OpenGl_RaytraceGeometry::Clear()
e276548b 136{
265d4508 137 BVH_Geometry<Standard_ShortReal, 4>::BVH_Geometry::Clear();
e276548b 138
265d4508 139 std::vector<OpenGl_RaytraceLight,
140 NCollection_StdAllocator<OpenGl_RaytraceLight> > anEmptySources;
e276548b 141
265d4508 142 Sources.swap (anEmptySources);
e276548b 143
144 std::vector<OpenGl_RaytraceMaterial,
265d4508 145 NCollection_StdAllocator<OpenGl_RaytraceMaterial> > anEmptyMaterials;
e276548b 146
147 Materials.swap (anEmptyMaterials);
148}
149
265d4508 150#ifdef HAVE_TBB
e276548b 151
265d4508 152struct OpenGL_BVHParallelBuilder
e276548b 153{
265d4508 154 BVH_ObjectSet<Standard_ShortReal, 4>* Set;
e276548b 155
265d4508 156 OpenGL_BVHParallelBuilder (BVH_ObjectSet<Standard_ShortReal, 4>* theSet)
157 : Set (theSet)
e276548b 158 {
265d4508 159 //
e276548b 160 }
e276548b 161
265d4508 162 void operator() (const tbb::blocked_range<size_t>& theRange) const
163 {
164 for (size_t anObjectIdx = theRange.begin(); anObjectIdx != theRange.end(); ++anObjectIdx)
165 {
166 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
167 Set->Objects().ChangeValue (static_cast<Standard_Integer> (anObjectIdx)).operator->());
5322131b 168
265d4508 169 if (aTriangleSet != NULL)
170 {
171 aTriangleSet->BVH();
172 }
173 }
174 }
175};
e276548b 176
e276548b 177#endif
178
179// =======================================================================
265d4508 180// function : ProcessAcceleration
181// purpose : Performs post-processing of high-level BVH
e276548b 182// =======================================================================
265d4508 183Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration()
e276548b 184{
265d4508 185#ifdef BVH_PRINT_INFO
186 OSD_Timer aTimer;
e276548b 187#endif
5322131b 188
265d4508 189 MarkDirty(); // force BVH rebuilding
e276548b 190
265d4508 191#ifdef BVH_PRINT_INFO
192 aTimer.Reset();
193 aTimer.Start();
e276548b 194#endif
195
265d4508 196#ifdef HAVE_TBB
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));
201#endif
5322131b 202
fc73a202 203 myBottomLevelTreeDepth = 0;
204
265d4508 205 for (Standard_Integer anObjectIdx = 0; anObjectIdx < Size(); ++anObjectIdx)
e276548b 206 {
265d4508 207 OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
208 myObjects.ChangeValue (anObjectIdx).operator->());
209
210 Standard_ASSERT_RETURN (aTriangleSet != NULL,
211 "Error! Failed to get triangulation of OpenGL element", Standard_False);
5322131b 212
265d4508 213 Standard_ASSERT_RETURN (!aTriangleSet->BVH().IsNull(),
214 "Error! Failed to update bottom-level BVH of OpenGL element", Standard_False);
fc73a202 215
216 myBottomLevelTreeDepth = Max (myBottomLevelTreeDepth, aTriangleSet->BVH()->Depth());
e276548b 217 }
218
265d4508 219#ifdef BVH_PRINT_INFO
220 aTimer.Stop();
e276548b 221
265d4508 222 std::cout << "Updating bottom-level BVHs (sec): " <<
223 aTimer.ElapsedTime() << std::endl;
224#endif
e276548b 225
265d4508 226#ifdef BVH_PRINT_INFO
227 aTimer.Reset();
228 aTimer.Start();
229#endif
e276548b 230
265d4508 231 NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVH = BVH();
e276548b 232
265d4508 233#ifdef BVH_PRINT_INFO
234 aTimer.Stop();
e276548b 235
265d4508 236 std::cout << "Updating high-level BVH (sec): " <<
237 aTimer.ElapsedTime() << std::endl;
e276548b 238#endif
239
265d4508 240 Standard_ASSERT_RETURN (!aBVH.IsNull(),
241 "Error! Failed to update high-level BVH of ray-tracing scene", Standard_False);
e276548b 242
fc73a202 243 myHighLevelTreeDepth = aBVH->Depth();
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// =======================================================================
283Standard_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 297Standard_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// =======================================================================
311Standard_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 325OpenGl_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
339namespace 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 // =======================================================================
b64d84be 373 Standard_Boolean IsRaytracedStructure (const OpenGl_Structure* theStructure)
e276548b 374 {
b64d84be 375 for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->DrawGroups());
376 aGroupIter.More(); aGroupIter.Next())
e276548b 377 {
b64d84be 378 if (aGroupIter.Value()->IsRaytracable())
e276548b 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}