mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
403 lines
11 KiB
C++
403 lines
11 KiB
C++
// Copyright (c) 1999-2014 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 <VrmlConverter_Drawer.hxx>
|
|
#include <VrmlConverter_ShadedShape.hxx>
|
|
#include <Vrml_Normal.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <Poly_Connect.hxx>
|
|
#include <TColgp_Array1OfDir.hxx>
|
|
#include <TColgp_HArray1OfVec.hxx>
|
|
#include <BRepTools.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <gp_Vec.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopLoc_Location.hxx>
|
|
#include <Poly_Array1OfTriangle.hxx>
|
|
#include <Vrml_IndexedFaceSet.hxx>
|
|
#include <Vrml_Coordinate3.hxx>
|
|
#include <math.hxx>
|
|
#include <TColStd_HArray1OfInteger.hxx>
|
|
#include <Geom_Surface.hxx>
|
|
#include <CSLib.hxx>
|
|
#include <BRepAdaptor_Surface.hxx>
|
|
#include <Precision.hxx>
|
|
#include <Vrml_Material.hxx>
|
|
#include <VrmlConverter_ShadingAspect.hxx>
|
|
#include <Vrml_ShapeHints.hxx>
|
|
#include <Vrml_Separator.hxx>
|
|
#include <Vrml_NormalBinding.hxx>
|
|
|
|
//=========================================================================
|
|
// function: Add
|
|
// purpose
|
|
//=========================================================================
|
|
void VrmlConverter_ShadedShape::Add( Standard_OStream& anOStream,
|
|
const TopoDS_Shape& aShape,
|
|
const Handle(VrmlConverter_Drawer)& aDrawer )
|
|
{
|
|
Handle(Poly_Triangulation) T;
|
|
TopLoc_Location theLocation;
|
|
Standard_Integer i, j, k, decal, nnv, EI;
|
|
|
|
Standard_Integer t[3], n[3];
|
|
gp_Pnt p;
|
|
TopExp_Explorer ex;
|
|
|
|
// counting phasis. This phasis will count the valid triangle
|
|
// and the vertices to allocate the correct size for the arrays:
|
|
|
|
Standard_Integer nbTriangles = 0, nbVertices = 0;
|
|
|
|
Standard_Integer nt, nnn, n1, n2, n3;
|
|
|
|
// iterating on each face of the shape:
|
|
for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {
|
|
// getting the face:
|
|
const TopoDS_Face& F = TopoDS::Face(ex.Current());
|
|
// getting the triangulation of the face. The triangulation may not exist:
|
|
T = BRep_Tool::Triangulation(F, theLocation);
|
|
// number of triangles:
|
|
if (T.IsNull()) continue; //smh
|
|
nnn = T->NbTriangles();
|
|
|
|
// Taking the nodes of the triangle, taking into account the orientation
|
|
// of the triangle.
|
|
for (nt = 1; nt <= nnn; nt++) {
|
|
if (F.Orientation() == TopAbs_REVERSED)
|
|
T->Triangle (nt).Get (n1,n3,n2);
|
|
else
|
|
T->Triangle (nt).Get (n1,n2,n3);
|
|
|
|
const gp_Pnt P1 = T->Node (n1);
|
|
const gp_Pnt P2 = T->Node (n2);
|
|
const gp_Pnt P3 = T->Node (n3);
|
|
// controlling whether the triangle correct from a 3d point of
|
|
// view: (the triangle may exist in the UV space but the
|
|
// in the 3d space a dimension is null for example)
|
|
gp_Vec V1(P1,P2);
|
|
if (V1.SquareMagnitude() > 1.e-10) {
|
|
gp_Vec V2(P2,P3);
|
|
if (V2.SquareMagnitude() > 1.e-10) {
|
|
gp_Vec V3(P3,P1);
|
|
if (V3.SquareMagnitude() > 1.e-10) {
|
|
V1.Normalize();
|
|
V2.Normalize();
|
|
V1.Cross(V2);
|
|
if (V1.SquareMagnitude() > 1.e-10) {
|
|
nbTriangles++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
nbVertices += T->NbNodes();
|
|
}
|
|
|
|
// std::cout << "nbTriangles = "<< nbTriangles << std::endl;
|
|
// std::cout << "nbVertices = "<< nbVertices << std::endl << std::endl;
|
|
|
|
//----------------------------
|
|
// now we are going to iterate again to build graphic data from the triangle.
|
|
if (nbVertices > 2 && nbTriangles > 0) {
|
|
// allocating the graphic arrays.
|
|
|
|
Handle(VrmlConverter_ShadingAspect) SA = new VrmlConverter_ShadingAspect;
|
|
SA = aDrawer->ShadingAspect();
|
|
|
|
Handle(TColgp_HArray1OfVec) HAV1 = new TColgp_HArray1OfVec(1, nbVertices);
|
|
Handle(TColgp_HArray1OfVec) HAV2 = new TColgp_HArray1OfVec(1, nbVertices);
|
|
|
|
gp_Vec V, VV;
|
|
|
|
Handle(TColStd_HArray1OfInteger) HAI1 = new TColStd_HArray1OfInteger(1,4*nbTriangles);
|
|
Handle(TColStd_HArray1OfInteger) HAI3 = new TColStd_HArray1OfInteger(1,(nbVertices/3*4+nbVertices%3));
|
|
Handle(TColStd_HArray1OfInteger) HAI2 = new TColStd_HArray1OfInteger(1,1);
|
|
Handle(TColStd_HArray1OfInteger) HAI4 = new TColStd_HArray1OfInteger(1,1);
|
|
|
|
HAI2->SetValue (1,-1);
|
|
HAI4->SetValue (1,-1);
|
|
|
|
// !! Specialize HAI2 - materialIndex HAI4 - textureCoordinateIndex
|
|
|
|
EI = 1;
|
|
nnv = 1;
|
|
|
|
for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {
|
|
const TopoDS_Face& F = TopoDS::Face(ex.Current());
|
|
T = BRep_Tool::Triangulation(F, theLocation);
|
|
if (!T.IsNull()) {
|
|
Poly_Connect pc(T);
|
|
|
|
// 1 - Building HAV1 - array of all XYZ of nodes for Vrml_Coordinate3 from the triangles
|
|
// and HAV2 - array of all normals of nodes for Vrml_Normal
|
|
|
|
TColgp_Array1OfDir NORMAL(1, T->NbNodes());
|
|
|
|
decal = nnv-1;
|
|
|
|
for (j= 1; j<= T->NbNodes(); j++) {
|
|
p = T->Node (j).Transformed (theLocation.Transformation());
|
|
|
|
V.SetX(p.X()); V.SetY(p.Y()); V.SetZ(p.Z());
|
|
HAV1->SetValue(nnv,V);
|
|
|
|
if(SA->HasNormals())
|
|
{
|
|
// to compute the normal.
|
|
ComputeNormal(F, pc, NORMAL);
|
|
|
|
VV.SetX(NORMAL(j).X()); VV.SetY(NORMAL(j).Y()); VV.SetZ(NORMAL(j).Z());
|
|
HAV2->SetValue(nnv,VV);
|
|
}
|
|
nnv++;
|
|
}
|
|
|
|
// 2 - Building HAI1 - array of indexes of all triangles and
|
|
// HAI3 - array of indexes of all normales for Vrml_IndexedFaceSet
|
|
nbTriangles = T->NbTriangles();
|
|
for (i = 1; i <= nbTriangles; i++) {
|
|
pc.Triangles(i,t[0],t[1],t[2]);
|
|
if (F.Orientation() == TopAbs_REVERSED)
|
|
T->Triangle (i).Get (n[0],n[2],n[1]);
|
|
else
|
|
T->Triangle (i).Get (n[0],n[1],n[2]);
|
|
const gp_Pnt P1 = T->Node (n[0]);
|
|
const gp_Pnt P2 = T->Node (n[1]);
|
|
const gp_Pnt P3 = T->Node (n[2]);
|
|
gp_Vec V1(P1,P2);
|
|
if (V1.SquareMagnitude() > 1.e-10) {
|
|
gp_Vec V2(P2,P3);
|
|
if (V2.SquareMagnitude() > 1.e-10) {
|
|
gp_Vec V3(P3,P1);
|
|
if (V3.SquareMagnitude() > 1.e-10) {
|
|
V1.Normalize();
|
|
V2.Normalize();
|
|
V1.Cross(V2);
|
|
if (V1.SquareMagnitude() > 1.e-10) {
|
|
for (j = 0; j < 3; j++) {
|
|
|
|
HAI1->SetValue(EI, n[j]+decal-1); // array of indexes of all triangles
|
|
EI++;
|
|
}
|
|
|
|
HAI1->SetValue(EI, -1);
|
|
EI++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if(SA->HasNormals())
|
|
{
|
|
j=1;
|
|
for (i=HAI3->Lower(); i <= HAI3->Upper(); i++)
|
|
{
|
|
k = i % 4;
|
|
if (k == 0)
|
|
{
|
|
HAI3->SetValue(i, -1);
|
|
j++;
|
|
}
|
|
else
|
|
{
|
|
HAI3->SetValue(i, i-j);
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------
|
|
/*
|
|
std::cout << " ******************** " << std::endl;
|
|
std::cout << " Array HAV1 - Coordinare3 " << std::endl;
|
|
|
|
for ( i=HAV1->Lower(); i <= HAV1->Upper(); i++ )
|
|
{
|
|
std::cout << HAV1->Value(i).X() << " " << HAV1->Value(i).Y()<< " " << HAV1->Value(i).Z() << std::endl;
|
|
}
|
|
|
|
if(SA->HasNormals())
|
|
{
|
|
|
|
std::cout << " ******************** " << std::endl;
|
|
std::cout << " Array HAV2 - Normals " << std::endl;
|
|
|
|
for ( i=HAV2->Lower(); i <= HAV2->Upper(); i++ )
|
|
{
|
|
std::cout << HAV2->Value(i).X() << " " << HAV2->Value(i).Y()<< " " << HAV2->Value(i).Z() << std::endl;
|
|
}
|
|
|
|
std::cout << " ******************** " << std::endl;
|
|
std::cout << " Array HAI3 - normalIndex " << std::endl;
|
|
|
|
for ( i=HAI3->Lower(); i <= HAI3->Upper(); i++ )
|
|
{
|
|
std::cout << HAI3->Value(i) << std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
std::cout << " ******************** " << std::endl;
|
|
std::cout << " Array HAI1 - coordIndex " << std::endl;
|
|
|
|
for ( i=HAI1->Lower(); i <= HAI1->Upper(); i++ )
|
|
{
|
|
std::cout << HAI1->Value(i) << std::endl;
|
|
}
|
|
|
|
std::cout << " ******************** " << std::endl;
|
|
*/
|
|
//----------------------------
|
|
|
|
// creation of Vrml objects
|
|
|
|
Vrml_ShapeHints SH;
|
|
SH = SA->ShapeHints();
|
|
|
|
if(SA->HasNormals())
|
|
{
|
|
// Separator 1 {
|
|
Vrml_Separator SE1;
|
|
SE1.Print(anOStream);
|
|
// Material
|
|
if (SA->HasMaterial()){
|
|
|
|
Handle(Vrml_Material) M;
|
|
M = SA->FrontMaterial();
|
|
|
|
M->Print(anOStream);
|
|
}
|
|
|
|
// Coordinate3
|
|
Handle(Vrml_Coordinate3) C3 = new Vrml_Coordinate3(HAV1);
|
|
C3->Print(anOStream);
|
|
// ShapeHints
|
|
SH.Print(anOStream);
|
|
// NormalBinding
|
|
Vrml_MaterialBindingAndNormalBinding MBNB1 = Vrml_PER_VERTEX_INDEXED;
|
|
Vrml_NormalBinding NB(MBNB1);
|
|
NB.Print(anOStream);
|
|
// Separator 2 {
|
|
Vrml_Separator SE2;
|
|
SE2.Print(anOStream);
|
|
// Normal
|
|
Vrml_Normal N(HAV2);
|
|
N.Print(anOStream);
|
|
// IndexedFaceSet
|
|
Vrml_IndexedFaceSet IFS;
|
|
IFS.SetCoordIndex(HAI1);
|
|
IFS.SetNormalIndex(HAI3);
|
|
IFS.Print(anOStream);
|
|
// Separator 2 }
|
|
SE2.Print(anOStream);
|
|
// Separator 1 }
|
|
SE1.Print(anOStream);
|
|
}
|
|
else
|
|
{
|
|
// Separator 1 {
|
|
Vrml_Separator SE1;
|
|
SE1.Print(anOStream);
|
|
// Material
|
|
if (SA->HasMaterial()){
|
|
|
|
Handle(Vrml_Material) M;
|
|
M = SA->FrontMaterial();
|
|
|
|
M->Print(anOStream);
|
|
}
|
|
// Coordinate3
|
|
Handle(Vrml_Coordinate3) C3 = new Vrml_Coordinate3(HAV1);
|
|
C3->Print(anOStream);
|
|
// ShapeHints
|
|
SH.Print(anOStream);
|
|
// IndexedFaceSet
|
|
Vrml_IndexedFaceSet IFS;
|
|
IFS.SetCoordIndex(HAI1);
|
|
IFS.Print(anOStream);
|
|
// Separator 1 }
|
|
SE1.Print(anOStream);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------- Notes -------------
|
|
|
|
// the necessary of calculation of Normals and Textures must be define in Drawer
|
|
// likes tolerance
|
|
|
|
//---------- End on notes ------------
|
|
|
|
|
|
|
|
//----------------------------
|
|
// Computing the normal
|
|
//-----------------------------
|
|
|
|
void VrmlConverter_ShadedShape::ComputeNormal(const TopoDS_Face& aFace,
|
|
Poly_Connect& pc,
|
|
TColgp_Array1OfDir& Nor)
|
|
{
|
|
const Handle(Poly_Triangulation)& T = pc.Triangulation();
|
|
BRepAdaptor_Surface S;
|
|
Standard_Boolean hasUV = T->HasUVNodes();
|
|
Standard_Integer i;
|
|
TopLoc_Location l;
|
|
Handle(Geom_Surface) GS = BRep_Tool::Surface(aFace, l);
|
|
|
|
if (hasUV && !GS.IsNull()) {
|
|
Standard_Boolean OK = Standard_True;
|
|
gp_Vec D1U,D1V;
|
|
gp_Vec D2U,D2V,D2UV;
|
|
gp_Pnt P;
|
|
Standard_Real U, V;
|
|
CSLib_DerivativeStatus aStatus;
|
|
CSLib_NormalStatus NStat;
|
|
S.Initialize(aFace);
|
|
for (i = 1; i <= T->NbNodes(); i++) {
|
|
U = T->UVNode (i).X();
|
|
V = T->UVNode (i).Y();
|
|
S.D1(U,V,P,D1U,D1V);
|
|
CSLib::Normal(D1U,D1V,Precision::Angular(),aStatus,Nor(i));
|
|
if (aStatus != CSLib_Done) {
|
|
S.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
|
|
CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor(i));
|
|
}
|
|
if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
|
|
}
|
|
}
|
|
else {
|
|
Standard_Integer n[3];
|
|
|
|
for (i = 1; i <= T->NbNodes(); i++) {
|
|
gp_XYZ eqPlan(0, 0, 0);
|
|
for (pc.Initialize(i); pc.More(); pc.Next()) {
|
|
T->Triangle (pc.Value()).Get (n[0], n[1], n[2]);
|
|
gp_XYZ v1 (T->Node (n[1]).Coord() - T->Node (n[0]).Coord());
|
|
gp_XYZ v2 (T->Node (n[2]).Coord() - T->Node (n[1]).Coord());
|
|
eqPlan += (v1^v2).Normalized();
|
|
}
|
|
Nor(i) = gp_Dir(eqPlan);
|
|
if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
|
|
}
|
|
}
|
|
}
|
|
|
|
|