|
|
1.1 ! root 1: // gl_mesh.c: triangle model functions ! 2: ! 3: #include "quakedef.h" ! 4: ! 5: /* ! 6: ================================================================= ! 7: ! 8: ALIAS MODEL DISPLAY LIST GENERATION ! 9: ! 10: ================================================================= ! 11: */ ! 12: ! 13: model_t *aliasmodel; ! 14: aliashdr_t *paliashdr; ! 15: ! 16: qboolean used[8192]; ! 17: ! 18: // the command list holds counts and s/t values that are valid for ! 19: // every frame ! 20: int commands[8192]; ! 21: int numcommands; ! 22: ! 23: // all frames will have their vertexes rearranged and expanded ! 24: // so they are in the order expected by the command list ! 25: int vertexorder[8192]; ! 26: int numorder; ! 27: ! 28: int allverts, alltris; ! 29: ! 30: int stripverts[128]; ! 31: int striptris[128]; ! 32: int stripcount; ! 33: ! 34: /* ! 35: ================ ! 36: StripLength ! 37: ================ ! 38: */ ! 39: int StripLength (int starttri, int startv) ! 40: { ! 41: int m1, m2; ! 42: int j; ! 43: mtriangle_t *last, *check; ! 44: int k; ! 45: ! 46: used[starttri] = 2; ! 47: ! 48: last = &triangles[starttri]; ! 49: ! 50: stripverts[0] = last->vertindex[(startv)%3]; ! 51: stripverts[1] = last->vertindex[(startv+1)%3]; ! 52: stripverts[2] = last->vertindex[(startv+2)%3]; ! 53: ! 54: striptris[0] = starttri; ! 55: stripcount = 1; ! 56: ! 57: m1 = last->vertindex[(startv+2)%3]; ! 58: m2 = last->vertindex[(startv+1)%3]; ! 59: ! 60: // look for a matching triangle ! 61: nexttri: ! 62: for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++) ! 63: { ! 64: if (check->facesfront != last->facesfront) ! 65: continue; ! 66: for (k=0 ; k<3 ; k++) ! 67: { ! 68: if (check->vertindex[k] != m1) ! 69: continue; ! 70: if (check->vertindex[ (k+1)%3 ] != m2) ! 71: continue; ! 72: ! 73: // this is the next part of the fan ! 74: ! 75: // if we can't use this triangle, this tristrip is done ! 76: if (used[j]) ! 77: goto done; ! 78: ! 79: // the new edge ! 80: if (stripcount & 1) ! 81: m2 = check->vertindex[ (k+2)%3 ]; ! 82: else ! 83: m1 = check->vertindex[ (k+2)%3 ]; ! 84: ! 85: stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ]; ! 86: striptris[stripcount] = j; ! 87: stripcount++; ! 88: ! 89: used[j] = 2; ! 90: goto nexttri; ! 91: } ! 92: } ! 93: done: ! 94: ! 95: // clear the temp used flags ! 96: for (j=starttri+1 ; j<pheader->numtris ; j++) ! 97: if (used[j] == 2) ! 98: used[j] = 0; ! 99: ! 100: return stripcount; ! 101: } ! 102: ! 103: /* ! 104: =========== ! 105: FanLength ! 106: =========== ! 107: */ ! 108: int FanLength (int starttri, int startv) ! 109: { ! 110: int m1, m2; ! 111: int j; ! 112: mtriangle_t *last, *check; ! 113: int k; ! 114: ! 115: used[starttri] = 2; ! 116: ! 117: last = &triangles[starttri]; ! 118: ! 119: stripverts[0] = last->vertindex[(startv)%3]; ! 120: stripverts[1] = last->vertindex[(startv+1)%3]; ! 121: stripverts[2] = last->vertindex[(startv+2)%3]; ! 122: ! 123: striptris[0] = starttri; ! 124: stripcount = 1; ! 125: ! 126: m1 = last->vertindex[(startv+0)%3]; ! 127: m2 = last->vertindex[(startv+2)%3]; ! 128: ! 129: ! 130: // look for a matching triangle ! 131: nexttri: ! 132: for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++) ! 133: { ! 134: if (check->facesfront != last->facesfront) ! 135: continue; ! 136: for (k=0 ; k<3 ; k++) ! 137: { ! 138: if (check->vertindex[k] != m1) ! 139: continue; ! 140: if (check->vertindex[ (k+1)%3 ] != m2) ! 141: continue; ! 142: ! 143: // this is the next part of the fan ! 144: ! 145: // if we can't use this triangle, this tristrip is done ! 146: if (used[j]) ! 147: goto done; ! 148: ! 149: // the new edge ! 150: m2 = check->vertindex[ (k+2)%3 ]; ! 151: ! 152: stripverts[stripcount+2] = m2; ! 153: striptris[stripcount] = j; ! 154: stripcount++; ! 155: ! 156: used[j] = 2; ! 157: goto nexttri; ! 158: } ! 159: } ! 160: done: ! 161: ! 162: // clear the temp used flags ! 163: for (j=starttri+1 ; j<pheader->numtris ; j++) ! 164: if (used[j] == 2) ! 165: used[j] = 0; ! 166: ! 167: return stripcount; ! 168: } ! 169: ! 170: ! 171: /* ! 172: ================ ! 173: BuildTris ! 174: ! 175: Generate a list of trifans or strips ! 176: for the model, which holds for all frames ! 177: ================ ! 178: */ ! 179: void BuildTris (void) ! 180: { ! 181: int i, j, k; ! 182: int startv; ! 183: mtriangle_t *last, *check; ! 184: int m1, m2; ! 185: int striplength; ! 186: trivertx_t *v; ! 187: mtriangle_t *tv; ! 188: float s, t; ! 189: int index; ! 190: int len, bestlen, besttype; ! 191: int bestverts[1024]; ! 192: int besttris[1024]; ! 193: int type; ! 194: ! 195: // ! 196: // build tristrips ! 197: // ! 198: numorder = 0; ! 199: numcommands = 0; ! 200: memset (used, 0, sizeof(used)); ! 201: for (i=0 ; i<pheader->numtris ; i++) ! 202: { ! 203: // pick an unused triangle and start the trifan ! 204: if (used[i]) ! 205: continue; ! 206: ! 207: bestlen = 0; ! 208: for (type = 0 ; type < 2 ; type++) ! 209: // type = 1; ! 210: { ! 211: for (startv =0 ; startv < 3 ; startv++) ! 212: { ! 213: if (type == 1) ! 214: len = StripLength (i, startv); ! 215: else ! 216: len = FanLength (i, startv); ! 217: if (len > bestlen) ! 218: { ! 219: besttype = type; ! 220: bestlen = len; ! 221: for (j=0 ; j<bestlen+2 ; j++) ! 222: bestverts[j] = stripverts[j]; ! 223: for (j=0 ; j<bestlen ; j++) ! 224: besttris[j] = striptris[j]; ! 225: } ! 226: } ! 227: } ! 228: ! 229: // mark the tris on the best strip as used ! 230: for (j=0 ; j<bestlen ; j++) ! 231: used[besttris[j]] = 1; ! 232: ! 233: if (besttype == 1) ! 234: commands[numcommands++] = (bestlen+2); ! 235: else ! 236: commands[numcommands++] = -(bestlen+2); ! 237: ! 238: for (j=0 ; j<bestlen+2 ; j++) ! 239: { ! 240: // emit a vertex into the reorder buffer ! 241: k = bestverts[j]; ! 242: vertexorder[numorder++] = k; ! 243: ! 244: // emit s/t coords into the commands stream ! 245: s = stverts[k].s; ! 246: t = stverts[k].t; ! 247: if (!triangles[besttris[0]].facesfront && stverts[k].onseam) ! 248: s += pheader->skinwidth / 2; // on back side ! 249: s = (s + 0.5) / pheader->skinwidth; ! 250: t = (t + 0.5) / pheader->skinheight; ! 251: ! 252: *(float *)&commands[numcommands++] = s; ! 253: *(float *)&commands[numcommands++] = t; ! 254: } ! 255: } ! 256: ! 257: commands[numcommands++] = 0; // end of list marker ! 258: ! 259: Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); ! 260: ! 261: allverts += numorder; ! 262: alltris += pheader->numtris; ! 263: } ! 264: ! 265: ! 266: /* ! 267: ================ ! 268: GL_MakeAliasModelDisplayLists ! 269: ================ ! 270: */ ! 271: void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) ! 272: { ! 273: int i, j; ! 274: maliasgroup_t *paliasgroup; ! 275: int *cmds; ! 276: trivertx_t *verts; ! 277: char cache[MAX_QPATH], fullpath[MAX_OSPATH], *c; ! 278: FILE *f; ! 279: int len; ! 280: byte *data; ! 281: ! 282: aliasmodel = m; ! 283: paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m); ! 284: ! 285: // ! 286: // look for a cached version ! 287: // ! 288: strcpy (cache, "glquake/"); ! 289: COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/")); ! 290: strcat (cache, ".ms2"); ! 291: ! 292: COM_FOpenFile (cache, &f); ! 293: if (f) ! 294: { ! 295: fread (&numcommands, 4, 1, f); ! 296: fread (&numorder, 4, 1, f); ! 297: fread (&commands, numcommands * sizeof(commands[0]), 1, f); ! 298: fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); ! 299: fclose (f); ! 300: } ! 301: else ! 302: { ! 303: // ! 304: // build it from scratch ! 305: // ! 306: Con_Printf ("meshing %s...\n",m->name); ! 307: ! 308: BuildTris (); // trifans or lists ! 309: ! 310: // ! 311: // save out the cached version ! 312: // ! 313: sprintf (fullpath, "%s/%s", com_gamedir, cache); ! 314: f = fopen (fullpath, "wb"); ! 315: if (f) ! 316: { ! 317: fwrite (&numcommands, 4, 1, f); ! 318: fwrite (&numorder, 4, 1, f); ! 319: fwrite (&commands, numcommands * sizeof(commands[0]), 1, f); ! 320: fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); ! 321: fclose (f); ! 322: } ! 323: } ! 324: ! 325: ! 326: // save the data out ! 327: ! 328: paliashdr->poseverts = numorder; ! 329: ! 330: cmds = Hunk_Alloc (numcommands * 4); ! 331: paliashdr->commands = (byte *)cmds - (byte *)paliashdr; ! 332: memcpy (cmds, commands, numcommands * 4); ! 333: ! 334: verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts ! 335: * sizeof(trivertx_t) ); ! 336: paliashdr->posedata = (byte *)verts - (byte *)paliashdr; ! 337: for (i=0 ; i<paliashdr->numposes ; i++) ! 338: for (j=0 ; j<numorder ; j++) ! 339: *verts++ = poseverts[i][vertexorder[j]]; ! 340: } ! 341:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.