do not break tjunctions :P

This commit is contained in:
Rudolf Polzer 2010-09-01 08:30:09 +02:00
parent 526654d3dd
commit f0215523f0

View File

@ -414,10 +414,11 @@ void TriangulatePatchSurface( entity_t *e , mapDrawSurface_t *ds )
} }
#define TINY_AREA 1.0f #define TINY_AREA 1.0f
#define MAXAREA_MAXTRIES 8
int MaxAreaIndexes(bspDrawVert_t *vert, int cnt, int *indexes) int MaxAreaIndexes(bspDrawVert_t *vert, int cnt, int *indexes)
{ {
int r, s, t, bestR = 0, bestS = 1, bestT = 2; int r, s, t, bestR = 0, bestS = 1, bestT = 2;
int i, j; int i, j, try;
double A, bestA = -1, V, bestV = -1; double A, bestA = -1, V, bestV = -1;
vec3_t ab, ac, bc, cross; vec3_t ab, ac, bc, cross;
bspDrawVert_t *buf; bspDrawVert_t *buf;
@ -488,49 +489,102 @@ int MaxAreaIndexes(bspDrawVert_t *vert, int cnt, int *indexes)
printf("value was REALLY bad\n"); printf("value was REALLY bad\n");
*/ */
if(bestA < TINY_AREA) for(try = 0; try < MAXAREA_MAXTRIES; ++try)
/* the biggest triangle is degenerate - then every other is too, and the other algorithms wouldn't generate anything useful either */
return 0;
i = 0;
indexes[i++] = bestR;
indexes[i++] = bestS;
indexes[i++] = bestT;
/* uses 3 */
/* identify the other fragments */
/* full polygon without triangle (bestR,bestS,bestT) = three new polygons:
* 1. bestR..bestS
* 2. bestS..bestT
* 3. bestT..bestR
*/
j = i + MaxAreaIndexes(vert + bestR, bestS - bestR + 1, indexes + i);
for(; i < j; ++i)
indexes[i] += bestR;
/* uses 3*(bestS-bestR+1)-6 */
j = i + MaxAreaIndexes(vert + bestS, bestT - bestS + 1, indexes + i);
for(; i < j; ++i)
indexes[i] += bestS;
/* uses 3*(bestT-bestS+1)-6 */
/* can'bestT recurse this one directly... therefore, buffering */
if(cnt + bestR - bestT + 1 >= 3)
{ {
buf = safe_malloc(sizeof(*vert) * (cnt + bestR - bestT + 1)); if(try)
memcpy(buf, vert + bestT, sizeof(*vert) * (cnt - bestT)); {
memcpy(buf + (cnt - bestT), vert, sizeof(*vert) * (bestR + 1)); bestR = rand() % cnt;
j = i + MaxAreaIndexes(buf, cnt + bestR - bestT + 1, indexes + i); bestS = rand() % cnt;
bestT = rand() % cnt;
if(bestR == bestS || bestR == bestT || bestS == bestT)
continue;
// bubblesort inline
// abc acb bac bca cab cba
if(bestR > bestS)
{
j = bestR;
bestR = bestS;
bestS = j;
}
// abc acb abc bca acb bca
if(bestS > bestT)
{
j = bestS;
bestS = bestT;
bestT = j;
}
// abc abc abc bac abc bac
if(bestR > bestS)
{
j = bestR;
bestR = bestS;
bestS = j;
}
// abc abc abc abc abc abc
VectorSubtract(vert[bestS].xyz, vert[bestR].xyz, ab);
VectorSubtract(vert[bestT].xyz, vert[bestR].xyz, ac);
CrossProduct(ab, ac, cross);
bestA = VectorLength(cross);
}
if(bestA < TINY_AREA)
/* the biggest triangle is degenerate - then every other is too, and the other algorithms wouldn't generate anything useful either */
continue;
i = 0;
indexes[i++] = bestR;
indexes[i++] = bestS;
indexes[i++] = bestT;
/* uses 3 */
/* identify the other fragments */
/* full polygon without triangle (bestR,bestS,bestT) = three new polygons:
* 1. bestR..bestS
* 2. bestS..bestT
* 3. bestT..bestR
*/
j = MaxAreaIndexes(vert + bestR, bestS - bestR + 1, indexes + i);
if(j < 0)
continue;
j += i;
for(; i < j; ++i) for(; i < j; ++i)
indexes[i] = (indexes[i] + bestT) % cnt; indexes[i] += bestR;
/* uses 3*(cnt+bestR-bestT+1)-6 */ /* uses 3*(bestS-bestR+1)-6 */
free(buf); j = MaxAreaIndexes(vert + bestS, bestT - bestS + 1, indexes + i);
if(j < 0)
continue;
j += i;
for(; i < j; ++i)
indexes[i] += bestS;
/* uses 3*(bestT-bestS+1)-6 */
/* can'bestT recurse this one directly... therefore, buffering */
if(cnt + bestR - bestT + 1 >= 3)
{
buf = safe_malloc(sizeof(*vert) * (cnt + bestR - bestT + 1));
memcpy(buf, vert + bestT, sizeof(*vert) * (cnt - bestT));
memcpy(buf + (cnt - bestT), vert, sizeof(*vert) * (bestR + 1));
j = MaxAreaIndexes(buf, cnt + bestR - bestT + 1, indexes + i);
if(j < 0)
{
free(buf);
continue;
}
j += i;
for(; i < j; ++i)
indexes[i] = (indexes[i] + bestT) % cnt;
/* uses 3*(cnt+bestR-bestT+1)-6 */
free(buf);
}
/* together 3 + 3*(cnt+3) - 18 = 3*cnt-6 q.e.d. */
return i;
} }
/* together 3 + 3*(cnt+3) - 18 = 3*cnt-6 q.e.d. */ return -1;
return i;
} }
/* /*
@ -540,6 +594,7 @@ creates a triangle list using max area indexes
void MaxAreaFaceSurface(mapDrawSurface_t *ds) void MaxAreaFaceSurface(mapDrawSurface_t *ds)
{ {
int n;
/* try to early out */ /* try to early out */
if( !ds->numVerts || (ds->type != SURFACE_FACE && ds->type != SURFACE_DECAL) ) if( !ds->numVerts || (ds->type != SURFACE_FACE && ds->type != SURFACE_DECAL) )
return; return;
@ -557,7 +612,16 @@ void MaxAreaFaceSurface(mapDrawSurface_t *ds)
/* do it! */ /* do it! */
ds->numIndexes = 3 * ds->numVerts - 6; ds->numIndexes = 3 * ds->numVerts - 6;
ds->indexes = safe_malloc( ds->numIndexes * sizeof( int ) ); ds->indexes = safe_malloc( ds->numIndexes * sizeof( int ) );
ds->numIndexes = MaxAreaIndexes(ds->verts, ds->numVerts, ds->indexes); n = MaxAreaIndexes(ds->verts, ds->numVerts, ds->indexes);
if(n < 0)
{
/* whatever we do, it's degenerate */
free(ds->indexes);
ds->numIndexes = 0;
StripFaceSurface(ds);
return;
}
ds->numIndexes = n;
/* add to count */ /* add to count */
numMaxAreaSurfaces++; numMaxAreaSurfaces++;