//========================================================================
// E3D library
//
// - VertexNodes
// VertexNodes are used on Polygons, TriangleStrips Faces etc.
//
// AUTHOR:  Gabor Nagy
// DATE:    2025-Dec-08 01:03:11
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//========================================================================
#ifndef _E3D_VertexNode_h
#define _E3D_VertexNode_h


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

// VertexAttributes flags
//
// These flags describe what's in the VertexNodes of a PolyGroup
//

// Built-in components
//
#define E3dVtxNodeNORMAL  0x00000004


// Optional components
//
#define E3dVtxNodeEDGE_INDEX    0x00000002  // Index of Mesh Edge that starts at this VertexNode
#define E3dVtxNodeCOLORRGBA8    0x00000010  // RGBA8
#define E3dVtxNodeCOLORRGBAf32  0x00000020  // RGBAf32
#define E3dVtxNodeST0           0x00000100  // Texture coordinates
#define E3dVtxNodeST1           0x00000200
#define E3dVtxNodeST2           0x00000400
#define E3dVtxNodeST3           0x00000800
#define E3dVtxNodeST4           0x00001000
#define E3dVtxNodeST5           0x00002000
#define E3dVtxNodeST6           0x00004000
#define E3dVtxNodeST7           0x00008000
#define E3dVtxNodeTANGENT       0x00010000  // Tangent for anisotropic shading
#define E3dVtxNodeUV            0x00100000  // U-V parameters

#define E3dVtxNodeCORE          0

#define E3dVtxNodeST  (E3dVtxNodeST0|E3dVtxNodeST1|E3dVtxNodeST2|E3dVtxNodeST3|E3dVtxNodeST4|E3dVtxNodeST5|E3dVtxNodeST6|E3dVtxNodeST7)

#define E3dVtxNodeMAX_ST  8

#define E3dVertexNodeCoreM\
 E3dVertexIndex  VertexID;		// Mesh Vertex index. Negative numbers separate the contours. E.g. -3 means that there's a hole coming up with 3 Vertices


// E3dFIXME_64BIT
// Add support for very large Meshes with E3dVtxNodeEDGE_INDEX VertexAttributes
// Some places may still assume E3dEdgeIndex to be an uinsigned int / int
// Check with features that use E3dPolygon_GetAllConnectedPolygons(). E.g. _MCB_FixPolygonDirections()
//
#define E3dEDGEINDEX_TYPE  EResINT32
typedef int32_t            E3dEdgeIndex;

#define E3dVtxNodeFlagEDGE_DEC         0x40000000  // OR-ed to Vertex attribute E3dVtxNodeEDGE_INDEX if not 0, Edge that starts at this VertexNode starts at higher VertexNode index (than the Edge End).
#define E3dVtxNodeFlagEDGE_BACKWARD    0x80000000  // OR-ed to Vertex attribute E3dVtxNodeEDGE_INDEX if not 0, Edge that starts at this VertexNode goes against Polygon winding order.
#define E3dVtxNodeFlagEDGE_INDEX_MASK  0x3FFFFFFF


typedef struct
{
	E3dVertexNodeCoreM;
} E3dVertexNodeCore;

typedef struct
{
	E3dVertexNodeCoreM;
} E3dVertexNode;


extern const char  E3dVtxAttribute_Position[];
extern const char  E3dVtxAttribute_Flags[];
extern const char  E3dVtxAttribute_EdgeIndex[];
extern const char  E3dVtxAttribute_Normal[];
extern const char  E3dVtxAttribute_Color[];
extern const char  E3dVtxAttribute_ST[];
extern const char  E3dVtxAttribute_UV[];
extern const char  E3dVtxAttribute_Tangent[];
extern const char  E3dVtxAttribute_SoftSelection[];

extern const EResource  E3dVtxAttrNormal;
extern const EResource  E3dVtxAttrEdgeIndex;
extern const EResource  E3dVtxAttrColorRGBAf32;
extern const EResource  E3dVtxAttrColorRGBAu8;
extern const EResource  E3dVtxAttrST;
extern const EResource  E3dVtxAttrUV;
extern const EResource  E3dVtxAttrTangent;


typedef uint32_t	E3dVertexAttributeFlags;


//============================================================================
// Return TRUE if a given VertexNode index points to a contour start
//============================================================================
static inline EBool E3dVertexNode_IndexIsContourStart(const E3dVertexNode* PVertexNodes, const E3dVertexNodeSize PVertexNodeSize, const EIndex PIndex)
{
	if(PIndex == 0) return(TRUE);
	else
	{
		const E3dVertexNode*  LVertexNode = EStruct_ByIndex(PVertexNodes, PVertexNodeSize, PIndex - 1);
		if(LVertexNode->VertexID < 0) return(TRUE);
	}
	return(FALSE);
}

extern int                E3dSemantic_ToType(const char* PSemantic, EIndex* PCount, EIndex* PSizeR);

EList_s(extern, EResource, E3dVertexGeometry_DefaultVertexAttributes);
//#define E3dVertexCore_Size() EResourceList_ValuesSize(&E3dVertexGeometry_DefaultVertexAttributes)
#define E3dVertexCore_Size() sizeof(E3dVertex)    // Rely on the compiler to properly pad the core of E3dVertex for memory alignment on th particular architecture (EResourceList_ValuesSize(&E3dVertexGeometry_DefaultVertexAttributes) may give us 14, which might break 4-byte alignment)

extern void               E3dVertexAttribute_ListInit(EResourceList* PList);

extern const char*        E3dVertexNode_SemanticGetBuiltIn(const char* PSemantic);

extern E3dVertexNode*     E3dVertexNodes_New(const int PNumOfVertexNodes, const E3dVertexNodeSize PVertexNodeSize);
extern E3dVertexNodeSize  E3dVertexNode_Size(const EResourceList* PComponents);

extern EBool              E3dVertexAttribute_IsST(const EResource* PVA);
extern void               E3dVertexNodeAttribute_ListInit(EResourceList* PList);
extern void               E3dVertexAttribute_ListFree(EResourceList* PList);
extern void               E3dVertexAttribute_ListUpdateOffsets(EResourceList* PList, const EIndex PBaseOffset);

extern int                E3dVertexNodeAttribute_Add(EResourceList* PList,  const char* PName, const char* PSemantic, const int PIndex,  const EResource* PCustomAttr,  EResource** PVARet);
extern E3dVertexNodeSize  E3dVertexNodeAttribute_Offset(const EResourceList* PList, const char* PSemantic, const int PIndex);
extern EIndex             E3dVertexNodeAttribute_GetIndex(const EResourceList* PList,  const char* PSemantic, const int PIndex);


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

#endif	// _E3D_VertexNode_h
