//================================================================
// E3D
//
// General Geometry-related functions header file
//
// AUTHOR:  Gabor Nagy
// DATE:    2025-Sep-07 20:29:41
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//================================================================
#ifndef _E3D_Geometry_h
#define _E3D_Geometry_h


#ifndef _E3D_Object_h
#include <E3D/Object.h>
#endif

#ifndef _E3dMaterial
#define _E3dMaterial
typedef struct E3dMaterial_S   E3dMaterial;    // Forward-define E3dMaterial
typedef struct E3dMaterial_S*  E3dMaterialPtr;
EList_t(E3dMaterialPtr);     // E3dMaterialPtrList
EListA_t(E3dMaterialPtr);    // E3dMaterialPtrListA
#endif


//------------------------------------------------------------------------
// Template functions
//------------------------------------------------------------------------

#define E3dTpl_ObjectComponentActivateWithCustomDefaultsCB_Geometry(pType, pPrefix, pComponentTemplate, pName,  pPlugin) do\
{\
	E3dScene*   lScene = E3d_Scene;\
	E3dObject*  lObject = NULL;\
\
	E3dModel*  lModel = E3dModel_CustomObjectNewInit(E3d_Scene, pComponentTemplate, &lObject, pName, (E3dp_Prefs.Duplicate_Flags & E3dCopyMODEL_UNIQUE_NAME) != 0);if(lModel)\
	{\
		E3dGeometry*  lGeometry = (E3dGeometry*)lObject;\
\
		lGeometry->AutoLOD = FALSE;\
\
		E3dScene_NodeHrcAdd(lScene, (E3dNode*)lModel, E3dCallSCENE_CALLBACKS);\
\
		E3dScene_ObjectsUpdateModelList(lScene);\
		E3dScene_LayoutOnSchematics(lScene, TRUE);\
	}\
\
	if(lObject)\
	{\
		if(((XePushButtonCallbackStruct*)PCallData)->Reason == XeCR_ACTIVATE_OPTIONS) E3dObject_Edit(lObject, (pPrefix##ComponentClass));\
		E3dWindows_RedrawByChangeFlags(lScene, E3dObject_GetChangeFlagsByClass(lObject)|E3dChgHIERARCHY);\
	}\
} while(0)


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


#ifndef _E3dGeometry
#define _E3dGeometry
typedef struct E3dGeometry_S   E3dGeometry;    // Forward-define E3dGeometry
#endif

typedef struct E3dGeometry_S*  E3dGeometryPtr;
EListA_t(E3dGeometryPtr);    // E3dGeometryPtrListA

#ifndef _E3dModel
#define _E3dModel
typedef struct E3dModel_S     E3dModel;        // Forward-define E3dModel
#endif


// Edge flags
//
// These two are saved into files, when Mesh->SaveEdges is TRUE
//
#define E3dEdgeSELECTED  0x0001    // Edge is selected
#define E3dEdgeVISIBLE   0x0002    // Edge is visible (e.g. Subdivision Surfaces may only show the ControlMesh Edges

#define E3dEdgeACTIVE    0x0004    // Mouse pointer is on Edge
#define E3dEdgeDRAWN     0x0008    // Edge has already been drawn
#define E3dEdgePASS      0x0010    // Temporary marker flag
#define E3dEdgeMARK0     0x0020    // Temporary marker flag
#define E3dEdgeFlagALL   0x003F

#define E3dEdgeDEFAULT   E3dEdgeVISIBLE

typedef struct
{
	E3dVertexIndex  Start, End;  // Index of starting and ending Vertex
	E3dEdgeFlags    Flags;
	float           Hardness;    // For subdivision surfaces
} E3dEdge;
EListA_t(E3dEdge);

typedef E3dGeometry*  (*E3dGetLOD)(E3dGeometry* PGeometry, const E3dCoordinate PSizeFactor);

// Per-vertex vectors or RGBA colos for VertexAttribute (e.g. normal, tangent, deformer weights) visualization.
// Elements are non-indexed and directly correspond to Vertices.
//
typedef struct
{
	char*     Semantic;       // So we can decide what color to use for vectors (e.g. normals)
	void*     Values;
	EIndex    NValues;        // Number of values in Values
	uint16_t  Type;           // E3dCOLOR or E3dLINES
	uint16_t  ComponentType;  // EResFLOAT32, EResINT16 etc.
} E3dVertexAttributeVisualization;
EListA_t(E3dVertexAttributeVisualization);

typedef struct
{
// Bounding box wireframe
//
	void*          VertexData;         // Vertex array
	unsigned int   VertexSize,         // VertexNode size (stride) for BBoxGLArray, in bytes
	               ArraySize;          // Size of BBoxGLArray in bytes
	unsigned int*  EdgeVertexIndices;
	EIndex         NLines;
} E3dBBoxGPUData;


typedef struct
{
	E3dBBoxGPUData  BBox;
} E3dGeometryGPUData;


// Fields of the generic Geometry structure (these are the first fields in all Geometry structures)
//
#define E3dGeometryCore\
	E3dObjectCore;\
	E3dGetLOD       GetLOD;                  /* For procedural (e.g. continous LOD on a subdiv. Mesh) LOD   */\
	E3dCoordinate   LODReference;            /* Level Of Detail "activation distance" for this Geometry     */\
	int             LODStep;                 /* Force displaying this LOD. 0: Original                      */\
	EList(, E3dGeometry*, LODs);             /* Levels of detail beyond this one                            */\
\
	E3dBBox         BBox;                    /* Bounding box                     */\
	ETime           Shape_TimeStamp;         /* The last time the shape changed  */\
\
	EBool           AutoLOD;\
\
	EBool           CastsShadows;\
	EBool           ReceivesShadows;\
\
	uint32_t        BBoxUptodate : 1;\
\
	E3dGeometryGPUData*  GeometryGPUData




// Generic Geometry structure
//
struct E3dGeometry_S
{
	E3dGeometryCore;
};


extern E3dObjectClass  E3dGeometry_class[];


//--------------------------------------------------------
// Function prototypes
//--------------------------------------------------------
extern void  E3dBBox_ToPoints(const E3dBBox* PBBox, E3dCoord3* PPoint);

extern void  E3dBBoxGPUData_Init(E3dBBoxGPUData* PGPUData);
extern void  E3dBBoxGPUData_FreeContents(E3dBBoxGPUData* PGPUData);
extern void  E3dBBoxGPUData_Update(E3dBBox* PBBox, E3dBBoxGPUData* PGPUData);
extern void  E3dBBox_GLDraw(const E3dBBoxGPUData* PBBox, const EcRGBAf32Color* PColor, const float PLineWidth);

extern E3dGeometry*  E3dGeometry_GetLODForDrawing(const E3dMatrix PWorldToViewerMatrix, const E3dCoordinate PSizeFactor, const E3dModel* PModel, E3dGeometry* PGeometry);

extern const char   E3dUI_Show0[], E3dUI_Show1[], E3dUI_Show2[], E3dUI_Show3[], E3dUI_ShowAll[], E3dUI_ShowAsVector[];
extern const char*  E3dUI_Show[];

extern void    E3dGeometry_InvalidateBBox(E3dGeometry* PGeometry);

//--------------------------------------------------------
// E3D/GeometryAdv.c
//--------------------------------------------------------
extern EIndex  E3dGeometry_TextureMappingUpdate(E3dGeometry* PGeometry, const EBool PUpdateSTs);

extern int     E3dGeometry_Invert(E3dGeometry* PGeometry, EChangeFlags* PChangedP);

extern void    E3dGeometry_Transform(E3dGeometry* PGeometry, const E3dMatrix PMatrix);

extern EBool   E3dGeometry_GetBoundingBox(E3dGeometry* PGeometry, const uint32_t PWhatToInclude,  E3dBBox* PBBox);
extern EBool   E3dGeometry_GetTransformedBoundingBox(const E3dGeometry* PGeometry, const E3dMatrix PMatrix, const uint32_t PWhatToInclude,  E3dBBox* PBBox);
extern EBool   E3dGeometry_GetPerspectiveProjectedBoundingBox(E3dGeometry* PGeometry, const E3dMatrix PMatrix, const uint32_t PWhatToInclude,  E3dCoord2* PBBMin, E3dCoord2* PBBMax,  E3dCoord4* PMaxProjectedXYAbsValPoint);


extern int     E3dGeometry_Tesselate(E3dGeometry* PGeometry, const EBool PSelectionOnly, const EBool PDoConvex);
extern int     E3dGeometry_ReplaceTexturePaths(E3dGeometry* PGeometry, const char* PTexturePath);

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

#endif	// _E3D_Geometry_h
