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