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