1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-29 14:00:49 +03:00

Add loader *.obj files.

This commit is contained in:
isk
2016-02-20 08:17:21 +03:00
parent 54573faf41
commit 5c52d14a08
20 changed files with 3558 additions and 0 deletions

61
samples/tcl/video.tcl Normal file
View File

@@ -0,0 +1,61 @@
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

View File

@@ -0,0 +1,16 @@
#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);
}

62
src/MeshVS/CafShapePrs.h Normal file
View File

@@ -0,0 +1,62 @@
// 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

View File

@@ -84,3 +84,19 @@ MeshVS_TwoNodes.hxx
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

150
src/MeshVS/FaceIterator.cpp Normal file
View File

@@ -0,0 +1,150 @@
// 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();
}
}

64
src/MeshVS/FaceIterator.h Normal file
View File

@@ -0,0 +1,64 @@
// 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

View File

@@ -0,0 +1,278 @@
// 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;
}
}
}

304
src/MeshVS/MeshDataSource.h Normal file
View File

@@ -0,0 +1,304 @@
// 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

View File

@@ -0,0 +1,137 @@
// 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);
}

View File

@@ -0,0 +1,57 @@
// 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

View File

@@ -0,0 +1,726 @@
// 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);
}

147
src/MeshVS/MeshPrsBuilder.h Normal file
View File

@@ -0,0 +1,147 @@
// 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

View File

@@ -0,0 +1,124 @@
// 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

View File

@@ -0,0 +1,680 @@
// 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;
}

View File

@@ -0,0 +1,43 @@
// 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

View File

@@ -0,0 +1,354 @@
// 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;
}

View File

@@ -0,0 +1,49 @@
// 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

View File

@@ -4,3 +4,5 @@ TKService
TKernel
TKG3d
TKG2d
TKXCAF
TKLCAF

View File

@@ -1,4 +1,6 @@
TKGeomBase
TKXCAF
TKLCAF
TKFillet
TKBRep
TKTopAlgo
@@ -15,6 +17,7 @@ TKTopTest
TKG3d
TKOffset
TKMesh
TKMeshVS
TKV3d
TKDraw
TKOpenGl

View File

@@ -5386,6 +5386,283 @@ static int VAutoActivateSelection (Draw_Interpretor& theDi,
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
@@ -5435,6 +5712,14 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
"\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",