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:
61
samples/tcl/video.tcl
Normal file
61
samples/tcl/video.tcl
Normal 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
|
16
src/MeshVS/CafShapePrs.cpp
Normal file
16
src/MeshVS/CafShapePrs.cpp
Normal 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
62
src/MeshVS/CafShapePrs.h
Normal 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
|
@@ -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
150
src/MeshVS/FaceIterator.cpp
Normal 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
64
src/MeshVS/FaceIterator.h
Normal 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
|
278
src/MeshVS/MeshDataSource.cpp
Normal file
278
src/MeshVS/MeshDataSource.cpp
Normal 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
304
src/MeshVS/MeshDataSource.h
Normal 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
|
137
src/MeshVS/MeshPresentation.cpp
Normal file
137
src/MeshVS/MeshPresentation.cpp
Normal 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);
|
||||
}
|
57
src/MeshVS/MeshPresentation.h
Normal file
57
src/MeshVS/MeshPresentation.h
Normal 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
|
726
src/MeshVS/MeshPrsBuilder.cpp
Normal file
726
src/MeshVS/MeshPrsBuilder.cpp
Normal 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
147
src/MeshVS/MeshPrsBuilder.h
Normal 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
|
124
src/MeshVS/MeshScalarProperty.h
Normal file
124
src/MeshVS/MeshScalarProperty.h
Normal 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
|
680
src/MeshVS/ObjDataSource.cpp
Normal file
680
src/MeshVS/ObjDataSource.cpp
Normal 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;
|
||||
}
|
43
src/MeshVS/ObjDataSource.h
Normal file
43
src/MeshVS/ObjDataSource.h
Normal 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
|
354
src/MeshVS/ObjDataWriter.cpp
Normal file
354
src/MeshVS/ObjDataWriter.cpp
Normal 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;
|
||||
}
|
49
src/MeshVS/ObjDataWriter.h
Normal file
49
src/MeshVS/ObjDataWriter.h
Normal 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
|
@@ -4,3 +4,5 @@ TKService
|
||||
TKernel
|
||||
TKG3d
|
||||
TKG2d
|
||||
TKXCAF
|
||||
TKLCAF
|
@@ -1,4 +1,6 @@
|
||||
TKGeomBase
|
||||
TKXCAF
|
||||
TKLCAF
|
||||
TKFillet
|
||||
TKBRep
|
||||
TKTopAlgo
|
||||
@@ -15,6 +17,7 @@ TKTopTest
|
||||
TKG3d
|
||||
TKOffset
|
||||
TKMesh
|
||||
TKMeshVS
|
||||
TKV3d
|
||||
TKDraw
|
||||
TKOpenGl
|
||||
|
@@ -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",
|
||||
|
Reference in New Issue
Block a user