]> SALOME platform Git repositories - modules/geom.git/blob - src/OBJECT/GEOM_Actor.cxx
Salome HOME
dde683ac84056c54879aa10406dfaff7432a99a7
[modules/geom.git] / src / OBJECT / GEOM_Actor.cxx
1 //  GEOM OBJECT : interactive object for Geometry entities visualization
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : GEOM_Actor.cxx
25 //  Author : Christophe ATTANASIO
26 //  Module : GEOM
27 //  $Header$
28
29 using namespace std;
30 /*!
31   \class GEOM_Actor GEOM_Actor.h
32   \brief This class allows to display an OpenCASCADE CAD model in a VTK viewer.
33 */
34
35 #include "GEOM_Actor.h"
36
37 // OpenCASCADE Includes
38 #include "GEOM_OCCReader.h"
39 #include <BRep_Tool.hxx>
40
41 //-------------------------------------------------------------
42 // Main methods
43 //-------------------------------------------------------------
44
45
46 GEOM_Actor* GEOM_Actor::New()
47 {
48   // First try to create the object from the vtkObjectFactory
49   vtkObject* ret = vtkObjectFactory::CreateInstance("GEOM_Actor");
50   if(ret)
51     {
52       return (GEOM_Actor*)ret;
53     }
54   // If the factory was unable to create the object, then create it here.
55   return new GEOM_Actor;
56 }
57
58
59 GEOM_Actor::GEOM_Actor()
60 {
61   this->Device = vtkActor::New();
62
63   this->WireframeMapper = NULL;
64   this->ShadingMapper = NULL;
65
66   this->ShadingProperty = NULL;
67   this->WireframeProperty = NULL;
68
69   this->deflection = 0;
70   myDisplayMode = 0; 
71
72   this->myIO = NULL;
73   this->myName = "";
74
75   this->HighlightProperty = NULL;
76   this->ishighlighted = false;
77
78   this->subshape = false;
79   this->myIsInfinite = false;
80 }
81
82 GEOM_Actor::~GEOM_Actor()
83 {
84   if (WireframeMapper != NULL)
85     WireframeMapper->Delete();
86   if (ShadingMapper != NULL)
87     ShadingMapper->Delete();
88   if (ShadingProperty != NULL)
89     ShadingProperty->Delete();
90   if (WireframeProperty != NULL)
91     WireframeProperty->Delete();
92   if (HighlightProperty != NULL)
93     HighlightProperty->Delete();
94 }
95
96
97 void GEOM_Actor::ShallowCopy(vtkProp *prop)
98 {
99   GEOM_Actor *f = GEOM_Actor::SafeDownCast(prop);
100   if ( f != NULL )
101     {
102       this->setInputShape(f->getTopo(),f->getDeflection(),f->getDisplayMode());
103       this->setName( f->getName() );
104       if ( f->hasIO() )
105         this->setIO( f->getIO() );
106       this->ShadingMapper = NULL;
107       this->WireframeMapper = NULL;
108     } else {
109       this->myIO = NULL;
110       this->myName = "";
111       this->ShadingMapper = NULL;
112       this->WireframeMapper = NULL;
113     }
114
115   // Now do superclass
116   this->SALOME_Actor::ShallowCopy(prop);
117 }
118
119 //-------------------------------------------------------------
120 // Set parameters
121 //-------------------------------------------------------------
122
123
124 void GEOM_Actor::setDisplayMode(int thenewmode) {
125   myDisplayMode = thenewmode;
126   if ( thenewmode >=1 ) {
127     if ((myShape.ShapeType() == TopAbs_WIRE) || 
128         (myShape.ShapeType() == TopAbs_EDGE) || 
129         (myShape.ShapeType() == TopAbs_VERTEX)) {
130       if ( !subshape )
131         CreateWireframeMapper();
132       else
133         return;
134     } else
135       CreateShadingMapper();
136   } else
137     CreateWireframeMapper();
138 }
139
140 void GEOM_Actor::setDeflection(double adef) {
141   deflection = adef;
142 }
143
144 void GEOM_Actor::setInputShape(const TopoDS_Shape& aShape,double adef,int imode) {
145   myShape = aShape;
146   deflection = adef;
147   setDisplayMode(imode);
148 }
149
150 //-------------------------------------------------------------
151 // Get parameters
152 //-------------------------------------------------------------
153
154 const TopoDS_Shape& GEOM_Actor::getTopo() {
155   return myShape;
156 }
157
158 double GEOM_Actor::getDeflection() {
159   return deflection;
160 }
161
162 void GEOM_Actor::SetWireframeProperty(vtkProperty* Prop) {
163   this->WireframeProperty = Prop;
164 }
165
166 void GEOM_Actor::SetShadingProperty(vtkProperty* Prop) {
167   this->ShadingProperty = Prop;
168 }
169
170
171 //-------------------------------------------------------------
172 // Mapper creating function
173 //-------------------------------------------------------------
174 void GEOM_Actor::CreateMapper(int theMode) {
175   this->myIsInfinite = myShape.Infinite();  
176   if(myShape.ShapeType() == TopAbs_VERTEX) {
177     gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(myShape));
178     this->SetPosition(aPnt.X(),aPnt.Y(),aPnt.Z());
179   }
180   GEOM_OCCReader* aread = GEOM_OCCReader::New();
181   aread->setTopo(myShape);
182   aread->setDisplayMode(theMode);
183   aread->GetOutput()->ReleaseDataFlagOn(); 
184     
185   vtkPolyDataMapper* aMapper = vtkPolyDataMapper::New();
186   if (theMode == 0) { 
187     aMapper->SetInput(aread->GetOutput());
188   } else {
189     vtkPolyDataNormals *normals = vtkPolyDataNormals::New();
190     normals->SetInput(aread->GetOutput());
191     aMapper->SetInput(normals->GetOutput());
192   }
193   aread->Delete();
194   this->SetMapper(theMode == 0? WireframeMapper = aMapper : ShadingMapper = aMapper);
195 }
196
197 void GEOM_Actor::CreateShadingMapper() {
198   CreateMapper(1);
199 }
200
201
202 void GEOM_Actor::CreateWireframeMapper() {
203   CreateMapper(0);
204 }
205
206 //-------------------------------------------------------------
207 // Render function
208 //-------------------------------------------------------------
209
210 void GEOM_Actor::Render(vtkRenderer *ren, vtkMapper *Mapper)
211 {
212   /* render the property */
213   if (!this->Property) {
214     // force creation of a property
215     this->GetProperty();
216     this->Property->SetInterpolation(1);
217     this->Property->SetRepresentationToSurface();
218     this->Property->SetAmbient(0.3);
219     this->Property->SetAmbientColor(0.88,0.86,0.2);
220     this->Property->SetDiffuseColor(0.99,0.7,0.21);
221     this->Property->SetSpecularColor(0.99,0.98,0.83);
222   }
223
224   if(!ishighlighted) {
225     if ( ispreselected ) 
226       this->Property = PreviewProperty;
227     else if(myDisplayMode >= 1) {
228       // SHADING
229       this->Property = ShadingProperty;
230     }
231     else {
232       this->Property = WireframeProperty;     
233     }
234
235   }
236
237   this->Property->Render(this, ren);
238   if (this->BackfaceProperty) {
239     this->BackfaceProperty->BackfaceRender(this, ren);
240     this->Device->SetBackfaceProperty(this->BackfaceProperty);
241   }
242   this->Device->SetProperty(this->Property);
243   // Store information on time it takes to render.
244   // We might want to estimate time from the number of polygons in mapper.
245   if(myDisplayMode >= 1) {
246     if((myShape.ShapeType() == TopAbs_WIRE) || 
247        (myShape.ShapeType() == TopAbs_EDGE) || 
248        (myShape.ShapeType() == TopAbs_VERTEX)) {
249       if ( !subshape ) {
250         if(WireframeMapper==NULL) CreateWireframeMapper();
251       } else
252         return;
253     }
254     else {
255       if(ShadingMapper==NULL) CreateShadingMapper();
256     }
257   }
258   else {
259     if(WireframeMapper==NULL) CreateWireframeMapper();
260   }
261   if(myShape.ShapeType() == TopAbs_VERTEX) {
262     if(ren){
263       //The parameter determine size of vertex actor relate to diagonal of RendererWindow
264       static float delta = 0.01;
265       float X1 = -1, Y1 = -1, Z1 = 0;
266       ren->ViewToWorld(X1,Y1,Z1);
267       float X2 = +1, Y2 = +1, Z2 = 0;
268       ren->ViewToWorld(X2,Y2,Z2);
269       Z2 = sqrt((X2-X1)*(X2-X1) + (Y2-Y1)*(Y2-Y1) + (Z2-Z1)*(Z2-Z1));
270       this->SetScale(Z2*delta);
271     }
272     vtkMatrix4x4 *aMatrix = vtkMatrix4x4::New();
273     this->GetMatrix(ren->GetActiveCamera(), aMatrix);
274     this->Device->SetUserMatrix(aMatrix);
275     this->Device->Render(ren,this->Mapper);
276     aMatrix->Delete();    
277   } else
278     this->Device->Render(ren, this->Mapper);
279  if(WireframeMapper!=NULL) this->EstimatedRenderTime = WireframeMapper->GetTimeToDraw(); 
280  else if(ShadingMapper!=NULL) this->EstimatedRenderTime = ShadingMapper->GetTimeToDraw();
281 }
282
283 // SubShape
284 void GEOM_Actor::SubShapeOn()
285 {
286   subshape = true;
287 }
288 void GEOM_Actor::SubShapeOff()
289 {
290   subshape = false;
291 }
292
293 //-------------------------------------------------------------
294 // Opacity methods
295 //-------------------------------------------------------------
296
297 void GEOM_Actor::SetOpacity(float opa)
298 {
299   //HighlightProperty->SetOpacity(opa);
300   SALOME_Actor::SetOpacity(opa);
301   ShadingProperty->SetOpacity(opa);
302 }
303
304 float GEOM_Actor::GetOpacity() {
305   return ShadingProperty->GetOpacity();
306 }
307
308 //-------------------------------------------------------------
309 // Color methods
310 //-------------------------------------------------------------
311 void GEOM_Actor::SetColor(float r,float g,float b) {
312   ShadingProperty->SetColor(r,g,b);  
313 }
314
315 void GEOM_Actor::GetColor(float& r,float& g,float& b) {
316   float color[3];
317    ShadingProperty->GetColor(color);
318    r = color[0];
319    g = color[1];
320    b = color[2];
321 }
322
323 //-------------------------------------------------------------
324 // Highlight methods
325 //-------------------------------------------------------------
326
327 void GEOM_Actor::highlight(Standard_Boolean highlight) {
328
329   if(highlight && !ishighlighted) {
330     ishighlighted=true;
331     // build highlight property is necessary
332     if(HighlightProperty==NULL) {
333       HighlightProperty = vtkProperty::New();
334       HighlightProperty->SetAmbient(0.5);
335       HighlightProperty->SetDiffuse(0.3);
336       HighlightProperty->SetSpecular(0.2);
337       HighlightProperty->SetRepresentationToSurface();
338       HighlightProperty->SetAmbientColor(1, 1, 1);
339       HighlightProperty->SetDiffuseColor(1, 1, 1);
340       HighlightProperty->SetSpecularColor(0.5, 0.5, 0.5); 
341     }
342       
343     this->Property = HighlightProperty;
344  
345   }
346   else if (!highlight) {
347     if(ishighlighted) {
348       ishighlighted=false;
349       if(myDisplayMode==1) {
350         //unhilight in shading
351         this->Property = ShadingProperty;
352       }
353       else {
354         //unhilight in wireframe
355         this->Property = WireframeProperty;
356       }
357     }
358   }
359 }
360
361 bool GEOM_Actor::hasHighlight()
362 {
363   return true;
364 }
365
366 void GEOM_Actor::SetHighlightProperty(vtkProperty* Prop) {
367   this->HighlightProperty = Prop;
368 }
369
370
371 void GEOM_Actor::ReleaseGraphicsResources(vtkWindow *renWin) 
372 {
373   vtkActor::ReleaseGraphicsResources(renWin);
374   
375   // broadcast the message down to the individual LOD mappers
376
377   if(WireframeMapper) this->WireframeMapper->ReleaseGraphicsResources(renWin);
378   if(ShadingMapper) this->ShadingMapper->ReleaseGraphicsResources(renWin);
379 }
380
381
382 // Copy the follower's composite 4x4 matrix into the matrix provided.
383 void GEOM_Actor::GetMatrix(vtkCamera* theCam, vtkMatrix4x4 *result)
384 {
385   double *pos, *vup;
386   double Rx[3], Ry[3], Rz[3], p1[3];
387   vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
388   int i;
389   double distance;
390   
391   this->GetOrientation();
392   this->Transform->Push();  
393   this->Transform->PostMultiply();  
394   this->Transform->Identity();
395
396   // apply user defined matrix last if there is one 
397   if (this->UserMatrix)
398     {
399     this->Transform->Concatenate(this->UserMatrix);
400     }
401
402   this->Transform->Translate(-this->Origin[0],
403                              -this->Origin[1],
404                              -this->Origin[2]);
405   // scale
406   this->Transform->Scale(this->Scale[0],
407                          this->Scale[1],
408                          this->Scale[2]);
409   
410   // rotate
411   this->Transform->RotateY(this->Orientation[1]);
412   this->Transform->RotateX(this->Orientation[0]);
413   this->Transform->RotateZ(this->Orientation[2]);
414
415   if (theCam)
416     {
417     // do the rotation
418     // first rotate y 
419     pos = theCam->GetPosition();
420     vup = theCam->GetViewUp();
421
422     if (theCam->GetParallelProjection())
423       {
424       theCam->GetDirectionOfProjection(Rz);
425       }
426     else
427       {
428       distance = sqrt(
429         (pos[0] - this->Position[0])*(pos[0] - this->Position[0]) +
430         (pos[1] - this->Position[1])*(pos[1] - this->Position[1]) +
431         (pos[2] - this->Position[2])*(pos[2] - this->Position[2]));
432       for (i = 0; i < 3; i++)
433         {
434         Rz[i] = (pos[i] - this->Position[i])/distance;
435         }
436       }
437   
438     vtkMath::Cross(vup,Rz,Rx);
439     vtkMath::Normalize(Rx);
440     vtkMath::Cross(Rz,Rx,Ry);
441     
442     matrix->Element[0][0] = Rx[0];
443     matrix->Element[1][0] = Rx[1];
444     matrix->Element[2][0] = Rx[2];
445     matrix->Element[0][1] = Ry[0];
446     matrix->Element[1][1] = Ry[1];
447     matrix->Element[2][1] = Ry[2];
448     matrix->Element[0][2] = Rz[0];
449     matrix->Element[1][2] = Rz[1];
450     matrix->Element[2][2] = Rz[2];
451     
452     this->Transform->Concatenate(matrix);
453     }
454   
455   // translate to projection reference point PRP
456   // this is the camera's position blasted through
457   // the current matrix
458   p1[0] = this->Origin[0] + this->Position[0];
459   p1[1] = this->Origin[1] + this->Position[1];
460   p1[2] = this->Origin[2] + this->Position[2];
461
462   this->Transform->Translate(p1[0],p1[1],p1[2]);
463   this->Transform->GetMatrix(result);
464   
465   matrix->Delete();
466   this->Transform->Pop();  
467 }