#ifndef _GF_MESH_H_
#define _GF_MESH_H_
#include <gpac/scenegraph_vrml.h>
#include <gpac/path2d.h>
#include <gpac/mediaobject.h>
#ifdef MESH_USE_SFCOLOR
#define MESH_MAKE_COL(_argb) _argb
#define MESH_GET_COLOR(_argb, _vertex) _argb = (_vertex).color;
#else
#define MESH_MAKE_COL(_argb) GF_COL_ARGB(FIX2INT(255*(_argb.alpha)), FIX2INT(255*(_argb.blue)), FIX2INT(255*(_argb.green)), FIX2INT(255*(_argb.red)))
#define MESH_GET_COLOR(_argb, _vertex) { _argb.alpha = INT2FIX(GF_COL_A((_vertex).color))/255; _argb.red = INT2FIX(GF_COL_R((_vertex).color))/255; _argb.green = INT2FIX(GF_COL_G((_vertex).color))/255; _argb.blue = INT2FIX(GF_COL_B((_vertex).color))/255; }
#endif
#ifdef MESH_USE_FIXED_NORMAL
#define MESH_SET_NORMAL(_vertex, _nor) _vertex.normal = _nor;
#define MESH_GET_NORMAL(_nor, _vertex) _nor = _vertex.normal;
#define MESH_NORMAL_UNIT FIX_ONE
#else
typedef struct
{
s8 x, y, z;
s8 __dummy;
} SFVec3f_bytes;
#define MESH_NORMAL_UNIT 1
#ifdef GPAC_FIXED_POINT
#define MESH_SET_NORMAL(_vertex, _nor) { SFVec3f_bytes __nor; __nor.x = (s8) FIX2INT(_nor.x*100); __nor.y = (s8) FIX2INT(_nor.y*100); __nor.z = (s8) FIX2INT(_nor.z*100); __nor.__dummy=0; _vertex.normal = __nor; }
#define MESH_GET_NORMAL(_nor, _vertex) { (_nor).x = INT2FIX(_vertex.normal.x); (_nor).y = INT2FIX(_vertex.normal.y); (_nor).z = INT2FIX(_vertex.normal.z); gf_vec_norm(&(_nor)); }
#else
#define MESH_SET_NORMAL(_vertex, _nor) { SFVec3f_bytes __nor; __nor.x = (s8) (_nor.x*100); __nor.y = (s8) (_nor.y*100); __nor.z = (s8) (_nor.z*100); __nor.__dummy=0; _vertex.normal = __nor; }
#define MESH_GET_NORMAL(_nor, _vertex) { (_nor).x = _vertex.normal.x; (_nor).y = _vertex.normal.y; (_nor).z = _vertex.normal.z; gf_vec_norm(&(_nor)); }
#endif
#endif
typedef struct
{
SFVec3f pos;
SFVec2f texcoords;
#ifdef MESH_USE_FIXED_NORMAL
SFVec3f normal;
#else
SFVec3f_bytes normal;
#endif
#ifdef MESH_USE_SFCOLOR
SFColorRGBA color;
#else
u32 color;
#endif
} GF_Vertex;
#define MESH_TEX_OFFSET 12
#define MESH_NORMAL_OFFSET 20
#ifdef MESH_USE_FIXED_NORMAL
#define MESH_COLOR_OFFSET 32
#else
#define MESH_COLOR_OFFSET 24
#endif
enum
{
MESH_TRIANGLES = 0,
MESH_POINTSET,
MESH_LINESET,
};
enum
{
MESH_HAS_COLOR = 1,
MESH_IS_2D = 1<<1,
MESH_NO_TEXTURE = 1<<2,
MESH_IS_CW = 1<<3,
MESH_IS_SOLID = 1<<4,
MESH_IS_SMOOTHED = 1<<5,
MESH_HAS_ALPHA = 1<<6,
};
#if defined(GPAC_USE_GLES1X) || defined(GPAC_USE_GLES2)
#define IDX_TYPE u16
#else
#define IDX_TYPE u32
#endif
typedef struct __gf_mesh
{
u32 v_count, v_alloc;
GF_Vertex *vertices;
u32 i_count, i_alloc;
IDX_TYPE *indices;
u32 mesh_type;
u32 flags;
GF_BBox bounds;
struct __AABBNode *aabb_root;
IDX_TYPE *aabb_indices;
u32 vbo;
u32 vbo_idx;
Bool vbo_dirty, vbo_dynamic;
} GF_Mesh;
GF_Mesh *new_mesh();
void mesh_free(GF_Mesh *mesh);
void mesh_reset(GF_Mesh *mesh);
void mesh_update_bounds(GF_Mesh *mesh);
void mesh_set_vertex_vx(GF_Mesh *mesh, GF_Vertex *vx);
void mesh_set_vertex(GF_Mesh *mesh, Fixed x, Fixed y, Fixed z, Fixed nx, Fixed ny, Fixed nz, Fixed u, Fixed v);
void mesh_set_index(GF_Mesh *mesh, u32 idx);
void mesh_set_point(GF_Mesh *mesh, Fixed x, Fixed y, Fixed z, SFColorRGBA col);
void mesh_set_triangle(GF_Mesh *mesh, u32 id1, u32 id2, u32 id3);
void mesh_clone(GF_Mesh *dest, GF_Mesh *orig);
void mesh_recompute_normals(GF_Mesh *mesh);
void mesh_generate_tex_coords(GF_Mesh *mesh, GF_Node *__texCoords);
void mesh_new_unit_bbox(GF_Mesh *mesh);
void mesh_new_rectangle(GF_Mesh *mesh, SFVec2f size, SFVec2f *orig, Bool flip);
void mesh_new_ellipse(GF_Mesh *mesh, Fixed a_dia, Fixed b_dia, Bool low_res);
void mesh_new_box(GF_Mesh *mesh, SFVec3f size);
void mesh_new_cylinder(GF_Mesh *mesh, Fixed height, Fixed radius, Bool bottom, Bool side, Bool top, Bool low_res);
void mesh_new_cone(GF_Mesh *mesh, Fixed height, Fixed radius, Bool bottom, Bool side, Bool low_res);
typedef struct
{
Fixed min_phi;
Fixed max_phi;
Fixed min_theta;
Fixed max_theta;
} GF_MeshSphereAngles;
void mesh_new_sphere(GF_Mesh *mesh, Fixed radius, Bool low_res, GF_MeshSphereAngles *angles);
void mesh_new_ils(GF_Mesh *mesh, GF_Node *__coord, MFInt32 *coordIndex, GF_Node *__color, MFInt32 *colorIndex, Bool colorPerVertex, Bool do_close);
void mesh_new_ifs2d(GF_Mesh *mesh, GF_Node *ifs2d);
void mesh_new_ifs(GF_Mesh *mesh, GF_Node *ifs);
void mesh_new_ps(GF_Mesh *mesh, GF_Node *__coord, GF_Node *__color);
void mesh_new_elevation_grid(GF_Mesh *mesh, GF_Node *eg);
void mesh_new_extrusion(GF_Mesh *mesh, GF_Node *ext);
void mesh_from_path(GF_Mesh *mesh, GF_Path *path);
void mesh_get_outline(GF_Mesh *mesh, GF_Path *path);
void mesh_extrude_path(GF_Mesh *mesh, GF_Path *path, MFVec3f *thespine, Fixed creaseAngle, Bool begin_cap, Bool end_cap, MFRotation *spine_ori, MFVec2f *spine_scale, Bool tx_along_spine);
void mesh_extrude_path_ext(GF_Mesh *mesh, GF_Path *path, MFVec3f *thespine, Fixed creaseAngle, Fixed min_cx, Fixed min_cy, Fixed width_cx, Fixed width_cy, Bool begin_cap, Bool end_cap, MFRotation *spine_ori, MFVec2f *spine_scale, Bool tx_along_spine);
Bool gf_mesh_intersect_ray(GF_Mesh *mesh, GF_Ray *r, SFVec3f *outPoint, SFVec3f *outNormal, SFVec2f *outTexCoords);
Bool gf_mesh_closest_face(GF_Mesh *mesh, SFVec3f pos, Fixed min_dist, SFVec3f *outPoint);
typedef struct __AABBNode
{
SFVec3f min, max;
IDX_TYPE *indices;
u32 nb_idx;
struct __AABBNode *pos, *neg;
} AABBNode;
enum
{
AABB_NONE,
AABB_LONGEST,
AABB_BALANCED,
AABB_BEST_AXIS,
AABB_SPLATTER,
AABB_FIFTY,
};
void gf_mesh_build_aabbtree(GF_Mesh *mesh);
void TesselateFaceMesh(GF_Mesh *mesh, GF_Mesh *face);
#ifdef GPAC_HAS_GLU
void gf_mesh_tesselate_path(GF_Mesh *mesh, GF_Path *path, u32 outline_style);
void TesselateFaceMeshComplex(GF_Mesh *dest, GF_Mesh *orig, u32 nbFaces, u32 *ptsPerFaces);
#endif
#endif