0023743: AIS_Triangulation crashes if Poly_Triangulation has no normals
[occt.git] / src / AIS / AIS_Triangulation.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18 #include <AIS_Drawer.hxx>
19 #include <AIS_Triangulation.hxx>
20 #include <AIS_InteractiveObject.hxx>
21 #include <Standard_DefineHandle.hxx>
22 #include <Poly_Array1OfTriangle.hxx>
23 #include <Poly_Triangulation.hxx>
24 #include <Prs3d_Root.hxx>
25 #include <Prs3d_ShadingAspect.hxx>
26 #include <TShort_Array1OfShortReal.hxx>
27 #include <TColgp_Array1OfPnt.hxx>
28 #include <TColStd_HArray1OfInteger.hxx>
29 #include <TShort_HArray1OfShortReal.hxx>
30 #include <Graphic3d_Group.hxx>
31 #include <Graphic3d_AspectFillArea3d.hxx>
32 #include <Graphic3d_ArrayOfTriangles.hxx>
33
34
35 IMPLEMENT_STANDARD_HANDLE(AIS_Triangulation, AIS_InteractiveObject)
36 IMPLEMENT_STANDARD_RTTIEXT(AIS_Triangulation, AIS_InteractiveObject)
37
38 AIS_Triangulation::AIS_Triangulation(const Handle(Poly_Triangulation)& Triangulation)
39 {
40   myTriangulation = Triangulation;
41   myNbNodes       = Triangulation->NbNodes();
42   myNbTriangles   = Triangulation->NbTriangles();
43   myFlagColor     = 0;
44 }
45
46 //=======================================================================
47 //function : Compute
48 //purpose  :
49 //=======================================================================
50 void AIS_Triangulation::Compute(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager,
51                                 const Handle(Prs3d_Presentation)& aPresentation,
52                                 const Standard_Integer aMode)
53 {
54   switch (aMode) 
55   {
56     case 0:
57       const TColgp_Array1OfPnt& nodes = myTriangulation->Nodes();             //Nodes
58       const Poly_Array1OfTriangle& triangles = myTriangulation->Triangles();  //Triangle
59
60       Standard_Boolean hasVNormals = myTriangulation->HasNormals();
61       Standard_Boolean hasVColors  = (myFlagColor == 1);
62
63       Handle(Graphic3d_ArrayOfTriangles) anArray =
64          new Graphic3d_ArrayOfTriangles ( myNbNodes,        //maxVertexs
65                                           myNbTriangles * 3,//maxEdges
66                                           hasVNormals,      //hasVNormals
67                                           hasVColors,       //hasVColors
68                                           Standard_False,   //hasTexels
69                                           Standard_True     //hasEdgeInfos
70                                          );
71       Handle(Graphic3d_Group) TheGroup = Prs3d_Root::CurrentGroup(aPresentation);
72       Handle(Graphic3d_AspectFillArea3d) aspect = myDrawer->ShadingAspect()->Aspect();
73
74       Standard_Integer i;
75       Standard_Integer j;
76
77       Standard_Real ambient = aspect->FrontMaterial().Ambient();
78       if (hasVNormals)
79       {
80         const TShort_Array1OfShortReal& normals = myTriangulation->Normals();
81         if (hasVColors)
82         {
83           const TColStd_Array1OfInteger& colors = myColor->Array1();
84           for ( i = nodes.Lower(); i <= nodes.Upper(); i++ )
85           {
86             j = (i - nodes.Lower()) * 3;
87             anArray->AddVertex(nodes(i), AttenuateColor(colors(i), ambient));
88             anArray->SetVertexNormal(i, normals(j+1), normals(j+2), normals(j+3));
89           }
90         }
91         else // !hasVColors
92         {
93           for ( i = nodes.Lower(); i <= nodes.Upper(); i++ )
94           {
95             j = (i - nodes.Lower()) * 3;
96             anArray->AddVertex(nodes(i));
97             anArray->SetVertexNormal(i, normals(j+1), normals(j+2), normals(j+3));
98           }
99         }
100       }
101       else // !hasVNormals
102       {
103         if (hasVColors)
104         {
105           const TColStd_Array1OfInteger& colors = myColor->Array1();
106           for ( i = nodes.Lower(); i <= nodes.Upper(); i++ )
107           {
108             anArray->AddVertex(nodes(i), AttenuateColor(colors(i), ambient));
109           }
110         }
111         else // !hasVColors
112         {
113           for ( i = nodes.Lower(); i <= nodes.Upper(); i++ )
114           {
115             anArray->AddVertex(nodes(i));
116           }
117         }
118       }
119
120       Standard_Integer indexTriangle[3] = {0,0,0};
121       for ( i = triangles.Lower(); i<= triangles.Upper(); i++ ) {
122         triangles(i).Get(indexTriangle[0], indexTriangle[1], indexTriangle[2]);
123         anArray->AddEdge(indexTriangle[0]);
124         anArray->AddEdge(indexTriangle[1]);
125         anArray->AddEdge(indexTriangle[2]);
126       }
127       TheGroup->SetPrimitivesAspect(aspect);
128       TheGroup->AddPrimitiveArray(anArray);
129       break;
130   }
131 }
132
133 //=======================================================================
134 //function : ComputeSelection
135 //purpose  : 
136 //=======================================================================
137 void AIS_Triangulation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
138                                          const Standard_Integer /*aMode*/)
139 {
140
141 }
142
143 //=======================================================================
144 //function : SetColor
145 //purpose  : Set the color for each node.
146 //           Each 32-bit color is Alpha << 24 + Blue << 16 + Green << 8 + Red
147 //           Order of color components is essential for further usage by OpenGL
148 //=======================================================================
149 void AIS_Triangulation::SetColors(const Handle(TColStd_HArray1OfInteger)& aColor)
150 {
151   myFlagColor = 1;
152   myColor = aColor;
153 }
154
155 //=======================================================================
156 //function : GetColor
157 //purpose  : Get the color for each node.
158 //           Each 32-bit color is Alpha << 24 + Blue << 16 + Green << 8 + Red
159 //           Order of color components is essential for further usage by OpenGL
160 //=======================================================================
161
162 Handle(TColStd_HArray1OfInteger) AIS_Triangulation::GetColors() const
163 {
164   return myColor;
165 }
166
167
168 //=======================================================================
169 //function : SetTriangulation
170 //purpose  : 
171 //=======================================================================
172 void AIS_Triangulation::SetTriangulation(const Handle(Poly_Triangulation)& aTriangulation)
173 {
174   myTriangulation = aTriangulation;
175 }
176
177 //=======================================================================
178 //function : GetTriangulation
179 //purpose  : 
180 //=======================================================================
181 Handle(Poly_Triangulation) AIS_Triangulation::GetTriangulation() const{
182   return myTriangulation;
183 }
184
185 //=======================================================================
186 //function : AttenuateColor
187 //purpose  : Attenuates 32-bit color by a given attenuation factor (0...1):
188 //           aColor = Alpha << 24 + Blue << 16 + Green << 8 + Red
189 //           All color components are multiplied by aComponent, the result is then packed again as 32-bit integer.
190 //           Color attenuation is applied to the vertex colors in order to have correct visual result 
191 //           after glColorMaterial(GL_AMBIENT_AND_DIFFUSE). Without it, colors look unnatural and flat.
192 //=======================================================================
193
194 Standard_Integer AIS_Triangulation::AttenuateColor( const Standard_Integer aColor,
195                                                     const Standard_Real aComposition)
196 {
197   Standard_Integer  red,
198                     green,
199                     blue,
200                     alpha;
201
202   alpha = aColor&0xff000000;
203   alpha >>= 24;
204
205   blue = aColor&0x00ff0000;
206   blue >>= 16;
207
208   green = aColor&0x0000ff00;
209   green >>= 8;
210
211   red = aColor&0x000000ff;
212   red >>= 0; 
213
214   red   = (Standard_Integer)(aComposition * red);
215   green = (Standard_Integer)(aComposition * green);
216   blue  = (Standard_Integer)(aComposition * blue);
217
218   Standard_Integer  color;
219   color = red;
220   color += green << 8;
221   color += blue  << 16; 
222   color += alpha << 24;
223   return color;
224 }
225