LCOV - code coverage report
Current view: top level - compositor - mesh_tesselate.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 159 208 76.4 %
Date: 2021-04-29 23:48:07 Functions: 8 10 80.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : #include <gpac/internal/mesh.h>
      28             : #include <gpac/color.h>
      29             : 
      30             : #ifndef GPAC_DISABLE_3D
      31             : 
      32             : /*for GPAC_HAS_GLU*/
      33             : #include "gl_inc.h"
      34             : 
      35             : #ifndef CALLBACK
      36             : #define CALLBACK
      37             : #endif
      38             : 
      39             : 
      40             : #ifdef GPAC_HAS_GLU
      41             : 
      42             : #ifdef GPAC_CONFIG_IOS
      43             : #define GLdouble GLfloat
      44             : #endif
      45             : 
      46             : 
      47             : typedef struct
      48             : {
      49             :         /*for tesselation*/
      50             :         GLUtesselator *tess_obj;
      51             :         GF_Mesh *mesh;
      52             : 
      53             :         /*vertex indices: we cannot use a static array because reallocating the array will likely change memory
      54             :         address of indices, hence break triangulator*/
      55             :         GF_List *vertex_index;
      56             : } MeshTess;
      57             : 
      58         829 : static void CALLBACK mesh_tess_begin(GLenum which) {
      59             :         assert(which==GL_TRIANGLES);
      60         829 : }
      61         829 : static void CALLBACK mesh_tess_end(void) {
      62         829 : }
      63           0 : static void CALLBACK mesh_tess_error(GLenum error_code)
      64             : {
      65           0 :         if (error_code)
      66           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Mesh] Tesselate error %s\n", gluErrorString(error_code)));
      67           0 : }
      68             : 
      69             : /*only needed to force GL_TRIANGLES*/
      70       69558 : static void CALLBACK mesh_tess_edgeflag(GLenum flag) { }
      71             : 
      72      173142 : static void CALLBACK mesh_tess_vertex(void *vertexData, void *user_data)
      73             : {
      74             :         MeshTess *tess = (MeshTess *) user_data;
      75      173142 :         mesh_set_index(tess->mesh, *(u32*)vertexData);
      76      173142 : }
      77             : 
      78        3499 : static void CALLBACK mesh_tess_combine(GLdouble coords[3], void* vertex_data[4], GLfloat weight[4], void** out_data, void *user_data)
      79             : {
      80             :         u32 i, idx;
      81             :         u32 *new_idx;
      82             :         SFVec3f n;
      83             :         SFVec2f tx;
      84             :         SFColor col;
      85             : 
      86             :         MeshTess *tess = (MeshTess *) user_data;
      87             : 
      88             :         col.red = col.green = col.blue = 0;
      89        3499 :         if (tess->mesh->flags & MESH_HAS_COLOR) {
      90             :                 for (i=0; i<4; i++) {
      91             :                         if (weight[i]) {
      92             :                                 SFColorRGBA rgba;
      93             :                                 Fixed _weight = FLT2FIX(weight[i]);
      94             :                                 idx = * (u32 *) vertex_data[i];
      95             : 
      96             :                                 MESH_GET_COLOR(rgba, tess->mesh->vertices[idx]);
      97             : 
      98             :                                 col.red += gf_mulfix(_weight, rgba.red);
      99             :                                 col.green += gf_mulfix(_weight, rgba.green);
     100             :                                 col.blue += gf_mulfix(_weight, rgba.blue);
     101             :                         }
     102             :                 }
     103             :         }
     104             : 
     105             :         n.x = n.y = n.z = 0;
     106        3499 :         if (tess->mesh->flags & MESH_IS_2D) {
     107             :                 n.z = FIX_ONE;
     108             :         } else {
     109           4 :                 for (i=0; i<4; i++) {
     110           4 :                         if (weight[i]) {
     111             :                                 Fixed _weight = FLT2FIX(weight[i]);
     112             :                                 SFVec3f _n;
     113           2 :                                 idx = * (u32 *) vertex_data[i];
     114           2 :                                 MESH_GET_NORMAL(_n, tess->mesh->vertices[idx]);
     115           2 :                                 n.x += gf_mulfix(_weight, _n.x);
     116           2 :                                 n.y += gf_mulfix(_weight, _n.y);
     117           2 :                                 n.z += gf_mulfix(_weight, _n.z);
     118             :                         }
     119             :                 }
     120             :         }
     121             :         tx.x = tx.y = 0;
     122        3499 :         if (!(tess->mesh->flags & MESH_NO_TEXTURE)) {
     123        5836 :                 for (i=0; i<4; i++) {
     124        5836 :                         if (weight[i]) {
     125             :                                 Fixed _weight = FLT2FIX(weight[i]);
     126        4046 :                                 idx = * (u32 *) vertex_data[i];
     127        4046 :                                 tx.x += gf_mulfix(_weight, tess->mesh->vertices[idx].texcoords.x);
     128        4046 :                                 tx.y += gf_mulfix(_weight, tess->mesh->vertices[idx].texcoords.y);
     129             :                         }
     130             :                 }
     131             :         }
     132             : 
     133        3499 :         new_idx = (u32 *) gf_malloc(sizeof(u32));
     134        3499 :         gf_list_add(tess->vertex_index, new_idx);
     135        3499 :         *new_idx = tess->mesh->v_count;
     136        3499 :         mesh_set_vertex(tess->mesh, FLT2FIX( (Float) coords[0]), FLT2FIX( (Float) coords[1]), FLT2FIX( (Float) coords[2]), n.x, n.y, n.z, tx.x, tx.y);
     137        3499 :         *out_data = new_idx;
     138        3499 : }
     139             : 
     140         820 : void gf_mesh_tesselate_path(GF_Mesh *mesh, GF_Path *path, u32 outline_style)
     141             : {
     142             :         u32 i, j, cur, nb_pts;
     143             :         u32 *idx;
     144             :         Fixed w, h, min_y;
     145             :         GF_Rect rc;
     146             :         GLdouble vertex[3];
     147             :         MeshTess *tess;
     148         820 :         if (!mesh || !path || !path->n_contours) return;
     149         820 :         tess = gf_malloc(sizeof(MeshTess));
     150         820 :         if (!tess) return;
     151             :         memset(tess, 0, sizeof(MeshTess));
     152         820 :         tess->tess_obj = gluNewTess();
     153         820 :         if (!tess->tess_obj) {
     154           0 :                 gf_free(tess);
     155           0 :                 return;
     156             :         }
     157         820 :         tess->vertex_index = gf_list_new();
     158             : 
     159         820 :         mesh_reset(mesh);
     160         820 :         mesh->flags |= MESH_IS_2D;
     161         820 :         if (outline_style==1) mesh->flags |= MESH_NO_TEXTURE;
     162             : 
     163         820 :         tess->mesh = mesh;
     164         820 :         gluTessCallback(tess->tess_obj, GLU_TESS_VERTEX_DATA, (void (CALLBACK*)()) &mesh_tess_vertex);
     165         820 :         gluTessCallback(tess->tess_obj, GLU_TESS_BEGIN, (void (CALLBACK*)()) &mesh_tess_begin);
     166         820 :         gluTessCallback(tess->tess_obj, GLU_TESS_END, (void (CALLBACK*)()) &mesh_tess_end);
     167         820 :         gluTessCallback(tess->tess_obj, GLU_TESS_COMBINE_DATA, (void (CALLBACK*)()) &mesh_tess_combine);
     168         820 :         gluTessCallback(tess->tess_obj, GLU_TESS_ERROR, (void (CALLBACK*)()) &mesh_tess_error);
     169         820 :         gluTessCallback(tess->tess_obj, GLU_EDGE_FLAG,(void (CALLBACK*)()) &mesh_tess_edgeflag);
     170             : 
     171         820 :         if (path->flags & GF_PATH_FILL_ZERO_NONZERO) gluTessProperty(tess->tess_obj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
     172             : 
     173         820 :         gluTessBeginPolygon(tess->tess_obj, tess);
     174         820 :         gluTessNormal(tess->tess_obj, 0, 0, 1);
     175             : 
     176         820 :         gf_path_flatten(path);
     177         820 :         gf_path_get_bounds(path, &rc);
     178             : 
     179         820 :         w = rc.width;
     180         820 :         h = rc.height;
     181         820 :         min_y = rc.y - h;
     182         820 :         vertex[2] = 0;
     183             :         /*since we're not sure whether subpaths overlaps or not, tesselate everything*/
     184             :         cur = 0;
     185        2064 :         for (i=0; i<path->n_contours; i++) {
     186        1244 :                 nb_pts = 1+path->contours[i]-cur;
     187             : 
     188        1244 :                 gluTessBeginContour(tess->tess_obj);
     189             : 
     190       47282 :                 for (j=0; j<nb_pts; j++) {
     191       46038 :                         GF_Point2D pt = path->points[cur+j];
     192       46038 :                         Fixed u = gf_divfix(pt.x - rc.x, w);
     193       46038 :                         Fixed v = gf_divfix(pt.y - min_y, h);
     194             : 
     195       46038 :                         idx = (u32 *) gf_malloc(sizeof(u32));
     196       46038 :                         *idx = mesh->v_count;
     197       46038 :                         gf_list_add(tess->vertex_index, idx);
     198       46038 :                         mesh_set_vertex(mesh, pt.x, pt.y, 0, 0, 0, FIX_ONE, u, v);
     199             : 
     200       46038 :                         vertex[0] = (Double) FIX2FLT(pt.x);
     201       46038 :                         vertex[1] = (Double) FIX2FLT(pt.y);
     202       46038 :                         gluTessVertex(tess->tess_obj, vertex, idx);
     203             :                 }
     204        1244 :                 gluTessEndContour(tess->tess_obj);
     205        1244 :                 cur+=nb_pts;
     206             :         }
     207             : 
     208         820 :         gluTessEndPolygon(tess->tess_obj);
     209             : 
     210         820 :         gluDeleteTess(tess->tess_obj);
     211             : 
     212       51176 :         while (gf_list_count(tess->vertex_index)) {
     213       49536 :                 u32 *idx = gf_list_get(tess->vertex_index, 0);
     214       49536 :                 gf_list_rem(tess->vertex_index, 0);
     215       49536 :                 gf_free(idx);
     216             :         }
     217         820 :         gf_list_del(tess->vertex_index);
     218         820 :         gf_free(tess);
     219             : 
     220         820 :         mesh->bounds.min_edge.x = rc.x;
     221         820 :         mesh->bounds.min_edge.y = rc.y-rc.height;
     222         820 :         mesh->bounds.max_edge.x = rc.x+rc.width;
     223         820 :         mesh->bounds.max_edge.y = rc.y;
     224         820 :         mesh->bounds.min_edge.z = mesh->bounds.max_edge.z = 0;
     225         820 :         gf_bbox_refresh(&mesh->bounds);
     226             : 
     227             : #ifdef GPAC_ENABLE_COVERAGE
     228         820 :         if (gf_sys_is_cov_mode()) {
     229             :                 mesh_tess_error(0);
     230             :         }
     231             : #endif
     232             : 
     233             : }
     234             : 
     235             : #else
     236             : 
     237             : void gf_mesh_tesselate_path(GF_Mesh *mesh, GF_Path *path, u32 outline_style) { }
     238             : 
     239             : #endif
     240             : 
     241             : 
     242             : 
     243             : #define GetPoint2D(pt, apt) \
     244             :         if (!direction) { pt.x = - apt.pos.z; pt.y = apt.pos.y; }       \
     245             :         else if (direction==1) { pt.x = apt.pos.z; pt.y = apt.pos.x; }  \
     246             :         else if (direction==2) { pt.x = apt.pos.x; pt.y = apt.pos.y; } \
     247             :  
     248             : 
     249             : #define ConvCompare(delta)      \
     250             :     ( (delta.x > 0) ? -1 :           \
     251             :       (delta.x < 0) ?        1 :             \
     252             :       (delta.y > 0) ? -1 :           \
     253             :       (delta.y < 0) ?        1 :     \
     254             :       0 )
     255             : 
     256             : #define ConvGetPointDelta(delta, pprev, pcur )                  \
     257             :     /* Given a previous point 'pprev', read a new point into 'pcur' */  \
     258             :     /* and return delta in 'delta'.                                 */  \
     259             :     GetPoint2D(pcur, pts[iread]); iread++;                      \
     260             :     delta.x = pcur.x - pprev.x;                                 \
     261             :     delta.y = pcur.y - pprev.y;                                 \
     262             :  
     263             : #define ConvCross(p, q) gf_mulfix(p.x,q.y) - gf_mulfix(p.y,q.x);
     264             : 
     265             : #define ConvCheckTriple                                         \
     266             :     if ( (thisDir = ConvCompare(dcur)) == -curDir ) {                   \
     267             :           ++dirChanges;                                                 \
     268             :           /* if ( dirChanges > 2 ) return NotConvex;              */ \
     269             :     }                                                                   \
     270             :     curDir = thisDir;                                                   \
     271             :     cross = ConvCross(dprev, dcur);                                     \
     272             :     if ( cross > 0 ) { \
     273             :                 if ( angleSign == -1 ) return GF_POLYGON_COMPLEX;               \
     274             :                 angleSign = 1;                                  \
     275             :         }                                                       \
     276             :     else if (cross < 0) {    \
     277             :                 if (angleSign == 1) return GF_POLYGON_COMPLEX;          \
     278             :                 angleSign = -1;                         \
     279             :         }                                               \
     280             :     pSecond = pThird;           \
     281             :     dprev.x = dcur.x;           \
     282             :     dprev.y = dcur.y;                                                   \
     283             :  
     284       13872 : u32 polygon_check_convexity(GF_Vertex *pts, u32 len, u32 direction)
     285             : {
     286             :         s32 curDir, thisDir = 0, dirChanges = 0, angleSign = 0;
     287             :         u32 iread;
     288             :         Fixed cross;
     289             :         GF_Point2D pSecond, pThird, pSaveSecond;
     290             :         GF_Point2D dprev, dcur;
     291             : 
     292       13872 :         if (len<3) return GF_POLYGON_CONVEX_LINE;
     293             : 
     294             :         pSecond.x = pSecond.y = 0;
     295             :         pThird = pSecond;
     296             : 
     297       13872 :         GetPoint2D(pThird, pts[0]);
     298             :         iread = 1;
     299       13872 :         ConvGetPointDelta(dprev, pThird, pSecond);
     300             :         pSaveSecond = pSecond;
     301             :         /*initial direction */
     302       13872 :         curDir = ConvCompare(dprev);
     303       27995 :         while ( iread < len) {
     304             :                 /* Get different point, break if no more points */
     305       14132 :                 ConvGetPointDelta(dcur, pSecond, pThird );
     306       14132 :                 if ( (dcur.x == 0) && (dcur.y == 0) ) continue;
     307             :                 /* Check current three points */
     308       14132 :                 ConvCheckTriple;
     309             :         }
     310             : 
     311             :         /* Must check for direction changes from last vertex back to first */
     312             :         /* Prepare for 'ConvexCheckTriple' */
     313       13863 :         GetPoint2D(pThird, pts[0]);
     314       13863 :         dcur.x = pThird.x - pSecond.x;
     315       13863 :         dcur.y = pThird.y - pSecond.y;
     316       13863 :         if ( ConvCompare(dcur) ) {
     317       13856 :                 ConvCheckTriple;
     318             :         }
     319             :         /* and check for direction changes back to second vertex */
     320       13863 :         dcur.x = pSaveSecond.x - pSecond.x;
     321       13863 :         dcur.y = pSaveSecond.y - pSecond.y;
     322             :         /* Don't care about 'pThird' now */
     323       13863 :         ConvCheckTriple;
     324             : 
     325             :         /* Decide on polygon type given accumulated status */
     326       13863 :         if ( dirChanges > 2 ) return GF_POLYGON_COMPLEX;
     327       13863 :         if ( angleSign > 0 ) return GF_POLYGON_CONVEX_CCW;
     328        5290 :         if ( angleSign < 0 ) return GF_POLYGON_CONVEX_CW;
     329           0 :         return GF_POLYGON_CONVEX_LINE;
     330             : }
     331             : 
     332             : 
     333       13872 : void TesselateFaceMesh(GF_Mesh *dest, GF_Mesh *orig)
     334             : {
     335             :         u32 poly_type, i, nb_pts, init_idx, direction;
     336             :         Fixed max_nor_coord, c;
     337             :         SFVec3f nor;
     338             : #ifdef GPAC_HAS_GLU
     339             :         u32 *idx;
     340             :         GLdouble vertex[3];
     341             :         MeshTess *tess;
     342             : #endif
     343             : 
     344             :         /*get normal*/
     345       13872 :         if (orig->flags & MESH_IS_2D) {
     346          32 :                 nor.x = nor.y = 0;
     347          32 :                 nor.z = FIX_ONE;
     348             :         } else {
     349       13840 :                 MESH_GET_NORMAL(nor, orig->vertices[0]);
     350             :         }
     351             : 
     352             :         /*select projection direction*/
     353             :         direction = 0;
     354       13872 :         max_nor_coord = ABS(nor.x);
     355       13872 :         c = ABS(nor.y);
     356       13872 :         if (c>max_nor_coord) {
     357             :                 direction = 1;
     358             :                 max_nor_coord = c;
     359             :         }
     360       13872 :         c = ABS(nor.z);
     361       13872 :         if (c>max_nor_coord) direction = 2;
     362             : 
     363             :         /*if this is a convex polygone don't triangulate*/
     364       13872 :         poly_type = polygon_check_convexity(orig->vertices, orig->v_count, direction);
     365       13872 :         switch (poly_type) {
     366       13863 :         case GF_POLYGON_CONVEX_LINE:
     367             :         /*do NOT try to make face CCW otherwise we loose front/back faces...*/
     368             :         case GF_POLYGON_CONVEX_CW:
     369             :         case GF_POLYGON_CONVEX_CCW:
     370       13863 :                 init_idx = dest->v_count;
     371             :                 nb_pts = orig->v_count;
     372       55682 :                 for (i=0; i<nb_pts; i++) {
     373       41819 :                         mesh_set_vertex_vx(dest, &orig->vertices[i]);
     374             :                 }
     375       13863 :                 nb_pts -= 1;
     376       27956 :                 for (i=1; i<nb_pts; i++) {
     377       14093 :                         mesh_set_triangle(dest, init_idx, init_idx + i, init_idx + i+1);
     378             :                 }
     379       13863 :                 return;
     380             :         default:
     381             :                 break;
     382             :         }
     383             : 
     384             : #ifdef GPAC_HAS_GLU
     385             : 
     386             :         /*tesselate it*/
     387           9 :         tess = gf_malloc(sizeof(MeshTess));
     388           9 :         if (!tess) return;
     389             :         memset(tess, 0, sizeof(MeshTess));
     390           9 :         tess->tess_obj = gluNewTess();
     391           9 :         if (!tess->tess_obj) {
     392           0 :                 gf_free(tess);
     393           0 :                 return;
     394             :         }
     395           9 :         tess->vertex_index = gf_list_new();
     396             : 
     397           9 :         tess->mesh = dest;
     398           9 :         gluTessCallback(tess->tess_obj, GLU_TESS_VERTEX_DATA, (void (CALLBACK*)()) &mesh_tess_vertex);
     399           9 :         gluTessCallback(tess->tess_obj, GLU_TESS_BEGIN, (void (CALLBACK*)()) &mesh_tess_begin);
     400           9 :         gluTessCallback(tess->tess_obj, GLU_TESS_END, (void (CALLBACK*)()) &mesh_tess_end);
     401           9 :         gluTessCallback(tess->tess_obj, GLU_TESS_COMBINE_DATA, (void (CALLBACK*)()) &mesh_tess_combine);
     402           9 :         gluTessCallback(tess->tess_obj, GLU_TESS_ERROR, (void (CALLBACK*)()) &mesh_tess_error);
     403           9 :         gluTessCallback(tess->tess_obj, GLU_EDGE_FLAG,(void (CALLBACK*)()) &mesh_tess_edgeflag);
     404             : 
     405           9 :         gluTessBeginPolygon(tess->tess_obj, tess);
     406           9 :         gluTessBeginContour(tess->tess_obj);
     407             : 
     408             : 
     409          94 :         for (i=0; i<orig->v_count; i++) {
     410          85 :                 idx = (u32 *) gf_malloc(sizeof(u32));
     411          85 :                 *idx = dest->v_count;
     412          85 :                 gf_list_add(tess->vertex_index, idx);
     413          85 :                 mesh_set_vertex_vx(dest, &orig->vertices[i]);
     414             : 
     415          85 :                 vertex[0] = (Double) FIX2FLT(orig->vertices[i].pos.x);
     416          85 :                 vertex[1] = (Double) FIX2FLT(orig->vertices[i].pos.y);
     417          85 :                 vertex[2] = (Double) FIX2FLT(orig->vertices[i].pos.z);
     418          85 :                 gluTessVertex(tess->tess_obj, vertex, idx);
     419             :         }
     420             : 
     421           9 :         gluTessEndContour(tess->tess_obj);
     422           9 :         gluTessEndPolygon(tess->tess_obj);
     423           9 :         gluDeleteTess(tess->tess_obj);
     424             : 
     425         104 :         while (gf_list_count(tess->vertex_index)) {
     426          86 :                 u32 *idx = gf_list_get(tess->vertex_index, 0);
     427          86 :                 gf_list_rem(tess->vertex_index, 0);
     428          86 :                 gf_free(idx);
     429             :         }
     430           9 :         gf_list_del(tess->vertex_index);
     431           9 :         gf_free(tess);
     432             : #endif
     433             : }
     434             : 
     435             : 
     436             : 
     437             : #ifdef GPAC_HAS_GLU
     438             : 
     439           0 : void TesselateFaceMeshComplex(GF_Mesh *dest, GF_Mesh *orig, u32 nbFaces, u32 *ptsPerFaces)
     440             : {
     441             :         u32 i, cur_pt_faces, cur_face;
     442             :         u32 *idx;
     443             :         GLdouble vertex[3];
     444             :         MeshTess *tess;
     445             : 
     446             :         /*tesselate it*/
     447           0 :         tess = gf_malloc(sizeof(MeshTess));
     448           0 :         if (!tess) return;
     449             :         memset(tess, 0, sizeof(MeshTess));
     450           0 :         tess->tess_obj = gluNewTess();
     451           0 :         if (!tess->tess_obj) {
     452           0 :                 gf_free(tess);
     453           0 :                 return;
     454             :         }
     455           0 :         tess->vertex_index = gf_list_new();
     456             : 
     457           0 :         tess->mesh = dest;
     458           0 :         gluTessCallback(tess->tess_obj, GLU_TESS_VERTEX_DATA, (void (CALLBACK*)()) &mesh_tess_vertex);
     459           0 :         gluTessCallback(tess->tess_obj, GLU_TESS_BEGIN, (void (CALLBACK*)()) &mesh_tess_begin);
     460           0 :         gluTessCallback(tess->tess_obj, GLU_TESS_END, (void (CALLBACK*)()) &mesh_tess_end);
     461           0 :         gluTessCallback(tess->tess_obj, GLU_TESS_COMBINE_DATA, (void (CALLBACK*)()) &mesh_tess_combine);
     462           0 :         gluTessCallback(tess->tess_obj, GLU_TESS_ERROR, (void (CALLBACK*)()) &mesh_tess_error);
     463           0 :         gluTessCallback(tess->tess_obj, GLU_EDGE_FLAG,(void (CALLBACK*)()) &mesh_tess_edgeflag);
     464             : 
     465           0 :         gluTessBeginPolygon(tess->tess_obj, tess);
     466           0 :         gluTessBeginContour(tess->tess_obj);
     467             : 
     468             : 
     469             :         cur_pt_faces = 0;
     470             :         cur_face = 0;
     471           0 :         for (i=0; i<orig->v_count; i++) {
     472             : 
     473           0 :                 if (i>= cur_pt_faces + ptsPerFaces[cur_face]) {
     474             :                         cur_pt_faces += ptsPerFaces[cur_face];
     475           0 :                         cur_face++;
     476           0 :                         if (cur_face>=nbFaces) break;
     477           0 :                         gluTessEndContour(tess->tess_obj);
     478           0 :                         gluTessBeginContour(tess->tess_obj);
     479             :                 }
     480             : 
     481           0 :                 idx = (u32 *) gf_malloc(sizeof(u32));
     482           0 :                 *idx = dest->v_count;
     483           0 :                 gf_list_add(tess->vertex_index, idx);
     484           0 :                 mesh_set_vertex_vx(dest, &orig->vertices[i]);
     485             : 
     486           0 :                 vertex[0] = (Double) FIX2FLT(orig->vertices[i].pos.x);
     487           0 :                 vertex[1] = (Double) FIX2FLT(orig->vertices[i].pos.y);
     488           0 :                 vertex[2] = (Double) FIX2FLT(orig->vertices[i].pos.z);
     489           0 :                 gluTessVertex(tess->tess_obj, vertex, idx);
     490             :         }
     491             : 
     492           0 :         gluTessEndContour(tess->tess_obj);
     493           0 :         gluTessEndPolygon(tess->tess_obj);
     494           0 :         gluDeleteTess(tess->tess_obj);
     495             : 
     496           0 :         while (gf_list_count(tess->vertex_index)) {
     497           0 :                 u32 *idx = gf_list_get(tess->vertex_index, 0);
     498           0 :                 gf_list_rem(tess->vertex_index, 0);
     499           0 :                 gf_free(idx);
     500             :         }
     501           0 :         gf_list_del(tess->vertex_index);
     502           0 :         gf_free(tess);
     503             : }
     504             : #endif
     505             : 
     506             : 
     507             : #endif  /*GPAC_DISABLE_3D*/

Generated by: LCOV version 1.13