/**************************************************************************** * * * 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 // OpenCascade Headers #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // osg headers #include #include #include //#define _LOG_DEBUG_ REGISTER_OSGPLUGIN(OpenCASCADE, ReaderWritterOpenCASCADE) ReaderWritterOpenCASCADE::ReaderWritterOpenCASCADE() { OSG_NOTICE<<"ReaderWritterOpenCASCADE::ReaderWritterOpenCASCADE()"< ReaderWritterOpenCASCADE::OCCTKReader::_createGeometryFromShape(TopoDS_Shape& shape, const osg::Vec3& geomColor, gp_Trsf& transformation) { // vector to save vertices osg::ref_ptr vertexList = new osg::Vec3Array(); osg::Array::Binding colorBinding = osg::Array::BIND_OVERALL; // vector to save _colorTool osg::ref_ptr colorList = new osg::Vec3Array(); if (colorBinding==osg::Array::BIND_OVERALL) { colorList->push_back(geomColor); } // create one osg primitive set osg::ref_ptr triangleStrip = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0); unsigned int noOfTriangles = 0; osg::ref_ptr geom = new osg::Geometry; // large vertex datasets work best with VBO. geom->setUseVertexBufferObjects(true); 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 if (colorBinding==osg::Array::BIND_PER_VERTEX) { 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(), colorBinding); #ifdef _LOG_DEBUG_ std::cout << "Adding Primitive set" << std::endl; #endif geom->addPrimitiveSet(triangleStrip.get()); } 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 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 : "<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 labels TDF_LabelSequence freeShapes; _assembly->GetFreeShapes(freeShapes); if(freeShapes.Length() == 0) { std::cout << "No Shapes found" << std::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; sv.setCreaseAngle(osg::DegreesToRadians(20.0)); _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 /// traverse 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 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 !!"; } } }