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