mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-16 10:08:36 +03:00
Added new flag Graphic3d_AspectFillArea3d::ToDrawSilhouette() activating silhouette (outline) rendering. The new feature can simulate fake HLR look-n-feel, when combined with Aspect_IS_HIDDENLINE interior style (filling object with background color), face boundary edges (with most continuity flag set to c2 or lower). Silhouette GLSL program is very simple - it displaces model alongside vertex normal, so that it is applicable only to smooth surfaces and closed volumes, and produces visual artifacts at sharp corners, especially when face boundary is disabled. OpenGl_SetOfShaderPrograms has been modified so that to reduce dimensions of the grid of static size based on amount of program combinations. OpenGl_PrimitiveArray no more allocates VBO resources if primitive array is marked to be not drawn via interior style / line type / marker type.
1147 lines
40 KiB
C++
1147 lines
40 KiB
C++
// Created on: 2011-07-13
|
|
// Created by: Sergey ZERCHANINOV
|
|
// Copyright (c) 2011-2013 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#include <OpenGl_AspectFace.hxx>
|
|
#include <OpenGl_Context.hxx>
|
|
#include <OpenGl_GraphicDriver.hxx>
|
|
#include <OpenGl_IndexBuffer.hxx>
|
|
#include <OpenGl_PointSprite.hxx>
|
|
#include <OpenGl_PrimitiveArray.hxx>
|
|
#include <OpenGl_Sampler.hxx>
|
|
#include <OpenGl_ShaderManager.hxx>
|
|
#include <OpenGl_ShaderProgram.hxx>
|
|
#include <OpenGl_Structure.hxx>
|
|
#include <OpenGl_VertexBufferCompat.hxx>
|
|
#include <OpenGl_View.hxx>
|
|
#include <OpenGl_Workspace.hxx>
|
|
#include <Graphic3d_TextureParams.hxx>
|
|
#include <NCollection_AlignedAllocator.hxx>
|
|
|
|
namespace
|
|
{
|
|
//! Convert data type to GL info
|
|
inline GLenum toGlDataType (const Graphic3d_TypeOfData theType,
|
|
GLint& theNbComp)
|
|
{
|
|
switch (theType)
|
|
{
|
|
case Graphic3d_TOD_USHORT:
|
|
theNbComp = 1;
|
|
return GL_UNSIGNED_SHORT;
|
|
case Graphic3d_TOD_UINT:
|
|
theNbComp = 1;
|
|
return GL_UNSIGNED_INT;
|
|
case Graphic3d_TOD_VEC2:
|
|
theNbComp = 2;
|
|
return GL_FLOAT;
|
|
case Graphic3d_TOD_VEC3:
|
|
theNbComp = 3;
|
|
return GL_FLOAT;
|
|
case Graphic3d_TOD_VEC4:
|
|
theNbComp = 4;
|
|
return GL_FLOAT;
|
|
case Graphic3d_TOD_VEC4UB:
|
|
theNbComp = 4;
|
|
return GL_UNSIGNED_BYTE;
|
|
case Graphic3d_TOD_FLOAT:
|
|
theNbComp = 1;
|
|
return GL_FLOAT;
|
|
}
|
|
theNbComp = 0;
|
|
return GL_NONE;
|
|
}
|
|
|
|
}
|
|
|
|
//! Auxiliary template for VBO with interleaved attributes.
|
|
template<class TheBaseClass, int NbAttributes>
|
|
class OpenGl_VertexBufferT : public TheBaseClass
|
|
{
|
|
public:
|
|
|
|
//! Create uninitialized VBO.
|
|
OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
|
|
: Stride (theAttribs.IsInterleaved() ? theAttribs.Stride : 0)
|
|
{
|
|
memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
|
|
}
|
|
|
|
virtual bool HasColorAttribute() const
|
|
{
|
|
for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
|
|
{
|
|
const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
|
|
if (anAttrib.Id == Graphic3d_TOA_COLOR)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual bool HasNormalAttribute() const
|
|
{
|
|
for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
|
|
{
|
|
const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
|
|
if (anAttrib.Id == Graphic3d_TOA_NORM)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual void BindPositionAttribute (const Handle(OpenGl_Context)& theGlCtx) const
|
|
{
|
|
if (!TheBaseClass::IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
TheBaseClass::Bind (theGlCtx);
|
|
GLint aNbComp;
|
|
const GLubyte* anOffset = TheBaseClass::myOffset;
|
|
const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
|
|
for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
|
|
{
|
|
const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
|
|
const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
|
|
if (anAttrib.Id == Graphic3d_TOA_POS
|
|
&& aDataType != GL_NONE)
|
|
{
|
|
TheBaseClass::bindAttribute (theGlCtx, Graphic3d_TOA_POS, aNbComp, aDataType, Stride, anOffset);
|
|
break;
|
|
}
|
|
|
|
anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
|
|
}
|
|
}
|
|
|
|
virtual void BindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
|
|
{
|
|
if (!TheBaseClass::IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
TheBaseClass::Bind (theGlCtx);
|
|
GLint aNbComp;
|
|
const GLubyte* anOffset = TheBaseClass::myOffset;
|
|
const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
|
|
for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
|
|
{
|
|
const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
|
|
const GLenum aDataType = toGlDataType (anAttrib.DataType, aNbComp);
|
|
if (aDataType != GL_NONE)
|
|
{
|
|
TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
|
|
}
|
|
anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
|
|
}
|
|
}
|
|
|
|
virtual void UnbindAllAttributes (const Handle(OpenGl_Context)& theGlCtx) const
|
|
{
|
|
if (!TheBaseClass::IsValid())
|
|
{
|
|
return;
|
|
}
|
|
TheBaseClass::Unbind (theGlCtx);
|
|
|
|
for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
|
|
{
|
|
const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
|
|
TheBaseClass::unbindAttribute (theGlCtx, anAttrib.Id);
|
|
}
|
|
}
|
|
|
|
private:
|
|
|
|
Graphic3d_Attribute Attribs[NbAttributes];
|
|
Standard_Integer Stride;
|
|
|
|
};
|
|
|
|
// =======================================================================
|
|
// function : clearMemoryGL
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
|
|
{
|
|
if (!myVboIndices.IsNull())
|
|
{
|
|
myVboIndices->Release (theGlCtx.operator->());
|
|
myVboIndices.Nullify();
|
|
}
|
|
if (!myVboAttribs.IsNull())
|
|
{
|
|
myVboAttribs->Release (theGlCtx.operator->());
|
|
myVboAttribs.Nullify();
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : initNormalVbo
|
|
// purpose :
|
|
// =======================================================================
|
|
Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Context)& theCtx) const
|
|
{
|
|
switch (myAttribs->NbAttributes)
|
|
{
|
|
case 1: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 1> (*myAttribs); break;
|
|
case 2: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 2> (*myAttribs); break;
|
|
case 3: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 3> (*myAttribs); break;
|
|
case 4: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 4> (*myAttribs); break;
|
|
case 5: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 5> (*myAttribs); break;
|
|
case 6: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 6> (*myAttribs); break;
|
|
case 7: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 7> (*myAttribs); break;
|
|
case 8: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 8> (*myAttribs); break;
|
|
case 9: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 9> (*myAttribs); break;
|
|
case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
|
|
}
|
|
|
|
const Standard_Boolean isAttribMutable = myAttribs->IsMutable();
|
|
const Standard_Boolean isAttribInterleaved = myAttribs->IsInterleaved();
|
|
if (myAttribs->NbElements != myAttribs->NbMaxElements()
|
|
&& myIndices.IsNull()
|
|
&& (!isAttribInterleaved || isAttribMutable))
|
|
{
|
|
throw Standard_ProgramError ("OpenGl_PrimitiveArray::buildVBO() - vertex attribute data with reserved size is not supported");
|
|
}
|
|
|
|
// specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
|
|
const Standard_Integer aNbVertexes = (isAttribMutable || !isAttribInterleaved) ? myAttribs->NbMaxElements() : myAttribs->NbElements;
|
|
if (!myVboAttribs->init (theCtx, myAttribs->Stride, aNbVertexes, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
|
|
{
|
|
TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbVertexes + " vertices. Out of memory?";
|
|
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
|
|
|
|
clearMemoryGL (theCtx);
|
|
return Standard_False;
|
|
}
|
|
else if (myIndices.IsNull())
|
|
{
|
|
if (isAttribMutable && isAttribInterleaved)
|
|
{
|
|
// for mutable interlaced array we can change dynamically number of vertexes (they will be just skipped at the end of buffer);
|
|
// this doesn't matter in case if we have indexed array
|
|
myVboAttribs->SetElemsNb (myAttribs->NbElements);
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
const Standard_Integer aNbIndexes = !myIndices->IsMutable() ? myIndices->NbElements : myIndices->NbMaxElements();
|
|
myVboIndices = new OpenGl_IndexBuffer();
|
|
bool isOk = false;
|
|
switch (myIndices->Stride)
|
|
{
|
|
case 2:
|
|
{
|
|
isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLushort*> (myIndices->Data()));
|
|
myVboIndices->SetElemsNb (myIndices->NbElements);
|
|
myIndices->Validate();
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLuint*> (myIndices->Data()));
|
|
myVboIndices->SetElemsNb (myIndices->NbElements);
|
|
myIndices->Validate();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
clearMemoryGL (theCtx);
|
|
return Standard_False;
|
|
}
|
|
}
|
|
if (!isOk)
|
|
{
|
|
TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbIndexes + " indices. Out of memory?";
|
|
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
|
|
clearMemoryGL (theCtx);
|
|
return Standard_False;
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : buildVBO
|
|
// purpose :
|
|
// =======================================================================
|
|
Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& theCtx,
|
|
const Standard_Boolean theToKeepData) const
|
|
{
|
|
bool isNormalMode = theCtx->ToUseVbo();
|
|
clearMemoryGL (theCtx);
|
|
if (myAttribs.IsNull()
|
|
|| myAttribs->IsEmpty()
|
|
|| myAttribs->NbElements < 1
|
|
|| myAttribs->NbAttributes < 1
|
|
|| myAttribs->NbAttributes > 10)
|
|
{
|
|
// vertices should be always defined - others are optional
|
|
return Standard_False;
|
|
}
|
|
|
|
if (isNormalMode
|
|
&& initNormalVbo (theCtx))
|
|
{
|
|
if (!theCtx->caps->keepArrayData
|
|
&& !theToKeepData
|
|
&& !myAttribs->IsMutable())
|
|
{
|
|
myIndices.Nullify();
|
|
myAttribs.Nullify();
|
|
}
|
|
else
|
|
{
|
|
myAttribs->Validate();
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
Handle(OpenGl_VertexBufferCompat) aVboAttribs;
|
|
switch (myAttribs->NbAttributes)
|
|
{
|
|
case 1: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 1> (*myAttribs); break;
|
|
case 2: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 2> (*myAttribs); break;
|
|
case 3: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 3> (*myAttribs); break;
|
|
case 4: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 4> (*myAttribs); break;
|
|
case 5: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 5> (*myAttribs); break;
|
|
case 6: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 6> (*myAttribs); break;
|
|
case 7: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 7> (*myAttribs); break;
|
|
case 8: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 8> (*myAttribs); break;
|
|
case 9: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 9> (*myAttribs); break;
|
|
case 10: aVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBufferCompat, 10>(*myAttribs); break;
|
|
}
|
|
aVboAttribs->initLink (myAttribs, 0, myAttribs->NbElements, GL_NONE);
|
|
if (!myIndices.IsNull())
|
|
{
|
|
Handle(OpenGl_VertexBufferCompat) aVboIndices = new OpenGl_VertexBufferCompat();
|
|
switch (myIndices->Stride)
|
|
{
|
|
case 2:
|
|
{
|
|
aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_SHORT);
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
aVboIndices->initLink (myIndices, 1, myIndices->NbElements, GL_UNSIGNED_INT);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
return Standard_False;
|
|
}
|
|
}
|
|
myVboIndices = aVboIndices;
|
|
}
|
|
myVboAttribs = aVboAttribs;
|
|
if (!theCtx->caps->keepArrayData
|
|
&& !theToKeepData)
|
|
{
|
|
// does not make sense for compatibility mode
|
|
//myIndices.Nullify();
|
|
//myAttribs.Nullify();
|
|
}
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : updateVBO
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::updateVBO (const Handle(OpenGl_Context)& theCtx) const
|
|
{
|
|
if (!myAttribs.IsNull())
|
|
{
|
|
Graphic3d_BufferRange aRange = myAttribs->InvalidatedRange();
|
|
if (!aRange.IsEmpty()
|
|
&& myVboAttribs->IsValid()
|
|
&& !myVboAttribs->IsVirtual())
|
|
{
|
|
myVboAttribs->Bind (theCtx);
|
|
theCtx->core15fwd->glBufferSubData (myVboAttribs->GetTarget(),
|
|
aRange.Start,
|
|
aRange.Length,
|
|
myAttribs->Data() + aRange.Start);
|
|
myVboAttribs->Unbind (theCtx);
|
|
if (myAttribs->IsInterleaved())
|
|
{
|
|
myVboAttribs->SetElemsNb (myAttribs->NbElements);
|
|
}
|
|
}
|
|
myAttribs->Validate();
|
|
}
|
|
if (!myIndices.IsNull())
|
|
{
|
|
Graphic3d_BufferRange aRange = myIndices->InvalidatedRange();
|
|
if (!aRange.IsEmpty()
|
|
&& myVboIndices->IsValid()
|
|
&& !myVboIndices->IsVirtual())
|
|
{
|
|
myVboIndices->Bind (theCtx);
|
|
theCtx->core15fwd->glBufferSubData (myVboIndices->GetTarget(),
|
|
aRange.Start,
|
|
aRange.Length,
|
|
myIndices->Data() + aRange.Start);
|
|
myVboIndices->Unbind (theCtx);
|
|
myVboIndices->SetElemsNb (myIndices->NbElements);
|
|
}
|
|
myIndices->Validate();
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : drawArray
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::drawArray (const Handle(OpenGl_Workspace)& theWorkspace,
|
|
const Graphic3d_Vec4* theFaceColors,
|
|
const Standard_Boolean theHasVertColor) const
|
|
{
|
|
if (myVboAttribs.IsNull())
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (myDrawMode == GL_POINTS)
|
|
{
|
|
// extreme compatibility mode - without sprites but with markers
|
|
drawMarkers (theWorkspace);
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
|
|
const bool toHilight = theWorkspace->ToHighlight();
|
|
const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
|
|
&& aGlContext->ActiveProgram()->HasTessellationStage()
|
|
? GL_PATCHES
|
|
: myDrawMode;
|
|
myVboAttribs->BindAllAttributes (aGlContext);
|
|
if (theHasVertColor && toHilight)
|
|
{
|
|
// disable per-vertex color
|
|
OpenGl_VertexBuffer::unbindAttribute (aGlContext, Graphic3d_TOA_COLOR);
|
|
}
|
|
if (!myVboIndices.IsNull())
|
|
{
|
|
myVboIndices->Bind (aGlContext);
|
|
GLubyte* anOffset = myVboIndices->GetDataOffset();
|
|
if (!myBounds.IsNull())
|
|
{
|
|
// draw primitives by vertex count with the indices
|
|
const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
|
|
for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
|
|
{
|
|
const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
|
|
if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
|
|
glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
|
|
anOffset += aStride * aNbElemsInGroup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// draw one (or sequential) primitive by the indices
|
|
glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
|
|
}
|
|
myVboIndices->Unbind (aGlContext);
|
|
}
|
|
else if (!myBounds.IsNull())
|
|
{
|
|
GLint aFirstElem = 0;
|
|
for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
|
|
{
|
|
const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
|
|
if (theFaceColors != NULL) aGlContext->SetColor4fv (theFaceColors[aGroupIter]);
|
|
glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
|
|
aFirstElem += aNbElemsInGroup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (myDrawMode == GL_POINTS)
|
|
{
|
|
drawMarkers (theWorkspace);
|
|
}
|
|
else
|
|
{
|
|
glDrawArrays (aDrawMode, 0, myVboAttribs->GetElemsNb());
|
|
}
|
|
}
|
|
|
|
// bind with 0
|
|
myVboAttribs->UnbindAllAttributes (aGlContext);
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : drawEdges
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::drawEdges (const OpenGl_Vec4& theEdgeColour,
|
|
const Handle(OpenGl_Workspace)& theWorkspace) const
|
|
{
|
|
const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
|
|
if (myVboAttribs.IsNull())
|
|
{
|
|
return;
|
|
}
|
|
|
|
const OpenGl_AspectLine* anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace()->AspectEdge());
|
|
const OpenGl_AspectLine* anAspect = theWorkspace->ApplyAspectLine();
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
const Standard_Integer aPolyModeOld = aGlContext->SetPolygonMode (GL_LINE);
|
|
#endif
|
|
|
|
if (aGlContext->core20fwd != NULL)
|
|
{
|
|
aGlContext->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspect->Aspect()->Type(),
|
|
Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, Standard_False,
|
|
anAspect->ShaderProgramRes (aGlContext));
|
|
}
|
|
const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull()
|
|
&& aGlContext->ActiveProgram()->HasTessellationStage()
|
|
? GL_PATCHES
|
|
: myDrawMode;
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (aGlContext->ActiveProgram().IsNull()
|
|
&& aGlContext->core11 != NULL)
|
|
{
|
|
glDisable (GL_LIGHTING);
|
|
}
|
|
#endif
|
|
|
|
/// OCC22236 NOTE: draw edges for all situations:
|
|
/// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indices array
|
|
/// 2) draw elements from vertex array, when bounds defines count of primitive's vertices.
|
|
/// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
|
|
myVboAttribs->BindPositionAttribute (aGlContext);
|
|
|
|
aGlContext->SetColor4fv (theEdgeColour);
|
|
aGlContext->SetTypeOfLine (anAspect->Aspect()->Type());
|
|
aGlContext->SetLineWidth (anAspect->Aspect()->Width());
|
|
|
|
if (!myVboIndices.IsNull())
|
|
{
|
|
myVboIndices->Bind (aGlContext);
|
|
GLubyte* anOffset = myVboIndices->GetDataOffset();
|
|
|
|
// draw primitives by vertex count with the indices
|
|
if (!myBounds.IsNull())
|
|
{
|
|
const size_t aStride = myVboIndices->GetDataType() == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
|
|
for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
|
|
{
|
|
const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
|
|
glDrawElements (aDrawMode, aNbElemsInGroup, myVboIndices->GetDataType(), anOffset);
|
|
anOffset += aStride * aNbElemsInGroup;
|
|
}
|
|
}
|
|
// draw one (or sequential) primitive by the indices
|
|
else
|
|
{
|
|
glDrawElements (aDrawMode, myVboIndices->GetElemsNb(), myVboIndices->GetDataType(), anOffset);
|
|
}
|
|
myVboIndices->Unbind (aGlContext);
|
|
}
|
|
else if (!myBounds.IsNull())
|
|
{
|
|
GLint aFirstElem = 0;
|
|
for (Standard_Integer aGroupIter = 0; aGroupIter < myBounds->NbBounds; ++aGroupIter)
|
|
{
|
|
const GLint aNbElemsInGroup = myBounds->Bounds[aGroupIter];
|
|
glDrawArrays (aDrawMode, aFirstElem, aNbElemsInGroup);
|
|
aFirstElem += aNbElemsInGroup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
|
|
}
|
|
|
|
// unbind buffers
|
|
myVboAttribs->UnbindAttribute (aGlContext, Graphic3d_TOA_POS);
|
|
|
|
// restore line context
|
|
theWorkspace->SetAspectLine (anAspectLineOld);
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
aGlContext->SetPolygonMode (aPolyModeOld);
|
|
#endif
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : drawMarkers
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
|
|
{
|
|
const OpenGl_AspectMarker* anAspectMarker = theWorkspace->ApplyAspectMarker();
|
|
const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
|
|
const GLenum aDrawMode = !aCtx->ActiveProgram().IsNull()
|
|
&& aCtx->ActiveProgram()->HasTessellationStage()
|
|
? GL_PATCHES
|
|
: myDrawMode;
|
|
|
|
const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
|
|
const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
|
|
if (aSpriteNorm != NULL
|
|
&& !aSpriteNorm->IsDisplayList())
|
|
{
|
|
// Textured markers will be drawn with the point sprites
|
|
aCtx->SetPointSize (anAspectMarker->MarkerSize());
|
|
aCtx->SetPointSpriteOrigin();
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (aCtx->core11 != NULL)
|
|
{
|
|
aCtx->core11fwd->glEnable (GL_ALPHA_TEST);
|
|
aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, 0.1f);
|
|
}
|
|
#endif
|
|
|
|
aCtx->core11fwd->glEnable (GL_BLEND);
|
|
aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
|
|
|
|
aCtx->core11fwd->glDisable (GL_BLEND);
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (aCtx->core11 != NULL)
|
|
{
|
|
if (aCtx->ShaderManager()->MaterialState().AlphaCutoff() >= ShortRealLast())
|
|
{
|
|
aCtx->core11fwd->glDisable (GL_ALPHA_TEST);
|
|
}
|
|
else
|
|
{
|
|
aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, aCtx->ShaderManager()->MaterialState().AlphaCutoff());
|
|
}
|
|
}
|
|
#endif
|
|
aCtx->SetPointSize (1.0f);
|
|
return;
|
|
}
|
|
else if (anAspectMarker->Aspect()->Type() == Aspect_TOM_POINT)
|
|
{
|
|
aCtx->SetPointSize (anAspectMarker->MarkerSize());
|
|
aCtx->core11fwd->glDrawArrays (aDrawMode, 0, !myVboAttribs.IsNull() ? myVboAttribs->GetElemsNb() : myAttribs->NbElements);
|
|
aCtx->SetPointSize (1.0f);
|
|
}
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
// Textured markers will be drawn with the glBitmap
|
|
else if (anAspectMarker->Aspect()->Type() != Aspect_TOM_POINT
|
|
&& aSpriteNorm != NULL)
|
|
{
|
|
/**if (!isHilight && (myPArray->vcolours != NULL))
|
|
{
|
|
for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
|
|
{
|
|
glColor4ubv (myPArray->vcolours[anIter].GetData());
|
|
glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
|
|
aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
|
|
}
|
|
}
|
|
else*/
|
|
{
|
|
for (Standard_Integer anIter = 0; anIter < myAttribs->NbElements; anIter++)
|
|
{
|
|
aCtx->core11->glRasterPos3fv (myAttribs->Value<Graphic3d_Vec3> (anIter).GetData());
|
|
aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : OpenGl_PrimitiveArray
|
|
// purpose :
|
|
// =======================================================================
|
|
OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver)
|
|
|
|
: myDrawMode (DRAW_MODE_NONE),
|
|
myIsFillType(Standard_False),
|
|
myIsVboInit (Standard_False)
|
|
{
|
|
if (theDriver != NULL)
|
|
{
|
|
myUID = theDriver->GetNextPrimitiveArrayUID();
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : OpenGl_PrimitiveArray
|
|
// purpose :
|
|
// =======================================================================
|
|
OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver,
|
|
const Graphic3d_TypeOfPrimitiveArray theType,
|
|
const Handle(Graphic3d_IndexBuffer)& theIndices,
|
|
const Handle(Graphic3d_Buffer)& theAttribs,
|
|
const Handle(Graphic3d_BoundBuffer)& theBounds)
|
|
|
|
: myIndices (theIndices),
|
|
myAttribs (theAttribs),
|
|
myBounds (theBounds),
|
|
myDrawMode (DRAW_MODE_NONE),
|
|
myIsFillType(Standard_False),
|
|
myIsVboInit (Standard_False)
|
|
{
|
|
if (!myIndices.IsNull()
|
|
&& myIndices->NbElements < 1)
|
|
{
|
|
// dummy index buffer?
|
|
myIndices.Nullify();
|
|
}
|
|
|
|
if (theDriver != NULL)
|
|
{
|
|
myUID = theDriver->GetNextPrimitiveArrayUID();
|
|
#if defined (GL_ES_VERSION_2_0)
|
|
const Handle(OpenGl_Context)& aCtx = theDriver->GetSharedContext();
|
|
if (!aCtx.IsNull())
|
|
{
|
|
processIndices (aCtx);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
setDrawMode (theType);
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : ~OpenGl_PrimitiveArray
|
|
// purpose :
|
|
// =======================================================================
|
|
OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
|
|
{
|
|
//
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : Release
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::Release (OpenGl_Context* theContext)
|
|
{
|
|
myIsVboInit = Standard_False;
|
|
if (!myVboIndices.IsNull())
|
|
{
|
|
if (theContext)
|
|
{
|
|
theContext->DelayedRelease (myVboIndices);
|
|
}
|
|
myVboIndices.Nullify();
|
|
}
|
|
if (!myVboAttribs.IsNull())
|
|
{
|
|
if (theContext)
|
|
{
|
|
theContext->DelayedRelease (myVboAttribs);
|
|
}
|
|
myVboAttribs.Nullify();
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : Render
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
|
|
{
|
|
if (myDrawMode == DRAW_MODE_NONE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const OpenGl_AspectFace* anAspectFace = theWorkspace->ApplyAspectFace();
|
|
const OpenGl_AspectLine* anAspectLine = theWorkspace->ApplyAspectLine();
|
|
const OpenGl_AspectMarker* anAspectMarker = myDrawMode == GL_POINTS
|
|
? theWorkspace->ApplyAspectMarker()
|
|
: theWorkspace->AspectMarker();
|
|
|
|
const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
|
|
|
|
Handle(OpenGl_TextureSet) aTextureBack;
|
|
bool toDrawArray = true;
|
|
int toDrawInteriorEdges = 0; // 0 - no edges, 1 - glsl edges, 2 - polygonMode
|
|
if (myIsFillType)
|
|
{
|
|
toDrawArray = anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_EMPTY;
|
|
if (anAspectFace->Aspect()->ToDrawEdges())
|
|
{
|
|
toDrawInteriorEdges = 1;
|
|
toDrawArray = true;
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID
|
|
|| aCtx->hasGeometryStage == OpenGl_FeatureNotAvailable
|
|
|| aCtx->caps->usePolygonMode)
|
|
{
|
|
toDrawInteriorEdges = 2;
|
|
if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_EMPTY)
|
|
{
|
|
if (anAspectFace->Aspect()->EdgeLineType() != Aspect_TOL_SOLID)
|
|
{
|
|
toDrawArray = false;
|
|
}
|
|
else
|
|
{
|
|
aCtx->SetPolygonMode (GL_LINE);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (myDrawMode == GL_POINTS)
|
|
{
|
|
if (anAspectMarker->Aspect()->Type() == Aspect_TOM_EMPTY)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (anAspectLine->Aspect()->Type() == Aspect_TOL_EMPTY)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Temporarily disable environment mapping
|
|
aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)());
|
|
}
|
|
|
|
// create VBOs on first render call
|
|
if (!myIsVboInit)
|
|
{
|
|
// compatibility - keep data to draw markers using display lists
|
|
Standard_Boolean toKeepData = Standard_False;
|
|
if (myDrawMode == GL_POINTS)
|
|
{
|
|
const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
|
|
const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
|
|
toKeepData = aSpriteNorm != NULL
|
|
&& aSpriteNorm->IsDisplayList();
|
|
}
|
|
#if defined (GL_ES_VERSION_2_0)
|
|
processIndices (aCtx);
|
|
#endif
|
|
buildVBO (aCtx, toKeepData);
|
|
myIsVboInit = Standard_True;
|
|
}
|
|
else if ((!myAttribs.IsNull()
|
|
&& myAttribs->IsMutable())
|
|
|| (!myIndices.IsNull()
|
|
&& myIndices->IsMutable()))
|
|
{
|
|
updateVBO (aCtx);
|
|
}
|
|
|
|
Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TOSM_UNLIT;
|
|
if (toDrawArray)
|
|
{
|
|
const bool hasColorAttrib = !myVboAttribs.IsNull()
|
|
&& myVboAttribs->HasColorAttribute();
|
|
const bool toHilight = theWorkspace->ToHighlight();
|
|
const bool hasVertColor = hasColorAttrib && !toHilight;
|
|
const bool hasVertNorm = !myVboAttribs.IsNull() && myVboAttribs->HasNormalAttribute();
|
|
switch (myDrawMode)
|
|
{
|
|
case GL_POINTS:
|
|
{
|
|
aShadingModel = aCtx->ShaderManager()->ChooseMarkerShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
|
|
const Handle(OpenGl_TextureSet)& aSpriteNormRes = anAspectMarker->SpriteRes (aCtx);
|
|
const OpenGl_PointSprite* aSpriteNorm = !aSpriteNormRes.IsNull() ? dynamic_cast<const OpenGl_PointSprite*> (aSpriteNormRes->First().get()) : NULL;
|
|
if (aSpriteNorm != NULL
|
|
&& !aSpriteNorm->IsDisplayList())
|
|
{
|
|
const Handle(OpenGl_TextureSet)& aSprite = toHilight && anAspectMarker->SpriteHighlightRes (aCtx)->First()->IsValid()
|
|
? anAspectMarker->SpriteHighlightRes (aCtx)
|
|
: aSpriteNormRes;
|
|
aCtx->BindTextures (aSprite);
|
|
aCtx->ShaderManager()->BindMarkerProgram (aSprite, aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
|
|
}
|
|
else
|
|
{
|
|
aCtx->ShaderManager()->BindMarkerProgram (Handle(OpenGl_TextureSet)(), aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx));
|
|
}
|
|
break;
|
|
}
|
|
case GL_LINES:
|
|
case GL_LINE_STRIP:
|
|
{
|
|
aShadingModel = aCtx->ShaderManager()->ChooseLineShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
|
|
aCtx->ShaderManager()->BindLineProgram (NULL,
|
|
anAspectLine->Aspect()->Type(),
|
|
aShadingModel,
|
|
Graphic3d_AlphaMode_Opaque,
|
|
hasVertColor,
|
|
anAspectLine->ShaderProgramRes (aCtx));
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
aShadingModel = aCtx->ShaderManager()->ChooseFaceShadingModel (anAspectFace->ShadingModel(), hasVertNorm);
|
|
const Handle(OpenGl_TextureSet)& aTextures = aCtx->ActiveTextures();
|
|
const Standard_Boolean toEnableEnvMap = (!aTextures.IsNull() && (aTextures == theWorkspace->EnvironmentTexture()));
|
|
aCtx->ShaderManager()->BindFaceProgram (aTextures,
|
|
aShadingModel,
|
|
aCtx->ShaderManager()->MaterialState().HasAlphaCutoff() ? Graphic3d_AlphaMode_Mask : Graphic3d_AlphaMode_Opaque,
|
|
toDrawInteriorEdges == 1 ? anAspectFace->Aspect()->InteriorStyle() : Aspect_IS_SOLID,
|
|
hasVertColor,
|
|
toEnableEnvMap,
|
|
toDrawInteriorEdges == 1,
|
|
anAspectFace->ShaderProgramRes (aCtx));
|
|
if (toDrawInteriorEdges == 1)
|
|
{
|
|
aCtx->ShaderManager()->PushInteriorState (aCtx->ActiveProgram(), anAspectFace->Aspect());
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
// manage FFP lighting
|
|
if (aCtx->ActiveProgram().IsNull()
|
|
&& aCtx->core11 != NULL)
|
|
{
|
|
if (aShadingModel == Graphic3d_TOSM_UNLIT)
|
|
{
|
|
glDisable (GL_LIGHTING);
|
|
}
|
|
else
|
|
{
|
|
glEnable (GL_LIGHTING);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!aCtx->ActiveTextures().IsNull()
|
|
&& !aCtx->ActiveTextures()->IsEmpty()
|
|
&& !aCtx->ActiveTextures()->First().IsNull()
|
|
&& myDrawMode != GL_POINTS) // transformation is not supported within point sprites
|
|
{
|
|
aCtx->SetTextureMatrix (aCtx->ActiveTextures()->First()->Sampler()->Parameters());
|
|
}
|
|
|
|
const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE
|
|
? myBounds->Colors
|
|
: NULL;
|
|
if (!myIsFillType)
|
|
{
|
|
const OpenGl_Vec4& aLineColor = myDrawMode == GL_POINTS ? theWorkspace->MarkerColor() : theWorkspace->LineColor();
|
|
aCtx->SetColor4fv (aLineColor);
|
|
if (myDrawMode == GL_LINES
|
|
|| myDrawMode == GL_LINE_STRIP)
|
|
{
|
|
aCtx->SetTypeOfLine (anAspectLine->Aspect()->Type());
|
|
aCtx->SetLineWidth (anAspectLine->Aspect()->Width());
|
|
}
|
|
|
|
drawArray (theWorkspace, aFaceColors, hasColorAttrib);
|
|
aCtx->BindTextures (aTextureBack);
|
|
return;
|
|
}
|
|
|
|
const OpenGl_Vec4& anInteriorColor = theWorkspace->InteriorColor();
|
|
aCtx->SetColor4fv (anInteriorColor);
|
|
drawArray (theWorkspace, aFaceColors, hasColorAttrib);
|
|
|
|
// draw outline - only closed triangulation with defined vertex normals can be drawn in this way
|
|
if (anAspectFace->Aspect()->ToDrawSilhouette()
|
|
&& aCtx->ToCullBackFaces()
|
|
&& aCtx->ShaderManager()->BindOutlineProgram())
|
|
{
|
|
const Graphic3d_Vec2i aViewSize (aCtx->Viewport()[2], aCtx->Viewport()[3]);
|
|
const Standard_Integer aMin = aViewSize.minComp();
|
|
const GLfloat anEdgeWidth = (GLfloat )anAspectFace->Aspect()->EdgeWidth() * aCtx->LineWidthScale() / (GLfloat )aMin;
|
|
const GLfloat anOrthoScale = theWorkspace->View()->Camera()->IsOrthographic() ? (GLfloat )theWorkspace->View()->Camera()->Scale() : -1.0f;
|
|
|
|
const Handle(OpenGl_ShaderProgram)& anOutlineProgram = aCtx->ActiveProgram();
|
|
anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_SILHOUETTE_THICKNESS), anEdgeWidth);
|
|
anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_ORTHO_SCALE), anOrthoScale);
|
|
aCtx->SetColor4fv (anAspectFace->Aspect()->EdgeColorRGBA());
|
|
|
|
aCtx->core11fwd->glCullFace (GL_FRONT);
|
|
drawArray (theWorkspace, NULL, false);
|
|
|
|
aCtx->core11fwd->glCullFace (GL_BACK);
|
|
}
|
|
}
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
// draw triangulation edges using Polygon Mode
|
|
if (toDrawInteriorEdges == 2)
|
|
{
|
|
if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HOLLOW
|
|
&& anAspectFace->Aspect()->EdgeLineType() == Aspect_TOL_SOLID)
|
|
{
|
|
aCtx->SetPolygonMode (GL_FILL);
|
|
}
|
|
else
|
|
{
|
|
const OpenGl_Vec4& anEdgeColor = theWorkspace->EdgeColor();
|
|
drawEdges (anEdgeColor, theWorkspace);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : setDrawMode
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::setDrawMode (const Graphic3d_TypeOfPrimitiveArray theType)
|
|
{
|
|
if (myAttribs.IsNull())
|
|
{
|
|
myDrawMode = DRAW_MODE_NONE;
|
|
myIsFillType = false;
|
|
return;
|
|
}
|
|
|
|
switch (theType)
|
|
{
|
|
case Graphic3d_TOPA_POINTS:
|
|
myDrawMode = GL_POINTS;
|
|
myIsFillType = false;
|
|
break;
|
|
case Graphic3d_TOPA_SEGMENTS:
|
|
myDrawMode = GL_LINES;
|
|
myIsFillType = false;
|
|
break;
|
|
case Graphic3d_TOPA_POLYLINES:
|
|
myDrawMode = GL_LINE_STRIP;
|
|
myIsFillType = false;
|
|
break;
|
|
case Graphic3d_TOPA_TRIANGLES:
|
|
myDrawMode = GL_TRIANGLES;
|
|
myIsFillType = true;
|
|
break;
|
|
case Graphic3d_TOPA_TRIANGLESTRIPS:
|
|
myDrawMode = GL_TRIANGLE_STRIP;
|
|
myIsFillType = true;
|
|
break;
|
|
case Graphic3d_TOPA_TRIANGLEFANS:
|
|
myDrawMode = GL_TRIANGLE_FAN;
|
|
myIsFillType = true;
|
|
break;
|
|
//
|
|
case Graphic3d_TOPA_LINES_ADJACENCY:
|
|
myDrawMode = GL_LINES_ADJACENCY;
|
|
myIsFillType = false;
|
|
break;
|
|
case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
|
|
myDrawMode = GL_LINE_STRIP_ADJACENCY;
|
|
myIsFillType = false;
|
|
break;
|
|
case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
|
|
myDrawMode = GL_TRIANGLES_ADJACENCY;
|
|
myIsFillType = true;
|
|
break;
|
|
case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
|
|
myDrawMode = GL_TRIANGLE_STRIP_ADJACENCY;
|
|
myIsFillType = true;
|
|
break;
|
|
//
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
case Graphic3d_TOPA_QUADRANGLES:
|
|
myDrawMode = GL_QUADS;
|
|
myIsFillType = true;
|
|
break;
|
|
case Graphic3d_TOPA_QUADRANGLESTRIPS:
|
|
myDrawMode = GL_QUAD_STRIP;
|
|
myIsFillType = true;
|
|
break;
|
|
case Graphic3d_TOPA_POLYGONS:
|
|
myDrawMode = GL_POLYGON;
|
|
myIsFillType = true;
|
|
break;
|
|
#else
|
|
case Graphic3d_TOPA_QUADRANGLES:
|
|
case Graphic3d_TOPA_QUADRANGLESTRIPS:
|
|
case Graphic3d_TOPA_POLYGONS:
|
|
#endif
|
|
case Graphic3d_TOPA_UNDEFINED:
|
|
myDrawMode = DRAW_MODE_NONE;
|
|
myIsFillType = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : processIndices
|
|
// purpose :
|
|
// =======================================================================
|
|
Standard_Boolean OpenGl_PrimitiveArray::processIndices (const Handle(OpenGl_Context)& theContext) const
|
|
{
|
|
if (myIndices.IsNull()
|
|
|| myAttribs.IsNull()
|
|
|| theContext->hasUintIndex)
|
|
{
|
|
return Standard_True;
|
|
}
|
|
|
|
if (myAttribs->NbElements > std::numeric_limits<GLushort>::max())
|
|
{
|
|
Handle(Graphic3d_Buffer) anAttribs = new Graphic3d_Buffer (new NCollection_AlignedAllocator (16));
|
|
if (!anAttribs->Init (myIndices->NbElements, myAttribs->AttributesArray(), myAttribs->NbAttributes))
|
|
{
|
|
return Standard_False; // failed to initialize attribute array
|
|
}
|
|
|
|
for (Standard_Integer anIdxIdx = 0; anIdxIdx < myIndices->NbElements; ++anIdxIdx)
|
|
{
|
|
const Standard_Integer anIndex = myIndices->Index (anIdxIdx);
|
|
memcpy (anAttribs->ChangeData() + myAttribs->Stride * anIdxIdx,
|
|
myAttribs->Data() + myAttribs->Stride * anIndex,
|
|
myAttribs->Stride);
|
|
}
|
|
|
|
myIndices.Nullify();
|
|
myAttribs = anAttribs;
|
|
}
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : InitBuffers
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& theContext,
|
|
const Graphic3d_TypeOfPrimitiveArray theType,
|
|
const Handle(Graphic3d_IndexBuffer)& theIndices,
|
|
const Handle(Graphic3d_Buffer)& theAttribs,
|
|
const Handle(Graphic3d_BoundBuffer)& theBounds)
|
|
{
|
|
// Release old graphic resources
|
|
Release (theContext.operator->());
|
|
|
|
myIndices = theIndices;
|
|
myAttribs = theAttribs;
|
|
myBounds = theBounds;
|
|
#if defined(GL_ES_VERSION_2_0)
|
|
processIndices (theContext);
|
|
#endif
|
|
|
|
setDrawMode (theType);
|
|
}
|