Loading files
// Created on: 2000-06-16
// Copyright (c) 2000-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 <Graphic3d_ArrayOfPrimitives.hxx>
#include <Graphic3d_ArrayOfPoints.hxx>
#include <Graphic3d_ArrayOfSegments.hxx>
#include <Graphic3d_ArrayOfPolylines.hxx>
#include <Graphic3d_ArrayOfTriangles.hxx>
#include <Graphic3d_ArrayOfTriangleStrips.hxx>
#include <Graphic3d_ArrayOfTriangleFans.hxx>
#include <Graphic3d_ArrayOfQuadrangles.hxx>
#include <Graphic3d_ArrayOfQuadrangleStrips.hxx>
#include <Graphic3d_ArrayOfPolygons.hxx>
#include <Graphic3d_AttribBuffer.hxx>
#include <Graphic3d_MutableIndexBuffer.hxx>
#include <TCollection_AsciiString.hxx>
#include <cstdio>
#include <cstdlib>
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPoints, Graphic3d_ArrayOfPrimitives)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfSegments, Graphic3d_ArrayOfPrimitives)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolylines, Graphic3d_ArrayOfPrimitives)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangles, Graphic3d_ArrayOfPrimitives)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleStrips, Graphic3d_ArrayOfPrimitives)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleFans, Graphic3d_ArrayOfPrimitives)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangles, Graphic3d_ArrayOfPrimitives)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangleStrips, Graphic3d_ArrayOfPrimitives)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolygons, Graphic3d_ArrayOfPrimitives)
//=================================================================================================
occ::handle<Graphic3d_ArrayOfPrimitives> Graphic3d_ArrayOfPrimitives::CreateArray(
Graphic3d_TypeOfPrimitiveArray theType,
int theMaxVertexs,
int theMaxBounds,
int theMaxEdges,
Graphic3d_ArrayFlags theArrayFlags)
{
switch (theType)
{
case Graphic3d_TOPA_UNDEFINED:
return occ::handle<Graphic3d_ArrayOfPrimitives>();
case Graphic3d_TOPA_POINTS:
return new Graphic3d_ArrayOfPoints(theMaxVertexs, theArrayFlags);
case Graphic3d_TOPA_SEGMENTS:
return new Graphic3d_ArrayOfSegments(theMaxVertexs, theMaxEdges, theArrayFlags);
case Graphic3d_TOPA_POLYLINES:
return new Graphic3d_ArrayOfPolylines(theMaxVertexs,
theMaxBounds,
theMaxEdges,
theArrayFlags);
case Graphic3d_TOPA_TRIANGLES:
return new Graphic3d_ArrayOfTriangles(theMaxVertexs, theMaxEdges, theArrayFlags);
case Graphic3d_TOPA_TRIANGLESTRIPS:
return new Graphic3d_ArrayOfTriangleStrips(theMaxVertexs, theMaxBounds, theArrayFlags);
case Graphic3d_TOPA_TRIANGLEFANS:
return new Graphic3d_ArrayOfTriangleFans(theMaxVertexs, theMaxBounds, theArrayFlags);
case Graphic3d_TOPA_LINES_ADJACENCY:
case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
return new Graphic3d_ArrayOfPrimitives(theType,
theMaxVertexs,
theMaxBounds,
theMaxEdges,
theArrayFlags);
case Graphic3d_TOPA_QUADRANGLES:
return new Graphic3d_ArrayOfQuadrangles(theMaxVertexs, theMaxEdges, theArrayFlags);
case Graphic3d_TOPA_QUADRANGLESTRIPS:
return new Graphic3d_ArrayOfQuadrangleStrips(theMaxVertexs, theMaxBounds, theArrayFlags);
case Graphic3d_TOPA_POLYGONS:
return new Graphic3d_ArrayOfPolygons(theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
}
return occ::handle<Graphic3d_ArrayOfPrimitives>();
}
//=================================================================================================
void Graphic3d_ArrayOfPrimitives::init(Graphic3d_TypeOfPrimitiveArray theType,
int theMaxVertexs,
int theMaxBounds,
int theMaxEdges,
Graphic3d_ArrayFlags theArrayOptions)
{
myType = theType;
myNormData = nullptr;
myTexData = nullptr;
myColData = nullptr;
myAttribs.Nullify();
myIndices.Nullify();
myBounds.Nullify();
const occ::handle<NCollection_BaseAllocator>& anAlloc = Graphic3d_Buffer::DefaultAllocator();
if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0
|| (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) != 0)
{
Graphic3d_AttribBuffer* anAttribs = new Graphic3d_AttribBuffer(anAlloc);
anAttribs->SetMutable((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0);
anAttribs->SetInterleaved((theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0);
myAttribs = anAttribs;
}
else
{
myAttribs = new Graphic3d_Buffer(anAlloc);
}
if (theMaxVertexs < 1)
{
return;
}
if (theMaxEdges > 0)
{
if ((theArrayOptions & Graphic3d_ArrayFlags_IndexesMutable) != 0)
{
myIndices = new Graphic3d_MutableIndexBuffer(anAlloc);
}
else
{
myIndices = new Graphic3d_IndexBuffer(anAlloc);
}
if (theMaxVertexs < int(USHRT_MAX))
{
if (!myIndices->Init<unsigned short>(theMaxEdges))
{
myIndices.Nullify();
return;
}
}
else
{
if (!myIndices->Init<unsigned int>(theMaxEdges))
{
myIndices.Nullify();
return;
}
}
myIndices->NbElements = 0;
}
Graphic3d_Attribute anAttribs[4];
int aNbAttribs = 0;
anAttribs[aNbAttribs].Id = Graphic3d_TOA_POS;
anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
++aNbAttribs;
if ((theArrayOptions & Graphic3d_ArrayFlags_VertexNormal) != 0)
{
anAttribs[aNbAttribs].Id = Graphic3d_TOA_NORM;
anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
++aNbAttribs;
}
if ((theArrayOptions & Graphic3d_ArrayFlags_VertexTexel) != 0)
{
anAttribs[aNbAttribs].Id = Graphic3d_TOA_UV;
anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC2;
++aNbAttribs;
}
if ((theArrayOptions & Graphic3d_ArrayFlags_VertexColor) != 0)
{
anAttribs[aNbAttribs].Id = Graphic3d_TOA_COLOR;
anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC4UB;
++aNbAttribs;
}
if (!myAttribs->Init(theMaxVertexs, anAttribs, aNbAttribs))
{
myAttribs.Nullify();
myIndices.Nullify();
return;
}
int anAttribDummy = 0;
myAttribs->ChangeAttributeData(Graphic3d_TOA_POS, anAttribDummy, myPosStride);
myNormData = myAttribs->ChangeAttributeData(Graphic3d_TOA_NORM, anAttribDummy, myNormStride);
myTexData = myAttribs->ChangeAttributeData(Graphic3d_TOA_UV, anAttribDummy, myTexStride);
myColData = myAttribs->ChangeAttributeData(Graphic3d_TOA_COLOR, anAttribDummy, myColStride);
memset(myAttribs->ChangeData(),
0,
size_t(myAttribs->Stride) * size_t(myAttribs->NbMaxElements()));
if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) == 0
&& (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0)
{
myAttribs->NbElements = 0;
}
if (theMaxBounds > 0)
{
myBounds = new Graphic3d_BoundBuffer(anAlloc);
if (!myBounds->Init(theMaxBounds, (theArrayOptions & Graphic3d_ArrayFlags_BoundColor) != 0))
{
myAttribs.Nullify();
myIndices.Nullify();
myBounds.Nullify();
return;
}
myBounds->NbBounds = 0;
}
}
//=================================================================================================
Graphic3d_ArrayOfPrimitives::~Graphic3d_ArrayOfPrimitives()
{
myIndices.Nullify();
myAttribs.Nullify();
myBounds.Nullify();
}
//=================================================================================================
int Graphic3d_ArrayOfPrimitives::AddBound(const int theEdgeNumber)
{
Standard_OutOfRange_Raise_if(myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds,
"TOO many BOUND");
myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
return ++myBounds->NbBounds;
}
//=================================================================================================
int Graphic3d_ArrayOfPrimitives::AddBound(const int theEdgeNumber,
const double theR,
const double theG,
const double theB)
{
Standard_OutOfRange_Raise_if(myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds,
"TOO many BOUND");
myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
++myBounds->NbBounds;
SetBoundColor(myBounds->NbBounds, theR, theG, theB);
return myBounds->NbBounds;
}
//=================================================================================================
int Graphic3d_ArrayOfPrimitives::AddEdge(const int theVertexIndex)
{
Standard_OutOfRange_Raise_if(myIndices.IsNull()
|| myIndices->NbElements >= myIndices->NbMaxElements(),
"TOO many EDGE");
Standard_OutOfRange_Raise_if(theVertexIndex < 1 || theVertexIndex > myAttribs->NbElements,
"BAD VERTEX index");
const int aVertIndex = theVertexIndex - 1;
myIndices->SetIndex(myIndices->NbElements, aVertIndex);
return ++myIndices->NbElements;
}
//=================================================================================================
void Graphic3d_ArrayOfPrimitives::AddTriangleStripEdges(int theVertexLower, int theVertexUpper)
{
if (myType != Graphic3d_TOPA_TRIANGLES)
{
throw Standard_TypeMismatch("Not array of triangles");
}
bool isOdd = true;
for (int aNodeIter = theVertexLower + 2; aNodeIter <= theVertexUpper; ++aNodeIter)
{
if (isOdd)
{
AddTriangleEdges(aNodeIter - 2, aNodeIter - 1, aNodeIter);
}
else
{
AddTriangleEdges(aNodeIter - 1, aNodeIter - 2, aNodeIter);
}
isOdd = !isOdd;
}
}
//=================================================================================================
void Graphic3d_ArrayOfPrimitives::AddTriangleFanEdges(int theVertexLower,
int theVertexUpper,
bool theToClose)
{
if (myType != Graphic3d_TOPA_TRIANGLES)
{
throw Standard_TypeMismatch("Not array of triangles");
}
for (int aNodeIter = theVertexLower + 1; aNodeIter <= theVertexUpper; ++aNodeIter)
{
AddTriangleEdges(theVertexLower, aNodeIter - 1, aNodeIter);
}
if (theToClose)
{
AddTriangleEdges(theVertexLower, theVertexUpper, theVertexLower + 1);
}
}
//=================================================================================================
void Graphic3d_ArrayOfPrimitives::AddPolylineEdges(int theVertexLower,
int theVertexUpper,
bool theToClose)
{
if (myType != Graphic3d_TOPA_SEGMENTS)
{
throw Standard_TypeMismatch("Not array of segments");
}
for (int aNodeIter = theVertexLower; aNodeIter < theVertexUpper; ++aNodeIter)
{
AddSegmentEdges(aNodeIter, aNodeIter + 1);
}
if (theToClose)
{
AddSegmentEdges(theVertexUpper, theVertexLower);
}
}
//=================================================================================================
const char* Graphic3d_ArrayOfPrimitives::StringType() const
{
switch (myType)
{
case Graphic3d_TOPA_POINTS:
return "ArrayOfPoints";
case Graphic3d_TOPA_SEGMENTS:
return "ArrayOfSegments";
case Graphic3d_TOPA_POLYLINES:
return "ArrayOfPolylines";
case Graphic3d_TOPA_TRIANGLES:
return "ArrayOfTriangles";
case Graphic3d_TOPA_TRIANGLESTRIPS:
return "ArrayOfTriangleStrips";
case Graphic3d_TOPA_TRIANGLEFANS:
return "ArrayOfTriangleFans";
case Graphic3d_TOPA_LINES_ADJACENCY:
return "ArrayOfLinesAdjacency";
case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
return "ArrayOfLineStripAdjacency";
case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
return "ArrayOfTrianglesAdjacency";
case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
return "ArrayOfTriangleStripAdjacency";
case Graphic3d_TOPA_QUADRANGLES:
return "ArrayOfQuadrangles";
case Graphic3d_TOPA_QUADRANGLESTRIPS:
return "ArrayOfQuadrangleStrips";
case Graphic3d_TOPA_POLYGONS:
return "ArrayOfPolygons";
case Graphic3d_TOPA_UNDEFINED:
return "UndefinedArray";
}
return "UndefinedArray";
}
//=================================================================================================
int Graphic3d_ArrayOfPrimitives::ItemNumber() const
{
if (myAttribs.IsNull())
{
return -1;
}
switch (myType)
{
case Graphic3d_TOPA_POINTS:
return myAttribs->NbElements;
case Graphic3d_TOPA_POLYLINES:
case Graphic3d_TOPA_POLYGONS:
return !myBounds.IsNull() ? myBounds->NbBounds : 1;
case Graphic3d_TOPA_SEGMENTS:
return myIndices.IsNull() || myIndices->NbElements < 1 ? myAttribs->NbElements / 2
: myIndices->NbElements / 2;
case Graphic3d_TOPA_TRIANGLES:
return myIndices.IsNull() || myIndices->NbElements < 1 ? myAttribs->NbElements / 3
: myIndices->NbElements / 3;
case Graphic3d_TOPA_QUADRANGLES:
return myIndices.IsNull() || myIndices->NbElements < 1 ? myAttribs->NbElements / 4
: myIndices->NbElements / 4;
case Graphic3d_TOPA_TRIANGLESTRIPS:
return !myBounds.IsNull() ? myAttribs->NbElements - 2 * myBounds->NbBounds
: myAttribs->NbElements - 2;
case Graphic3d_TOPA_QUADRANGLESTRIPS:
return !myBounds.IsNull() ? myAttribs->NbElements / 2 - myBounds->NbBounds
: myAttribs->NbElements / 2 - 1;
case Graphic3d_TOPA_TRIANGLEFANS:
return !myBounds.IsNull() ? myAttribs->NbElements - 2 * myBounds->NbBounds
: myAttribs->NbElements - 2;
case Graphic3d_TOPA_LINES_ADJACENCY:
return myIndices.IsNull() || myIndices->NbElements < 1 ? myAttribs->NbElements / 4
: myIndices->NbElements / 4;
case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
return !myBounds.IsNull() ? myAttribs->NbElements - 4 * myBounds->NbBounds
: myAttribs->NbElements - 4;
case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
return myIndices.IsNull() || myIndices->NbElements < 1 ? myAttribs->NbElements / 6
: myIndices->NbElements / 6;
case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
return !myBounds.IsNull() ? myAttribs->NbElements - 4 * myBounds->NbBounds
: myAttribs->NbElements - 4;
case Graphic3d_TOPA_UNDEFINED:
return -1;
}
return -1;
}
//=================================================================================================
bool Graphic3d_ArrayOfPrimitives::IsValid()
{
if (myAttribs.IsNull())
{
return false;
}
int nvertexs = myAttribs->NbElements;
int nbounds = myBounds.IsNull() ? 0 : myBounds->NbBounds;
int nedges = myIndices.IsNull() ? 0 : myIndices->NbElements;
switch (myType)
{
case Graphic3d_TOPA_POINTS:
if (nvertexs < 1)
{
return false;
}
break;
case Graphic3d_TOPA_POLYLINES:
if (nedges > 0 && nedges < 2)
{
return false;
}
if (nvertexs < 2)
{
return false;
}
break;
case Graphic3d_TOPA_SEGMENTS:
if (nvertexs < 2)
{
return false;
}
break;
case Graphic3d_TOPA_POLYGONS:
if (nedges > 0 && nedges < 3)
{
return false;
}
if (nvertexs < 3)
{
return false;
}
break;
case Graphic3d_TOPA_TRIANGLES:
if (nedges > 0)
{
if (nedges < 3 || nedges % 3 != 0)
{
if (nedges <= 3)
{
return false;
}
myIndices->NbElements = 3 * (nedges / 3);
}
}
else if (nvertexs < 3 || nvertexs % 3 != 0)
{
if (nvertexs <= 3)
{
return false;
}
myAttribs->NbElements = 3 * (nvertexs / 3);
}
break;
case Graphic3d_TOPA_QUADRANGLES:
if (nedges > 0)
{
if (nedges < 4 || nedges % 4 != 0)
{
if (nedges <= 4)
{
return false;
}
myIndices->NbElements = 4 * (nedges / 4);
}
}
else if (nvertexs < 4 || nvertexs % 4 != 0)
{
if (nvertexs <= 4)
{
return false;
}
myAttribs->NbElements = 4 * (nvertexs / 4);
}
break;
case Graphic3d_TOPA_TRIANGLEFANS:
case Graphic3d_TOPA_TRIANGLESTRIPS:
if (nvertexs < 3)
{
return false;
}
break;
case Graphic3d_TOPA_QUADRANGLESTRIPS:
if (nvertexs < 4)
{
return false;
}
break;
case Graphic3d_TOPA_LINES_ADJACENCY:
case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
if (nvertexs < 4)
{
return false;
}
break;
case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
if (nvertexs < 6)
{
return false;
}
break;
case Graphic3d_TOPA_UNDEFINED:
default:
return false;
}
// total number of edges(vertices) in bounds should be the same as variable
// of total number of defined edges(vertices); if no edges - only vertices
// could be in bounds.
if (nbounds > 0)
{
int n = 0;
for (int aBoundIter = 0; aBoundIter < nbounds; ++aBoundIter)
{
n += myBounds->Bounds[aBoundIter];
}
if (nedges > 0 && n != nedges)
{
if (nedges <= n)
{
return false;
}
myIndices->NbElements = n;
}
else if (nedges == 0 && n != nvertexs)
{
if (nvertexs <= n)
{
return false;
}
myAttribs->NbElements = n;
}
}
// check that edges (indexes to an array of vertices) are in range.
if (nedges > 0)
{
for (int anEdgeIter = 0; anEdgeIter < nedges; ++anEdgeIter)
{
if (myIndices->Index(anEdgeIter) >= myAttribs->NbElements)
{
return false;
}
}
}
return true;
}
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.