Beispiel #1
0
/* \brief return tristripped indecies for triangle index data */
glhckImportIndexData* _glhckTriStrip(const glhckImportIndexData *indices, unsigned int memb, unsigned int *outMemb)
{
#if !GLHCK_TRISTRIP
   (void)indices;
   (void)memb;
   (void)outMemb;

   /* stripping is disabled.
    * importers should fallback to GLHCK_TRIANGLES */
   return NULL;
#else
   int prim;
   glhckImportIndexData v1, v2, v3;
   glhckImportIndexData *outIndices = NULL, *newIndices = NULL;
   unsigned int i, primCount, tmp;
   ACTCData *tc = NULL;
   CALL(0, "%p, %u, %p", indices, memb, outMemb);

   /* check if the triangles we got are valid */
   if (memb % 3 != 0)
      goto not_valid;

   if (!(outIndices = _glhckMalloc(memb * sizeof(glhckImportIndexData))))
      goto out_of_memory;

   if (!(tc = actcNew()))
      goto actc_fail;

   /* parameters */
   ACTC_CALL(actcParami(tc, ACTC_OUT_MIN_FAN_VERTS, INT_MAX));
   ACTC_CALL(actcParami(tc, ACTC_OUT_HONOR_WINDING, ACTC_FALSE));

   /* input data */
   ACTC_CALL(actcBeginInput(tc));
   for (i = 0; i != memb; i+=3) {
      ACTC_CALL(actcAddTriangle(tc,
               indices[i+0],
               indices[i+1],
               indices[i+2]));
   }
   ACTC_CALL(actcEndInput(tc));

   /* FIXME: fix the winding of generated stiched strips */

   /* output data */
   tmp = memb, i = 0, primCount = 0;
   unsigned int flipStart = 0, length = 0;
   ACTC_CALL(actcBeginOutput(tc));
   while ((prim = actcStartNextPrim(tc, &v1, &v2)) != ACTC_DATABASE_EMPTY) {
      assert(prim == ACTC_PRIM_STRIP);
      if (i + (primCount?5:3) > memb)
         goto no_profit;

      /* degenerate to next strip */
      if (primCount && v1 != v3) {
         if (length & 1) {
            _glhckTriStripReverse(&outIndices[flipStart], i-flipStart);
            if (flipStart) outIndices[flipStart-1] = outIndices[flipStart];
         }

         v3 = outIndices[i-1];
         if (v1 != v3) {
            outIndices[i++] = v3;
            outIndices[i++] = v1;
         }
         flipStart = i;
      }

      length = 0;
      outIndices[i++] = v1;
      outIndices[i++] = v2;
      while (actcGetNextVert(tc, &v3) != ACTC_PRIM_COMPLETE) {
         if (i + 1 > memb)
            goto no_profit;
         outIndices[i++] = v3;
         ++length;
      }

      primCount++;
   }
   ACTC_CALL(actcEndOutput(tc));
   puts("");
   printf("%u alloc\n", memb);
   if (outMemb) *outMemb = i;
   memb = tmp;

   // for (i = *outMemb-12; i != *outMemb; ++i)
      // outIndices[i] = 0;

#if 0
   puts("- INDICES:");
   for (i = 0; i != *outMemb; ++i)
      printf("%u%s", outIndices[i], (!((i+1) % 3)?"\n":", "));
   puts("");
#endif

   if (!(newIndices = _glhckRealloc(outIndices, memb, i, sizeof(glhckImportIndexData))))
      goto out_of_memory;
   outIndices = newIndices;

   printf("%u indices\n", memb);
   printf("%u out indicies\n", i);
   printf("%u tristrips\n", primCount);
   printf("%u profit\n", memb - i);
   actcDelete(tc);

   RET(0, "%p", outIndices);
   return outIndices;

not_valid:
   DEBUG(GLHCK_DBG_ERROR, "Tristripper: not valid triangle indices");
   goto fail;
out_of_memory:
   DEBUG(GLHCK_DBG_ERROR, "Tristripper: out of memory");
   goto fail;
actc_fail:
   DEBUG(GLHCK_DBG_ERROR, "Tristripper: init failed");
   goto fail;
no_profit:
   DEBUG(GLHCK_DBG_CRAP, "Tripstripper: no profit from stripping, fallback to triangles");
fail:
   IFDO(actcDelete, tc);
   IFDO(_glhckFree, outIndices);
   RET(0, "%p", NULL);
   return NULL;
#endif
}
Beispiel #2
0
// draw a mesh consisting of vertices, facets, colors, normals etc.
void DispCmdTriMesh::putdata(const float * vertices,
                             const float * normals,
                             const float * colors,
                             int num_verts,
                             const int * facets,
                             int num_facets, 
                             int enablestrips,
                             VMDDisplayList * dobj) {
  int builtstrips = 0; 

#if defined(VMDACTC) 
  if (enablestrips)  {
    // Rearrange face data into triangle strips
    ACTCData *tc = actcNew();  // intialize ACTC stripification library
    int fsize = num_facets * 3;
    int i, ind, ii;
    int iPrimCount = 0;
    int iCurrPrimSize;

    // XXX over-allocate the vertex and facet buffers to prevent an
    //     apparent bug in ACTC 1.1 from crashing VMD.  This was causing
    //     Surf surfaces to crash ACTC at times.
    int *p_iPrimSize = new int[fsize + 6];  // num vertices in a primitive 
    unsigned int *f2 = new uint[fsize + 6];
    
    if (tc == NULL) {
      msgErr << "ACTC initialization failed, using triangle mesh." << sendmsg;
    } else {
      msgInfo << "Performing ACTC Triangle Consolidation..." << sendmsg;
 
      // only produce strips, not fans, give a ridiculously high min value.
      actcParami(tc, ACTC_OUT_MIN_FAN_VERTS, 2147483647);

      // disabling honoring vertex winding order might allow ACTC to
      // consolidate more triangles into strips, but this is only useful
      // if VMD has two-sided lighting enabled.
      // actcParami(tc, ACTC_OUT_HONOR_WINDING, ACTC_TRUE);
        
      // send triangle data over to ACTC library
      actcBeginInput(tc);
      for (ii=0; ii < num_facets; ii++) {
        ind = ii * 3;
        if ((actcAddTriangle(tc, facets[ind], facets[ind + 1], facets[ind + 2])) != ACTC_NO_ERROR) {
          msgInfo << "ACTC Add Triangle Error." << sendmsg;
        }
      }
      actcEndInput(tc);
        
      // get triangle strips back from ACTC, loop through once to get sizes
      actcBeginOutput(tc);
      i = 0;
      while ((actcStartNextPrim(tc, &f2[i], &f2[i+1]) != ACTC_DATABASE_EMPTY)) {
        iCurrPrimSize = 2;  // if we're here, we got 2 vertices
        i+=2;               // increment array position
        while (actcGetNextVert(tc, &f2[i]) != ACTC_PRIM_COMPLETE) {
          iCurrPrimSize++;  // increment number of vertices for this primitive
          i++;              // increment array position
        }

        p_iPrimSize[iPrimCount] = iCurrPrimSize;  // save vertex count
        iPrimCount++;       // increment primitive counter
      }
      actcEndOutput(tc);
      msgInfo << "ACTC: Created " << iPrimCount << " triangle strips" << sendmsg;
      msgInfo << "ACTC: Average vertices per strip = " << i / iPrimCount  << sendmsg;

      // Draw triangle strips, uses double-sided lighting until we change
      // things to allow the callers to specify the desired lighting 
      // explicitly.
      DispCmdTriStrips::putdata(vertices, normals, colors, num_verts, p_iPrimSize, iPrimCount, f2, i, 1, dobj);
          
      // delete temporary memory
      delete [] f2;
      delete [] p_iPrimSize;

      // delete ACTC handle
      actcDelete(tc);

      builtstrips = 1; // don't generate a regular triangle mesh
    }  
  } 
#endif

  if (!builtstrips) {
    // make a triangle mesh (no strips)
    DispCmdTriMesh *ptr = (DispCmdTriMesh *) 
                  (dobj->append(DTRIMESH_C4F_N3F_V3F, sizeof(DispCmdTriMesh) +
                                          sizeof(float) * num_verts * 10 +
                                          sizeof(int) * num_facets * 3));
    if (ptr == NULL)
      return;
    ptr->pervertexcolors=1;
    ptr->numverts=num_verts;
    ptr->numfacets=num_facets;
    float *cnv;
    int *f;
    ptr->getpointers(cnv, f);

#if 1
    int ind10, ind3;
    for (ind10=0,ind3=0; ind10<num_verts*10; ind10+=10,ind3+=3) {
      cnv[ind10    ] =   colors[ind3    ];
      cnv[ind10 + 1] =   colors[ind3 + 1]; 
      cnv[ind10 + 2] =   colors[ind3 + 2]; 
      cnv[ind10 + 3] =   1.0; 
      cnv[ind10 + 4] =  normals[ind3    ];
      cnv[ind10 + 5] =  normals[ind3 + 1];
      cnv[ind10 + 6] =  normals[ind3 + 2];
      cnv[ind10 + 7] = vertices[ind3    ];
      cnv[ind10 + 8] = vertices[ind3 + 1];
      cnv[ind10 + 9] = vertices[ind3 + 2];
    }
#else
    int i, ind, ind2;
    for (i=0; i<num_verts; i++) {
      ind = i * 10;
      ind2 = i * 3;
      cnv[ind    ] =   colors[ind2    ];
      cnv[ind + 1] =   colors[ind2 + 1]; 
      cnv[ind + 2] =   colors[ind2 + 2]; 
      cnv[ind + 3] =   1.0; 
      cnv[ind + 4] =  normals[ind2    ];
      cnv[ind + 5] =  normals[ind2 + 1];
      cnv[ind + 6] =  normals[ind2 + 2];
      cnv[ind + 7] = vertices[ind2    ];
      cnv[ind + 8] = vertices[ind2 + 1];
      cnv[ind + 9] = vertices[ind2 + 2];
    } 
#endif

    memcpy(f, facets, ptr->numfacets * 3 * sizeof(int));
  }
}
Beispiel #3
0
int main(int argc, char **argv)
{
    ACTCData *tc;
    int i;
    uint v1, v2, v3, v4, v5, v6, v7;

    tc = actcNew();
    if(tc == NULL) {
	printf("failed to allocate TC structure\n");
	exit(1);
    }
    i = actcParami(tc, ACTC_OUT_MAX_PRIM_VERTS, 2);
    if(i != ACTC_INVALID_VALUE) {
	printf("didn't get error on MAX_PRIM_VERTS=2 as expected\n");
	exit(1);
    }
    if(i != actcGetError(tc)) {
	printf("error returned didn't equal the error stored\n");
	exit(1);
    }

/* Triangle 1,2,3 */
    CHECKERR(actcBeginInput(tc));
    CHECKERR(actcAddTriangle(tc, 1, 2, 3));
    CHECKERR(actcEndInput(tc));
    CHECKERR(actcBeginOutput(tc));
    CHECKNOT(actcStartNextPrim(tc, &v1, &v2), ACTC_PRIM_STRIP);
    CHECKERR(actcGetNextVert(tc, &v3));
    CHECKNOT(actcGetNextVert(tc, &v4), ACTC_PRIM_COMPLETE);
    CHECKERR(actcEndOutput(tc));
    if(
	! (v1 == 1 && v2 == 2 && v3 == 3) &&
	! (v1 == 2 && v2 == 3 && v3 == 1) &&
	! (v1 == 3 && v2 == 1 && v3 == 2) ) {
	printf("unexpected vertex output:  %u %u %u\n", v1, v2, v3);
	exit(1);
    }

/* Quad 1,2,3,4 */
    CHECKERR(actcBeginInput(tc));
    CHECKERR(actcAddTriangle(tc, 1, 2, 4));
    CHECKERR(actcAddTriangle(tc, 4, 2, 3));
    CHECKERR(actcEndInput(tc));
    CHECKERR(actcBeginOutput(tc));
    CHECKNOT(actcStartNextPrim(tc, &v1, &v2), ACTC_PRIM_STRIP);
    CHECKERR(actcGetNextVert(tc, &v3));
    CHECKERR(actcGetNextVert(tc, &v4));
    CHECKNOT(actcGetNextVert(tc, &v5), ACTC_PRIM_COMPLETE);
    CHECKERR(actcEndOutput(tc));
    /*
     * Next two tests could be fooled by returning same triangle twice,
     * which would certainly be possible, say, if vertices and edges were
     * erroneously not removed from their membership lists.  See tctest2
     * for a more exhaustive and accurate testing framework.
     */
    if(
	! (v1 == 1 && v2 == 2 && v3 == 4) &&
	! (v1 == 2 && v2 == 4 && v3 == 1) &&
	! (v1 == 4 && v2 == 1 && v3 == 2) &&
	! (v1 == 2 && v2 == 3 && v3 == 4) &&
	! (v1 == 3 && v2 == 4 && v3 == 2) &&
	! (v1 == 4 && v2 == 2 && v3 == 3) ) {
	printf("%d : unexpected vertex output:  %u %u %u\n", __LINE__,
	    v1, v2, v3);
	exit(1);
    }
    if(
	! (v2 == 1 && v3 == 4 && v4 == 2) &&
	! (v2 == 2 && v3 == 1 && v4 == 4) &&
	! (v2 == 4 && v3 == 2 && v4 == 1) &&
	! (v2 == 2 && v3 == 4 && v4 == 3) &&
	! (v2 == 3 && v3 == 2 && v4 == 4) &&
	! (v2 == 4 && v3 == 3 && v4 == 2) ) {
	printf("%d : unexpected vertex output:  %u %u %u\n", __LINE__,
	    v2, v3, v4);
	exit(1);
    }

/* independent triangles 1,2,3 and 4,5,6 */
    CHECKERR(actcBeginInput(tc));
    CHECKERR(actcAddTriangle(tc, 1, 2, 3));
    CHECKERR(actcAddTriangle(tc, 4, 5, 6));
    CHECKERR(actcEndInput(tc));
    CHECKERR(actcBeginOutput(tc));
    CHECKNOT(actcStartNextPrim(tc, &v1, &v2), ACTC_PRIM_STRIP);
    CHECKERR(actcGetNextVert(tc, &v3));
    CHECKNOT(actcGetNextVert(tc, &v4), ACTC_PRIM_COMPLETE);
    CHECKNOT(actcStartNextPrim(tc, &v4, &v5), ACTC_PRIM_STRIP);
    CHECKERR(actcGetNextVert(tc, &v6));
    CHECKNOT(actcGetNextVert(tc, &v7), ACTC_PRIM_COMPLETE);
    CHECKERR(actcEndOutput(tc));
    /*
     * Next two tests could be fooled by returning same triangle twice,
     * which would certainly be possible, say, if vertices and edges were
     * erroneously not removed from their membership lists.  See tctest2
     * for a more exhaustive and accurate testing framework.
     */
    if(
	! (v1 == 1 && v2 == 2 && v3 == 3) &&
	! (v1 == 2 && v2 == 3 && v3 == 1) &&
	! (v1 == 3 && v2 == 1 && v3 == 2) &&
	! (v1 == 4 && v2 == 5 && v3 == 6) &&
	! (v1 == 5 && v2 == 6 && v3 == 4) &&
	! (v1 == 6 && v2 == 4 && v3 == 5) ) {
	printf("%d : unexpected vertex output:  %u %u %u\n", __LINE__,
	    v1, v2, v3);
	exit(1);
    }
    if(
	! (v4 == 1 && v5 == 2 && v6 == 3) &&
	! (v4 == 2 && v5 == 3 && v6 == 1) &&
	! (v4 == 3 && v5 == 1 && v6 == 2) &&
	! (v4 == 4 && v5 == 5 && v6 == 6) &&
	! (v4 == 5 && v5 == 6 && v6 == 4) &&
	! (v4 == 6 && v5 == 4 && v6 == 5) ) {
	printf("%d : unexpected vertex output:  %u %u %u\n", __LINE__,
	    v1, v2, v3);
	exit(1);
    }

/* Triangle 1,2,3, but delete it */
    CHECKERR(actcBeginInput(tc));
    CHECKERR(actcAddTriangle(tc, 1, 2, 3));
    CHECKERR(actcEndInput(tc));
    CHECKERR(actcBeginOutput(tc));
    CHECKERR(actcMakeEmpty(tc));
    CHECKNOT(i = actcStartNextPrim(tc, &v1, &v2), ACTC_IDLE);

    actcDelete(tc);

    exit(0);
}