0023804: Visualization - unexpected color modulation during texture mapping
[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_Drawer.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 <Precision.hxx>
27 #include <Prs3d_Presentation.hxx>
28 #include <Prs3d_Root.hxx>
29 #include <Prs3d_ShadingAspect.hxx>
30 #include <PrsMgr_PresentationManager3d.hxx>
31 #include <Standard_ErrorHandler.hxx>
32 #include <StdPrs_ShadedShape.hxx>
33 #include <StdPrs_ToolShadedShape.hxx>
34 #include <StdPrs_WFDeflectionShape.hxx>
35 #include <StdPrs_WFShape.hxx>
36 #include <TopExp_Explorer.hxx>
37
38 IMPLEMENT_STANDARD_HANDLE (AIS_TexturedShape, AIS_Shape)
39 IMPLEMENT_STANDARD_RTTIEXT(AIS_TexturedShape, AIS_Shape)
40
41 //=======================================================================
42 //function : AIS_TexturedShape
43 //purpose  :
44 //=======================================================================
45 AIS_TexturedShape::AIS_TexturedShape (const TopoDS_Shape& theShape)
46 : AIS_Shape         (theShape),
47   myPredefTexture   (Graphic3d_NameOfTexture2D(0)),
48   myToMapTexture    (Standard_True),
49   myModulate        (Standard_True),
50   myUVOrigin        (0.0, 0.0),
51   myIsCustomOrigin  (Standard_True),
52   myUVRepeat        (1.0, 1.0),
53   myToRepeat        (Standard_True),
54   myUVScale         (1.0, 1.0),
55   myToScale         (Standard_True),
56   myToShowTriangles (Standard_False)
57 {
58 }
59
60 //=======================================================================
61 //function : SetTextureFileName
62 //purpose  :
63 //=======================================================================
64 void AIS_TexturedShape::SetTextureFileName (const TCollection_AsciiString& theTextureFileName)
65 {
66   myTexturePixMap.Nullify();
67
68   if (theTextureFileName.IsIntegerValue())
69   {
70     const Standard_Integer aValue = theTextureFileName.IntegerValue();
71     if (aValue < Graphic3d_Texture2D::NumberOfTextures()
72      && aValue >= 0)
73     {
74       myPredefTexture = Graphic3d_NameOfTexture2D (aValue);
75     }
76     else
77     {
78       std::cout << "Texture " << theTextureFileName << " doesn't exist\n";
79       std::cout << "Using Texture 0 instead ...\n";
80       myPredefTexture = Graphic3d_NameOfTexture2D (0);
81     }
82     myTextureFile = "";
83   }
84   else
85   {
86     myTextureFile   = theTextureFileName;
87     myPredefTexture = Graphic3d_NOT_2D_UNKNOWN;
88   }
89 }
90
91 //=======================================================================
92 //function : SetTexturePixMap
93 //purpose  :
94 //=======================================================================
95 void AIS_TexturedShape::SetTexturePixMap (const Handle(Image_PixMap)& theTexturePixMap)
96 {
97   myTextureFile = "";
98   myPredefTexture = Graphic3d_NOT_2D_UNKNOWN;
99   myTexturePixMap = theTexturePixMap;
100 }
101
102 //=======================================================================
103 //function : SetTextureRepeat
104 //purpose  :
105 //=======================================================================
106
107 void AIS_TexturedShape::SetTextureRepeat (const Standard_Boolean theToRepeat,
108                                           const Standard_Real    theURepeat,
109                                           const Standard_Real    theVRepeat)
110 {
111   myToRepeat = theToRepeat;
112   myUVRepeat.SetCoord (theURepeat, theVRepeat);
113 }
114
115 //=======================================================================
116 //function : SetTextureMapOn
117 //purpose  :
118 //=======================================================================
119
120 void AIS_TexturedShape::SetTextureMapOn()
121 {
122   myToMapTexture = Standard_True;
123 }
124
125 //=======================================================================
126 //function : SetTextureMapOff
127 //purpose  :
128 //=======================================================================
129
130 void AIS_TexturedShape::SetTextureMapOff()
131 {
132   myToMapTexture = Standard_False;
133 }
134
135 //=======================================================================
136 //function : SetTextureOrigin
137 //purpose  :
138 //=======================================================================
139
140 void AIS_TexturedShape::SetTextureOrigin (const Standard_Boolean theToSetTextureOrigin,
141                                           const Standard_Real    theUOrigin,
142                                           const Standard_Real    theVOrigin)
143 {
144   myIsCustomOrigin = theToSetTextureOrigin;
145   myUVOrigin.SetCoord (theUOrigin, theVOrigin);
146 }
147
148 //=======================================================================
149 //function : SetTextureScale
150 //purpose  :
151 //=======================================================================
152
153 void AIS_TexturedShape::SetTextureScale (const Standard_Boolean theToSetTextureScale,
154                                          const Standard_Real    theScaleU,
155                                          const Standard_Real    theScaleV)
156 {
157   myToScale = theToSetTextureScale;
158   myUVScale.SetCoord (theScaleU, theScaleV);
159 }
160
161 //=======================================================================
162 //function : ShowTriangles
163 //purpose  :
164 //=======================================================================
165
166 void AIS_TexturedShape::ShowTriangles (const Standard_Boolean theToShowTriangles)
167 {
168   myToShowTriangles = theToShowTriangles;
169 }
170
171 //=======================================================================
172 //function : EnableTextureModulate
173 //purpose  :
174 //=======================================================================
175
176 void AIS_TexturedShape::EnableTextureModulate()
177 {
178   myModulate = Standard_True;
179 }
180
181 //=======================================================================
182 //function : DisableTextureModulate
183 //purpose  :
184 //=======================================================================
185
186 void AIS_TexturedShape::DisableTextureModulate()
187 {
188   myModulate = Standard_False;
189 }
190
191 //=======================================================================
192 //function : SetColor
193 //purpose  :
194 //=======================================================================
195
196 void AIS_TexturedShape::SetColor (const Quantity_Color& theColor)
197 {
198   AIS_Shape::SetColor (theColor);
199
200   if (!GetContext().IsNull())
201   {
202     if (GetContext()->MainPrsMgr()->HasPresentation (this, 3))
203     {
204       updateAttributes (GetContext()->MainPrsMgr()->Presentation (this, 3)->Presentation());
205     }
206   }
207 }
208
209 //=======================================================================
210 //function : UpdateAttributes
211 //purpose  :
212 //=======================================================================
213
214 void AIS_TexturedShape::UpdateAttributes()
215 {
216   updateAttributes (Presentation());
217 }
218
219 //=======================================================================
220 //function : updateAttributes
221 //purpose  :
222 //=======================================================================
223
224 void AIS_TexturedShape::updateAttributes (const Handle(Prs3d_Presentation)& thePrs)
225 {
226   myAspect = new Graphic3d_AspectFillArea3d (*myDrawer->ShadingAspect()->Aspect());
227   if (HasPolygonOffsets())
228   {
229     // Issue 23115: copy polygon offset settings passed through myDrawer
230     Standard_Integer aMode;
231     Standard_ShortReal aFactor, aUnits;
232     PolygonOffsets (aMode, aFactor, aUnits);
233     myAspect->SetPolygonOffsets (aMode, aFactor, aUnits);
234   }
235
236   if (!myToMapTexture)
237   {
238     myAspect->SetTextureMapOff();
239     return;
240   }
241
242   if (!myTexturePixMap.IsNull())
243   {
244     myTexture = new Graphic3d_Texture2Dmanual (myTexturePixMap);
245   }
246   else if (myPredefTexture != Graphic3d_NOT_2D_UNKNOWN)
247   {
248     myTexture = new Graphic3d_Texture2Dmanual (myPredefTexture);
249   }
250   else
251   {
252     myTexture = new Graphic3d_Texture2Dmanual (myTextureFile.ToCString());
253   }
254
255   myAspect->SetTextureMapOn();
256   myAspect->SetTextureMap (myTexture);
257   if (!myTexture->IsDone())
258   {
259     std::cout << "An error occurred while building texture\n";
260     myAspect->SetTextureMapOff();
261     return;
262   }
263
264   if (myModulate)
265     myTexture->EnableModulate();
266   else
267     myTexture->DisableModulate();
268
269   if (myToShowTriangles)
270     myAspect->SetEdgeOn();
271   else
272     myAspect->SetEdgeOff();
273
274   // manage back face culling in consistent way (as in StdPrs_ShadedShape::Add())
275   if (StdPrs_ToolShadedShape::IsClosed (myshape))
276   {
277     myAspect->SuppressBackFace();
278   }
279   else
280   {
281     myAspect->AllowBackFace();
282   }
283
284   if (!thePrs.IsNull())
285   {
286     Prs3d_Root::CurrentGroup (thePrs)->SetGroupPrimitivesAspect (myAspect);
287   }
288 }
289
290 //=======================================================================
291 //function : Compute
292 //purpose  :
293 //=======================================================================
294
295 void AIS_TexturedShape::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
296                                  const Handle(Prs3d_Presentation)&           thePrs,
297                                  const Standard_Integer                      theMode)
298 {
299   thePrs->Clear();
300
301   if (myshape.IsNull())
302   {
303     return;
304   }
305
306   if (myshape.ShapeType() > TopAbs_FACE && myshape.ShapeType() < TopAbs_SHAPE)
307   {
308     thePrs->SetVisual (Graphic3d_TOS_ALL);
309     thePrs->SetDisplayPriority (myshape.ShapeType() + 2);
310   }
311
312   if (myshape.ShapeType() == TopAbs_COMPOUND)
313   {
314     TopExp_Explorer anExplor (myshape, TopAbs_VERTEX);
315     if (!anExplor.More())
316     {
317       return;
318     }
319   }
320
321   if (IsInfinite())
322   {
323     thePrs->SetInfiniteState (Standard_True);
324   }
325
326   switch (theMode)
327   {
328     case AIS_WireFrame:
329     {
330       StdPrs_WFDeflectionShape::Add (thePrs, myshape, myDrawer);
331       break;
332     }
333     case AIS_Shaded:
334     {
335       Standard_Real prevangle;
336       Standard_Real newangle;
337       Standard_Real prevcoeff;
338       Standard_Real newcoeff;
339
340       Standard_Boolean isOwnDeviationAngle = OwnDeviationAngle(newangle,prevangle);
341       Standard_Boolean isOwnDeviationCoefficient = OwnDeviationCoefficient(newcoeff,prevcoeff);
342       if (((Abs (newangle - prevangle) > Precision::Angular()) && isOwnDeviationAngle) ||
343           ((Abs (newcoeff - prevcoeff) > Precision::Confusion()) && isOwnDeviationCoefficient)) {
344         BRepTools::Clean (myshape);
345       }
346       if (myshape.ShapeType() > TopAbs_FACE)
347       {
348         StdPrs_WFDeflectionShape::Add (thePrs, myshape, myDrawer);
349         break;
350       }
351       myDrawer->SetShadingAspectGlobal (Standard_False);
352       if (IsInfinite())
353       {
354         StdPrs_WFDeflectionShape::Add (thePrs, myshape, myDrawer);
355         break;
356       }
357       try
358       {
359         OCC_CATCH_SIGNALS
360         StdPrs_ShadedShape::Add (thePrs, myshape, myDrawer);
361       }
362       catch (Standard_Failure)
363       {
364         std::cout << "AIS_TexturedShape::Compute() in ShadingMode failed \n";
365         StdPrs_WFShape::Add (thePrs, myshape, myDrawer);
366       }
367       break;
368     }
369     case 2: // Bounding box
370     {
371       if (IsInfinite())
372       {
373         StdPrs_WFDeflectionShape::Add (thePrs, myshape, myDrawer);
374       }
375       else
376       {
377         AIS_Shape::DisplayBox (thePrs, BoundingBox(), myDrawer);
378       }
379       break;
380     }
381     case 3: // texture mapping on triangulation
382     {
383       BRepTools::Clean  (myshape);
384       BRepTools::Update (myshape);
385       try
386       {
387         OCC_CATCH_SIGNALS
388         StdPrs_ShadedShape::Add (thePrs, myshape, myDrawer,
389                                  Standard_True,
390                                  myIsCustomOrigin ? myUVOrigin : gp_Pnt2d (0.0, 0.0),
391                                  myUVRepeat,
392                                  myToScale        ? myUVScale  : gp_Pnt2d (1.0, 1.0));
393
394         updateAttributes (thePrs);
395       }
396       catch (Standard_Failure)
397       {
398         std::cout << "AIS_TexturedShape::Compute() in ShadingMode failed\n";
399         StdPrs_WFShape::Add (thePrs, myshape, myDrawer);
400       }
401       break;
402     }
403   }
404 }