mirror of
https://git.salome-platform.org/gitpub/modules/geom.git
synced 2024-11-13 17:18:36 +05:00
465 lines
12 KiB
C++
465 lines
12 KiB
C++
// GEOM OBJECT : interactive object for Geometry entities visualization
|
|
//
|
|
// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
|
|
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
|
|
//
|
|
//
|
|
//
|
|
// File : GEOM_Actor.cxx
|
|
// Author : Christophe ATTANASIO
|
|
// Module : GEOM
|
|
// $Header$
|
|
|
|
using namespace std;
|
|
/*!
|
|
\class GEOM_Actor GEOM_Actor.h
|
|
\brief This class allows to display an OpenCASCADE CAD model in a VTK viewer.
|
|
*/
|
|
|
|
#include "GEOM_Actor.h"
|
|
|
|
// OpenCASCADE Includes
|
|
#include "GEOM_OCCReader.h"
|
|
#include <BRep_Tool.hxx>
|
|
|
|
//-------------------------------------------------------------
|
|
// Main methods
|
|
//-------------------------------------------------------------
|
|
|
|
|
|
GEOM_Actor* GEOM_Actor::New()
|
|
{
|
|
// First try to create the object from the vtkObjectFactory
|
|
vtkObject* ret = vtkObjectFactory::CreateInstance("GEOM_Actor");
|
|
if(ret)
|
|
{
|
|
return (GEOM_Actor*)ret;
|
|
}
|
|
// If the factory was unable to create the object, then create it here.
|
|
return new GEOM_Actor;
|
|
}
|
|
|
|
|
|
GEOM_Actor::GEOM_Actor()
|
|
{
|
|
this->Device = vtkActor::New();
|
|
|
|
this->WireframeMapper = NULL;
|
|
this->ShadingMapper = NULL;
|
|
|
|
this->ShadingProperty = NULL;
|
|
this->WireframeProperty = NULL;
|
|
|
|
this->deflection = 0;
|
|
myDisplayMode = 0;
|
|
|
|
this->myIO = NULL;
|
|
this->myName = "";
|
|
|
|
this->HighlightProperty = NULL;
|
|
this->ishighlighted = false;
|
|
|
|
this->subshape = false;
|
|
}
|
|
|
|
GEOM_Actor::~GEOM_Actor()
|
|
{
|
|
if (WireframeMapper != NULL)
|
|
WireframeMapper->Delete();
|
|
if (ShadingMapper != NULL)
|
|
ShadingMapper->Delete();
|
|
if (ShadingProperty != NULL)
|
|
ShadingProperty->Delete();
|
|
if (WireframeProperty != NULL)
|
|
WireframeProperty->Delete();
|
|
if (HighlightProperty != NULL)
|
|
HighlightProperty->Delete();
|
|
}
|
|
|
|
|
|
void GEOM_Actor::ShallowCopy(vtkProp *prop)
|
|
{
|
|
GEOM_Actor *f = GEOM_Actor::SafeDownCast(prop);
|
|
if ( f != NULL )
|
|
{
|
|
this->setInputShape(f->getTopo(),f->getDeflection(),f->getDisplayMode());
|
|
this->setName( f->getName() );
|
|
if ( f->hasIO() )
|
|
this->setIO( f->getIO() );
|
|
this->ShadingMapper = NULL;
|
|
this->WireframeMapper = NULL;
|
|
} else {
|
|
this->myIO = NULL;
|
|
this->myName = "";
|
|
this->ShadingMapper = NULL;
|
|
this->WireframeMapper = NULL;
|
|
}
|
|
|
|
// Now do superclass
|
|
this->SALOME_Actor::ShallowCopy(prop);
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Set parameters
|
|
//-------------------------------------------------------------
|
|
|
|
|
|
void GEOM_Actor::setDisplayMode(int thenewmode) {
|
|
myDisplayMode = thenewmode;
|
|
if ( thenewmode >=1 ) {
|
|
if ((myShape.ShapeType() == TopAbs_WIRE) ||
|
|
(myShape.ShapeType() == TopAbs_EDGE) ||
|
|
(myShape.ShapeType() == TopAbs_VERTEX)) {
|
|
if ( !subshape )
|
|
CreateWireframeMapper();
|
|
else
|
|
return;
|
|
} else
|
|
CreateShadingMapper();
|
|
} else
|
|
CreateWireframeMapper();
|
|
}
|
|
|
|
void GEOM_Actor::setDeflection(double adef) {
|
|
deflection = adef;
|
|
}
|
|
|
|
void GEOM_Actor::setInputShape(const TopoDS_Shape& aShape,double adef,int imode) {
|
|
myShape = aShape;
|
|
deflection = adef;
|
|
setDisplayMode(imode);
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Get parameters
|
|
//-------------------------------------------------------------
|
|
|
|
const TopoDS_Shape& GEOM_Actor::getTopo() {
|
|
return myShape;
|
|
}
|
|
|
|
double GEOM_Actor::getDeflection() {
|
|
return deflection;
|
|
}
|
|
|
|
void GEOM_Actor::SetWireframeProperty(vtkProperty* Prop) {
|
|
this->WireframeProperty = Prop;
|
|
}
|
|
|
|
void GEOM_Actor::SetShadingProperty(vtkProperty* Prop) {
|
|
this->ShadingProperty = Prop;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Mapper creating function
|
|
//-------------------------------------------------------------
|
|
void GEOM_Actor::CreateMapper(int theMode) {
|
|
if(myShape.ShapeType() == TopAbs_VERTEX) {
|
|
gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(myShape));
|
|
this->SetPosition(aPnt.X(),aPnt.Y(),aPnt.Z());
|
|
}
|
|
GEOM_OCCReader* aread = GEOM_OCCReader::New();
|
|
aread->setTopo(myShape);
|
|
aread->setDisplayMode(theMode);
|
|
aread->GetOutput()->ReleaseDataFlagOn();
|
|
|
|
vtkPolyDataMapper* aMapper = vtkPolyDataMapper::New();
|
|
if (theMode == 0) {
|
|
aMapper->SetInput(aread->GetOutput());
|
|
} else {
|
|
vtkPolyDataNormals *normals = vtkPolyDataNormals::New();
|
|
normals->SetInput(aread->GetOutput());
|
|
aMapper->SetInput(normals->GetOutput());
|
|
}
|
|
aread->Delete();
|
|
this->SetMapper(theMode == 0? WireframeMapper = aMapper : ShadingMapper = aMapper);
|
|
}
|
|
|
|
void GEOM_Actor::CreateShadingMapper() {
|
|
CreateMapper(1);
|
|
}
|
|
|
|
|
|
void GEOM_Actor::CreateWireframeMapper() {
|
|
CreateMapper(0);
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Render function
|
|
//-------------------------------------------------------------
|
|
|
|
void GEOM_Actor::Render(vtkRenderer *ren, vtkMapper *Mapper)
|
|
{
|
|
/* render the property */
|
|
if (!this->Property) {
|
|
// force creation of a property
|
|
this->GetProperty();
|
|
this->Property->SetInterpolation(1);
|
|
this->Property->SetRepresentationToSurface();
|
|
this->Property->SetAmbient(0.3);
|
|
this->Property->SetAmbientColor(0.88,0.86,0.2);
|
|
this->Property->SetDiffuseColor(0.99,0.7,0.21);
|
|
this->Property->SetSpecularColor(0.99,0.98,0.83);
|
|
}
|
|
|
|
if(!ishighlighted) {
|
|
if(myDisplayMode >= 1) {
|
|
// SHADING
|
|
this->Property = ShadingProperty;
|
|
}
|
|
else {
|
|
this->Property = WireframeProperty;
|
|
}
|
|
|
|
if ( ispreselected )
|
|
this->Property = PreviewProperty;
|
|
}
|
|
|
|
this->Property->Render(this, ren);
|
|
if (this->BackfaceProperty) {
|
|
this->BackfaceProperty->BackfaceRender(this, ren);
|
|
this->Device->SetBackfaceProperty(this->BackfaceProperty);
|
|
}
|
|
this->Device->SetProperty(this->Property);
|
|
// Store information on time it takes to render.
|
|
// We might want to estimate time from the number of polygons in mapper.
|
|
if(myDisplayMode >= 1) {
|
|
if((myShape.ShapeType() == TopAbs_WIRE) ||
|
|
(myShape.ShapeType() == TopAbs_EDGE) ||
|
|
(myShape.ShapeType() == TopAbs_VERTEX)) {
|
|
if ( !subshape ) {
|
|
if(WireframeMapper==NULL) CreateWireframeMapper();
|
|
} else
|
|
return;
|
|
}
|
|
else {
|
|
if(ShadingMapper==NULL) CreateShadingMapper();
|
|
}
|
|
}
|
|
else {
|
|
if(WireframeMapper==NULL) CreateWireframeMapper();
|
|
}
|
|
if(myShape.ShapeType() == TopAbs_VERTEX) {
|
|
if(ren){
|
|
//The parameter determine size of vertex actor relate to diagonal of RendererWindow
|
|
static float delta = 0.01;
|
|
float X1 = -1, Y1 = -1, Z1 = 0;
|
|
ren->ViewToWorld(X1,Y1,Z1);
|
|
float X2 = +1, Y2 = +1, Z2 = 0;
|
|
ren->ViewToWorld(X2,Y2,Z2);
|
|
Z2 = sqrt((X2-X1)*(X2-X1) + (Y2-Y1)*(Y2-Y1) + (Z2-Z1)*(Z2-Z1));
|
|
this->SetScale(Z2*delta);
|
|
}
|
|
vtkMatrix4x4 *aMatrix = vtkMatrix4x4::New();
|
|
this->GetMatrix(ren->GetActiveCamera(), aMatrix);
|
|
this->Device->SetUserMatrix(aMatrix);
|
|
this->Device->Render(ren,this->Mapper);
|
|
aMatrix->Delete();
|
|
} else
|
|
this->Device->Render(ren, this->Mapper);
|
|
this->EstimatedRenderTime = WireframeMapper->GetTimeToDraw();
|
|
}
|
|
|
|
// SubShape
|
|
void GEOM_Actor::SubShapeOn()
|
|
{
|
|
subshape = true;
|
|
}
|
|
void GEOM_Actor::SubShapeOff()
|
|
{
|
|
subshape = false;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Opacity methods
|
|
//-------------------------------------------------------------
|
|
|
|
void GEOM_Actor::SetOpacity(float opa)
|
|
{
|
|
//HighlightProperty->SetOpacity(opa);
|
|
SALOME_Actor::SetOpacity(opa);
|
|
ShadingProperty->SetOpacity(opa);
|
|
}
|
|
|
|
float GEOM_Actor::GetOpacity() {
|
|
return ShadingProperty->GetOpacity();
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Color methods
|
|
//-------------------------------------------------------------
|
|
void GEOM_Actor::SetColor(float r,float g,float b) {
|
|
ShadingProperty->SetColor(r,g,b);
|
|
}
|
|
|
|
void GEOM_Actor::GetColor(float& r,float& g,float& b) {
|
|
float color[3];
|
|
ShadingProperty->GetColor(color);
|
|
r = color[0];
|
|
g = color[1];
|
|
b = color[2];
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Highlight methods
|
|
//-------------------------------------------------------------
|
|
|
|
void GEOM_Actor::highlight(Standard_Boolean highlight) {
|
|
|
|
if(highlight && !ishighlighted) {
|
|
ishighlighted=true;
|
|
// build highlight property is necessary
|
|
if(HighlightProperty==NULL) {
|
|
HighlightProperty = vtkProperty::New();
|
|
HighlightProperty->SetAmbient(0.5);
|
|
HighlightProperty->SetDiffuse(0.3);
|
|
HighlightProperty->SetSpecular(0.2);
|
|
HighlightProperty->SetRepresentationToSurface();
|
|
HighlightProperty->SetAmbientColor(1, 1, 1);
|
|
HighlightProperty->SetDiffuseColor(1, 1, 1);
|
|
HighlightProperty->SetSpecularColor(0.5, 0.5, 0.5);
|
|
}
|
|
|
|
this->Property = HighlightProperty;
|
|
|
|
}
|
|
else if (!highlight) {
|
|
if(ishighlighted) {
|
|
ishighlighted=false;
|
|
if(myDisplayMode==1) {
|
|
//unhilight in shading
|
|
this->Property = ShadingProperty;
|
|
}
|
|
else {
|
|
//unhilight in wireframe
|
|
this->Property = WireframeProperty;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GEOM_Actor::hasHighlight()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void GEOM_Actor::SetHighlightProperty(vtkProperty* Prop) {
|
|
this->HighlightProperty = Prop;
|
|
}
|
|
|
|
|
|
void GEOM_Actor::ReleaseGraphicsResources(vtkWindow *renWin)
|
|
{
|
|
vtkActor::ReleaseGraphicsResources(renWin);
|
|
|
|
// broadcast the message down to the individual LOD mappers
|
|
|
|
if(WireframeMapper) this->WireframeMapper->ReleaseGraphicsResources(renWin);
|
|
if(ShadingMapper) this->ShadingMapper->ReleaseGraphicsResources(renWin);
|
|
}
|
|
|
|
|
|
// Copy the follower's composite 4x4 matrix into the matrix provided.
|
|
void GEOM_Actor::GetMatrix(vtkCamera* theCam, vtkMatrix4x4 *result)
|
|
{
|
|
double *pos, *vup;
|
|
double Rx[3], Ry[3], Rz[3], p1[3];
|
|
vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
|
|
int i;
|
|
double distance;
|
|
|
|
this->GetOrientation();
|
|
this->Transform->Push();
|
|
this->Transform->PostMultiply();
|
|
this->Transform->Identity();
|
|
|
|
// apply user defined matrix last if there is one
|
|
if (this->UserMatrix)
|
|
{
|
|
this->Transform->Concatenate(this->UserMatrix);
|
|
}
|
|
|
|
this->Transform->Translate(-this->Origin[0],
|
|
-this->Origin[1],
|
|
-this->Origin[2]);
|
|
// scale
|
|
this->Transform->Scale(this->Scale[0],
|
|
this->Scale[1],
|
|
this->Scale[2]);
|
|
|
|
// rotate
|
|
this->Transform->RotateY(this->Orientation[1]);
|
|
this->Transform->RotateX(this->Orientation[0]);
|
|
this->Transform->RotateZ(this->Orientation[2]);
|
|
|
|
if (theCam)
|
|
{
|
|
// do the rotation
|
|
// first rotate y
|
|
pos = theCam->GetPosition();
|
|
vup = theCam->GetViewUp();
|
|
|
|
if (theCam->GetParallelProjection())
|
|
{
|
|
theCam->GetDirectionOfProjection(Rz);
|
|
}
|
|
else
|
|
{
|
|
distance = sqrt(
|
|
(pos[0] - this->Position[0])*(pos[0] - this->Position[0]) +
|
|
(pos[1] - this->Position[1])*(pos[1] - this->Position[1]) +
|
|
(pos[2] - this->Position[2])*(pos[2] - this->Position[2]));
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
Rz[i] = (pos[i] - this->Position[i])/distance;
|
|
}
|
|
}
|
|
|
|
vtkMath::Cross(vup,Rz,Rx);
|
|
vtkMath::Normalize(Rx);
|
|
vtkMath::Cross(Rz,Rx,Ry);
|
|
|
|
matrix->Element[0][0] = Rx[0];
|
|
matrix->Element[1][0] = Rx[1];
|
|
matrix->Element[2][0] = Rx[2];
|
|
matrix->Element[0][1] = Ry[0];
|
|
matrix->Element[1][1] = Ry[1];
|
|
matrix->Element[2][1] = Ry[2];
|
|
matrix->Element[0][2] = Rz[0];
|
|
matrix->Element[1][2] = Rz[1];
|
|
matrix->Element[2][2] = Rz[2];
|
|
|
|
this->Transform->Concatenate(matrix);
|
|
}
|
|
|
|
// translate to projection reference point PRP
|
|
// this is the camera's position blasted through
|
|
// the current matrix
|
|
p1[0] = this->Origin[0] + this->Position[0];
|
|
p1[1] = this->Origin[1] + this->Position[1];
|
|
p1[2] = this->Origin[2] + this->Position[2];
|
|
|
|
this->Transform->Translate(p1[0],p1[1],p1[2]);
|
|
this->Transform->GetMatrix(result);
|
|
|
|
matrix->Delete();
|
|
this->Transform->Pop();
|
|
}
|