/*
* GPAC - Multimedia Framework C SDK
*
* Authors: Jean Le Feuvre
* Copyright (c) Telecom ParisTech 2000-2012
* All rights reserved
*
* This file is part of GPAC / Scene Compositor sub-project
*
* GPAC is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* GPAC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _GF_MESH_H_
#define _GF_MESH_H_
#include <gpac/scenegraph_vrml.h>
#include <gpac/path2d.h>
#include <gpac/mediaobject.h>
/*by default we store each color on 32 bit rather than 4 floats (128 bits)*/
//#define MESH_USE_SFCOLOR
#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
/*by default we store normals as signed bytes rather than floats*/
//#define MESH_USE_FIXED_NORMAL
#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
{
/*position*/
SFVec3f pos;
/*texture coordinates*/
SFVec2f texcoords;
/*normal*/
#ifdef MESH_USE_FIXED_NORMAL
SFVec3f normal;
#else
SFVec3f_bytes normal;
#endif
/*color if used by mesh object*/
#ifdef MESH_USE_SFCOLOR
SFColorRGBA color;
#else
u32 color;
#endif
} GF_Vertex;
/*memory offset in bytes from start of vertex to texcoords = 3 * 4bytes*/
#define MESH_TEX_OFFSET 12
/*memory offset in bytes from start of vertex to normal = 5 * 4bytes*/
#define MESH_NORMAL_OFFSET 20
/*memory offset in bytes from start of vertex to color - platform dependent*/
#ifdef MESH_USE_FIXED_NORMAL
/*3+2+3 * 4*/
#define MESH_COLOR_OFFSET 32
#else
/*3+2 * 4 + 4 (3 + 1 byte alignment)*/
#define MESH_COLOR_OFFSET 24
#endif
/*mesh type used*/
enum
{
/*default: triangles described by indices (nb triangles = nb indices / 3) */
MESH_TRIANGLES = 0,
/*point set: indices is meaningless*/
MESH_POINTSET,
/*line set: lines described by indices (nb lines = nb indices / 2) */
MESH_LINESET,
};
/*mesh flags*/
enum
{
/*vertex.color is used*/
MESH_HAS_COLOR = 1,
/*mesh is 2D: normal should be ignored and a global normal set to 0 0 1*/
MESH_IS_2D = 1<<1,
/*mesh has no texture coords - disable texturing*/
MESH_NO_TEXTURE = 1<<2,
/*mesh faces are clockwise*/
MESH_IS_CW = 1<<3,
/*mesh is solid (back face culling + 2 side lighting)*/
MESH_IS_SOLID = 1<<4,
/*mesh has smoothed normals*/
MESH_IS_SMOOTHED = 1<<5,
/*vertex.color is used with alpha channel*/
MESH_HAS_ALPHA = 1<<6,
};
/*indexes as used in glDrawElements - note that integer type is not allowed with oglES*/
#if defined(GPAC_USE_GLES1X) || defined(GPAC_USE_GLES2)
#define IDX_TYPE u16
#else
#define IDX_TYPE u32
#endif
/*mesh object used by all 2D/3D primitives. */
typedef struct __gf_mesh
{
/*vertex list*/
u32 v_count, v_alloc;
GF_Vertex *vertices;
/*triangle indexes*/
u32 i_count, i_alloc;
IDX_TYPE *indices;
/*one of the above type*/
u32 mesh_type;
/*one of the above flags*/
u32 flags;
/*bounds info: bounding box and bounding sphere radius*/
GF_BBox bounds;
/*aabb tree of the mesh if any*/
struct __AABBNode *aabb_root;
/*triangle indexes used in AABB tree - order may be different than the one in mesh->indices*/
IDX_TYPE *aabb_indices;
// u32 aabb_nb_index;
u32 vbo;
u32 vbo_idx;
Bool vbo_dirty, vbo_dynamic;
} GF_Mesh;
GF_Mesh *new_mesh();
void mesh_free(GF_Mesh *mesh);
/*reset mesh*/
void mesh_reset(GF_Mesh *mesh);
/*recompute mesh bounds*/
void mesh_update_bounds(GF_Mesh *mesh);
/*adds new vertex*/
void mesh_set_vertex_vx(GF_Mesh *mesh, GF_Vertex *vx);
/*adds new vertex (exported for tesselator only)*/
void mesh_set_vertex(GF_Mesh *mesh, Fixed x, Fixed y, Fixed z, Fixed nx, Fixed ny, Fixed nz, Fixed u, Fixed v);
/*adds an index (exported for tesselator only)*/
void mesh_set_index(GF_Mesh *mesh, u32 idx);
/*adds an point & associated color, normal set to NULL*/
void mesh_set_point(GF_Mesh *mesh, Fixed x, Fixed y, Fixed z, SFColorRGBA col);
/*adds an index (exported for tesselator only)*/
void mesh_set_triangle(GF_Mesh *mesh, u32 id1, u32 id2, u32 id3);
/*make dest mesh the clone of orig*/
void mesh_clone(GF_Mesh *dest, GF_Mesh *orig);
/*recompute all normals*/
void mesh_recompute_normals(GF_Mesh *mesh);
/*generate texture coordinate - ONLY LOCAL MODES SUPPORTED FOR NOW*/
void mesh_generate_tex_coords(GF_Mesh *mesh, GF_Node *__texCoords);
/*inserts a box (lines only) of size 1.0 1.0 1.0*/
void mesh_new_unit_bbox(GF_Mesh *mesh);
/*insert base primitives - low res indicates less subdivision steps for circles (cone, cylinder, ellipse, sphere)*/
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;
/*create a new sphere of the given radius. If angles is set, mesh is a partial sphere but tx coords still range from 0,0 to 1,1*/
void mesh_new_sphere(GF_Mesh *mesh, Fixed radius, Bool low_res, GF_MeshSphereAngles *angles);
/*inserts ILS/ILS2D and IFS2D outline when not filled*/
void mesh_new_ils(GF_Mesh *mesh, GF_Node *__coord, MFInt32 *coordIndex, GF_Node *__color, MFInt32 *colorIndex, Bool colorPerVertex, Bool do_close);
/*inserts IFS2D*/
void mesh_new_ifs2d(GF_Mesh *mesh, GF_Node *ifs2d);
/*inserts IFS*/
void mesh_new_ifs(GF_Mesh *mesh, GF_Node *ifs);
/*inserts PS/PS2D*/
void mesh_new_ps(GF_Mesh *mesh, GF_Node *__coord, GF_Node *__color);
/*inserts ElevationGrid*/
void mesh_new_elevation_grid(GF_Mesh *mesh, GF_Node *eg);
/*inserts Extrusion*/
void mesh_new_extrusion(GF_Mesh *mesh, GF_Node *ext);
/*builds mesh from path, performing tesselation if desired*/
void mesh_from_path(GF_Mesh *mesh, GF_Path *path);
/*builds mesh for outline of the given path*/
void mesh_get_outline(GF_Mesh *mesh, GF_Path *path);
/*constructs an extrusion from given path - mesh is reseted, txcoords computed from path bounds
@thespine: spine line
@creaseAngle: creaseAngle for normal smoothing, 0 for no smoothing
begin_cap, end_cap: indicates whether start/end faces shall be added
@spine_ori: orientation at spine points
@spine_scale: scale at spine points
@tx_along_spine: if set, texture coords are generated so that the texture is mapped on the side,
otherwise the same txcoords are used all along the extrusion spine
*/
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);
/*special extension of the above: APPENDS an extrusion from given path - mesh is NOT reseted, txcoords are computed based on min_cx, min_cy, width_cx, width_cy*/
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);
/*returns 1 if intersection and set outPoint to closest intersection, 0 otherwise*/
Bool gf_mesh_intersect_ray(GF_Mesh *mesh, GF_Ray *r, SFVec3f *outPoint, SFVec3f *outNormal, SFVec2f *outTexCoords);
/*returns 1 if any face is less than min_dist from pos, with collision point on closest face (towards pos)*/
Bool gf_mesh_closest_face(GF_Mesh *mesh, SFVec3f pos, Fixed min_dist, SFVec3f *outPoint);
/*AABB tree node (exported for bounds drawing)*/
typedef struct __AABBNode
{
/*bbox*/
SFVec3f min, max;
/*sorted indices in mesh indices list*/
IDX_TYPE *indices;
/*nb triangles*/
u32 nb_idx;
/*children nodes, NULL if leaf*/
struct __AABBNode *pos, *neg;
} AABBNode;
/*tree construction modes*/
enum
{
/*AABB tree is not used*/
AABB_NONE,
/*longest box axis is used to divide an AABB node*/
AABB_LONGEST,
/*keep tree well-balanced*/
AABB_BALANCED,
/*best axis is use: test largest, then middle, then smallest axis*/
AABB_BEST_AXIS,
/*use variance to pick axis*/
AABB_SPLATTER,
/*fifty/fifty point split*/
AABB_FIFTY,
};
void gf_mesh_build_aabbtree(GF_Mesh *mesh);
/*
* tesselation functions
*/
/*appends given face (and tesselate if needed) to the mesh. Only vertices are used in the face
indices are ignored.
partially implemented on ogl-ES*/
void TesselateFaceMesh(GF_Mesh *mesh, GF_Mesh *face);
#ifdef GPAC_HAS_GLU
/*converts 2D path into a polygon - these are only partially implemented when using oglES
for_outline:
0, regular odd/even windining rule with texCoords
1, zero-non-zero windining rule without texCoords
2, zero-non-zero windining rule with texCoords
*/
void gf_mesh_tesselate_path(GF_Mesh *mesh, GF_Path *path, u32 outline_style);
/*appends given face (and tesselate if needed) to the mesh. Only vertices are used in the face
indices are ignored.
Same as TesselateFaceMesh + faces info to determine where are the polygons in the face - used by extruder only
*/
void TesselateFaceMeshComplex(GF_Mesh *dest, GF_Mesh *orig, u32 nbFaces, u32 *ptsPerFaces);
#endif
#endif /*_GF_MESH_H_*/