Renamed the iges plugin to OpenCASCADE to make it clearer what the plugin is, and added file extension aliases for stp, step, igs and iges to the OpenCASCADE plugin to enable automatic loading.

This commit is contained in:
Robert Osfield
2016-12-09 17:52:17 +00:00
parent 61462dcf97
commit 3432f02d5f
6 changed files with 437 additions and 572 deletions

View File

@@ -444,6 +444,11 @@ Registry::Registry()
addFileExtensionAlias("modified", "revisions");
// STEP/IGES file mappings
addFileExtensionAlias("stp", "opencascade");
addFileExtensionAlias("step", "opencascade");
addFileExtensionAlias("igs", "opencascade");
addFileExtensionAlias("iges", "opencascade");
// add built-in mime-type extension mappings

View File

@@ -154,7 +154,7 @@ IF(FBX_FOUND AND OSG_CPP_EXCEPTIONS_AVAILABLE)
ENDIF()
IF(OPENCASCADE_FOUND)
ADD_SUBDIRECTORY(iges)
ADD_SUBDIRECTORY(OpenCASCADE)
ENDIF()
ADD_SUBDIRECTORY(bvh)

View File

@@ -1,11 +1,11 @@
INCLUDE_DIRECTORIES(${OPENCASCADE_INCLUDE_DIR})
SET(TARGET_SRC
ReaderWriterIGES.cpp
ReaderWriterOpenCASCADE.cpp
)
SET(TARGET_H
ReaderWriterIGES.h
ReaderWriterOpenCASCADE.h
)
SET(TARGET_LIBRARIES_VARS OPENCASCADE_LIBRARY)
@@ -14,4 +14,4 @@ SET(TARGET_LIBRARIES_VARS OPENCASCADE_LIBRARY)
set (CMAKE_CXX_STANDARD 11)
#### end var setup ###
SETUP_PLUGIN(iges)
SETUP_PLUGIN(opencascade)

View File

@@ -0,0 +1,428 @@
/****************************************************************************
*
*
* Copyright 2010-2013, VizExpertsIndia Pvt. Ltd. (unpublished)
*
* All rights reserved. This notice is intended as a precaution against
* inadvertent publication and does not imply publication or any waiver
* of confidentiality. The year included in the foregoing notice is the
* year of creation of the work. No part of this work may be used,
* reproduced, or transmitted in any form or by any means without the prior
* written permission of Vizexperts India Pvt Ltd.
*
*
***************************************************************************
*/
/// \file ReaderWritterOpenCASCADE.cpp
/// \brief implementation file for osgdb plugin for IGES format
/// contains implementation of ReaderWritterOpenCASCADE class
/// \author Abhishek Bansal
#include "ReaderWriterOpenCASCADE.h"
#include <iostream>
// OpenCascade Headers
#include <TopTools_HSequenceOfShape.hxx>
#include <TopExp_Explorer.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_CString.hxx>
#include <Standard_Macro.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepGProp_Face.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <ShapeFix_Shape.hxx>
#include <gp_Pnt2d.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <IGESControl_Reader.hxx>
#include <IGESControl_Writer.hxx>
#include <IGESControl_Controller.hxx>
#include <STEPCAFControl_Reader.hxx>
#include <TDocStd_Document.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFDoc_Location.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFApp_Application.hxx>
#include <IGESCAFControl_Reader.hxx>
#include <TDF_Label.hxx>
#include <TDF_LabelSequence.hxx>
#include <TDF_ChildIterator.hxx>
#include <Quantity_Color.hxx>
// osg headers
#include<osg/PrimitiveSet>
#include <osg/MatrixTransform>
#include <osgUtil/TriStripVisitor>
#include <osgUtil/SmoothingVisitor>
//#define _LOG_DEBUG_
REGISTER_OSGPLUGIN(OpenCASCADE, ReaderWritterOpenCASCADE)
ReaderWritterOpenCASCADE::ReaderWritterOpenCASCADE()
{
OSG_NOTICE<<"ReaderWritterOpenCASCADE::ReaderWritterOpenCASCADE()"<<std::endl;
supportsExtension("IGES","IGES file format");
supportsExtension("iges","IGES file format");
supportsExtension("IGS","IGS file format");
supportsExtension("igs","IGS file format");
supportsExtension("stp","STEP file format");
supportsExtension("STP","STEP file format");
}
osgDB::ReaderWriter::ReadResult ReaderWritterOpenCASCADE::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
{
// some error handling
std::string ext = osgDB::getLowerCaseFileExtension(fileName);
if (!acceptsExtension(ext))
return ReadResult::FILE_NOT_HANDLED;
std::string file = osgDB::findDataFile(fileName, options);
if (file.empty())
return ReadResult::FILE_NOT_FOUND;
OSG_INFO << "ReaderWritterOpenCASCADE::readNode(" << file.c_str() << ")\n";
OCCTKReader reader;
return reader.igesToOSGGeode(fileName);
}
osgDB::ReaderWriter::WriteResult ReaderWritterOpenCASCADE::writeNode(const osg::Node& /*node*/,const std::string& fileName /*fileName*/,const Options*) const
{
// some error handling
std::string ext = osgDB::getLowerCaseFileExtension(fileName);
if (!acceptsExtension(ext))
return WriteResult::FILE_NOT_HANDLED;
std::cout << "File Writing not supported yet" << std::endl;
return WriteResult::FILE_NOT_HANDLED;
}
/// \brief heals a opencascade shape
/// \detail http://www.opencascade.org/org/forum/thread_12716/?forum=3
/// Usually IGES files suffer from precision problems (when transfering from
/// one CAD system to another).It might be the case that faces are not sewed
/// properly, or do not have the right precision, and so the tesselator does
/// not treat them like "sewed". this needs to be done for sewing
/// \param shape opencascade shape to be healed
void ReaderWritterOpenCASCADE::OCCTKReader::_healShape(TopoDS_Shape& shape)
{
#ifdef _LOG_DEBUG_
std::cout << std::endl << "Going to heal shape!!";
#endif
ShapeFix_Shape fixer(shape);
fixer.Perform();
shape = fixer.Shape();
BRepBuilderAPI_Sewing sew;
sew.Add(shape);
sew.Perform();
shape = sew.SewedShape();
}
/// \brief takes and OpenCascadeShape and returns OSG geometry(drawable), which further can be added to a geode
/// \detail it iterates shape and breaks it into faces, builds vertex list, color list and creates geometry
/// transformation is applied to each vertex before storing it into vertex list
/// all vertices are assigned same color
/// \param shape shape to be converted in geometry. Not a const because it needs to be modified if healing
/// is enabled
/// \param color color of geometry
/// \param transformation matrix with which vertex position has to be transformed
osg::ref_ptr<osg::Geometry> ReaderWritterOpenCASCADE::OCCTKReader::_createGeometryFromShape(TopoDS_Shape& shape, const osg::Vec3& geomColor, gp_Trsf& transformation)
{
// vector to save vertices
osg::ref_ptr<osg::Vec3Array> vertexList = new osg::Vec3Array();
// vector to save _colorTool
osg::ref_ptr<osg::Vec3Array> colorList = new osg::Vec3Array();
// create one osg primitive set
osg::ref_ptr<osg::DrawElementsUInt> triangleStrip = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
unsigned int noOfTriangles = 0;
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
if(!shape.IsNull())
{
// clean any previous triangulation
BRepTools::Clean(shape);
//_healShape(shape);
#ifdef _LOG_DEBUG_
std::cout << std::endl << "Building a Mesh !!" ;
#endif
/// call to incremental mesh on this shape
/// \todo not sure why this 1 is passed. Its called deflection BTW
/// need to find a way to calculate it
double linearDeflection = 1.0;
BRepMesh_IncrementalMesh(shape, linearDeflection);
///iterate faces
// this variable will help in keeping track of face indices
unsigned int index = 0;
for (TopExp_Explorer ex(shape, TopAbs_FACE); ex.More(); ex.Next())
{
TopoDS_Face face = TopoDS::Face(ex.Current());
TopLoc_Location location;
/// triangulate current face
Handle (Poly_Triangulation) triangulation = BRep_Tool::Triangulation(face, location);
if (!triangulation.IsNull())
{
int noOfNodes = triangulation->NbNodes();
// Store vertices. Build vertex array here
for(int j = 1; j <= triangulation->NbNodes(); j++)
{
// populate vertex list
// Ref: http://www.opencascade.org/org/forum/thread_16694/?forum=3
gp_Pnt pt = (triangulation->Nodes())(j).Transformed(transformation * location.Transformation());
vertexList->push_back(osg::Vec3(pt.X(), pt.Y(), pt.Z()));
// populate color list
colorList->push_back(geomColor);
}
/// now we need to get face indices for triangles
// get list of triangle first
const Poly_Array1OfTriangle& triangles = triangulation->Triangles();
//No of triangles in this triangulation
noOfTriangles = triangulation->NbTriangles();
Standard_Integer v1, v2, v3;
for (unsigned int j = 1; j <= noOfTriangles; j++)
{
/// If face direction is reversed then we add verticews in reverse order
/// order of vertices is important for normal calculation later
if (face.Orientation() == TopAbs_REVERSED)
{
triangles(j).Get(v1, v3, v2);
}
else
{
triangles(j).Get(v1, v2, v3);
}
triangleStrip->push_back(index + v1 - 1);
triangleStrip->push_back(index + v2 - 1);
triangleStrip->push_back(index + v3 - 1);
}
index = index + noOfNodes;
}
}
#ifdef _LOG_DEBUG_
std::cout << "Creating a geometry.." << std::endl;
#endif
geom->setVertexArray(vertexList.get());
geom->setColorArray(colorList.get());
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
#ifdef _LOG_DEBUG_
std::cout << "Adding Primitive set" << std::endl;
#endif
geom->addPrimitiveSet(triangleStrip);
}
return geom;
}
/// \brief this function is single point of contact for this class.
/// it takes path of IGES file and returns an OpenSceneGraph Geode
/// which directly can be used anywhere. It calculates normals using osgUtil::smoother
osg::ref_ptr<osg::Geode> ReaderWritterOpenCASCADE::OCCTKReader::igesToOSGGeode(const std::string& filePath)
{
// XDE: Extended Data Exchange
// OCAF: OpenCascade Application Technology Framework
/// Getting an XDE document
Handle(TDocStd_Document) doc;
XCAFApp_Application::GetApplication()->NewDocument("MDTV-XCAF", doc);
std::string ext = osgDB::getLowerCaseFileExtension(filePath);
if (ext=="stp" || ext=="step")
{
OSG_NOTICE<<"Using STEPCAFControl_Reader to read file : "<<filePath<<std::endl;
STEPCAFControl_Reader reader;
reader.SetColorMode(true);
reader.SetNameMode(true);
reader.SetLayerMode(true);
//IGESControl_Reader Reader;
reader.ReadFile( (Standard_CString)filePath.c_str() );
/// transfer data from reader to doc
if(!reader.Transfer(doc))
{
cout << "Cannot read any relevant data from the STEP file" << endl;
return NULL;
}
}
else
{
OSG_NOTICE<<"Using IGESCAFControl_Reader to read file : "<<filePath<<std::endl;
IGESCAFControl_Reader reader;
reader.SetColorMode(true);
reader.SetNameMode(true);
reader.SetLayerMode(true);
//IGESControl_Reader Reader;
reader.ReadFile( (Standard_CString)filePath.c_str() );
/// transfer data from reader to doc
if(!reader.Transfer(doc))
{
cout << "Cannot read any relevant data from the IGES file" << endl;
return NULL;
}
}
// To get a node considered as an Assembly from an XDE structure, you can use the Label of the node.
_assembly = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
// To query, edit, or initialize a Document to handle Colors of XCAF
_colorTool = XCAFDoc_DocumentTool::ColorTool(doc->Main());
// free shape sequence
// get sequence of free shape lables
TDF_LabelSequence freeShapes;
_assembly->GetFreeShapes(freeShapes);
if(freeShapes.Length() == 0)
{
std::cout << "No Shapes found" << endl;
return NULL;
}
else
{
std::cout << std::endl << "No of Free Shapes: " << freeShapes.Length();
}
_modelGeode = new osg::Geode();
/// send all root nodes for recursive traversing
/// find transformation as it will be needed for location calculation later
for (int i = 1; i <= freeShapes.Length(); i++)
{
Handle(XCAFDoc_Location) attribute;
gp_Trsf transformation;
freeShapes.Value(i).FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
transformation = location.Transformation();
}
_traverse(freeShapes.Value(i), transformation);
}
/// calculate normals
#ifdef _LOG_DEBUG_
std::cout << "Calculating Normals" << std::endl;
#endif
osgUtil::SmoothingVisitor sv;
_modelGeode->accept(sv);
return _modelGeode;
}
/// \brief recursively traverse opencascade assembly structure and build a osg geode
/// this function also finds color for leaf node shapes and calculates transformation from parent
/// to leaf
/// \param shapeTree its a OCT(OpenCascade Technology) XDE document label which might contain children or referred shapes
/// \param transformation contains transformation matrix to be applied
/// \note Simple Shape: is a shape which is not a compound. Its can be a free or non free shape
/// \note Support Thread: http://www.opencascade.org/org/forum/thread_25512/?forum=3
void ReaderWritterOpenCASCADE::OCCTKReader::_traverse(const TDF_Label &shapeTree, gp_Trsf& transformation)
{
TDF_Label referredShape;
/// find if current shape referes some shape. if it does then traverse that
/// else it is a simple shape and do visualize that simple shape
if(_assembly->GetReferredShape(shapeTree, referredShape))
{
Handle(XCAFDoc_Location) attribute;
referredShape.FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
transformation *= location.Transformation();
}
/// if referred shape has children traverse them first else
/// travese the shape itself
if(referredShape.HasChild())
{
TDF_ChildIterator it;
for(it.Initialize(referredShape); it.More(); it.Next())
{
_traverse(it.Value(), transformation);
}
}
else
{
#ifdef _LOG_DEBUG_
std::cout << std::endl << "No children found";
#endif
_traverse(referredShape, transformation);
}
}
else
{
/// Find out if this simple shape has any color store that color as color of geometry
Quantity_Color color;
osg::Vec3 geomColor = osg::Vec3(.7, .7, .7);
if(_colorTool->GetColor(shapeTree, XCAFDoc_ColorGen, color) ||
_colorTool->GetColor(shapeTree, XCAFDoc_ColorSurf, color) ||
_colorTool->GetColor(shapeTree, XCAFDoc_ColorCurv, color) )
{
#ifdef _LOG_DEBUG_
std::cout << std::endl << "Free Shape has a color !! " << color.Red() << " " << color.Green() << " "<< color.Blue();
#endif
geomColor = osg::Vec3(color.Red(),color.Green(), color.Blue());
}
TopoDS_Shape shape = _assembly->GetShape(shapeTree);
Handle(XCAFDoc_Location) attribute;
shapeTree.FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
transformation *= location.Transformation();
}
osg::ref_ptr<osg::Geometry> geom = _createGeometryFromShape(shape, geomColor, transformation);
/// add this geometry to model geode
if(geom.valid())
{
_modelGeode->addDrawable(geom);
}
else
{
std::cout << std::endl << "Invalid Geometry found !!";
}
}
}

View File

@@ -1,432 +0,0 @@
/****************************************************************************
*
*
* Copyright 2010-2013, VizExpertsIndia Pvt. Ltd. (unpublished)
*
* All rights reserved. This notice is intended as a precaution against
* inadvertent publication and does not imply publication or any waiver
* of confidentiality. The year included in the foregoing notice is the
* year of creation of the work. No part of this work may be used,
* reproduced, or transmitted in any form or by any means without the prior
* written permission of Vizexperts India Pvt Ltd.
*
*
***************************************************************************
*/
/// \file ReaderWriterIGES.cpp
/// \brief implementation file for osgdb plugin for IGES format
/// contains implementation of ReaderWriterIGES class
/// \author Abhishek Bansal
#include "ReaderWriterIGES.h"
#include <iostream>
// OpenCascade Headers
#include <TopTools_HSequenceOfShape.hxx>
#include <TopExp_Explorer.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_CString.hxx>
#include <Standard_Macro.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepGProp_Face.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <ShapeFix_Shape.hxx>
#include <gp_Pnt2d.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <IGESControl_Reader.hxx>
#include <IGESControl_Writer.hxx>
#include <IGESControl_Controller.hxx>
#include <STEPCAFControl_Reader.hxx>
#include <TDocStd_Document.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFDoc_Location.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFApp_Application.hxx>
#include <IGESCAFControl_Reader.hxx>
#include <TDF_Label.hxx>
#include <TDF_LabelSequence.hxx>
#include <TDF_ChildIterator.hxx>
#include <Quantity_Color.hxx>
// osg headers
#include<osg/PrimitiveSet>
#include <osg/MatrixTransform>
#include <osgUtil/TriStripVisitor>
#include <osgUtil/SmoothingVisitor>
//#define _LOG_DEBUG_
namespace IGES
{
REGISTER_OSGPLUGIN(iges, ReaderWriterIGES)
ReaderWriterIGES::ReaderWriterIGES()
{
OSG_NOTICE<<"ReaderWriterIGES::ReaderWriterIGES()"<<std::endl;
supportsExtension("IGES","IGES file format");
supportsExtension("iges","IGES file format");
supportsExtension("IGS","IGS file format");
supportsExtension("igs","IGS file format");
supportsExtension("stp","STEP file format");
supportsExtension("STP","STEP file format");
}
osgDB::ReaderWriter::ReadResult ReaderWriterIGES::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
{
// some error handling
std::string ext = osgDB::getLowerCaseFileExtension(fileName);
if (!acceptsExtension(ext))
return ReadResult::FILE_NOT_HANDLED;
std::string file = osgDB::findDataFile(fileName, options);
if (file.empty())
return ReadResult::FILE_NOT_FOUND;
OSG_INFO << "ReaderWriterIGES::readNode(" << file.c_str() << ")\n";
IGESReader reader;
return reader.igesToOSGGeode(fileName);
}
osgDB::ReaderWriter::WriteResult ReaderWriterIGES::writeNode(const osg::Node& /*node*/,const std::string& fileName /*fileName*/,const Options*) const
{
// some error handling
std::string ext = osgDB::getLowerCaseFileExtension(fileName);
if (!acceptsExtension(ext))
return WriteResult::FILE_NOT_HANDLED;
std::cout << "File Writing not supported yet" << std::endl;
return WriteResult::FILE_NOT_HANDLED;
}
/// \brief heals a opencascade shape
/// \detail http://www.opencascade.org/org/forum/thread_12716/?forum=3
/// Usually IGES files suffer from precision problems (when transfering from
/// one CAD system to another).It might be the case that faces are not sewed
/// properly, or do not have the right precision, and so the tesselator does
/// not treat them like "sewed". this needs to be done for sewing
/// \param shape opencascade shape to be healed
void ReaderWriterIGES::IGESReader::_healShape(TopoDS_Shape& shape)
{
#ifdef _LOG_DEBUG_
std::cout << std::endl << "Going to heal shape!!";
#endif
ShapeFix_Shape fixer(shape);
fixer.Perform();
shape = fixer.Shape();
BRepBuilderAPI_Sewing sew;
sew.Add(shape);
sew.Perform();
shape = sew.SewedShape();
}
/// \brief takes and OpenCascadeShape and returns OSG geometry(drawable), which further can be added to a geode
/// \detail it iterates shape and breaks it into faces, builds vertex list, color list and creates geometry
/// transformation is applied to each vertex before storing it into vertex list
/// all vertices are assigned same color
/// \param shape shape to be converted in geometry. Not a const because it needs to be modified if healing
/// is enabled
/// \param color color of geometry
/// \param transformation matrix with which vertex position has to be transformed
osg::ref_ptr<osg::Geometry> ReaderWriterIGES::IGESReader::_createGeometryFromShape(TopoDS_Shape& shape, const osg::Vec3& geomColor, gp_Trsf& transformation)
{
// vector to save vertices
osg::ref_ptr<osg::Vec3Array> vertexList = new osg::Vec3Array();
// vector to save _colorTool
osg::ref_ptr<osg::Vec3Array> colorList = new osg::Vec3Array();
// create one osg primitive set
osg::ref_ptr<osg::DrawElementsUInt> triangleStrip = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
unsigned int noOfTriangles = 0;
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
if(!shape.IsNull())
{
// clean any previous triangulation
BRepTools::Clean(shape);
//_healShape(shape);
#ifdef _LOG_DEBUG_
std::cout << std::endl << "Building a Mesh !!" ;
#endif
/// call to incremental mesh on this shape
/// \todo not sure why this 1 is passed. Its called deflection BTW
/// need to find a way to calculate it
double linearDeflection = 1.0;
BRepMesh_IncrementalMesh(shape, linearDeflection);
///iterate faces
// this variable will help in keeping track of face indices
unsigned int index = 0;
for (TopExp_Explorer ex(shape, TopAbs_FACE); ex.More(); ex.Next())
{
TopoDS_Face face = TopoDS::Face(ex.Current());
TopLoc_Location location;
/// triangulate current face
Handle (Poly_Triangulation) triangulation = BRep_Tool::Triangulation(face, location);
if (!triangulation.IsNull())
{
int noOfNodes = triangulation->NbNodes();
// Store vertices. Build vertex array here
for(int j = 1; j <= triangulation->NbNodes(); j++)
{
// populate vertex list
// Ref: http://www.opencascade.org/org/forum/thread_16694/?forum=3
gp_Pnt pt = (triangulation->Nodes())(j).Transformed(transformation * location.Transformation());
vertexList->push_back(osg::Vec3(pt.X(), pt.Y(), pt.Z()));
// populate color list
colorList->push_back(geomColor);
}
/// now we need to get face indices for triangles
// get list of triangle first
const Poly_Array1OfTriangle& triangles = triangulation->Triangles();
//No of triangles in this triangulation
noOfTriangles = triangulation->NbTriangles();
Standard_Integer v1, v2, v3;
for (unsigned int j = 1; j <= noOfTriangles; j++)
{
/// If face direction is reversed then we add verticews in reverse order
/// order of vertices is important for normal calculation later
if (face.Orientation() == TopAbs_REVERSED)
{
triangles(j).Get(v1, v3, v2);
}
else
{
triangles(j).Get(v1, v2, v3);
}
triangleStrip->push_back(index + v1 - 1);
triangleStrip->push_back(index + v2 - 1);
triangleStrip->push_back(index + v3 - 1);
}
index = index + noOfNodes;
}
}
#ifdef _LOG_DEBUG_
std::cout << "Creating a geometry.." << std::endl;
#endif
geom->setVertexArray(vertexList.get());
geom->setColorArray(colorList.get());
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
#ifdef _LOG_DEBUG_
std::cout << "Adding Primitive set" << std::endl;
#endif
geom->addPrimitiveSet(triangleStrip);
}
return geom;
}
/// \brief this function is single point of contact for this class.
/// it takes path of IGES file and returns an OpenSceneGraph Geode
/// which directly can be used anywhere. It calculates normals using osgUtil::smoother
osg::ref_ptr<osg::Geode> ReaderWriterIGES::IGESReader::igesToOSGGeode(const std::string& filePath)
{
// XDE: Extended Data Exchange
// OCAF: OpenCascade Application Technology Framework
/// Getting an XDE document
Handle(TDocStd_Document) doc;
XCAFApp_Application::GetApplication()->NewDocument("MDTV-XCAF", doc);
std::string ext = osgDB::getLowerCaseFileExtension(filePath);
if (ext=="stp" || ext=="step")
{
OSG_NOTICE<<"Using STEPCAFControl_Reader to read file : "<<filePath<<std::endl;
STEPCAFControl_Reader reader;
reader.SetColorMode(true);
reader.SetNameMode(true);
reader.SetLayerMode(true);
//IGESControl_Reader Reader;
reader.ReadFile( (Standard_CString)filePath.c_str() );
/// transfer data from reader to doc
if(!reader.Transfer(doc))
{
cout << "Cannot read any relevant data from the STEP file" << endl;
return NULL;
}
}
else
{
OSG_NOTICE<<"Using IGESCAFControl_Reader to read file : "<<filePath<<std::endl;
IGESCAFControl_Reader reader;
reader.SetColorMode(true);
reader.SetNameMode(true);
reader.SetLayerMode(true);
//IGESControl_Reader Reader;
reader.ReadFile( (Standard_CString)filePath.c_str() );
/// transfer data from reader to doc
if(!reader.Transfer(doc))
{
cout << "Cannot read any relevant data from the IGES file" << endl;
return NULL;
}
}
// To get a node considered as an Assembly from an XDE structure, you can use the Label of the node.
_assembly = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
// To query, edit, or initialize a Document to handle Colors of XCAF
_colorTool = XCAFDoc_DocumentTool::ColorTool(doc->Main());
// free shape sequence
// get sequence of free shape lables
TDF_LabelSequence freeShapes;
_assembly->GetFreeShapes(freeShapes);
if(freeShapes.Length() == 0)
{
std::cout << "No Shapes found" << endl;
return NULL;
}
else
{
std::cout << std::endl << "No of Free Shapes: " << freeShapes.Length();
}
_modelGeode = new osg::Geode();
/// send all root nodes for recursive traversing
/// find transformation as it will be needed for location calculation later
for (int i = 1; i <= freeShapes.Length(); i++)
{
Handle(XCAFDoc_Location) attribute;
gp_Trsf transformation;
freeShapes.Value(i).FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
transformation = location.Transformation();
}
_traverse(freeShapes.Value(i), transformation);
}
/// calculate normals
#ifdef _LOG_DEBUG_
std::cout << "Calculating Normals" << std::endl;
#endif
osgUtil::SmoothingVisitor sv;
_modelGeode->accept(sv);
return _modelGeode;
}
/// \brief recursively traverse opencascade assembly structure and build a osg geode
/// this function also finds color for leaf node shapes and calculates transformation from parent
/// to leaf
/// \param shapeTree its a OCT(OpenCascade Technology) XDE document label which might contain children or referred shapes
/// \param transformation contains transformation matrix to be applied
/// \note Simple Shape: is a shape which is not a compound. Its can be a free or non free shape
/// \note Support Thread: http://www.opencascade.org/org/forum/thread_25512/?forum=3
void ReaderWriterIGES::IGESReader::_traverse(const TDF_Label &shapeTree, gp_Trsf& transformation)
{
TDF_Label referredShape;
/// find if current shape referes some shape. if it does then traverse that
/// else it is a simple shape and do visualize that simple shape
if(_assembly->GetReferredShape(shapeTree, referredShape))
{
Handle(XCAFDoc_Location) attribute;
referredShape.FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
transformation *= location.Transformation();
}
/// if referred shape has children traverse them first else
/// travese the shape itself
if(referredShape.HasChild())
{
TDF_ChildIterator it;
for(it.Initialize(referredShape); it.More(); it.Next())
{
_traverse(it.Value(), transformation);
}
}
else
{
#ifdef _LOG_DEBUG_
std::cout << std::endl << "No children found";
#endif
_traverse(referredShape, transformation);
}
}
else
{
/// Find out if this simple shape has any color store that color as color of geometry
Quantity_Color color;
osg::Vec3 geomColor = osg::Vec3(.7, .7, .7);
if(_colorTool->GetColor(shapeTree, XCAFDoc_ColorGen, color) ||
_colorTool->GetColor(shapeTree, XCAFDoc_ColorSurf, color) ||
_colorTool->GetColor(shapeTree, XCAFDoc_ColorCurv, color) )
{
#ifdef _LOG_DEBUG_
std::cout << std::endl << "Free Shape has a color !! " << color.Red() << " " << color.Green() << " "<< color.Blue();
#endif
geomColor = osg::Vec3(color.Red(),color.Green(), color.Blue());
}
TopoDS_Shape shape = _assembly->GetShape(shapeTree);
Handle(XCAFDoc_Location) attribute;
shapeTree.FindAttribute(XCAFDoc_Location::GetID(), attribute);
if(attribute.IsNull() == Standard_False)
{
TopLoc_Location location = attribute->Get();
transformation *= location.Transformation();
}
osg::ref_ptr<osg::Geometry> geom = _createGeometryFromShape(shape, geomColor, transformation);
/// add this geometry to model geode
if(geom.valid())
{
_modelGeode->addDrawable(geom);
}
else
{
std::cout << std::endl << "Invalid Geometry found !!";
}
}
}
} // namespace

View File

@@ -1,136 +0,0 @@
/*
* IGES importer for OpenSceneGraph.
* Copyright (c)2013 VizExperts India Pvt. Ltd.
*
* 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, or (at your option) any later version.
*
* 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
*/
#ifndef _READERWRITERIGES_H_
#define _READERWRITERIGES_H_
/// \file ReaderWriterIGES.h
/// \brief header file for creating osgdb plugin for IGES format
/// \author Abhishek Bansal, Engineer Graphics, vizExperts India Pvt. Ltd.
#ifdef WIN32
/// \brief preproccessor macro required for compilation with open cascade
/// \todo not sure what it does
#define WNT
#endif
#include <TDF_LabelSequence.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <TopoDS_Shape.hxx>
#include <gp_Trsf.hxx>
#include <osg/Notify>
#include <osg/Geode>
#include <osg/Geometry>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgUtil/TriStripVisitor>
/// \class ReaderWriterIGES
/// \brief contains implementation of reading IGES models
/// depends on OpenCascade library
/// this code was written with version 6.6.0
/// \todo enabling/disabling Healing can be added as reader writer options
namespace IGES
{
class ReaderWriterIGES: public osgDB::ReaderWriter
{
public:
/// \brief constructor
ReaderWriterIGES();
/// \brief returns class name
virtual const char* className() const { return "STEP/IGES Reader"; }
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*) const;
virtual osgDB::ReaderWriter::WriteResult writeNode(const osg::Node&, const std::string&, const Options* =NULL) const ;
private:
/// \brief following class will contain all reading related functionality
/// \detail this class uses OCT XDE module to read IGES file. XDE mechanism is needed
/// to find out colors and transformation of sub shapes.
/// normal IGESReader wasn't giving very good results with shapes. Edges weren't sharp enough
/// and also there is no way in which we can get color information with that
/// \Note Go through XDE user guide and IGES User guide supplied with
/// \todo OSG automatic normal calculation is not working good for few mnodels
/// try to get from XDE document only
class IGESReader
{
public:
/// \brief this function is single point of contact for this class.
/// it takes path of IGES file and returns an OpenSceneGraph Geode
/// which directly can be used anywhere. It calculates normals using osgUtil::smoother
osg::ref_ptr<osg::Geode> igesToOSGGeode(const std::string& filePath);
private:
/// \brief heals a opencascade shape
/// \detail http://www.opencascade.org/org/forum/thread_12716/?forum=3
/// Usually IGES files suffer from precision problems (when transfering from
/// one CAD system to another).It might be the case that faces are not sewed
/// properly, or do not have the right precision, and so the tesselator does
/// not treat them like "sewed". this needs to be done for sewing
/// \param[in,out] shape opencascade shape to be healed
void _healShape(TopoDS_Shape& shape);
/// \brief recursively traverse opencascade assembly structure and build a osg geode
/// this function also finds color for leaf node shapes and calculates transformation from parent
/// to leaf
/// \param[in] shapeTree its a OCT(OpenCascade Technology) XDE document label which might contain children or referred shapes
/// \param[in] transformation contains transformation matrix to be applied
void _traverse(const TDF_Label &shapeTree, gp_Trsf& transformation);
/// \brief takes and OpenCascadeShape and returns OSG geometry(drawable), which further can be added to a geode
/// \detail it iterates shape and breaks it into faces, builds vertex list, color list and creates geometry
/// transformation is applied to each vertex before storing it into vertex list
/// all vertices are assigned same color
/// \param[in] shape shape to be converted in geometry. Not a const because it needs to be modified if healing
/// is enabled
/// \param[in] color color of geometry
/// \param[in] transformation matrix with which vertex position has to be transformed
osg::ref_ptr<osg::Geometry> _createGeometryFromShape(TopoDS_Shape& shape, const osg::Vec3& color, gp_Trsf& transformation);
private:
/// \bried XDE document color tool it stores all colors in color table
/// and used to get color from a label
Handle(XCAFDoc_ColorTool) _colorTool;
/// \brief geode to contain full model
osg::ref_ptr<osg::Geode> _modelGeode;
/// \brief shape tool instance to deal with shapes(simple shapes), referredShape, children etc
Handle (XCAFDoc_ShapeTool) _assembly;
};
};
} // namespace
#endif // _READERWRITERIGES_H_