0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / AIS / AIS_TexturedShape.cxx
1 // Created on: 2001-07-02
2 // Created by: Mathias BOSSHARD
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <AIS_TexturedShape.hxx>
17
18 #include <AIS_GraphicTool.hxx>
19 #include <AIS_InteractiveContext.hxx>
20 #include <BRepTools.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <Graphic3d_AspectFillArea3d.hxx>
23 #include <Graphic3d_Group.hxx>
24 #include <Graphic3d_StructureManager.hxx>
25 #include <Graphic3d_Texture2Dmanual.hxx>
26 #include <Message.hxx>
27 #include <Message_Messenger.hxx>
28 #include <Precision.hxx>
29 #include <Prs3d_Drawer.hxx>
30 #include <Prs3d_Presentation.hxx>
31 #include <PrsMgr_ModedPresentation.hxx>
32 #include <Prs3d_Root.hxx>
33 #include <Prs3d_LineAspect.hxx>
34 #include <Prs3d_ShadingAspect.hxx>
35 #include <PrsMgr_PresentationManager3d.hxx>
36 #include <Standard_ErrorHandler.hxx>
37 #include <StdPrs_BndBox.hxx>
38 #include <StdPrs_ShadedShape.hxx>
39 #include <StdPrs_ToolTriangulatedShape.hxx>
40 #include <StdPrs_WFShape.hxx>
41 #include <TopExp_Explorer.hxx>
42
43
44 IMPLEMENT_STANDARD_RTTIEXT(AIS_TexturedShape,AIS_Shape)
45
46 //=======================================================================
47 //function : AIS_TexturedShape
48 //purpose  :
49 //=======================================================================
50 AIS_TexturedShape::AIS_TexturedShape (const TopoDS_Shape& theShape)
51 : AIS_Shape         (theShape),
52   myPredefTexture   (Graphic3d_NameOfTexture2D(0)),
53   myToMapTexture    (Standard_True),
54   myModulate        (Standard_True),
55   myIsCustomOrigin  (Standard_True),
56   myToRepeat        (Standard_True),
57   myToScale         (Standard_True),
58   myToShowTriangles (Standard_False)
59 {
60 }
61
62 //=======================================================================
63 //function : SetTextureFileName
64 //purpose  :
65 //=======================================================================
66 void AIS_TexturedShape::SetTextureFileName (const TCollection_AsciiString& theTextureFileName)
67 {
68   myTexturePixMap.Nullify();
69
70   if (theTextureFileName.IsIntegerValue())
71   {
72     const Standard_Integer aValue = theTextureFileName.IntegerValue();
73     if (aValue < Graphic3d_Texture2D::NumberOfTextures()
74      && aValue >= 0)
75     {
76       myPredefTexture = Graphic3d_NameOfTexture2D (aValue);
77     }
78     else
79     {
80       Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: texture with ID ") + theTextureFileName
81                                        + " is undefined! Texture 0 will be used instead.", Message_Fail);
82       myPredefTexture = Graphic3d_NameOfTexture2D (0);
83     }
84     myTextureFile = "";
85   }
86   else
87   {
88     myTextureFile   = theTextureFileName;
89     myPredefTexture = Graphic3d_NOT_2D_UNKNOWN;
90   }
91 }
92
93 //=======================================================================
94 //function : SetTexturePixMap
95 //purpose  :
96 //=======================================================================
97 void AIS_TexturedShape::SetTexturePixMap (const Handle(Image_PixMap)& theTexturePixMap)
98 {
99   myTextureFile = "";
100   myPredefTexture = Graphic3d_NOT_2D_UNKNOWN;
101   myTexturePixMap = theTexturePixMap;
102 }
103
104 //=======================================================================
105 //function : SetTextureRepeat
106 //purpose  :
107 //=======================================================================
108
109 void AIS_TexturedShape::SetTextureRepeat (const Standard_Boolean theToRepeat,
110                                           const Standard_Real    theURepeat,
111                                           const Standard_Real    theVRepeat)
112 {
113   myToRepeat = theToRepeat;
114   myUVRepeat.SetCoord (theURepeat, theVRepeat);
115 }
116
117 //=======================================================================
118 //function : SetTextureMapOn
119 //purpose  :
120 //=======================================================================
121
122 void AIS_TexturedShape::SetTextureMapOn()
123 {
124   myToMapTexture = Standard_True;
125 }
126
127 //=======================================================================
128 //function : SetTextureMapOff
129 //purpose  :
130 //=======================================================================
131
132 void AIS_TexturedShape::SetTextureMapOff()
133 {
134   myToMapTexture = Standard_False;
135 }
136
137 //=======================================================================
138 //function : SetTextureOrigin
139 //purpose  :
140 //=======================================================================
141
142 void AIS_TexturedShape::SetTextureOrigin (const Standard_Boolean theToSetTextureOrigin,
143                                           const Standard_Real    theUOrigin,
144                                           const Standard_Real    theVOrigin)
145 {
146   myIsCustomOrigin = theToSetTextureOrigin;
147   myUVOrigin.SetCoord (theUOrigin, theVOrigin);
148 }
149
150 //=======================================================================
151 //function : SetTextureScale
152 //purpose  :
153 //=======================================================================
154
155 void AIS_TexturedShape::SetTextureScale (const Standard_Boolean theToSetTextureScale,
156                                          const Standard_Real    theScaleU,
157                                          const Standard_Real    theScaleV)
158 {
159   myToScale = theToSetTextureScale;
160   myUVScale.SetCoord (theScaleU, theScaleV);
161 }
162
163 //=======================================================================
164 //function : ShowTriangles
165 //purpose  :
166 //=======================================================================
167
168 void AIS_TexturedShape::ShowTriangles (const Standard_Boolean theToShowTriangles)
169 {
170   myToShowTriangles = theToShowTriangles;
171 }
172
173 //=======================================================================
174 //function : EnableTextureModulate
175 //purpose  :
176 //=======================================================================
177
178 void AIS_TexturedShape::EnableTextureModulate()
179 {
180   myModulate = Standard_True;
181 }
182
183 //=======================================================================
184 //function : DisableTextureModulate
185 //purpose  :
186 //=======================================================================
187
188 void AIS_TexturedShape::DisableTextureModulate()
189 {
190   myModulate = Standard_False;
191 }
192
193 //=======================================================================
194 //function : SetColor
195 //purpose  :
196 //=======================================================================
197
198 void AIS_TexturedShape::SetColor (const Quantity_Color& theColor)
199 {
200   AIS_Shape::SetColor (theColor);
201
202   for (Standard_Integer aPrsIt = 1; aPrsIt <= Presentations().Length(); ++aPrsIt)
203   {
204     const PrsMgr_ModedPresentation& aPrsModed = Presentations().Value (aPrsIt);
205
206     if (aPrsModed.Mode() != 3)
207       continue;
208
209     updateAttributes (aPrsModed.Presentation()->Presentation());
210   }
211 }
212
213 //=======================================================================
214 //function : UnsetColor
215 //purpose  :
216 //=======================================================================
217
218 void AIS_TexturedShape::UnsetColor()
219 {
220   AIS_Shape::UnsetColor();
221
222   for (Standard_Integer aPrsIt = 1; aPrsIt <= Presentations().Length(); ++aPrsIt)
223   {
224     const PrsMgr_ModedPresentation& aPrsModed = Presentations().Value (aPrsIt);
225
226     if (aPrsModed.Mode() != 3)
227       continue;
228     
229     Handle(Prs3d_Presentation) aPrs = aPrsModed.Presentation()->Presentation();
230     Handle(Graphic3d_Group)    aGroup = Prs3d_Root::CurrentGroup (aPrs);
231
232     Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->Link()->ShadingAspect()->Aspect();
233     Handle(Graphic3d_AspectLine3d)     aLineAsp  = myDrawer->Link()->LineAspect()->Aspect();
234     Quantity_Color aColor;
235     AIS_GraphicTool::GetInteriorColor (myDrawer->Link(), aColor);
236     anAreaAsp->SetInteriorColor (aColor);
237     // Check if aspect of given type is set for the group, 
238     // because setting aspect for group with no already set aspect
239     // can lead to loss of presentation data
240     if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
241     {
242       aGroup->SetGroupPrimitivesAspect (anAreaAsp);
243     }
244     if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_LINE))
245     {
246       aGroup->SetGroupPrimitivesAspect (aLineAsp);
247     }
248
249     updateAttributes (aPrs);
250   }
251 }
252
253 //=======================================================================
254 //function : SetMaterial
255 //purpose  : 
256 //=======================================================================
257
258 void AIS_TexturedShape::SetMaterial (const Graphic3d_MaterialAspect& theMat)
259 {
260   AIS_Shape::SetMaterial (theMat);
261
262   for (Standard_Integer aPrsIt = 1; aPrsIt <= Presentations().Length(); ++aPrsIt)
263   {
264     const PrsMgr_ModedPresentation& aPrsModed = Presentations().Value (aPrsIt);
265     
266     if (aPrsModed.Mode() != 3)
267       continue;
268     
269     updateAttributes (aPrsModed.Presentation()->Presentation());
270   }
271 }
272
273 //=======================================================================
274 //function : UnsetMaterial
275 //purpose  : 
276 //=======================================================================
277 void AIS_TexturedShape::UnsetMaterial()
278 {
279   AIS_Shape::UnsetMaterial();
280
281   for (Standard_Integer aPrsIt = 1; aPrsIt <= Presentations().Length(); ++aPrsIt)
282   {
283     const PrsMgr_ModedPresentation& aPrsModed = Presentations().Value (aPrsIt);
284
285     if (aPrsModed.Mode() != 3)
286       continue;
287
288     updateAttributes (aPrsModed.Presentation()->Presentation());
289   }
290 }
291
292 //=======================================================================
293 //function : UpdateAttributes
294 //purpose  :
295 //=======================================================================
296
297 void AIS_TexturedShape::UpdateAttributes()
298 {
299   updateAttributes (Presentation());
300 }
301
302 //=======================================================================
303 //function : updateAttributes
304 //purpose  :
305 //=======================================================================
306
307 void AIS_TexturedShape::updateAttributes (const Handle(Prs3d_Presentation)& thePrs)
308 {
309   myAspect = new Graphic3d_AspectFillArea3d (*myDrawer->ShadingAspect()->Aspect());
310   if (HasPolygonOffsets())
311   {
312     Standard_Integer aMode;
313     Standard_ShortReal aFactor, aUnits;
314     PolygonOffsets (aMode, aFactor, aUnits);
315     myAspect->SetPolygonOffsets (aMode, aFactor, aUnits);
316   }
317
318   Standard_Boolean hasTexture = Standard_False;
319   if (myToMapTexture)
320   {
321     TCollection_AsciiString aTextureDesc;
322     if (!myTexturePixMap.IsNull())
323     {
324       myTexture = new Graphic3d_Texture2Dmanual (myTexturePixMap);
325       aTextureDesc = " (custom image)";
326     }
327     else if (myPredefTexture != Graphic3d_NOT_2D_UNKNOWN)
328     {
329       myTexture = new Graphic3d_Texture2Dmanual (myPredefTexture);
330       aTextureDesc = TCollection_AsciiString(" (predefined texture ") + myTexture->GetId() + ")";
331     }
332     else
333     {
334       myTexture = new Graphic3d_Texture2Dmanual (myTextureFile.ToCString());
335       aTextureDesc = TCollection_AsciiString(" (") + myTextureFile + ")";
336     }
337
338     if (myModulate)
339     {
340       myTexture->EnableModulate();
341     }
342     else
343     {
344       myTexture->DisableModulate();
345     }
346
347     if (myTexture->IsDone())
348     {
349       hasTexture = Standard_True;
350     }
351     else
352     {
353       Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: texture can not be loaded ") + aTextureDesc, Message_Fail);
354     }
355   }
356
357   myAspect->SetTextureMap (myTexture);
358   if (hasTexture)
359   {
360     myAspect->SetTextureMapOn();
361   }
362   else
363   {
364     myAspect->SetTextureMapOff();
365   }
366
367   if (myToShowTriangles)
368   {
369     myAspect->SetEdgeOn();
370   }
371   else
372   {
373     myAspect->SetEdgeOff();
374   }
375
376   // Go through all groups to change fill aspect for all primitives
377   for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (thePrs->Groups()); aGroupIt.More(); aGroupIt.Next())
378   {
379     const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
380     if (!aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
381     {
382       continue;
383     }
384     aGroup->SetGroupPrimitivesAspect (myAspect);
385   }
386 }
387
388 //=======================================================================
389 //function : Compute
390 //purpose  :
391 //=======================================================================
392
393 void AIS_TexturedShape::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
394                                  const Handle(Prs3d_Presentation)&           thePrs,
395                                  const Standard_Integer                      theMode)
396 {
397   if (myshape.IsNull())
398   {
399     return;
400   }
401
402   if (myshape.ShapeType() > TopAbs_FACE && myshape.ShapeType() < TopAbs_SHAPE)
403   {
404     thePrs->SetVisual (Graphic3d_TOS_ALL);
405     thePrs->SetDisplayPriority (myshape.ShapeType() + 2);
406   }
407
408   if (myshape.ShapeType() == TopAbs_COMPOUND)
409   {
410     TopExp_Explorer anExplor (myshape, TopAbs_VERTEX);
411     if (!anExplor.More())
412     {
413       return;
414     }
415   }
416
417   if (IsInfinite())
418   {
419     thePrs->SetInfiniteState (Standard_True);
420   }
421
422   switch (theMode)
423   {
424     case AIS_WireFrame:
425     {
426       StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
427       StdPrs_WFShape::Add (thePrs, myshape, myDrawer);
428       break;
429     }
430     case AIS_Shaded:
431     case 3: // texture mapping on triangulation
432     {
433       StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (myshape, myDrawer, Standard_True);
434       if (myshape.ShapeType() > TopAbs_FACE)
435       {
436         StdPrs_WFShape::Add (thePrs, myshape, myDrawer);
437         break;
438       }
439
440       if (IsInfinite())
441       {
442         StdPrs_WFShape::Add (thePrs, myshape, myDrawer);
443         break;
444       }
445       try
446       {
447         OCC_CATCH_SIGNALS
448         if (theMode == AIS_Shaded)
449         {
450           StdPrs_ShadedShape::Add (thePrs, myshape, myDrawer);
451         }
452         else
453         {
454           StdPrs_ShadedShape::Add (thePrs, myshape, myDrawer,
455                                    Standard_True,
456                                    myIsCustomOrigin ? myUVOrigin : gp_Pnt2d (0.0, 0.0),
457                                    myUVRepeat,
458                                    myToScale        ? myUVScale  : gp_Pnt2d (1.0, 1.0));
459           updateAttributes (thePrs);
460         }
461       }
462       catch (Standard_Failure)
463       {
464 #ifdef OCCT_DEBUG
465         std::cout << "AIS_TexturedShape::Compute() in ShadingMode failed \n";
466 #endif
467         StdPrs_WFShape::Add (thePrs, myshape, myDrawer);
468       }
469       break;
470     }
471     case 2: // Bounding box
472     {
473       if (IsInfinite())
474       {
475         StdPrs_WFShape::Add (thePrs, myshape, myDrawer);
476       }
477       else
478       {
479         StdPrs_BndBox::Add (thePrs, BoundingBox(), myDrawer);
480       }
481       break;
482     }
483   }
484 }