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