//================================================================
// E3D library
//
// - Polygon Mesh
//
// AUTHOR:  Gabor Nagy
// DATE:    2025-Dec-14 22:12:21
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//================================================================
#ifndef _E3D_Mesh_h
#define _E3D_Mesh_h


#ifndef _E3D_VertexGeometry_h
#include <E3D/VertexGeometry.h>
#endif

#ifndef _E3D_Node_h
#include <E3D/Node.h>
#endif

#ifndef _E3D_Polygon_h
#include <E3D/Polygon.h>
#endif


#define E3dVTXALLOC_INCREMENT  32

//----------------------------------------
// For E3dMesh_EdgeGetPolygons()
//----------------------------------------
#define	E3dPolyEDGE_IS_IN_HOLE_CONTOUR    0x0001
#define	E3dPolyEDGE_BACKWARD              0x0002  // This Edge goes against the winding order of this Polygon.
#define	E3dPolyEDGE_DEC                   0x0004  // This Edge starts at the higher VertexNode index (than the Edge End).

// Describes a Polygon on an Edge
typedef struct
{
	E3dPolygon*  Polygon;
	EIndex       PolyGroupIndex;
	EIndex       StartVertexNodeIndex, EndVertexNodeIndex;
	uint16_t     Flags;
} E3dEdgePolygonInfo;
//----------------------------------------


// An array of this structure tells for each Mesh Vertex:
// - Which Polygon VertexNodes use that Vertex
// - The other end (Vertex) of each Edge that connects to this Vertex
// Usually used for operations needing unique VertexNode identification:
// - SmoothingAngle-based normal computation
// - Global Illumination processing with per-Polygon VertexNode normals
// etc.
//
typedef struct
{
	E3dVertexLinkCore;

// VertexNodes that refer to this Mesh Vertex (i.e. the of Polygons that share this Vertex)
//
	E3dVertexNode**  VertexNodes;int32_t  VertexNodes_Count, VertexNodes_CountAllocated;  // VertexNodes that refer to this Mesh Vertex
	E3dPolygon**     Polygons;                                                            // Corresponding Polygons for the VertexNodes
	E3dPolyGroup**   PolyGroups;                                                          // Corresponding PolyGroups for the VertexNodes
} E3dVertexLinkPolys;


#ifndef _E3dMesh
#define _E3dMesh
typedef struct E3dMesh_S  E3dMesh;
#endif

typedef int32_t  E3dEdgePolygonIndex;

typedef struct
{
	E3dEdgePolygonInfo*  Polygons;E3dEdgePolygonIndex  Polygons_Count;
} E3dWingedEdge;


// Mesh flags
//
#define E3dACTIVE_EDGES      0x0001
#define E3dSELECTED_EDGES    0x0002
#define E3dHARD_EDGES        0x0004


typedef struct
{
	unsigned int*  GLArrayEdgeVertexIndices;     // For fast wireframe rendering
	unsigned int*  GLArrayVisibleEdgeVertexIndices;
	unsigned int*  GLArrayHiddenEdgeVertexIndices;
	EIndex         GLArrayVisibleEdgesCount;
} E3dMeshGPUData;


#define E3dVertexLinksEDGES       0x0001
#define E3dVertexLinksPOLYGONS    0x0002   // If set, VertexLinksNew points to an array of E3dVertexLinkPolys structs
#define E3dVertexLinksPOLYGROUPS  0x0004

// Polygon Mesh
//
struct E3dMesh_S
{
	E3dVertexGeometryCore;

	E3dVertexLinkNew*       VertexLinksNew;       // This might be kept temporarily to avoid repeated calls to E3dMesh_GetVertexLinksNew() when processing PolyGroups of the same Mesh
	uint16_t             VertexLinksFlags;     // E3dVertexLinksEDGES, E3dVertexLinksPOLYGONS, E3dVertexLinksPOLYGROUPS
	EIndex               VertexLinksStride;    // VertexLinksNew array element size in bytes

	EListA_s(, E3dEdge, Edges);
	E3dWingedEdge*       WingedEdges;

	EList_s(, E3dPolyGroupPtr, PolyGroups);

	EcRGBAf32Color       EdgeRGBAfColor;EBool  UseCustomEdgeColor;

	EBool                ShowVertices,
											 ShowAllVertices,
											 ShowAllEdges,                 // Show all Edges, even if their E3dEdgeVISIBLE flag is 0
											 AlwaysShowEdges,              // Show Edges, even if the Mesh is not selected	() for visualizing KDTree etc.
											 SaveEdges, SaveEdgeHardness;  // Edges carry information (e.g. it's a Subdivision surface), so save/restore them

	E3dCoordinate        VertexSamplingRadius;         // For normal calculation, Vertices within this distance are considered the same Vertex.

	E3dDisplayFlags      DisplayFlags;                 // If not 0, always draw in this mode (e.g. wireframe, even in solid modes. Useful for editing objects inside of this one.)

	uint16_t             EdgeFlags;                    // OR-ed flags: E3dACTIVE_EDGES, E3dSELECTED_EDGES, E3dHARD_EDGES (same as on PolyGroup). See E3dMesh_EdgeFlagsUpdate()

	E3dMeshGPUData       GPUData;
};


typedef struct
{
	const E3dRTriangle*  RTriangle;
	E3dCoord2            UV;
} E3dSurfacePointSample;



// For E3dPolygon_GetAllConnectedPolygons
//
#define E3dBY_EDGE                 0x01
#define E3dBY_VERTEX               0x02
#define E3dSTOP_AT_SELECTED_EDGES  0x04

#define E3dBACKWARD   0x01

// Describes a Polygon
//
typedef struct
{
	E3dPolygon*    Polygon;
	E3dPolyGroup*  PolyGroup;
	unsigned int   Flags;    // E3dBACKWARD
} E3dPolyInfo;




//--------------------------------
// Macro functions
//--------------------------------
#define E3dM_VertexInit(pVertex)     (pVertex)->Flags = E3dVtxDEFAULT
#define E3dM_VertexCopy(pSrc, pDst)  (pDst)->Flags = (pSrc)->Flags


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif



extern E3dObjectClass  E3dMesh_class[];

//--------------------------------
// Function externs
//--------------------------------
//========================================
// Initialize a Vertex
//========================================
static inline void E3dVertex_Init(E3dVertex* PVertex, const E3dVertexSize PVertexSize,  const E3dCoordinate PX, const E3dCoordinate PY, const E3dCoordinate PZ)
{
	PVertex->Position.X = PX;PVertex->Position.Y = PY;PVertex->Position.Z = PZ;
	PVertex->Flags = E3dVtxVISIBLE;
	const E3dVertexSize  LVertexCoreSize = E3dVertexCore_Size();
	if(PVertexSize > LVertexCoreSize) memset((uint8_t*)PVertex + LVertexCoreSize, 0, PVertexSize);
}


static inline void E3dEdge_Init(E3dEdge* PEdge,  const EIndex PStartVertexIndex, const EIndex PEndVertexIndex)
{
	PEdge->Start = PStartVertexIndex;
	PEdge->End   = PEndVertexIndex;
	PEdge->Flags = E3dEdgeDEFAULT;
	PEdge->Hardness = 0.0;
}


static inline void E3dEdge_SetVertices(E3dEdge* PEdge,  const EIndex P0, const EIndex P1)
{
//assert(P0 >= 0);
//assert(P1 >= 0);

	if(P0 < P1) { PEdge->Start = P0;PEdge->End = P1; }
	else { PEdge->Start = P1;PEdge->End = P0; }
}



#define E3dEdge_Copy(pSrc, pDst)  *pDst = *pSrc

#define _E3dEdges_Cmp_pp(p0, p1) do\
{\
	if(p0->Start < p1->Start) return(-1);\
	else if(p0->Start > p1->Start) return(1);\
	else\
	{\
		if(p0->End < p1->End) return(-1);\
		else if(p0->End > p1->End) return(1);\
		else return(0);\
	}\
} while(0)

/*
#define E3dMesh_WingedEdgesFree(pMesh) do\
{\
	if(pMesh->WingedEdges)\
	{\
printf("%sWingedEdges%s           <%s%p:%s%s>  %s()  %s:%d\n", ECodeRed, ECodeNormal, ECodeCyan, pMesh, ECodeNormal, pMesh->Name, __FUNCTION__, __FILE__, __LINE__);fflush(stdout);\
		E3dWingedEdges_Free(&pMesh->WingedEdges, pMesh->Edges_Count);\
	}\
} while(0)


#define E3dMesh_CreateWingedEdgesFromEdges(pMesh, pKeepVertexLinks) do\
{\
printf("%sWingedEdges%s FromEdges <%s%p:%s%s>  %s()  %s:%d\n", ECodeGreen, ECodeNormal, ECodeCyan, pMesh, ECodeNormal, pMesh->Name, __FUNCTION__, __FILE__, __LINE__);fflush(stdout);\
	_E3dMesh_CreateWingedEdgesFromEdges(pMesh, pKeepVertexLinks);\
} while(0)
*/


// Vertex functions
extern E3dVertex*       E3dVertices_New(const E3dVertexSize PVertexSize, const EIndex PNumOfVertices,  const EBool PInitialize);
extern E3dVertex*       E3dVertices_Add(E3dVertex* POldVertices, const E3dVertexSize PVertexSize,  const EIndex PNumOfOldVertices, const EIndex PNumOfNewVertices, const EBool PInitialize);

extern E3dVertex*       E3dMesh_VerticesAdd(E3dMesh* PMesh, const EIndex PCount);
extern EBool            E3dMesh_VertexRemove(E3dMesh* PMesh, const EIndex PIndex);
extern void             E3dMesh_VerticesFree(E3dMesh* PMesh);
extern EIndex           E3dMesh_NumOfSelectedVertices(const E3dMesh* PMesh, const float PSoftSelectionThreshold, EIndex* PNSoftSelectedVertices);
extern EIndex           E3dMesh_FilterVertices(const E3dMesh* PMesh, const unsigned int PWhatToInclude);
extern void             E3dMesh_VerticesRemap(E3dMesh* PMesh, const EIndex* PRemappingTable, const EIndex PNumOfVertices);
extern EIndex           E3dMesh_VertexGetConnectedVertices(const E3dMesh* PMesh, const EIndex PVertexIndex, EIndex** PVertexIndicesPtr);
extern EIndex           E3dMesh_VertexGetEdges(const E3dMesh* PMesh, const EIndex PVertexIndex, E3dEdge*** PEdgesPtr);
extern EIndex           E3dMesh_VertexGetNumOfPolygons(const E3dMesh* PMesh, const EIndex PVertexIndex);
extern EIndex           E3dMesh_VertexGetPolygons(const E3dMesh* PMesh, const EIndex PVertexIndex, E3dPolygon*** PPolygonsPtr, E3dVertexNode*** PVertexNodesPtr, E3dPolyGroup*** PPolyGroupsPtr);


extern int                  E3dVertexLinks_AddEdge(E3dVertexLinkNew* PVertexLinks, const EIndex PVertexLinksStride,  const EIndex PStartV, const EIndex PEndV,  const EIndex PEdgeIndex);
extern E3dVertexLinkNew*       E3dVertexLinks_FromEdges(const E3dEdge* PEdges, const EIndex PEN,  const EIndex PVN, const EIndex PVStride);
extern E3dVertexLinkNew*       E3dMesh_GetVertexLinksNew(E3dMesh* PMesh, const uint16_t PFlags);

extern void                E3dVertexLinks_Free(E3dVertexLinkNew* PVertexLinks, const EIndex PN, const EIndex PStride);
extern void                E3dMesh_VertexLinksNewFree(E3dMesh* PMesh);


// Edge functions
extern E3dEdge*       E3dEdges_New(const EIndex PEdgeNum);
extern E3dEdge*       E3dEdges_Add(E3dEdge* POldEdges, const EIndex PNumOfOldEdges, const EIndex PNumOfNewEdges, const EBool PInitialize);
extern E3dEdge*       E3dMesh_EdgesNew(E3dMesh* PMesh, const EIndex PCount, const EBool PInitialize);
extern E3dEdge*       E3dMesh_EdgesAdd(E3dMesh* PMesh, const EIndex PCount, const EBool PInitialize);
extern void           E3dMesh_EdgesFree(E3dMesh* PMesh);
extern EIndex         E3dMesh_EdgeGetIndex(E3dMesh* PMesh, const E3dVertexIndex PStart, const E3dVertexIndex PEnd);
extern int            E3dMesh_EdgesSorted(E3dMesh* PMesh);
extern int            E3dEdges_Sort(E3dEdge* PEdges, const EIndex PCount);
extern int            E3dMesh_EdgesSort(E3dMesh* PMesh, const EBool PCheckIfSorted);
extern void           E3dWingedEdges_Free(E3dWingedEdge** PEdges, const EIndex PCount);

extern void           E3dMesh_WingedEdgesFree(E3dMesh* PMesh);
extern void           E3dMesh_CreateWingedEdgesFromEdges(E3dMesh* PMesh, const EBool PKeepVertexLinks, const EBool PRepair);

extern void           E3dPolyGroup_CreateEdgesFromPolygons(E3dPolyGroup* PPolyGroup, const EIndex PNVertices,  E3dVertexLinkNew* PVertexLinks, const EIndex PVertexLinksStride,  E3dEdge** PEdgesP, EIndex* PNEdgesP);

extern void           E3dMesh_CreateEdgesFromPolygons(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup, const EBool PUpdateWingedEdges, const EBool PKeepVertexLinks);
extern void           E3dMesh_ClearActiveEdgeFlags(E3dMesh* PMesh);
extern E3dCoord3Sum*  E3dMesh_GetEdgeNormals(const E3dMesh* PMesh);
extern void           E3dMesh_EdgePolygonGetInfo(const E3dMesh* PMesh, const E3dEdge* PEdge, const EIndex PPolyGroupIndex, E3dPolygon* PPolygon,  E3dEdgePolygonInfo** PDescriptors, EIndex* PDescriptors_Count, EIndex* PDescriptors_CountAllocated,  uint32_t* PDescription);
extern EIndex         E3dMesh_EdgeGetPolygons(const E3dMesh* PMesh, const E3dEdge* PEdge, E3dEdgePolygonInfo** PDescriptorsP, unsigned int* PDescriptionP);

extern EIndex         E3dMesh_NumOfVisibleEdges(const E3dMesh* PMesh);
extern EIndex         E3dMesh_NumOfSelectedEdges(const E3dMesh* PMesh);

extern E3dVertex*     E3dMesh_EdgeAddVertex(E3dMesh* PMesh, const E3dEdge* PEdge, const E3dCoord3* PPosition3, const E3dCoordinate PU);
extern void           E3dMesh_EdgeFlagsUpdate(E3dMesh* PMesh);
extern int            E3dMesh_PolyGroupsEdgesFromMeshEdges(E3dMesh* PMesh, const EBool PKeepEdgeCaches, const EBool PRepair);
enum
{
	E3dEdgeNOT_SHARED_BY_2_POLYS         = -100,
	E3dEdgePOLYS_IN_DIFFERENT_POLYGROUPS = -101,
	E3dEdgeIN_HOLE                       = -102,
	E3dEdgeVERTEX_WITH_VALENCE_2         = -103
};
extern int            E3dMesh_EdgeMergePolygons(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup, const E3dEdge* PEdge,  E3dEdgePolygonInfo* PEdgeDescriptors, const int PNumOfPolygonsOnEdge,  const EBool PDeletePolys, E3dPolygon** PNewPolygonP);


// PolyGroup functions
extern int            E3dMesh_AppendPolyGroup(E3dMesh* PMesh,  E3dPolyGroup* PPolyGroup);
extern E3dPolyGroup*  E3dMesh_PolyGroupAdd(E3dMesh* PMesh);
extern int            E3dMesh_PolyGroupDel(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup);
extern void           E3dMesh_PolyGroupsFree(E3dMesh* PMesh);

typedef struct
{
	uint8_t  Mode;E3dCoordinate  Spacing, Scaling;
} E3dMergePolyGroupsLayoutComponent;

typedef struct
{
	EBool                              Active;
	E3dMergePolyGroupsLayoutComponent  LayoutST0, LayoutST1, LayoutUV;
} E3dMergePolyGroups;

extern EIndex         E3dMesh_MergePolyGroups(E3dMesh* PMesh, E3dMergePolyGroups* PSettings);


// Polygon functions
extern void           E3dMesh_PolygonsFree(E3dMesh* PMesh);
extern E3dPolygon*    E3dMesh_PolyGroupAddPolygon(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup);
extern E3dPolygon*    E3dMesh_PolyGroupAddPolygons(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup, const EIndex PNumOfNewPolygons);
extern E3dPolygon*    E3dMesh_AddAndInitPolygon(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup, const uint16_t PFlags, EIndex PNumOfVertexNodes,...);
extern void           E3dMesh_RemovePolygon(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup, E3dPolygon* PPolygon);
extern void           E3dMesh_ChangePolygonFlags(E3dMesh* PMesh, const E3dPolygonFlags PFlags, const int PAction);
extern E3dTriangleStrip*  E3dMesh_PolyGroupAddTriangleStrip(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup);
extern E3dTriangleStrip*  E3dMesh_PolyGroupAddTriangleStrips(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup, const EIndex PNumOfNewStrips);
extern void            E3dMesh_CreateRenderablePolygons(E3dMesh* PMesh, const EBool PDoConvex);


extern void            E3dMesh_RecomputePolygonNormals(E3dMesh* PMesh);
extern void            E3dMesh_RecomputeNormals(E3dMesh* PMesh, const EBool PRefreshPolygonNormals, const EBool PRefreshMeshVertexNormals);
extern void            E3dMesh_GenerateVertexNormals(E3dMesh* PMesh);





// Utility/misc functions
extern E3dCoord3*     E3dMesh_GetRayDisplacements(E3dMesh* PMesh, E3dCoordinate PDistance);
extern void           E3dMesh_FreeCaches(E3dMesh* PMesh);
extern void           E3dMesh_RenderDataFree(E3dMesh* PMesh);

extern EIndex         E3dMesh_TextureMappingUpdate(E3dMesh* PMesh, const EBool PUpdateSTs);



// Algorithm choices for E3dMesh_GetVertexNormals
//
enum
{
	E3dMeshVertexNormalFROM_POLYGONS = 1,
	E3dMeshVertexNormalFROM_EDGES    // More accurate, but expensive (need to build WingedEdges etc.)
};

extern E3dCoord3Sum*   E3dMesh_GetVertexNormals(const E3dMesh* PMesh, const uint8_t PAlgorithm);


extern void            E3dMesh_EdgesAndPolyGroupsRemapVertexIndices(E3dMesh* PMesh, const EIndex* PInToNewVertexIndexTable);

extern void            E3dPolyGroup_RefreshPolygonNormals(E3dPolyGroup* PPolyGroup,  const E3dVertex* PVertices, const EIndex PNVertices, const E3dVertexSize PVertexSize);

extern E3dCoordinate   E3dMeshPolyGroup_Area(const E3dMesh* PMesh, const E3dPolyGroup* PPolyGroup);
extern void            E3dMeshPolyGroup_Check(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup);
extern void            E3dMeshPolyGroup_RefreshPolygonNormals(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup);
extern void            E3dMeshPolyGroup_RefreshNormals(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup, const int PPolyVertexNormalType, const E3dCoordinate PSmoothingAngle);
extern void            E3dMeshPolyGroup_UpdateForDisplay(E3dMesh* Pmesh, E3dPolyGroup* PPolyGroup,  const EUpdateFlags PUpdateFlags, const ECallFlags PCallFlags);

extern EIndex          E3dMeshPolyGroup_CollectVertexAttributes(const E3dMesh* PMesh, const E3dPolyGroup* PPolyGroup,  const char* PSemantic, const int PIndex, const EBool PIndexed,  EResource** PAttributesRet, void* PBufferRet, unsigned int* PStrideRet, E3dVertexIndex** PIndicesRet, EIndex* PTotalNumOfVertexNodesRet);
extern EIndex          E3dMeshPolyGroup_CollectVertexNodes(const E3dMesh* PMesh, const E3dPolyGroup* PPolyGroup, const EBool PCompress,  E3dVertexNode** PBufferRet, EIndex** PRemappingTableRet);


extern EIndex          E3dMeshPolyGroup_NumOfSelectedEdges(const E3dMesh* PMesh, const E3dPolyGroup* PPolyGroup);


// Utility functions
extern EBool       E3dMesh_GetBoundingBox(const E3dMesh* PMesh, const uint32_t PWhatToInclude, E3dBBox* PBBox);
extern EBool       E3dMesh_GetTransformedBoundingBox(const E3dMesh* PMesh, const E3dMatrix PMatrix, const uint32_t PWhatToInclude, E3dBBox* PBBox);
extern EBool       E3dMesh_GetPerspectiveProjectedBoundingBox(const E3dMesh* PMesh, const E3dMatrix PMatrix, const uint32_t PWhatToInclude, E3dCoord2* PBBMin, E3dCoord2* PBBMax, E3dCoord4* PMaxProjectedXYAbsValPoint);


extern E3dCoordinate*  E3dMesh_GenerateSurfacePoints(const E3dModel* PModel, const E3dMesh* PMesh, const E3dPolyGroup* PPolyGroup,  const EIndex PNumOfPoints, const int PRandomSeed, const EBool PGetNormals, const EIndex PDensityTextureIndex, const int PDensityTextureChannel, E3dRPolyGroup*** PRPolyGroupsP, E3dSurfacePointSample** PSurfacePointSamplesP);

extern void            E3dMesh_CreateWireSphere(E3dMesh* PProjMesh,  const E3dCoord3* PCenter, const E3dCoordinate PRadius,
                        const E3dCoordinate PUStartAngle, const E3dCoordinate PUEndAngle, const EIndex PUCount, const EIndex PUSub1, const EIndex PUSub2,
                        const E3dCoordinate PVStartAngle, const E3dCoordinate PVEndAngle, const EIndex PVCount, const EIndex PVSub1, const EIndex PVSub2);


extern void            E3dMesh_FromGLArrays(E3dMesh* PMesh,
                        const float* PVertexPositions,  const int PVertexPositionStride,
                        const float* PTextureCoords,  const int PTextureCoordStride,
                        const void* PIndexLists, const int* PIndexCounts, const EIndex PNIndexLists, const int PIndexType);


extern int            E3dMesh_VertexAttributeDel(E3dMesh* PMesh,  const char* PSemantic, const EIndex PIndex);

extern void           E3dVertexAttributeVisualization_Free(E3dVertexAttributeVisualizationListA* PVis, const EBool PFreeArray);

extern void           E3dVertexGeometry_Init(E3dVertexGeometry* PVertexGeometry);
extern void           E3dVertexGeometry_FreeContents(E3dVertexGeometry* PVertexGeometry);

extern int            E3dVertexGeometry_VertexAttributeDelByIndex(E3dVertexGeometry* PVertexGeometry,  const EIndex PIndex);
extern E3dVertex*     E3dVertexGeometry_VerticesAdd(E3dVertexGeometry* PVertexGeometry, const EIndex PCount);
extern int            E3dVertexAttribute_Add(EResourceList* PList,  const char* PSemantic, const char* PName, const uint16_t PType, const EIndex PCount,  EResource** PVARet);
extern int            E3dVertexGeometry_VertexAttributeAdd(E3dVertexGeometry* PVertexGeometry,  const char* PSemantic, const char* PName, const uint16_t PType, const EIndex PCount,  EResource** PAttrRet);

extern uint16_t       E3dVertexAttribute_VisualizationType(const EResource* PAttr);


extern E3dEPolygon**  E3dMesh_GetPolygonEdgeIndices(const E3dMesh* PMesh);
extern void           E3dMesh_FreePolygonEdgeIndices(const E3dMesh* PMesh, E3dEPolygon** PEPolygonLists, const EIndex PPGN);

extern EIndex         E3dMesh_NumOfSelectedPolygons(const E3dMesh* PMesh);

extern int            E3dMesh_Check(const E3dMesh* PMesh, const int PIndent);
extern void           E3dMesh_EdgesPrint(const E3dMesh* PMesh);

extern void           E3dMesh_FromBBox(E3dMesh* PMesh,  const E3dBBox* PBBox);

extern EIndex         E3dPolyGroup_TextureMappingUpdate(E3dVertexGeometry* PVertexGeometry, E3dPolyGroup* PPolyGroup,  const EBool PUpdateSTs);


extern void        E3dGL_VertexArrayCheck(void* PGLArrayIn, const int PGLArraySize, const unsigned int PGLArrayVertexNodeSize, const unsigned int* PGLTriangleVertexIndexArray, const int PN);
extern void        E3dMesh_GLRefreshPolyVertices(E3dMesh* PMesh);
extern void        E3dMesh_PolyGroupRefreshGLPolyVertices(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup);
extern void        E3dMesh_FreeVertexArrays(E3dMesh* PMesh);


//--------------------------------
// Polygon.c
//--------------------------------
extern EIndex	     E3dPolygon_GetAllConnectedPolygons(E3dPolyGroup* PPolyGroup, E3dPolygon* PPolygon, const uint32_t PFlags, const EBool POnlyFromPPolyGroup, E3dPolyInfo** PPolygonsP);


//--------------------------------
// PolyGroup.c
//--------------------------------
extern EIndex         E3dPolyGroup_GetTextureMappers(const E3dVertexGeometry* PVertexGeometry, const E3dPolyGroup* PPolyGroup,  E3dTextureMapperPtrList* PTextureMappers);


//--------------------------------
// TextureMapping.c
//--------------------------------
extern int        E3dPolyGroup_Map2DTextureByMapper(E3dVertexGeometry* PVertexGeometry, E3dPolyGroup* PPolyGroup, E3dTextureMapper* PTextureMapper);

extern int        E3dVertexGeometry_Map2DTextureByMapper(E3dVertexGeometry* PVertexGeometry, E3dTextureMapper* PTextureMapper);
extern void       E3dRPolyGroup_UpdateTextureMappers(E3dVertexGeometry* PVertexGeometry, E3dPolyGroup* PSrcPolyGroup,  E3dRPolyGroup* PRPolyGroup);


//--------------------------------
// GeometryAdv.c
//--------------------------------
extern int         E3dMeshPolyGroup_TextureLayout(E3dMesh* PMesh, E3dPolyGroup* PPolyGroup,  const char* PSemantic, const int PIndex,  const E3dCoordinate PMarginX, const E3dCoordinate PMarginY,  const E3dCoordinate PSpacingX, const E3dCoordinate PSpacingY,  E3dCoordinate* PAspectRatioRet);


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif

#endif	// _E3D_Mesh_h
