| 1 | // Created on: 2011-08-01 |
| 2 | // Created by: Sergey ZERCHANINOV |
| 3 | // Copyright (c) 2011-2014 OPEN CASCADE SAS |
| 4 | // |
| 5 | // This file is part of Open CASCADE Technology software library. |
| 6 | // |
| 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. |
| 12 | // |
| 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
| 14 | // commercial license or contractual agreement. |
| 15 | |
| 16 | #include <OpenGl_CappingAlgo.hxx> |
| 17 | #include <OpenGl_GlCore11.hxx> |
| 18 | #include <OpenGl_ClippingIterator.hxx> |
| 19 | #include <OpenGl_ShaderManager.hxx> |
| 20 | #include <OpenGl_ShaderProgram.hxx> |
| 21 | #include <OpenGl_StructureShadow.hxx> |
| 22 | #include <OpenGl_Vec.hxx> |
| 23 | #include <OpenGl_View.hxx> |
| 24 | #include <OpenGl_Workspace.hxx> |
| 25 | |
| 26 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Structure,Graphic3d_CStructure) |
| 27 | |
| 28 | // ======================================================================= |
| 29 | // function : renderBoundingBox |
| 30 | // purpose : |
| 31 | // ======================================================================= |
| 32 | void OpenGl_Structure::renderBoundingBox (const Handle(OpenGl_Workspace)& theWorkspace) const |
| 33 | { |
| 34 | if (!myBndBox.IsValid()) |
| 35 | { |
| 36 | return; |
| 37 | } |
| 38 | |
| 39 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
| 40 | const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); |
| 41 | const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer); |
| 42 | const Graphic3d_Vec3d aMoveVec = myTrsfPers.IsNull() |
| 43 | && !aLayer.OriginTransformation().IsNull() |
| 44 | ? -Graphic3d_Vec3d (aLayer.Origin().X(), aLayer.Origin().Y(), aLayer.Origin().Z()) |
| 45 | : Graphic3d_Vec3d (0.0, 0.0, 0.0); |
| 46 | if (aCtx->core20fwd != NULL |
| 47 | && aCtx->ShaderManager()->BindBoundBoxProgram()) |
| 48 | { |
| 49 | const Graphic3d_Vec3d aCenter = myBndBox.Center() + aMoveVec; |
| 50 | const Graphic3d_Vec3d aSize = myBndBox.Size(); |
| 51 | aCtx->ActiveProgram()->SetUniform (aCtx, "occBBoxCenter", Graphic3d_Vec3 ((float )aCenter.x(), (float )aCenter.y(), (float )aCenter.z())); |
| 52 | aCtx->ActiveProgram()->SetUniform (aCtx, "occBBoxSize", Graphic3d_Vec3 ((float )aSize.x(), (float )aSize.y(), (float )aSize.z())); |
| 53 | aCtx->SetColor4fv (theWorkspace->InteriorColor()); |
| 54 | |
| 55 | const Handle(OpenGl_VertexBuffer)& aBoundBoxVertBuffer = aCtx->ShaderManager()->BoundBoxVertBuffer(); |
| 56 | aBoundBoxVertBuffer->BindAttribute (aCtx, Graphic3d_TOA_POS); |
| 57 | aCtx->core20fwd->glDrawArrays (GL_LINES, 0, aBoundBoxVertBuffer->GetElemsNb()); |
| 58 | aBoundBoxVertBuffer->UnbindAttribute(aCtx, Graphic3d_TOA_POS); |
| 59 | } |
| 60 | else if (aCtx->core11ffp != NULL) |
| 61 | { |
| 62 | const Graphic3d_Vec3d aMind = myBndBox.CornerMin() + aMoveVec; |
| 63 | const Graphic3d_Vec3d aMaxd = myBndBox.CornerMax() + aMoveVec; |
| 64 | const Graphic3d_Vec3 aMin ((float )aMind.x(), (float )aMind.y(), (float )aMind.z()); |
| 65 | const Graphic3d_Vec3 aMax ((float )aMaxd.x(), (float )aMaxd.y(), (float )aMaxd.z()); |
| 66 | const OpenGl_Vec3 aVerts[16] = |
| 67 | { |
| 68 | OpenGl_Vec3 (aMin.x(), aMin.y(), aMin.z()), |
| 69 | OpenGl_Vec3 (aMin.x(), aMin.y(), aMax.z()), |
| 70 | OpenGl_Vec3 (aMin.x(), aMax.y(), aMax.z()), |
| 71 | OpenGl_Vec3 (aMin.x(), aMax.y(), aMin.z()), |
| 72 | OpenGl_Vec3 (aMin.x(), aMin.y(), aMin.z()), |
| 73 | OpenGl_Vec3 (aMax.x(), aMin.y(), aMin.z()), |
| 74 | OpenGl_Vec3 (aMax.x(), aMin.y(), aMax.z()), |
| 75 | OpenGl_Vec3 (aMax.x(), aMax.y(), aMax.z()), |
| 76 | OpenGl_Vec3 (aMax.x(), aMax.y(), aMin.z()), |
| 77 | OpenGl_Vec3 (aMax.x(), aMin.y(), aMin.z()), |
| 78 | OpenGl_Vec3 (aMax.x(), aMax.y(), aMin.z()), |
| 79 | OpenGl_Vec3 (aMin.x(), aMax.y(), aMin.z()), |
| 80 | OpenGl_Vec3 (aMin.x(), aMax.y(), aMax.z()), |
| 81 | OpenGl_Vec3 (aMax.x(), aMax.y(), aMax.z()), |
| 82 | OpenGl_Vec3 (aMax.x(), aMin.y(), aMax.z()), |
| 83 | OpenGl_Vec3 (aMin.x(), aMin.y(), aMax.z()) |
| 84 | }; |
| 85 | |
| 86 | aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID, Graphic3d_TypeOfShadingModel_Unlit, Graphic3d_AlphaMode_Opaque, false, Handle(OpenGl_ShaderProgram)()); |
| 87 | aCtx->SetColor4fv (theWorkspace->InteriorColor()); |
| 88 | aCtx->core11fwd->glDisable (GL_LIGHTING); |
| 89 | aCtx->core11ffp->glEnableClientState (GL_VERTEX_ARRAY); |
| 90 | aCtx->core11ffp->glVertexPointer (3, GL_FLOAT, 0, aVerts[0].GetData()); |
| 91 | aCtx->core11fwd->glDrawArrays (GL_LINE_STRIP, 0, 16); |
| 92 | aCtx->core11ffp->glDisableClientState (GL_VERTEX_ARRAY); |
| 93 | } |
| 94 | aCtx->BindTextures (aPrevTexture, Handle(OpenGl_ShaderProgram)()); |
| 95 | } |
| 96 | |
| 97 | // ======================================================================= |
| 98 | // function : OpenGl_Structure |
| 99 | // purpose : |
| 100 | // ======================================================================= |
| 101 | OpenGl_Structure::OpenGl_Structure (const Handle(Graphic3d_StructureManager)& theManager) |
| 102 | : Graphic3d_CStructure (theManager), |
| 103 | myInstancedStructure (NULL), |
| 104 | myIsRaytracable (Standard_False), |
| 105 | myModificationState (0), |
| 106 | myIsMirrored (Standard_False) |
| 107 | { |
| 108 | updateLayerTransformation(); |
| 109 | } |
| 110 | |
| 111 | // ======================================================================= |
| 112 | // function : ~OpenGl_Structure |
| 113 | // purpose : |
| 114 | // ======================================================================= |
| 115 | OpenGl_Structure::~OpenGl_Structure() |
| 116 | { |
| 117 | Release (Handle(OpenGl_Context)()); |
| 118 | } |
| 119 | |
| 120 | // ======================================================================= |
| 121 | // function : SetZLayer |
| 122 | // purpose : |
| 123 | // ======================================================================= |
| 124 | void OpenGl_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerIndex) |
| 125 | { |
| 126 | Graphic3d_CStructure::SetZLayer (theLayerIndex); |
| 127 | updateLayerTransformation(); |
| 128 | } |
| 129 | |
| 130 | // ======================================================================= |
| 131 | // function : SetTransformation |
| 132 | // purpose : |
| 133 | // ======================================================================= |
| 134 | void OpenGl_Structure::SetTransformation (const Handle(TopLoc_Datum3D)& theTrsf) |
| 135 | { |
| 136 | myTrsf = theTrsf; |
| 137 | myIsMirrored = Standard_False; |
| 138 | if (!myTrsf.IsNull()) |
| 139 | { |
| 140 | // Determinant of transform matrix less then 0 means that mirror transform applied. |
| 141 | const gp_Trsf& aTrsf = myTrsf->Transformation(); |
| 142 | const Standard_Real aDet = aTrsf.Value(1, 1) * (aTrsf.Value (2, 2) * aTrsf.Value (3, 3) - aTrsf.Value (3, 2) * aTrsf.Value (2, 3)) |
| 143 | - aTrsf.Value(1, 2) * (aTrsf.Value (2, 1) * aTrsf.Value (3, 3) - aTrsf.Value (3, 1) * aTrsf.Value (2, 3)) |
| 144 | + aTrsf.Value(1, 3) * (aTrsf.Value (2, 1) * aTrsf.Value (3, 2) - aTrsf.Value (3, 1) * aTrsf.Value (2, 2)); |
| 145 | myIsMirrored = aDet < 0.0; |
| 146 | } |
| 147 | |
| 148 | updateLayerTransformation(); |
| 149 | if (IsRaytracable()) |
| 150 | { |
| 151 | ++myModificationState; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | // ======================================================================= |
| 156 | // function : SetTransformPersistence |
| 157 | // purpose : |
| 158 | // ======================================================================= |
| 159 | void OpenGl_Structure::SetTransformPersistence (const Handle(Graphic3d_TransformPers)& theTrsfPers) |
| 160 | { |
| 161 | if ((myTrsfPers.IsNull() || theTrsfPers.IsNull()) && myTrsfPers != theTrsfPers) |
| 162 | { |
| 163 | ++myModificationState; |
| 164 | } |
| 165 | myTrsfPers = theTrsfPers; |
| 166 | updateLayerTransformation(); |
| 167 | } |
| 168 | |
| 169 | // ======================================================================= |
| 170 | // function : updateLayerTransformation |
| 171 | // purpose : |
| 172 | // ======================================================================= |
| 173 | void OpenGl_Structure::updateLayerTransformation() |
| 174 | { |
| 175 | gp_Trsf aRenderTrsf; |
| 176 | if (!myTrsf.IsNull()) |
| 177 | { |
| 178 | aRenderTrsf = myTrsf->Trsf(); |
| 179 | } |
| 180 | |
| 181 | const Graphic3d_ZLayerSettings& aLayer = myGraphicDriver->ZLayerSettings (myZLayer); |
| 182 | if (!aLayer.OriginTransformation().IsNull() |
| 183 | && myTrsfPers.IsNull()) |
| 184 | { |
| 185 | aRenderTrsf.SetTranslationPart (aRenderTrsf.TranslationPart() - aLayer.Origin()); |
| 186 | } |
| 187 | aRenderTrsf.GetMat4 (myRenderTrsf); |
| 188 | } |
| 189 | |
| 190 | // ======================================================================= |
| 191 | // function : GraphicHighlight |
| 192 | // purpose : |
| 193 | // ======================================================================= |
| 194 | void OpenGl_Structure::GraphicHighlight (const Handle(Graphic3d_PresentationAttributes)& theStyle) |
| 195 | { |
| 196 | myHighlightStyle = theStyle; |
| 197 | highlight = 1; |
| 198 | } |
| 199 | |
| 200 | // ======================================================================= |
| 201 | // function : GraphicUnhighlight |
| 202 | // purpose : |
| 203 | // ======================================================================= |
| 204 | void OpenGl_Structure::GraphicUnhighlight() |
| 205 | { |
| 206 | highlight = 0; |
| 207 | myHighlightStyle.Nullify(); |
| 208 | } |
| 209 | |
| 210 | // ======================================================================= |
| 211 | // function : OnVisibilityChanged |
| 212 | // purpose : |
| 213 | // ======================================================================= |
| 214 | void OpenGl_Structure::OnVisibilityChanged() |
| 215 | { |
| 216 | if (IsRaytracable()) |
| 217 | { |
| 218 | ++myModificationState; |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | // ======================================================================= |
| 223 | // function : IsRaytracable |
| 224 | // purpose : |
| 225 | // ======================================================================= |
| 226 | Standard_Boolean OpenGl_Structure::IsRaytracable() const |
| 227 | { |
| 228 | if (!myGroups.IsEmpty() |
| 229 | && myIsRaytracable |
| 230 | && myTrsfPers.IsNull()) |
| 231 | { |
| 232 | return Standard_True; |
| 233 | } |
| 234 | |
| 235 | return myInstancedStructure != NULL |
| 236 | && myInstancedStructure->IsRaytracable(); |
| 237 | } |
| 238 | |
| 239 | // ======================================================================= |
| 240 | // function : UpdateRaytracableState |
| 241 | // purpose : |
| 242 | // ======================================================================= |
| 243 | void OpenGl_Structure::UpdateStateIfRaytracable (const Standard_Boolean toCheck) const |
| 244 | { |
| 245 | myIsRaytracable = !toCheck; |
| 246 | if (!myIsRaytracable) |
| 247 | { |
| 248 | for (OpenGl_Structure::GroupIterator anIter (myGroups); anIter.More(); anIter.Next()) |
| 249 | { |
| 250 | if (anIter.Value()->IsRaytracable()) |
| 251 | { |
| 252 | myIsRaytracable = Standard_True; |
| 253 | break; |
| 254 | } |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | if (IsRaytracable()) |
| 259 | { |
| 260 | ++myModificationState; |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | // ======================================================================= |
| 265 | // function : Connect |
| 266 | // purpose : |
| 267 | // ======================================================================= |
| 268 | void OpenGl_Structure::Connect (Graphic3d_CStructure& theStructure) |
| 269 | { |
| 270 | OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure); |
| 271 | |
| 272 | Standard_ASSERT_RAISE (myInstancedStructure == NULL || myInstancedStructure == aStruct, |
| 273 | "Error! Instanced structure is already defined"); |
| 274 | |
| 275 | myInstancedStructure = aStruct; |
| 276 | |
| 277 | if (aStruct->IsRaytracable()) |
| 278 | { |
| 279 | UpdateStateIfRaytracable (Standard_False); |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | // ======================================================================= |
| 284 | // function : Disconnect |
| 285 | // purpose : |
| 286 | // ======================================================================= |
| 287 | void OpenGl_Structure::Disconnect (Graphic3d_CStructure& theStructure) |
| 288 | { |
| 289 | OpenGl_Structure* aStruct = static_cast<OpenGl_Structure*> (&theStructure); |
| 290 | |
| 291 | if (myInstancedStructure == aStruct) |
| 292 | { |
| 293 | myInstancedStructure = NULL; |
| 294 | |
| 295 | if (aStruct->IsRaytracable()) |
| 296 | { |
| 297 | UpdateStateIfRaytracable(); |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | // ======================================================================= |
| 303 | // function : NewGroup |
| 304 | // purpose : |
| 305 | // ======================================================================= |
| 306 | Handle(Graphic3d_Group) OpenGl_Structure::NewGroup (const Handle(Graphic3d_Structure)& theStruct) |
| 307 | { |
| 308 | Handle(OpenGl_Group) aGroup = new OpenGl_Group (theStruct); |
| 309 | myGroups.Append (aGroup); |
| 310 | return aGroup; |
| 311 | } |
| 312 | |
| 313 | // ======================================================================= |
| 314 | // function : RemoveGroup |
| 315 | // purpose : |
| 316 | // ======================================================================= |
| 317 | void OpenGl_Structure::RemoveGroup (const Handle(Graphic3d_Group)& theGroup) |
| 318 | { |
| 319 | if (theGroup.IsNull()) |
| 320 | { |
| 321 | return; |
| 322 | } |
| 323 | |
| 324 | for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) |
| 325 | { |
| 326 | // Check for the given group |
| 327 | if (aGroupIter.Value() == theGroup) |
| 328 | { |
| 329 | const Standard_Boolean wasRaytracable = |
| 330 | static_cast<const OpenGl_Group&> (*theGroup).IsRaytracable(); |
| 331 | |
| 332 | theGroup->Clear (Standard_False); |
| 333 | |
| 334 | if (wasRaytracable) |
| 335 | { |
| 336 | UpdateStateIfRaytracable(); |
| 337 | } |
| 338 | |
| 339 | myGroups.Remove (aGroupIter); |
| 340 | return; |
| 341 | } |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | // ======================================================================= |
| 346 | // function : Clear |
| 347 | // purpose : |
| 348 | // ======================================================================= |
| 349 | void OpenGl_Structure::Clear() |
| 350 | { |
| 351 | Clear (GlDriver()->GetSharedContext()); |
| 352 | } |
| 353 | |
| 354 | // ======================================================================= |
| 355 | // function : Clear |
| 356 | // purpose : |
| 357 | // ======================================================================= |
| 358 | void OpenGl_Structure::Clear (const Handle(OpenGl_Context)& theGlCtx) |
| 359 | { |
| 360 | Standard_Boolean aRaytracableGroupDeleted (Standard_False); |
| 361 | |
| 362 | // Release groups |
| 363 | for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) |
| 364 | { |
| 365 | aRaytracableGroupDeleted |= aGroupIter.Value()->IsRaytracable(); |
| 366 | |
| 367 | // Delete objects |
| 368 | aGroupIter.ChangeValue()->Release (theGlCtx); |
| 369 | } |
| 370 | myGroups.Clear(); |
| 371 | |
| 372 | if (aRaytracableGroupDeleted) |
| 373 | { |
| 374 | myIsRaytracable = Standard_False; |
| 375 | } |
| 376 | |
| 377 | Is2dText = Standard_False; |
| 378 | IsForHighlight = Standard_False; |
| 379 | } |
| 380 | |
| 381 | // ======================================================================= |
| 382 | // function : renderGeometry |
| 383 | // purpose : |
| 384 | // ======================================================================= |
| 385 | void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorkspace, |
| 386 | bool& theHasClosed) const |
| 387 | { |
| 388 | if (myInstancedStructure != NULL) |
| 389 | { |
| 390 | myInstancedStructure->renderGeometry (theWorkspace, theHasClosed); |
| 391 | } |
| 392 | |
| 393 | bool anOldCastShadows = false; |
| 394 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
| 395 | for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) |
| 396 | { |
| 397 | const OpenGl_Group* aGroup = aGroupIter.Value(); |
| 398 | |
| 399 | const Handle(Graphic3d_TransformPers)& aTrsfPers = aGroup->TransformPersistence(); |
| 400 | if (!aTrsfPers.IsNull()) |
| 401 | { |
| 402 | applyPersistence (aCtx, aTrsfPers, true, anOldCastShadows); |
| 403 | aCtx->ApplyModelViewMatrix(); |
| 404 | } |
| 405 | |
| 406 | theHasClosed = theHasClosed || aGroup->IsClosed(); |
| 407 | aGroup->Render (theWorkspace); |
| 408 | |
| 409 | if (!aTrsfPers.IsNull()) |
| 410 | { |
| 411 | revertPersistence (aCtx, aTrsfPers, true, anOldCastShadows); |
| 412 | aCtx->ApplyModelViewMatrix(); |
| 413 | } |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | // ======================================================================= |
| 418 | // function : Render |
| 419 | // purpose : |
| 420 | // ======================================================================= |
| 421 | void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) const |
| 422 | { |
| 423 | // Process the structure only if visible |
| 424 | if (!visible) |
| 425 | { |
| 426 | return; |
| 427 | } |
| 428 | |
| 429 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
| 430 | |
| 431 | // Render named status |
| 432 | if (highlight && !myHighlightStyle.IsNull() && myHighlightStyle->Method() != Aspect_TOHM_BOUNDBOX) |
| 433 | { |
| 434 | theWorkspace->SetHighlightStyle (myHighlightStyle); |
| 435 | } |
| 436 | |
| 437 | // Apply local transformation |
| 438 | aCtx->ModelWorldState.Push(); |
| 439 | OpenGl_Mat4& aModelWorld = aCtx->ModelWorldState.ChangeCurrent(); |
| 440 | aModelWorld = myRenderTrsf; |
| 441 | |
| 442 | const Standard_Boolean anOldGlNormalize = aCtx->IsGlNormalizeEnabled(); |
| 443 | |
| 444 | // detect scale transform |
| 445 | if (aCtx->core11ffp != NULL |
| 446 | && !myTrsf.IsNull()) |
| 447 | { |
| 448 | const Standard_Real aScale = myTrsf->Trsf().ScaleFactor(); |
| 449 | if (Abs (aScale - 1.0) > Precision::Confusion()) |
| 450 | { |
| 451 | aCtx->SetGlNormalizeEnabled (Standard_True); |
| 452 | } |
| 453 | } |
| 454 | |
| 455 | bool anOldCastShadows = false; |
| 456 | #ifdef GL_DEPTH_CLAMP |
| 457 | bool toRestoreDepthClamp = false; |
| 458 | #endif |
| 459 | if (!myTrsfPers.IsNull()) |
| 460 | { |
| 461 | applyPersistence (aCtx, myTrsfPers, false, anOldCastShadows); |
| 462 | |
| 463 | #ifdef GL_DEPTH_CLAMP |
| 464 | if (myTrsfPers->Mode() == Graphic3d_TMF_CameraPers |
| 465 | && aCtx->arbDepthClamp) |
| 466 | { |
| 467 | toRestoreDepthClamp = true; |
| 468 | aCtx->core11fwd->glEnable (GL_DEPTH_CLAMP); |
| 469 | } |
| 470 | #endif |
| 471 | } |
| 472 | |
| 473 | // Take into account transform persistence |
| 474 | aCtx->ApplyModelViewMatrix(); |
| 475 | |
| 476 | // remember aspects |
| 477 | const OpenGl_Aspects* aPrevAspectFace = theWorkspace->Aspects(); |
| 478 | |
| 479 | // Apply correction for mirror transform |
| 480 | if (myIsMirrored) |
| 481 | { |
| 482 | aCtx->core11fwd->glFrontFace (GL_CW); |
| 483 | } |
| 484 | |
| 485 | // Collect clipping planes of structure scope |
| 486 | aCtx->ChangeClipping().SetLocalPlanes (myClipPlanes); |
| 487 | |
| 488 | // True if structure is fully clipped |
| 489 | bool isClipped = false; |
| 490 | bool hasDisabled = false; |
| 491 | if (aCtx->Clipping().IsClippingOrCappingOn()) |
| 492 | { |
| 493 | const Graphic3d_BndBox3d& aBBox = BoundingBox(); |
| 494 | if (!myClipPlanes.IsNull() |
| 495 | && myClipPlanes->ToOverrideGlobal()) |
| 496 | { |
| 497 | aCtx->ChangeClipping().DisableGlobal(); |
| 498 | hasDisabled = aCtx->Clipping().HasDisabled(); |
| 499 | } |
| 500 | else if (!myTrsfPers.IsNull()) |
| 501 | { |
| 502 | if (myTrsfPers->IsZoomOrRotate()) |
| 503 | { |
| 504 | // Zoom/rotate persistence object lives in two worlds at the same time. |
| 505 | // Global clipping planes can not be trivially applied without being converted |
| 506 | // into local space of transformation persistence object. |
| 507 | // As more simple alternative - just clip entire object by its anchor point defined in the world space. |
| 508 | const gp_Pnt anAnchor = myTrsfPers->AnchorPoint(); |
| 509 | for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More() && aPlaneIt.IsGlobal(); aPlaneIt.Next()) |
| 510 | { |
| 511 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); |
| 512 | if (!aPlane->IsOn()) |
| 513 | { |
| 514 | continue; |
| 515 | } |
| 516 | |
| 517 | // check for clipping |
| 518 | const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0); |
| 519 | if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out) |
| 520 | { |
| 521 | isClipped = true; |
| 522 | break; |
| 523 | } |
| 524 | } |
| 525 | } |
| 526 | |
| 527 | aCtx->ChangeClipping().DisableGlobal(); |
| 528 | hasDisabled = aCtx->Clipping().HasDisabled(); |
| 529 | } |
| 530 | |
| 531 | // Set of clipping planes that do not intersect the structure, |
| 532 | // and thus can be disabled to improve rendering performance |
| 533 | if (aBBox.IsValid() |
| 534 | && myTrsfPers.IsNull()) |
| 535 | { |
| 536 | for (OpenGl_ClippingIterator aPlaneIt (aCtx->Clipping()); aPlaneIt.More(); aPlaneIt.Next()) |
| 537 | { |
| 538 | const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value(); |
| 539 | if (aPlaneIt.IsDisabled()) |
| 540 | { |
| 541 | continue; |
| 542 | } |
| 543 | |
| 544 | const Graphic3d_ClipState aBoxState = aPlane->ProbeBox (aBBox); |
| 545 | if (aBoxState == Graphic3d_ClipState_In) |
| 546 | { |
| 547 | aCtx->ChangeClipping().SetEnabled (aPlaneIt, false); |
| 548 | hasDisabled = true; |
| 549 | } |
| 550 | else if (aBoxState == Graphic3d_ClipState_Out && myBndBoxClipCheck) |
| 551 | { |
| 552 | isClipped = true; |
| 553 | break; |
| 554 | } |
| 555 | } |
| 556 | } |
| 557 | |
| 558 | if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty()) |
| 559 | || hasDisabled) |
| 560 | { |
| 561 | // Set OCCT state uniform variables |
| 562 | aCtx->ShaderManager()->UpdateClippingState(); |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | // Render groups |
| 567 | bool hasClosedPrims = false; |
| 568 | if (!isClipped) |
| 569 | { |
| 570 | renderGeometry (theWorkspace, hasClosedPrims); |
| 571 | } |
| 572 | |
| 573 | // Reset correction for mirror transform |
| 574 | if (myIsMirrored) |
| 575 | { |
| 576 | aCtx->core11fwd->glFrontFace (GL_CCW); |
| 577 | } |
| 578 | |
| 579 | // Render capping for structure groups |
| 580 | if (hasClosedPrims |
| 581 | && aCtx->Clipping().IsCappingOn()) |
| 582 | { |
| 583 | OpenGl_CappingAlgo::RenderCapping (theWorkspace, *this); |
| 584 | } |
| 585 | |
| 586 | // Revert structure clippings |
| 587 | if (hasDisabled) |
| 588 | { |
| 589 | // enable planes that were previously disabled |
| 590 | aCtx->ChangeClipping().RestoreDisabled(); |
| 591 | } |
| 592 | aCtx->ChangeClipping().SetLocalPlanes (Handle(Graphic3d_SequenceOfHClipPlane)()); |
| 593 | if ((!myClipPlanes.IsNull() && !myClipPlanes->IsEmpty()) |
| 594 | || hasDisabled) |
| 595 | { |
| 596 | // Set OCCT state uniform variables |
| 597 | aCtx->ShaderManager()->RevertClippingState(); |
| 598 | } |
| 599 | |
| 600 | // Restore local transformation |
| 601 | aCtx->ModelWorldState.Pop(); |
| 602 | aCtx->SetGlNormalizeEnabled (anOldGlNormalize); |
| 603 | |
| 604 | // Restore aspects |
| 605 | theWorkspace->SetAspects (aPrevAspectFace); |
| 606 | |
| 607 | // Apply highlight box |
| 608 | if (!isClipped |
| 609 | && !myHighlightStyle.IsNull() |
| 610 | && myHighlightStyle->Method() == Aspect_TOHM_BOUNDBOX) |
| 611 | { |
| 612 | aCtx->ApplyModelViewMatrix(); |
| 613 | theWorkspace->SetHighlightStyle (myHighlightStyle); |
| 614 | renderBoundingBox (theWorkspace); |
| 615 | } |
| 616 | |
| 617 | if (!myTrsfPers.IsNull()) |
| 618 | { |
| 619 | revertPersistence (aCtx, myTrsfPers, false, anOldCastShadows); |
| 620 | #ifdef GL_DEPTH_CLAMP |
| 621 | if (toRestoreDepthClamp) { aCtx->core11fwd->glDisable (GL_DEPTH_CLAMP); } |
| 622 | #endif |
| 623 | } |
| 624 | |
| 625 | // Restore named status |
| 626 | theWorkspace->SetHighlightStyle (Handle(Graphic3d_PresentationAttributes)()); |
| 627 | } |
| 628 | |
| 629 | // ======================================================================= |
| 630 | // function : Release |
| 631 | // purpose : |
| 632 | // ======================================================================= |
| 633 | void OpenGl_Structure::Release (const Handle(OpenGl_Context)& theGlCtx) |
| 634 | { |
| 635 | // Release groups |
| 636 | Clear (theGlCtx); |
| 637 | myHighlightStyle.Nullify(); |
| 638 | } |
| 639 | |
| 640 | // ======================================================================= |
| 641 | // function : ReleaseGlResources |
| 642 | // purpose : |
| 643 | // ======================================================================= |
| 644 | void OpenGl_Structure::ReleaseGlResources (const Handle(OpenGl_Context)& theGlCtx) |
| 645 | { |
| 646 | for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next()) |
| 647 | { |
| 648 | aGroupIter.ChangeValue()->Release (theGlCtx); |
| 649 | } |
| 650 | } |
| 651 | |
| 652 | //======================================================================= |
| 653 | //function : ShadowLink |
| 654 | //purpose : |
| 655 | //======================================================================= |
| 656 | Handle(Graphic3d_CStructure) OpenGl_Structure::ShadowLink (const Handle(Graphic3d_StructureManager)& theManager) const |
| 657 | { |
| 658 | return new OpenGl_StructureShadow (theManager, this); |
| 659 | } |
| 660 | |
| 661 | // ======================================================================= |
| 662 | // function : applyPersistence |
| 663 | // purpose : |
| 664 | // ======================================================================= |
| 665 | void OpenGl_Structure::applyPersistence (const Handle(OpenGl_Context)& theCtx, |
| 666 | const Handle(Graphic3d_TransformPers)& theTrsfPers, |
| 667 | const Standard_Boolean theIsLocal, |
| 668 | Standard_Boolean& theOldCastShadows) const |
| 669 | { |
| 670 | // temporarily disable shadows on non-3d objects |
| 671 | theOldCastShadows = theCtx->ShaderManager()->SetCastShadows (false); |
| 672 | |
| 673 | theCtx->WorldViewState.Push(); |
| 674 | OpenGl_Mat4& aWorldView = theCtx->WorldViewState.ChangeCurrent(); |
| 675 | |
| 676 | if (theIsLocal |
| 677 | && theTrsfPers->IsZoomOrRotate()) |
| 678 | { |
| 679 | // move anchor point to presentation location |
| 680 | theCtx->ModelWorldState.Push(); |
| 681 | OpenGl_Mat4& aModelWorld = theCtx->ModelWorldState.ChangeCurrent(); |
| 682 | gp_Pnt aStartPnt = theTrsfPers->AnchorPoint(); |
| 683 | Graphic3d_Vec4 anAnchorPoint = aModelWorld * Graphic3d_Vec4 ((Standard_ShortReal)aStartPnt.X(), |
| 684 | (Standard_ShortReal)aStartPnt.Y(), |
| 685 | (Standard_ShortReal)aStartPnt.Z(), 1.0f); |
| 686 | aModelWorld.SetColumn (3, Graphic3d_Vec4 (Graphic3d_Vec3 (0.0), 1.0)); // reset translation part |
| 687 | aStartPnt.SetCoord (anAnchorPoint.x(), anAnchorPoint.y(), anAnchorPoint.z()); |
| 688 | |
| 689 | theTrsfPers->Apply (theCtx->Camera(), |
| 690 | theCtx->ProjectionState.Current(), aWorldView, |
| 691 | theCtx->VirtualViewport()[2], theCtx->VirtualViewport()[3], |
| 692 | &aStartPnt); |
| 693 | } |
| 694 | else |
| 695 | { |
| 696 | theTrsfPers->Apply (theCtx->Camera(), |
| 697 | theCtx->ProjectionState.Current(), aWorldView, |
| 698 | theCtx->VirtualViewport()[2], theCtx->VirtualViewport()[3]); |
| 699 | } |
| 700 | |
| 701 | if (!theCtx->IsGlNormalizeEnabled() |
| 702 | && theCtx->core11ffp != NULL) |
| 703 | { |
| 704 | const Standard_Real aScale = Graphic3d_TransformUtils::ScaleFactor (aWorldView); |
| 705 | if (Abs (aScale - 1.0) > Precision::Confusion()) |
| 706 | { |
| 707 | theCtx->SetGlNormalizeEnabled (true); |
| 708 | } |
| 709 | } |
| 710 | } |
| 711 | |
| 712 | // ======================================================================= |
| 713 | // function : revertPersistence |
| 714 | // purpose : |
| 715 | // ======================================================================= |
| 716 | void OpenGl_Structure::revertPersistence (const Handle(OpenGl_Context)& theCtx, |
| 717 | const Handle(Graphic3d_TransformPers)& theTrsfPers, |
| 718 | const Standard_Boolean theIsLocal, |
| 719 | const Standard_Boolean theOldCastShadows) const |
| 720 | { |
| 721 | if (theIsLocal |
| 722 | && theTrsfPers->IsZoomOrRotate()) |
| 723 | { |
| 724 | theCtx->ModelWorldState.Pop(); |
| 725 | } |
| 726 | theCtx->WorldViewState.Pop(); |
| 727 | theCtx->ShaderManager()->SetCastShadows (theOldCastShadows); |
| 728 | } |
| 729 | |
| 730 | //======================================================================= |
| 731 | //function : DumpJson |
| 732 | //purpose : |
| 733 | //======================================================================= |
| 734 | void OpenGl_Structure::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const |
| 735 | { |
| 736 | OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) |
| 737 | |
| 738 | OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Graphic3d_CStructure) |
| 739 | |
| 740 | OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myInstancedStructure) |
| 741 | |
| 742 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsRaytracable) |
| 743 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myModificationState) |
| 744 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsMirrored) |
| 745 | } |