1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/OpenGl/OpenGl_AspectFace.cxx

495 lines
19 KiB
C++

// Created on: 2011-07-13
// Created by: Sergey ZERCHANINOV
// Copyright (c) 2011-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#include <Aspect_PolygonOffsetMode.hxx>
#include <NCollection_Vec3.hxx>
#include <OpenGl_AspectFace.hxx>
#include <OpenGl_Context.hxx>
#include <OpenGl_ShaderManager.hxx>
#include <OpenGl_ShaderProgram.hxx>
#include <OpenGl_Texture.hxx>
#include <OpenGl_Workspace.hxx>
#include <Graphic3d_CGroup.hxx>
#include <Graphic3d_ShaderProgram.hxx>
#include <Graphic3d_TextureMap.hxx>
#include <Graphic3d_TypeOfReflection.hxx>
#include <Graphic3d_MaterialAspect.hxx>
namespace
{
static OPENGL_SURF_PROP THE_DEFAULT_MATERIAL =
{
0.2F, 0.8F, 0.1F, 0.0F, // amb, diff, spec, emsv
1.0F, 10.0F, 0.0F, // trans, shine, env_reflexion
0, // isphysic
(OPENGL_AMBIENT_MASK | OPENGL_DIFFUSE_MASK | OPENGL_SPECULAR_MASK), // color_mask
{{ 1.0F, 1.0F, 1.0F, 1.0F }}, // ambient color
{{ 1.0F, 1.0F, 1.0F, 1.0F }}, // diffuse color
{{ 1.0F, 1.0F, 1.0F, 1.0F }}, // specular color
{{ 1.0F, 1.0F, 1.0F, 1.0F }}, // emissive color
{{ 1.0F, 1.0F, 1.0F, 1.0F }} // material color
};
static TEL_POFFSET_PARAM THE_DEFAULT_POFFSET = { Aspect_POM_Fill, 1.0F, 0.0F };
static const TCollection_AsciiString THE_EMPTY_KEY;
};
// =======================================================================
// function : convertMaterial
// purpose :
// =======================================================================
void OpenGl_AspectFace::convertMaterial (const CALL_DEF_MATERIAL& theMat,
OPENGL_SURF_PROP& theSurf)
{
theSurf.amb = theMat.IsAmbient ? theMat.Ambient : 0.0f;
theSurf.diff = theMat.IsDiffuse ? theMat.Diffuse : 0.0f;
theSurf.spec = theMat.IsSpecular ? theMat.Specular : 0.0f;
theSurf.emsv = theMat.IsEmission ? theMat.Emission : 0.0f;
theSurf.isphysic = theMat.IsPhysic ? 1 : 0; // type of material
// color of material
theSurf.color_mask = 0;
if (theMat.IsAmbient)
{
theSurf.color_mask |= OPENGL_AMBIENT_MASK;
}
if (theMat.IsDiffuse)
{
theSurf.color_mask |= OPENGL_DIFFUSE_MASK;
}
if (theMat.IsSpecular)
{
theSurf.color_mask |= OPENGL_SPECULAR_MASK;
}
if (theMat.IsEmission)
{
theSurf.color_mask |= OPENGL_EMISSIVE_MASK;
}
// ambient color
theSurf.ambcol.rgb[0] = theMat.ColorAmb.r;
theSurf.ambcol.rgb[1] = theMat.ColorAmb.g;
theSurf.ambcol.rgb[2] = theMat.ColorAmb.b;
theSurf.ambcol.rgb[3] = 1.0f;
// diffuse color
theSurf.difcol.rgb[0] = theMat.ColorDif.r;
theSurf.difcol.rgb[1] = theMat.ColorDif.g;
theSurf.difcol.rgb[2] = theMat.ColorDif.b;
theSurf.difcol.rgb[3] = 1.0f;
// specular color
theSurf.speccol.rgb[0] = theMat.ColorSpec.r;
theSurf.speccol.rgb[1] = theMat.ColorSpec.g;
theSurf.speccol.rgb[2] = theMat.ColorSpec.b;
theSurf.speccol.rgb[3] = 1.0f;
// emission color
theSurf.emscol.rgb[0] = theMat.ColorEms.r;
theSurf.emscol.rgb[1] = theMat.ColorEms.g;
theSurf.emscol.rgb[2] = theMat.ColorEms.b;
theSurf.emscol.rgb[3] = 1.0f;
theSurf.shine = 128.0f * float(theMat.Shininess);
theSurf.env_reflexion = theMat.EnvReflexion;
// trans = 0. => opaque
// trans = 1. => transparent
// in OpenGl it is opposite.
theSurf.trans = 1.0f - theMat.Transparency;
}
// =======================================================================
// function : OpenGl_AspectFace
// purpose :
// =======================================================================
OpenGl_AspectFace::OpenGl_AspectFace()
: myInteriorStyle (Aspect_IS_SOLID),
myEdge (TOff),
myHatch (TEL_HS_SOLID),
myDistinguishingMode (TOff),
myCullingMode (TelCullNone),
myIntFront (THE_DEFAULT_MATERIAL),
myIntBack (THE_DEFAULT_MATERIAL),
myPolygonOffset (THE_DEFAULT_POFFSET),
myDoTextureMap (false)
{}
// =======================================================================
// function : SetAspect
// purpose :
// =======================================================================
void OpenGl_AspectFace::SetAspect (const CALL_DEF_CONTEXTFILLAREA& theAspect)
{
myInteriorStyle = (Aspect_InteriorStyle )theAspect.Style;
myEdge = theAspect.Edge ? TOn : TOff;
//TelInteriorStyleIndex
switch (theAspect.Hatch)
{
case 0: /* Aspect_HS_HORIZONTAL */
myHatch = TEL_HS_HORIZONTAL;
break;
case 1: /* Aspect_HS_HORIZONTAL_WIDE */
myHatch = TEL_HS_HORIZONTAL_SPARSE;
break;
case 2: /* Aspect_HS_VERTICAL */
myHatch = TEL_HS_VERTICAL;
break;
case 3: /* Aspect_HS_VERTICAL_WIDE */
myHatch = TEL_HS_VERTICAL_SPARSE;
break;
case 4: /* Aspect_HS_DIAGONAL_45 */
myHatch = TEL_HS_DIAG_45;
break;
case 5: /* Aspect_HS_DIAGONAL_45_WIDE */
myHatch = TEL_HS_DIAG_45_SPARSE;
break;
case 6: /* Aspect_HS_DIAGONAL_135 */
myHatch = TEL_HS_DIAG_135;
break;
case 7: /* Aspect_HS_DIAGONAL_135_WIDE */
myHatch = TEL_HS_DIAG_135_SPARSE;
break;
case 8: /* Aspect_HS_GRID */
myHatch = TEL_HS_GRID;
break;
case 9: /* Aspect_HS_GRID_WIDE */
myHatch = TEL_HS_GRID_SPARSE;
break;
case 10: /* Aspect_HS_GRID_DIAGONAL */
myHatch = TEL_HS_CROSS;
break;
case 11: /* Aspect_HS_GRID_DIAGONAL_WIDE */
myHatch = TEL_HS_CROSS_SPARSE;
break;
default:
myHatch = 0;
break;
}
myDistinguishingMode = theAspect.Distinguish ? TOn : TOff;
myCullingMode = theAspect.BackFace ? TelCullBack : TelCullNone;
convertMaterial (theAspect.Front, myIntFront);
convertMaterial (theAspect.Back, myIntBack);
//TelInteriorColour
myIntFront.matcol.rgb[0] = (float )theAspect.IntColor.r;
myIntFront.matcol.rgb[1] = (float )theAspect.IntColor.g;
myIntFront.matcol.rgb[2] = (float )theAspect.IntColor.b;
myIntFront.matcol.rgb[3] = 1.0f;
//TelBackInteriorColour
myIntBack.matcol.rgb[0] = (float )theAspect.BackIntColor.r;
myIntBack.matcol.rgb[1] = (float )theAspect.BackIntColor.g;
myIntBack.matcol.rgb[2] = (float )theAspect.BackIntColor.b;
myIntBack.matcol.rgb[3] = 1.0f;
//TelPolygonOffset
myPolygonOffset.mode = (Aspect_PolygonOffsetMode )theAspect.PolygonOffsetMode;
myPolygonOffset.factor = theAspect.PolygonOffsetFactor;
myPolygonOffset.units = theAspect.PolygonOffsetUnits;
CALL_DEF_CONTEXTLINE anEdgeAspect;
anEdgeAspect.Color.r = (float )theAspect.EdgeColor.r;
anEdgeAspect.Color.g = (float )theAspect.EdgeColor.g;
anEdgeAspect.Color.b = (float )theAspect.EdgeColor.b;
anEdgeAspect.LineType = (Aspect_TypeOfLine )theAspect.LineType;
anEdgeAspect.Width = (float )theAspect.Width;
myAspectEdge.SetAspect (anEdgeAspect);
myDoTextureMap = (theAspect.Texture.doTextureMap != 0);
// update texture binding
myTexture = theAspect.Texture.TextureMap;
const TCollection_AsciiString& aTextureKey = myTexture.IsNull() ? THE_EMPTY_KEY : myTexture->GetId();
if (aTextureKey.IsEmpty() || myResources.TextureId != aTextureKey)
{
myResources.ResetTexture();
}
// update shader program binding
myShaderProgram = theAspect.ShaderProgram;
const TCollection_AsciiString& aShaderKey = myShaderProgram.IsNull() ? THE_EMPTY_KEY : myShaderProgram->GetId();
if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey)
{
myResources.ResetShader();
}
}
// =======================================================================
// function : SetAspect
// purpose :
// =======================================================================
void OpenGl_AspectFace::SetAspect (const Handle(Graphic3d_AspectFillArea3d)& theAspect)
{
CALL_DEF_CONTEXTFILLAREA aFaceContext;
Standard_Real aWidth;
Quantity_Color aBackIntColor;
Quantity_Color aEdgeColor;
Aspect_TypeOfLine aLType;
Quantity_Color aIntColor;
Aspect_InteriorStyle aIntStyle;
NCollection_Vec3<Standard_Real> aColor;
theAspect->Values (aIntStyle, aIntColor, aBackIntColor, aEdgeColor, aLType, aWidth);
aIntColor.Values (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
aFaceContext.Style = int (aIntStyle);
aFaceContext.IntColor.r = float (aColor.r());
aFaceContext.IntColor.g = float (aColor.g());
aFaceContext.IntColor.b = float (aColor.b());
if (theAspect->Distinguish())
{
aBackIntColor.Values (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
}
aFaceContext.BackIntColor.r = float (aColor.r());
aFaceContext.BackIntColor.g = float (aColor.g());
aFaceContext.BackIntColor.b = float (aColor.b());
aFaceContext.Edge = theAspect->Edge () ? 1:0;
aEdgeColor.Values (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
aFaceContext.EdgeColor.r = float (aColor.r());
aFaceContext.EdgeColor.g = float (aColor.g());
aFaceContext.EdgeColor.b = float (aColor.b());
aFaceContext.LineType = int (aLType);
aFaceContext.Width = float (aWidth);
aFaceContext.Hatch = int (theAspect->HatchStyle ());
aFaceContext.Distinguish = theAspect->Distinguish () ? 1:0;
aFaceContext.BackFace = theAspect->BackFace () ? 1:0;
aFaceContext.Back.Shininess = float ((theAspect->BackMaterial ()).Shininess ());
aFaceContext.Back.Ambient = float ((theAspect->BackMaterial ()).Ambient ());
aFaceContext.Back.Diffuse = float ((theAspect->BackMaterial ()).Diffuse ());
aFaceContext.Back.Specular = float ((theAspect->BackMaterial ()).Specular ());
aFaceContext.Back.Transparency = float ((theAspect->BackMaterial ()).Transparency ());
aFaceContext.Back.Emission = float ((theAspect->BackMaterial ()).Emissive ());
// Reflection mode
aFaceContext.Back.IsAmbient = ((theAspect->BackMaterial ()).ReflectionMode (Graphic3d_TOR_AMBIENT) ? 1 : 0 );
aFaceContext.Back.IsDiffuse = ((theAspect->BackMaterial ()).ReflectionMode (Graphic3d_TOR_DIFFUSE) ? 1 : 0 );
aFaceContext.Back.IsSpecular = ((theAspect->BackMaterial ()).ReflectionMode (Graphic3d_TOR_SPECULAR) ? 1 : 0 );
aFaceContext.Back.IsEmission = ((theAspect->BackMaterial ()).ReflectionMode (Graphic3d_TOR_EMISSION) ? 1 : 0 );
// Material type
const Graphic3d_MaterialAspect aBackMat = theAspect->BackMaterial ();
Standard_Boolean isBackPhys = aBackMat.MaterialType (Graphic3d_MATERIAL_PHYSIC);
aFaceContext.Back.IsPhysic = (isBackPhys ? 1 : 0 );
// Specular Color
aFaceContext.Back.ColorSpec.r = float (((theAspect->BackMaterial ()).SpecularColor ()).Red ());
aFaceContext.Back.ColorSpec.g = float (((theAspect->BackMaterial ()).SpecularColor ()).Green ());
aFaceContext.Back.ColorSpec.b = float (((theAspect->BackMaterial ()).SpecularColor ()).Blue ());
// Ambient color
aFaceContext.Back.ColorAmb.r = float (((theAspect->BackMaterial ()).AmbientColor ()).Red ());
aFaceContext.Back.ColorAmb.g = float (((theAspect->BackMaterial ()).AmbientColor ()).Green ());
aFaceContext.Back.ColorAmb.b = float (((theAspect->BackMaterial ()).AmbientColor ()).Blue ());
// Diffuse color
aFaceContext.Back.ColorDif.r = float (((theAspect->BackMaterial ()).DiffuseColor ()).Red ());
aFaceContext.Back.ColorDif.g = float (((theAspect->BackMaterial ()).DiffuseColor ()).Green ());
aFaceContext.Back.ColorDif.b = float (((theAspect->BackMaterial ()).DiffuseColor ()).Blue ());
// Emissive color
aFaceContext.Back.ColorEms.r = float (((theAspect->BackMaterial ()).EmissiveColor ()).Red ());
aFaceContext.Back.ColorEms.g = float (((theAspect->BackMaterial ()).EmissiveColor ()).Green ());
aFaceContext.Back.ColorEms.b = float (((theAspect->BackMaterial ()).EmissiveColor ()).Blue ());
aFaceContext.Back.EnvReflexion = float ((theAspect->BackMaterial ()).EnvReflexion());
aFaceContext.Front.Shininess = float ((theAspect->FrontMaterial ()).Shininess ());
aFaceContext.Front.Ambient = float ((theAspect->FrontMaterial ()).Ambient ());
aFaceContext.Front.Diffuse = float ((theAspect->FrontMaterial ()).Diffuse ());
aFaceContext.Front.Specular = float ((theAspect->FrontMaterial ()).Specular ());
aFaceContext.Front.Transparency = float ((theAspect->FrontMaterial ()).Transparency ());
aFaceContext.Front.Emission = float ((theAspect->FrontMaterial ()).Emissive ());
// Reflection mode
aFaceContext.Front.IsAmbient = ((theAspect->FrontMaterial ()).ReflectionMode (Graphic3d_TOR_AMBIENT) ? 1 : 0);
aFaceContext.Front.IsDiffuse = ((theAspect->FrontMaterial ()).ReflectionMode (Graphic3d_TOR_DIFFUSE) ? 1 : 0);
aFaceContext.Front.IsSpecular = ((theAspect->FrontMaterial ()).ReflectionMode (Graphic3d_TOR_SPECULAR) ? 1 : 0);
aFaceContext.Front.IsEmission = ((theAspect->FrontMaterial ()).ReflectionMode (Graphic3d_TOR_EMISSION) ? 1 : 0);
// Material type
const Graphic3d_MaterialAspect aFrontMat = theAspect->FrontMaterial ();
Standard_Boolean isFrontPhys = aFrontMat.MaterialType (Graphic3d_MATERIAL_PHYSIC);
aFaceContext.Front.IsPhysic = (isFrontPhys ? 1 : 0 );
// Specular Color
aFaceContext.Front.ColorSpec.r = float (((theAspect->FrontMaterial ()).SpecularColor ()).Red ());
aFaceContext.Front.ColorSpec.g = float (((theAspect->FrontMaterial ()).SpecularColor ()).Green ());
aFaceContext.Front.ColorSpec.b = float (((theAspect->FrontMaterial ()).SpecularColor ()).Blue ());
// Ambient color
aFaceContext.Front.ColorAmb.r = float (((theAspect->FrontMaterial ()).AmbientColor ()).Red ());
aFaceContext.Front.ColorAmb.g = float (((theAspect->FrontMaterial ()).AmbientColor ()).Green ());
aFaceContext.Front.ColorAmb.b = float (((theAspect->FrontMaterial ()).AmbientColor ()).Blue ());
// Diffuse color
aFaceContext.Front.ColorDif.r = float (((theAspect->FrontMaterial ()).DiffuseColor ()).Red ());
aFaceContext.Front.ColorDif.g = float (((theAspect->FrontMaterial ()).DiffuseColor ()).Green ());
aFaceContext.Front.ColorDif.b = float (((theAspect->FrontMaterial ()).DiffuseColor ()).Blue ());
// Emissive color
aFaceContext.Front.ColorEms.r = float (((theAspect->FrontMaterial ()).EmissiveColor ()).Red ());
aFaceContext.Front.ColorEms.g = float (((theAspect->FrontMaterial ()).EmissiveColor ()).Green ());
aFaceContext.Front.ColorEms.b = float (((theAspect->FrontMaterial ()).EmissiveColor ()).Blue ());
aFaceContext.Front.EnvReflexion = float ((theAspect->FrontMaterial ()).EnvReflexion());
aFaceContext.IsDef = 1;
aFaceContext.Texture.TextureMap = theAspect->TextureMap();
aFaceContext.Texture.doTextureMap = theAspect->TextureMapState() ? 1 : 0;
Standard_Integer aPolyMode;
Standard_ShortReal aPolyFactor, aPolyUnits;
theAspect->PolygonOffsets (aPolyMode, aPolyFactor, aPolyUnits);
aFaceContext.PolygonOffsetMode = aPolyMode;
aFaceContext.PolygonOffsetFactor = (Standard_ShortReal)aPolyFactor;
aFaceContext.PolygonOffsetUnits = (Standard_ShortReal)aPolyUnits;
aFaceContext.ShaderProgram = theAspect->ShaderProgram();
SetAspect (aFaceContext);
}
// =======================================================================
// function : Render
// purpose :
// =======================================================================
void OpenGl_AspectFace::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
{
theWorkspace->SetAspectFace (this);
}
// =======================================================================
// function : Release
// purpose :
// =======================================================================
void OpenGl_AspectFace::Release (const Handle(OpenGl_Context)& theContext)
{
if (!myResources.Texture.IsNull())
{
if (!theContext.IsNull())
{
if (myResources.TextureId.IsEmpty())
{
theContext->DelayedRelease (myResources.Texture);
}
else
{
myResources.Texture.Nullify(); // we need nullify all handles before ReleaseResource() call
theContext->ReleaseResource (myResources.TextureId);
}
}
myResources.Texture.Nullify();
}
myResources.TextureId.Clear();
myResources.ResetTexture();
if (!myResources.ShaderProgram.IsNull()
&& !theContext.IsNull())
{
theContext->ShaderManager()->Unregister (myResources.ShaderProgramId,
myResources.ShaderProgram);
}
myResources.ShaderProgramId.Clear();
myResources.ResetShader();
}
// =======================================================================
// function : BuildTexture
// purpose :
// =======================================================================
void OpenGl_AspectFace::Resources::BuildTexture (const Handle(OpenGl_Workspace)& theWS,
const Handle(Graphic3d_TextureMap)& theTexture)
{
const Handle(OpenGl_Context)& aContext = theWS->GetGlContext();
// release old texture resource
if (!Texture.IsNull())
{
if (TextureId.IsEmpty())
{
aContext->DelayedRelease (Texture);
Texture.Nullify();
}
else
{
Texture.Nullify(); // we need nullify all handles before ReleaseResource() call
aContext->ReleaseResource (TextureId);
}
}
TextureId = theTexture.IsNull() ? THE_EMPTY_KEY : theTexture->GetId();
if (!theTexture.IsNull())
{
if (TextureId.IsEmpty() || !aContext->GetResource<Handle(OpenGl_Texture)> (TextureId, Texture))
{
Texture = new OpenGl_Texture (theTexture->GetParams());
Handle(Image_PixMap) anImage = theTexture->GetImage();
if (!anImage.IsNull())
{
Texture->Init (aContext, *anImage.operator->(), theTexture->Type());
}
if (!TextureId.IsEmpty())
{
aContext->ShareResource (TextureId, Texture);
}
}
}
}
// =======================================================================
// function : BuildShader
// purpose :
// =======================================================================
void OpenGl_AspectFace::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
const Handle(Graphic3d_ShaderProgram)& theShader)
{
const Handle(OpenGl_Context)& aContext = theWS->GetGlContext();
if (!aContext->IsGlGreaterEqual (2, 0))
{
return;
}
// release old shader program resources
if (!ShaderProgram.IsNull())
{
aContext->ShaderManager()->Unregister (ShaderProgramId, ShaderProgram);
}
if (theShader.IsNull())
{
return;
}
aContext->ShaderManager()->Create (theShader, ShaderProgramId, ShaderProgram);
}