int BuildTris (s_trianglevert_t (*x)[3], s_mesh_t *y, byte **ppdata ) { int i, j, k, m; int startv; int len, bestlen, besttype; int bestverts[MAXSTUDIOTRIANGLES]; int besttris[MAXSTUDIOTRIANGLES]; int peak[MAXSTUDIOTRIANGLES]; int type; int total = 0; long t; int maxlen; triangles = x; pmesh = y; t = time( NULL ); for (i=0 ; i<pmesh->numtris ; i++) { neighbortri[i][0] = neighbortri[i][1] = neighbortri[i][2] = -1; used[i] = 0; peak[i] = pmesh->numtris; } // printf("finding neighbors\n"); for (i=0 ; i<pmesh->numtris; i++) { for (k = 0; k < 3; k++) { if (used[i] & (1 << k)) continue; FindNeighbor( i, k ); } // printf("%d", used[i] ); } // printf("\n"); // // build tristrips // numcommandnodes = 0; numcommands = 0; memset (used, 0, sizeof(used)); for (i=0 ; i<pmesh->numtris ;) { // pick an unused triangle and start the trifan if (used[i]) { i++; continue; } maxlen = 9999; bestlen = 0; m = 0; for (k = i; k < pmesh->numtris && bestlen < 127; k++) { int localpeak = 0; if (used[k]) continue; if (peak[k] <= bestlen) continue; m++; for (type = 0 ; type < 2 ; type++) { for (startv =0 ; startv < 3 ; startv++) { if (type == 1) len = FanLength (k, startv); else len = StripLength (k, startv); if (len > 127) { // skip these, they are too long to encode } else if (len > bestlen) { besttype = type; bestlen = len; for (j=0 ; j<bestlen ; j++) { besttris[j] = striptris[j]; bestverts[j] = stripverts[j]; } // printf("%d %d\n", k, bestlen ); } if (len > localpeak) localpeak = len; } } peak[k] = localpeak; if (localpeak == maxlen) break; } total += (bestlen - 2); // printf("%d (%d) %d\n", bestlen, pmesh->numtris - total, i ); maxlen = bestlen; // mark the tris on the best strip as used for (j=0 ; j<bestlen ; j++) used[besttris[j]] = 1; if (besttype == 1) commands[numcommands++] = -bestlen; else commands[numcommands++] = bestlen; for (j=0 ; j<bestlen ; j++) { s_trianglevert_t *tri; tri = &triangles[besttris[j]][bestverts[j]]; commands[numcommands++] = tri->vertindex; commands[numcommands++] = tri->normindex; commands[numcommands++] = tri->s; commands[numcommands++] = tri->t; } // printf("%d ", bestlen - 2 ); numcommandnodes++; if (t != time(NULL)) { printf("%2d%%\r", (total * 100) / pmesh->numtris ); t = time(NULL); } } commands[numcommands++] = 0; // end of list marker *ppdata = (byte *)commands; // printf("%d %d %d\n", numcommandnodes, numcommands, pmesh->numtris ); return numcommands * sizeof( short ); }
/* ================ BuildTris Generate a list of trifans or strips for the model, which holds for all frames ================ */ void BuildTris (void) { int i, j, k; int startv; float s, t; int len, bestlen, besttype; int bestverts[1024]; int besttris[1024]; int type; // // build tristrips // numorder = 0; numcommands = 0; memset (used, 0, sizeof(used)); for (i = 0; i < pheader->numtris; i++) { // pick an unused triangle and start the trifan if (used[i]) continue; bestlen = 0; besttype = 0; for (type = 0 ; type < 2 ; type++) // type = 1; { for (startv = 0; startv < 3; startv++) { if (type == 1) len = StripLength (i, startv); else len = FanLength (i, startv); if (len > bestlen) { besttype = type; bestlen = len; for (j = 0; j < bestlen+2; j++) bestverts[j] = stripverts[j]; for (j = 0; j < bestlen; j++) besttris[j] = striptris[j]; } } } // mark the tris on the best strip as used for (j = 0; j < bestlen; j++) used[besttris[j]] = 1; if (besttype == 1) commands[numcommands++] = (bestlen+2); else commands[numcommands++] = -(bestlen+2); for (j = 0; j < bestlen+2; j++) { int tmp; // emit a vertex into the reorder buffer k = bestverts[j]; vertexorder[numorder++] = k; // emit s/t coords into the commands stream s = stverts[k].s; t = stverts[k].t; if (!triangles[besttris[0]].facesfront && stverts[k].onseam) s += pheader->skinwidth / 2; // on back side s = (s + 0.5) / pheader->skinwidth; t = (t + 0.5) / pheader->skinheight; // *(float *)&commands[numcommands++] = s; // *(float *)&commands[numcommands++] = t; // NOTE: 4 == sizeof(int) // == sizeof(float) memcpy (&tmp, &s, 4); commands[numcommands++] = tmp; memcpy (&tmp, &t, 4); commands[numcommands++] = tmp; } } commands[numcommands++] = 0; // end of list marker Con_DPrintf2 ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); allverts += numorder; alltris += pheader->numtris; }
/* BuildTris Generate a list of trifans or strips for the model, which holds for all frames */ static void BuildTris (void) { float s, t; int bestlen, len, startv, type, i, j, k; int besttype = 0; int *bestverts = 0, *besttris = 0; // build tristrips numorder = 0; numcommands = 0; stripcount = 0; alloc_used (pheader->mdl.numtris); memset (used, 0, used_size * sizeof (used[0])); for (i = 0; i < pheader->mdl.numtris; i++) { // pick an unused triangle and start the trifan if (used[i]) continue; bestlen = 0; for (type = 0; type < 2; type++) { // type = 1; for (startv = 0; startv < 3; startv++) { if (type == 1) len = StripLength (i, startv); else len = FanLength (i, startv); if (len > bestlen) { besttype = type; bestlen = len; if (bestverts) free (bestverts); if (besttris) free (besttris); bestverts = stripverts; besttris = striptris; stripverts = striptris = 0; strip_size = 0; } } } // mark the tris on the best strip as used for (j = 0; j < bestlen; j++) used[besttris[j + 2]] = 1; if (besttype == 1) add_command (bestlen + 2); else add_command (-(bestlen + 2)); for (j = 0; j < bestlen + 2; j++) { int tmp; // emit a vertex into the reorder buffer k = bestverts[j]; add_vertex (k); // emit s/t coords into the commands stream s = stverts[k].s; t = stverts[k].t; if (!triangles[besttris[0]].facesfront && stverts[k].onseam) s += pheader->mdl.skinwidth / 2; // on back side s = (s + 0.5) / pheader->mdl.skinwidth; t = (t + 0.5) / pheader->mdl.skinheight; memcpy (&tmp, &s, 4); add_command (tmp); memcpy (&tmp, &t, 4); add_command (tmp); } } add_command (0); // end of list marker Sys_MaskPrintf (SYS_DEV, "%3i tri %3i vert %3i cmd\n", pheader->mdl.numtris, numorder, numcommands); allverts += numorder; alltris += pheader->mdl.numtris; if (bestverts) free (bestverts); if (besttris) free (besttris); }
/* ================ BuildTris Generate a list of trifans or strips for the model, which holds for all frames ================ */ void BuildTris (void) { int i, j, k; int startv; mtriangle_t *last, *check; int m1, m2; int striplength; trivertx_t *v; mtriangle_t *tv; float s, t; int index; int len, bestlen, besttype; int* bestverts = Sys_BigStackAlloc(1024 * sizeof(int), "BuildTris"); int* besttris = Sys_BigStackAlloc(1024 * sizeof(int), "BuildTris"); int type; // // build tristrips // numorder = 0; numcommands = 0; memset (used, 0, sizeof(used)); for (i=0 ; i<pheader->numtris ; i++) { // pick an unused triangle and start the trifan if (used[i]) continue; bestlen = 0; for (type = 0 ; type < 2 ; type++) // type = 1; { for (startv =0 ; startv < 3 ; startv++) { if (type == 1) len = StripLength (i, startv); else len = FanLength (i, startv); if (len > bestlen) { besttype = type; bestlen = len; for (j=0 ; j<bestlen+2 ; j++) bestverts[j] = stripverts[j]; for (j=0 ; j<bestlen ; j++) besttris[j] = striptris[j]; } } } // mark the tris on the best strip as used for (j=0 ; j<bestlen ; j++) used[besttris[j]] = 1; if (besttype == 1) commands[numcommands++] = (bestlen+2); else commands[numcommands++] = -(bestlen+2); for (j=0 ; j<bestlen+2 ; j++) { // emit a vertex into the reorder buffer k = bestverts[j]; vertexorder[numorder++] = k; // emit s/t coords into the commands stream s = stverts[k].s; t = stverts[k].t; if (!triangles[besttris[0]].facesfront && stverts[k].onseam) s += pheader->skinwidth / 2; // on back side s = (s + 0.5) / pheader->skinwidth; t = (t + 0.5) / pheader->skinheight; *(float *)&commands[numcommands++] = s; *(float *)&commands[numcommands++] = t; } } commands[numcommands++] = 0; // end of list marker Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); allverts += numorder; alltris += pheader->numtris; Sys_BigStackFree(1024 * sizeof(int) + 1024 * sizeof(int), "BuildTris"); }
/* ================ BuildGlCmds Generate a list of trifans or strips for the model, which holds for all frames ================ */ static void BuildGlCmds (void) { int i, j, k; int startv; float s, t; int len, bestlen, besttype; int best_xyz[1024]; int best_st[1024]; int best_tris[1024]; int type; // // build tristrips // numcommands = 0; numglverts = 0; memset (used, 0, sizeof(used)); for (i=0 ; i<model.num_tris ; i++) { // pick an unused triangle and start the trifan if (used[i]) continue; bestlen = 0; for (type = 0 ; type < 2 ; type++) // type = 1; { for (startv =0 ; startv < 3 ; startv++) { if (type == 1) len = StripLength (i, startv); else len = FanLength (i, startv); if (len > bestlen) { besttype = type; bestlen = len; for (j=0 ; j<bestlen+2 ; j++) { best_st[j] = strip_st[j]; best_xyz[j] = strip_xyz[j]; } for (j=0 ; j<bestlen ; j++) best_tris[j] = strip_tris[j]; } } } // mark the tris on the best strip/fan as used for (j=0 ; j<bestlen ; j++) used[best_tris[j]] = 1; if (besttype == 1) commands[numcommands++] = (bestlen+2); else commands[numcommands++] = -(bestlen+2); numglverts += bestlen+2; for (j=0 ; j<bestlen+2 ; j++) { // emit a vertex into the reorder buffer k = best_st[j]; // emit s/t coords into the commands stream s = base_st[k].s; t = base_st[k].t; s = (s + 0.5) / model.skinwidth; t = (t + 0.5) / model.skinheight; *(float *)&commands[numcommands++] = s; *(float *)&commands[numcommands++] = t; *(int *)&commands[numcommands++] = best_xyz[j]; } } commands[numcommands++] = 0; // end of list marker }
/* ================ BuildTris Generate a list of trifans or strips for the model, which holds for all frames ================ */ void BuildTris (void) { int i, j, k; int startv; mtriangle_t *last, *check; int m1, m2; int striplength; trivertx_t *v; mtriangle_t *tv; float s, t; int index; int len, bestlen, besttype; int bestverts[1024]; int besttris[1024]; int type; int stripmax = 0; // // build tristrips // numorder = 0; numcommands = 0; memset (used, 0, sizeof(used)); for (i=0 ; i<pheader->numtris ; i++) { // pick an unused triangle and start the trifan if (used[i]) continue; bestlen = 0; for (type = 0 ; type < 2 ; type++) // type = 1; { for (startv =0 ; startv < 3 ; startv++) { if (type == 1) len = StripLength (i, startv); else len = FanLength (i, startv); // Save peak if (len > stripmax) stripmax = len; if (len > bestlen) { besttype = type; bestlen = len; for (j=0 ; j<bestlen+2 ; j++) bestverts[j] = stripverts[j]; for (j=0 ; j<bestlen ; j++) besttris[j] = striptris[j]; } } } // mark the tris on the best strip as used for (j=0 ; j<bestlen ; j++) used[besttris[j]] = 1; ChkCmds ("BuildTris"); if (besttype == 1) commands[numcommands++] = (bestlen+2); else commands[numcommands++] = -(bestlen+2); for (j=0 ; j<bestlen+2 ; j++) { // emit a vertex into the reorder buffer k = bestverts[j]; vertexorder[numorder++] = k; // emit s/t coords into the commands stream s = stverts[k].s; t = stverts[k].t; if (!triangles[besttris[0]].facesfront && stverts[k].onseam) s += pheader->skinwidth / 2; // on back side s = (s + 0.5) / pheader->skinwidth; t = (t + 0.5) / pheader->skinheight; ChkCmds ("BuildTris"); *(float *)&commands[numcommands++] = s; *(float *)&commands[numcommands++] = t; } } ChkCmds ("BuildTris"); commands[numcommands++] = 0; // end of list marker // Check old limit if (stripmax + 2 >= 128) { Con_Printf ("\002BuildTris: "); Con_Printf ("excessive stripcount (%d, normal max = %d) in %s\n", stripmax, 128 - 2, aliasmodel->name); } // Check old limit if (numcommands >= 8192) { Con_Printf ("\002BuildTris: "); Con_Printf ("excessive commands (%d, normal max = %d) in %s\n", numcommands, 8192, aliasmodel->name); } #ifndef NO_CACHE_MESH Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); #endif }