0024023: Revamp the OCCT Handle -- ambiguity
[occt.git] / src / MeshVS / MeshVS_ElementalColorPrsBuilder.cxx
CommitLineData
b311480e 1// Created on: 2003-11-12
2// Created by: Alexander SOLOVYOV
973c2be1 3// Copyright (c) 2003-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
7fd59977 16#include <MeshVS_ElementalColorPrsBuilder.ixx>
17
18#include <Graphic3d_AspectFillArea3d.hxx>
19#include <Graphic3d_AspectLine3d.hxx>
20#include <Graphic3d_ArrayOfPolygons.hxx>
21#include <Graphic3d_ArrayOfPolylines.hxx>
37ac4a67 22#include <Graphic3d_ArrayOfSegments.hxx>
23#include <Graphic3d_ArrayOfTriangles.hxx>
7fd59977 24#include <Graphic3d_Group.hxx>
7fd59977 25
26#include <Prs3d_ShadingAspect.hxx>
27#include <Prs3d_Root.hxx>
28#include <Prs3d_LineAspect.hxx>
29
30#include <TColStd_MapOfInteger.hxx>
31#include <TColStd_PackedMapOfInteger.hxx>
32#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
33#include <TColStd_ListIteratorOfListOfInteger.hxx>
34#include <TColStd_Array1OfReal.hxx>
35#include <TColStd_SequenceOfInteger.hxx>
36#include <TColStd_HArray1OfReal.hxx>
37#include <TColStd_HPackedMapOfInteger.hxx>
38
39#include <MeshVS_DisplayModeFlags.hxx>
40#include <MeshVS_DataSource.hxx>
41#include <MeshVS_Mesh.hxx>
42#include <MeshVS_DataMapOfColorMapOfInteger.hxx>
43#include <MeshVS_DataMapOfTwoColorsMapOfInteger.hxx>
44#include <MeshVS_Drawer.hxx>
45#include <MeshVS_DrawerAttribute.hxx>
46#include <MeshVS_DataMapIteratorOfDataMapOfIntegerTwoColors.hxx>
47#include <MeshVS_DataMapIteratorOfDataMapOfIntegerColor.hxx>
48#include <MeshVS_DataMapIteratorOfDataMapOfTwoColorsMapOfInteger.hxx>
49#include <MeshVS_DataMapIteratorOfDataMapOfColorMapOfInteger.hxx>
50#include <MeshVS_MeshPrsBuilder.hxx>
51#include <MeshVS_Buffer.hxx>
37ac4a67 52#include <MeshVS_HArray1OfSequenceOfInteger.hxx>
7fd59977 53
54//================================================================
55// Function : Constructor MeshVS_ElementalColorPrsBuilder
56// Purpose :
57//================================================================
58MeshVS_ElementalColorPrsBuilder::MeshVS_ElementalColorPrsBuilder
59 ( const Handle(MeshVS_Mesh)& Parent,
60 const MeshVS_DisplayModeFlags& Flags,
61 const Handle (MeshVS_DataSource)& DS,
62 const Standard_Integer Id,
63 const MeshVS_BuilderPriority& Priority )
64: MeshVS_PrsBuilder ( Parent, Flags, DS, Id, Priority )
65{
66 SetExcluding ( Standard_True );
67}
68
69//================================================================
70// Function : Build
71// Purpose :
72//================================================================
73void MeshVS_ElementalColorPrsBuilder::Build ( const Handle(Prs3d_Presentation)& Prs,
74 const TColStd_PackedMapOfInteger& IDs,
75 TColStd_PackedMapOfInteger& IDsToExclude,
76 const Standard_Boolean IsElement,
77 const Standard_Integer DisplayMode) const
78{
79 Handle (MeshVS_DataSource) aSource = GetDataSource();
80 Handle (MeshVS_Drawer) aDrawer = GetDrawer();
81
82 if ( aSource.IsNull() || aDrawer.IsNull() )
83 return;
84
85 Standard_Integer aMaxFaceNodes;
86 if ( !aDrawer->GetInteger ( MeshVS_DA_MaxFaceNodes, aMaxFaceNodes ) && aMaxFaceNodes<=0 )
87 return;
88
89 MeshVS_DataMapOfIntegerColor* anElemColorMap = (MeshVS_DataMapOfIntegerColor*) &myElemColorMap1;
90 MeshVS_DataMapOfIntegerTwoColors* anElemTwoColorsMap = (MeshVS_DataMapOfIntegerTwoColors*)&myElemColorMap2;
91
92 MeshVS_DataMapOfColorMapOfInteger aColorsOfElements;
93 MeshVS_DataMapOfTwoColorsMapOfInteger aTwoColorsOfElements;
94
95 MeshVS_Buffer aCoordsBuf (3*aMaxFaceNodes*sizeof(Standard_Real));
96 TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3*aMaxFaceNodes);
97 Standard_Integer NbNodes;
98 MeshVS_EntityType aType;
99
100 if ( !( DisplayMode & GetFlags() ) || !IsElement ||
101 ( myElemColorMap1.IsEmpty() && myElemColorMap2.IsEmpty() ) )
102 return;
103
104 // subtract the hidden elements and ids to exclude (to minimise allocated memory)
105 TColStd_PackedMapOfInteger anIDs;
106 anIDs.Assign( IDs );
107 Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
108 if ( !aHiddenElems.IsNull() )
109 anIDs.Subtract( aHiddenElems->Map() );
110 anIDs.Subtract( IDsToExclude );
111
112 // STEP 0: We looking for two colored elements, who has equal two colors and move it
113 // to map of elements with one assigned color
114 TColStd_ListOfInteger aColorOne;
115 for ( MeshVS_DataMapIteratorOfDataMapOfIntegerTwoColors anIter ( *anElemTwoColorsMap ); anIter.More(); anIter.Next () )
116 {
117 Standard_Integer aKey = anIter.Key ();
118 MeshVS_TwoColors aValue = anIter.Value ();
119 Quantity_Color aCol1, aCol2;
120 ExtractColors ( aValue, aCol1, aCol2 );
121 if ( aCol1 == aCol2 )
122 {
123 aColorOne.Append ( aKey );
124 anElemColorMap->Bind ( aKey, aCol1 );
125 }
126 }
127
128 for ( TColStd_ListIteratorOfListOfInteger aLIter ( aColorOne ); aLIter.More(); aLIter.Next() )
129 anElemTwoColorsMap->UnBind ( aLIter.Value() );
130
131 // The map is to resort itself by colors.
132 // STEP 1: We start sorting elements with one assigned color
133 for ( MeshVS_DataMapIteratorOfDataMapOfIntegerColor anIterM ( *anElemColorMap ); anIterM.More(); anIterM.Next () )
134 {
135 Standard_Integer aMKey = anIterM.Key ();
136 // The ID of current element
137 Standard_Boolean IsExist = Standard_False;
138 for ( MeshVS_DataMapIteratorOfDataMapOfColorMapOfInteger anIterC ( aColorsOfElements );
139 anIterC.More() && !IsExist; anIterC.Next () )
140 if ( anIterC.Key()==anIterM.Value() )
141 {
142 TColStd_MapOfInteger& aChangeValue = (TColStd_MapOfInteger&) anIterC.Value();
143 aChangeValue.Add ( aMKey );
144 IsExist = Standard_True;
145 }
146
147 if ( !IsExist )
148 {
149 TColStd_MapOfInteger aNewMap; aNewMap.Add ( aMKey );
150 aColorsOfElements.Bind ( anIterM.Value(), aNewMap );
151 }
152 }
153
154 // STEP 2: We start sorting elements with two assigned colors
155 for ( MeshVS_DataMapIteratorOfDataMapOfIntegerTwoColors anIterM2 ( *anElemTwoColorsMap ); anIterM2.More();
156 anIterM2.Next () )
157 {
158 Standard_Integer aMKey = anIterM2.Key ();
159 // The ID of current element
160 Standard_Boolean IsExist = Standard_False;
161 for ( MeshVS_DataMapIteratorOfDataMapOfTwoColorsMapOfInteger anIterC2 ( aTwoColorsOfElements );
162 anIterC2.More() && !IsExist; anIterC2.Next () )
163 if ( IsEqual ( anIterC2.Key(), anIterM2.Value() ) )
164 {
165 TColStd_MapOfInteger& aChangeValue = (TColStd_MapOfInteger&) anIterC2.Value();
166 aChangeValue.Add ( aMKey );
167 IsExist = Standard_True;
168 }
169
170 if ( !IsExist )
171 {
172 TColStd_MapOfInteger aNewMap; aNewMap.Add ( aMKey );
173 aTwoColorsOfElements.Bind ( anIterM2.Value(), aNewMap );
174 }
175 }
176
177 //Now we are ready to draw faces with equal colors
7fd59977 178 Aspect_TypeOfLine anEdgeType = Aspect_TOL_SOLID;
179 Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
180 Standard_Integer anEdgeInt, aLineInt;
181 Standard_Real anEdgeWidth, aLineWidth;
182 Quantity_Color anInteriorColor;
183 Quantity_Color anEdgeColor, aLineColor;
184 Standard_Boolean anEdgeOn = Standard_True, IsReflect = Standard_False,
185 IsMeshSmoothShading = Standard_False;
186
187 aDrawer->GetColor ( MeshVS_DA_InteriorColor, anInteriorColor );
188 aDrawer->GetColor ( MeshVS_DA_EdgeColor, anEdgeColor );
189 aDrawer->GetColor ( MeshVS_DA_BeamColor, aLineColor );
190 aDrawer->GetDouble ( MeshVS_DA_EdgeWidth, anEdgeWidth );
191 aDrawer->GetDouble ( MeshVS_DA_BeamWidth, aLineWidth );
192 aDrawer->GetBoolean( MeshVS_DA_ShowEdges, anEdgeOn );
193 aDrawer->GetBoolean( MeshVS_DA_ColorReflection, IsReflect );
194 aDrawer->GetBoolean( MeshVS_DA_SmoothShading, IsMeshSmoothShading );
195
7fd59977 196 if ( aDrawer->GetInteger ( MeshVS_DA_EdgeType, anEdgeInt) )
197 anEdgeType = (Aspect_TypeOfLine) anEdgeInt;
198
199 if ( aDrawer->GetInteger ( MeshVS_DA_BeamType, aLineInt) )
200 aLineType = (Aspect_TypeOfLine) aLineInt;
201
202 Handle( MeshVS_HArray1OfSequenceOfInteger ) aTopo;
203 Standard_Integer PolygonVerticesFor3D = 0, PolygonBoundsFor3D = 0;
204 TColStd_MapIteratorOfPackedMapOfInteger it (anIDs);
205 for( ; it.More(); it.Next() )
206 {
207 Standard_Integer aKey = it.Key();
208 if( aSource->Get3DGeom( aKey, NbNodes, aTopo ) )
209 MeshVS_MeshPrsBuilder::HowManyPrimitives
210 ( aTopo, Standard_True, Standard_False, NbNodes,
211 PolygonVerticesFor3D, PolygonBoundsFor3D );
212 }
213
214 Graphic3d_MaterialAspect aMaterial[2];
37ac4a67 215 for (Standard_Integer i = 0; i < 2; i++)
7fd59977 216 {
217 // OCC20644 "plastic" is most suitable here, as it is "non-physic"
218 // so TelUpdateMaterial() from OpenGl_attri.c uses the interior
219 // color from AspectFillArea3d to calculate all material colors
220 aMaterial[i] = Graphic3d_MaterialAspect ( Graphic3d_NOM_PLASTIC );
221
222 // OCC21720 For single-colored elements turning all material components off is a good idea,
223 // as anyhow the normals are not computed and the lighting will be off,
224 // the element color will be taken from Graphic3d_AspectFillArea3d's interior color,
225 // and there is no need to spend time on updating material properties
226 if ( !IsReflect )
227 {
228 aMaterial[i].SetReflectionModeOff(Graphic3d_TOR_AMBIENT);
229 aMaterial[i].SetReflectionModeOff(Graphic3d_TOR_DIFFUSE);
230 aMaterial[i].SetReflectionModeOff(Graphic3d_TOR_SPECULAR);
231 aMaterial[i].SetReflectionModeOff(Graphic3d_TOR_EMISSION);
232 }
233 else
234 {
235 // OCC20644 This stuff is important in order for elemental and nodal colors
236 // to produce similar visual impression and also to make colors match
237 // those in the color scale most exactly (the sum of all reflection
238 // coefficients is equal to 1). See also MeshVS_NodalColorPrsBuilder
239 // class for more explanations.
240 aMaterial[i].SetAmbient( .5 );
241 aMaterial[i].SetDiffuse( .5 );
242 aMaterial[i].SetSpecular( 0. );
243 aMaterial[i].SetEmissive( 0. );
244 }
245 }
246
247 // Draw elements with one color
248 for ( MeshVS_DataMapIteratorOfDataMapOfColorMapOfInteger aColIter ( aColorsOfElements ); aColIter.More();
249 aColIter.Next() )
250 {
251 Standard_Integer aSize = aColIter.Value().Extent();
252 if ( aSize<=0 )
253 continue;
254
255 TColStd_PackedMapOfInteger aCustomElements;
256
257 Prs3d_Root::NewGroup ( Prs );
258 Handle ( Graphic3d_Group ) aGGroup = Prs3d_Root::CurrentGroup ( Prs );
259 Prs3d_Root::NewGroup ( Prs );
260 Handle ( Graphic3d_Group ) aLGroup = Prs3d_Root::CurrentGroup ( Prs );
37ac4a67 261 Prs3d_Root::NewGroup ( Prs );
262 Handle ( Graphic3d_Group ) aSGroup = Prs3d_Root::CurrentGroup ( Prs );
263
264 Standard_Integer aNbFacePrimitives = 0;
265 Standard_Integer aNbVolmPrimitives = 0;
266 Standard_Integer aNbEdgePrimitives = 0;
267 Standard_Integer aNbLinkPrimitives = 0;
268
269 for (it.Reset(); it.More(); it.Next())
270 {
271 Standard_Integer aNbNodes = 0;
272
273 if (!aColIter.Value().Contains (it.Key()))
274 continue;
275
276 if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType))
277 continue;
278
279 if (aType == MeshVS_ET_Volume)
280 {
281 if (aSource->Get3DGeom (it.Key(), aNbNodes, aTopo))
282 {
283 for (Standard_Integer aFaceIdx = aTopo->Lower(); aFaceIdx <= aTopo->Upper(); ++aFaceIdx)
284 {
285 const TColStd_SequenceOfInteger& aFaceNodes = aTopo->Value (aFaceIdx);
7fd59977 286
37ac4a67 287 if (anEdgeOn) // add edge segments
288 {
289 aNbEdgePrimitives += aFaceNodes.Length();
290 }
291
709e97a0 292 aNbVolmPrimitives += aFaceNodes.Length() - 2;
37ac4a67 293 }
294 }
295 }
296 else if (aType == MeshVS_ET_Link)
297 {
298 if (anEdgeOn)
299 {
300 aNbLinkPrimitives += aNbNodes - 1; // add link segments
301 }
302 }
303 else if (aType == MeshVS_ET_Face)
304 {
305 if (anEdgeOn)
306 {
307 aNbEdgePrimitives += aNbNodes; // add edge segments
308 }
309
310 aNbFacePrimitives += aNbNodes - 2; // add face triangles
311 }
312 }
313
314 // Here we do not use indices arrays because they are not effective for some mesh
315 // drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D
316 // cell rendering (normal interpolation is not always applicable - flat shading),
317 // elemental coloring (color interpolation is impossible)
318
319 Handle (Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles (
320 (aNbFacePrimitives + aNbVolmPrimitives) * 3, 0, IsReflect );
7fd59977 321 Standard_Boolean IsPolyG = Standard_False;
322
37ac4a67 323 Handle (Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2);
324 Handle (Graphic3d_ArrayOfSegments) aLinkSegments = new Graphic3d_ArrayOfSegments (aNbLinkPrimitives * 2);
7fd59977 325 Standard_Boolean IsPolyL = Standard_False;
326
327 // OCC20644 NOTE: aColIter.Key() color is then scaled by TelUpdateMaterial() in OpenGl_attri.c
328 // using the material reflection coefficients. This affects the visual result.
37ac4a67 329 Handle(Graphic3d_AspectFillArea3d) aFillAspect =
7fd59977 330 new Graphic3d_AspectFillArea3d ( Aspect_IS_SOLID, aColIter.Key(), anEdgeColor,
331 anEdgeType, anEdgeWidth, aMaterial[0], aMaterial[1] );
332
37ac4a67 333 Handle(Graphic3d_AspectLine3d) aLinkAspect =
7fd59977 334 new Graphic3d_AspectLine3d ( aColIter.Key(), aLineType, aLineWidth );
335
37ac4a67 336 Handle(Graphic3d_AspectLine3d) anEdgeAspect =
337 new Graphic3d_AspectLine3d ( anEdgeColor, anEdgeType, anEdgeWidth );
338
339 aFillAspect->SetDistinguishOff ();
340 aFillAspect->SetInteriorColor ( aColIter.Key() );
7fd59977 341 if (anEdgeOn)
37ac4a67 342 aFillAspect->SetEdgeOn();
7fd59977 343 else
37ac4a67 344 aFillAspect->SetEdgeOff();
7fd59977 345
37ac4a67 346 for (it.Reset(); it.More(); it.Next())
7fd59977 347 {
348 Standard_Integer aKey = it.Key();
37ac4a67 349
350 if (aColIter.Value().Contains (aKey))
7fd59977 351 {
37ac4a67 352 if (!aSource->GetGeom (aKey, Standard_True, aCoords, NbNodes, aType))
7fd59977 353 continue;
37ac4a67 354
355 if (aType != MeshVS_ET_Face && aType != MeshVS_ET_Link && aType != MeshVS_ET_Volume)
7fd59977 356 {
37ac4a67 357 aCustomElements.Add (aKey);
358 continue;
7fd59977 359 }
37ac4a67 360
361 if (IsExcludingOn())
362 IDsToExclude.Add (aKey);
363
364 if (aType == MeshVS_ET_Volume)
7fd59977 365 {
37ac4a67 366 if (!aSource->Get3DGeom (aKey, NbNodes, aTopo))
7fd59977 367 {
7fd59977 368 continue;
37ac4a67 369 }
370
371 MeshVS_MeshPrsBuilder::AddVolumePrs (aTopo, aCoords,
372 NbNodes, aFaceTriangles, IsReflect, Standard_False, Standard_False, 1.0);
373
374 if (anEdgeOn)
375 {
376 MeshVS_MeshPrsBuilder::AddVolumePrs (aTopo, aCoords,
377 NbNodes, anEdgeSegments, IsReflect, Standard_False, Standard_False, 1.0);
378 }
379
380 IsPolyG = Standard_True;
7fd59977 381 }
37ac4a67 382 else if (aType == MeshVS_ET_Face)
7fd59977 383 {
37ac4a67 384 // Preparing normals
385 Handle(TColStd_HArray1OfReal) aNormals;
386 Standard_Boolean aHasNormals = IsReflect && aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals);
7fd59977 387
37ac4a67 388 for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx)
389 {
390 for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx)
391 {
392 if (IsReflect)
393 {
394 aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1),
395 aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2),
396 aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3),
397 aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1) : 0.0,
398 aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2) : 0.0,
399 aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3) : 1.0);
400 }
401 else
402 {
403 aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 1),
404 aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 2),
405 aCoords (3 * (anIdx == 0 ? 0 : (aNodeIdx + anIdx)) + 3));
406 }
407 }
408 }
7fd59977 409
37ac4a67 410 if (anEdgeOn)
7fd59977 411 {
37ac4a67 412 for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx)
7fd59977 413 {
37ac4a67 414 const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes;
415
416 anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
417 aCoords (3 * aNodeIdx + 2),
418 aCoords (3 * aNodeIdx + 3));
419
420 anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
421 aCoords (3 * aNextIdx + 2),
422 aCoords (3 * aNextIdx + 3));
7fd59977 423 }
7fd59977 424 }
37ac4a67 425
426 IsPolyG = Standard_True;
427 }
428 else if (aType == MeshVS_ET_Link)
429 {
430 for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 1; ++aNodeIdx)
7fd59977 431 {
37ac4a67 432 const Standard_Integer aNextIdx = aNodeIdx + 1;
433
434 aLinkSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
435 aCoords (3 * aNodeIdx + 2),
436 aCoords (3 * aNodeIdx + 3));
437
438 aLinkSegments->AddVertex (aCoords (3 * aNextIdx + 1),
439 aCoords (3 * aNextIdx + 2),
440 aCoords (3 * aNextIdx + 3));
441
7fd59977 442 IsPolyL = Standard_True;
443 }
37ac4a67 444 }
7fd59977 445 }
446 }
447
37ac4a67 448 if (IsPolyG)
7fd59977 449 {
37ac4a67 450 aFillAspect->SetEdgeOff();
451 aGGroup->SetPrimitivesAspect (aFillAspect);
452 aGGroup->AddPrimitiveArray (aFaceTriangles);
453
454 if (anEdgeOn)
455 {
456 aFillAspect->SetEdgeOff();
457 aSGroup->AddPrimitiveArray (anEdgeSegments);
458 aSGroup->SetGroupPrimitivesAspect (anEdgeAspect);
459 }
7fd59977 460 }
37ac4a67 461 if (IsPolyL)
7fd59977 462 {
37ac4a67 463 aFillAspect->SetEdgeOff();
464 aLGroup->SetPrimitivesAspect (aFillAspect);
465 aLGroup->SetPrimitivesAspect (aLinkAspect);
466 aLGroup->AddPrimitiveArray (aLinkSegments);
7fd59977 467 if (anEdgeOn)
37ac4a67 468 aFillAspect->SetEdgeOn();
7fd59977 469 else
37ac4a67 470 aFillAspect->SetEdgeOff();
7fd59977 471 }
472
37ac4a67 473 if (!aCustomElements.IsEmpty())
474 CustomBuild(Prs, aCustomElements, IDsToExclude, DisplayMode);
7fd59977 475 }
476
477 Graphic3d_MaterialAspect aMaterial2[2];
37ac4a67 478 for (Standard_Integer i = 0; i < 2; i++)
7fd59977 479 {
480 // OCC20644 "plastic" is most suitable here, as it is "non-physic"
481 // so TelUpdateMaterial() from OpenGl_attri.c uses the interior
482 // color from AspectFillArea3d to calculate all material colors
483 aMaterial2[i] = Graphic3d_MaterialAspect ( Graphic3d_NOM_PLASTIC );
484
485 if ( !IsReflect )
486 {
487 // OCC21720 Cannot turn ALL material components off, as such a material
488 // would be ignored by TelUpdateMaterial(), but we need it in order
489 // to have different materials for front and back sides!
490 // Instead, trying to make material color "nondirectional" with
491 // only ambient component on.
492 aMaterial2[i].SetReflectionModeOn ( Graphic3d_TOR_AMBIENT );
493 aMaterial2[i].SetReflectionModeOff( Graphic3d_TOR_DIFFUSE );
494 aMaterial2[i].SetReflectionModeOff( Graphic3d_TOR_SPECULAR );
495 aMaterial2[i].SetReflectionModeOff( Graphic3d_TOR_EMISSION );
496 aMaterial2[i].SetAmbient ( 1. );
497 aMaterial2[i].SetDiffuse ( 0. );
498 aMaterial2[i].SetSpecular( 0. );
499 aMaterial2[i].SetEmissive( 0. );
500 }
501 else
502 {
503 // OCC20644 This stuff is important in order for elemental and nodal colors
504 // to produce similar visual impression and also to make colors match
505 // those in the color scale most exactly (the sum of all reflection
506 // coefficients is equal to 1). See also MeshVS_NodalColorPrsBuilder
507 // class for more explanations.
508 aMaterial2[i].SetAmbient( .5 );
509 aMaterial2[i].SetDiffuse( .5 );
510 aMaterial2[i].SetSpecular( 0. );
511 aMaterial2[i].SetEmissive( 0. );
512 }
513 }
514
515 // Draw faces with two color
516 for ( MeshVS_DataMapIteratorOfDataMapOfTwoColorsMapOfInteger aColIter2 ( aTwoColorsOfElements );
517 aColIter2.More(); aColIter2.Next() )
518 {
519 Prs3d_Root::NewGroup ( Prs );
520 Handle ( Graphic3d_Group ) aGroup2 = Prs3d_Root::CurrentGroup ( Prs );
37ac4a67 521 Prs3d_Root::NewGroup ( Prs );
522 Handle ( Graphic3d_Group ) aGroup3 = Prs3d_Root::CurrentGroup ( Prs );
7fd59977 523
524 Standard_Integer aSize = aColIter2.Value().Extent();
525 if ( aSize<=0 )
526 continue;
527
37ac4a67 528 Standard_Integer aNbFacePrimitives = 0;
529 Standard_Integer aNbEdgePrimitives = 0;
530
531 for (it.Reset(); it.More(); it.Next())
532 {
533 Standard_Integer aNbNodes = 0;
534
535 if (!aColIter2.Value().Contains (it.Key()))
536 continue;
537
538 if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType))
539 continue;
540
541 if ( aType == MeshVS_ET_Face && aNbNodes > 0 )
542 {
543 if (anEdgeOn)
544 {
545 aNbEdgePrimitives += aNbNodes; // add edge segments
546 }
547
548 aNbFacePrimitives += aNbNodes - 2; // add face triangles
549 }
550 }
551
552 Handle (Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles
553 (aNbFacePrimitives * 3, 0, IsReflect);
554
555 Handle (Graphic3d_ArrayOfSegments) anEdgeSegments = new Graphic3d_ArrayOfSegments
556 (aNbEdgePrimitives * 2);
7fd59977 557
558 MeshVS_TwoColors aTC = aColIter2.Key();
559 Quantity_Color aMyIntColor, aMyBackColor;
560 ExtractColors ( aTC, aMyIntColor, aMyBackColor );
561
562 // OCC20644 NOTE: aMyIntColor color is then scaled by TelUpdateMaterial() in OpenGl_attri.c
563 // using the material reflection coefficients. This affects the visual result.
564 Handle(Graphic3d_AspectFillArea3d) anAsp =
565 new Graphic3d_AspectFillArea3d ( Aspect_IS_SOLID, aMyIntColor, anEdgeColor,
566 anEdgeType, anEdgeWidth, aMaterial2[0], aMaterial2[1] );
567 anAsp->SetDistinguishOn ();
568 anAsp->SetInteriorColor ( aMyIntColor );
569 anAsp->SetBackInteriorColor ( aMyBackColor );
37ac4a67 570 /*if (anEdgeOn)
7fd59977 571 anAsp->SetEdgeOn();
572 else
37ac4a67 573 anAsp->SetEdgeOff();*/
7fd59977 574
37ac4a67 575 Handle(Graphic3d_AspectLine3d) anEdgeAspect =
576 new Graphic3d_AspectLine3d (anEdgeColor, anEdgeType, anEdgeWidth);
7fd59977 577
578 for( it.Reset(); it.More(); it.Next() )
579 {
580 Standard_Integer aKey = it.Key();
581 if( aColIter2.Value().Contains( aKey ) )
582 {
583 if ( !aSource->GetGeom ( aKey, Standard_True, aCoords, NbNodes, aType ) )
584 continue;
585
586 if( IsExcludingOn() )
587 IDsToExclude.Add( aKey );
588
37ac4a67 589 if (aType == MeshVS_ET_Face && NbNodes > 0)
7fd59977 590 {
591 // Preparing normal(s) to show reflections if requested
592 Handle(TColStd_HArray1OfReal) aNormals;
593 // OCC21720 Always passing normals to OpenGL to make materials work
594 // For OpenGL: "No normals" -> "No lighting" -> "no materials taken into account"
37ac4a67 595 Standard_Boolean aHasNormals = /*IsReflect &&*/
596 aSource->GetNormalsByElement (aKey, IsMeshSmoothShading, aMaxFaceNodes, aNormals);
7fd59977 597
37ac4a67 598 for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes - 2; ++aNodeIdx)
599 {
600 for (Standard_Integer anIdx = 0; anIdx < 3; ++anIdx)
601 {
602 if (IsReflect)
603 {
604 aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1),
605 aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2),
606 aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3),
607 aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1) : 0.0,
608 aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2) : 0.0,
609 aHasNormals ? aNormals->Value (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3) : 1.0);
610 }
611 else
612 {
613 aFaceTriangles->AddVertex (aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 1),
614 aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 2),
615 aCoords (3 * (anIdx == 0 ? 0 : aNodeIdx + anIdx) + 3));
616 }
617 }
618 }
7fd59977 619
37ac4a67 620 if (anEdgeOn)
7fd59977 621 {
37ac4a67 622 for (Standard_Integer aNodeIdx = 0; aNodeIdx < NbNodes; ++aNodeIdx)
7fd59977 623 {
37ac4a67 624 const Standard_Integer aNextIdx = (aNodeIdx + 1) % NbNodes;
625
626 anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
627 aCoords (3 * aNodeIdx + 2),
628 aCoords (3 * aNodeIdx + 3));
629
630 anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
631 aCoords (3 * aNextIdx + 2),
632 aCoords (3 * aNextIdx + 3));
7fd59977 633 }
7fd59977 634 }
7fd59977 635 }
636 }
637 }
37ac4a67 638
639 aGroup2->AddPrimitiveArray (aFaceTriangles);
640 aGroup2->SetGroupPrimitivesAspect (anAsp);
641 aGroup3->AddPrimitiveArray (anEdgeSegments);
642 aGroup3->SetGroupPrimitivesAspect (anEdgeAspect);
7fd59977 643 }
644}
645
646//================================================================
647// Function : SetColors
648// Purpose :
649//================================================================
650void MeshVS_ElementalColorPrsBuilder::SetColors1 ( const MeshVS_DataMapOfIntegerColor& theColorMap )
651{
652 myElemColorMap1 = theColorMap;
653}
654
655//================================================================
656// Function : GetColors
657// Purpose :
658//================================================================
659const MeshVS_DataMapOfIntegerColor& MeshVS_ElementalColorPrsBuilder::GetColors1 () const
660{
661 return myElemColorMap1;
662}
663
664//================================================================
665// Function : HasColors1
666// Purpose :
667//================================================================
668Standard_Boolean MeshVS_ElementalColorPrsBuilder::HasColors1 () const
669{
670 return ( myElemColorMap1.Extent() >0 );
671}
672
673//================================================================
674// Function : GetColor1
675// Purpose :
676//================================================================
677Standard_Boolean MeshVS_ElementalColorPrsBuilder::GetColor1 ( const Standard_Integer ID,
678 Quantity_Color& theColor ) const
679{
680 Standard_Boolean aRes = myElemColorMap1.IsBound ( ID );
681 if ( aRes )
682 theColor = myElemColorMap1.Find ( ID );
683
684 return aRes;
685}
686
687//================================================================
688// Function : SetColor1
689// Purpose :
690//================================================================
691void MeshVS_ElementalColorPrsBuilder::SetColor1 ( const Standard_Integer theID,
692 const Quantity_Color& theCol )
693{
694 Standard_Boolean aRes = myElemColorMap1.IsBound ( theID );
695 if ( aRes )
696 myElemColorMap1.ChangeFind ( theID ) = theCol;
697 else
698 myElemColorMap1.Bind ( theID, theCol );
699}
700
701//================================================================
702// Function : SetColors2
703// Purpose :
704//================================================================
705void MeshVS_ElementalColorPrsBuilder::SetColors2 ( const MeshVS_DataMapOfIntegerTwoColors& theColorMap )
706{
707 myElemColorMap2 = theColorMap;
708}
709
710//================================================================
711// Function : GetColors2
712// Purpose :
713//================================================================
714const MeshVS_DataMapOfIntegerTwoColors& MeshVS_ElementalColorPrsBuilder::GetColors2 () const
715{
716 return myElemColorMap2;
717}
718
719//================================================================
720// Function : HasColors2
721// Purpose :
722//================================================================
723Standard_Boolean MeshVS_ElementalColorPrsBuilder::HasColors2 () const
724{
725 return (myElemColorMap2.Extent()>0);
726}
727
728//================================================================
729// Function : GetColor2
730// Purpose :
731//================================================================
732Standard_Boolean MeshVS_ElementalColorPrsBuilder::GetColor2 ( const Standard_Integer ID,
733 MeshVS_TwoColors& theColor ) const
734{
735 Standard_Boolean aRes = myElemColorMap2.IsBound ( ID );
736 if ( aRes )
737 theColor = myElemColorMap2.Find ( ID );
738
739 return aRes;
740}
741
742//================================================================
743// Function : GetColor2
744// Purpose :
745//================================================================
746Standard_Boolean MeshVS_ElementalColorPrsBuilder::GetColor2 ( const Standard_Integer ID,
747 Quantity_Color& theColor1,
748 Quantity_Color& theColor2 ) const
749{
750 MeshVS_TwoColors aTC;
751 Standard_Boolean aRes = GetColor2 ( ID, aTC );
752 if ( aRes)
753 ExtractColors ( aTC, theColor1, theColor2 );
754 return aRes;
755}
756
757//================================================================
758// Function : SetColor2
759// Purpose :
760//================================================================
761void MeshVS_ElementalColorPrsBuilder::SetColor2 ( const Standard_Integer theID,
762 const Quantity_Color& theCol1,
763 const Quantity_Color& theCol2 )
764{
765 SetColor2 ( theID, BindTwoColors ( theCol1, theCol2 ) );
766}
767
768//================================================================
769// Function : SetColor2
770// Purpose :
771//================================================================
772void MeshVS_ElementalColorPrsBuilder::SetColor2 ( const Standard_Integer theID,
773 const MeshVS_TwoColors& theCol )
774{
775 Standard_Boolean aRes = myElemColorMap2.IsBound ( theID );
776 if ( aRes )
777 myElemColorMap2.ChangeFind ( theID ) = theCol;
778 else
779 myElemColorMap2.Bind ( theID, theCol );
780}