1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/MeshVS/MeshVS_NodalColorPrsBuilder.cxx
mzernova b1492cb30f 0022777: Visualization - Unsafe way to get attribute values from MeshVS_Drawer
Set default values for local variables used for storing values that are obtained by MeshVS_Drawer::Get****() methods
2019-09-14 10:49:50 +03:00

836 lines
31 KiB
C++

// Created on: 2003-11-12
// Created by: Alexander SOLOVYOV
// Copyright (c) 2003-2014 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.
#define _POLYGONES_
// if define _POLYGONES_ ColorPrsBuilder use ArrayOfPolygons for drawing faces
#include <Aspect_SequenceOfColor.hxx>
#include <gp_Pnt.hxx>
#include <Graphic3d_ArrayOfPolygons.hxx>
#include <Graphic3d_ArrayOfPolylines.hxx>
#include <Graphic3d_ArrayOfPrimitives.hxx>
#include <Graphic3d_ArrayOfSegments.hxx>
#include <Graphic3d_ArrayOfTriangles.hxx>
#include <Graphic3d_AspectFillArea3d.hxx>
#include <Graphic3d_AspectLine3d.hxx>
#include <Graphic3d_Group.hxx>
#include <Graphic3d_Texture2D.hxx>
#include <Graphic3d_TextureParams.hxx>
#include <Graphic3d_TypeOfTextureMode.hxx>
#include <Image_PixMap.hxx>
#include <MeshVS_Buffer.hxx>
#include <MeshVS_DataSource.hxx>
#include <MeshVS_DisplayModeFlags.hxx>
#include <MeshVS_Drawer.hxx>
#include <MeshVS_DrawerAttribute.hxx>
#include <MeshVS_HArray1OfSequenceOfInteger.hxx>
#include <MeshVS_Mesh.hxx>
#include <MeshVS_MeshPrsBuilder.hxx>
#include <MeshVS_NodalColorPrsBuilder.hxx>
#include <MeshVS_SymmetricPairHasher.hxx>
#include <MeshVS_Tool.hxx>
#include <NCollection_Map.hxx>
#include <NCollection_Vector.hxx>
#include <Prs3d_Drawer.hxx>
#include <Prs3d_LineAspect.hxx>
#include <Prs3d_Presentation.hxx>
#include <Prs3d_Root.hxx>
#include <Prs3d_ShadingAspect.hxx>
#include <PrsMgr_PresentationManager3d.hxx>
#include <Quantity_Array1OfColor.hxx>
#include <Quantity_Color.hxx>
#include <Standard_Type.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TColStd_HPackedMapOfInteger.hxx>
#include <TColStd_ListIteratorOfListOfInteger.hxx>
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
#include <TColStd_SequenceOfInteger.hxx>
IMPLEMENT_STANDARD_RTTIEXT(MeshVS_NodalColorPrsBuilder,MeshVS_PrsBuilder)
/*
Class : MeshVS_ImageTexture2D
Description : Texture for nodal presentation
*/
class MeshVS_ImageTexture2D : public Graphic3d_Texture2D
{
public:
MeshVS_ImageTexture2D (const Handle(Image_PixMap)& theImg) : Graphic3d_Texture2D (theImg, Graphic3d_TOT_2D)
{
myParams->SetModulate (Standard_True);
myParams->SetFilter (Graphic3d_TOTF_BILINEAR);
}
public:
DEFINE_STANDARD_RTTI_INLINE(MeshVS_ImageTexture2D,Graphic3d_Texture2D)
};
DEFINE_STANDARD_HANDLE (MeshVS_ImageTexture2D, Graphic3d_Texture2D)
//================================================================
// Function : getNearestPow2
// Purpose : Returns the nearest power of two greater than the
// argument value
//================================================================
static inline Standard_Integer getNearestPow2( Standard_Integer theValue )
{
// Precaution against overflow
Standard_Integer aHalfMax = IntegerLast() >> 1, aRes = 1;
if ( theValue > aHalfMax ) theValue = aHalfMax;
while ( aRes < theValue ) aRes <<= 1;
return aRes;
}
/*
Class : MeshVS_NodalColorPrsBuilder
Description : This class provides methods to create presentation of
nodes with assigned color (See hxx for more description )
*/
//================================================================
// Function : Constructor MeshVS_NodalColorPrsBuilder
// Purpose :
//================================================================
MeshVS_NodalColorPrsBuilder::MeshVS_NodalColorPrsBuilder ( const Handle(MeshVS_Mesh)& Parent,
const MeshVS_DisplayModeFlags& Flags,
const Handle (MeshVS_DataSource)& DS,
const Standard_Integer Id,
const MeshVS_BuilderPriority& Priority )
: MeshVS_PrsBuilder ( Parent, Flags, DS, Id, Priority ),
myUseTexture( Standard_False ),
myInvalidColor( Quantity_NOC_GRAY )
{
SetExcluding ( Standard_True );
}
//================================================================
// Function : Build
// Purpose :
//================================================================
void MeshVS_NodalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
const TColStd_PackedMapOfInteger& IDs,
TColStd_PackedMapOfInteger& IDsToExclude,
const Standard_Boolean IsElement,
const Standard_Integer DisplayMode) const
{
Handle (MeshVS_DataSource) aSource = GetDataSource();
Handle (MeshVS_Drawer) aDrawer = GetDrawer();
if ( aSource.IsNull() || aDrawer.IsNull() )
return;
Standard_Integer aMaxFaceNodes;
if ( !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, aMaxFaceNodes ) || aMaxFaceNodes <= 0 )
return;
MeshVS_Buffer aCoordsBuf (3*aMaxFaceNodes*sizeof(Standard_Real));
TColStd_Array1OfReal aCoords ( aCoordsBuf, 1, 3 * aMaxFaceNodes );
Standard_Integer NbNodes;
MeshVS_EntityType aType;
if ( !( DisplayMode & GetFlags() ) || !IsElement )
return;
if ( (myUseTexture && ( !myTextureCoords.Extent() || !myTextureColorMap.Length() )) ||
(!myUseTexture && !myNodeColorMap.Extent()) )
return;
// subtract the hidden elements and ids to exclude (to minimize allocated memory)
TColStd_PackedMapOfInteger anIDs;
anIDs.Assign( IDs );
Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
if ( !aHiddenElems.IsNull() )
anIDs.Subtract( aHiddenElems->Map() );
anIDs.Subtract( IDsToExclude );
Standard_Boolean IsReflect = Standard_False, IsMeshSmoothShading = Standard_False;
aDrawer->GetBoolean( MeshVS_DA_ColorReflection, IsReflect );
aDrawer->GetBoolean( MeshVS_DA_SmoothShading, IsMeshSmoothShading );
// Following parameter are used for texture presentation only
int nbColors = 0; // Number of colors from color map
int nbTextureColors = 0; // Number of colors in texture (it will be pow of 2)
if ( myUseTexture )
{
nbColors = myTextureColorMap.Length();
nbTextureColors = getNearestPow2( nbColors );
}
Standard_Integer aSize = anIDs.Extent();
// Calculate maximum possible number of vertices and bounds
Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0;
TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
for( ; it.More(); it.Next() )
{
Standard_Integer aKey = it.Key();
if ( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
MeshVS_MeshPrsBuilder::HowManyPrimitives
( aTopo, Standard_True, Standard_False, NbNodes,
PolygonVerticesFor3D, PolygonBoundsFor3D );
}
// Draw faces with nodal color
// OCC20644 Use "plastic" material as it is "non-physic" and so it is easier to get the required colors
Graphic3d_MaterialAspect aMaterial[2] = { Graphic3d_NOM_PLASTIC, Graphic3d_NOM_PLASTIC };
for (Standard_Integer i = 0; i < 2; ++i)
{
aMaterial[i].SetSpecularColor (Quantity_NOC_BLACK);
aMaterial[i].SetEmissiveColor (Quantity_NOC_BLACK);
if ( !IsReflect )
{
aMaterial[i].SetAmbientColor (Quantity_NOC_BLACK);
aMaterial[i].SetDiffuseColor (Quantity_NOC_BLACK);
}
else{
// OCC20644 Using the material with reflection properties same as in
// ElementalColorPrsBuilder, to get the same colors.
// Additionally, ambient and diffuse coefficients are used below to scale incoming colors,
// to simulate TelUpdateMaterial() function from OpenGl_attri.c.
// This is mandatory, as these "scaled" colors are then passed directly to OpenGL
// as ambient and diffuse colors of the current material using glColorMaterial().
// In ElementalColorPrsBuilder we do not need to do scale the colors, as this
// is done by TelUpdateMaterial().
// 0.5 is used to have the colors in 3D maximally similar to those in the color scale.
// This is possible when the sum of all coefficient is equal to 1.
aMaterial[i].SetAmbientColor (Quantity_Color (Graphic3d_Vec3 (0.5f)));
aMaterial[i].SetDiffuseColor (Quantity_Color (Graphic3d_Vec3 (0.5f)));
}
}
// Create array of polygons for interior presentation of faces and volumes
Handle(Graphic3d_ArrayOfPolygons) aCPolyArr = new Graphic3d_ArrayOfPolygons
( aMaxFaceNodes * aSize + PolygonVerticesFor3D, aSize + PolygonBoundsFor3D,
0, myUseTexture || IsReflect, !myUseTexture, Standard_False, myUseTexture );
Standard_Integer aNbFacePrimitives = 0;
Standard_Integer aNbVolmPrimitives = 0;
Standard_Integer aNbEdgePrimitives = 0;
Standard_Integer aNbLinkPrimitives = 0;
for (it.Reset(); it.More(); it.Next())
{
Standard_Integer aNbNodes = 0;
if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType))
continue;
if (aType == MeshVS_ET_Volume)
{
if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo))
{
for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx)
{
const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx);
aNbEdgePrimitives += aFaceNodes.Length(); // add edge segments
aNbVolmPrimitives += aFaceNodes.Length() - 2; // add volumetric cell triangles
}
}
}
else if (aType == MeshVS_ET_Link)
{
aNbLinkPrimitives += aNbNodes - 1; // add link segments
}
else if (aType == MeshVS_ET_Face)
{
aNbEdgePrimitives += aNbNodes; // add edge segments
aNbFacePrimitives += aNbNodes - 2; // add face triangles
}
}
// Here we do not use indices arrays because they are not effective for some mesh
// drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D
// cell rendering (normal interpolation is not always applicable - flat shading),
// elemental coloring (color interpolation is impossible)
// Create array of polygons for interior presentation of faces and volumes
Handle(Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles
( (aNbFacePrimitives + aNbVolmPrimitives) * 3, 0, myUseTexture || IsReflect, !myUseTexture, myUseTexture );
// Create array of polylines for presentation of edges
Handle(Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments
(aNbEdgePrimitives * 2);
gp_Pnt P, Start;
Standard_Real aMin = gp::Resolution() * gp::Resolution();
gp_Dir aDefNorm( 0., 0., 1. );
// Prepare for scaling the incoming colors
const Standard_Real anColorRatio = !IsReflect ? 0.44f : 0.5f;
for (it.Reset(); it.More(); it.Next())
{
Standard_Integer aKey = it.Key();
if (aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType))
{
TColStd_Array1OfInteger aNodes (1, NbNodes);
if (!aSource->GetNodesByElement (aKey, aNodes, NbNodes))
continue;
Quantity_Color aNColor;
Standard_Boolean isValid = Standard_True;
if (myUseTexture)
{
for (Standard_Integer k = 1; k <= NbNodes && isValid; ++k)
isValid = myTextureCoords.IsBound (aNodes (k));
}
else
{
for (Standard_Integer k = 1; k <= NbNodes && isValid; ++k)
isValid = GetColor (aNodes (k), aNColor);
}
if (!isValid)
continue;
// Preparing normal(s) to show reflections if requested
Handle(TColStd_HArray1OfReal) aNormals;
Standard_Boolean hasNormals =
(IsReflect && aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals));
if (aType == MeshVS_ET_Face)
{
for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx) // triangulate polygon
{
for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle
{
gp_XYZ aPnt (aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
gp_Vec aNorm = aDefNorm;
if (hasNormals)
{
gp_Vec aTestNorm (aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
if (aTestNorm.SquareMagnitude() > aMin)
{
aNorm = gp_Dir (aTestNorm);
}
}
if (myUseTexture)
{
const Standard_Real aTexCoord = myTextureCoords (aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)));
// Transform texture coordinate in accordance with number of colors specified
// by upper level and real size of OpenGL texture. The OpenGL texture has border
// colors interpolated with the colors from the color map, thats why we need to
// shrink texture coordinates around the middle point to exclude areas where the
// map colors are interpolated with the borders color
aFaceTriangles->AddVertex (aPnt, aNorm, gp_Pnt2d (
(aTexCoord * (nbColors - 1.0) + 0.5) / nbTextureColors, aTexCoord < 0 || aTexCoord > 1 ? 0.25 : 0.75));
}
else
{
GetColor (aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)), aNColor);
if (IsReflect)
{
aNColor.SetValues (anColorRatio * aNColor.Red(),
anColorRatio * aNColor.Green(),
anColorRatio * aNColor.Blue(),
Quantity_TOC_RGB);
aFaceTriangles->AddVertex (aPnt, aNorm, aNColor);
}
else
{
aFaceTriangles->AddVertex (aPnt, aNColor);
}
}
}
}
for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx) // border segmentation
{
const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes;
anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
aCoords (3 * aNodeIdx + 2),
aCoords (3 * aNodeIdx + 3));
anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
aCoords (3 * aNextIdx + 2),
aCoords (3 * aNextIdx + 3));
}
// if IsExcludingOn then presentation must not be built by other builders
if (IsExcludingOn())
{
IDsToExclude.Add (aKey);
}
}
else if (aType == MeshVS_ET_Volume)
{
if (!aSource->Get3DGeom (aKey, NbNodes, aTopo))
continue;
AddVolumePrs (aTopo, aNodes, aCoords, aFaceTriangles,
IsReflect, nbColors, nbTextureColors, anColorRatio);
AddVolumePrs (aTopo, aNodes, aCoords, anEdgeSegments,
IsReflect, nbColors, nbTextureColors, anColorRatio);
// if IsExcludingOn then presentation must not be built by other builders
if (IsExcludingOn())
IDsToExclude.Add (aKey);
}
}
} // for ( ...
Handle(Graphic3d_AspectFillArea3d) anAsp;
// Aspect_InteriorStyle aStyle;
// Standard_Integer aStyleInt;
Aspect_TypeOfLine anEdgeType = Aspect_TOL_SOLID;
Standard_Real anEdgeWidth = 1.0;
Quantity_Color anInteriorColor;
Quantity_Color anEdgeColor, aLineColor;
Standard_Boolean aShowEdges = Standard_True;
aDrawer->GetColor ( MeshVS_DA_InteriorColor, anInteriorColor );
aDrawer->GetColor ( MeshVS_DA_EdgeColor, anEdgeColor );
aDrawer->GetColor ( MeshVS_DA_BeamColor, aLineColor );
aDrawer->GetDouble ( MeshVS_DA_EdgeWidth, anEdgeWidth );
aDrawer->GetBoolean( MeshVS_DA_ShowEdges, aShowEdges );
Standard_Integer anEdgeInt = Aspect_TOL_SOLID;
if ( aDrawer->GetInteger ( MeshVS_DA_EdgeType, anEdgeInt ) )
anEdgeType = (Aspect_TypeOfLine) anEdgeInt;
if ( myUseTexture )
{
Handle(Prs3d_Drawer) aPrsDrawer = myParentMesh->Attributes();
if ( aPrsDrawer.IsNull() )
return;
aPrsDrawer->SetShadingAspect( new Prs3d_ShadingAspect() );
anAsp = aPrsDrawer->ShadingAspect()->Aspect();
if ( anAsp.IsNull() )
return;
anAsp->SetFrontMaterial( aMaterial[ 0 ] );
anAsp->SetBackMaterial( aMaterial[ 1 ] );
Handle(Graphic3d_Texture2D) aTexture = CreateTexture();
if ( aTexture.IsNull() )
return;
anAsp->SetTextureMapOn();
anAsp->SetTextureMap( aTexture );
anAsp->SetInteriorColor( Quantity_NOC_WHITE );
}
else
{
// if ( aDrawer->GetInteger ( MeshVS_DA_InteriorStyle, aStyleInt ) )
// aStyle = (Aspect_InteriorStyle)aStyleInt;
anAsp = new Graphic3d_AspectFillArea3d (
Aspect_IS_SOLID, Quantity_NOC_GRAY, anEdgeColor,
anEdgeType, anEdgeWidth, aMaterial[ 0 ], aMaterial[ 1 ] );
}
anAsp->SetDistinguishOff();
anAsp->SetEdgeOff();
Handle(Graphic3d_AspectLine3d) anLAsp =
new Graphic3d_AspectLine3d( anEdgeColor, anEdgeType, anEdgeWidth );
Handle(Graphic3d_Group) aGroup1 = Prs3d_Root::NewGroup (Prs);
Standard_Boolean toSupressBackFaces = Standard_False;
aDrawer->GetBoolean (MeshVS_DA_SupressBackFaces, toSupressBackFaces);
aGroup1->SetClosed (toSupressBackFaces == Standard_True);
aGroup1->SetPrimitivesAspect( anAsp );
aGroup1->AddPrimitiveArray( aFaceTriangles /*aCPolyArr*/ );
//aGroup1->AddPrimitiveArray( aCPolyArr );
if (aShowEdges)
{
Prs3d_Root::NewGroup ( Prs );
Handle(Graphic3d_Group) aGroup2 = Prs3d_Root::CurrentGroup ( Prs );
Handle(Graphic3d_AspectFillArea3d) anAspCopy = new Graphic3d_AspectFillArea3d (*anAsp);
anAspCopy->SetTextureMapOff();
aGroup2->SetPrimitivesAspect( anAspCopy );
aGroup2->SetPrimitivesAspect( anLAsp );
aGroup2->AddPrimitiveArray( anEdgeSegments );
}
}
//================================================================
// Function : AddVolumePrs
// Purpose :
//================================================================
void MeshVS_NodalColorPrsBuilder::AddVolumePrs (const Handle(MeshVS_HArray1OfSequenceOfInteger)& theTopo,
const TColStd_Array1OfInteger& theNodes,
const TColStd_Array1OfReal& theCoords,
const Handle(Graphic3d_ArrayOfPrimitives)& theArray,
const Standard_Boolean theIsShaded,
const Standard_Integer theNbColors,
const Standard_Integer theNbTexColors,
const Standard_Real theColorRatio) const
{
Standard_Integer aLow = theCoords.Lower();
if (theTopo.IsNull() || theArray.IsNull())
return;
Standard_Boolean aIsPolygons = theArray->IsKind (STANDARD_TYPE (Graphic3d_ArrayOfTriangles));
if (aIsPolygons)
{
for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
{
const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
TColStd_Array1OfReal aPolyNodes (0, 3 * aFaceNodes.Length());
for (Standard_Integer aNodeIdx = 0; aNodeIdx < aFaceNodes.Length(); ++aNodeIdx)
{
Standard_Integer anIdx = aFaceNodes.Value (aNodeIdx + 1);
Standard_Real aX = theCoords.Value (aLow + 3 * anIdx + 0);
Standard_Real aY = theCoords.Value (aLow + 3 * anIdx + 1);
Standard_Real aZ = theCoords.Value (aLow + 3 * anIdx + 2);
aPolyNodes.SetValue (3 * aNodeIdx + 1, aX);
aPolyNodes.SetValue (3 * aNodeIdx + 2, aY);
aPolyNodes.SetValue (3 * aNodeIdx + 3, aZ);
}
gp_Vec aNorm (0.0, 0.0, 1.0);
if (theIsShaded)
{
aPolyNodes.SetValue (0, aFaceNodes.Length());
if (!MeshVS_Tool::GetAverageNormal (aPolyNodes, aNorm))
{
aNorm.SetCoord (0.0, 0.0, 1.0);
}
}
for (Standard_Integer aNodeIdx = 0; aNodeIdx < aFaceNodes.Length() - 2; ++aNodeIdx) // triangulate polygon
{
for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx) // generate sub-triangle
{
gp_Pnt aPnt (aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
aPolyNodes.Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
if (myUseTexture)
{
const Standard_Real aTexCoord = myTextureCoords (theNodes (aFaceNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)) + 1));
theArray->AddVertex (aPnt, aNorm, gp_Pnt2d (
(aTexCoord * (theNbColors - 1.0) + 0.5) / theNbTexColors, aTexCoord < 0 || aTexCoord > 1 ? 0.25 : 0.75));
}
else
{
Quantity_Color aNColor;
GetColor (theNodes ((aFaceNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1)) + 1)), aNColor);
if (theIsShaded)
{
aNColor.SetValues (theColorRatio * aNColor.Red(),
theColorRatio * aNColor.Green(),
theColorRatio * aNColor.Blue(),
Quantity_TOC_RGB);
theArray->AddVertex (aPnt, aNorm, aNColor);
}
else
{
theArray->AddVertex (aPnt, aNColor);
}
}
}
}
}
}
else
{
// Find all pairs of nodes (edges) to draw (will be drawn only once)
NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher> aEdgeMap;
for (Standard_Integer aFaceIdx = theTopo->Lower(), topoup = theTopo->Upper(); aFaceIdx <= topoup; ++aFaceIdx)
{
const TColStd_SequenceOfInteger& aFaceNodes = theTopo->Value (aFaceIdx);
for (Standard_Integer aNodeIdx = 0, aNbNodes = aFaceNodes.Length(); aNodeIdx < aNbNodes; ++aNodeIdx)
{
const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes;
aEdgeMap.Add (MeshVS_NodePair (aFaceNodes.Value (aNodeIdx + 1),
aFaceNodes.Value (aNextIdx + 1)));
}
}
// Draw edges
for(NCollection_Map<MeshVS_NodePair, MeshVS_SymmetricPairHasher>::Iterator anIt (aEdgeMap); anIt.More(); anIt.Next())
{
const Standard_Integer anIdx1 = aLow + 3 * anIt.Key().first;
const Standard_Integer anIdx2 = aLow + 3 * anIt.Key().second;
Standard_Real aX[] = { theCoords.Value (anIdx1 + 0), theCoords.Value (anIdx2 + 0) };
Standard_Real aY[] = { theCoords.Value (anIdx1 + 1), theCoords.Value (anIdx2 + 1) };
Standard_Real aZ[] = { theCoords.Value (anIdx1 + 2), theCoords.Value (anIdx2 + 2) };
theArray->AddVertex (aX[0], aY[0], aZ[0]);
theArray->AddVertex (aX[1], aY[1], aZ[1]);
}
}
}
//================================================================
// Function : SetColors
// Purpose :
//================================================================
void MeshVS_NodalColorPrsBuilder::SetColors (
const MeshVS_DataMapOfIntegerColor& theColorMap )
{
myNodeColorMap = theColorMap;
}
//================================================================
// Function : GetColors
// Purpose :
//================================================================
const MeshVS_DataMapOfIntegerColor& MeshVS_NodalColorPrsBuilder::GetColors() const
{
return myNodeColorMap;
}
//================================================================
// Function : HasColors
// Purpose :
//================================================================
Standard_Boolean MeshVS_NodalColorPrsBuilder::HasColors () const
{
return ( myNodeColorMap.Extent() >0 );
}
//================================================================
// Function : GetColor
// Purpose :
//================================================================
Standard_Boolean MeshVS_NodalColorPrsBuilder::GetColor ( const Standard_Integer ID,
Quantity_Color& theColor ) const
{
Standard_Boolean aRes = myNodeColorMap.IsBound ( ID );
if ( aRes )
theColor = myNodeColorMap.Find ( ID );
return aRes;
}
//================================================================
// Function : SetColor
// Purpose :
//================================================================
void MeshVS_NodalColorPrsBuilder::SetColor ( const Standard_Integer theID,
const Quantity_Color& theCol )
{
Standard_Boolean aRes = myNodeColorMap.IsBound ( theID );
if ( aRes )
myNodeColorMap.ChangeFind ( theID ) = theCol;
else
myNodeColorMap.Bind ( theID, theCol );
}
//================================================================
// Function : UseTexture
// Purpose : Specify whether texture must be used to build presentation
//================================================================
void MeshVS_NodalColorPrsBuilder::UseTexture( const Standard_Boolean theToUse )
{
myUseTexture = theToUse;
if ( myUseTexture )
myNodeColorMap.Clear();
else
myTextureColorMap.Clear();
}
//================================================================
// Function : IsUseTexture
// Purpose : Verify whether texture is used to build presentation
//================================================================
Standard_Boolean MeshVS_NodalColorPrsBuilder::IsUseTexture() const
{
return myUseTexture;
}
//================================================================
// Function : SetColorMap
// Purpose : Set colors to be used for texrture presentation.
// Generate texture in accordance with given parameters
//================================================================
void MeshVS_NodalColorPrsBuilder::SetColorMap( const Aspect_SequenceOfColor& theColors )
{
myTextureColorMap = theColors;
}
//================================================================
// Function : GetColorMap
// Purpose : Return colors used for texrture presentation
//================================================================
const Aspect_SequenceOfColor& MeshVS_NodalColorPrsBuilder::GetColorMap() const
{
return myTextureColorMap;
}
//================================================================
// Function : SetInvalidColor
// Purpose : Set color representing invalid texture coordinate
// (laying outside range [0, 1])
//================================================================
void MeshVS_NodalColorPrsBuilder::SetInvalidColor(
const Quantity_Color& theInvalidColor )
{
myInvalidColor = theInvalidColor;
}
//================================================================
// Function : GetInvalidColor
// Purpose : Return color representing invalid texture coordinate
// (laying outside range [0, 1])
//================================================================
Quantity_Color MeshVS_NodalColorPrsBuilder::GetInvalidColor() const
{
return myInvalidColor;
}
//================================================================
// Function : SetTextureCoords
// Purpose : Specify correspondence between node IDs and texture
// coordinates (range [0, 1])
//================================================================
void MeshVS_NodalColorPrsBuilder::SetTextureCoords (
const TColStd_DataMapOfIntegerReal& theMap )
{
myTextureCoords = theMap;
}
//================================================================
// Function : GetTextureCoords
// Purpose : Get correspondence between node IDs and texture
// coordinates (range [0, 1])
//================================================================
const TColStd_DataMapOfIntegerReal& MeshVS_NodalColorPrsBuilder::GetTextureCoords() const
{
return myTextureCoords;
}
//================================================================
// Function : SetTextureCoord
// Purpose : Specify correspondence between node ID and texture
// coordinate (range [0, 1])
//================================================================
void MeshVS_NodalColorPrsBuilder::SetTextureCoord( const Standard_Integer theID,
const Standard_Real theCoord )
{
myTextureCoords.Bind( theID, theCoord );
}
//================================================================
// Function : GetTextureCoord
// Purpose : Return correspondence between node IDs and texture
// coordinate (range [0, 1])
//================================================================
Standard_Real MeshVS_NodalColorPrsBuilder::GetTextureCoord( const Standard_Integer theID )
{
return myTextureCoords.IsBound( theID ) ? myTextureCoords( theID ) : -1;
}
//================================================================
// Function : CreateTexture
// Purpose : Create texture in accordance with myTextureColorMap
//================================================================
Handle(Graphic3d_Texture2D) MeshVS_NodalColorPrsBuilder::CreateTexture() const
{
const Standard_Integer aColorsNb = myTextureColorMap.Length();
if (aColorsNb == 0)
{
return NULL;
}
// create and fill image with colors
Handle(Image_PixMap) anImage = new Image_PixMap();
if (!anImage->InitTrash (Image_Format_RGBA, Standard_Size(getNearestPow2 (aColorsNb)), 2))
{
return NULL;
}
anImage->SetTopDown (false);
for (Standard_Size aCol = 0; aCol < Standard_Size(aColorsNb); ++aCol)
{
const Quantity_Color& aSrcColor = myTextureColorMap.Value (Standard_Integer(aCol) + 1);
Image_ColorRGBA& aColor = anImage->ChangeValue<Image_ColorRGBA> (0, aCol);
aColor.r() = Standard_Byte(255.0 * aSrcColor.Red());
aColor.g() = Standard_Byte(255.0 * aSrcColor.Green());
aColor.b() = Standard_Byte(255.0 * aSrcColor.Blue());
aColor.a() = 0xFF;
}
// fill padding bytes
const Quantity_Color& aLastColorSrc = myTextureColorMap.Last();
const Image_ColorRGBA aLastColor =
{{
Standard_Byte(255.0 * aLastColorSrc.Red()),
Standard_Byte(255.0 * aLastColorSrc.Green()),
Standard_Byte(255.0 * aLastColorSrc.Blue()),
0xFF
}};
// fill second row
for (Standard_Size aCol = (Standard_Size )aColorsNb; aCol < anImage->SizeX(); ++aCol)
{
anImage->ChangeValue<Image_ColorRGBA> (0, aCol) = aLastColor;
}
const Image_ColorRGBA anInvalidColor =
{{
Standard_Byte(255.0 * myInvalidColor.Red()),
Standard_Byte(255.0 * myInvalidColor.Green()),
Standard_Byte(255.0 * myInvalidColor.Blue()),
0xFF
}};
for (Standard_Size aCol = 0; aCol < anImage->SizeX(); ++aCol)
{
anImage->ChangeValue<Image_ColorRGBA> (1, aCol) = anInvalidColor;
}
// create texture
return new MeshVS_ImageTexture2D (anImage);
}