0024718: Broken build on VC8 (VS 2005) if TBB is used
[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
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 45namespace
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// =======================================================================
55OpenGl_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 69OpenGl_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 87OpenGl_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 107OpenGl_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 129OpenGl_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 141void 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 158struct 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 189Standard_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// =======================================================================
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 // =======================================================================
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