Example #1
0
File: hidgl.c Project: bert/pcb-rnd
/* FIXME: JUST DRAWS THE FIRST PIECE.. TODO: SUPPORT FOR FULLPOLY POLYGONS */
void
hidgl_fill_pcb_polygon (PolygonType *poly, const BoxType *clip_box, double scale)
{
  int vertex_count = 0;
  PLINE *contour;
  struct do_hole_info info;
  int stencil_bit;

  info.scale = scale;
  global_scale = scale;

  if (poly->Clipped == NULL)
    {
      fprintf (stderr, "hidgl_fill_pcb_polygon: poly->Clipped == NULL\n");
      return;
    }

  stencil_bit = hidgl_assign_clear_stencil_bit ();
  if (!stencil_bit)
    {
      printf ("hidgl_fill_pcb_polygon: No free stencil bits, aborting polygon\n");
      return;
    }

  /* Flush out any existing geoemtry to be rendered */
  hidgl_flush_triangles (&buffer);

  /* Walk the polygon structure, counting vertices */
  /* This gives an upper bound on the amount of storage required */
  for (contour = poly->Clipped->contours;
       contour != NULL; contour = contour->next)
    vertex_count = MAX (vertex_count, contour->Count);

  info.vertices = malloc (sizeof(GLdouble) * vertex_count * 3);
  info.tobj = gluNewTess ();
  gluTessCallback(info.tobj, GLU_TESS_BEGIN,   (_GLUfuncptr)myBegin);
  gluTessCallback(info.tobj, GLU_TESS_VERTEX,  (_GLUfuncptr)myVertex);
  gluTessCallback(info.tobj, GLU_TESS_COMBINE, (_GLUfuncptr)myCombine);
  gluTessCallback(info.tobj, GLU_TESS_ERROR,   (_GLUfuncptr)myError);

  glPushAttrib (GL_STENCIL_BUFFER_BIT);                 /* Save the write mask etc.. for final restore */
  glEnable (GL_STENCIL_TEST);
  glPushAttrib (GL_STENCIL_BUFFER_BIT |                 /* Resave the stencil write-mask etc.., and */
                GL_COLOR_BUFFER_BIT);                   /* the colour buffer write mask etc.. for part way restore */
  glStencilMask (stencil_bit);                          /* Only write to our stencil bit */
  glStencilFunc (GL_ALWAYS, stencil_bit, stencil_bit);  /* Always pass stencil test, ref value is our bit */
  glColorMask (0, 0, 0, 0);                             /* Disable writting in color buffer */

  glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);           /* Stencil pass => replace stencil value */

  /* Drawing operations now set our reference bit in the stencil buffer */

  r_search (poly->Clipped->contour_tree, clip_box, NULL, do_hole, &info);
  hidgl_flush_triangles (&buffer);

  glPopAttrib ();                               /* Restore the colour and stencil buffer write-mask etc.. */

  glStencilOp (GL_KEEP, GL_KEEP, GL_INVERT);    /* This allows us to toggle the bit on any subcompositing bitplane */
                                                /* If the stencil test has passed, we know that bit is 0, so we're */
                                                /* effectively just setting it to 1. */

  glStencilFunc (GL_GEQUAL, 0, assigned_bits);  /* Pass stencil test if all assigned bits clear, */
                                                /* reference is all assigned bits so we set */
                                                /* any bits permitted by the stencil writemask */

  /* Drawing operations as masked to areas where the stencil buffer is '0' */

  /* Draw the polygon outer */
  tesselate_contour (info.tobj, poly->Clipped->contours, info.vertices, scale);
  hidgl_flush_triangles (&buffer);

  /* Unassign our stencil buffer bit */
  hidgl_return_stencil_bit (stencil_bit);

  glPopAttrib ();                               /* Restore the stencil buffer write-mask etc.. */

  gluDeleteTess (info.tobj);
  myFreeCombined ();
  free (info.vertices);
}
Example #2
0
 work(LLRegion &r) : region(r) {
     tobj = gluNewTess();
 }
Example #3
0
void init_scene(int width, int height)
{
   GLubyte* tex;

   GLUtesselator* tobj;
   GLfloat rect[4][3]={
                         {50.0f,  50.0f,  0.0f},
                         {200.0f, 50.0f,  0.0f},
                         {200.0f, 200.0f, 0.0f},
                         {50.0f,  200.0f, 0.0f}
                      };
   GLfloat tri[3][3]={
                        {75.0f,  75.0f,  0.0f},
                        {125.0f, 175.0f, 0.0f},
                        {175.0f, 75.0f,  0.0f}
                     };
   GLfloat star[5][6]={
                         {250.0f, 50.0f,  0.0f, 1.0f, 0.0f, 1.0f},
                         {325.0f, 200.0f, 0.0f, 1.0f, 1.0f, 0.0f},
                         {400.0f, 50.0f,  0.0f, 0.0f, 1.0f, 1.0f},
                         {250.0f, 150.0f, 0.0f, 1.0f, 0.0f, 0.0f},
                         {400.0f, 150.0f, 0.0f, 0.0f, 1.0f, 0.0f}
                      };
   GLfloat triangle[9][8]={
                             {450.0f, 50.0f,  0.0f, 1.0f,  0.0f,  0.0f,  0.0f,  0.0f},
                             {525.0f, 200.0f, 0.0f, 1.0f,  1.0f,  1.0f,  0.5f,  1.0f},
                             {600.0f, 50.0f,  0.0f, 0.0f,  0.0f,  1.0f,  1.0f,  0.0f},
                             {500.0f, 50.0f,  0.0f, 0.666f, 0.000f, 0.333f, 0.333f, 0.000f},
                             {550.0f, 150.0f, 0.0f, 0.666f, 0.666f, 1.000f, 0.666f, 0.666f},
                             {500.0f, 150.0f, 0.0f, 1.000f, 0.666f, 0.666f, 0.333f, 0.666f},
                             {550.0f, 50.0f,  0.0f, 0.333f, 0.000f, 0.666f, 0.666f, 0.000f},
                             {575.0f, 100.0f, 0.0f, 0.333f, 0.333f, 1.000f, 0.825f, 0.333f},
                             {475.0f, 100.0f, 0.0f, 1.000f, 0.333f, 0.333f, 0.175f, 0.333f}
                          };

   glViewport(0, 0, (GLsizei)width, (GLsizei)height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluOrtho2D(0.0f, (GLfloat)width, 0.0f, (GLfloat)height);

   glClearColor(0.0, 0.0, 0.0, 0.0);

   /* Create new triangulator */
   tobj=gluNewTess();

   /* Set triangulator's callbacks */
   gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback);
   gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback);

   /* reset object */
   object1.sequences=0;

   /* rectangle with triangular hole inside */
   gluTessBeginPolygon(tobj, (void*)&object1);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, rect[0], rect[0]);
         gluTessVertex(tobj, rect[1], rect[1]);
         gluTessVertex(tobj, rect[2], rect[2]);
         gluTessVertex(tobj, rect[3], rect[3]);
      gluTessEndContour(tobj);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, tri[0], tri[0]);
         gluTessVertex(tobj, tri[1], tri[1]);
         gluTessVertex(tobj, tri[2], tri[2]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);

   /* Set triangulator's callbacks */
   gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexColorCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback);
   gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback);
   gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid (*)())&combineColorCallback);

   /* reset object */
   object2.sequences=0;

   /*  self-intersecting star  */
   gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
   gluTessBeginPolygon(tobj, (void*)&object2);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, star[0], star[0]);
         gluTessVertex(tobj, star[1], star[1]);
         gluTessVertex(tobj, star[2], star[2]);
         gluTessVertex(tobj, star[3], star[3]);
         gluTessVertex(tobj, star[4], star[4]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);

   /* Set triangulator's callbacks */
   gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexTexColorCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback);
   gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback);
   gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid (*)())&combineTexColorCallback);

   /* reset object */
   object3.sequences=0;

   /*  self-intersecting star  */
   gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
   gluTessBeginPolygon(tobj, (void*)&object3);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, triangle[0], triangle[0]);
         gluTessVertex(tobj, triangle[1], triangle[1]);
         gluTessVertex(tobj, triangle[2], triangle[2]);
      gluTessEndContour(tobj);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, triangle[3], triangle[3]);
         gluTessVertex(tobj, triangle[4], triangle[4]);
         gluTessVertex(tobj, triangle[5], triangle[5]);
         gluTessVertex(tobj, triangle[6], triangle[6]);
         gluTessVertex(tobj, triangle[7], triangle[7]);
         gluTessVertex(tobj, triangle[8], triangle[8]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);

   /* Destroy triangulator object */
   gluDeleteTess(tobj);

   /* enable filtering */
   glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

   tex=make_texture(256, 256);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, tex);
   free(tex);
}
Example #4
0
/* ARGSUSED4 */
static void draw_cut_style_cap_callback (int iloop,
                                  double cap[][3], 
                                  float face_color[3],
                                  gleDouble cut_vector[3],
                                  gleDouble bisect_vector[3],
                                  double norms[][3], 
                                  int frontwards)
{
   int i;
#ifdef OPENGL_10
   GLUtriangulatorObj *tobj;
   tobj = gluNewTess ();
   gluTessCallback (tobj, GLU_BEGIN, (void (CALLBACK*)()) glBegin);
   gluTessCallback (tobj, GLU_VERTEX, (void (CALLBACK*)()) glVertex3dv);
   gluTessCallback (tobj, GLU_END, (void (CALLBACK*)()) glEnd);
#endif /* OPENGL_10 */

   if (face_color != NULL) C3F (face_color);

   if (frontwards) {

      /* if lighting is on, specify the endcap normal */
      if (cut_vector != NULL) {
         /* if normal pointing in wrong direction, flip it. */
         if (cut_vector[2] < 0.0) { 
            VEC_SCALE (cut_vector, -1.0, cut_vector); 
         }
         N3F_D (cut_vector);
      }
#ifdef GL_32
      BGNPOLYGON();
      for (i=0; i<iloop; i++) {
         V3F_D (cap[i], i, FRONT_CAP);
      }
      ENDPOLYGON();
#endif /* GL_32 */
#ifdef OPENGL_10
      gluBeginPolygon (tobj);
      for (i=0; i<iloop; i++) {
         gluTessVertex (tobj, cap[i], cap[i]);
      }
      gluEndPolygon (tobj);
#endif /* OPENGL_10 */
   } else {

      /* if lighting is on, specify the endcap normal */
      if (cut_vector != NULL) {
         /* if normal pointing in wrong direction, flip it. */
         if (cut_vector[2] > 0.0) {
            VEC_SCALE (cut_vector, -1.0, cut_vector); 
         }
         N3F_D (cut_vector);
      }
      /* the sense of the loop is reversed for backfacing culling */
#ifdef GL_32
      BGNPOLYGON();
      for (i=iloop-1; i>-1; i--) {
         V3F_D (cap[i], i, BACK_CAP);
      }
      ENDPOLYGON();
#endif /* GL_32 */
#ifdef OPENGL_10
      gluBeginPolygon (tobj);
      for (i=iloop-1; i>-1; i--) {
         gluTessVertex (tobj, cap[i], cap[i]);
      }
      gluEndPolygon (tobj);
#endif /* OPENGL_10 */
   }

#ifdef OPENGL_10
   gluDeleteTess (tobj);
#endif /* OPENGL_10 */

}
Example #5
0
int PolyTessGeo::BuildTessGL(void)
{
#ifdef ocpnUSE_GL
    
      int iir, ip;
      int *cntr;
      GLdouble *geoPt;

      wxString    sout;
      wxString    sout1;
      wxString    stemp;


#ifdef __WXMSW__
//  If using the OpenGL dlls provided with Windows,
//  load the dll and establish addresses of the entry points needed

#ifdef USE_GLU_DLL

      if(!s_glu_dll_ready)
      {


            s_hGLU_DLL = LoadLibrary("glu32.dll");
            if (s_hGLU_DLL != NULL)
            {
                  s_lpfnTessProperty = (LPFNDLLTESSPROPERTY)GetProcAddress(s_hGLU_DLL,"gluTessProperty");
                  s_lpfnNewTess = (LPFNDLLNEWTESS)GetProcAddress(s_hGLU_DLL, "gluNewTess");
                  s_lpfnTessBeginContour = (LPFNDLLTESSBEGINCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessBeginContour");
                  s_lpfnTessEndContour = (LPFNDLLTESSENDCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessEndContour");
                  s_lpfnTessBeginPolygon = (LPFNDLLTESSBEGINPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessBeginPolygon");
                  s_lpfnTessEndPolygon = (LPFNDLLTESSENDPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessEndPolygon");
                  s_lpfnDeleteTess = (LPFNDLLDELETETESS)GetProcAddress(s_hGLU_DLL, "gluDeleteTess");
                  s_lpfnTessVertex = (LPFNDLLTESSVERTEX)GetProcAddress(s_hGLU_DLL, "gluTessVertex");
                  s_lpfnTessCallback = (LPFNDLLTESSCALLBACK)GetProcAddress(s_hGLU_DLL, "gluTessCallback");

                  s_glu_dll_ready = true;
            }
            else
            {
                  return ERROR_NO_DLL;
            }
      }

#endif
#endif


    //  Allocate a work buffer, which will be grown as needed
#define NINIT_BUFFER_LEN 10000
      s_pwork_buf = (GLdouble *)malloc(NINIT_BUFFER_LEN * 2 * sizeof(GLdouble));
      s_buf_len = NINIT_BUFFER_LEN * 2;
      s_buf_idx = 0;

      //    Create an array to hold pointers to allocated vertices created by "combine" callback,
      //    so that they may be deleted after tesselation.
      s_pCombineVertexArray = new wxArrayPtrVoid;

    //  Create tesselator
      GLUtessobj = gluNewTess();

    //  Register the callbacks
      gluTessCallback(GLUtessobj, GLU_TESS_BEGIN,   (GLvoid (__CALL_CONVENTION *) ())&beginCallback);
      gluTessCallback(GLUtessobj, GLU_TESS_BEGIN,   (GLvoid (__CALL_CONVENTION *) ())&beginCallback);
      gluTessCallback(GLUtessobj, GLU_TESS_VERTEX,  (GLvoid (__CALL_CONVENTION *) ())&vertexCallback);
      gluTessCallback(GLUtessobj, GLU_TESS_END,     (GLvoid (__CALL_CONVENTION *) ())&endCallback);
      gluTessCallback(GLUtessobj, GLU_TESS_COMBINE, (GLvoid (__CALL_CONVENTION *) ())&combineCallback);

//    gluTessCallback(GLUtessobj, GLU_TESS_ERROR,   (GLvoid (__CALL_CONVENTION *) ())&errorCallback);

//    glShadeModel(GL_SMOOTH);
      gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE,
                      GLU_TESS_WINDING_POSITIVE );

    //  gluTess algorithm internally selects vertically oriented triangle strips and fans.
    //  This orientation is not optimal for conventional memory-mapped raster display shape filling.
    //  We can "fool" the algorithm by interchanging the x and y vertex values passed to gluTessVertex
    //  and then reverting x and y on the resulting vertexCallbacks.
    //  In this implementation, we will explicitely set the preferred orientation.

    //Set the preferred orientation
      tess_orient = TESS_HORZ;                    // prefer horizontal tristrips



//      Get total number of contours
      m_ncnt  = m_pxgeom->n_contours;

//      Allocate cntr array
      cntr = (int *)malloc(m_ncnt * sizeof(int));

//      Get total number of points(vertices)
      int npta  = m_pxgeom->contour_array[0];
      cntr[0] = npta;
      npta += 2;                            // fluff

      for( iir=0 ; iir < m_ncnt-1 ; iir++)
      {
            int nptr = m_pxgeom->contour_array[iir+1];
            cntr[iir+1] = nptr;

            npta += nptr + 2;             // fluff
      }



//      printf("xgeom npta: %d\n", npta);
      geoPt = (GLdouble *)malloc((npta) * 3 * sizeof(GLdouble));     // vertex array



   //  Grow the work buffer if necessary

      if((npta * 4) > s_buf_len)
      {
            s_pwork_buf = (GLdouble *)realloc(s_pwork_buf, npta * 4 * sizeof(GLdouble));
            s_buf_len = npta * 4;
      }


//  Define the polygon
      gluTessBeginPolygon(GLUtessobj, NULL);


//      Create input structures

//    Exterior Ring
      int npte = m_pxgeom->contour_array[0];
      cntr[0] = npte;

      GLdouble *ppt = geoPt;


//  Check and account for winding direction of ring
      bool cw = true;

      double x0, y0, x, y;
      OGRPoint p;

      wxPoint2DDouble *pp = m_pxgeom->vertex_array;
      pp++;       // skip 0?

      if(cw)
      {
//            poly->getExteriorRing()->getPoint(0, &p);
            x0 = pp->m_x;
            y0 = pp->m_y;
      }
      else
      {
//            poly->getExteriorRing()->getPoint(npte-1, &p);
            x0 = pp[npte-1].m_x;
            y0 = pp[npte-1].m_y;
//            x0 = p.getX();
//            y0 = p.getY();
      }

//      pp++;

      gluTessBeginContour(GLUtessobj);

//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
      for(ip = 0 ; ip < npte ; ip++)
      {
            int pidx;
            if(cw)
                  pidx = npte - ip - 1;

            else
                  pidx = ip;

//            poly->getExteriorRing()->getPoint(pidx, &p);
            x = pp[pidx].m_x;
            y = pp[pidx].m_y;

//            pp++;

            if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
            {
                  GLdouble *ppt_temp = ppt;
                  if(tess_orient == TESS_VERT)
                  {
                        *ppt++ = x;
                        *ppt++ = y;
                  }
                  else
                  {
                        *ppt++ = y;
                        *ppt++ = x;
                  }

                  *ppt++ = 0.0;

                  gluTessVertex( GLUtessobj, ppt_temp, ppt_temp ) ;
 //printf("tess from xgeom, external vertex %g %g\n", x, y);

            }
            else
                  cntr[0]--;

            x0 = x;
            y0 = y;
      }

      gluTessEndContour(GLUtessobj);


      int index_offset = npte;
#if 1
//  Now the interior contours
      for(iir=0; iir < m_ncnt-1; iir++)
      {
            gluTessBeginContour(GLUtessobj);

//            int npti = cntr[iir];
            int npti  = m_pxgeom->contour_array[iir+1];

      //  Check and account for winding direction of ring
            bool cw = false; //!(poly->getInteriorRing(iir)->isClockwise() == 0);

            if(!cw)
            {
                  x0 = pp[index_offset].m_x;
                  y0 = pp[index_offset].m_y;
            }
            else
            {
                  x0 = pp[index_offset + npti-1].m_x;
                  y0 = pp[index_offset + npti-1].m_y;
            }

//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
            for(int ip = 0 ; ip < npti ; ip++)
            {
                  OGRPoint p;
                  int pidx;
                  if(!cw)                               // interior contours must be cw
                        pidx = npti - ip - 1;
                  else
                        pidx = ip;


                  x = pp[pidx + index_offset].m_x;
                  y = pp[pidx + index_offset].m_y;

                  if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
                  {
                        GLdouble *ppt_temp = ppt;
                        if(tess_orient == TESS_VERT)
                        {
                              *ppt++ = x;
                              *ppt++ = y;
                        }
                        else
                        {
                              *ppt++ = y;
                              *ppt++ = x;
                        }
                        *ppt++ = 0.0;

                        gluTessVertex( GLUtessobj, ppt_temp, ppt_temp ) ;
//      printf("tess from xgeom, internal vertex %d %g %g\n", ip, x, y);

                  }
                  else
                        cntr[iir+1]--;

                  x0 = x;
                  y0 = y;

            }

            gluTessEndContour(GLUtessobj);

            index_offset += npti;
      }
#endif

    //  Store some SM conversion data in static store,
    //  for callback access
      s_bSENC_SM =  false;

      s_bmerc_transform = true;
      s_transform_x_rate   =  m_pxgeom->x_rate;
      s_transform_x_origin =  m_pxgeom->x_offset;
      s_transform_y_rate   =  m_pxgeom->y_rate;
      s_transform_y_origin =  m_pxgeom->y_offset;


    //      Ready to kick off the tesselator

      s_pTPG_Last = NULL;
      s_pTPG_Head = NULL;

      s_nvmax = 0;

      gluTessEndPolygon(GLUtessobj);          // here it goes

      m_nvertex_max = s_nvmax;               // record largest vertex count, updates in callback


    //  Tesselation all done, so...

    //  Create the data structures

      m_ppg_head = new PolyTriGroup;
      m_ppg_head->m_bSMSENC = s_bSENC_SM;

      m_ppg_head->nContours = m_ncnt;
      m_ppg_head->pn_vertex = cntr;             // pointer to array of poly vertex counts
      m_ppg_head->data_type = DATA_TYPE_DOUBLE;
      

//  Transcribe the raw geometry buffer
//  Converting to float as we go, and
//  allowing for tess_orient
//  Also, convert to SM if requested

      int nptfinal = npta;
      
      //  No longer need the full geometry in the SENC,
      nptfinal = 1;
      
      m_nwkb = (nptfinal +1) * 2 * sizeof(float);
      m_ppg_head->pgroup_geom = (float *)malloc(m_nwkb);
      float *vro = m_ppg_head->pgroup_geom;
      ppt = geoPt;
      float tx,ty;

      for(ip = 0 ; ip < nptfinal ; ip++)
      {
            if(TESS_HORZ == tess_orient)
            {
                  ty = *ppt++;
                  tx = *ppt++;
            }
            else
            {
                  tx = *ppt++;
                  ty = *ppt++;
            }

            if(0/*bSENC_SM*/)
            {
            //  Calculate SM from chart common reference point
                  double easting, northing;
//                  toSM(ty, tx, ref_lat, ref_lon, &easting, &northing);
                  *vro++ = easting;              // x
                  *vro++ = northing;             // y
            }
            else
            {
                  *vro++ = tx;                  // lon
                  *vro++ = ty;                  // lat
            }

            ppt++;                      // skip z
      }

      m_ppg_head->tri_prim_head = s_pTPG_Head;         // head of linked list of TriPrims

      //  Convert the Triangle vertex arrays into a single memory allocation of floats
      //  to reduce SENC size and enable efficient access later
      
      //  First calculate the total byte size
      int total_byte_size = 2 * sizeof(float);
      TriPrim *p_tp = m_ppg_head->tri_prim_head;
      while( p_tp ) {
          total_byte_size += p_tp->nVert * 2 * sizeof(float);
          p_tp = p_tp->p_next; // pick up the next in chain
      }
      
      float *vbuf = (float *)malloc(total_byte_size);
      p_tp = m_ppg_head->tri_prim_head;
      float *p_run = vbuf;
      while( p_tp ) {
          float *pfbuf = p_run;
          GLdouble *pdouble_buf = (GLdouble *)p_tp->p_vertex;
          
          for( int i=0 ; i < p_tp->nVert * 2 ; ++i){
              float x = (float)( *((GLdouble *)pdouble_buf) );
              *p_run++ = x;
              pdouble_buf++;
          }
          
          free(p_tp->p_vertex);
          p_tp->p_vertex = (double *)pfbuf;
          p_tp = p_tp->p_next; // pick up the next in chain
      }
      m_ppg_head->bsingle_alloc = true;
      m_ppg_head->single_buffer = (unsigned char *)vbuf;
      m_ppg_head->single_buffer_size = total_byte_size;
      m_ppg_head->data_type = DATA_TYPE_FLOAT;
      
      gluDeleteTess(GLUtessobj);

      free( s_pwork_buf );
      s_pwork_buf = NULL;

      free (geoPt);

      //    All allocated buffers are owned now by the m_ppg_head
      //    And will be freed on dtor of this object
      delete m_pxgeom;

      //      Free up any "Combine" vertices created
      for(unsigned int i = 0; i < s_pCombineVertexArray->GetCount() ; i++)
            free (s_pCombineVertexArray->Item(i));
      delete s_pCombineVertexArray;


      m_pxgeom = NULL;

      m_bOK = true;

#endif          //#ifdef ocpnUSE_GL
      
      return 0;
}
PsychError SCREENFillPoly(void)  
{	
	PsychColorType				color;
	PsychWindowRecordType		*windowRecord;
	double						whiteValue;
	int							i, mSize, nSize, pSize;
	psych_bool					isArgThere;
	double						*pointList;
	double						isConvex;
	int							j,k;
	int							flag;
	double						z;
	
	combinerCacheSlot = 0;
	combinerCacheSize = 0;
	combinerCache = NULL;
	
	//all sub functions should have these two lines
	PsychPushHelp(useString, synopsisString,seeAlsoString);
	if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
	
	//check for superfluous arguments
	PsychErrorExit(PsychCapNumInputArgs(4));   //The maximum number of inputs
	PsychErrorExit(PsychCapNumOutputArgs(0));  //The maximum number of outputs
	
	//get the window record from the window record argument and get info from the window record
	PsychAllocInWindowRecordArg(1, kPsychArgRequired, &windowRecord);
	
	//Get the color argument or use the default, then coerce to the form determened by the window depth.  
	isArgThere=PsychCopyInColorArg(2, FALSE, &color);
	if(!isArgThere){
		whiteValue=PsychGetWhiteValueFromWindow(windowRecord);
		PsychLoadColorStruct(&color, kPsychIndexColor, whiteValue ); //index mode will coerce to any other.
	}
 	PsychCoerceColorMode( &color);
	
	//get the list of pairs and validate.  
	PsychAllocInDoubleMatArg(3, kPsychArgRequired, &mSize, &nSize, &pSize, &pointList);
	if(nSize!=2) PsychErrorExitMsg(PsychError_user, "Width of pointList must be 2");
	if(mSize<3)  PsychErrorExitMsg(PsychError_user, "Polygons must consist of at least 3 points; M dimension of pointList was < 3!");
	if(pSize>1)  PsychErrorExitMsg(PsychError_user, "pointList must be a 2D matrix, not a 3D matrix!");
	
	isConvex = -1;
	PsychCopyInDoubleArg(4, kPsychArgOptional, &isConvex);
	
    // On non-OpenGL1/2 we always force isConvex to zero, so the GLU tesselator is
    // always used. This because the tesselator only emits GL_TRIANGLES and GL_TRIANGLE_STRIP
    // and GL_TRIANGLE_FANS primitives which are supported on all current OpenGL API's, whereas
    // or "classic" fast-path needs GL_POLYGONS, which are only supported on classic OpenGL1/2:
    if (!PsychIsGLClassic(windowRecord)) isConvex = 0;

	// Enable this windowRecords framebuffer as current drawingtarget:
	PsychSetDrawingTarget(windowRecord);
	
	// Set default drawshader:
	PsychSetShader(windowRecord, -1);
	
	PsychUpdateAlphaBlendingFactorLazily(windowRecord);		 
	PsychSetGLColor(&color, windowRecord);
	
	///////// Test for convexity ////////
	// This algorithm checks, if the polygon is definitely convex, or not.
	// We take the slow-path, if polygon is non-convex or if we can't prove
	// that it is convex.
	//
	// Algorithm adapted from: http://astronomy.swin.edu.au/~pbourke/geometry/clockwise/
	// Which was written by Paul Bourke, 1998.
	//
	// -> This webpage explains the mathematical principle behind the test and provides
	// a C-Source file which has been adapted for use here.
	//	
	if (isConvex == -1) {
		flag = 0;
		for (i=0; i < mSize; i++) {
			j = (i + 1) % mSize;
			k = (i + 2) % mSize;
			z  = (pointList[j] - pointList[i]) * (pointList[k+mSize] - pointList[j+mSize]);
			z -= (pointList[j+mSize] - pointList[i+mSize]) * (pointList[k] - pointList[j]);
			
			if (z < 0) {
				flag |= 1;
			}
			else if (z > 0) {
				flag |= 2;
			}
			
			if (flag == 3) {
				// This is definitely a CONCAVE polygon --> not Convex --> Take slow but safe path.
				break;
			}
		}
		
		if (flag!=0 && flag!=3) {
			// This is a convex polygon --> Take fast path.
			isConvex = 1;
		}
		else {
			// This is a complex polygon --> can't determine if it is convex or not --> Take slow but safe path.
			isConvex = 0;
		}
	}
			
	////// Switch between fast path and slow path, depending on convexity of polygon:
	if (isConvex > 0) {
		// Convex, non-self-intersecting polygon - Take the fast-path:
		glBegin(GL_POLYGON);
		for(i=0;i<mSize;i++) glVertex2d((GLdouble)pointList[i], (GLdouble)pointList[i+mSize]);
		glEnd();
	}
	else {
		// Possibly concave and/or self-intersecting polygon - At least we couldn't prove it is convex.
		// Take the slow, but safe, path using GLU-Tesselators to break it up into a couple of convex, simple
		// polygons:
		
		// Create and initialize a new GLU-Tesselator object, if needed:
		if (NULL == tess) {
			// Create tesselator:
			tess = gluNewTess();
			if (NULL == tess) PsychErrorExitMsg(PsychError_outofMemory, "Out of memory condition in Screen('FillPoly')! Not enough space.");

			// Assign our callback-functions:
			gluTessCallback(tess, GLU_TESS_BEGIN, GLUTESSCBCASTER PsychtcbBegin);
			gluTessCallback(tess, GLU_TESS_VERTEX, GLUTESSCBCASTER PsychtcbVertex);
			gluTessCallback(tess, GLU_TESS_END, GLUTESSCBCASTER PsychtcbEnd);
			gluTessCallback(tess, GLU_TESS_COMBINE, GLUTESSCBCASTER PsychtcbCombine);

			// Define all tesselated polygons to lie in the x-y plane:
			gluTessNormal(tess, 0, 0, 1);
		}

		// We need to hold the values in a temporary array:
		if (tempvsize < mSize) {
			tempvsize = ((mSize / 1000) + 1) * 1000;
			tempv = (double*) realloc((void*) tempv, sizeof(double) * 3 * tempvsize);
			if (NULL == tempv) PsychErrorExitMsg(PsychError_outofMemory, "Out of memory condition in Screen('FillPoly')! Not enough space.");
		}

		// Now submit our Polygon for tesselation:
		gluTessBeginPolygon(tess, NULL);
		gluTessBeginContour(tess);

		for(i=0; i < mSize; i++) {
			tempv[i*3]=(GLdouble) pointList[i];
			tempv[i*3+1]=(GLdouble) pointList[i+mSize];
			tempv[i*3+2]=0;
			gluTessVertex(tess, (GLdouble*) &(tempv[i*3]), (void*) &(tempv[i*3]));
		}
		
		// Process, finalize and render it by calling our callback-functions:
		gluTessEndContour(tess);
		gluTessEndPolygon (tess);
		
		// Done with drawing the filled polygon. (Slow-Path)
	}
	
	// Mark end of drawing op. This is needed for single buffered drawing:
	PsychFlushGL(windowRecord);
	
	// printf("CombinerCalls %i out of %i allocated.\n", combinerCacheSlot, combinerCacheSize);

	return(PsychError_none);
}
Example #7
0
void
extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
  GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
{
  static GLUtriangulatorObj *tobj = NULL;
  GLdouble vertex[3], dx, dy, len;
  int i;
  int count = dataSize / (2 * sizeof(GLfloat));

  if (tobj == NULL) {
    tobj = gluNewTess();  /* create and initialize a GLU
                             polygon * * tesselation object */
    gluTessCallback(tobj, GLU_BEGIN, (void (CALLBACK*)()) glBegin);
    gluTessCallback(tobj, GLU_VERTEX, (void (CALLBACK*)()) glVertex2fv);  /* semi-tricky */
    gluTessCallback(tobj, GLU_END, (void (CALLBACK*)()) glEnd);
  }
  glNewList(side, GL_COMPILE);
  glShadeModel(GL_SMOOTH);  /* smooth minimizes seeing
                               tessellation */
  gluBeginPolygon(tobj);
  for (i = 0; i < count; i++) {
    vertex[0] = data[i][0];
    vertex[1] = data[i][1];
    vertex[2] = 0;
    gluTessVertex(tobj, vertex, data[i]);
  }
  gluEndPolygon(tobj);
  glEndList();
  glNewList(edge, GL_COMPILE);
  glShadeModel(GL_FLAT);  /* flat shade keeps angular hands
                             from being * * "smoothed" */
  glBegin(GL_QUAD_STRIP);
  for (i = 0; i <= count; i++) {
    /* mod function handles closing the edge */
    glVertex3f(data[i % count][0], data[i % count][1], 0.0);
    glVertex3f(data[i % count][0], data[i % count][1], thickness);
    /* Calculate a unit normal by dividing by Euclidean
       distance. We * could be lazy and use
       glEnable(GL_NORMALIZE) so we could pass in * arbitrary
       normals for a very slight performance hit. */
    dx = data[(i + 1) % count][1] - data[i % count][1];
    dy = data[i % count][0] - data[(i + 1) % count][0];
    len = sqrt(dx * dx + dy * dy);
    glNormal3f(dx / len, dy / len, 0.0);
  }
  glEnd();
  glEndList();
  glNewList(whole, GL_COMPILE);
  glFrontFace(GL_CW);
  glCallList(edge);
  glNormal3f(0.0, 0.0, -1.0);  /* constant normal for side */
  glCallList(side);
  glPushMatrix();
  glTranslatef(0.0, 0.0, thickness);
  glFrontFace(GL_CCW);
  glNormal3f(0.0, 0.0, 1.0);  /* opposite normal for other side 

                               */
  glCallList(side);
  glPopMatrix();
  glEndList();
}
/**
  Convert to TriMesh
 */
void PolyhedronGeom::convert(GeomObject* target)
{
  TriMeshGeom* tm = dynamic_cast<TriMeshGeom*>(target);
  vec3d* vertsptr = verts.dataPtr();
  // Index of the corresponding facevarying (or facevertex) variable
  int facevarindex = 0;
  int i, j;

  // Check if the target geom is really a TriMesh
  if (tm==0)
  {
    throw ENotImplementedError("Conversion not supported by the PolyhedronGeom");
  }

  // No tesselation object allocated yet? Then do so once and for all...
  if (tess==0)
  {
    tess = gluNewTess();
    if (tess==0)
      return;
  }

  PolyTriangulation polyTriangulation(*this);

  // Remove any existing variable in the trimesh...
  tm->deleteAllVariables();

  dataMemManager.setDataSize(3*sizeof(GLdouble)+2*sizeof(int));

  gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (TessCallback)(&onTessBegin_triangulation));
  gluTessCallback(tess, GLU_TESS_END_DATA, (TessCallback)(&onTessEnd_triangulation));
  gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (TessCallback)(&onTessVertex_triangulation));
    
  gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
  gluTessProperty(tess, GLU_TESS_TOLERANCE, 0);
  gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);

  // Iterate over all polygons...
  for(i=0; i<getNumPolys(); i++)
  {
    dataMemManager.reset();

    gluTessBeginPolygon(tess, &polyTriangulation);
    // Iterate over all loops of polygon i...
    for(j=0; j<getNumLoops(i); j++)
    {
      gluTessBeginContour(tess);
      LoopIterator it = loopBegin(i, j);
      LoopIterator itend = loopEnd(i, j);
      vec3d* v;
      for( ; it!=itend; it++)
      {
	int vidx = (*it);
	v = vertsptr + vidx;
	GLdouble* loc = (GLdouble*)dataMemManager.newDataPtr();
	loc[0] = v->x;
	loc[1] = v->y;
	loc[2] = v->z;
	int* data = (int*)(loc+3);
	data[0] = vidx;  // Vertex index
	data[1] = facevarindex;  // facevarying variable index
	gluTessVertex(tess, loc, data);
	facevarindex++;
      }
      gluTessEndContour(tess);
    }
    gluTessEndPolygon(tess);
    polyTriangulation.polyFinished();
  }

  polyTriangulation.initTriMesh(*tm);

}
/**
  Draw the polyhedron.
 */
void PolyhedronGeom::drawGL()
{
  // No tesselation object allocated yet? Then do so once and for all...
  if (tess==0)
  {
    tess = gluNewTess();
    if (tess==0)
      return;
  }

  // Set flag to 0 (i.e. no variables are present so far)
  tess_data_flag = 0;
  PrimVarAccess<vec3d> normals(*this, std::string("N"), NORMAL, 1, std::string("Nfaces"));
  PrimVarAccess<double> texcoords(*this, std::string("st"), FLOAT, 2, std::string("stfaces"));
  PrimVarAccess<vec3d> colors(*this, std::string("Cs"), COLOR, 1, std::string("Csfaces"));
  vec3d* N;
  vec3d* Cs;
  GLfloat glcol[4] = {0,0,0,1};
  double* st;
  vec3d* vertsptr = verts.dataPtr();
  int i,j;
  int nfloats=3;

  // Check which variables has to be passed to the vertex callback
  // (this is the case when mode is > 2)
  if (normals.mode>2)
  {
    tess_data_flag |= 0x01;
    nfloats += 3;
  }
  if (texcoords.mode>2)
  {
    tess_data_flag |= 0x02;
    nfloats += 2;
  }
  if (colors.mode>2)
  {
    tess_data_flag |= 0x04;
    nfloats += 3;
  }

  dataMemManager.setDataSize(nfloats*sizeof(GLdouble));

  gluTessCallback(tess, GLU_TESS_BEGIN, (TessCallback)(&onTessBegin));
  gluTessCallback(tess, GLU_TESS_END, (TessCallback)(&onTessEnd));
  gluTessCallback(tess, GLU_TESS_VERTEX, (TessCallback)(&onTessVertex));
    
  gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
  gluTessProperty(tess, GLU_TESS_TOLERANCE, 0);
  gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);

  // Iterate over all polygons...
  for(i=0; i<getNumPolys(); i++)
  {
    dataMemManager.reset();

    // No normals? Then a face normal has to be calculated...
    if (normals.mode==0)
    {
      vec3d Ng;
      computeNormal(i, Ng);
      glNormal3d(Ng.x, Ng.y, Ng.z);      
    }

    // Process uniform variables...
    if (normals.onFace(N))
      glNormal3d(N->x, N->y, N->z);
    if (texcoords.onFace(st))
      glTexCoord2dv(st);
    if (colors.onFace(Cs))
    {
      glcol[0] = GLfloat(Cs->x);
      glcol[1] = GLfloat(Cs->y);
      glcol[2] = GLfloat(Cs->z);
      glMaterialfv(GL_FRONT, GL_DIFFUSE, glcol);
    }

    gluTessBeginPolygon(tess, 0);
    // Iterate over all loops of polygon i...
    for(j=0; j<getNumLoops(i); j++)
    {
      gluTessBeginContour(tess);
      LoopIterator it = loopBegin(i, j);
      LoopIterator itend = loopEnd(i, j);
      vec3d* v;
      for( ; it!=itend; it++)
      {
	int vidx = (*it);
	v = vertsptr + vidx;
	GLdouble* data = (GLdouble*)dataMemManager.newDataPtr();
	GLdouble* p = data+3;
	data[0] = v->x;
	data[1] = v->y;
	data[2] = v->z;
	if (normals.onVertex(vidx, N))
	{
	  p[0] = N->x;
	  p[1] = N->y;
	  p[2] = N->z;
	  p += 3;
	}
	if (texcoords.onVertex(vidx, st))
	{
	  p[0] = st[0];
	  p[1] = st[1];
	  p += 2;
	}
	if (colors.onVertex(vidx, Cs))
	{
	  p[0] = Cs->x;
	  p[1] = Cs->y;
	  p[2] = Cs->z;
	}
	gluTessVertex(tess, data, data);
      }
      gluTessEndContour(tess);
    }
    gluTessEndPolygon(tess);
  }

  /*  for(i=0; i<getNumPolys(); i++)
  {
    for(j=0; j<getNumLoops(i); j++)
    {
      LoopIterator it = loopBegin(i, j);
      LoopIterator itend = loopEnd(i, j);
      vec3d* v;
      glBegin(GL_LINE_LOOP);
      for( ; it!=itend; it++)
      {
	v = vertsptr + (*it);
	glVertex3d(v->x, v->y, v->z);
      }
      glEnd();
    }
    }*/
}
Example #10
0
int
Tesselate (Tcl_Interp *interp, int argc, char* argv [])
{
   int result = TCL_OK;
   int icoord = 0;
   int edgeflags = 1;
   int iarg;
   GLUtriangulatorObj* obj;
   int dlist = -1;
   GLdouble coord [3];
   GLfloat* vtx;
   GLfloat* vtxptr;

   globalinterp = interp;
   globalresult = TCL_OK;

   for (iarg = 2; iarg < argc; iarg++) {	
      int len = (int)strlen (argv [iarg]);
      if (strncmp (argv [iarg], "-displaylist", len) == 0) {
	 iarg++;
	 if (iarg == argc) {
            Tcl_AppendResult (interp, "not enough arguments", (char*)NULL);
            return TCL_ERROR;
         }
         if (strcmp (argv [iarg], "none") == 0) {
            dlist = 0;
         } 
         else if (Tcl_GetInt (interp, argv [iarg], &dlist) != TCL_OK) {
	    Tcl_AppendResult (interp,
	           "\nError parsing display list number", (char*) NULL);
	    return TCL_ERROR;
	 }
      } 
      else if (strncmp (argv [iarg], "-noedgeflags", len) == 0) {
	 edgeflags = 0;
      }
      else break;
   }

   if (argc - iarg < 9) {
      Tcl_AppendResult (interp,
	      "Not enough vertices", (char*) NULL);
      return TCL_ERROR;
   }

   obj = gluNewTess();
   vtx = (GLfloat*) malloc (sizeof (GLfloat) * (argc - iarg));
   vtxptr = vtx;

   assert (vtx != NULL);

   gluTessCallback(obj, GLU_BEGIN, glBegin);
   gluTessCallback(obj, GLU_VERTEX, glVertex3fv); 
   gluTessCallback(obj, GLU_END, glEnd);
   gluTessCallback(obj, GLU_ERROR, (TessCallback) TessError);
   if (edgeflags) gluTessCallback (obj, GLU_EDGE_FLAG, (TessCallback) glEdgeFlag);
   if (dlist == -1) dlist = glGenLists (1);   
   if (dlist != 0) glNewList (dlist, GL_COMPILE);
   gluBeginPolygon (obj);

   for (; iarg < argc; iarg++) {	
      int len = (int)strlen (argv [iarg]);
      if (strncmp (argv [iarg], "-contour", len) == 0) {
	 gluNextContour (obj, GLU_UNKNOWN);
      }
      else {
	 if (Tcl_GetDouble (interp, argv [iarg], &coord[icoord]) != TCL_OK) {
	    Tcl_AppendResult (interp,
	      "\nError parsing tesselation vertex coord", (char*) NULL);
	    result = TCL_ERROR;
	    break;
	 }
	 else {
	    icoord = (icoord+1)%3;
	    if (icoord == 0) {
	       *(vtxptr) = (GLfloat)coord [0];
	       *(vtxptr+1) = (GLfloat)coord [1];
	       *(vtxptr+2) = (GLfloat)coord [2];
	       gluTessVertex (obj, coord, vtxptr);
	       vtxptr += 3;
	    }
	 }
      }
   }
   
   gluEndPolygon (obj);
   gluDeleteTess (obj);
   free (vtx);
   if (dlist != 0) glEndList(); 

   if (result != TCL_OK || globalresult != TCL_OK) {
      if (dlist != 0) glDeleteLists (dlist, 1);
      return TCL_ERROR;
   }
   
   if (dlist != 0) {
     char tmp[128];
     sprintf (tmp, "%d", dlist);
     Tcl_SetResult(interp, tmp, TCL_VOLATILE);
   }
   return TCL_OK;
}
Example #11
0
//----------------------------------------------------------
void ofBeginShape(){

	if (bSmoothHinted && drawMode == OF_OUTLINE) startSmoothing();

	// just clear the vertices, just to make sure that
	// someone didn't do something improper, like :
	// a) ofBeginShape()
	// b) ofVertex(), ofVertex(), ofVertex() ....
	// c) ofBeginShape()
	// etc...

	clearTessVertices();
	
	
	// now get the tesselator object up and ready: 
	
	tobj = gluNewTess();


	// --------------------------------------------------------
	// note: 	you could write your own begin and end callbacks
	// 			if you wanted to...
	// 			for example, to count triangles or know which
	// 			type of object tess is giving back, etc...
	// --------------------------------------------------------

//	#if defined( TARGET_WIN32) || defined( TARGET_LINUX ) || defined( MAC_OS_X_VERSION_10_5 )
//		gluTessCallback( tobj, GLU_TESS_BEGIN, (void(CALLBACK*)())&glBegin);
//		gluTessCallback( tobj, GLU_TESS_VERTEX, (void(CALLBACK*)())&tessVertex);
//		gluTessCallback( tobj, GLU_TESS_COMBINE, (void(CALLBACK*)())&tessCombine);
//		gluTessCallback( tobj, GLU_TESS_END, (void(CALLBACK*)())&glEnd);
//		gluTessCallback( tobj, GLU_TESS_ERROR, (void(CALLBACK*)())&tessError);
//	#else
//		// xcode / osx complained, so we write it the way that makes it happy:
//		gluTessCallback( tobj, GLU_TESS_BEGIN, (void(CALLBACK*)(...))&glBegin);
//		gluTessCallback( tobj, GLU_TESS_VERTEX, (void(CALLBACK*)(...))&tessVertex);
//		gluTessCallback( tobj, GLU_TESS_COMBINE, (void(CALLBACK*)(...))&tessCombine);
//		gluTessCallback( tobj, GLU_TESS_END, (void(CALLBACK*)(...))&glEnd);
//		gluTessCallback( tobj, GLU_TESS_ERROR, (void(CALLBACK*)(...))&tessError);
//	#endif


	gluTessProperty( tobj, GLU_TESS_WINDING_RULE, polyMode);

	if (drawMode == OF_OUTLINE){
		gluTessProperty( tobj, GLU_TESS_BOUNDARY_ONLY, true);
	} else {
		gluTessProperty( tobj, GLU_TESS_BOUNDARY_ONLY, false);
	}

	gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0);

	/* ------------------------------------------
	for 2d, this next call (normal) likely helps speed up ....
	quote : The computation of the normal represents about 10% of
	the computation time. For example, if all polygons lie in
	the x-y plane, you can provide the normal by using the
	-------------------------------------------  */

	gluTessNormal(tobj, 0.0, 0.0, 1.0);
	gluTessBeginPolygon( tobj, NULL);
	
}
Example #12
0
/* convert a PolyList into a linked list of PolyListNodes, subdivide
 * non-flat or concave polgons
 */
static PolyListNode *
PolyListToLinkedPoyList(Transform T, Transform Tdual, Transform TxT,
			const void **tagged_app,
			PolyListNode **plistp,
			PolyList *pl, struct obstack *scratch)
{
  PolyListNode *plist = NULL;
  int pnr;
  
  if (!plistp) {
    plistp = &plist;
  }

  PolyListComputeNormals(pl, PL_HASVN|PL_HASPN|PL_HASPFL);
  for (pnr = 0; pnr < pl->n_polys; pnr++) {
    PolyListNode *new_pn;
    Poly *poly;

    if (pl->p[pnr].flags & POLY_NOPOLY) {
      /* degenerated, just skip it */
      continue;
    }

    poly = &pl->p[pnr];
    poly->flags |= pl->geomflags;

    if (T && T != TM_IDENTITY) {
      poly = transform_poly(T, Tdual, TxT, poly, scratch);
    }

    switch (pl->p[pnr].n_vertices) {
    case 3: /* ok */
      new_pn = new_poly_list_node(tagged_app, scratch);
      new_pn->poly = poly;
      ListPush(*plistp, new_pn);
      break;
#if !HAVE_LIBGLU
    case 4: /* supported */
      if (pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) {
	/* split this polygon along a diagonal, if the polygon is
	 * concave: split across the unique concave vertex.
	 */
	int concave;

	if (pl->p[pnr].flags & POLY_CONCAVE) {
	  Point3 nu;

	  /* We need to determine the concave vertex */
	  PolyNormal(poly, &nu, pl->geomflags & VERT_4D, false, NULL,
		     &concave);
	} else {
	  concave= 0;
	}
	split_quad_poly(concave, poly, plistp, tagged_app, scratch);
      } else {
	new_pn = new_poly_list_node(tagged_app, scratch);
	new_pn->poly = poly;
	ListPush(*plistp, new_pn);
      }
      break;
    default:
      if (pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) {
	static int was_here;
	
	if (!was_here ) {
	  GeomError(1, "Non-flat or concave polygons not supported yet.\n");
	  was_here = 1;
	}
      }
      new_pn = new_poly_list_node(tagged_app, scratch);
      new_pn->poly = poly;
      ListPush(*plistp, new_pn);
      break;
#else
    case 4:
      /* if we want to be able to render polygons with
       * self-intersections "correctly", then we always have to use
       * the GLU tesselater for polygons with more than 4 vertices and
       * for non-convex quadrilaterals. We can handle non-flat
       * quadrilaterals ourselves.
       */
      if ((pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) == POLY_NONFLAT) {
	/* Split this polygon along a diagonal. Leave concave
	 * quadrilaterals to the GLU tesselator; they could have
	 * self-intersections.
	 */
	split_quad_poly(0, poly, plistp, tagged_app, scratch);
      } else if ((pl->p[pnr].flags & POLY_CONCAVE) == 0) {
	new_pn = new_poly_list_node(tagged_app, scratch);
	new_pn->poly = poly;
	ListPush(*plistp, new_pn);
      }
      break;
      /* otherwise fall into the > 4 vertices case and leave
       * everything to the GLU tesselator.
       */
    default: {
      /* We use the GLU tesselator here, if available. It is not
       * necessary to reinvent the wheel; also, the OpenGL MG backend
       * also uses the tesselator (so we will get comparable shapes
       * w/o translucency).
       */
      static GLUtesselator *glutess;
      struct tess_data tessdata[1];
      VARARRAY2(dv, GLdouble, poly->n_vertices, 3);
      Vertex **vp;
      int i;
      
      if (glutess == NULL) {
	glutess = gluNewTess();
	gluTessProperty(glutess,
			GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
	gluTessCallback(glutess, GLU_TESS_BEGIN_DATA,
			(GLvoid (*)())tess_begin_data);
	gluTessCallback(glutess, GLU_TESS_VERTEX_DATA,
			(GLvoid (*)())tess_vertex_data);
	gluTessCallback(glutess, GLU_TESS_COMBINE_DATA,
			(GLvoid (*)())tess_combine_data);
      }

      tessdata->trickyp    = poly;
      tessdata->polyflags  = poly->flags;
      tessdata->pn         = &poly->pn;
      tessdata->scratch    = scratch;
      tessdata->plistp     = plistp;
      tessdata->tagged_app = tagged_app;

      /* tell GLU what we think is a good approximation for the normal */
      gluTessNormal(glutess, poly->pn.x, poly->pn.y, poly->pn.z);

      /* rest is done in the callback functions */
      gluTessBeginPolygon(glutess, tessdata);
      gluTessBeginContour(glutess);
      for (i = 0, vp = poly->v; i < poly->n_vertices; i++, vp++) {
	HPt3Coord w = (*vp)->pt.w ? (*vp)->pt.w : 1e20;

	if (w == 1.0) {
	  dv[i][0] = (*vp)->pt.x;
	  dv[i][1] = (*vp)->pt.y;
	  dv[i][2] = (*vp)->pt.z;
	} else {
	  dv[i][0] = (*vp)->pt.x / w;
	  dv[i][1] = (*vp)->pt.y / w;
	  dv[i][2] = (*vp)->pt.z / w;
	}
	gluTessVertex(glutess, dv[i], *vp);
      }
      gluTessEndContour(glutess);
      gluTessEndPolygon(glutess);
      break; /* out of switch */
    } /* default */
#endif
    } /* switch */
  } /* for */
  return *plistp;
}
/* draw all solid polygons found in aPolysList
 * aZpos = z position in board internal units
 * aThickness = thickness in board internal units
 * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
 * If aThickness > 0, a solid object is drawn.
 *  The top side is located at aZpos + aThickness / 2
 *  The bottom side is located at aZpos - aThickness / 2
 */
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
        int aZpos, int aThickness, double aBiuTo3DUnits,
        bool aUseTextures )
{
    // for Tess callback functions:
    s_biuTo3Dunits = aBiuTo3DUnits;
    s_useTextures = aUseTextures;

    GLUtesselator* tess = gluNewTess();

    gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )tessBeginCB );
    gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )tessEndCB );
    gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB );
    gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tessCPolyPt2Vertex );

    GLdouble    v_data[3];
    double      zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits;
    s_currentZpos = zpos;     // for Tess callback functions
    v_data[2] = aZpos + (aThickness / 2.0);

    // Set normal toward positive Z axis, for a solid object on the top side
    if( aThickness )
        SetNormalZpos();

    // gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);

    // Draw solid areas contained in this list
    CPOLYGONS_LIST polylist = aPolysList;    // temporary copy for gluTessVertex

    int startContour;

    for( int side = 0; side < 2; side++ )
    {
        startContour = 1;

        for( unsigned ii = 0; ii < polylist.GetCornersCount(); ii++ )
        {
            if( startContour == 1 )
            {
                gluTessBeginPolygon( tess, NULL );
                gluTessBeginContour( tess );
                startContour = 0;
            }

            // https://www.opengl.org/sdk/docs/man2/xhtml/gluTessNormal.xml
            gluTessNormal( tess, 0.0, 0.0, 0.0 );


            v_data[0]   = polylist.GetX( ii ) * aBiuTo3DUnits;
            v_data[1]   = -polylist.GetY( ii ) * aBiuTo3DUnits;
            // gluTessVertex store pointers on data, not data, so do not store
            // different corners values in a temporary variable
            // but send pointer on each CPolyPt value in polylist
            // before calling gluDeleteTess
            gluTessVertex( tess, v_data, &polylist[ii] );


            if( polylist.IsEndContour( ii ) )
            {
                gluTessEndContour( tess );
                gluTessEndPolygon( tess );
                startContour = 1;
            }
        }

        if( aThickness == 0 )
            break;

        // Prepare the bottom side of solid areas
        zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits;
        s_currentZpos = zpos;     // for Tess callback functions
        v_data[2] = zpos;
        // Set normal toward negative Z axis, for a solid object on bottom side
        SetNormalZneg();
    }

    if( startContour == 0 )
    {
        gluTessEndContour( tess );
        gluTessEndPolygon( tess );
    }

    gluDeleteTess( tess );

    if( aThickness == 0 )
    {
        return;
    }

    // Build the 3D data : vertical side
    Draw3D_VerticalPolygonalCylinder( polylist, aThickness, aZpos - (aThickness / 2.0), false, aBiuTo3DUnits );
}
void EngineTessellator::Run(double windingRule, bool ccw)
{
	//make sure the last polygon is inserted
	if (current.size())
	{
		polygons.push_back(current);
		current.clear();
	}

	tessellate_t* t=new tessellate_t;
	t->ccw = ccw;
	t->tess = gluNewTess();
	DebugAssert(t->tess);

	gluTessCallback( t->tess, GLU_TESS_ERROR       ,(void (CALLBACK*)())callback_error);
	gluTessCallback( t->tess, GLU_TESS_VERTEX_DATA ,(void (CALLBACK*)())callback_vertex);
	gluTessCallback( t->tess, GLU_TESS_BEGIN_DATA  ,(void (CALLBACK*)())callback_begin);
	gluTessCallback( t->tess, GLU_TESS_END_DATA    ,(void (CALLBACK*)())callback_end);
	gluTessCallback( t->tess, GLU_TESS_COMBINE_DATA,(void (CALLBACK*)())callback_combine);
	gluTessProperty( t->tess, GLU_TESS_WINDING_RULE, windingRule );
	gluTessProperty( t->tess, GLU_TESS_BOUNDARY_ONLY,GL_FALSE); 

	for (polygon_set_t::const_iterator IT=polygons.begin();IT!=polygons.end();IT++)
	{
		const polygon_t& polygon=*IT;

		gluTessBeginPolygon(t->tess,t);
		for (polygon_t::const_iterator JT=polygon.begin();JT!=polygon.end();JT++)
		{
			const contour_t& contour=*JT;
			gluTessBeginContour(t->tess);
			for (int V=0;V<(int)contour.size();V++)
			{
				double* v=new double[3];
				t->to_dealloc.push_back(v);
				v[0]=contour[V].x;
				v[1]=contour[V].y;
				v[2]=contour[V].z;
				gluTessVertex(t->tess,v,v);
			}
			gluTessEndContour(t->tess);
		}
		gluTessEndPolygon(t->tess);
	}

	this->m_raw_triangles=std::vector<Vec3f>();
	for (int I=0;I<(int)t->result.size();I+=3)
	{
		Vec3f& v0=t->result[I+0];this->m_raw_triangles.push_back(Vec3f(v0.x,v0.y,v0.z));
		Vec3f& v1=t->result[I+1];this->m_raw_triangles.push_back(Vec3f(v1.x,v1.y,v1.z));
		Vec3f& v2=t->result[I+2];this->m_raw_triangles.push_back(Vec3f(v2.x,v2.y,v2.z));	
	}

	//the projection matrix
	Mat4f T=Mat4f::getProjectionMatrix(t->result);
	Mat4f Ti=T.invert();

	this->m_matrix=Mat4f(Ti);

	//the graph
	m_g.reset(new Graph(2));

	for (int I=0;I<(int)t->result.size();I+=3)
	{
		Vec3f _v0=T * t->result[I+0];
		Vec3f _v1=T * t->result[I+1];
		Vec3f _v2=T * t->result[I+2];

		//after the projection they should have one less coordinate (which should be v.z)
		Vecf v0=Vecf(1.0f,_v0.x,_v0.y);
		Vecf v1=Vecf(1.0f,_v1.x,_v1.y);
		Vecf v2=Vecf(1.0f,_v2.x,_v2.y);

		//*** vertices *** 
		unsigned int N0=m_g->findVertex(v0); 
		unsigned int N1=m_g->findVertex(v1); 
		unsigned int N2=m_g->findVertex(v2);

		if (!N0) N0=m_g->addVertex(v0);
		if (!N1) N1=m_g->addVertex(v1);
		if (!N2) N2=m_g->addVertex(v2);

		//***  edges *** 
		unsigned int E01=0,E12=0,E20=0;

		E01=m_g->findFirstCommonNode(N0,N1,Graph::DIRECTION_UP);
		E12=m_g->findFirstCommonNode(N1,N2,Graph::DIRECTION_UP);
		E20=m_g->findFirstCommonNode(N2,N0,Graph::DIRECTION_UP);

		if (!E01) {E01=m_g->addEdge(N0,N1);memcpy(m_g->getGeometry(E01,true),m_g->getFittingPlane(E01).mem,sizeof(float)*3);}
		if (!E12) {E12=m_g->addEdge(N1,N2);memcpy(m_g->getGeometry(E12,true),m_g->getFittingPlane(E12).mem,sizeof(float)*3);}
		if (!E20) {E20=m_g->addEdge(N2,N0);memcpy(m_g->getGeometry(E20,true),m_g->getFittingPlane(E20).mem,sizeof(float)*3);}

		//***  triangle *** 
		unsigned int T=0;

		if (!T) {T=m_g->findFirstCommonNode(E01,E12,Graph::DIRECTION_UP);DebugAssert(!T || m_g->findArch(E20,T,Graph::DIRECTION_UP)!=0);}
		if (!T) {T=m_g->findFirstCommonNode(E12,E20,Graph::DIRECTION_UP);DebugAssert(!T || m_g->findArch(E01,T,Graph::DIRECTION_UP)!=0);}
		if (!T) {T=m_g->findFirstCommonNode(E20,E01,Graph::DIRECTION_UP);DebugAssert(!T || m_g->findArch(E12,T,Graph::DIRECTION_UP)!=0);}

		//if the triangle does not exists
		if (!T)
		{
			unsigned int T=m_g->addNode(2);
			m_g->addArch(E01,T);
			m_g->addArch(E12,T);
			m_g->addArch(E20,T);
			m_g->addArch(T,N0);//double connectivity
			m_g->addArch(T,N1);
			m_g->addArch(T,N2);
		}
	}

	//deallocate tessellator
	gluDeleteTess(t->tess);
	for (int i=0;i<(int)t->to_dealloc.size();i++)  delete [] t->to_dealloc[i];
	delete t;

}
Example #15
0
void init (void) 
{
   int i;
   GLUtesselator *tobj;
   GLdouble rect[4][3] = {50.0, 50.0, 0.0,
                          200.0, 50.0, 0.0,
                          200.0, 200.0, 0.0,
                          50.0, 200.0, 0.0};
   GLdouble tri[3][3] = {75.0, 75.0, 0.0,
                         125.0, 175.0, 0.0,
                         175.0, 75.0, 0.0};
   GLdouble star[5][6] = {250.0, 50.0, 0.0, 1.0, 0.0, 1.0,
                          325.0, 200.0, 0.0, 1.0, 1.0, 0.0,
                          400.0, 50.0, 0.0, 0.0, 1.0, 1.0,
                          250.0, 150.0, 0.0, 1.0, 0.0, 0.0,
                          400.0, 150.0, 0.0, 0.0, 1.0, 0.0};

   glClearColor(0.0, 0.0, 0.0, 0.0);


   startList = glGenLists(2);

   tobj = gluNewTess();
   gluTessCallback(tobj, GLU_TESS_VERTEX, 
                   glVertex3dv);
   gluTessCallback(tobj, GLU_TESS_BEGIN, 
                   beginCallback);
   gluTessCallback(tobj, GLU_TESS_END, 
                   endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, 
                   errorCallback);

   /*  rectangle with triangular hole inside  */
   glNewList(startList, GL_COMPILE);
   glShadeModel(GL_FLAT);    
printf("a");
   gluTessBeginPolygon(tobj, NULL);
printf("b");
      gluTessBeginContour(tobj);
printf("c");
         gluTessVertex(tobj, rect[0], rect[0]);
         gluTessVertex(tobj, rect[1], rect[1]);
         gluTessVertex(tobj, rect[2], rect[2]);
         gluTessVertex(tobj, rect[3], rect[3]);
      gluTessEndContour(tobj);
printf(" d");
      gluTessBeginContour(tobj);
printf("e");
         gluTessVertex(tobj, tri[0], tri[0]);
         gluTessVertex(tobj, tri[1], tri[1]);
         gluTessVertex(tobj, tri[2], tri[2]);
printf("f");
      gluTessEndContour(tobj);
printf("g");
   gluTessEndPolygon(tobj);
printf(" h");
   glEndList();

   gluTessCallback(tobj, GLU_TESS_VERTEX, 
                   vertexCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN, 
                   beginCallback);
   gluTessCallback(tobj, GLU_TESS_END, 
                   endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, 
                   errorCallback);
   gluTessCallback(tobj, GLU_TESS_COMBINE, 
                   combineCallback);

   /*  smooth shaded, self-intersecting star  */
   glNewList(startList + 1, GL_COMPILE);
   glShadeModel(GL_SMOOTH);    
   gluTessProperty(tobj, GLU_TESS_WINDING_RULE,
                   GLU_TESS_WINDING_POSITIVE);
   gluTessBeginPolygon(tobj, NULL);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, star[0], star[0]);
         gluTessVertex(tobj, star[1], star[1]);
         gluTessVertex(tobj, star[2], star[2]);
         gluTessVertex(tobj, star[3], star[3]);
         gluTessVertex(tobj, star[4], star[4]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);


	glPushMatrix();
		glTranslatef(-100.0, 200.0, 0.0);
		glBegin(GL_POLYGON);
		for (i=0; i<5; i++) {
			glColor3f(star[i][3], star[i][4], star[i][5]);
			glVertex3f(star[i][0], star[i][1], star[i][2]);
		}
		glEnd();
		glColor3f(1,1,1);
		glBegin(GL_LINE_STRIP);
			glVertex3f(100, 100, 0);
			glVertex3f(100, -100, 0);
			glVertex3f(-100, 0, 0);
			glVertex3f(100, 0, 0);
		glEnd();
	glPopMatrix();


   glEndList();
   gluDeleteTess(tobj);
}
void Playback3D::do_mask_sync(Playback3DCommand *command)
{
#ifdef HAVE_GL
	command->canvas->lock_canvas("Playback3D::do_mask_sync");
	if(command->canvas->get_canvas())
	{
		BC_WindowBase *window = command->canvas->get_canvas();
		window->lock_window("Playback3D::do_mask_sync");
		window->enable_opengl();
		
		switch(command->frame->get_opengl_state())
		{
			case VFrame::RAM:
// Time to upload to the texture
				command->frame->to_texture();
				break;

			case VFrame::SCREEN:
// Read back from PBuffer
// Bind context to pbuffer
				command->frame->enable_opengl();
				command->frame->screen_to_texture();
				break;
		}



// Create PBuffer and draw the mask on it
		command->frame->enable_opengl();

// Initialize coordinate system
		int w = command->frame->get_w();
		int h = command->frame->get_h();
		command->frame->init_screen();
		int value = command->keyframe_set->get_value(command->start_position_project,
			PLAY_FORWARD);
		float feather = command->keyframe_set->get_feather(command->start_position_project,
			PLAY_FORWARD);

// Clear screen
		glDisable(GL_TEXTURE_2D);
		if(command->default_auto->mode == MASK_MULTIPLY_ALPHA)
		{
			glClearColor(0.0, 0.0, 0.0, 0.0);
			glColor4f((float)value / 100, 
				(float)value / 100, 
				(float)value / 100, 
				1.0);
		}
		else
		{
			glClearColor(1.0, 1.0, 1.0, 1.0);
			glColor4f((float)1.0 - (float)value / 100, 
				(float)1.0 - (float)value / 100, 
				(float)1.0 - (float)value / 100, 
				1.0);
		}
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		
// Draw mask with scaling to simulate feathering
		GLUtesselator *tesselator = gluNewTess();
		gluTessProperty(tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
		gluTessCallback(tesselator, GLU_TESS_VERTEX, (GLvoid (*) ( )) &glVertex3dv);
		gluTessCallback(tesselator, GLU_TESS_BEGIN, (GLvoid (*) ( )) &glBegin);
		gluTessCallback(tesselator, GLU_TESS_END, (GLvoid (*) ( )) &glEnd);
		gluTessCallback(tesselator, GLU_TESS_COMBINE, (GLvoid (*) ( ))&combine_callback);


// Draw every submask as a new polygon
		int total_submasks = command->keyframe_set->total_submasks(
			command->start_position_project, 
			PLAY_FORWARD);
		float scale = feather + 1;
 		int display_list = glGenLists(1);
 		glNewList(display_list, GL_COMPILE);
		for(int k = 0; k < total_submasks; k++)
		{
			gluTessBeginPolygon(tesselator, NULL);
			gluTessBeginContour(tesselator);
			ArrayList<MaskPoint*> *points = new ArrayList<MaskPoint*>;
			command->keyframe_set->get_points(points, 
				k, 
				command->start_position_project, 
				PLAY_FORWARD);

			int first_point = 0;
// Need to tabulate every vertex in persistent memory because
// gluTessVertex doesn't copy them.
			ArrayList<GLdouble*> coords;
			for(int i = 0; i < points->total; i++)
			{
				MaskPoint *point1 = points->values[i];
				MaskPoint *point2 = (i >= points->total - 1) ? 
					points->values[0] : 
					points->values[i + 1];


// This is very slow.
				float x, y;
				int segments = (int)(sqrt(SQR(point1->x - point2->x) + SQR(point1->y - point2->y)));
				if(point1->control_x2 == 0 &&
					point1->control_y2 == 0 &&
					point2->control_x1 == 0 &&
					point2->control_y1 == 0)
					segments = 1;

				float x0 = point1->x;
				float y0 = point1->y;
				float x1 = point1->x + point1->control_x2;
				float y1 = point1->y + point1->control_y2;
				float x2 = point2->x + point2->control_x1;
				float y2 = point2->y + point2->control_y1;
				float x3 = point2->x;
				float y3 = point2->y;

				for(int j = 0; j <= segments; j++)
				{
					float t = (float)j / segments;
					float tpow2 = t * t;
					float tpow3 = t * t * t;
					float invt = 1 - t;
					float invtpow2 = invt * invt;
					float invtpow3 = invt * invt * invt;

					x = (        invtpow3 * x0
						+ 3 * t     * invtpow2 * x1
						+ 3 * tpow2 * invt     * x2 
						+     tpow3            * x3);
					y = (        invtpow3 * y0 
						+ 3 * t     * invtpow2 * y1
						+ 3 * tpow2 * invt     * y2 
						+     tpow3            * y3);


					if(j > 0 || first_point)
					{
						GLdouble *coord = new GLdouble[3];
						coord[0] = x / scale;
						coord[1] = -h + y / scale;
						coord[2] = 0;
						coords.append(coord);
						first_point = 0;
					}
				}
			}

// Now that we know the total vertices, send them to GLU
			for(int i = 0; i < coords.total; i++)
				gluTessVertex(tesselator, coords.values[i], coords.values[i]);

			gluTessEndContour(tesselator);
			gluTessEndPolygon(tesselator);
			points->remove_all_objects();
			delete points;
			coords.remove_all_objects();
		}
		glEndList();
 		glCallList(display_list);
 		glDeleteLists(display_list, 1);

		glColor4f(1, 1, 1, 1);


// Read mask into temporary texture.
// For feathering, just read the part of the screen after the downscaling.


		float w_scaled = w / scale;
		float h_scaled = h / scale;
// Don't vary the texture size according to scaling because that 
// would waste memory.
// This enables and binds the temporary texture.
		glActiveTexture(GL_TEXTURE1);
		BC_Texture::new_texture(&temp_texture,
			w, 
			h, 
			command->frame->get_color_model());
		temp_texture->bind(1);
		glReadBuffer(GL_BACK);

// Need to add extra size to fill in the bottom right
		glCopyTexSubImage2D(GL_TEXTURE_2D,
			0,
			0,
			0,
			0,
			0,
			(int)MIN(w_scaled + 2, w),
			(int)MIN(h_scaled + 2, h));

		command->frame->bind_texture(0);


// For feathered masks, use a shader to multiply.
// For unfeathered masks, we could use a stencil buffer 
// for further optimization but we also need a YUV algorithm.
		unsigned int frag_shader = 0;
		switch(temp_texture->get_texture_components())
		{
			case 3: 
				if(command->frame->get_color_model() == BC_YUV888)
					frag_shader = VFrame::make_shader(0,
						multiply_yuvmask3_frag,
						0);
				else
					frag_shader = VFrame::make_shader(0,
						multiply_mask3_frag,
						0);
				break;
			case 4: 
				frag_shader = VFrame::make_shader(0,
					multiply_mask4_frag,
					0);
				break;
		}

		if(frag_shader)
		{
			int variable;
			glUseProgram(frag_shader);
			if((variable = glGetUniformLocation(frag_shader, "tex")) >= 0)
				glUniform1i(variable, 0);
			if((variable = glGetUniformLocation(frag_shader, "tex1")) >= 0)
				glUniform1i(variable, 1);
			if((variable = glGetUniformLocation(frag_shader, "scale")) >= 0)
				glUniform1f(variable, scale);
		}



// Write texture to PBuffer with multiply and scaling for feather.

		
		command->frame->draw_texture(0, 0, w, h, 0, 0, w, h);
		command->frame->set_opengl_state(VFrame::SCREEN);


// Disable temp texture
		glUseProgram(0);

		glActiveTexture(GL_TEXTURE1);
		glDisable(GL_TEXTURE_2D);
		delete temp_texture;
		temp_texture = 0;

		glActiveTexture(GL_TEXTURE0);
		glDisable(GL_TEXTURE_2D);

// Default drawable
		window->enable_opengl();
		window->unlock_window();
	}
	command->canvas->unlock_canvas();
#endif
}
//----------------------------------------------------------
ofVboMesh ofTessellator::tessellate( const ofPolyline& polyline, bool bIs2D ){

	mutex.lock();
	
	clear();
	resultMesh = ofVboMesh();
//	resultMesh.clear();
	
	// now get the tesselator object up and ready:
	GLUtesselator * ofShapeTobj = gluNewTess();
	
#if defined( TARGET_OSX)
#ifndef MAC_OS_X_VERSION_10_5
#define OF_NEED_GLU_FIX
#endif
#endif
	
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	// MAC - XCODE USERS PLEASE NOTE - some machines will not be able to compile the code below
	// if this happens uncomment the "OF_NEED_GLU_FIX" line below and it
	// should compile also please post to the forums with the error message, you OS X version,
	// Xcode verison and the CPU type - PPC or Intel. Thanks!
	// (note: this is known problem based on different version of glu.h, we are working on a fix)
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	
	//#define OF_NEED_GLU_FIX
	
#ifdef OF_NEED_GLU_FIX
#define OF_GLU_CALLBACK_HACK (void(CALLBACK*)(...))
#else
#define OF_GLU_CALLBACK_HACK (void(CALLBACK*)())
#endif
	gluTessCallback( ofShapeTobj, GLU_TESS_BEGIN, OF_GLU_CALLBACK_HACK &ofTessellator::begin);
	gluTessCallback( ofShapeTobj, GLU_TESS_VERTEX, OF_GLU_CALLBACK_HACK &ofTessellator::vertex);
	gluTessCallback( ofShapeTobj, GLU_TESS_COMBINE, OF_GLU_CALLBACK_HACK &ofTessellator::combine);
	gluTessCallback( ofShapeTobj, GLU_TESS_END, OF_GLU_CALLBACK_HACK &ofTessellator::end);
	gluTessCallback( ofShapeTobj, GLU_TESS_ERROR, OF_GLU_CALLBACK_HACK &ofTessellator::error);
	
	gluTessProperty( ofShapeTobj, GLU_TESS_WINDING_RULE, ofGetStyle().polyMode);
	if (!ofGetStyle().bFill){
		gluTessProperty( ofShapeTobj, GLU_TESS_BOUNDARY_ONLY, true);
	} else {
		gluTessProperty( ofShapeTobj, GLU_TESS_BOUNDARY_ONLY, false);
	}
	gluTessProperty( ofShapeTobj, GLU_TESS_TOLERANCE, 0);
	
	/* ------------------------------------------
	 for 2d, this next call (normal) likely helps speed up ....
	 quote : The computation of the normal represents about 10% of
	 the computation time. For example, if all polygons lie in
	 the x-y plane, you can provide the normal by using the
	 -------------------------------------------  */
	if( bIs2D) 
		gluTessNormal(ofShapeTobj, 0.0, 0.0, 1.0);

	gluTessBeginPolygon( ofShapeTobj, NULL);
	
	for ( int i=0; i<polyline.size(); i++ ) {
		double* point = new double[3];
		point[0] = polyline[i].x;
		point[1] = polyline[i].y;
		point[2] = polyline[i].z;
		ofShapePolyVertexs.push_back(point);
	}

	gluTessBeginContour( ofShapeTobj );
	
	for (int i=0; i<(int)ofShapePolyVertexs.size(); i++) {
		gluTessVertex( ofShapeTobj, ofShapePolyVertexs[i], ofShapePolyVertexs[i]);
	}
	
	gluTessEndContour( ofShapeTobj );

	
	
	// no matter what we did / do, we need to delete the tesselator object
	gluTessEndPolygon( ofShapeTobj);
	gluDeleteTess( ofShapeTobj);
	ofShapeTobj = NULL;
	
   	// now clear the vertices on the dynamically allocated data
   	clear();

	mutex.unlock();
	
	return resultMesh;
	
}
Example #18
0
GLUtriangulatorObj* gluauxNewTess (void)
{
 GLUtriangulatorObj* tessobj = gluNewTess();
 create(tessobj);
 return tessobj; 
}
Example #19
0
void CMFCTessView::OnDraw(CDC* pDC)
{
	CMFCTessDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	//some per-drawing init stuff
	glLoadIdentity();

	//setup drawing dimensions, etc
	CPoint vptorg = m_pDC->GetViewportOrg() ; //note m_pDC, NOT pDC
	CRect rect ;
	GetWindowRect( &rect ) ;
	int dx = rect.Width() ;
	int dy = rect.Height() ;
	glViewport( 0, 0, dx, dy );

	glMatrixMode( GL_MODELVIEW );
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	
	// create bitmaps for the device context font's first 256 glyphs 
	HDC hdc = m_pDC->GetSafeHdc() ;
	wglUseFontBitmaps(hdc, 0, 256, 1000); 
	glListBase(1000);

	float R ;
	if( pDoc->m_ContourList.GetCount() > 0 )
	{
		CalculateExtents() ; // Collect overall figure extents (in meters)
		R = Radius ;

		//11/29/03 experiment to eliminate probs w/non-square windows
		float glleft = -R ;
		float gltop = +R ;
		float nearplane = -R ; //rev 07/25/03
		float farplane = R ; //rev 07/25/03

		float glleft2 = glleft ;
		float gltop2 = gltop ;
		float glright2 = ( glleft + 2*R ) ;
		float glbottom2 = ( gltop - 2*R ) ;

		//adjust for non-square viewing window
		float dxdy = (float)dx/(float)dy ;  //=1.00 for square window
		if( dxdy > 1 )
		{
			glOrtho( glleft2*dxdy , glright2*dxdy, glbottom2, gltop2, nearplane, farplane ) ;
		}
		else
		{
			glOrtho( glleft2 , glright2, glbottom2/dxdy, gltop2/dxdy, nearplane, farplane ) ;
		}
		
		glTranslatef( -m_Center.x, -m_Center.y, -m_Center.z ) ;
	}
	else
	{  
		CString txtstr ;
		glOrtho( -1.f , 1.f, -1.f, 1.f, -1.f, 1.f ) ;
		glTranslatef( 0.f, 0.f, 0.f ) ;
		txtstr = "Nothing to draw" ;
		glColor3f( 0.f, 0.f, 0.f ) ;
		glRasterPos3f(0.0F, 0.0F, 0.0F ); 
		glCallLists(txtstr.GetLength(), GL_UNSIGNED_BYTE, txtstr); 

		//clean up & exit
		glFlush(); 
		glDeleteLists(1000, 256) ; 
		SwapBuffers( m_pDC->GetSafeHdc() );
		return ;
	}

	glPushMatrix() ;

	//01/09/05 implement tessellation
	GLUtesselator *tobj;
	tobj = gluNewTess();

	//added 02/09/05 as part of mem leak fix
	while( gm_VertexPtrList.GetCount() > 0 )
	{
		GLdouble* pV = (GLdouble*)gm_VertexPtrList.RemoveHead() ;
		delete[] pV ;
		pV = NULL ;
	}

	gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK *) ())beginCallback);
	gluTessCallback(tobj, GLU_TESS_VERTEX, (void (CALLBACK *) ()) vertexCallback);
	gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK *) ())endCallback);
	gluTessCallback(tobj, GLU_TESS_ERROR,(void (CALLBACK *) ())errorCallback);
	gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK *) ())combineCallback);

	glShadeModel(GL_SMOOTH);    
	gluTessProperty(tobj, GLU_TESS_WINDING_RULE,
               m_WindingRule );

	//only one polygon, but multiple contours
	gluTessBeginPolygon(tobj, NULL);


	POSITION pos = pDoc->m_ContourList.GetHeadPosition() ;
	while ( pos ) 
	{
		CContour* pCtr = (CContour*)pDoc->m_ContourList.GetNext( pos ) ;
		ASSERT( pCtr != NULL && pCtr->m_NumVertex > 0 && pCtr->m_ppVertexArray != NULL ) ;
		int numcorners = pCtr->m_NumVertex ;

		gluTessBeginContour(tobj);

		for( int cnridx = 0; cnridx < numcorners; cnridx++ )
		{
			GLdouble* glvert = pCtr->m_ppVertexArray[cnridx];
			gluTessVertex( tobj, glvert, glvert ) ;
		   TRACE( "Draw: Sent vertex(%f,%f,%f,%f,%f,%f)\n", glvert[0],glvert[1],glvert[2],glvert[3],glvert[4],glvert[5] ) ;
		}

		gluTessEndContour(tobj);
		
	} //end of all contour definitions

		gluTessEndPolygon(tobj);

	//clean up & exit
	glFlush(); 
	glDeleteLists(1000, 256) ; // delete our 256 glyph display lists 
	SwapBuffers( m_pDC->GetSafeHdc() );
	gluDeleteTess( tobj ) ;

	//added 02/09/05 as part of mem leak fix
	while( gm_VertexPtrList.GetCount() > 0 )
	{
		GLdouble* pV = (GLdouble*)gm_VertexPtrList.RemoveHead() ;
		delete[] pV ;
		pV = NULL ;
	}
}
Example #20
0
void GFXSystem::init()  // that's the constructor of the system dependent
// object used for the SDL port
{
	unsigned char *keyboard;
	int size;

	Uint32 rmask, gmask, bmask, amask;

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
#else
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
#endif

	if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
		error("Couldn't initialize SDL: %s\n", SDL_GetError());
	}

	//atexit(Sound_Quit);
	//  atexit(SDL_Quit);

	/*    if (TTF_Init() < 0)
	 {
	 fprintf(stderr, "Couldn't initialize TTF: %s\n", SDL_GetError());
	 exit(1);
	 }
	 atexit(TTF_Quit);

	 int rendersolid = 0;
	 int renderstyle = 0;
	 int rendertype = 0;

	 int ptsize = 11;

	 font = TTF_OpenFont("verdana.ttf", ptsize);

	 if (font == NULL)
	 {
	 fprintf(stderr, "Couldn't load %d pt font from %s: %s\n", ptsize, "verdana.ttf",
	 SDL_GetError());
	 exit(2);
	 }

	 TTF_SetFontStyle(font, renderstyle);*/

	SDL_WM_SetCaption("Alone in the dark \"GL\"", "AITD");

	// SDL_ShowCursor (SDL_DISABLE);

	// SDL_EnableUNICODE (SDL_ENABLE); // not much used in fact

	SDL_PumpEvents();

	keyboard = SDL_GetKeyState(&size);

	keyboard[SDLK_RETURN] = 0;

	sdl_screen = SDL_SetVideoMode(800, 600, 32, SDL_OPENGL/*|SDL_FULLSCREEN*/);

	if(sdl_screen == NULL) {
		error("Couldn't set 640x480x32 video mode: %s\n", SDL_GetError());
	}

	_mouseLeft = 0;
	_mouseRight = 0;

	glEnable(GL_TEXTURE_2D);
	//glEnable(GL_CULL_FACE);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	// glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glViewport(0, 0, 800, 600);

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);       // Black Background
	glMatrixMode(GL_PROJECTION);            // Select The Projection Matrix
	glLoadIdentity();                 // Reset The Projection Matrix
	glOrtho(0, 320, 200, 0, 0.2, -100 * 1000);
	glMatrixMode(GL_MODELVIEW);             // Select The Modelview Matrix
	glLoadIdentity();                 // Reset The Modelview Matrix

	modelsDisplayList = glGenLists(1);

	// Create a new tessellation object
	tobj = gluNewTess();

	// Set callback functions
	gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid( *)())vertexCallback);
	gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid( *)())glBegin);
	gluTessCallback(tobj, GLU_TESS_END, glEnd);
	gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid( *)())combineCallback);

	gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid( *)())vertexCallback);
	gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid( *)())glBegin);
	gluTessCallback(tobj, GLU_TESS_END, glEnd);
	gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid( *)())combineCallback);

	// init debug font
#if 0
#ifdef INTERNAL_DEBUGGER
	glGenTextures(1, &debugFontTexture);
	glBindTexture(GL_TEXTURE_2D, debugFontTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, debugFont);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#endif
#endif

	// SDL_mixer init

	if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 1, 2048) == -1) {
		error("Mix_OpenAudio: %s\n", Mix_GetError());
	}

	Mix_HookMusic(OPL_musicPlayer, NULL);

	// configure offset mode
	glPolygonOffset(1, 2);

	// generate textures
	{
		int i;
		int j;

		unsigned char ditherMap[256*256*4];

		unsigned char *tempPtr = ditherMap;

		for(i = 0; i < 256; i++) {
			for(j = 0; j < 256; j++) {
				unsigned char ditherValue = g_fitd->randRange(0, 0x50);

				*(tempPtr++) = ditherValue;
				*(tempPtr++) = ditherValue;
				*(tempPtr++) = ditherValue;
				*(tempPtr++) = 255;
			}
		}

		//glBlendFunc(GL_SRC_ALPHA,GL_ONE);

		glGenTextures(1, &ditherTexture);
		glBindTexture(GL_TEXTURE_2D, ditherTexture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, ditherMap);

		glBindTexture(GL_TEXTURE_2D, 0);


		glEnable(GL_TEXTURE_2D);
		glEnable(GL_TEXTURE_1D);
	}

	// quadrics init

	sphere = gluNewQuadric();
}
Example #21
0
//      Build PolyTessGeo Object from OGR Polygon
//      Using OpenGL/GLU tesselator
int PolyTessGeo::BuildTessGLU()
{
    
    unsigned int iir, ip;
    GLdouble *geoPt;


#if 0    
    //  Make a quick sanity check of the polygon coherence
    bool b_ok = true;
    OGRLineString *tls = poly->getExteriorRing();
    if(!tls) {
        b_ok = false;
    }
    else {
        int tnpta  = poly->getExteriorRing()->getNumPoints();
        if(tnpta < 3 )
            b_ok = false;
    }

    
    for( iir=0 ; iir < poly->getNumInteriorRings() ; iir++)
    {
        int tnptr = poly->getInteriorRing(iir)->getNumPoints();
        if( tnptr < 3 )
            b_ok = false;
    }
    
    if( !b_ok )
        return ERROR_BAD_OGRPOLY;
    
#endif
    


    //  Allocate a work buffer, which will be grown as needed
#define NINIT_BUFFER_LEN 10000
    m_pwork_buf = (GLdouble *)malloc(NINIT_BUFFER_LEN * 2 * sizeof(GLdouble));
    m_buf_len = NINIT_BUFFER_LEN * 2;
    m_buf_idx = 0;

      //    Create an array to hold pointers to allocated vertices created by "combine" callback,
      //    so that they may be deleted after tesselation.
    m_pCombineVertexArray = new wxArrayPtrVoid;

    //  Create tesselator
    GLUtessobj = gluNewTess();

    //  Register the callbacks
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN_DATA,   (GLvoid (*) ())&beginCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN_DATA,   (GLvoid (*) ())&beginCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_VERTEX_DATA,  (GLvoid (*) ())&vertexCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_END_DATA,     (GLvoid (*) ())&endCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_COMBINE_DATA, (GLvoid (*) ())&combineCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_ERROR_DATA,   (GLvoid (*) ())&errorCallback);

    gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
    gluTessNormal(GLUtessobj, 0, 0, 1);

//      Get total number of points(vertices)  to build a buffer
    int npta  = 0;

    for( int i=0 ; i < m_ncnt ; i++)
        npta += m_cntr[i];


    geoPt = (GLdouble *)malloc((npta + 6) * 3 * sizeof(GLdouble));     // vertex array



   //  Grow the work buffer if necessary

    if((npta * 4) > m_buf_len)
    {
        m_pwork_buf = (GLdouble *)realloc(m_pwork_buf, npta * 4 * sizeof(GLdouble));
        m_buf_len = npta * 4;
    }


//  Define the polygon
    gluTessBeginPolygon(GLUtessobj, this);


    
    //  Check and account for winding direction of ring


      double x0, y0, x, y;
//      OGRPoint p;

      wxPoint2DDouble *pp = (wxPoint2DDouble *)m_vertexPtrArray[0];
      bool cw = !isRingClockwise(pp, m_cntr[0]);
      
      //pp++;       // skip 0?

      if(cw)
      {
            x0 = pp->m_x;
            y0 = pp->m_y;
      }
      else
      {
            x0 = pp[m_cntr[0]-1].m_x;
            y0 = pp[m_cntr[0]-1].m_y;
      }



      unsigned int ptValid = m_cntr[0];
      
//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
      GLdouble *ppt = geoPt;
      
      for(ip = 0 ; ip < (unsigned int)m_cntr[0] ; ip++)
      {
            int pidx;
            if(cw)
                  pidx = m_cntr[0] - ip - 1;

            else
                  pidx = ip;

            x = pp[pidx].m_x;
            y = pp[pidx].m_y;

            if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
            {
                  if(m_tess_orient == TESS_VERT)
                  {
                        *ppt++ = x;
                        *ppt++ = y;
                        *ppt++ = 0;
                  }
                  else
                  {
                        *ppt++ = y;
                        *ppt++ = x;
                        *ppt++ = 0;
                  }
            }
            else
                  ptValid--;

            x0 = x;
            y0 = y;
      }

      //  Apply LOD reduction
    int beforeLOD = ptValid;
    int afterLOD = beforeLOD;
   
 
    if(ptValid > 20 && (m_LOD_meters > .01)) {
        std::vector<bool> bool_keep(ptValid, false);

        // Keep a few key points
        bool_keep[0] = true;
        bool_keep[1] = true;
        bool_keep[ptValid-1] = true;
        bool_keep[ptValid-2] = true;
        
        DouglasPeuckerDI(geoPt, 1, ptValid-2, m_LOD_meters, bool_keep);
            
        // Create a new buffer
        double *LOD_result = (double *)malloc((m_cntr[0]) * 3 * sizeof(double));     
        double *plod = LOD_result;
        int kept_LOD =0;
        
        for(unsigned int i=0 ; i < ptValid ; i++){
            if(bool_keep[i]){
                double x = geoPt[i*3];
                double y = geoPt[(i*3) + 1];
                *plod++ = x;
                *plod++ = y;
                *plod++ = 0;
                kept_LOD++;
            }
        }

        beforeLOD = ptValid;
        afterLOD = kept_LOD;

        // Copy the lod points back into the vertex buffer
        memcpy(geoPt, LOD_result, kept_LOD * 3 * sizeof(double));
        
        free(LOD_result);
        ptValid = kept_LOD;
    }

    //  Declare the gluContour and copy the points
    gluTessBeginContour(GLUtessobj);
    
    double *DPrun = geoPt;
    for(ip = 0 ; ip < ptValid ; ip++) {
        gluTessVertex( GLUtessobj, DPrun, DPrun ) ;
        DPrun += 3;
    }
  
    gluTessEndContour(GLUtessobj);

    //  Now the interior contours
#if 1    
    int gpIndex = m_cntr[0];
    
    for(iir=0; iir < (unsigned int)m_ncnt-1; iir++){
        
            wxPoint2DDouble *pp = (wxPoint2DDouble *)m_vertexPtrArray[iir + 1];

            int npti  = m_cntr[iir+1];
            ptValid = npti;
            
            double *ppt = &geoPt[gpIndex * 3]; // next available location in geoPT
            double *DPStart = ppt;
            
      //  Check and account for winding direction of ring
            bool cw = isRingClockwise(pp, m_cntr[iir+1]);

            if(cw)
            {
                  x0 = pp[0].m_x;
                  y0 = pp[0].m_y;
            }
            else
            {
                  x0 = pp[npti-1].m_x;
                  y0 = pp[npti-1].m_y;
            }

//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
            for(int ip = 0 ; ip < npti ; ip++)
            {
                  int pidx;
                  if(cw)                               // interior contours must be cw
                        pidx = npti - ip - 1;
                  else
                        pidx = ip;


                  x = pp[pidx].m_x;
                  y = pp[pidx].m_y;

                  if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
                  {
                        if(m_tess_orient == TESS_VERT)
                        {
                              *ppt++ = x;
                              *ppt++ = y;
                              *ppt++ = 0;
                        }
                        else
                        {
                              *ppt++ = y;
                              *ppt++ = x;
                              *ppt++ = 0;
                        }
                  }
                  else
                        ptValid--;

                  x0 = x;
                  y0 = y;

            }
            
                       //  Declare the gluContour and reference the points
            gluTessBeginContour(GLUtessobj);
    
            double *DPruni = DPStart;
            for(ip = 0 ; ip < ptValid ; ip++)
            {
                gluTessVertex( GLUtessobj, DPruni, DPruni ) ;
                DPruni += 3;
            }
        
            gluTessEndContour(GLUtessobj);

            gpIndex +=  m_cntr[iir+1];
      }
#endif
        
        
        
        

    m_pTPG_Last = NULL;
    m_pTPG_Head = NULL;
    m_nvmax = 0;

    //      Ready to kick off the tesselator
    gluTessEndPolygon(GLUtessobj);          // here it goes

    m_nvertex_max = m_nvmax;               // record largest vertex count, updates in callback


    //  Tesselation all done, so...

    //  Create the data structures

    m_ppg_head = new PolyTriGroup;
    m_ppg_head->m_bSMSENC = m_b_senc_sm;

    m_ppg_head->nContours = m_ncnt;

    m_ppg_head->pn_vertex = m_cntr;             // pointer to array of poly vertex counts
    m_ppg_head->data_type = DATA_TYPE_DOUBLE;
    

//  Transcribe the raw geometry buffer
//  Converting to float as we go, and
//  allowing for tess_orient
//  Also, convert to SM if requested

// Recalculate the size of the geometry buffer
    unsigned int nptfinal = m_cntr[0] + 2;
//     for(int i=0 ; i < nint ; i++)
//         nptfinal += cntr[i+1] + 2;
    
    //  No longer need the full geometry in the SENC,
    nptfinal = 1;
    
    m_nwkb = (nptfinal + 1) * 2 * sizeof(float);
    m_ppg_head->pgroup_geom = (float *)calloc(sizeof(float), (nptfinal + 1) * 2);
    float *vro = m_ppg_head->pgroup_geom;
    ppt = geoPt;
    float tx,ty;

    for(ip = 0 ; ip < nptfinal ; ip++)
    {
        if(TESS_HORZ == m_tess_orient)
        {
            ty = *ppt++;
            tx = *ppt++;
        }
        else
        {
            tx = *ppt++;
            ty = *ppt++;
        }

        if(m_b_senc_sm)
        {
            //  Calculate SM from chart common reference point
            double easting, northing;
            toSM(ty, tx, m_ref_lat, m_ref_lon, &easting, &northing);
            *vro++ = easting;              // x
            *vro++ = northing;             // y
        }
        else
        {
            *vro++ = tx;                  // lon
            *vro++ = ty;                  // lat
        }

        ppt++;                      // skip z
    }

    m_ppg_head->tri_prim_head = m_pTPG_Head;         // head of linked list of TriPrims


    //  Convert the Triangle vertex arrays into a single memory allocation of floats
    //  to reduce SENC size and enable efficient access later
    
    //  First calculate the total byte size
    int total_byte_size = 2 * sizeof(float);
    TriPrim *p_tp = m_ppg_head->tri_prim_head;
    while( p_tp ) {
        total_byte_size += p_tp->nVert * 2 * sizeof(float);
        p_tp = p_tp->p_next; // pick up the next in chain
    }
    
    float *vbuf = (float *)malloc(total_byte_size);
    p_tp = m_ppg_head->tri_prim_head;
    float *p_run = vbuf;
    while( p_tp ) {
        float *pfbuf = p_run;
        GLdouble *pdouble_buf = (GLdouble *)p_tp->p_vertex;
        
        for( int i=0 ; i < p_tp->nVert * 2 ; ++i){
            float x = (float)( *((GLdouble *)pdouble_buf) );
            pdouble_buf++;
            *p_run++ = x;
        }
        
        free(p_tp->p_vertex);
        p_tp->p_vertex = (double *)pfbuf;
        p_tp = p_tp->p_next; // pick up the next in chain
    }
    m_ppg_head->bsingle_alloc = true;
    m_ppg_head->single_buffer = (unsigned char *)vbuf;
    m_ppg_head->single_buffer_size = total_byte_size;
    m_ppg_head->data_type = DATA_TYPE_FLOAT;
    
    
    
    
    
    
    gluDeleteTess(GLUtessobj);

    free( m_pwork_buf );
    m_pwork_buf = NULL;

    free (geoPt);

    //      Free up any "Combine" vertices created
    for(unsigned int i = 0; i < m_pCombineVertexArray->GetCount() ; i++)
          free (m_pCombineVertexArray->Item(i));
    delete m_pCombineVertexArray;

    m_bOK = true;

    
    return 0;
}
Example #22
0
void init (void) 
{
   GLUtesselator *tobj;
   GLdouble rect[4][3] = {50.0, 50.0, 0.0,
                          200.0, 50.0, 0.0,
                          200.0, 200.0, 0.0,
                          50.0, 200.0, 0.0};
   GLdouble tri[3][3] = {75.0, 75.0, 0.0,
                         125.0, 175.0, 0.0,
                         175.0, 75.0, 0.0};
   GLdouble star[5][6] = {250.0, 50.0, 0.0, 1.0, 0.0, 1.0,
                          325.0, 200.0, 0.0, 1.0, 1.0, 0.0,
                          400.0, 50.0, 0.0, 0.0, 1.0, 1.0,
                          250.0, 150.0, 0.0, 1.0, 0.0, 0.0,
                          400.0, 150.0, 0.0, 0.0, 1.0, 0.0};

   glClearColor(0.0, 0.0, 0.0, 0.0);

   startList = glGenLists(2);

   tobj = gluNewTess();
   gluTessCallback(tobj, GLU_TESS_VERTEX, 
                   glVertex3dv);
   gluTessCallback(tobj, GLU_TESS_BEGIN, 
                   beginCallback);
   gluTessCallback(tobj, GLU_TESS_END, 
                   endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, 
                   errorCallback);

   /*  rectangle with triangular hole inside  */
   glNewList(startList, GL_COMPILE);
   glShadeModel(GL_FLAT);    
   gluTessBeginPolygon(tobj, NULL);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, rect[0], rect[0]);
         gluTessVertex(tobj, rect[1], rect[1]);
         gluTessVertex(tobj, rect[2], rect[2]);
         gluTessVertex(tobj, rect[3], rect[3]);
      gluTessEndContour(tobj);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, tri[0], tri[0]);
         gluTessVertex(tobj, tri[1], tri[1]);
         gluTessVertex(tobj, tri[2], tri[2]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);
   glEndList();

   gluTessCallback(tobj, GLU_TESS_VERTEX, 
                   vertexCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN, 
                   beginCallback);
   gluTessCallback(tobj, GLU_TESS_END, 
                   endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, 
                   errorCallback);
   gluTessCallback(tobj, GLU_TESS_COMBINE, 
                   combineCallback);

   /*  smooth shaded, self-intersecting star  */
   glNewList(startList + 1, GL_COMPILE);
   glShadeModel(GL_SMOOTH);    
   gluTessProperty(tobj, GLU_TESS_WINDING_RULE,
                   GLU_TESS_WINDING_POSITIVE);
   gluTessBeginPolygon(tobj, NULL);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, star[0], star[0]);
         gluTessVertex(tobj, star[1], star[1]);
         gluTessVertex(tobj, star[2], star[2]);
         gluTessVertex(tobj, star[3], star[3]);
         gluTessVertex(tobj, star[4], star[4]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);
   glEndList();
   gluDeleteTess(tobj);
}
Example #23
0
GLUTriangulator::GLUTriangulator() {
  tess = gluNewTess();
  gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLUTessCallback)_faceBegin);
  gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLUTessCallback)_faceVertex);
  gluTessCallback(tess,  GLU_TESS_END_DATA, (GLUTessCallback)_faceEnd);
}
Example #24
0
void Boundary::render(bool invert) {
  // Calculate the geometry of the border
  calculate();

  //glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE);

  // Render the border
  glBegin(GL_QUADS);
  for (int i = 0; i < outerEdges.size(); i++) {
    Edge out = outerEdges[i];
    Edge in = innerEdges[i];

    if (!invert) {
      glColor4f(0.0, 0.0, 0.0, 0.0);
    } else {
      glColor4f(1.0, 1.0, 1.0, 1.0);
    }
    glVertex3f(out.a.x, out.a.y, 0.0);
    glVertex3f(out.b.x, out.b.y, 0.0);
    
    if (!invert) {
      glColor4f(1.0, 1.0, 1.0, 1.0);
    } else {
      glColor4f(0.0, 0.0, 0.0, 0.0);
    }
    glVertex3f(in.b.x, in.b.y, 0.0);
    glVertex3f(in.a.x, in.a.y, 0.0);
  }
  glEnd();
  
  // Fill the border
  if (!invert) {
    glColor3f(1.0, 1.0, 1.0);
  } else {
    glColor3f(0.0, 0.0, 0.0);
  }

  GLUtesselator *tess = gluNewTess();

  gluTessCallback(tess, GLU_TESS_BEGIN, (GLvoid (*) ()) &glBegin);
  gluTessCallback(tess, GLU_TESS_END, (GLvoid (*) ()) &glEnd);
  gluTessCallback(tess, GLU_TESS_VERTEX, (GLvoid (*) ()) &glVertex3dv); 
  
  gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);   
  gluTessNormal(tess, 0, 0, 1);

  gluTessBeginPolygon(tess, NULL);
  gluTessBeginContour(tess);

  GLdouble *vertices = new GLdouble[innerEdges.size() * 3];
  for (int i = 0; i < innerEdges.size(); i++) {
    vertices[(i * 3) + 0] = innerEdges[i].a.x;
    vertices[(i * 3) + 1] = innerEdges[i].a.y;
    vertices[(i * 3) + 2] = 0.0;

    gluTessVertex(tess, vertices + (i * 3), vertices + (i * 3));
  }

  gluTessEndContour(tess);
  gluTessEndPolygon(tess);

  delete [] vertices;
  gluDeleteTess(tess);
}
Example #25
0
//      Build PolyTessGeo Object from OGR Polygon
//      Using OpenGL/GLU tesselator
int PolyTessGeo::PolyTessGeoGL(OGRPolygon *poly, bool bSENC_SM, double ref_lat, double ref_lon)
{
#ifdef ocpnUSE_GL
    
    int iir, ip;
    int *cntr;
    GLdouble *geoPt;

    wxString    sout;
    wxString    sout1;
    wxString    stemp;

    //  Make a quick sanity check of the polygon coherence
    bool b_ok = true;
    OGRLineString *tls = poly->getExteriorRing();
    if(!tls) {
        b_ok = false;
    }
    else {
        int tnpta  = poly->getExteriorRing()->getNumPoints();
        if(tnpta < 3 )
            b_ok = false;
    }

    
    for( iir=0 ; iir < poly->getNumInteriorRings() ; iir++)
    {
        int tnptr = poly->getInteriorRing(iir)->getNumPoints();
        if( tnptr < 3 )
            b_ok = false;
    }
    
    if( !b_ok )
        return ERROR_BAD_OGRPOLY;
    

#ifdef __WXMSW__
//  If using the OpenGL dlls provided with Windows,
//  load the dll and establish addresses of the entry points needed

#ifdef USE_GLU_DLL

    if(!s_glu_dll_ready)
    {


        s_hGLU_DLL = LoadLibrary("glu32.dll");
        if (s_hGLU_DLL != NULL)
        {
            s_lpfnTessProperty = (LPFNDLLTESSPROPERTY)GetProcAddress(s_hGLU_DLL,"gluTessProperty");
            s_lpfnNewTess = (LPFNDLLNEWTESS)GetProcAddress(s_hGLU_DLL, "gluNewTess");
            s_lpfnTessBeginContour = (LPFNDLLTESSBEGINCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessBeginContour");
            s_lpfnTessEndContour = (LPFNDLLTESSENDCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessEndContour");
            s_lpfnTessBeginPolygon = (LPFNDLLTESSBEGINPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessBeginPolygon");
            s_lpfnTessEndPolygon = (LPFNDLLTESSENDPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessEndPolygon");
            s_lpfnDeleteTess = (LPFNDLLDELETETESS)GetProcAddress(s_hGLU_DLL, "gluDeleteTess");
            s_lpfnTessVertex = (LPFNDLLTESSVERTEX)GetProcAddress(s_hGLU_DLL, "gluTessVertex");
            s_lpfnTessCallback = (LPFNDLLTESSCALLBACK)GetProcAddress(s_hGLU_DLL, "gluTessCallback");

            s_glu_dll_ready = true;
        }
        else
        {
            return ERROR_NO_DLL;
        }
    }

#endif
#endif


    //  Allocate a work buffer, which will be grown as needed
#define NINIT_BUFFER_LEN 10000
    s_pwork_buf = (GLdouble *)malloc(NINIT_BUFFER_LEN * 2 * sizeof(GLdouble));
    s_buf_len = NINIT_BUFFER_LEN * 2;
    s_buf_idx = 0;

      //    Create an array to hold pointers to allocated vertices created by "combine" callback,
      //    so that they may be deleted after tesselation.
    s_pCombineVertexArray = new wxArrayPtrVoid;

    //  Create tesselator
    GLUtessobj = gluNewTess();

    //  Register the callbacks
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN,   (GLvoid (__CALL_CONVENTION *) ())&beginCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN,   (GLvoid (__CALL_CONVENTION *) ())&beginCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_VERTEX,  (GLvoid (__CALL_CONVENTION *) ())&vertexCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_END,     (GLvoid (__CALL_CONVENTION *) ())&endCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_COMBINE, (GLvoid (__CALL_CONVENTION *) ())&combineCallback);

//    gluTessCallback(GLUtessobj, GLU_TESS_ERROR,   (GLvoid (__CALL_CONVENTION *) ())&errorCallback);

//    glShadeModel(GL_SMOOTH);
    gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE,
                    GLU_TESS_WINDING_POSITIVE );

    //  gluTess algorithm internally selects vertically oriented triangle strips and fans.
    //  This orientation is not optimal for conventional memory-mapped raster display shape filling.
    //  We can "fool" the algorithm by interchanging the x and y vertex values passed to gluTessVertex
    //  and then reverting x and y on the resulting vertexCallbacks.
    //  In this implementation, we will explicitely set the preferred orientation.

    //Set the preferred orientation
    tess_orient = TESS_HORZ;                    // prefer horizontal tristrips



//    PolyGeo BBox as lat/lon
    OGREnvelope Envelope;
    poly->getEnvelope(&Envelope);
    xmin = Envelope.MinX;
    ymin = Envelope.MinY;
    xmax = Envelope.MaxX;
    ymax = Envelope.MaxY;


//      Get total number of contours
    m_ncnt = 1;                         // always exterior ring
    int nint = poly->getNumInteriorRings();  // interior rings
    m_ncnt += nint;


//      Allocate cntr array
    cntr = (int *)malloc(m_ncnt * sizeof(int));


//      Get total number of points(vertices)
    int npta  = poly->getExteriorRing()->getNumPoints();
    cntr[0] = npta;
    npta += 2;                            // fluff

    for( iir=0 ; iir < nint ; iir++)
    {
        int nptr = poly->getInteriorRing(iir)->getNumPoints();
        cntr[iir+1] = nptr;

        npta += nptr + 2;
    }

//    printf("pPoly npta: %d\n", npta);

    geoPt = (GLdouble *)malloc((npta) * 3 * sizeof(GLdouble));     // vertex array



   //  Grow the work buffer if necessary

    if((npta * 4) > s_buf_len)
    {
        s_pwork_buf = (GLdouble *)realloc(s_pwork_buf, npta * 4 * sizeof(GLdouble));
        s_buf_len = npta * 4;
    }


//  Define the polygon
    gluTessBeginPolygon(GLUtessobj, NULL);


//      Create input structures

//    Exterior Ring
    int npte  = poly->getExteriorRing()->getNumPoints();
    cntr[0] = npte;

    GLdouble *ppt = geoPt;


//  Check and account for winding direction of ring
    bool cw = !(poly->getExteriorRing()->isClockwise() == 0);

    double x0, y0, x, y;
    OGRPoint p;

    if(cw)
    {
        poly->getExteriorRing()->getPoint(0, &p);
        x0 = p.getX();
        y0 = p.getY();
    }
    else
    {
        poly->getExteriorRing()->getPoint(npte-1, &p);
        x0 = p.getX();
        y0 = p.getY();
    }

    //  Transcribe contour to an array of doubles, with duplicates eliminated
    double *DPbuffer = (double *)malloc(npte * 2 * sizeof(double));
    double *DPrun = DPbuffer;
    int nPoints = npte;
    
    for(ip = 0 ; ip < npte ; ip++)
    {
        int pidx;
        if(cw)
            pidx = npte - ip - 1;
    
        else
            pidx = ip;
    
        poly->getExteriorRing()->getPoint(pidx, &p);
        x = p.getX();
        y = p.getY();
    
        if(  ((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS)))
        {
            GLdouble *ppt_temp = ppt;
            if(tess_orient == TESS_VERT)
            {
                *DPrun++ = x;
                *DPrun++ = y;
            }
            else
            {
                *DPrun++ = y;
                *DPrun++ = x;
            }
        
            x0 = x;
            y0 = y;
        }
        else
            nPoints--;
    
    }

 
    if(nPoints > 5 && (m_LOD_meters > .01)){
        index_keep.Clear();
        index_keep.Add(0);
        index_keep.Add(nPoints-1);
        index_keep.Add(1);
        index_keep.Add(nPoints-2);
        
        DouglasPeucker(DPbuffer, 1, nPoints-2, m_LOD_meters/(1852 * 60), &index_keep);
//        printf("DP Reduction: %d/%d\n", index_keep.GetCount(), nPoints);
        
        g_keep += index_keep.GetCount();
        g_orig += nPoints;
//        printf("...................Running: %g\n", (double)g_keep/g_orig);
    }
    else {
        index_keep.Clear();
        for(int i = 0 ; i < nPoints ; i++)
            index_keep.Add(i);
    }
    
    cntr[0] = index_keep.GetCount();
 
    
    // Mark the keepers by adding a simple constant to X
    for(unsigned int i=0 ; i < index_keep.GetCount() ; i++){
        int k = index_keep.Item(i);
        DPbuffer[2*k] += 2000.;
    }

    

    //  Declare the gluContour and copy the points
    gluTessBeginContour(GLUtessobj);
    
    DPrun = DPbuffer;
    for(ip = 0 ; ip < nPoints ; ip++)
    {
        x = *DPrun++;
        y = *DPrun++;
        
        if(x > 1000.){
            
            GLdouble *ppt_top = ppt;
            *ppt++ = x-2000;
            *ppt++ = y;
            *ppt++ = 0;
            
            gluTessVertex( GLUtessobj, ppt_top, ppt_top ) ;
        }
    }
    
    gluTessEndContour(GLUtessobj);
    
    free(DPbuffer);    
    
  
//  Now the interior contours
    for(iir=0 ; iir < nint ; iir++)
    {
        gluTessBeginContour(GLUtessobj);

        int npti = poly->getInteriorRing(iir)->getNumPoints();

      //  Check and account for winding direction of ring
        bool cw = !(poly->getInteriorRing(iir)->isClockwise() == 0);

        if(!cw)
        {
            poly->getInteriorRing(iir)->getPoint(0, &p);
            x0 = p.getX();
            y0 = p.getY();
        }
        else
        {
            poly->getInteriorRing(iir)->getPoint(npti-1, &p);
            x0 = p.getX();
            y0 = p.getY();
        }

//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
        for(int ip = 0 ; ip < npti ; ip++)
        {
            OGRPoint p;
            int pidx;
            if(!cw)                               // interior contours must be cw
                pidx = npti - ip - 1;
            else
                pidx = ip;

            poly->getInteriorRing(iir)->getPoint(pidx, &p);
            x = p.getX();
            y = p.getY();

            if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
            {
                GLdouble *ppt_temp = ppt;
                if(tess_orient == TESS_VERT)
                {
                    *ppt++ = x;
                    *ppt++ = y;
                }
                else
                {
                    *ppt++ = y;
                    *ppt++ = x;
                }
                *ppt++ = 0.0;

                gluTessVertex( GLUtessobj, ppt_temp, ppt_temp ) ;

//       printf("tess from Poly, internal vertex %d %g %g\n", ip, x, y);

            }
            else
                cntr[iir+1]--;

            x0 = x;
            y0 = y;

        }

        gluTessEndContour(GLUtessobj);
    }

    //  Store some SM conversion data in static store,
    //  for callback access
    s_ref_lat = ref_lat;
    s_ref_lon = ref_lon;
    s_bSENC_SM = bSENC_SM;

    s_bmerc_transform = false;

    //      Ready to kick off the tesselator

    s_pTPG_Last = NULL;
    s_pTPG_Head = NULL;

    s_nvmax = 0;

    gluTessEndPolygon(GLUtessobj);          // here it goes

    m_nvertex_max = s_nvmax;               // record largest vertex count, updates in callback


    //  Tesselation all done, so...

    //  Create the data structures

    m_ppg_head = new PolyTriGroup;
    m_ppg_head->m_bSMSENC = s_bSENC_SM;

    m_ppg_head->nContours = m_ncnt;

    m_ppg_head->pn_vertex = cntr;             // pointer to array of poly vertex counts
    m_ppg_head->data_type = DATA_TYPE_DOUBLE;
    

//  Transcribe the raw geometry buffer
//  Converting to float as we go, and
//  allowing for tess_orient
//  Also, convert to SM if requested

// Recalculate the size of the geometry buffer
    int nptfinal = cntr[0] + 2;
    for(int i=0 ; i < nint ; i++)
        nptfinal += cntr[i+1] + 2;
    
    //  No longer need the full geometry in the SENC,
    nptfinal = 1;
    
    m_nwkb = (nptfinal + 1) * 2 * sizeof(float);
    m_ppg_head->pgroup_geom = (float *)calloc(sizeof(float), (nptfinal + 1) * 2);
    float *vro = m_ppg_head->pgroup_geom;
    ppt = geoPt;
    float tx,ty;

    for(ip = 0 ; ip < nptfinal ; ip++)
    {
        if(TESS_HORZ == tess_orient)
        {
            ty = *ppt++;
            tx = *ppt++;
        }
        else
        {
            tx = *ppt++;
            ty = *ppt++;
        }

        if(bSENC_SM)
        {
            //  Calculate SM from chart common reference point
            double easting, northing;
            toSM(ty, tx, ref_lat, ref_lon, &easting, &northing);
            *vro++ = easting;              // x
            *vro++ = northing;             // y
        }
        else
        {
            *vro++ = tx;                  // lon
            *vro++ = ty;                  // lat
        }

        ppt++;                      // skip z
    }

    m_ppg_head->tri_prim_head = s_pTPG_Head;         // head of linked list of TriPrims


    //  Convert the Triangle vertex arrays into a single memory allocation of floats
    //  to reduce SENC size and enable efficient access later
    
    //  First calculate the total byte size
    int total_byte_size = 2 * sizeof(float);
    TriPrim *p_tp = m_ppg_head->tri_prim_head;
    while( p_tp ) {
        total_byte_size += p_tp->nVert * 2 * sizeof(float);
        p_tp = p_tp->p_next; // pick up the next in chain
    }
    
    float *vbuf = (float *)malloc(total_byte_size);
    p_tp = m_ppg_head->tri_prim_head;
    float *p_run = vbuf;
    while( p_tp ) {
        float *pfbuf = p_run;
        GLdouble *pdouble_buf = (GLdouble *)p_tp->p_vertex;
        
        for( int i=0 ; i < p_tp->nVert * 2 ; ++i){
            float x = (float)( *((GLdouble *)pdouble_buf) );
            pdouble_buf++;
            *p_run++ = x;
        }
        
        free(p_tp->p_vertex);
        p_tp->p_vertex = (double *)pfbuf;
        p_tp = p_tp->p_next; // pick up the next in chain
    }
    m_ppg_head->bsingle_alloc = true;
    m_ppg_head->single_buffer = (unsigned char *)vbuf;
    m_ppg_head->single_buffer_size = total_byte_size;
    m_ppg_head->data_type = DATA_TYPE_FLOAT;
    
    
    
    
    
    
    gluDeleteTess(GLUtessobj);

    free( s_pwork_buf );
    s_pwork_buf = NULL;

    free (geoPt);

    //      Free up any "Combine" vertices created
    for(unsigned int i = 0; i < s_pCombineVertexArray->GetCount() ; i++)
          free (s_pCombineVertexArray->Item(i));
    delete s_pCombineVertexArray;

    m_bOK = true;

#endif          //    #ifdef ocpnUSE_GL
    
    return 0;
}
Example #26
0
void tesselateComplexPolygon(Array<Vector3>& input, Array<Triangle>& output) {
    // Use the GLU triangulator to do the hard work.

    static GLUtriangulatorObj* tobj = NULL;

    if (tobj == NULL) {
        tobj = gluNewTess();
#if defined(G3D_OSX) 
        #define CAST(x) reinterpret_cast<void (*)(...)>(x)
#elif defined(G3D_LINUX)
        #define CAST(x) reinterpret_cast<void (*)()>(x)
#else
        #define CAST(x) reinterpret_cast<void (__stdcall *)(void)>(x) 
#endif
	gluTessCallback(tobj, GLU_TESS_BEGIN_DATA,    CAST(_tesselateBegin));
        gluTessCallback(tobj, GLU_TESS_VERTEX_DATA,   CAST(_tesselateVertex));
        gluTessCallback(tobj, GLU_TESS_END_DATA,      CAST(_tesselateEnd));
        gluTessCallback(tobj, GLU_TESS_COMBINE_DATA,  CAST(_tesselateCombine));
        gluTessCallback(tobj, GLU_TESS_ERROR,         CAST(_tesselateError));
        gluTessProperty(tobj, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE,  GLU_TESS_WINDING_ODD);
        #undef CAST
    }

    double v[3];
    int i;
    TessData data;

    gluTessBeginPolygon(tobj, &data);
        gluTessBeginContour(tobj);
            for (i = 0; i < input.size(); ++i) {
                // Expand the input to double precision
                v[0] = input[i].x;
                v[1] = input[i].y;
                v[2] = input[i].z;
                gluTessVertex(tobj, v, &(input[i]));
            }
        gluTessEndContour(tobj);
    gluTessEndPolygon(tobj);


    for (int p = 0; p < data.primitive.size(); ++p) {
        const TessData::Primitive& primitive = data.primitive[p];

        // Turn the tesselated primitive into triangles
        switch (primitive.primitiveType) {
        case GL_TRIANGLES:
            // This is easy, just walk through them in order.
            for (i = 0; i < primitive.vertex.size(); i += 3) {
                output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2]));
            }
            break;

        case GL_TRIANGLE_FAN:
            {
                // Make a triangle between every pair of vertices and the 1st vertex
                for (i = 1; i < primitive.vertex.size() - 1; ++i) {
                    output.append(Triangle(primitive.vertex[0], primitive.vertex[i], primitive.vertex[i + 1]));
                }
            }
            break;

        case GL_TRIANGLE_STRIP:
            for (i = 0; i < primitive.vertex.size() - 3; i += 2) {
                output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2]));
                output.append(Triangle(primitive.vertex[i + 2], primitive.vertex[i + 1], primitive.vertex[i + 3]));
            }
            if (i < primitive.vertex.size() - 2) {
                output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2]));
            }
            break;

        default:
            //debugAssertM(false, GLenumToString(primitive.primitiveType));
            // Ignore other primitives
            ;
        }
    }
}
Example #27
0
static void
_cogl_path_build_fill_attribute_buffer (CoglPath *path)
{
  CoglPathTesselator tess;
  unsigned int path_start = 0;
  CoglPathData *data = path->data;
  int i;

  /* If we've already got a vbo then we don't need to do anything */
  if (data->fill_attribute_buffer)
    return;

  tess.primitive_type = FALSE;

  /* Generate a vertex for each point on the path */
  tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex));
  g_array_set_size (tess.vertices, data->path_nodes->len);
  for (i = 0; i < data->path_nodes->len; i++)
    {
      CoglPathNode *node =
        &g_array_index (data->path_nodes, CoglPathNode, i);
      CoglPathTesselatorVertex *vertex =
        &g_array_index (tess.vertices, CoglPathTesselatorVertex, i);

      vertex->x = node->x;
      vertex->y = node->y;

      /* Add texture coordinates so that a texture would be drawn to
         fit the bounding box of the path and then cropped by the
         path */
      if (data->path_nodes_min.x == data->path_nodes_max.x)
        vertex->s = 0.0f;
      else
        vertex->s = ((node->x - data->path_nodes_min.x)
                     / (data->path_nodes_max.x - data->path_nodes_min.x));
      if (data->path_nodes_min.y == data->path_nodes_max.y)
        vertex->t = 0.0f;
      else
        vertex->t = ((node->y - data->path_nodes_min.y)
                     / (data->path_nodes_max.y - data->path_nodes_min.y));
    }

  tess.indices_type =
    _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len);
  _cogl_path_tesselator_allocate_indices_array (&tess);

  tess.glu_tess = gluNewTess ();

  if (data->fill_rule == COGL_PATH_FILL_RULE_EVEN_ODD)
    gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
                     GLU_TESS_WINDING_ODD);
  else
    gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
                     GLU_TESS_WINDING_NONZERO);

  /* All vertices are on the xy-plane */
  gluTessNormal (tess.glu_tess, 0.0, 0.0, 1.0);

  gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA,
                   _cogl_path_tesselator_begin);
  gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA,
                   _cogl_path_tesselator_vertex);
  gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA,
                   _cogl_path_tesselator_end);
  gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA,
                   _cogl_path_tesselator_combine);

  gluTessBeginPolygon (tess.glu_tess, &tess);

  while (path_start < data->path_nodes->len)
    {
      CoglPathNode *node =
        &g_array_index (data->path_nodes, CoglPathNode, path_start);

      gluTessBeginContour (tess.glu_tess);

      for (i = 0; i < node->path_size; i++)
        {
          double vertex[3] = { node[i].x, node[i].y, 0.0 };
          gluTessVertex (tess.glu_tess, vertex,
                         GINT_TO_POINTER (i + path_start));
        }

      gluTessEndContour (tess.glu_tess);

      path_start += node->path_size;
    }

  gluTessEndPolygon (tess.glu_tess);

  gluDeleteTess (tess.glu_tess);

  data->fill_attribute_buffer =
    cogl_attribute_buffer_new (data->context,
                               sizeof (CoglPathTesselatorVertex) *
                               tess.vertices->len,
                               tess.vertices->data);
  g_array_free (tess.vertices, TRUE);

  data->fill_attributes[0] =
    cogl_attribute_new (data->fill_attribute_buffer,
                        "cogl_position_in",
                        sizeof (CoglPathTesselatorVertex),
                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, x),
                        2, /* n_components */
                        COGL_ATTRIBUTE_TYPE_FLOAT);
  data->fill_attributes[1] =
    cogl_attribute_new (data->fill_attribute_buffer,
                        "cogl_tex_coord0_in",
                        sizeof (CoglPathTesselatorVertex),
                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, s),
                        2, /* n_components */
                        COGL_ATTRIBUTE_TYPE_FLOAT);

  data->fill_vbo_indices = cogl_indices_new (data->context,
                                             tess.indices_type,
                                             tess.indices->data,
                                             tess.indices->len);
  data->fill_vbo_n_indices = tess.indices->len;
  g_array_free (tess.indices, TRUE);
}
Example #28
0
void FTVectoriser::MakeMesh(FTGL_DOUBLE zNormal, int outsetType, float outsetSize)
{
    if(mesh)
    {
        delete mesh;
    }

    mesh = new FTMesh;

    GLUtesselator* tobj = gluNewTess();

    gluTessCallback(tobj, GLU_TESS_BEGIN_DATA,     (GLUTesselatorFunction)ftglBegin);
    gluTessCallback(tobj, GLU_TESS_VERTEX_DATA,    (GLUTesselatorFunction)ftglVertex);
    gluTessCallback(tobj, GLU_TESS_COMBINE_DATA,   (GLUTesselatorFunction)ftglCombine);
    gluTessCallback(tobj, GLU_TESS_END_DATA,       (GLUTesselatorFunction)ftglEnd);
    gluTessCallback(tobj, GLU_TESS_ERROR_DATA,     (GLUTesselatorFunction)ftglError);

    if(contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill
    {
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
    }
    else
    {
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
    }


    gluTessProperty(tobj, GLU_TESS_TOLERANCE, 0);
    gluTessNormal(tobj, 0.0f, 0.0f, zNormal);
    gluTessBeginPolygon(tobj, mesh);

        for(size_t c = 0; c < ContourCount(); ++c)
        {
            /* Build the */
            switch(outsetType)
            {
                case 1 : contourList[c]->buildFrontOutset(outsetSize); break;
                case 2 : contourList[c]->buildBackOutset(outsetSize); break;
            }
            const FTContour* contour = contourList[c];


            gluTessBeginContour(tobj);
                for(size_t p = 0; p < contour->PointCount(); ++p)
                {
                    const FTGL_DOUBLE* d;
                    switch(outsetType)
                    {
                        case 1: d = contour->FrontPoint(p); break;
                        case 2: d = contour->BackPoint(p); break;
                        case 0: default: d = contour->Point(p); break;
                    }
                    // XXX: gluTessVertex doesn't modify the data but does not
                    // specify "const" in its prototype, so we cannot cast to
                    // a const type.
                    gluTessVertex(tobj, (GLdouble *)d, (GLvoid *)d);
                }

            gluTessEndContour(tobj);
        }
    gluTessEndPolygon(tobj);

    gluDeleteTess(tobj);
}
/* Mark Kilgard's tessellation code from the "dino" demos. */
void extrudeSolidFromPolygon(GLfloat data[][3], unsigned int dataSize,
		GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
{
	GLdouble vertex[3], dx, dy, len;
	int i, k;
	int flag = 0;
	int count = dataSize / (3 * sizeof(GLfloat));
    static GLUtriangulatorObj *tobj = NULL;

    if (tobj == NULL) {
    	tobj = gluNewTess();
    	
    	gluTessCallback(tobj, GLU_BEGIN, glBegin);
    	gluTessCallback(tobj, GLU_VERTEX, glVertex3fv);
    	gluTessCallback(tobj, GLU_END, glEnd);
    }
    glNewList(side, GL_COMPILE);
    	glShadeModel(GL_SMOOTH);
    	gluBeginPolygon(tobj);
    		for(i = 0; i < count; i++) {
    			/* This detects a new contour from a large number placed in
    			the unused z coordinate of the vertex where the new contour 
    			starts. See the coordinates for letterO, above. The coordinate 
    			must be reset below for additional calls. */

    			if (data[i][2] > 1000.0) {
    				data[i][2] = 0.0;
    				flag = 1; k = i;
    				gluNextContour(tobj, GLU_INTERIOR); 
    			}
    			
    			vertex[0] = data[i][0];
    			vertex[1] = data[i][1];
    			vertex[2] = 0.0;
    			gluTessVertex(tobj, vertex, data[i]);
    		}
    	gluEndPolygon(tobj);
    glEndList();
	
				/* Reset coordinate for new calls. */
				if (flag == 1) {
				data[k][2] = 10000.0;
				flag = 0;
				}
	glNewList(edge, GL_COMPILE);
		glBegin(GL_QUAD_STRIP);
		for(i = 0; i <= count; i++) {
			glVertex3f(data[i % count][0], data[i % count][1], 0.0);
			glVertex3f(data[i % count][0], data[i % count][1], thickness);
			/* Normals */
			dx = data[(i+ 1) % count][1] - data[i % count][1];
			dy = data[i % count][0] - data[(i + 1) % count][0];
			len = sqrt(dx * dx + dy * dy);
			glNormal3f(dx / len, dy / len, 0.0);
		}
		glEnd();
	glEndList();
	
	glNewList(whole, GL_COMPILE);
		glFrontFace(GL_CW);

		glMaterialfv(GL_FRONT, GL_DIFFUSE, edgeColor);
		glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
		glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);				

		glCallList(edge);
		glNormal3f(0.0, 0.0, -1.0); 
		glCallList(side);
		glPushMatrix();
			glTranslatef(0.0, 0.0, thickness);
			glFrontFace(GL_CCW);
			glNormal3f(0.0, 0.0, 1.0);

		glMaterialfv(GL_FRONT, GL_DIFFUSE, sideColor);
		glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
		glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);		
		
			glCallList(side);
		glPopMatrix();
	glEndList();
}
Example #30
0
gint
gv_area_tessellate(GvArea *in_area)
{
    typedef void (*f);
    static GLUtesselator *tess = NULL;
    GArray *ring;
    GvVertex *v;
    int i, j;
    GLdouble coords[3];

    
    if (!tess)
    {
	tess = gluNewTess();
	g_return_val_if_fail(tess, FALSE);

	gluTessCallback(tess, GLU_TESS_BEGIN, (f) tess_begin);
	gluTessCallback(tess, GLU_TESS_END,   (f) tess_end);
	gluTessCallback(tess, GLU_TESS_VERTEX,(f) tess_vertex);
	gluTessCallback(tess, GLU_TESS_ERROR, (f) tess_error);
    }

    /* Global is available to all tess callbacks */
    area = in_area;

    /* Check for short ring lengths */
    if (!check_ring_lengths()) return FALSE;
    
    /* Fix ring winding before tesselation */
    check_winding();
    
    area->fill_objects = 0;
    if (area->fill)
    {
	g_array_set_size(area->fill, 0);
	g_array_set_size(area->mode_offset, 0);
    }
    else
    {
	area->fill = g_array_new(FALSE, FALSE, sizeof(GvVertex));
	area->mode_offset = 
	  g_array_new(FALSE, FALSE, sizeof(gint));
    }

    coords[2] = 0.0;

    gluTessBeginPolygon(tess, NULL);
    for (i=0; i < area->rings->len; ++i)
    {
	ring = gv_areas_get_ring(area, i);
	
	gluTessBeginContour(tess);
	for (j=0; j < ring->len; ++j)
	{
	    v = &g_array_index(ring, GvVertex, j);
	    coords[0] = (GLdouble)v->x;
	    coords[1] = (GLdouble)v->y;
	    
	    gluTessVertex(tess, coords, v);
	}
	gluTessEndContour(tess);
    }
    gluTessEndPolygon(tess);

    return (area->fill_objects > 0 
	    && g_array_index(area->mode_offset,gint,0) != GV_TESS_NONE);
}