--- /dev/null
+pload ALL
+
+vclear
+vclose all
+
+vinit name=View1 w=512 h=512
+vsetdispmode 1
+vcamera -persp -fovy 90
+
+vzbufftrihedron
+
+set folderTyre "D:/TmpFiles/for_video/Tyre"
+set folderEnv "D:/TmpFiles/for_video/Environment"
+
+#road
+puts "Loading road..."
+vdisplayobj road "${folderEnv}/roadV2.obj"
+vlocrotate road 0 0 0 1 0 0 90
+vlocscale road 1 1 0 102400
+vloctranslate road 0 1 3.5
+#vlocscale road
+
+#building0
+puts "Loading the first building..."
+vdisplayobj building0 "${folderEnv}/Building N100715.obj"
+vlocscale building0 1 1 1 10922
+vlocrotate building0 0 0 0 1 0 0 90
+vlocrotate building0 0 0 0 0 1 0 45
+vloctranslate building0 -6 3 3
+
+#House N090614
+puts "Loading the second building..."
+vdisplayobj HouseN090614 "${folderEnv}/House N090614.obj"
+vloctranslate HouseN090614 0 0 1000
+vlocrotate HouseN090614 0 0 0 1 0 0 90
+vlocscale HouseN090614 1 1 1 1024
+
+#Building1
+puts "Loading the third building..."
+vdisplayobj building1 "${folderEnv}/Building N101213.obj"
+vlocrotate building1 0 0 0 1 0 0 90
+vlocscale building1 1 1 1 21845
+vloctranslate building1 -1 1 0
+vlocrotate building1 0 0 0 0 1 0 45
+
+#Tyre
+puts "Loading tyre..."
+vdisplayobj tyre "${folderTyre}/tyre.obj"
+vloctranslate tyre 0 -10000 400
+
+#vlight del 0
+#vlight del 1
+#vlight add positional head 0 pos 0.5 0.5 50.85
+#vlight change 0 sm 0.06
+#vlight change 0 int 160.0
+
+
+#vrenderparams -ray -gi -rayDepth 8
+vtextureenv on 4
+vrenderparams -ray -env on
+vfit
--- /dev/null
+#include <CafShapePrs.h>
+
+IMPLEMENT_STANDARD_RTTIEXT(CafShapePrs, XCAFPrs_AISObject)
+
+// =======================================================================
+// function : CafShapePrs
+// purpose :
+// =======================================================================
+CafShapePrs::CafShapePrs (const TDF_Label& theLabel,
+ const XCAFPrs_Style& theStyle,
+ const Graphic3d_MaterialAspect& theMaterial)
+: XCAFPrs_AISObject (theLabel),
+ myDefStyle (theStyle)
+{
+ SetMaterial (theMaterial);
+}
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifndef CafShapePrs_Header
+#define CafShapePrs_Header
+
+#include <XCAFPrs_AISObject.hxx>
+#include <XCAFPrs_Style.hxx>
+
+typedef NCollection_DataMap<TopoDS_Shape, Handle(AIS_ColoredDrawer), TopTools_ShapeMapHasher> CafDataMapOfShapeColor;
+
+//! Interactive object for shape in DECAF document.
+class CafShapePrs : public XCAFPrs_AISObject
+{
+
+public:
+
+ //! Default constructor.
+ Standard_EXPORT CafShapePrs (const TDF_Label& theLabel,
+ const XCAFPrs_Style& theStyle,
+ const Graphic3d_MaterialAspect& theMaterial);
+
+ //! Search custom aspect for specified shape.
+ Standard_Boolean FindCustomAspects (const TopoDS_Shape& theShape,
+ Handle(AIS_ColoredDrawer)& theAspects) const
+ {
+ return myShapeColors.Find (theShape, theAspects);
+ }
+
+ //! Access the styles map.
+ const CafDataMapOfShapeColor& ShapeColors() const { return myShapeColors; }
+
+ //! Override default style.
+ virtual void DefaultStyle (XCAFPrs_Style& theStyle) const Standard_OVERRIDE
+ {
+ theStyle = myDefStyle;
+ }
+
+protected:
+
+ XCAFPrs_Style myDefStyle; //!< default style
+
+public: //! @name Declaration of CASCADE RTTI
+
+ DEFINE_STANDARD_RTTIEXT(CafShapePrs, XCAFPrs_AISObject)
+
+};
+
+DEFINE_STANDARD_HANDLE (CafShapePrs, XCAFPrs_AISObject)
+
+#endif
MeshVS_TwoNodesHasher.hxx
MeshVS_VectorPrsBuilder.cxx
MeshVS_VectorPrsBuilder.hxx
+
+MeshDataSource.h
+MeshDataSource.cpp
+ObjDataSource.h
+ObjDataSource.cpp
+MeshScalarProperty.h
+MeshPresentation.h
+MeshPresentation.cpp
+MeshPrsBuilder.h
+MeshPrsBuilder.cpp
+ObjDataWriter.h
+ObjDataWriter.cpp
+FaceIterator.h
+FaceIterator.cpp
+CafShapePrs.h
+CafShapePrs.cpp
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <FaceIterator.h>
+
+#include <AIS_ColoredShape.hxx>
+#include <AIS_ConnectedInteractive.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepLProp_SLProps.hxx>
+#include <BRep_Tool.hxx>
+#include <CafShapePrs.h>
+#include <Poly_Array1OfTriangle.hxx>
+#include <Poly_Triangulation.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+
+// =======================================================================
+// function : FaceIterator
+// purpose :
+// =======================================================================
+FaceIterator::FaceIterator (const AIS_ListOfInteractive& thePrsList)
+: myPrsIter (thePrsList)
+{
+ Next();
+}
+
+// =======================================================================
+// function : Next
+// purpose :
+// =======================================================================
+void FaceIterator::Next()
+{
+ for (; myPrsIter.More(); myPrsIter.Next())
+ {
+ Handle(AIS_ConnectedInteractive) aConnected = Handle(AIS_ConnectedInteractive)::DownCast (myPrsIter.Value());
+ Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (!aConnected.IsNull() ? aConnected->ConnectedTo() : myPrsIter.Value());
+
+ ShapePrs = Handle(CafShapePrs)::DownCast (aShapePrs);
+ myPrsLocation = TopLoc_Location();
+ if (ShapePrs.IsNull())
+ {
+ Triangulation.Nullify();
+ Face.Nullify();
+ myFacesMap.Clear();
+ continue;
+ }
+ else if (!aConnected.IsNull()
+ && aConnected->LocalTransformation().Form() != gp_Identity)
+ {
+ myPrsLocation = TopLoc_Location (aConnected->LocalTransformation());
+ }
+
+ TopoDS_Shape aShape = ShapePrs->Shape();
+ if (aShape.IsNull())
+ {
+ Triangulation.Nullify();
+ Face.Nullify();
+ myFacesMap.Clear();
+ continue;
+ }
+
+ if (myFacesMap.IsEmpty())
+ {
+ // should be replaced by TopTools_OrientedShapeMaphasher to export correctly composed solids
+ // (e.g. shared face should be exported twice with different order of triangles
+ // and possible unique color)
+ TopExp::MapShapesAndAncestors (aShape, TopAbs_FACE, TopAbs_SHAPE, myFacesMap);
+ if (myFacesMap.IsEmpty())
+ {
+ Triangulation.Nullify();
+ Face.Nullify();
+ continue;
+ }
+
+ // register compounds generated by XCAFPrs_AISObject for grouping elements with the same style
+ const CafDataMapOfShapeColor& aColorsMap = ShapePrs->ShapeColors();
+ for (CafDataMapOfShapeColor::Iterator aShapeMapIter (aColorsMap); aShapeMapIter.More(); aShapeMapIter.Next())
+ {
+ if (aShapeMapIter.Key().ShapeType() != TopAbs_COMPOUND
+ || aShapeMapIter.Key().IsEqual (aShape))
+ {
+ continue;
+ }
+
+ for (TopExp_Explorer aCompFaceIter (aShapeMapIter.Key(), TopAbs_FACE); aCompFaceIter.More(); aCompFaceIter.Next())
+ {
+ const Standard_Integer anIndex = myFacesMap.FindIndex (aCompFaceIter.Current());
+ if (anIndex != 0)
+ {
+ myFacesMap.ChangeFromIndex (anIndex).Append (aShapeMapIter.Key());
+ }
+ }
+ }
+
+ myFaceIter = TopTools_IndexedDataMapOfShapeListOfShape::Iterator (myFacesMap);
+ }
+ for (; myFaceIter.More(); myFaceIter.Next())
+ {
+ Face = TopoDS::Face (myFaceIter.Key());
+ Triangulation = BRep_Tool::Triangulation (Face, myFaceLocation);
+ Trsf = myPrsLocation.Multiplied (myFaceLocation).Transformation();
+ if ( Triangulation.IsNull()
+ || Triangulation->Triangles().Length() == 0
+ || !Triangulation->HasUVNodes())
+ {
+ continue;
+ }
+
+ Handle(AIS_ColoredDrawer) aCustomDrawer;
+ if (!ShapePrs->FindCustomAspects (Face, aCustomDrawer))
+ {
+ for (TopTools_ListOfShape::Iterator aParentIter (myFaceIter.Value()); aParentIter.More(); aParentIter.Next())
+ {
+ if (ShapePrs->FindCustomAspects (aParentIter.Value(), aCustomDrawer))
+ {
+ break;
+ }
+ }
+ if (aCustomDrawer.IsNull())
+ {
+ ShapePrs->FindCustomAspects (aShape, aCustomDrawer);
+ }
+ }
+ Drawer = aCustomDrawer;
+ if (Drawer.IsNull())
+ {
+ Drawer = aShapePrs->Attributes();
+ }
+
+ myFaceIter.Next();
+ return;
+ }
+ Triangulation.Nullify();
+ Face.Nullify();
+ myFacesMap.Clear();
+ myFaceIter = TopTools_IndexedDataMapOfShapeListOfShape::Iterator();
+ Drawer.Nullify();
+ }
+}
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifndef FaceIterator_H
+#define FaceIterator_H
+
+#include <AIS_ListOfInteractive.hxx>
+#include <gp_Trsf.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopLoc_Location.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+
+class CafShapePrs;
+class Prs3d_Drawer;
+class Poly_Triangulation;
+
+//! Auxiliary class to iterate through triangulated faces in presentations list.
+class FaceIterator
+{
+
+public:
+
+ Handle(CafShapePrs) ShapePrs;
+ TopoDS_Face Face;
+ Handle(Prs3d_Drawer) Drawer;
+ Handle(Poly_Triangulation) Triangulation;
+ gp_Trsf Trsf;
+
+public:
+
+ //! Main constructor.
+ Standard_EXPORT FaceIterator (const AIS_ListOfInteractive& thePrsList);
+
+ //! Return true if iterator points to the valid triangulation.
+ bool More() const
+ {
+ return !Triangulation.IsNull();
+ }
+
+ //! Find next value.
+ Standard_EXPORT void Next();
+
+private:
+
+ AIS_ListOfInteractive::Iterator myPrsIter;
+ TopLoc_Location myPrsLocation;
+ TopTools_IndexedDataMapOfShapeListOfShape myFacesMap;
+ TopTools_IndexedDataMapOfShapeListOfShape::Iterator myFaceIter;
+ TopLoc_Location myFaceLocation;
+
+};
+
+#endif // FaceIterator_H
--- /dev/null
+// Copyright (c) 2014-2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <MeshDataSource.h>
+
+#include <Standard_CLocaleSentry.hxx>
+#include <MeshVS_Drawer.hxx>
+#include <MeshVS_DrawerAttribute.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_ProgressSentry.hxx>
+#include <NCollection_Handle.hxx>
+#include <TColgp_SequenceOfXYZ.hxx>
+#include <TColStd_DataMapOfIntegerReal.hxx>
+#include <TColStd_DataMapOfIntegerInteger.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
+#include <TCollection_ExtendedString.hxx>
+#include <Quantity_Color.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(MeshScalarProperty, Standard_Transient)
+
+IMPLEMENT_STANDARD_RTTIEXT(MeshDataSource, MeshVS_DataSource)
+
+//================================================================
+// Function : Constructor
+// Purpose :
+//================================================================
+MeshDataSource::MeshDataSource()
+{
+ //
+}
+
+//================================================================
+// Function : Clear
+// Purpose :
+//================================================================
+void MeshDataSource::Clear()
+{
+ myUsedNodes.Clear();
+ myFreeNodes.Clear();
+ myUsedElements.Clear();
+ myComments.Clear();
+ myNodes.Clear();
+ myNormals.Clear();
+ myNodesUV.Clear();
+ myNodalColors.Clear();
+ myElements.Clear();
+ myNodalQuantities.Clear();
+ myElementalQuantities.Clear();
+ myGroups.Clear();
+}
+
+//================================================================
+// Function : GetGeom
+// Purpose :
+//================================================================
+Standard_Boolean MeshDataSource::GetGeom (const Standard_Integer theID,
+ const Standard_Boolean theIsElement,
+ TColStd_Array1OfReal& theCoords,
+ Standard_Integer& theNbNodes,
+ MeshVS_EntityType& theType) const
+{
+ const Standard_Integer aLow = theCoords.Lower();
+ if (theIsElement)
+ {
+ if (theID < 0 || theID >= myUsedElements.Extent())
+ {
+ return Standard_False;
+ }
+
+ const Graphic3d_Vec4i& anElem = myElements.Value (theID);
+ theType = MeshVS_ET_Face;
+ theNbNodes = anElem[3] == -1 ? 3 : 4;
+ for (Standard_Integer aNodeIter = 0, aCoordIter = aLow - 1; aNodeIter < theNbNodes; ++aNodeIter)
+ {
+ const Graphic3d_Vec3& aNode = myNodes.Value (anElem[aNodeIter]);
+ theCoords (++aCoordIter) = aNode.x();
+ theCoords (++aCoordIter) = aNode.y();
+ theCoords (++aCoordIter) = aNode.z();
+ }
+ return Standard_True;
+ }
+ else if (theID < 0 || theID >= myUsedNodes.Extent())
+ {
+ return Standard_False;
+ }
+
+ theType = MeshVS_ET_Node;
+ theNbNodes = 1;
+ const Graphic3d_Vec3& aNode = myNodes.Value (theID);
+ theCoords (aLow) = aNode.x();
+ theCoords (aLow + 1) = aNode.y();
+ theCoords (aLow + 2) = aNode.z();
+ return Standard_True;
+}
+
+//================================================================
+// Function : GetNodesByElement
+// Purpose :
+//================================================================
+Standard_Boolean MeshDataSource::GetNodesByElement (const Standard_Integer theID,
+ TColStd_Array1OfInteger& theNodeIDs,
+ Standard_Integer& theNbNodes) const
+{
+ if (theID < 0 || theID >= myUsedElements.Extent())
+ {
+ return Standard_False;
+ }
+
+ const Graphic3d_Vec4i& anElem = myElements.Value (theID);
+ theNbNodes = anElem[3] == -1 ? 3 : 4;
+ if (theNodeIDs.Length() < theNbNodes)
+ {
+ return Standard_False;
+ }
+
+ const Standard_Integer aLow = theNodeIDs.Lower();
+ theNodeIDs (aLow) = anElem[0];
+ theNodeIDs (aLow + 1) = anElem[1];
+ theNodeIDs (aLow + 2) = anElem[2];
+ if (theNbNodes == 4)
+ {
+ theNodeIDs (aLow + 3) = anElem[3];
+ }
+ return Standard_True;
+}
+
+//================================================================
+// Function : GetNodeNormal
+// Purpose :
+//================================================================
+Standard_Boolean MeshDataSource::GetNodeNormal (const Standard_Integer theRankNode,
+ const Standard_Integer theElementId,
+ Standard_Real& theNX,
+ Standard_Real& theNY,
+ Standard_Real& theNZ) const
+{
+ if (theElementId < 0 || theElementId >= myUsedElements.Extent()
+ || !HasNormals())
+ {
+ return Standard_False;
+ }
+
+ const Graphic3d_Vec4i& anElem = myElements.Value (theElementId);
+ const Graphic3d_Vec3& aNorm = myNormals.Value (anElem[theRankNode - 1]);
+ theNX = Standard_Real(aNorm.x());
+ theNY = Standard_Real(aNorm.y());
+ theNZ = Standard_Real(aNorm.z());
+ return Standard_True;
+}
+
+inline void truncateToRange (Standard_Real& theValue,
+ const Standard_Real theLower,
+ const Standard_Real theUpper)
+{
+ if (theValue <= theLower)
+ {
+ theValue = theLower;
+ }
+ else if (theValue >= theUpper)
+ {
+ theValue = theUpper;
+ }
+}
+
+//================================================================
+// Function : FillPropertyBuilder
+// Purpose :
+//================================================================
+void MeshDataSource::FillPropertyBuilder (const Handle(MeshVS_PrsBuilder)& theBuilder,
+ const Handle(MeshScalarProperty)& theProperty) const
+{
+ Handle(MeshVS_NodalColorPrsBuilder) aNodalBuilder = Handle(MeshVS_NodalColorPrsBuilder) ::DownCast (theBuilder);
+ Handle(MeshVS_ElementalColorPrsBuilder) anElemBuilder = Handle(MeshVS_ElementalColorPrsBuilder)::DownCast (theBuilder);
+ if ((aNodalBuilder.IsNull() && anElemBuilder.IsNull())
+ || theProperty.IsNull())
+ {
+ return;
+ }
+
+ //theBuilder->UseTexture (Standard_True);
+ const Standard_Boolean isGrayscale = (theProperty->Name() == "intensity");
+
+ const Standard_Real aLowerValue = isGrayscale ? 0.0 : theProperty->LowerValue();
+ const Standard_Real aRange = isGrayscale ? 1.0 : theProperty->UpperValue() - theProperty->LowerValue();
+
+ const Graphic3d_Vec3d aScale00 = isGrayscale ? Graphic3d_Vec3d (0.0, 0.0, 0.0) : Graphic3d_Vec3d (0.0, 0.0, 1.0);
+ const Graphic3d_Vec3d aScale05 = isGrayscale ? Graphic3d_Vec3d (0.5, 0.5, 0.5) : Graphic3d_Vec3d (0.0, 1.0, 0.0);
+ const Graphic3d_Vec3d aScale10 = isGrayscale ? Graphic3d_Vec3d (1.0, 1.0, 1.0) : Graphic3d_Vec3d (1.0, 0.0, 0.0);
+ Graphic3d_Vec3d aColor;
+ for (Standard_Integer anElemIter = theProperty->LowerIndex(); anElemIter <= theProperty->UpperIndex(); ++anElemIter)
+ {
+ if (aRange <= Precision::Confusion())
+ {
+ aColor = aScale00;
+ }
+ else
+ {
+ Standard_Real aValue = (theProperty->Value (anElemIter) - aLowerValue) / aRange;
+ if (aValue < 0.5)
+ {
+ aValue *= 2.0;
+ aColor = aScale00 * (1.0 - aValue) + aScale05 * aValue;
+ }
+ else
+ {
+ aValue = (aValue - 0.5) * 2.0;
+ aColor = aScale05 * (1.0 - aValue) + aScale10 * aValue;
+ }
+ truncateToRange (aColor.r(), 0.0, 1.0);
+ truncateToRange (aColor.g(), 0.0, 1.0);
+ truncateToRange (aColor.b(), 0.0, 1.0);
+ }
+
+ const Quantity_Color aQColor (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
+ if (!aNodalBuilder.IsNull())
+ {
+ aNodalBuilder->SetColor (anElemIter, aQColor);
+ }
+ else
+ {
+ anElemBuilder->SetColor1 (anElemIter, aQColor);
+ }
+ }
+}
+
+//================================================================
+// Function : FillNodalColorsBuilder
+// Purpose :
+//================================================================
+void MeshDataSource::FillNodalColorsBuilder (const Handle(MeshVS_NodalColorPrsBuilder)& theBuilder) const
+{
+ if (theBuilder.IsNull()
+ || !HasNodalColors())
+ {
+ return;
+ }
+
+ for (Standard_Integer aNodeIter = myNodalColors.Lower(); aNodeIter <= myNodalColors.Upper(); ++aNodeIter)
+ {
+ const Graphic3d_Vec4ub& aColor = myNodalColors.Value (aNodeIter);
+ const Quantity_Color aQColor (aColor.r() / 255.0, aColor.g() / 255.0, aColor.b() / 255.0, Quantity_TOC_RGB);
+ theBuilder->SetColor (aNodeIter, aQColor);
+ }
+}
+
+//================================================================
+// Function : NbElements
+// Purpose :
+//================================================================
+void MeshDataSource::NbElements (Standard_Integer& theNbTris,
+ Standard_Integer& theNbQuads) const
+{
+ for (NCollection_Vector<Graphic3d_Vec4i>::Iterator anElemIter (myElements); anElemIter.More(); anElemIter.Next())
+ {
+ const Graphic3d_Vec4i& anElem = anElemIter.Value();
+ if (anElem[3] == -1)
+ {
+ ++theNbTris;
+ }
+ else
+ {
+ ++theNbQuads;
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifndef MeshDataSource_H
+#define MeshDataSource_H
+
+#include <MeshScalarProperty.h>
+
+#include <MeshVS_DataSource.hxx>
+#include <MeshVS_EntityType.hxx>
+#include <MeshVS_ElementalColorPrsBuilder.hxx>
+#include <MeshVS_NodalColorPrsBuilder.hxx>
+#include <MeshVS_PrsBuilder.hxx>
+#include <Message_ProgressIndicator.hxx>
+#include <NCollection_DataMap.hxx>
+#include <TColStd_HArray2OfInteger.hxx>
+#include <TColStd_HArray2OfReal.hxx>
+
+#if defined(_WIN32)
+ #define ftell64(a) _ftelli64(a)
+ #define fseek64(a,b,c) _fseeki64(a,b,c)
+#else
+ #define ftell64(a) ftello(a)
+ #define fseek64(a,b,c) fseeko(a,b,c)
+#endif
+
+//! Material definition.
+struct MeshMaterial
+{
+ Graphic3d_MaterialAspect Aspect;
+ TCollection_AsciiString Texture;
+};
+
+//! Mesh sub-group definition
+struct MeshGroup
+{
+ TCollection_AsciiString Name; //!< group name
+ Standard_Integer NodeLower; //!< index of lower Vertex
+ Standard_Integer NodeUpper; //!< index of upper Vertex
+ Standard_Integer ElemLower; //!< index of lower Element
+ Standard_Integer ElemUpper; //!< index of upper Element
+ MeshMaterial Material; //!< associated material
+
+ MeshGroup() : NodeLower (-1), NodeUpper (-1), ElemLower (-1), ElemUpper (-1) {}
+
+};
+
+//! The DataSource for working with mesh data.
+class MeshDataSource : public MeshVS_DataSource
+{
+
+public:
+
+ //! Empty constructor.
+ Standard_EXPORT MeshDataSource();
+
+ //! Clear mesh structure.
+ Standard_EXPORT void Clear();
+
+ //! Read the mesh from specified file.
+ virtual Standard_Boolean Read (const TCollection_AsciiString& theFile,
+ const Handle(Message_ProgressIndicator)& theProgress = NULL,
+ const Standard_Integer theIndexLimit = -1,
+ const Standard_Integer theMemoryLimitMiB = -1) = 0;
+
+ //! Returns geometry information about node or element by co-ordinates.
+ //! For element this method must return all its nodes co-ordinates in the strict order: X, Y, Z and
+ //! with nodes order is the same as in wire bounding the face or link.
+ //! @param theIsElement flag to retrieve information about Element or Node
+ //! @param theNbNodes number of nodes of element, it is recommended to return 1 for node
+ //! @param theType element type
+ Standard_EXPORT virtual Standard_Boolean GetGeom (const Standard_Integer theID,
+ const Standard_Boolean theIsElement,
+ TColStd_Array1OfReal& theCoords,
+ Standard_Integer& theNbNodes,
+ MeshVS_EntityType& theType) const Standard_OVERRIDE;
+
+ //! This method is similar to GetGeom, but returns only element or node type.
+ virtual Standard_Boolean GetGeomType (const Standard_Integer /*theID*/,
+ const Standard_Boolean theIsElement,
+ MeshVS_EntityType& theType) const Standard_OVERRIDE
+ {
+ theType = theIsElement ? MeshVS_ET_Face : MeshVS_ET_Node;
+ return Standard_True;
+ }
+
+ //! Return pointer which represents element or node data structure.
+ virtual Standard_Address GetAddr (const Standard_Integer /*theID*/,
+ const Standard_Boolean /*theIsElement*/) const Standard_OVERRIDE { return NULL; }
+
+ //! This method returns information about what node this element consist of.
+ Standard_EXPORT virtual Standard_Boolean GetNodesByElement (const Standard_Integer theID,
+ TColStd_Array1OfInteger& theNodeIDs,
+ Standard_Integer& theNbNodes) const Standard_OVERRIDE;
+
+ //! This method returns map of all nodes the object consist of.
+ virtual const TColStd_PackedMapOfInteger& GetAllNodes() const Standard_OVERRIDE { return myFreeNodes; }
+
+ //! This method returns map of all elements the object consist of.
+ virtual const TColStd_PackedMapOfInteger& GetAllElements() const Standard_OVERRIDE { return myUsedElements; }
+
+ //! This method return normal of node ranknode of face Id,
+ //! which is using for smooth shading presentation.
+ //! Returns false if normal isn't defined.
+ Standard_EXPORT virtual Standard_Boolean GetNodeNormal (const Standard_Integer theRankNode,
+ const Standard_Integer theElementId,
+ Standard_Real& theNX,
+ Standard_Real& theNY,
+ Standard_Real& theNZ) const Standard_OVERRIDE;
+
+public:
+
+ //! Return file comments.
+ const NCollection_Sequence<TCollection_AsciiString>& FileComments() const
+ {
+ return myComments;
+ }
+
+ //! Return list of sub-groups with materials.
+ const NCollection_Vector<MeshGroup>& Groups() { return myGroups; }
+
+ //! Return overall nodes number.
+ Standard_Integer NbNodes() const { return myNodes.Length(); }
+
+ //! Return vector of nodes.
+ const NCollection_Vector<Graphic3d_Vec3>& Nodes() const { return myNodes; }
+
+ //! Return overall elements number.
+ Standard_Integer NbElements() const { return myElements.Length(); }
+
+ //! Determine elements number.
+ Standard_EXPORT void NbElements (Standard_Integer& theNbTris,
+ Standard_Integer& theNbQuads) const;
+
+ //! Return vector of elements.
+ const NCollection_Vector<Graphic3d_Vec4i>& Elements() const { return myElements; }
+
+ //! Return per-node scalar properties.
+ const MeshScalarProperties& NodalQuantities() const { return myNodalQuantities; }
+
+ //! Return per-element scalar properties.
+ const MeshScalarProperties& ElementalQuantities() const { return myElementalQuantities; }
+
+ //! Return true if per-node colors have been assigned
+ Standard_Boolean HasNodalColors() const
+ {
+ return myNodalColors.Length() == myNodes.Length()
+ && !myNodalColors.IsEmpty();
+ }
+
+ //! Return vector of nodal colors (optional).
+ const NCollection_Vector<Graphic3d_Vec4ub>& NodalColors() const { return myNodalColors; }
+
+ //! Return true if per-node normals have been assigned
+ Standard_Boolean HasNormals() const
+ {
+ return myNormals.Length() == myNodes.Length()
+ && !myNormals.IsEmpty();
+ }
+
+ //! Return vector of nodal normals (optional).
+ const NCollection_Vector<Graphic3d_Vec3>& Normals() const { return myNormals; }
+
+ //! Return true if per-node UV parameters have been assigned
+ Standard_Boolean HasUV() const
+ {
+ return myNodesUV.Length() == myNodes.Length()
+ && !myNodesUV.IsEmpty();
+ }
+
+ //! Return vector of nodal UV parameters (optional).
+ const NCollection_Vector<Graphic3d_Vec2>& NodesUV() const { return myNodesUV; }
+
+ //! Return true if texture has been assigned.
+ Standard_Boolean HasTexture() const
+ {
+ Standard_Integer aTextureCount = 0;
+ for (auto anIter = myGroups.cbegin(); anIter != myGroups.cend(); ++anIter)
+ {
+ aTextureCount += (anIter->Material.Texture.IsEmpty()) ? 0 : 1;
+ }
+ return !myGroups.IsEmpty()
+ //&& !myGroups.First().Material.Texture.IsEmpty()
+ && aTextureCount
+ && HasUV();
+ }
+
+ //! Return assigned texture.
+ TCollection_AsciiString Texture() const
+ {
+ return HasTexture() ? myGroups.First().Material.Texture : "";
+ }
+
+public:
+
+ //! Fill-in nodal (MeshVS_NodalColorPrsBuilder) or elemental (MeshVS_ElementalColorPrsBuilder) builder.
+ Standard_EXPORT void FillPropertyBuilder (const Handle(MeshVS_PrsBuilder)& theBuilder,
+ const Handle(MeshScalarProperty)& theProperty) const;
+
+ //! Fill-in nodal (MeshVS_NodalColorPrsBuilder) builder by colors.
+ Standard_EXPORT void FillNodalColorsBuilder (const Handle(MeshVS_NodalColorPrsBuilder)& theBuilder) const;
+
+public:
+
+ //! Append new vertex.
+ void AddNodePosition (const Graphic3d_Vec3& thePosition)
+ {
+ myNodes.Append (thePosition);
+ myUsedNodes.Add (myNodes.Upper());
+ }
+
+ //! Append new vertex.
+ void AddNodePosition (const gp_XYZ& thePosition)
+ {
+ myNodes.Append (Graphic3d_Vec3 ((float )thePosition.X(),
+ (float )thePosition.Y(),
+ (float )thePosition.Z()));
+ myUsedNodes.Add (myNodes.Upper());
+ }
+
+ //! Append new normal.
+ void AddNodeNormal (const Graphic3d_Vec3& theNormal)
+ {
+ myNormals.Append (theNormal);
+ }
+
+ //! Append new normal.
+ void AddNodeNormal (const gp_XYZ& theNormal)
+ {
+ myNormals.Append (Graphic3d_Vec3 ((float )theNormal.X(),
+ (float )theNormal.Y(),
+ (float )theNormal.Z()));
+ }
+
+ //! Append new UV parameters pair.
+ void AddNodeUV (const Graphic3d_Vec2& theUV)
+ {
+ myNodesUV.Append (theUV);
+ }
+
+ //! Append new color.
+ void AddNodeColor (const Graphic3d_Vec4ub& theColor)
+ {
+ myNodalColors.Append (theColor);
+ }
+
+ //! Append node property.
+ void AddNodeProperty (const Standard_Integer thePropIndex,
+ const Standard_Real theValue)
+ {
+ myNodalQuantities.ChangeValue (thePropIndex)->AppendValue (theValue);
+ }
+
+ //! Append new element.
+ void AddElement (const Graphic3d_Vec4i& theNodeIndices)
+ {
+ myElements.Append (theNodeIndices);
+ myUsedElements.Add (myElements.Upper());
+ }
+
+ //! Append element property.
+ void AddElementProperty (const Standard_Integer thePropIndex,
+ const Standard_Real theValue)
+ {
+ myElementalQuantities.ChangeValue (thePropIndex)->AppendValue (theValue);
+ }
+
+protected:
+
+ TColStd_PackedMapOfInteger myUsedNodes; //!< used node indices
+ TColStd_PackedMapOfInteger myFreeNodes; //!< indices of free nodes
+ TColStd_PackedMapOfInteger myUsedElements; //!< used element indices
+ NCollection_Sequence<TCollection_AsciiString>
+ myComments; //!< file comments
+ NCollection_Vector<Graphic3d_Vec3> myNodes; //!< vector of nodes
+ NCollection_Vector<Graphic3d_Vec3> myNormals; //!< vector of nodal normals (optional)
+ NCollection_Vector<Graphic3d_Vec2> myNodesUV; //!< vector of UV nodes (optional)
+ NCollection_Vector<Graphic3d_Vec4ub> myNodalColors; //!< vector of nodal colors (optional)
+ NCollection_Vector<Graphic3d_Vec4i> myElements; //!< vector of elements
+ MeshScalarProperties myNodalQuantities; //!< per-node scalar quantities
+ MeshScalarProperties myElementalQuantities; //!< per-element scalar quantities
+
+ NCollection_Vector<MeshGroup> myGroups; //!< sub-groups with materials
+
+public:
+
+ DEFINE_STANDARD_RTTIEXT(MeshDataSource, MeshVS_DataSource)
+
+};
+
+DEFINE_STANDARD_HANDLE(MeshDataSource, MeshVS_DataSource)
+
+#endif // MeshDataSource_H
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#include "MeshPresentation.h"
+
+#include <MeshVS_Drawer.hxx>
+#include <MeshVS_DrawerAttribute.hxx>
+#include <MeshVS_Tool.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(MeshPresentation, MeshVS_Mesh)
+
+// =======================================================================
+// function : MeshPresentation
+// purpose :
+// =======================================================================
+MeshPresentation::MeshPresentation()
+{}
+
+// =======================================================================
+// function : SetMaterial
+// purpose :
+// =======================================================================
+void MeshPresentation::SetMaterial (const Graphic3d_MaterialAspect& theMat)
+{
+ Handle(MeshVS_Drawer) aDrawer = GetDrawer();
+ if (aDrawer.IsNull())
+ {
+ return;
+ }
+
+ aDrawer->SetMaterial (MeshVS_DA_FrontMaterial, theMat);
+ aDrawer->SetMaterial (MeshVS_DA_BackMaterial, theMat);
+ Standard_Boolean hasReflection = Standard_True;
+ aDrawer->GetBoolean (MeshVS_DA_Reflection, hasReflection);
+ Graphic3d_MaterialAspect aMat = theMat;
+ if (!hasReflection)
+ {
+ aMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
+ aMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
+ aMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
+ aMat.SetReflectionModeOff (Graphic3d_TOR_EMISSION);
+ }
+ Handle(Graphic3d_AspectFillArea3d) anAreaAsp = MeshVS_Tool::CreateAspectFillArea3d (aDrawer, aMat);
+ Handle(Graphic3d_AspectLine3d) anOldLineAsp = new Graphic3d_AspectLine3d();
+ Handle(Graphic3d_AspectText3d) anOldTextAsp = new Graphic3d_AspectText3d();
+ Handle(Graphic3d_AspectMarker3d) anOldPntAsp = new Graphic3d_AspectMarker3d();
+ Handle(Graphic3d_AspectFillArea3d) anOldAreaAps = new Graphic3d_AspectFillArea3d();
+
+ const PrsMgr_Presentations& aPrsList = Presentations();
+ for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
+ {
+ const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
+ if (aPrsModed.Mode() == MeshVS_DMF_WireFrame
+ || aPrsModed.Mode() == MeshVS_DMF_NodalColorDataPrs
+ || aPrsModed.Mode() == MeshVS_DMF_ElementalColorDataPrs)
+ {
+ continue;
+ }
+
+ const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
+ for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
+ {
+ const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
+ if (!aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
+ {
+ continue;
+ }
+
+ aGroup->GroupPrimitivesAspect (anOldLineAsp, anOldTextAsp, anOldPntAsp, anOldAreaAps);
+ anAreaAsp->SetTextureMap (anOldAreaAps->TextureMap());
+ if (anOldAreaAps->TextureMapState())
+ {
+ anAreaAsp->SetTextureMapOn();
+ }
+ else
+ {
+ anAreaAsp->SetTextureMapOff();
+ }
+
+ aGroup->SetGroupPrimitivesAspect (anAreaAsp);
+ }
+ }
+}
+
+// =======================================================================
+// function : SetClosed
+// purpose :
+// =======================================================================
+void MeshPresentation::SetClosed (const bool theIsClosed)
+{
+ const PrsMgr_Presentations& aPrsList = Presentations();
+ for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
+ {
+ const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
+ if (aPrsModed.Mode() == MeshVS_DMF_WireFrame
+ || aPrsModed.Mode() == MeshVS_DMF_Shrink)
+ {
+ continue;
+ }
+
+ const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
+ for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
+ {
+ const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
+ if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
+ {
+ aGroup->SetClosed (theIsClosed);
+ }
+ }
+ }
+}
+
+// =======================================================================
+// function : SetClosed
+// purpose :
+// =======================================================================
+void MeshPresentation::Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode)
+{
+ MeshVS_Mesh::Compute (thePrsMgr, thePrs, theMode);
+
+ // mark mesh as closed without checks for Capping algorithm but without suppressing back faces,
+ // thus artifacts on shells will appear only with capping option turned on and not in normal mode
+ SetClosed (true);
+}
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifndef MeshPresentation_H
+#define MeshPresentation_H
+
+#include <MeshVS_Mesh.hxx>
+
+//! Interactive presentation for the mesh.
+class MeshPresentation : public MeshVS_Mesh
+{
+public:
+
+ //! Empty constructor.
+ Standard_EXPORT MeshPresentation();
+
+ //! Return presentation type.
+ virtual AIS_KindOfInteractive Type() const Standard_OVERRIDE { return AIS_KOI_Object; }
+
+ //! Return presentation signature.
+ virtual Standard_Integer Signature() const Standard_OVERRIDE { return 0; }
+
+ //! Setup new material.
+ virtual void SetMaterial (const Graphic3d_NameOfMaterial theName) Standard_OVERRIDE
+ {
+ SetMaterial (Graphic3d_MaterialAspect (theName));
+ }
+
+ //! Setup new material.
+ virtual void SetMaterial (const Graphic3d_MaterialAspect& theMat) Standard_OVERRIDE;
+
+ //! Override presentation compute.
+ virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
+ const Handle(Prs3d_Presentation)& thePrs,
+ const Standard_Integer theMode) Standard_OVERRIDE;
+
+ //! Setup closed flag.
+ void SetClosed (const bool theIsClosed);
+
+public:
+
+ DEFINE_STANDARD_RTTIEXT(MeshPresentation, MeshVS_Mesh)
+
+};
+
+#endif // MeshPresentation_H
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifdef __APPLE__
+ #import <TargetConditionals.h>
+#endif
+
+#include "MeshPrsBuilder.h"
+
+#include <Aspect_TypeOfLine.hxx>
+#include <MeshVS_Buffer.hxx>
+#include <MeshVS_DataSource.hxx>
+#include <MeshVS_Drawer.hxx>
+#include <MeshVS_DrawerAttribute.hxx>
+#include <MeshVS_EntityType.hxx>
+#include <MeshVS_Mesh.hxx>
+#include <MeshVS_Tool.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <Graphic3d_ArrayOfTriangles.hxx>
+#include <Graphic3d_ArrayOfSegments.hxx>
+#include <Graphic3d_AspectFillArea3d.hxx>
+#include <Graphic3d_AspectLine3d.hxx>
+#include <Graphic3d_Texture2Dmanual.hxx>
+#include <Image_PixMap.hxx>
+#include <Prs3d_Drawer.hxx>
+#include <Prs3d_ShadingAspect.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+#include <TColStd_HPackedMapOfInteger.hxx>
+#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
+
+static const int THE_NB_COLORS = 128;
+
+//! Auxiliary wrapper
+class MeshTexture : public Graphic3d_Texture2Dmanual
+{
+public:
+
+ //! Main constructor.
+ MeshTexture (const TCollection_AsciiString& theFileName)
+ : Graphic3d_Texture2Dmanual (theFileName), myPathOrig (theFileName) {}
+
+ //! Image reader.
+ virtual Handle(Image_PixMap) GetImage() const Standard_OVERRIDE
+ {
+ #if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(__ANDROID__)
+ // mobile version is build without FreeImage to reduce binaries size - use Qt instead
+ Handle(PixMapQt) anImage = new PixMapQt();
+ if(!anImage->Load (myPathOrig))
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("Can not read image ") + myPathOrig + "!", Message_Fail);
+ return Handle(Image_PixMap)();
+ }
+ return anImage;
+ #else
+ return Graphic3d_Texture2Dmanual::GetImage();
+ #endif
+ }
+
+private:
+
+ TCollection_AsciiString myPathOrig;
+
+public:
+
+ DEFINE_STANDARD_RTTIEXT(MeshTexture, Graphic3d_Texture2Dmanual)
+
+};
+
+DEFINE_STANDARD_HANDLE(MeshTexture, Graphic3d_Texture2Dmanual)
+
+IMPLEMENT_STANDARD_RTTIEXT(MeshPrsTexture, Graphic3d_Texture2D)
+IMPLEMENT_STANDARD_RTTIEXT(MeshTexture, Graphic3d_Texture2Dmanual)
+IMPLEMENT_STANDARD_RTTIEXT(MeshPrsBuilder, MeshVS_PrsBuilder)
+
+//================================================================
+// Function : MeshPrsBuilder
+// Purpose :
+//================================================================
+MeshPrsBuilder::MeshPrsBuilder (const Handle(MeshVS_Mesh)& theMesh,
+ const MeshVS_DisplayModeFlags& theFlags)
+: MeshVS_PrsBuilder (theMesh, theFlags, Handle(MeshVS_DataSource)(), -1, MeshVS_BP_NodalColor),
+ myIsElemental (Standard_False),
+ myIsGrayscale (Standard_False),
+ myRangeFrom (0.0),
+ myRangeTo (1.0),
+ myToMapTexture(Standard_False),
+ myToFlipV (Standard_False)
+{
+#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(__ANDROID__)
+ myToFlipV = Standard_True;
+#else
+ myToFlipV = Standard_False;
+#endif
+
+ SetExcluding (Standard_True);
+}
+
+//================================================================
+// Function : buildTextured
+// Purpose :
+//================================================================
+void MeshPrsBuilder::buildTextured (const Handle(Prs3d_Presentation)& thePrs,
+ const TColStd_PackedMapOfInteger& theIDs,
+ TColStd_PackedMapOfInteger& theIDsToExclude) const
+
+{
+ myPrsGroup.Nullify();
+
+ Handle(MeshDataSource) aSource = Handle(MeshDataSource)::DownCast (GetDataSource());
+ Handle(MeshVS_Drawer) aDrawer = GetDrawer();
+ if (aSource.IsNull()
+ || aDrawer.IsNull())
+ {
+ return;
+ }
+
+ // subtract the hidden elements and ids to exclude (to minimize allocated memory)
+ TColStd_PackedMapOfInteger anIDs;
+ anIDs.Assign (theIDs);
+ Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
+ if (!aHiddenElems.IsNull())
+ {
+ anIDs.Subtract (aHiddenElems->Map());
+ }
+ anIDs.Subtract (theIDsToExclude);
+
+ Standard_Boolean hasReflection = Standard_True;
+ Standard_Boolean isSmoothShading = Standard_False;
+ aDrawer->GetBoolean (MeshVS_DA_Reflection, hasReflection);
+ aDrawer->GetBoolean (MeshVS_DA_SmoothShading, isSmoothShading);
+
+ MeshGroup aFullGroup;
+ aFullGroup.NodeLower = aSource->Nodes().Lower();
+ aFullGroup.NodeUpper = aSource->Nodes().Upper();
+ aFullGroup.ElemLower = aSource->Elements().Lower();
+ aFullGroup.ElemUpper = aSource->Elements().Upper();
+ for (Standard_Integer aGroupIter = 0; aGroupIter == 0 || aGroupIter <= aSource->Groups().Upper(); ++aGroupIter)
+ {
+ const MeshGroup& aGroup = !aSource->Groups().IsEmpty() ? aSource->Groups().Value (aGroupIter) : aFullGroup;
+ const Standard_Integer aNbNodes = aGroup.NodeUpper - aGroup.NodeLower + 1;
+ if (aGroup.NodeLower < 0
+ || aGroup.NodeUpper < 0
+ || aGroup.ElemLower < 0
+ || aGroup.ElemUpper < 0
+ || aNbNodes < 1)
+ {
+ continue;
+ }
+
+ Handle(MeshTexture) aTexture;
+ if (!aGroup.Material.Texture.IsEmpty()
+ && myToMapTexture
+ && aSource->HasUV())
+ {
+ aTexture = new MeshTexture (aGroup.Material.Texture);
+ }
+
+ Standard_Integer aNbTris = 0;
+ for (Standard_Integer anElemIter = aGroup.ElemLower; anElemIter <= aGroup.ElemUpper; ++anElemIter)
+ {
+ if (!anIDs.Contains (anElemIter)) { continue; }
+ const Graphic3d_Vec4i& anElem = aSource->Elements().Value (anElemIter);
+ ++aNbTris;
+ if (anElem[3] != -1)
+ {
+ ++aNbTris;
+ }
+ }
+ if (aNbTris < 1)
+ {
+ continue;
+ }
+
+ Handle(Graphic3d_ArrayOfTriangles) aTriangles = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3,
+ aSource->HasNormals() || isSmoothShading, Standard_False, !aTexture.IsNull());
+ // fill nodes
+ if (!aTexture.IsNull())
+ {
+ if (aSource->HasNormals())
+ {
+ for (Standard_Integer aNodeIter = aGroup.NodeLower; aNodeIter <= aGroup.NodeUpper; ++aNodeIter)
+ {
+ const Graphic3d_Vec3& aNode = aSource->Nodes() .Value (aNodeIter);
+ const Graphic3d_Vec3& aNorm = aSource->Normals().Value (aNodeIter);
+ const Graphic3d_Vec2& anUV = aSource->NodesUV().Value (aNodeIter);
+ const float aV = myToFlipV ? (1.0f - anUV.y()) : anUV.y();
+ aTriangles->AddVertex (aNode.x(), aNode.y(), aNode.z(),
+ aNorm.x(), aNorm.y(), aNorm.z(),
+ anUV.x(), aV);
+ }
+ }
+ else
+ {
+ for (Standard_Integer aNodeIter = aGroup.NodeLower; aNodeIter <= aGroup.NodeUpper; ++aNodeIter)
+ {
+ const Graphic3d_Vec3& aNode = aSource->Nodes() .Value (aNodeIter);
+ const Graphic3d_Vec2& anUV = aSource->NodesUV().Value (aNodeIter);
+ const float aV = myToFlipV ? (1.0f - anUV.y()) : anUV.y();
+ aTriangles->AddVertex (aNode.x(), aNode.y(), aNode.z(),
+ anUV.x(), aV);
+ }
+ }
+ }
+ else
+ {
+ if (aSource->HasNormals())
+ {
+ for (Standard_Integer aNodeIter = aGroup.NodeLower; aNodeIter <= aGroup.NodeUpper; ++aNodeIter)
+ {
+ const Graphic3d_Vec3& aNode = aSource->Nodes() .Value (aNodeIter);
+ const Graphic3d_Vec3& aNorm = aSource->Normals().Value (aNodeIter);
+ aTriangles->AddVertex (aNode.x(), aNode.y(), aNode.z(),
+ aNorm.x(), aNorm.y(), aNorm.z());
+ }
+ }
+ else
+ {
+ for (Standard_Integer aNodeIter = aGroup.NodeLower; aNodeIter <= aGroup.NodeUpper; ++aNodeIter)
+ {
+ const Graphic3d_Vec3& aNode = aSource->Nodes().Value (aNodeIter);
+ aTriangles->AddVertex (aNode.x(), aNode.y(), aNode.z());
+ }
+ }
+ }
+
+ // fill indices
+ for (Standard_Integer anElemIter = aGroup.ElemLower; anElemIter <= aGroup.ElemUpper; ++anElemIter)
+ {
+ if (!anIDs.Contains (anElemIter)) { continue; }
+ const Graphic3d_Vec4i& anElem = aSource->Elements().Value (anElemIter);
+ aTriangles->AddEdge (anElem[0] + 1 - aGroup.NodeLower);
+ aTriangles->AddEdge (anElem[1] + 1 - aGroup.NodeLower);
+ aTriangles->AddEdge (anElem[2] + 1 - aGroup.NodeLower);
+ if (anElem[3] != -1)
+ {
+ aTriangles->AddEdge (anElem[0] + 1 - aGroup.NodeLower);
+ aTriangles->AddEdge (anElem[2] + 1 - aGroup.NodeLower);
+ aTriangles->AddEdge (anElem[3] + 1 - aGroup.NodeLower);
+ }
+ }
+
+ // reconstruct normals
+ if (!aSource->HasNormals() && isSmoothShading)
+ {
+ // compute normal at each node, taking into account size of each element (e.g. without pre-normalization)
+ for (Standard_Integer anElemIter = aGroup.ElemLower; anElemIter <= aGroup.ElemUpper; ++anElemIter)
+ {
+ if (!anIDs.Contains (anElemIter)) { continue; }
+ const Graphic3d_Vec4i& anElem = aSource->Elements().Value (anElemIter);
+
+ const Graphic3d_Vec3& aNode0 = aSource->Nodes().Value (anElem[0]);
+ const Graphic3d_Vec3& aNode1 = aSource->Nodes().Value (anElem[1]);
+ const Graphic3d_Vec3& aNode2 = aSource->Nodes().Value (anElem[2]);
+
+ const Graphic3d_Vec3 aVec01 = aNode1 - aNode0;
+ const Graphic3d_Vec3 aVec02 = aNode2 - aNode0;
+ const Graphic3d_Vec3 aCross = Graphic3d_Vec3::Cross (aVec01, aVec02);
+ const Graphic3d_Vec3d aTriNorm (aCross.x(), aCross.y(), aCross.z());
+ const Standard_Integer aNbElemNodes = anElem[3] != -1 ? 4 : 3;
+ Graphic3d_Vec3d aNorm;
+ for (Standard_Integer aNodeIter = 0; aNodeIter < aNbElemNodes; ++aNodeIter)
+ {
+ // Graphic3d_ArrayOfPrimitives zeroes values in costructor
+ const Standard_Integer aNodeIndex = anElem[aNodeIter] + 1 - aGroup.NodeLower;
+ aTriangles->VertexNormal (aNodeIndex, aNorm.x(), aNorm.y(), aNorm.z());
+ aNorm += aTriNorm;
+ aTriangles->SetVertexNormal (aNodeIndex, aNorm.x(), aNorm.y(), aNorm.z());
+ }
+ }
+
+ // normalize
+ for (Standard_Integer anElemIter = aGroup.ElemLower; anElemIter <= aGroup.ElemUpper; ++anElemIter)
+ {
+ if (!anIDs.Contains (anElemIter)) { continue; }
+ const Graphic3d_Vec4i& anElem = aSource->Elements().Value (anElemIter);
+ const Standard_Integer aNbElemNodes = anElem[3] != -1 ? 4 : 3;
+ Graphic3d_Vec3d aNorm;
+ for (Standard_Integer aNodeIter = 0; aNodeIter < aNbElemNodes; ++aNodeIter)
+ {
+ const Standard_Integer aNodeIndex = anElem[aNodeIter] + 1 - aGroup.NodeLower;
+ aTriangles->VertexNormal (aNodeIndex, aNorm.x(), aNorm.y(), aNorm.z());
+ aNorm.Normalize();
+ aTriangles->SetVertexNormal (aNodeIndex, aNorm.x(), aNorm.y(), aNorm.z());
+ }
+ }
+ }
+
+ Graphic3d_MaterialAspect aMat[2];
+ aDrawer->GetMaterial(MeshVS_DA_FrontMaterial, aMat[0]);
+ aDrawer->GetMaterial(MeshVS_DA_BackMaterial, aMat[1]);
+ if (aMat[0].Name() == Graphic3d_NOM_DEFAULT
+ && aGroup.Material.Aspect.Name() != Graphic3d_NOM_DEFAULT)
+ {
+ aMat[0] = aGroup.Material.Aspect;
+ aMat[1] = aGroup.Material.Aspect;
+ }
+ if (!hasReflection)
+ {
+ aMat[0].SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
+ aMat[0].SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
+ aMat[0].SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
+ aMat[0].SetReflectionModeOff (Graphic3d_TOR_EMISSION);
+ }
+
+ Handle(Graphic3d_AspectFillArea3d) anAreaAsp = MeshVS_Tool::CreateAspectFillArea3d (aDrawer, aMat[0]);
+ if (!aTexture.IsNull())
+ {
+ anAreaAsp->SetTextureMap (aTexture);
+ anAreaAsp->SetTextureMapOn();
+ }
+
+ Handle(Graphic3d_Group) aPrsGroup = thePrs->NewGroup();
+ aPrsGroup->SetGroupPrimitivesAspect (anAreaAsp);
+ aPrsGroup->AddPrimitiveArray (aTriangles);
+ }
+}
+
+//================================================================
+// Function : Build
+// Purpose :
+//================================================================
+void MeshPrsBuilder::Build (const Handle(Prs3d_Presentation)& thePrs,
+ const TColStd_PackedMapOfInteger& theIDs,
+ TColStd_PackedMapOfInteger& theIDsToExclude,
+ const Standard_Boolean theIsElement,
+ const Standard_Integer theDisplayMode) const
+{
+ myPrsGroup.Nullify();
+ if (myProperty.IsNull())
+ {
+ buildTextured (thePrs, theIDs, theIDsToExclude);
+ return;
+ }
+
+ Handle(MeshVS_DataSource) aSource = GetDataSource();
+ Handle(MeshVS_Drawer) aDrawer = GetDrawer();
+ if (aSource.IsNull()
+ || aDrawer.IsNull()
+ || myProperty.IsNull())
+ {
+ return;
+ }
+
+ Standard_Integer aMaxFaceNodes = 0;
+ if (!aDrawer->GetInteger (MeshVS_DA_MaxFaceNodes, aMaxFaceNodes)
+ || aMaxFaceNodes <= 0 )
+ {
+ return;
+ }
+
+ MeshVS_Buffer aCoordsBuf (3 * aMaxFaceNodes * sizeof(Standard_Real));
+ TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * aMaxFaceNodes);
+ if ((theDisplayMode & GetFlags()) == 0
+ || !theIsElement)
+ {
+ return;
+ }
+
+ const Standard_Real aLowerValue = propertyLowerValue();
+ const Standard_Real anUpperValue = propertyUpperValue();
+ const Standard_Real aRange = anUpperValue - aLowerValue;
+
+ // subtract the hidden elements and ids to exclude (to minimize allocated memory)
+ TColStd_PackedMapOfInteger anIDs;
+ anIDs.Assign (theIDs);
+ Handle(TColStd_HPackedMapOfInteger) aHiddenElems = myParentMesh->GetHiddenElems();
+ if (!aHiddenElems.IsNull())
+ {
+ anIDs.Subtract (aHiddenElems->Map());
+ }
+ anIDs.Subtract (theIDsToExclude);
+
+ Standard_Boolean isReflect = Standard_False, isMeshSmoothShading = Standard_False;
+ aDrawer->GetBoolean (MeshVS_DA_ColorReflection, isReflect);
+ aDrawer->GetBoolean (MeshVS_DA_SmoothShading, isMeshSmoothShading);
+
+ // Following parameter are used for texture presentation only
+ int nbColors = THE_NB_COLORS;///myTextureColorMap.Length(); // Number of colors from color map
+ int nbTextureColors = nbColors; // Number of colors in texture (it will be pow of 2)
+
+ Graphic3d_MaterialAspect aMaterials[2] =
+ {
+ Graphic3d_MaterialAspect (Graphic3d_NOM_PLASTIC),
+ Graphic3d_MaterialAspect (Graphic3d_NOM_PLASTIC)
+ };
+ for (Standard_Integer aMatIter = 0; aMatIter < 2; ++aMatIter)
+ {
+ Graphic3d_MaterialAspect& aMat = aMaterials[aMatIter];
+ if (!isReflect)
+ {
+ aMat.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
+ aMat.SetReflectionModeOff (Graphic3d_TOR_AMBIENT);
+ aMat.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE);
+ aMat.SetReflectionModeOff (Graphic3d_TOR_EMISSION);
+ }
+ else
+ {
+ aMat.SetAmbient (0.5);
+ aMat.SetDiffuse (0.5);
+ aMat.SetSpecular(0.0);
+ aMat.SetEmissive(0.0);
+ }
+ }
+
+ Standard_Integer aNbFacePrimitives = 0;
+ Standard_Integer aNbEdgePrimitives = 0;
+ for (TColStd_MapIteratorOfPackedMapOfInteger it (anIDs); it.More(); it.Next())
+ {
+ MeshVS_EntityType aType = MeshVS_ET_NONE;
+ Standard_Integer aNbNodes = 0;
+ if (!aSource->GetGeom (it.Key(), Standard_True, aCoords, aNbNodes, aType)
+ || aType != MeshVS_ET_Face)
+ {
+ continue;
+ }
+
+ aNbEdgePrimitives += aNbNodes; // add edge segments
+ aNbFacePrimitives += aNbNodes - 2; // add face triangles
+ }
+
+ Standard_Boolean toShowEdges = Standard_True;
+ aDrawer->GetBoolean (MeshVS_DA_ShowEdges, toShowEdges);
+
+ // Here we do not use indices arrays because they are not effective for some mesh
+ // drawing modes: shrinking mode (displaces the vertices inside the polygon), 3D
+ // cell rendering (normal interpolation is not always applicable - flat shading),
+ // elemental coloring (color interpolation is impossible)
+
+ Handle(Graphic3d_ArrayOfTriangles) aFaceTriangles = new Graphic3d_ArrayOfTriangles (aNbFacePrimitives * 3, 0,
+ Standard_True, Standard_False, Standard_True);
+ Handle(Graphic3d_ArrayOfSegments) anEdgeSegments;
+ if (toShowEdges)
+ {
+ anEdgeSegments = new Graphic3d_ArrayOfSegments (aNbEdgePrimitives * 2);
+ }
+
+ gp_Pnt P, Start;
+ Standard_Real aMin = gp::Resolution() * gp::Resolution();
+ gp_Dir aDefNorm = gp::DZ();
+
+ TColStd_Array1OfInteger aNodes (1, 10);
+ for (TColStd_MapIteratorOfPackedMapOfInteger it (anIDs); it.More(); it.Next())
+ {
+ Standard_Integer aKey = it.Key();
+ Standard_Integer aNbNodes = 0;
+ MeshVS_EntityType aType = MeshVS_ET_NONE;
+ if (!aSource->GetGeom (aKey, Standard_True, aCoords, aNbNodes, aType)
+ || aType != MeshVS_ET_Face
+ || aNbNodes > 10
+ || !aSource->GetNodesByElement (aKey, aNodes, aNbNodes))
+ {
+ continue;
+ }
+
+ // Preparing normal(s) to show reflections if requested
+ Handle(TColStd_HArray1OfReal) aNormals;
+ Standard_Boolean hasNormals = isReflect
+ && aSource->GetNormalsByElement (aKey, isMeshSmoothShading, aMaxFaceNodes, aNormals);
+
+ for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbNodes - 2; ++aNodeIdx)
+ {
+ for (Standard_Integer aSubIdx = 0; aSubIdx < 3; ++aSubIdx)
+ {
+ gp_XYZ aPnt (aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
+ aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
+ aCoords (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
+
+ gp_Vec aNorm = aDefNorm;
+ if (hasNormals)
+ {
+ gp_Vec aTestNorm (aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 1),
+ aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 2),
+ aNormals->Value (3 * (aSubIdx == 0 ? 0 : (aNodeIdx + aSubIdx)) + 3));
+
+ if (aTestNorm.SquareMagnitude() > aMin)
+ {
+ aNorm = gp_Dir (aTestNorm);
+ }
+ }
+
+ // retrieve nodal value
+ Standard_Integer aNodeIndex = aKey;
+ if (!myIsElemental)
+ {
+ aNodeIndex = aNodes (aSubIdx == 0 ? 1 : (aNodeIdx + aSubIdx + 1));
+ }
+
+ Standard_Real aTexCoordU = 0.25;
+ Standard_Real aTexCoordV = 0.25;
+ const Standard_Real aValue = myProperty->Value (aNodeIndex);
+ if (aRange > gp::Resolution()
+ && !IsNaN (aValue))
+ {
+ const Standard_Real aNormVal = (aValue - aLowerValue) / aRange;
+ aTexCoordU = (aNormVal * (nbColors - 1.0) + 0.5) / nbTextureColors;
+ aTexCoordV = 0.75;
+ }
+
+ // Transform texture coordinate in accordance with number of colors specified
+ // by upper level and real size of OpenGL texture. The OpenGL texture has border
+ // colors interpolated with the colors from the color map, thats why we need to
+ // shrink texture coordinates around the middle point to exclude areas where the
+ // map colors are interpolated with the borders color
+ aFaceTriangles->AddVertex (aPnt, aNorm, gp_Pnt2d (aTexCoordU, aTexCoordV));
+ }
+ }
+
+ if (!anEdgeSegments.IsNull())
+ {
+ for (Standard_Integer aNodeIdx = 0; aNodeIdx < aNbNodes; ++aNodeIdx) // border segmentation
+ {
+ const Standard_Integer aNextIdx = (aNodeIdx + 1) % aNbNodes;
+
+ anEdgeSegments->AddVertex (aCoords (3 * aNodeIdx + 1),
+ aCoords (3 * aNodeIdx + 2),
+ aCoords (3 * aNodeIdx + 3));
+
+ anEdgeSegments->AddVertex (aCoords (3 * aNextIdx + 1),
+ aCoords (3 * aNextIdx + 2),
+ aCoords (3 * aNextIdx + 3));
+ }
+ }
+
+ // if IsExcludingOn then presentation must not be built by other builders
+ if (IsExcludingOn())
+ {
+ theIDsToExclude.Add (aKey);
+ }
+ }
+
+ Aspect_TypeOfLine anEdgeType = Aspect_TOL_SOLID;
+ Standard_Integer anEdgeInt;
+ Standard_Real anEdgeWidth;
+ Quantity_Color anInteriorColor, anEdgeColor, aLineColor;
+
+ aDrawer->GetColor (MeshVS_DA_InteriorColor, anInteriorColor);
+ aDrawer->GetColor (MeshVS_DA_EdgeColor, anEdgeColor);
+ aDrawer->GetColor (MeshVS_DA_BeamColor, aLineColor);
+ aDrawer->GetDouble (MeshVS_DA_EdgeWidth, anEdgeWidth);
+
+ if (aDrawer->GetInteger (MeshVS_DA_EdgeType, anEdgeInt))
+ {
+ anEdgeType = (Aspect_TypeOfLine )anEdgeInt;
+ }
+
+ Handle(Prs3d_Drawer) aPrs3dDrawer = myParentMesh->Attributes();
+ if (aPrs3dDrawer.IsNull())
+ {
+ return;
+ }
+
+ aPrs3dDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
+
+ myFillAsp = new Graphic3d_AspectFillArea3d();
+ *myFillAsp = *aPrs3dDrawer->ShadingAspect()->Aspect();
+
+ myFillAsp->SetFrontMaterial(aMaterials[0]);
+ myFillAsp->SetBackMaterial (aMaterials[1]);
+
+ Handle(Graphic3d_Texture2D) aTexture = createTexture (myIsGrayscale, myRangeFrom, myRangeTo, myProperty->IsInversed());
+ if (aTexture.IsNull())
+ {
+ return;
+ }
+
+ myFillAsp->SetTextureMapOn();
+ myFillAsp->SetTextureMap (aTexture);
+ myFillAsp->SetInteriorColor (Quantity_NOC_WHITE);
+
+ myFillAsp->SetDistinguishOff();
+ myFillAsp->SetEdgeOff();
+
+ Handle(Graphic3d_Group) aGroup1 = thePrs->NewGroup();
+ aGroup1->SetGroupPrimitivesAspect (myFillAsp);
+ aGroup1->AddPrimitiveArray (aFaceTriangles);
+
+ myPrsGroup = aGroup1;
+
+ if (toShowEdges)
+ {
+ Handle(Graphic3d_Group) aGroup2 = thePrs->NewGroup();
+
+ Handle(Graphic3d_AspectLine3d) anLAsp = new Graphic3d_AspectLine3d (anEdgeColor, anEdgeType, anEdgeWidth);
+ aGroup2->SetGroupPrimitivesAspect (anLAsp);
+ aGroup2->AddPrimitiveArray (anEdgeSegments);
+ }
+}
+
+//================================================================
+// Function : SetProperty
+// Purpose :
+//================================================================
+void MeshPrsBuilder::SetProperty (const Handle(MeshScalarProperty)& theProperty,
+ const Standard_Boolean theIsElemental)
+{
+ myProperty = theProperty;
+ myIsElemental = theIsElemental;
+ if (!myProperty.IsNull())
+ {
+ myRangeFrom = myProperty->ColorscaleRangeFrom();
+ myRangeTo = myProperty->ColorscaleRangeTo();
+ }
+}
+
+//================================================================
+// Function : SetRange
+// Purpose :
+//================================================================
+void MeshPrsBuilder::SetRange (const Standard_Real theFrom,
+ const Standard_Real theTo,
+ const bool theIsInversed)
+{
+ Standard_Real aPrec = 1.0 / Standard_Real(THE_NB_COLORS * 10);
+ if (Abs (myRangeFrom - theFrom) < aPrec
+ && Abs (myRangeTo - theTo) < aPrec
+ && (myProperty.IsNull() || myProperty->IsInversed() == theIsInversed))
+ {
+ return;
+ }
+
+ myRangeFrom = theFrom;
+ myRangeTo = theTo;
+ if (!myProperty.IsNull())
+ {
+ myProperty->SetInversed (theIsInversed);
+ myProperty->SetColorscaleRange (theFrom, theTo);
+ }
+ if (myPrsGroup.IsNull())
+ {
+ return;
+ }
+
+ Handle(Graphic3d_Texture2D) aTexture = createTexture (myIsGrayscale, myRangeFrom, myRangeTo, theIsInversed);
+ if (aTexture.IsNull())
+ {
+ return;
+ }
+
+ myFillAsp->SetTextureMap (aTexture);
+ myPrsGroup->SetGroupPrimitivesAspect (myFillAsp);
+}
+
+//================================================================
+// Function : createTexture
+// Purpose :
+//================================================================
+Handle(Graphic3d_Texture2D) MeshPrsBuilder::createTexture (const Standard_Boolean theIsGrayscale,
+ const Standard_Real theFrom,
+ const Standard_Real theTo,
+ const bool theIsInversed)
+{
+ const Standard_Integer aNbColors = THE_NB_COLORS;
+
+ const Graphic3d_Vec3d anOut = Graphic3d_Vec3d (0.5, 0.5, 0.5);
+ Graphic3d_Vec3d aScale00 = theIsGrayscale ? Graphic3d_Vec3d (0.0, 0.0, 0.0) : Graphic3d_Vec3d (0.0, 0.0, 1.0);
+ Graphic3d_Vec3d aScale05 = theIsGrayscale ? Graphic3d_Vec3d (0.5, 0.5, 0.5) : Graphic3d_Vec3d (0.0, 1.0, 0.0);
+ Graphic3d_Vec3d aScale10 = theIsGrayscale ? Graphic3d_Vec3d (1.0, 1.0, 1.0) : Graphic3d_Vec3d (1.0, 0.0, 0.0);
+ if (theIsInversed)
+ {
+ std::swap (aScale00, aScale10);
+ }
+
+ const Standard_Real aRange = Max (theTo - theFrom, 0.01);
+ const Standard_Real aRangeInv = 1.0 / aRange;
+ const Standard_Real aMiddle = theFrom + 0.5 * aRange;
+ const Standard_Real aFrom = theFrom;
+
+ // create and fill image with colors
+ Handle(Image_PixMap) anImage = new Image_PixMap();
+ if (!anImage->InitTrash (Image_PixMap::ImgRGBA, aNbColors, 2))
+ {
+ return NULL;
+ }
+
+ Image_ColorRGBA anOutColor;
+ anOutColor.r() = Standard_Byte(255.0 * anOut.r());
+ anOutColor.g() = Standard_Byte(255.0 * anOut.g());
+ anOutColor.b() = Standard_Byte(255.0 * anOut.b());
+ anOutColor.a() = 0xFF;
+
+ anImage->SetTopDown (false);
+ for (Standard_Size aColIter = 0; aColIter < Standard_Size(aNbColors); ++aColIter)
+ {
+ const Standard_Real aValue = Standard_Real(aColIter) / Standard_Real(aNbColors - 1);
+ Graphic3d_Vec3d aColorVal;
+ if (aValue < theFrom
+ || aValue > theTo)
+ {
+ aColorVal = anOut;
+ }
+ else if (aValue < aMiddle)
+ {
+ const Standard_Real aHalfVal = (aValue - aFrom) * 2.0 * aRangeInv;
+ aColorVal = aScale00 * (1.0 - aHalfVal) + aScale05 * aHalfVal;
+ }
+ else
+ {
+ const Standard_Real aHalfVal = (aValue - aFrom) * 2.0 * aRangeInv - 1.0;
+ aColorVal = aScale05 * (1.0 - aHalfVal) + aScale10 * aHalfVal;
+ }
+
+ Image_ColorRGBA& aColor0 = anImage->ChangeValue<Image_ColorRGBA> (0, aColIter);
+ Image_ColorRGBA& aColor1 = anImage->ChangeValue<Image_ColorRGBA> (1, aColIter);
+ aColor0.r() = Standard_Byte(255.0 * aColorVal.r());
+ aColor0.g() = Standard_Byte(255.0 * aColorVal.g());
+ aColor0.b() = Standard_Byte(255.0 * aColorVal.b());
+ aColor0.a() = 0xFF;
+ aColor1 = anOutColor;
+ }
+
+ // create texture
+ return new MeshPrsTexture (anImage);
+}
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifndef MeshPrsBuilder_H
+#define MeshPrsBuilder_H
+
+#include "MeshDataSource.h"
+
+#include <MeshVS_PrsBuilder.hxx>
+#include <Graphic3d_Texture2D.hxx>
+#include <Graphic3d_TextureParams.hxx>
+
+//! Auxiliary class to hold texture.
+class MeshPrsTexture : public Graphic3d_Texture2D
+{
+public:
+
+ MeshPrsTexture (const Handle(Image_PixMap)& theImg)
+ : Graphic3d_Texture2D (theImg, Graphic3d_TOT_2D)
+ {
+ myParams->SetModulate (Standard_True);
+ myParams->SetFilter (Graphic3d_TOTF_BILINEAR);
+ }
+
+public:
+
+ DEFINE_STANDARD_RTTIEXT(MeshPrsTexture, Graphic3d_Texture2D)
+
+};
+
+DEFINE_STANDARD_HANDLE(MeshPrsTexture, Graphic3d_Texture2D)
+
+//! Auxiliary builder for Nodal or Elemental mesh properties using textured colorscale.
+class MeshPrsBuilder : public MeshVS_PrsBuilder
+{
+
+public:
+
+ //! Default constructor.
+ Standard_EXPORT MeshPrsBuilder (const Handle(MeshVS_Mesh)& theMesh,
+ const MeshVS_DisplayModeFlags& theFlags);
+
+ //! Setup textures when available.
+ Standard_Boolean ToMapTextures() const { return myToMapTexture; }
+
+ //! Setup textures when available.
+ void SetMapTextures (const Standard_Boolean theToMap) { myToMapTexture = theToMap; }
+
+public:
+
+ //! Setup property to display.
+ Standard_EXPORT void SetProperty (const Handle(MeshScalarProperty)& theProperty,
+ const Standard_Boolean theIsElemental);
+
+ //! Grayscale flag.
+ Standard_Boolean IsGrayscale() const
+ {
+ return myIsGrayscale;
+ }
+
+ //! Specify using grayscale or B->G->R colorscale
+ void SetGrayscale (const Standard_Boolean theIsGrayscale)
+ {
+ myIsGrayscale = theIsGrayscale;
+ }
+
+ //! Adjust colorscale range.
+ Standard_EXPORT void SetRange (const Standard_Real theFrom,
+ const Standard_Real theTo,
+ const bool theIsInversed);
+
+public:
+
+ //! Main builder.
+ Standard_EXPORT virtual void Build (const Handle(Prs3d_Presentation)& thePrs,
+ const TColStd_PackedMapOfInteger& theIDs,
+ TColStd_PackedMapOfInteger& theIDsToExclude,
+ const Standard_Boolean theIsElement,
+ const Standard_Integer theDisplayMode) const Standard_OVERRIDE;
+
+protected:
+
+ //! Textured presentation builder.
+ void buildTextured (const Handle(Prs3d_Presentation)& thePrs,
+ const TColStd_PackedMapOfInteger& theIDs,
+ TColStd_PackedMapOfInteger& theIDsToExclude) const;
+
+ //! Auxiliary method to create texture.
+ static Handle(Graphic3d_Texture2D) createTexture (const Standard_Boolean theIsGrayscale,
+ const Standard_Real theFrom,
+ const Standard_Real theTo,
+ const bool theIsInversed);
+
+ //! Return lower property value.
+ Standard_Real propertyLowerValue() const
+ {
+ if (myProperty.IsNull())
+ {
+ return 0.0;
+ }
+ return myIsGrayscale ? Min (0.0, myProperty->LowerValue()) : myProperty->LowerValue();
+ }
+
+ //! Return upper property value.
+ Standard_Real propertyUpperValue() const
+ {
+ if (myProperty.IsNull())
+ {
+ return 1.0;
+ }
+ return myIsGrayscale ? Max (1.0, myProperty->UpperValue()) : myProperty->UpperValue();
+ }
+
+protected:
+
+ Handle(MeshScalarProperty) myProperty; //!< property to display
+ Standard_Boolean myIsElemental; //!< flag indicating elemental property
+ Standard_Boolean myIsGrayscale; //!< flag to create grayscale colorscale
+ Standard_Real myRangeFrom; //!< colorscale range, lower value
+ Standard_Real myRangeTo; //!< colorscale range, upper value
+
+ Standard_Boolean myToMapTexture;//!< setup textures when available
+ Standard_Boolean myToFlipV; //!< flip texture coordinates vertically
+
+ mutable Handle(Graphic3d_Group) myPrsGroup; //!< presentation group with triangles
+ mutable Handle(Graphic3d_AspectFillArea3d) myFillAsp;
+
+public:
+
+ DEFINE_STANDARD_RTTIEXT(MeshPrsBuilder, MeshVS_PrsBuilder)
+
+};
+
+DEFINE_STANDARD_HANDLE(MeshPrsBuilder, MeshVS_PrsBuilder)
+
+#endif // MeshPrsBuilder_H
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifndef MeshScalarProperty_H
+#define MeshScalarProperty_H
+
+#include <gp_XYZ.hxx>
+#include <Graphic3d_Vec.hxx>
+#include <NCollection_Vector.hxx>
+#include <NCollection_Sequence.hxx>
+#include <Precision.hxx>
+#include <TCollection_AsciiString.hxx>
+
+//! Return true for NaN.
+inline bool IsNaN (const double theValue)
+{
+#if defined(_MSC_VER)
+ return ::_isnan (theValue) != 0;
+#else
+ return std::isnan (theValue);
+#endif
+}
+
+//! Property assigned to Mesh elements or nodes
+class MeshScalarProperty : public Standard_Transient
+{
+
+public:
+
+ //! Return property name.
+ const TCollection_AsciiString& Name() const { return myName; }
+
+ //! Return lower index.
+ Standard_Integer LowerIndex() const { return myValues.Lower(); }
+
+ //! Return upper index.
+ Standard_Integer UpperIndex() const { return myValues.Upper(); }
+
+ //! Return value for specified index.
+ Standard_Real Value (const Standard_Integer theIndex) const { return myValues.Value (theIndex); }
+
+ //! Return lower value of the property.
+ Standard_Real LowerValue() const { return myValueLower; }
+
+ //! Return lower value of the property.
+ Standard_Real UpperValue() const { return myValueUpper; }
+
+ //! Return true if values has opposite meaning (greater value is better).
+ bool IsInversed() const { return myIsInversed; }
+
+ //! Setup flag inficating that values has opposite meaning (greater value is better) or normal meaning (greater value is badder).
+ void SetInversed(const bool theIsInversed) { myIsInversed = theIsInversed; }
+
+ //! Return colorscale range (from).
+ Standard_Real ColorscaleRangeFrom() const { return myCSRangeFrom; }
+
+ //! Return colorscale range (to).
+ Standard_Real ColorscaleRangeTo() const { return myCSRangeTo; }
+
+ //! Setup colorscale range.
+ void SetColorscaleRange (const Standard_Real theFrom,
+ const Standard_Real theTo)
+ {
+ myCSRangeFrom = theFrom;
+ myCSRangeTo = theTo;
+ }
+
+public:
+
+ //! Default constructor.
+ MeshScalarProperty (const TCollection_AsciiString& theName)
+ : myName (theName),
+ myValueLower ( Precision::Infinite()),
+ myValueUpper (-Precision::Infinite()),
+ myCSRangeFrom(0.0),
+ myCSRangeTo (1.0),
+ myIsInversed (false)
+ {}
+
+ //! Append new value
+ void AppendValue (const Standard_Real theValue)
+ {
+ myValues.Append ((float )theValue);
+
+ if (!IsNaN (theValue))
+ {
+ myValueLower = Min (myValueLower, theValue);
+ myValueUpper = Max (myValueUpper, theValue);
+ }
+ }
+
+protected:
+
+ TCollection_AsciiString myName; //!< property name
+ //NCollection_Vector<Standard_Real> myValues; //!< property values
+ NCollection_Vector<float> myValues; //!< property values
+ Standard_Real myValueLower; //!< values range - lower value
+ Standard_Real myValueUpper; //!< values range - upper value
+ Standard_Real myCSRangeFrom;//!< colorscale range - from
+ Standard_Real myCSRangeTo; //!< colorscale range - to
+ bool myIsInversed; //!< values meaning
+
+public:
+
+ DEFINE_STANDARD_RTTIEXT(MeshScalarProperty, Standard_Transient)
+
+};
+
+DEFINE_STANDARD_HANDLE(MeshScalarProperty, Standard_Transient)
+
+typedef NCollection_Vector<Handle(MeshScalarProperty)> MeshScalarProperties;
+
+#endif // MeshScalarProperty_H
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <ObjDataSource.h>
+
+#include <Standard_CLocaleSentry.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_ProgressSentry.hxx>
+#include <OSD_OpenFile.hxx>
+#include <OSD_Timer.hxx>
+#include <TCollection_ExtendedString.hxx>
+#include <Quantity_Color.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(ObjDataSource, MeshDataSource)
+
+//! Simple wrapper.
+struct FileSentry
+{
+ FILE* File;
+
+ FileSentry (const TCollection_AsciiString& theFile)
+ : File (OSD_OpenFile (theFile.ToCString(), "rb")) {}
+
+ ~FileSentry()
+ {
+ if (File != NULL)
+ {
+ ::fclose (File);
+ }
+ }
+};
+
+//! Read 3 float values.
+inline bool objReadVec3 (const char* thePos,
+ char*& theNext,
+ Graphic3d_Vec3& theVec)
+{
+ const char* aPos = thePos;
+ theVec.x() = (float )Strtod (aPos, &theNext);
+ aPos = theNext;
+ theVec.y() = (float )Strtod (aPos, &theNext);
+ aPos = theNext;
+ theVec.z() = (float )Strtod (aPos, &theNext);
+ return aPos != theNext;
+}
+
+//! Read string.
+inline bool objReadName (const char* thePos,
+ TCollection_AsciiString& theName)
+{
+ TCollection_AsciiString aName = TCollection_AsciiString (thePos);
+ Standard_Integer aTail = aName.Length();
+ if (aTail > 0
+ && aName.Value (aTail) == '\n')
+ {
+ aName.SetValue (aTail--, '\0'); // replace '\n'
+ }
+ if (aTail > 0
+ && aName.Value (aTail) == '\r')
+ {
+ aName.SetValue (aTail--, '\0'); // replace '\r'
+ }
+ theName = aName.ToCString();
+ theName.LeftAdjust();
+ theName.RightAdjust();
+ return !theName.IsEmpty();
+}
+
+//! Reader of mtl files.
+class ObjMaterialReader
+{
+public:
+
+ //! Main constructor.
+ ObjMaterialReader (NCollection_DataMap<TCollection_AsciiString, MeshMaterial>& theMaterials)
+ : myFile (NULL), myMaterials (&theMaterials), myNbLines (0) {}
+
+ //! Destructor.
+ ~ObjMaterialReader()
+ {
+ if (myFile != NULL)
+ {
+ ::fclose (myFile);
+ }
+ }
+
+ //! Read the file.
+ Standard_Boolean Read (const TCollection_AsciiString& theFolder,
+ const TCollection_AsciiString& theFile)
+ {
+ myPath = theFolder + theFile;
+ myFile = OSD_OpenFile (myPath.ToCString(), "rb");
+ if (myFile == NULL)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("OBJ material file '") + myPath + "' is not found!", Message_Warning);
+ return Standard_False;
+ }
+
+ char aLine[256] = {};
+ TCollection_AsciiString aMatName;
+ MeshMaterial aMat;
+ const Standard_Integer aNbMatOld = myMaterials->Extent();
+ bool hasAspect = false;
+ for (; ::feof (myFile) == 0 && ::fgets (aLine, 255, myFile) != NULL; )
+ {
+ ++myNbLines;
+
+ const char* aPos = aLine;
+ if (*aLine == '#'
+ || *aLine == '\n'
+ || *aLine == '\0')
+ {
+ continue;
+ }
+
+ if (::memcmp (aLine, "newmtl ", 7) == 0)
+ {
+ aPos += 7;
+ if (!aMatName.IsEmpty())
+ {
+ if (hasAspect)
+ {
+ aMat.Aspect.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
+ aMat.Aspect.SetMaterialName (aMatName.ToCString());
+ }
+ else
+ {
+ // reset incomplete material definition
+ aMat.Aspect = Graphic3d_MaterialAspect();
+ }
+ myMaterials->Bind (aMatName, aMat);
+ hasAspect = false;
+ }
+
+ aMatName = TCollection_AsciiString(aPos);
+ aMat = MeshMaterial();
+ if (!objReadName (aPos, aMatName))
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Empty OBJ material at line ") + myNbLines + " in file " + myPath, Message_Warning);
+ }
+ }
+ else if (::memcmp (aLine, "Ka ", 3) == 0)
+ {
+ aPos += 3;
+ char* aNext = NULL;
+ Graphic3d_Vec3 aColor;
+ objReadVec3 (aPos, aNext, aColor);
+ aPos = aNext;
+ if (validateColor (aColor))
+ {
+ Quantity_Color aQColor (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
+ aMat.Aspect.SetAmbientColor (aQColor);
+ hasAspect = true;
+ }
+ }
+ else if (::memcmp (aLine, "Kd ", 3) == 0)
+ {
+ aPos += 3;
+ char* aNext = NULL;
+ Graphic3d_Vec3 aColor;
+ objReadVec3 (aPos, aNext, aColor);
+ aPos = aNext;
+ if (validateColor (aColor))
+ {
+ Quantity_Color aQColor (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
+ aMat.Aspect.SetDiffuseColor (aQColor);
+ hasAspect = true;
+ }
+ }
+ else if (::memcmp (aLine, "Ks ", 3) == 0)
+ {
+ aPos += 3;
+ char* aNext = NULL;
+ Graphic3d_Vec3 aColor;
+ objReadVec3 (aPos, aNext, aColor);
+ aPos = aNext;
+ if (validateColor (aColor))
+ {
+ Quantity_Color aQColor (aColor.r(), aColor.g(), aColor.b(), Quantity_TOC_RGB);
+ aMat.Aspect.SetSpecularColor (aQColor);
+ }
+ }
+ else if (::memcmp (aLine, "Ns ", 3) == 0)
+ {
+ aPos += 3;
+ char* aNext = NULL;
+ Standard_Real aSpecular = Strtod (aPos, &aNext);
+ aPos = aNext;
+ if (aSpecular >= 0.0
+ && aSpecular <= 128.0)
+ {
+ aMat.Aspect.SetShininess (aSpecular / 128.0);
+ }
+ }
+ else if (::memcmp (aLine, "Tr ", 3) == 0)
+ {
+ aPos += 3;
+ char* aNext = NULL;
+ Standard_Real anAlpha = Strtod (aPos, &aNext);
+ aPos = aNext;
+ if (validateScalar (anAlpha))
+ {
+ //aMat.Aspect.SetTransparency (anAlpha);
+ }
+ }
+ else if (::memcmp (aLine, "map_Kd ", 7) == 0)
+ {
+ aPos += 7;
+ if (!objReadName (aPos, aMat.Texture))
+ {
+ //
+ }
+ else
+ {
+ aMat.Texture = theFolder + aMat.Texture;
+ }
+ }
+ /*else if (::memcmp (aLine, "illum ", 6) == 0)
+ {
+ aPos += 6;
+ char* aNext = NULL;
+ const int aModel = strtol (aPos, &aNext, 10);
+ aPos = aNext;
+ if (aModel < 0 || aModel > 10)
+ {
+ // unknown model
+ }
+ }*/
+ }
+
+ if (!aMatName.IsEmpty())
+ {
+ if (hasAspect)
+ {
+ aMat.Aspect.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
+ aMat.Aspect.SetMaterialName (aMatName.ToCString());
+ }
+ else
+ {
+ // reset incomplete material definition
+ aMat.Aspect = Graphic3d_MaterialAspect();
+ }
+ myMaterials->Bind (aMatName, aMat);
+ }
+ return myMaterials->Extent() != aNbMatOld;
+ }
+
+private:
+
+ //! Validate scalar value
+ inline bool validateScalar (const Standard_Real theValue)
+ {
+ if (theValue < 0.0
+ || theValue > 1.0)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid scalar in OBJ material at line ") + myNbLines + " in file " + myPath, Message_Warning);
+ return false;
+ }
+ return true;
+ }
+
+ //! Validate RGB color
+ inline bool validateColor (const Graphic3d_Vec3& theVec)
+ {
+ if (theVec.r() < 0.0 || theVec.r() > 1.0
+ || theVec.g() < 0.0 || theVec.g() > 1.0
+ || theVec.b() < 0.0 || theVec.b() > 1.0)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid color in OBJ material at line ") + myNbLines + " in file " + myPath, Message_Warning);
+ return false;
+ }
+ return true;
+ }
+
+private:
+
+ FILE* myFile;
+ TCollection_AsciiString myPath;
+ NCollection_DataMap<TCollection_AsciiString, MeshMaterial>* myMaterials;
+ Standard_Integer myNbLines;
+
+};
+
+//================================================================
+// Function : Constructor
+// Purpose :
+//================================================================
+ObjDataSource::ObjDataSource()
+{
+ //
+}
+
+//! Hasher for 3 ordered integers.
+class ObjVec3iHasher
+{
+public:
+
+ static Standard_Integer HashCode (const Graphic3d_Vec3i& theKey,
+ const Standard_Integer theUpper)
+ {
+ return ::HashCode (::HashCodes ((Standard_CString )&theKey, sizeof(Graphic3d_Vec3i)), theUpper);
+ }
+
+ static Standard_Boolean IsEqual (const Graphic3d_Vec3i& theKey1,
+ const Graphic3d_Vec3i& theKey2)
+ {
+ return theKey1[0] == theKey2[0]
+ && theKey1[1] == theKey2[1]
+ && theKey1[2] == theKey2[2];
+ }
+
+};
+
+//================================================================
+// Function : Read
+// Purpose :
+//================================================================
+Standard_Boolean ObjDataSource::Read (const TCollection_AsciiString& theFile,
+ const Handle(Message_ProgressIndicator)& theProgress,
+ const Standard_Integer /*theIndexLimit*/,
+ const Standard_Integer theMemLimitMiB)
+{
+ Clear();
+
+ Standard_CLocaleSentry aLocaleSentry;
+ FileSentry aFile (theFile);
+ if (aFile.File == NULL)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("File '") + theFile + "' is not found!", Message_Fail);
+ return Standard_False;
+ }
+
+ // determine file location to load associated files
+ TCollection_AsciiString aFolder;
+ {
+ OSD_Path aPath (theFile);
+ aPath.SetName ("");
+ aPath.SetExtension ("");
+ aPath.SystemName (aFolder);
+ }
+
+ // determine length of file
+ ::fseek64 (aFile.File, 0, SEEK_END);
+ const int64_t aFileLen = ::ftell64 (aFile.File);
+ if (aFileLen <= 0L)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("File '") + theFile + "' is empty!", Message_Fail);
+ return Standard_False;
+ }
+ ::fseek64 (aFile.File, 0, SEEK_SET);
+
+ const Standard_Integer aNbMiBTotal = Standard_Integer(aFileLen / (1024 * 1024));
+ Standard_Integer aNbMiBPassed = 0;
+ Message_ProgressSentry aPSentry (theProgress, "Reading text OBJ file", 0, aNbMiBTotal, 1);
+ OSD_Timer aTimer;
+ aTimer.Start();
+
+ // Each node in the Element specifies independent indices of Vertex position, Texture coordinates and Normal.
+ // This scheme does not match natural definition of Primitive Array where each unique set of nodal properties defines Vertex
+ // (thus node at the same location but with different normal should be duplicated).
+ // The following code converts OBJ definition of nodal properties to Primitive Array definition.
+ NCollection_Vector<Graphic3d_Vec3> aVerts;
+ NCollection_Vector<Graphic3d_Vec2> aVertParams;
+ NCollection_Vector<Graphic3d_Vec3> aNorms;
+ NCollection_DataMap<Graphic3d_Vec3i, Standard_Integer, ObjVec3iHasher> aPackedIndices;
+ NCollection_DataMap<TCollection_AsciiString, MeshMaterial> aMaterials;
+ TCollection_AsciiString anActiveMat;
+ MeshGroup aGroup;
+
+ const size_t aMemLimitBytes = theMemLimitMiB == -1
+ ? size_t(-1)
+ : (theMemLimitMiB * 1024 * 1024);
+ size_t aMemEstim = 0;
+
+ char aLine[256] = {};
+ Standard_Integer aNbLines = 0;
+ bool isStart = true;
+ for (; ::feof (aFile.File) == 0 && ::fgets (aLine, 255, aFile.File) != NULL; )
+ {
+ ++aNbLines;
+ if (aTimer.ElapsedTime() > 1.0)
+ {
+ if (!aPSentry.More())
+ {
+ return Standard_False;
+ }
+
+ const Standard_Integer aNbMiBRead = Standard_Integer(::ftell64 (aFile.File) / (1024 * 1024));
+ for (; aNbMiBPassed < aNbMiBRead; ++aNbMiBPassed) { aPSentry.Next(); }
+ aTimer.Reset();
+ aTimer.Start();
+ }
+
+ const char* aPos = aLine;
+ if (*aLine == '#')
+ {
+ if (isStart)
+ {
+ TCollection_AsciiString aComment (aLine + 1);
+ aComment.LeftAdjust();
+ aComment.RightAdjust();
+ if (!aComment.IsEmpty())
+ {
+ myComments.Append (aComment);
+ }
+ }
+ continue;
+ }
+ else if (*aLine == '\n'
+ || *aLine == '\0')
+ {
+
+ continue;
+ }
+ isStart = false;
+
+ if (::memcmp (aLine, "v ", 2) == 0)
+ {
+ aPos += 2;
+ char* aNext = NULL;
+ Graphic3d_Vec3 aVert;
+ objReadVec3 (aPos, aNext, aVert);
+ aPos = aNext;
+
+ aMemEstim += sizeof(Graphic3d_Vec3);
+ if (aMemEstim >= aMemLimitBytes)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
+ + "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
+ + "\nMesh data will be truncated!", Message_Fail);
+ return Standard_False;
+ }
+
+ aVerts.Append (aVert);
+ }
+ else if (::memcmp (aLine, "vn ", 3) == 0)
+ {
+ aPos += 3;
+ char* aNext = NULL;
+ Graphic3d_Vec3 aNorm;
+ objReadVec3 (aPos, aNext, aNorm);
+ aPos = aNext;
+
+ aMemEstim += sizeof(Graphic3d_Vec3);
+ if (aMemEstim >= aMemLimitBytes)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
+ + "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
+ + "\nMesh data will be truncated!", Message_Fail);
+ return Standard_False;
+ }
+
+ aNorms.Append (aNorm);
+ }
+ else if (::memcmp (aLine, "vt ", 3) == 0)
+ {
+ aPos += 3;
+ char* aNext = NULL;
+ Graphic3d_Vec2 anUV;
+ anUV.x() = (float )Strtod (aPos, &aNext);
+ aPos = aNext;
+ anUV.y() = (float )Strtod (aPos, &aNext);
+ aPos = aNext;
+
+ aMemEstim += sizeof(Graphic3d_Vec2);
+ if (aMemEstim >= aMemLimitBytes)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
+ + "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
+ + "\nMesh data will be truncated!", Message_Fail);
+ return Standard_False;
+ }
+
+ aVertParams.Append (anUV);
+ }
+ else if (::memcmp (aLine, "f ", 2) == 0)
+ {
+ aPos += 2;
+ char* aNext = NULL;
+
+ Graphic3d_Vec4i aTriNodes (-1, -1, -1, -1);
+ for (int aNode = 0; aNode < 4; ++aNode)
+ {
+ Graphic3d_Vec3i a3Indices (-1, -1, -1);
+ a3Indices[0] = strtol (aPos, &aNext, 10) - 1;
+ if (aNext == aPos)
+ {
+ continue;
+ }
+
+ // parse UV index
+ aPos = aNext;
+ if (*aPos == '/')
+ {
+ ++aPos;
+ a3Indices[1] = strtol (aPos, &aNext, 10) - 1;
+ aPos = aNext;
+
+ // parse Normal index
+ if (*aPos == '/')
+ {
+ ++aPos;
+ a3Indices[2] = strtol (aPos, &aNext, 10) - 1;
+ aPos = aNext;
+ }
+ }
+ if (*aPos != ' '
+ && *aPos != '\n'
+ && *aPos != '\0')
+ {
+ ++aPos;
+ }
+
+ // handle negative indices
+ if (a3Indices[0] < -1)
+ {
+ a3Indices[0] += aVerts.Upper() + 2;
+ }
+ if (a3Indices[1] < -1)
+ {
+ a3Indices[1] += aVertParams.Upper() + 2;
+ }
+ if (a3Indices[2] < -1)
+ {
+ a3Indices[2] += aNorms.Upper() + 2;
+ }
+
+ Standard_Integer anIndex = -1;
+ if (!aPackedIndices.Find (a3Indices, anIndex))
+ {
+ if (a3Indices[0] >= 0)
+ {
+ aMemEstim += sizeof(Graphic3d_Vec3);
+ }
+ if (a3Indices[1] >= 0)
+ {
+ aMemEstim += sizeof(Graphic3d_Vec2);
+ }
+ if (a3Indices[2] >= 0)
+ {
+ aMemEstim += sizeof(Graphic3d_Vec3);
+ }
+ aMemEstim += sizeof(Graphic3d_Vec4i) + sizeof(Standard_Integer); // naive map
+ if (aMemEstim >= aMemLimitBytes)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
+ + "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
+ + "\nMesh data will be truncated!", Message_Fail);
+ return Standard_False;
+ }
+
+ if (a3Indices[0] < aVerts.Lower() || a3Indices[0] > aVerts.Upper())
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Fail);
+ return Standard_False;
+ }
+ AddNodePosition (aVerts.Value (a3Indices[0]));
+ aGroup.NodeUpper = myNodes.Upper();
+ if (aGroup.NodeLower < 0)
+ {
+ aGroup.NodeLower = aGroup.NodeUpper;
+ }
+ if (a3Indices[1] >= 0)
+ {
+ if (a3Indices[1] < aVertParams.Lower() || a3Indices[1] > aVertParams.Upper())
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Fail);
+ return Standard_False;
+ }
+ AddNodeUV (aVertParams.Value (a3Indices[1]));
+ }
+ if (a3Indices[2] >= 0)
+ {
+ if (a3Indices[2] < aNorms.Lower() || a3Indices[2] > aNorms.Upper())
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Fail);
+ return Standard_False;
+ }
+ AddNodeNormal (aNorms.Value (a3Indices[2]));
+ }
+ anIndex = myNodes.Upper();
+ aPackedIndices.Bind (a3Indices, anIndex);
+ }
+ aTriNodes[aNode] = anIndex;
+ }
+
+ if (aTriNodes[0] < 0
+ || aTriNodes[1] < 0
+ || aTriNodes[2] < 0)
+ {
+ continue;
+ }
+
+ aMemEstim += sizeof(Graphic3d_Vec4i);
+ if (aMemEstim >= aMemLimitBytes)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("OBJ file contains more than ") + myElements.Size() + " elements and " + aVerts.Size() + " vertices"
+ + "\nwhich does not fit into " + theMemLimitMiB + " MiB limit."
+ + "\nMesh data will be truncated!", Message_Fail);
+ return Standard_False;
+ }
+
+ AddElement (aTriNodes);
+ aGroup.ElemUpper = myElements.Upper();
+ if (aGroup.ElemLower < 0)
+ {
+ aGroup.ElemLower = aGroup.ElemUpper;
+ if (!anActiveMat.IsEmpty())
+ {
+ aMaterials.Find (anActiveMat, aGroup.Material);
+ }
+ }
+ }
+ else if (::memcmp (aLine, "g ", 2) == 0)
+ {
+ if (aGroup.ElemLower >= 0
+ && aGroup.ElemLower != aGroup.ElemUpper)
+ {
+ myGroups.Append (aGroup);
+ aGroup = MeshGroup();
+ aPackedIndices.Clear(); // vertices might be duplicated after this...
+ }
+
+ TCollection_AsciiString aGroupName;
+ if (!objReadName (aPos + 2, aGroupName))
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Warning);
+ continue;
+ }
+ }
+ else if (::memcmp (aLine, "mtllib ", 7) == 0)
+ {
+ TCollection_AsciiString aMatPath;
+ if (!objReadName (aPos + 7, aMatPath))
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Warning);
+ continue;
+ }
+
+ ObjMaterialReader aMatReader (aMaterials);
+ aMatReader.Read (aFolder, aMatPath);
+ }
+ else if (::memcmp (aLine, "usemtl ", 7) == 0)
+ {
+ TCollection_AsciiString aMatName;
+ if (!objReadName (aPos + 7, aMatName))
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Invalid OBJ syntax at line ") + aNbLines, Message_Warning);
+ continue;
+ }
+ else if (!aMaterials.IsBound (aMatName))
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Use of undefined OBJ material at line ") + aNbLines, Message_Warning);
+ continue;
+ }
+
+ anActiveMat = aMatName;
+ }
+ }
+
+ if (aGroup.ElemLower >= 0
+ && aGroup.ElemLower != aGroup.ElemUpper)
+ {
+ myGroups.Append (aGroup);
+ }
+
+ for (; aNbMiBPassed < aNbMiBTotal; ++aNbMiBPassed) { aPSentry.Next(); }
+ return Standard_True;
+}
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifndef ObjDataSource_H
+#define ObjDataSource_H
+
+#include <MeshDataSource.h>
+
+//! The DataSource for working with OBJ mesh reader.
+class ObjDataSource : public MeshDataSource
+{
+
+public:
+
+ //! Empty constructor.
+ Standard_EXPORT ObjDataSource();
+
+ //! Read the mesh from specified file.
+ Standard_EXPORT virtual Standard_Boolean Read (const TCollection_AsciiString& theFile,
+ const Handle(Message_ProgressIndicator)& theProgress,
+ const Standard_Integer theIndexLimit,
+ const Standard_Integer theMemoryLimitMiB) Standard_OVERRIDE;
+
+public:
+
+ DEFINE_STANDARD_RTTIEXT(ObjDataSource, MeshDataSource)
+
+};
+
+DEFINE_STANDARD_HANDLE(ObjDataSource, MeshDataSource)
+
+#endif // ObjDataSource_H
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <ObjDataWriter.h>
+
+#include <FaceIterator.h>
+#include <CafShapePrs.h>
+
+#include <BRep_Tool.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepLProp_SLProps.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_ProgressSentry.hxx>
+#include <OSD_OpenFile.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <Poly_Triangulation.hxx>
+#include <Standard_CLocaleSentry.hxx>
+#include <TDataStd_Name.hxx>
+#include <TopoDS.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(ObjDataWriter, Standard_Transient)
+
+//! Auxiliary class to write OBJ.
+class ObjWriter
+{
+
+public:
+
+ //! Main constructor.
+ ObjWriter (const TCollection_AsciiString& theName,
+ const Standard_Boolean theHasNormals)
+ : myFile (OSD_OpenFile (theName.ToCString(), "wb")),
+ myName (theName),
+ myHasNormals (theHasNormals == Standard_True)
+ {
+ if (myFile == NULL)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("File can not be created!\n") + theName, Message_Fail);
+ return;
+ }
+ }
+
+ //! Destructor, will emit error message if file was not closed.
+ ~ObjWriter()
+ {
+ if (myFile != NULL)
+ {
+ ::fclose (myFile);
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("File can not be written!\n") + myName, Message_Fail);
+ }
+ }
+
+ //! Return true if file has been opened.
+ bool IsOpened() const { return myFile != NULL; }
+
+ //! Correctly close the file.
+ void Close()
+ {
+ ::fclose (myFile);
+ myFile = NULL;
+ }
+
+ //! Write the header.
+ bool WriteHeader (const Standard_Integer theNbNodes,
+ const Standard_Integer theNbElems)
+ {
+ return ::Fprintf (myFile, "# Exported by OpenCASCADE CAD Assistant [www.opencascade.com]\n"
+ "# Vertices: %d\n"
+ "# Faces: %d\n", theNbNodes, theNbElems) != 0;
+ }
+
+ //! Writing a triangle
+ bool WriteTriangle (const Graphic3d_Vec4i& theTri)
+ {
+ if (myHasNormals)
+ {
+ return Fprintf (myFile, "f %d//%d %d//%d %d//%d\n",
+ theTri[0] + 1, theTri[0] + 1,
+ theTri[1] + 1, theTri[1] + 1,
+ theTri[2] + 1, theTri[2] + 1) != 0;
+ }
+ return Fprintf (myFile, "f %d %d %d\n",
+ theTri[0] + 1,
+ theTri[1] + 1,
+ theTri[2] + 1) != 0;
+ }
+
+ //! Writing a quad
+ bool WriteQuad (const Graphic3d_Vec4i& theQuad)
+ {
+ if (myHasNormals)
+ {
+ return Fprintf (myFile, "f %d//%d %d//%d %d//%d %d//%d\n",
+ theQuad[0] + 1, theQuad[0] + 1,
+ theQuad[1] + 1, theQuad[1] + 1,
+ theQuad[2] + 1, theQuad[2] + 1,
+ theQuad[3] + 1, theQuad[3] + 1) != 0;
+ }
+ return Fprintf (myFile, "f %d %d %d %d\n",
+ theQuad[0] + 1,
+ theQuad[1] + 1,
+ theQuad[2] + 1,
+ theQuad[3] + 1) != 0;
+ }
+
+ //! Writing a vector
+ bool WriteVertex (const Graphic3d_Vec3& theValue)
+ {
+ return Fprintf (myFile, "v %f %f %f\n", theValue.x(), theValue.y(), theValue.z()) != 0;
+ }
+
+ //! Writing a vector
+ bool WriteNormal (const Graphic3d_Vec3& theValue)
+ {
+ return Fprintf (myFile, "vn %f %f %f\n", theValue.x(), theValue.y(), theValue.z()) != 0;
+ }
+
+ //! Writing a group name
+ bool WriteGroup (const TCollection_AsciiString& theValue)
+ {
+ return Fprintf (myFile, "g %s\n", theValue.ToCString()) != 0;
+ }
+
+private:
+
+ FILE* myFile;
+ TCollection_AsciiString myName;
+ bool myHasNormals;
+ bool myIsOpened;
+
+};
+
+//================================================================
+// Function : Constructor
+// Purpose :
+//================================================================
+ObjDataWriter::ObjDataWriter()
+{
+ //
+}
+
+//================================================================
+// Function : Write
+// Purpose :
+//================================================================
+Standard_Boolean ObjDataWriter::Write (const Handle(MeshDataSource)& theDataSrc,
+ const TCollection_AsciiString& theFile,
+ const Handle(Message_ProgressIndicator)& /*theProgress*/)
+{
+ if (theDataSrc.IsNull())
+ {
+ return Standard_False;
+ }
+
+ // header
+ /*NCollection_IndexedMap<TCollection_AsciiString> aComments;
+ for (NCollection_Sequence<TCollection_AsciiString>::Iterator aCommentIter (theDataSrc->FileComments()); aCommentIter.More(); aCommentIter.Next())
+ {
+ aComments.Add (aCommentIter.Value());
+ }
+ aComments.Add ("Exported by OpenCASCADE CAD Assistant [www.opencascade.com]");*/
+
+ Standard_CLocaleSentry aLocaleSentry;
+ ObjWriter anObjFile (theFile, theDataSrc->HasNormals());
+ if (!anObjFile.IsOpened()
+ || !anObjFile.WriteHeader (theDataSrc->NbNodes(), theDataSrc->NbElements()))
+ {
+ return Standard_False;
+ }
+
+ for (Standard_Integer aNodeIter = 0; aNodeIter < theDataSrc->NbNodes(); ++aNodeIter)
+ {
+ const Graphic3d_Vec3& aNode = theDataSrc->Nodes().Value (aNodeIter);
+ if (!anObjFile.WriteVertex (aNode))
+ {
+ return Standard_False;
+ }
+ }
+ if (theDataSrc->HasNormals())
+ {
+ for (Standard_Integer aNodeIter = 0; aNodeIter < theDataSrc->NbNodes(); ++aNodeIter)
+ {
+ const Graphic3d_Vec3& aNormal = theDataSrc->Normals().Value (aNodeIter);
+ if (!anObjFile.WriteNormal (aNormal))
+ {
+ return Standard_False;
+ }
+ }
+ }
+
+ for (Standard_Integer anElemIter = 0; anElemIter < theDataSrc->NbElements(); ++anElemIter)
+ {
+ const Graphic3d_Vec4i& anElem = theDataSrc->Elements().Value (anElemIter);
+ if (anElem[3] == -1)
+ {
+ if (!anObjFile.WriteTriangle (anElem))
+ {
+ return Standard_False;
+ }
+ }
+ else
+ {
+ if (!anObjFile.WriteQuad (anElem))
+ {
+ return Standard_False;
+ }
+ }
+ }
+
+ anObjFile.Close();
+ return Standard_True;
+}
+
+//! Trivial convertor
+inline Graphic3d_Vec3 objXyzToVec (const gp_XYZ& thePnt)
+{
+ return Graphic3d_Vec3 ((float )thePnt.X(), (float )thePnt.Y(), (float )thePnt.Z());
+}
+
+//================================================================
+// Function : Write
+// Purpose :
+//================================================================
+Standard_Boolean ObjDataWriter::Write (const AIS_ListOfInteractive& thePrsList,
+ const TCollection_AsciiString& theFile,
+ const Handle(Message_ProgressIndicator)& /*theProgress*/)
+{
+ if (thePrsList.IsEmpty())
+ {
+ return Standard_False;
+ }
+
+ Standard_Integer aNbNodesAll = 0;
+ Standard_Integer aNbElemsAll = 0;
+ for (FaceIterator aFaceIter (thePrsList); aFaceIter.More(); aFaceIter.Next())
+ {
+ aNbNodesAll += aFaceIter.Triangulation->Nodes().Length();
+ aNbElemsAll += aFaceIter.Triangulation->Triangles().Length();
+ }
+
+ if (aNbNodesAll == 0
+ || aNbElemsAll == 0)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("No mesh data to save!\n"), Message_Fail);
+ return Standard_False;
+ }
+
+ Standard_CLocaleSentry aLocaleSentry;
+ ObjWriter anObjFile (theFile, Standard_True);
+ if (!anObjFile.IsOpened()
+ || !anObjFile.WriteHeader (aNbNodesAll, aNbElemsAll))
+ {
+ return Standard_False;
+ }
+
+ // write vertices
+ BRepAdaptor_Surface aFaceAdaptor;
+ BRepLProp_SLProps aSLTool (1, 1e-12);
+ gp_Dir aNormal;
+ Standard_Integer aFirstNode = 0;
+ Graphic3d_Vec4i aTriNodes (-1, -1, -1, -1);
+ Standard_Integer aNbFaces = 0;
+ TCollection_AsciiString aPrevGroup;
+ for (FaceIterator aFaceIter (thePrsList); aFaceIter.More(); aFaceIter.Next())
+ {
+ ++aNbFaces;
+ const Standard_Integer aLower = aFaceIter.Triangulation->Triangles().Lower();
+ const Standard_Boolean isMirrored = aFaceIter.Trsf.VectorialPart().Determinant() < 0.0;
+ const Handle(Poly_Triangulation)& aTriangulation = aFaceIter.Triangulation;
+
+ TCollection_AsciiString aRefName;
+ Handle(TDataStd_Name) aNodeName;
+ if (aFaceIter.ShapePrs->GetLabel().FindAttribute (TDataStd_Name::GetID(), aNodeName))
+ {
+ aRefName = TCollection_AsciiString (aNodeName->Get());
+ }
+ if (!aRefName.IsEmpty()
+ && !aRefName.IsEqual (aPrevGroup)
+ && !anObjFile.WriteGroup (aRefName))
+ {
+ return Standard_False;
+ }
+
+ // write nodes
+ const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
+ const gp_Trsf aTrsf = aFaceIter.Trsf;
+ for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
+ {
+ gp_Pnt aNode = aNodes (aNodeIter);
+ aNode.Transform (aTrsf);
+ if (!anObjFile.WriteVertex (objXyzToVec (aNode.XYZ())))
+ {
+ return Standard_False;
+ }
+ }
+
+ // write normals
+ TopoDS_Face aFace = TopoDS::Face (aFaceIter.Face.Oriented (TopAbs_FORWARD));
+ aFace.Location (TopLoc_Location());
+ aFaceAdaptor.Initialize (aFace, Standard_False);
+ aSLTool.SetSurface (aFaceAdaptor);
+ const TColgp_Array1OfPnt2d& aNodeUVs = aTriangulation->UVNodes();
+ for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
+ {
+ const gp_XY& anUV = aNodeUVs.Value (aNodeIter).XY();
+ aSLTool.SetParameters (anUV.X(), anUV.Y());
+ gp_Dir aNormal ((aSLTool.IsNormalDefined() ? aSLTool.Normal() : gp::DZ()).XYZ());
+ aNormal.Transform (aTrsf);
+ if (aFaceIter.Face.Orientation() == TopAbs_REVERSED)
+ {
+ aNormal.Reverse();
+ }
+ if (!anObjFile.WriteNormal (objXyzToVec (aNormal.XYZ())))
+ {
+ return Standard_False;
+ }
+ }
+
+ // write indices
+ for (Poly_Array1OfTriangle::Iterator anElemIter (aFaceIter.Triangulation->Triangles()); anElemIter.More(); anElemIter.Next())
+ {
+ if ((aFaceIter.Face.Orientation() == TopAbs_REVERSED) ^ isMirrored)
+ {
+ anElemIter.Value().Get (aTriNodes[0], aTriNodes[2], aTriNodes[1]);
+ }
+ else
+ {
+ anElemIter.Value().Get (aTriNodes[0], aTriNodes[1], aTriNodes[2]);
+ }
+ aTriNodes[0] = aFirstNode + aTriNodes[0] - aLower;
+ aTriNodes[1] = aFirstNode + aTriNodes[1] - aLower;
+ aTriNodes[2] = aFirstNode + aTriNodes[2] - aLower;
+ if (!anObjFile.WriteTriangle (aTriNodes))
+ {
+ return Standard_False;
+ }
+ }
+ aFirstNode += aFaceIter.Triangulation->NbNodes();
+ }
+
+ anObjFile.Close();
+ return Standard_True;
+}
--- /dev/null
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of commercial software by OPEN CASCADE SAS.
+//
+// This software is furnished in accordance with the terms and conditions
+// of the contract and with the inclusion of this copyright notice.
+// This software or any other copy thereof may not be provided or otherwise
+// be made available to any third party.
+// No ownership title to the software is transferred hereby.
+//
+// OPEN CASCADE SAS makes no representation or warranties with respect to the
+// performance of this software, and specifically disclaims any responsibility
+// for any damages, special or consequential, connected with its use.
+
+#ifndef ObjDataWriter_H
+#define ObjDataWriter_H
+
+#include <MeshDataSource.h>
+
+#include <AIS_ListOfInteractive.hxx>
+
+//! Mesh writer to the OBJ format.
+class ObjDataWriter : public Standard_Transient
+{
+
+public:
+
+ //! Empty constructor.
+ Standard_EXPORT ObjDataWriter();
+
+ //! Write the mesh into specified file.
+ Standard_EXPORT Standard_Boolean Write (const Handle(MeshDataSource)& theDataSrc,
+ const TCollection_AsciiString& theFile,
+ const Handle(Message_ProgressIndicator)& theProgress);
+
+ //! Write the mesh presentation of the model into specified file.
+ Standard_EXPORT Standard_Boolean Write (const AIS_ListOfInteractive& thePrsList,
+ const TCollection_AsciiString& theFile,
+ const Handle(Message_ProgressIndicator)& theProgress);
+
+public:
+
+ DEFINE_STANDARD_RTTIEXT(ObjDataWriter, Standard_Transient)
+
+};
+
+DEFINE_STANDARD_HANDLE(ObjDataWriter, Standard_Transient)
+
+#endif // ObjDataWriter_H
TKernel
TKG3d
TKG2d
+TKXCAF
+TKLCAF
\ No newline at end of file
TKGeomBase
+TKXCAF
+TKLCAF
TKFillet
TKBRep
TKTopAlgo
TKG3d
TKOffset
TKMesh
+TKMeshVS
TKV3d
TKDraw
TKOpenGl
return 0;
}
+#include <ObjDataSource.h>
+#include <MeshPresentation.h>
+#include <MeshVS_Drawer.hxx>
+#include <MeshPrsBuilder.h>
+#include <MeshVS_MeshPrsBuilder.hxx>
+#include <MeshVS_DrawerAttribute.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+namespace
+{
+ std::vector<TCollection_AsciiString> Split (const TCollection_AsciiString& pSource,
+ const TCollection_AsciiString& pSeparator)
+ {
+ std::vector<TCollection_AsciiString> result;
+
+ TCollection_AsciiString token;
+ const Standard_Integer aSize = pSource.Length();
+ unsigned int previousPos = 1;
+ unsigned int currentPos = 1;
+ while ((currentPos = pSource.FirstLocationInSet(pSeparator, currentPos, aSize)) != 0)
+ {
+ result.push_back(pSource.SubString(previousPos, currentPos - previousPos));
+
+ previousPos = ++currentPos;
+ }
+
+ // Save last element.
+ result.push_back(pSource.SubString(previousPos, aSize));
+
+ return result;
+ }
+
+ //! Returns true for grayscale properties.
+ inline bool isGrayscaleProperty (const TCollection_AsciiString& theName)
+ {
+ return theName == "intensity";
+ }
+
+ Handle(MeshPresentation) createMeshPresentation (const Handle(MeshDataSource)& theDataSource,
+ const TCollection_AsciiString& theEntry,
+ TCollection_AsciiString& theSelEntry,
+ Handle(MeshScalarProperty)& theSelProperty)
+ {
+ theSelEntry.Clear();
+ theSelProperty.Nullify();
+ if (theDataSource.IsNull())
+ {
+ return Handle(MeshPresentation)();
+ }
+
+ theSelEntry = theEntry;
+ if (theEntry.IsEmpty())
+ {
+ if (theDataSource->HasTexture())
+ {
+ theSelEntry = "ply_textured";
+ }
+ else if (theDataSource->HasNodalColors())
+ {
+ theSelEntry = "ply_colored";
+ }
+ /*else if (theDataSource->HasNormals())
+ {
+ theSelEntry = "ply_smoothshaded";
+ }*/
+ else
+ {
+ theSelEntry = "ply_smoothshaded";
+ //theSelEntry = "ply_shaded";
+ }
+ }
+
+ std::cout << theSelEntry << std::endl;
+
+ Handle(MeshPresentation) aMesh = new MeshPresentation();
+ Handle(MeshVS_Drawer) aDrawer = aMesh->GetDrawer();
+ aDrawer->SetBoolean(MeshVS_DA_ShowEdges, Standard_False);
+ aDrawer->SetBoolean(MeshVS_DA_SmoothShading, theDataSource->HasNormals());
+ aMesh->SetDataSource(theDataSource);
+ aMesh->SetMaterial(Graphic3d_NOM_PLASTIC); // myMatAspect
+ if (theSelEntry == "ply_textured")
+ {
+ //myPrsCaps |= DisplayCaps_Texture;
+ aDrawer->SetBoolean(MeshVS_DA_SmoothShading, Standard_True);
+ aDrawer->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GRAY65);
+ Handle(MeshPrsBuilder) aBuilder = new MeshPrsBuilder(aMesh, MeshVS_DMF_Shading);
+ aBuilder->SetMapTextures(Standard_True);
+ aMesh->AddBuilder(aBuilder, Standard_True);
+ aMesh->SetDisplayMode(MeshVS_DMF_Shading);
+ }
+ else if (theSelEntry == "ply_colored")
+ {
+ //myPrsCaps |= DisplayCaps_VertColor;
+ aDrawer->SetBoolean(MeshVS_DA_ColorReflection, Standard_True);
+
+ Handle(MeshVS_NodalColorPrsBuilder) aBuilder = new MeshVS_NodalColorPrsBuilder(aMesh, MeshVS_DMF_NodalColorDataPrs);
+ theDataSource->FillNodalColorsBuilder(aBuilder);
+ aMesh->AddBuilder(aBuilder, Standard_True);
+ aMesh->SetDisplayMode(MeshVS_DMF_NodalColorDataPrs);
+ }
+ else if (theSelEntry == "ply_wireframe")
+ {
+ aMesh->AddBuilder(new MeshVS_MeshPrsBuilder(aMesh.operator->()), Standard_True);
+ aMesh->SetDisplayMode(MeshVS_DMF_WireFrame);
+ }
+ else if (theSelEntry == "ply_smoothshaded")
+ {
+ aDrawer->SetBoolean(MeshVS_DA_SmoothShading, Standard_True);
+ aDrawer->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GRAY65);
+ Handle(MeshPrsBuilder) aBuilder = new MeshPrsBuilder(aMesh, MeshVS_DMF_Shading);
+ aBuilder->SetMapTextures(Standard_False);
+ aMesh->AddBuilder(aBuilder, Standard_True);
+ aMesh->SetDisplayMode(MeshVS_DMF_Shading);
+ }
+ else if (theSelEntry == "ply_shaded")
+ {
+ aDrawer->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GRAY65);
+ aDrawer->SetBoolean(MeshVS_DA_SmoothShading, Standard_False);
+ aMesh->AddBuilder(new MeshVS_MeshPrsBuilder(aMesh.operator->()), Standard_True);
+ aMesh->SetDisplayMode(MeshVS_DMF_Shading);
+ }
+ else if (theSelEntry == "ply_shrink")
+ {
+ aDrawer->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GRAY65);
+ aMesh->AddBuilder(new MeshVS_MeshPrsBuilder(aMesh.operator->()), Standard_True);
+ aMesh->SetDisplayMode(MeshVS_DMF_Shrink);
+ }
+ //else if (theSelEntry.startsWith("ply_group_nodalprops\n"))
+ else if (theSelEntry.Search("ply_group_nodalprops\n") != -1)
+ {
+ //myPrsCaps |= DisplayCaps_Texture;
+ std::vector<TCollection_AsciiString> aList = Split(theEntry, "\n");
+ const int aPropIndex = aList.size() != 2 ? 0 : aList.back().IntegerValue();
+
+ theSelProperty = theDataSource->NodalQuantities().Value(aPropIndex);
+ const Standard_Boolean isGrayscale = isGrayscaleProperty(theSelProperty->Name());
+ const Standard_Integer aMeshEdgesLimit = 100000;
+ if (!isGrayscale
+ && (aMeshEdgesLimit < 0 || theDataSource->NbNodes() <= aMeshEdgesLimit))
+ {
+ aDrawer->SetBoolean(MeshVS_DA_ShowEdges, Standard_True);
+ }
+ aDrawer->SetBoolean(MeshVS_DA_ColorReflection, Standard_True);
+
+ Handle(MeshPrsBuilder) aBuilder = new MeshPrsBuilder(aMesh, MeshVS_DMF_NodalColorDataPrs);
+ aBuilder->SetProperty(theSelProperty, Standard_False);
+ aBuilder->SetGrayscale(isGrayscale);
+
+ aMesh->AddBuilder(aBuilder, Standard_True);
+ aMesh->SetDisplayMode(MeshVS_DMF_NodalColorDataPrs);
+ }
+ //else if (theSelEntry.startsWith("ply_group_elemprops\n"))
+ else if (theSelEntry.Search("ply_group_elemprops\n") != -1)
+ {
+ //myPrsCaps |= DisplayCaps_Texture;
+ std::vector<TCollection_AsciiString> aList = Split(theEntry, "\n");
+ const int aPropIndex = aList.size() != 2 ? 0 : aList.back().IntegerValue();
+
+ aDrawer->SetBoolean(MeshVS_DA_ColorReflection, Standard_True);
+
+ theSelProperty = theDataSource->ElementalQuantities().Value(aPropIndex);
+
+ Handle(MeshPrsBuilder) aBuilder = new MeshPrsBuilder(aMesh, MeshVS_DMF_ElementalColorDataPrs);
+ aBuilder->SetProperty(theSelProperty, Standard_True);
+ aBuilder->SetGrayscale(isGrayscaleProperty(theSelProperty->Name()));
+
+ aMesh->AddBuilder(aBuilder, Standard_True);
+ aMesh->SetDisplayMode(MeshVS_DMF_ElementalColorDataPrs);
+ }
+
+ return aMesh;
+ }
+}
+
+// =============================================================================
+// function : VDisplayObj
+// purpose :
+// =============================================================================
+static int VDisplayObj (Draw_Interpretor& theDi,
+ Standard_Integer theArgNb,
+ const char** theArgVec)
+{
+ if (theArgNb < 3)
+ {
+ theDi << theArgVec[0] << "Error: wrong number of arguments.\n";
+ return 1;
+ }
+
+ const TCollection_AsciiString aName (theArgVec[1]);
+ const TCollection_AsciiString aPath (theArgVec[2]);
+
+ if (GetMapOfAIS().IsBound2(aName))
+ {
+ theDi << aName << "already exist.\n";
+ return 1;
+ }
+
+ Handle(ObjDataSource) aLoader = new ObjDataSource();
+
+ Standard_Boolean aResult = aLoader->Read (aPath, NULL, -1, -1);
+
+ if (!aResult)
+ {
+ theDi << "Error: can't read a file: '" << aPath.ToCString() << "'\n";
+ return 1;
+ }
+
+ /*const NCollection_Vector<MeshGroup>& aGroups = aLoader->Groups();
+ for (auto anIter = aGroups.cbegin(); anIter != aGroups.cend(); ++anIter)
+ {
+ const Quantity_Color& aDiffuseColor = anIter->Material.Aspect.DiffuseColor();
+ const Graphic3d_BSDF& aBSDF = anIter->Material.Aspect.BSDF();
+
+ std::cout << anIter->Material.Texture << std::endl;
+ std::cout << aDiffuseColor.Red() << ", " << aDiffuseColor.Green() << ", " << aDiffuseColor.Green() << std::endl;
+ std::cout << aBSDF.Kd.x() << ", " << aBSDF.Kd.y() << ", " << aBSDF.Kd.z() << std::endl << std::endl;
+ }*/
+
+ Handle(MeshScalarProperty) aProperty;
+ TCollection_AsciiString aSelEntry;
+ Handle(MeshVS_Mesh) aMesh = createMeshPresentation(aLoader, "", aSelEntry, aProperty);
+
+ ViewerTest::Display(aName, aMesh, Standard_False);
+
+ return 0;
+}
+
+#include <ObjDataWriter.h>
+#include <AIS_ListOfInteractive.hxx>
+// =============================================================================
+// function : VSaveObj
+// purpose :
+// =============================================================================
+static int VSaveObj (Draw_Interpretor& theDi,
+ Standard_Integer theArgNb,
+ const char** theArgVec)
+{
+ if (theArgNb < 3)
+ {
+ theDi << theArgVec[0] << "Error: wrong number of arguments.\n";
+ return 1;
+ }
+
+ const TCollection_AsciiString aPath (theArgVec[1]);
+ AIS_ListOfInteractive aList;
+ Handle(ObjDataWriter) aWriter = new ObjDataWriter();
+
+ for (Standard_Integer anIter = 2; anIter < theArgNb; ++anIter)
+ {
+ TCollection_AsciiString aName (theArgVec[anIter]);
+
+ if (!GetMapOfAIS().IsBound2(aName))
+ {
+ theDi << aName << "is not exist.\n";
+ continue;
+ }
+
+ Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(aName));
+ if (anObject.IsNull())
+ {
+ theDi << aName << "is not an interactive object.\n";
+ continue;
+ }
+
+ /*Handle(MeshVS_Mesh) aMesh = Handle(MeshVS_Mesh)::DownCast(anObject);
+ if (!aMesh.IsNull())
+ {
+ aWriter->Write (aMesh->GetDataSource(), aPath, NULL);
+ }*/
+
+ aList.Append(anObject);
+ }
+ aWriter->Write (aList, aPath, NULL);
+
+ return 0;
+}
+
//==============================================================================
//function : ViewerTest::Commands
//purpose : Add all the viewer command in the Draw_Interpretor
"\n\t\t: -redisplay recomputes presentation of objects.",
__FILE__, VDisplay2, group);
+ theCommands.Add("vdisplayobj",
+ "vdisplayobj name path",
+ __FILE__, VDisplayObj, group);
+
+ theCommands.Add("vsaveobj",
+ "vsaveobj file names",
+ __FILE__, VSaveObj, group);
+
theCommands.Add ("vupdate",
"vupdate name1 [name2] ... [name n]"
"\n\t\t: Updates named objects in interactive context",