Commit | Line | Data |
---|---|---|
7fd59977 | 1 | // File: AIS_TexturedShape.cdl |
2 | // Created: Mon Jul 2 11:32:59 2001 | |
3 | // Author: Mathias BOSSHARD | |
4 | // <mbd@pomalox.paris1.matra-dtv.fr> | |
5 | // Copyright: Matra Datavision 2001 | |
6 | // | |
7 | // Modified: | |
8 | // | |
9 | // | |
10 | // | |
11 | //////////////////////////////////////////////////////////////////////// | |
12 | ||
13 | ||
14 | #include <AIS_TexturedShape.ixx> | |
15 | #include <Standard_ErrorHandler.hxx> | |
16 | ||
17 | #include <BRepTools.hxx> | |
18 | #include <gp_Vec.hxx> | |
19 | #include <Graphic3d_StructureManager.hxx> | |
20 | #include <Graphic3d_Texture2Dmanual.hxx> | |
21 | #include <Graphic3d_AspectFillArea3d.hxx> | |
22 | #include <AIS_InteractiveContext.hxx> | |
23 | #include <Prs3d_ShadingAspect.hxx> | |
24 | #include <Prs3d_Root.hxx> | |
25 | #include <PrsMgr_PresentationManager3d.hxx> | |
26 | #include <Prs3d_Presentation.hxx> | |
27 | #include <TopExp_Explorer.hxx> | |
28 | #include <StdPrs_WFDeflectionShape.hxx> | |
29 | #include <Graphic3d_Group.hxx> | |
30 | #include <AIS_Drawer.hxx> | |
31 | #include <StdPrs_WFShape.hxx> | |
32 | #include <StdPrs_ShadedShape.hxx> | |
33 | #include <StdPrs_ToolShadedShape.hxx> | |
34 | #include <Precision.hxx> | |
35 | #include <BRepMesh.hxx> | |
36 | #include <Poly_Triangulation.hxx> | |
37 | #include <Poly_Connect.hxx> | |
38 | #include <Graphic3d_Array1OfVertexNT.hxx> | |
39 | #include <Aspect_Array1OfEdge.hxx> | |
40 | #include <TColgp_Array1OfDir.hxx> | |
41 | #include <TColgp_Array1OfPnt2d.hxx> | |
42 | ||
43 | #define MAX2(X, Y) ( Abs(X) > Abs(Y)? Abs(X) : Abs(Y) ) | |
44 | #define MAX3(X, Y, Z) ( MAX2 ( MAX2(X,Y) , Z) ) | |
45 | ||
46 | ////////////////////////////////////////////////////////////////////// | |
47 | // CONSTRUCTOR / DESTRUCTOR | |
48 | ////////////////////////////////////////////////////////////////////// | |
49 | ||
50 | //======================================================================= | |
51 | //function : AIS_TexturedShape | |
52 | //purpose : | |
53 | //======================================================================= | |
54 | ||
55 | AIS_TexturedShape::AIS_TexturedShape(const TopoDS_Shape& ashape):AIS_Shape(ashape), | |
56 | myPredefTexture(Graphic3d_NameOfTexture2D(0)), | |
57 | myTextureFile(""), | |
58 | DoRepeat(Standard_True), | |
59 | myURepeat(1.0), | |
60 | myVRepeat(1.0), | |
61 | DoMapTexture(Standard_True), | |
62 | DoSetTextureOrigin(Standard_True), | |
63 | myUOrigin(0.0), | |
64 | myVOrigin(0.0), | |
65 | DoSetTextureScale(Standard_True), | |
66 | myScaleU(1.0), | |
67 | myScaleV(1.0), | |
68 | DoShowTriangles(Standard_False), | |
69 | myModulate(Standard_True) | |
70 | { | |
71 | } | |
72 | ||
73 | ////////////////////////////////////////////////////////////////////// | |
74 | // TEXTURE MAPPING MANAGEMENT METHODS | |
75 | ////////////////////////////////////////////////////////////////////// | |
76 | ||
77 | //======================================================================= | |
78 | //function : SetTextureFileName | |
79 | //purpose : | |
80 | //======================================================================= | |
81 | ||
82 | void AIS_TexturedShape::SetTextureFileName(const TCollection_AsciiString& TextureFileName) | |
83 | { | |
84 | if (TextureFileName.IsIntegerValue()) | |
85 | { | |
86 | if(TextureFileName.IntegerValue()<Graphic3d_Texture2D::NumberOfTextures() && TextureFileName.IntegerValue()>=0) | |
87 | myPredefTexture = (Graphic3d_NameOfTexture2D)(TextureFileName.IntegerValue()); | |
88 | else | |
89 | { | |
90 | cout << "Texture "<<TextureFileName<<" doesn't exist \n"<< endl; | |
91 | cout << "Using Texture 0 instead ...\n"<< endl; | |
92 | myPredefTexture = (Graphic3d_NameOfTexture2D)(0); | |
93 | } | |
94 | myTextureFile = ""; | |
95 | } | |
96 | else | |
97 | { | |
98 | myTextureFile = TextureFileName; | |
99 | myPredefTexture = (Graphic3d_NameOfTexture2D)(-1); | |
100 | } | |
101 | } | |
102 | ||
103 | //======================================================================= | |
104 | //function : SetTextureRepeat | |
105 | //purpose : | |
106 | //======================================================================= | |
107 | ||
108 | void AIS_TexturedShape::SetTextureRepeat(const Standard_Boolean RepeatYN, | |
109 | const Standard_Real URepeat, | |
110 | const Standard_Real VRepeat) | |
111 | { | |
112 | DoRepeat = RepeatYN; | |
113 | myURepeat = URepeat; | |
114 | myVRepeat = VRepeat; | |
115 | } | |
116 | ||
117 | //======================================================================= | |
118 | //function : SetTextureMapOn | |
119 | //purpose : | |
120 | //======================================================================= | |
121 | ||
122 | void AIS_TexturedShape::SetTextureMapOn() | |
123 | { | |
124 | DoMapTexture = Standard_True; | |
125 | } | |
126 | ||
127 | //======================================================================= | |
128 | //function : SetTextureMapOff | |
129 | //purpose : | |
130 | //======================================================================= | |
131 | ||
132 | void AIS_TexturedShape::SetTextureMapOff() | |
133 | { | |
134 | DoMapTexture = Standard_False; | |
135 | } | |
136 | ||
137 | //======================================================================= | |
138 | //function : SetTextureOrigin | |
139 | //purpose : | |
140 | //======================================================================= | |
141 | ||
142 | void AIS_TexturedShape::SetTextureOrigin(const Standard_Boolean SetTextureOriginYN, const Standard_Real UOrigin, const Standard_Real VOrigin) | |
143 | { | |
144 | DoSetTextureOrigin = SetTextureOriginYN; | |
145 | myUOrigin = UOrigin; | |
146 | myVOrigin = VOrigin; | |
147 | } | |
148 | ||
149 | //======================================================================= | |
150 | //function : SetTextureScale | |
151 | //purpose : | |
152 | //======================================================================= | |
153 | ||
154 | void AIS_TexturedShape::SetTextureScale(const Standard_Boolean SetTextureScaleYN, const Standard_Real ScaleU, const Standard_Real ScaleV) | |
155 | { | |
156 | DoSetTextureScale = SetTextureScaleYN; | |
157 | myScaleU = ScaleU; | |
158 | myScaleV = ScaleV; | |
159 | } | |
160 | ||
161 | //======================================================================= | |
162 | //function : TriangleIsValid | |
163 | //purpose : | |
164 | //======================================================================= | |
165 | ||
166 | Standard_Boolean AIS_TexturedShape::TriangleIsValid(const gp_Pnt& P1, const gp_Pnt& P2, const gp_Pnt& P3) const | |
167 | { | |
168 | gp_Vec V1(P1,P2); // V1=(P1,P2) | |
169 | gp_Vec V2(P2,P3); // V2=(P2,P3) | |
170 | gp_Vec V3(P3,P1); // V3=(P3,P1) | |
171 | ||
172 | if ((V1.SquareMagnitude() > 1.e-10) && (V2.SquareMagnitude() > 1.e-10) && (V3.SquareMagnitude() > 1.e-10)) | |
173 | { | |
174 | V1.Cross(V2); // V1 = Normal | |
175 | if (V1.SquareMagnitude() > 1.e-10) | |
176 | return Standard_True; | |
177 | else | |
178 | return Standard_False; | |
179 | } | |
180 | else | |
181 | return Standard_False; | |
182 | ||
183 | } | |
184 | ||
185 | //======================================================================= | |
186 | //function : ShowTriangles | |
187 | //purpose : | |
188 | //======================================================================= | |
189 | ||
190 | void AIS_TexturedShape::ShowTriangles(const Standard_Boolean ShowTrianglesYN) | |
191 | { | |
192 | DoShowTriangles = ShowTrianglesYN; | |
193 | } | |
194 | ||
195 | //======================================================================= | |
196 | //function : EnableTextureModulate | |
197 | //purpose : | |
198 | //======================================================================= | |
199 | ||
200 | void AIS_TexturedShape::EnableTextureModulate() | |
201 | { | |
202 | myModulate = Standard_True; | |
203 | } | |
204 | ||
205 | //======================================================================= | |
206 | //function : DisableTextureModulate | |
207 | //purpose : | |
208 | //======================================================================= | |
209 | ||
210 | void AIS_TexturedShape::DisableTextureModulate() | |
211 | { | |
212 | myModulate = Standard_False; | |
213 | } | |
214 | ||
215 | //======================================================================= | |
216 | //function : UpdateAttributes | |
217 | //purpose : | |
218 | //======================================================================= | |
219 | ||
220 | void AIS_TexturedShape::UpdateAttributes() | |
221 | { | |
222 | Handle(Graphic3d_StructureManager) aStrucMana = GetContext()->MainPrsMgr()->StructureManager(); | |
223 | myAspect = (new Prs3d_ShadingAspect())->Aspect(); | |
224 | Handle(Prs3d_Presentation) aPrs = Presentation(); | |
225 | if (!DoMapTexture) | |
226 | { | |
227 | myAspect->SetTextureMapOff(); | |
228 | return; | |
229 | } | |
230 | ||
231 | if(myPredefTexture!=-1) | |
232 | mytexture = new Graphic3d_Texture2Dmanual(aStrucMana, myPredefTexture); | |
233 | else | |
234 | mytexture = new Graphic3d_Texture2Dmanual(aStrucMana, myTextureFile.ToCString()); | |
235 | ||
236 | myAspect->SetTextureMapOn(); | |
237 | ||
238 | myAspect->SetTextureMap(mytexture); | |
239 | if (!mytexture->IsDone()) | |
240 | { | |
241 | cout << "An error occured while building texture \n" <<endl; | |
242 | return; | |
243 | } | |
244 | ||
245 | if (DoShowTriangles) | |
246 | myAspect->SetEdgeOn(); | |
247 | else | |
248 | myAspect->SetEdgeOff(); | |
249 | ||
250 | Prs3d_Root::CurrentGroup(aPrs)->SetGroupPrimitivesAspect(myAspect); | |
251 | } | |
252 | ||
253 | //======================================================================= | |
254 | //function : Compute | |
255 | //purpose : | |
256 | //======================================================================= | |
257 | ||
258 | void AIS_TexturedShape::Compute(const Handle(PrsMgr_PresentationManager3d)& /*aPresentationManager*/, | |
259 | const Handle(Prs3d_Presentation)& aPrs, | |
260 | const Standard_Integer aMode) | |
261 | { | |
262 | aPrs->Clear(); | |
263 | ||
264 | if(myshape.IsNull()) return; | |
265 | ||
266 | Standard_Integer TheType; | |
267 | TheType = (Standard_Integer) myshape.ShapeType(); | |
268 | if(TheType>4 && TheType<8) | |
269 | { | |
270 | aPrs->SetVisual(Graphic3d_TOS_ALL); | |
271 | aPrs->SetDisplayPriority(TheType+2); | |
272 | } | |
273 | ||
274 | if (myshape.ShapeType() == TopAbs_COMPOUND) | |
275 | { | |
276 | TopExp_Explorer anExplor (myshape, TopAbs_VERTEX); | |
277 | if (!anExplor.More()) {return;} | |
278 | } | |
279 | ||
280 | if (IsInfinite()) | |
281 | aPrs->SetInfiniteState(Standard_True); | |
282 | ||
283 | switch (aMode) | |
284 | { | |
285 | ||
286 | case 0: // Wireframe | |
287 | StdPrs_WFDeflectionShape::Add(aPrs,myshape,myDrawer); | |
288 | break; | |
289 | ||
290 | case 1: // Shading) | |
291 | { | |
292 | Standard_Real prevangle ; | |
293 | Standard_Real newangle ; | |
294 | Standard_Real prevcoeff ; | |
295 | Standard_Real newcoeff ; | |
296 | ||
297 | if (OwnDeviationAngle(newangle,prevangle) || OwnDeviationCoefficient(newcoeff,prevcoeff)) | |
298 | if (Abs (newangle - prevangle) > Precision::Angular() || Abs (newcoeff - prevcoeff) > Precision::Confusion() ) | |
299 | { | |
300 | BRepTools::Clean(myshape); | |
301 | } | |
302 | if ((Standard_Integer) myshape.ShapeType()>4) | |
303 | StdPrs_WFDeflectionShape::Add(aPrs,myshape,myDrawer); | |
304 | else | |
305 | { | |
306 | myDrawer->SetShadingAspectGlobal(Standard_False); | |
307 | if (IsInfinite()) | |
308 | StdPrs_WFDeflectionShape::Add(aPrs,myshape,myDrawer); | |
309 | else | |
310 | { | |
311 | try | |
312 | { | |
313 | OCC_CATCH_SIGNALS | |
314 | StdPrs_ShadedShape::Add(aPrs,myshape,myDrawer); | |
315 | } | |
316 | catch (Standard_Failure) | |
317 | { | |
318 | cout <<"AIS_TexturedShape::Compute() in ShadingMode failed \n" <<endl; | |
319 | StdPrs_WFShape::Add(aPrs,myshape,myDrawer); | |
320 | } | |
321 | } | |
322 | } | |
323 | break; | |
324 | } | |
325 | ||
326 | case 2: // Bounding box | |
327 | { | |
328 | if (IsInfinite()) | |
329 | { | |
330 | StdPrs_WFDeflectionShape::Add(aPrs,myshape,myDrawer); | |
331 | } | |
332 | else | |
333 | { | |
334 | AIS_Shape::DisplayBox(aPrs,BoundingBox(),myDrawer); | |
335 | } | |
336 | break; | |
337 | } | |
338 | ||
339 | case 3: // texture mapping on triangulation | |
340 | { | |
341 | BRepTools::Clean(myshape); | |
342 | BRepTools::Update(myshape); | |
343 | ||
344 | Handle(Graphic3d_StructureManager) aStrucMana = GetContext()->MainPrsMgr()->StructureManager(); | |
161c4476 K |
345 | { |
346 | Handle(Prs3d_ShadingAspect) aPrs3d_ShadingAspect = new Prs3d_ShadingAspect; | |
347 | myAspect = aPrs3d_ShadingAspect->Aspect(); | |
348 | } | |
7fd59977 | 349 | if (!DoMapTexture) |
350 | { | |
351 | myAspect->SetTextureMapOff(); | |
352 | return; | |
353 | } | |
354 | myAspect->SetTextureMapOn(); | |
355 | ||
356 | if(myPredefTexture!=-1) | |
357 | mytexture = new Graphic3d_Texture2Dmanual(aStrucMana, myPredefTexture); | |
358 | else | |
359 | mytexture = new Graphic3d_Texture2Dmanual(aStrucMana, myTextureFile.ToCString()); | |
360 | ||
361 | if (!mytexture->IsDone()) | |
362 | { | |
363 | cout <<"An error occured while building texture \n" <<endl; | |
364 | return; | |
365 | } | |
366 | if (myModulate) | |
367 | mytexture->EnableModulate(); | |
368 | else | |
369 | mytexture->DisableModulate(); | |
370 | ||
371 | myAspect->SetTextureMap(mytexture); | |
372 | if (DoShowTriangles) | |
373 | myAspect->SetEdgeOn(); | |
374 | else | |
375 | myAspect->SetEdgeOff(); | |
376 | ||
377 | if (DoRepeat) | |
378 | mytexture->EnableRepeat(); | |
379 | else | |
380 | mytexture->DisableRepeat(); | |
381 | ||
382 | myDeflection = AIS_Shape::GetDeflection(myshape,myDrawer); | |
383 | BRepMesh::Mesh(myshape,myDeflection); | |
384 | // Adds a triangulation of the shape myshape to its topological data structure. | |
385 | // This triangulation is computed with the deflection myDeflection. | |
386 | ||
387 | #ifdef DEBUG | |
388 | cout <<"Deflection = " << myDeflection << "\n" << endl; | |
389 | #endif | |
390 | ||
391 | StdPrs_ToolShadedShape SST; | |
392 | ||
393 | Standard_Integer NumFace; | |
394 | TopExp_Explorer ExpFace; | |
395 | ||
396 | for( NumFace=0,ExpFace.Init(myshape,TopAbs_FACE); ExpFace.More(); ExpFace.Next(),NumFace++ ) | |
397 | { | |
398 | TopoDS_Face myFace = TopoDS::Face(ExpFace.Current()); | |
399 | TopLoc_Location aLocation = myFace.Location(); | |
400 | ||
401 | #ifdef DEBUG | |
402 | cout << "J\'explore actuellement la face " << NumFace << "\n" << endl; | |
403 | #endif | |
404 | Handle(Poly_Triangulation) myT = BRep_Tool::Triangulation(myFace, aLocation); | |
405 | // Returns the Triangulation of the face. It is a null handle if there is no triangulation. | |
406 | ||
407 | if (myT.IsNull()) | |
408 | { | |
409 | #ifdef DEBUG | |
410 | cout << "Triangulation of the face "<< i <<" is null \n"<< endl; | |
411 | #endif | |
412 | return; | |
413 | } | |
414 | Poly_Connect pc(myT); | |
415 | const TColgp_Array1OfPnt& Nodes = myT->Nodes(); | |
416 | const TColgp_Array1OfPnt2d& UVNodes = myT->UVNodes(); | |
417 | const Poly_Array1OfTriangle& triangles = myT->Triangles(); | |
418 | TColgp_Array1OfDir myNormal(Nodes.Lower(), Nodes.Upper()); | |
419 | ||
420 | SST.Normal(myFace, pc, myNormal); | |
421 | BRepTools::UVBounds(myFace,Umin, Umax, Vmin, Vmax); | |
422 | dUmax = (Umax - Umin); | |
423 | dVmax = (Vmax - Vmin); | |
424 | Handle(Graphic3d_Group) mygroup = Prs3d_Root::CurrentGroup(aPrs); | |
425 | ||
426 | Standard_Integer nnn = myT->NbTriangles(); // nnn : nombre de triangles | |
427 | Standard_Integer nt, n1, n2, n3 = 0; // nt : triangle courant | |
428 | // ni : sommet i du triangle courant | |
429 | for (nt = 1; nt <= nnn; nt++) | |
430 | { | |
431 | #ifdef DEBUG | |
432 | cout << "On traite actuellement le triangle : "<< nt <<"\n"; | |
433 | #endif | |
434 | if (SST.Orientation(myFace) == TopAbs_REVERSED) // si la face est "reversed" | |
435 | triangles(nt).Get(n1,n3,n2); // le triangle est n1,n3,n2 | |
436 | else | |
437 | triangles(nt).Get(n1,n2,n3); // le triangle est n1,n2,n3 | |
438 | ||
439 | if (TriangleIsValid (Nodes(n1),Nodes(n2),Nodes(n3)) ) | |
440 | { // Associates a vertexNT to each node | |
441 | Graphic3d_Array1OfVertexNT Points(1,3); | |
442 | Aspect_Array1OfEdge aretes(1,3); | |
443 | ||
444 | mygroup->BeginPrimitives(); | |
445 | { | |
446 | gp_Pnt p = Nodes(n1).Transformed(aLocation.Transformation()); | |
447 | gp_Pnt q = Nodes(n2).Transformed(aLocation.Transformation()); | |
448 | gp_Pnt r = Nodes(n3).Transformed(aLocation.Transformation()); | |
449 | ||
450 | Points(1).SetCoord(p.X(), p.Y(), p.Z()); | |
451 | Points(2).SetCoord(q.X(), q.Y(), q.Z()); | |
452 | Points(3).SetCoord(r.X(), r.Y(), r.Z()); | |
453 | ||
454 | Points(1).SetNormal(myNormal(n1).X(), myNormal(n1).Y(), myNormal(n1).Z()); | |
455 | Points(2).SetNormal(myNormal(n2).X(), myNormal(n2).Y(), myNormal(n2).Z()); | |
456 | Points(3).SetNormal(myNormal(n3).X(), myNormal(n3).Y(), myNormal(n3).Z()); | |
457 | ||
458 | Points(1).SetTextureCoordinate((-myUOrigin+(myURepeat*(UVNodes(n1).X()-Umin))/dUmax)/myScaleU, | |
459 | (-myVOrigin+(myVRepeat*(UVNodes(n1).Y()-Vmin))/dVmax)/myScaleV); | |
460 | Points(2).SetTextureCoordinate((-myUOrigin+(myURepeat*(UVNodes(n2).X()-Umin))/dUmax)/myScaleU, | |
461 | (-myVOrigin+(myVRepeat*(UVNodes(n2).Y()-Vmin))/dVmax)/myScaleV); | |
462 | Points(3).SetTextureCoordinate((-myUOrigin+(myURepeat*(UVNodes(n3).X()-Umin))/dUmax)/myScaleU, | |
463 | (-myVOrigin+(myVRepeat*(UVNodes(n3).Y()-Vmin))/dVmax)/myScaleV); | |
464 | ||
465 | aretes(1).SetValues(1, 2, Aspect_TOE_INVISIBLE); | |
466 | aretes(2).SetValues(2, 3, Aspect_TOE_INVISIBLE); | |
467 | aretes(3).SetValues(3, 1, Aspect_TOE_INVISIBLE); | |
468 | } | |
469 | mygroup->EndPrimitives(); | |
470 | mygroup->TriangleSet(Points, aretes, Standard_True); | |
471 | ||
472 | } // end of "if the triangle is valid | |
473 | } // end of the "parcours" of the triangles | |
474 | mygroup->SetGroupPrimitivesAspect(myAspect); | |
475 | }// end of the exploration of the shape in faces | |
476 | break; | |
477 | }// end case 3 | |
478 | ||
479 | } // end switch | |
480 | // aPrs->ReCompute(); // for hidden line recomputation if necessary... | |
481 | } | |
482 | ||
483 | ||
484 | ||
485 | ||
486 | ||
487 | ///////////////////////////////////////////////////////// | |
488 | // QUERY METHODS | |
489 | ///////////////////////////////////////////////////////// | |
490 | ||
491 | ||
492 | ||
493 | Standard_Boolean AIS_TexturedShape::TextureMapState() const | |
494 | { | |
495 | return DoMapTexture; | |
496 | } | |
497 | ||
498 | Standard_Real AIS_TexturedShape::URepeat() const | |
499 | { | |
500 | return myURepeat; | |
501 | } | |
502 | ||
503 | Standard_Boolean AIS_TexturedShape::TextureRepeat() const | |
504 | { | |
505 | return DoRepeat; | |
506 | } | |
507 | ||
508 | Standard_Real AIS_TexturedShape::Deflection() const | |
509 | { | |
510 | return myDeflection; | |
511 | } | |
512 | ||
513 | Standard_CString AIS_TexturedShape::TextureFile() const | |
514 | { | |
515 | return myTextureFile.ToCString(); | |
516 | } | |
517 | ||
518 | Standard_Real AIS_TexturedShape::VRepeat() const | |
519 | { | |
520 | return myVRepeat; | |
521 | } | |
522 | Standard_Boolean AIS_TexturedShape::ShowTriangles() const | |
523 | { | |
524 | return DoShowTriangles; | |
525 | } | |
526 | Standard_Real AIS_TexturedShape::TextureUOrigin() const | |
527 | { | |
528 | return myUOrigin; | |
529 | } | |
530 | Standard_Real AIS_TexturedShape::TextureVOrigin() const | |
531 | { | |
532 | return myVOrigin; | |
533 | } | |
534 | Standard_Real AIS_TexturedShape::TextureScaleU() const | |
535 | { | |
536 | return myScaleU; | |
537 | } | |
538 | Standard_Real AIS_TexturedShape::TextureScaleV() const | |
539 | { | |
540 | return myScaleV; | |
541 | } | |
542 | Standard_Boolean AIS_TexturedShape::TextureScale() const | |
543 | { | |
544 | return DoSetTextureScale; | |
545 | } | |
546 | Standard_Boolean AIS_TexturedShape::TextureOrigin() const | |
547 | { | |
548 | return DoSetTextureOrigin; | |
549 | } | |
550 | Standard_Boolean AIS_TexturedShape::TextureModulate() const | |
551 | { | |
552 | return myModulate; | |
553 | } |