Esempio n. 1
0
File: fog.c Progetto: Elzair/q3map2
void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, mesh_t **back ){
	int w, h, split;
	float d[MAX_PATCH_SIZE][MAX_PATCH_SIZE];
	bspDrawVert_t   *dv, *v1, *v2;
	int c_front, c_back, c_on;
	mesh_t  *f, *b;
	int i;
	float frac;
	int frontAprox, backAprox;

	for ( i = 0 ; i < 2 ; i++ ) {
		dv = in->verts;
		c_front = 0;
		c_back = 0;
		c_on = 0;
		for ( h = 0 ; h < in->height ; h++ ) {
			for ( w = 0 ; w < in->width ; w++, dv++ ) {
				d[h][w] = DotProduct( dv->xyz, normal ) - dist;
				if ( d[h][w] > ON_EPSILON ) {
					c_front++;
				}
				else if ( d[h][w] < -ON_EPSILON ) {
					c_back++;
				}
				else {
					c_on++;
				}
			}
		}

		*front = NULL;
		*back = NULL;

		if ( !c_front ) {
			*back = in;
			return;
		}
		if ( !c_back ) {
			*front = in;
			return;
		}

		// find a split point
		split = -1;
		for ( w = 0 ; w < in->width - 1 ; w++ ) {
			if ( ( d[0][w] < 0 ) != ( d[0][w + 1] < 0 ) ) {
				if ( split == -1 ) {
					split = w;
					break;
				}
			}
		}

		if ( split == -1 ) {
			if ( i == 1 ) {
				Sys_FPrintf( SYS_VRB, "No crossing points in patch\n" );
				*front = in;
				return;
			}

			in = TransposeMesh( in );
			InvertMesh( in );
			continue;
		}

		// make sure the split point stays the same for all other rows
		for ( h = 1 ; h < in->height ; h++ ) {
			for ( w = 0 ; w < in->width - 1 ; w++ ) {
				if ( ( d[h][w] < 0 ) != ( d[h][w + 1] < 0 ) ) {
					if ( w != split ) {
						Sys_Printf( "multiple crossing points for patch -- can't clip\n" );
						*front = in;
						return;
					}
				}
			}
			if ( ( d[h][split] < 0 ) == ( d[h][split + 1] < 0 ) ) {
				Sys_Printf( "differing crossing points for patch -- can't clip\n" );
				*front = in;
				return;
			}
		}

		break;
	}


	// create two new meshes
	f = safe_malloc( sizeof( *f ) );
	f->width = split + 2;
	if ( !( f->width & 1 ) ) {
		f->width++;
		frontAprox = 1;
	}
	else {
		frontAprox = 0;
	}
	if ( f->width > MAX_PATCH_SIZE ) {
		Error( "MAX_PATCH_SIZE after split" );
	}
	f->height = in->height;
	f->verts = safe_malloc( sizeof( f->verts[0] ) * f->width * f->height );

	b = safe_malloc( sizeof( *b ) );
	b->width = in->width - split;
	if ( !( b->width & 1 ) ) {
		b->width++;
		backAprox = 1;
	}
	else {
		backAprox = 0;
	}
	if ( b->width > MAX_PATCH_SIZE ) {
		Error( "MAX_PATCH_SIZE after split" );
	}
	b->height = in->height;
	b->verts = safe_malloc( sizeof( b->verts[0] ) * b->width * b->height );

	if ( d[0][0] > 0 ) {
		*front = f;
		*back = b;
	}
	else {
		*front = b;
		*back = f;
	}

	// distribute the points
	for ( w = 0 ; w < in->width ; w++ ) {
		for ( h = 0 ; h < in->height ; h++ ) {
			if ( w <= split ) {
				f->verts[ h * f->width + w ] = in->verts[ h * in->width + w ];
			}
			else {
				b->verts[ h * b->width + w - split + backAprox ] = in->verts[ h * in->width + w ];
			}
		}
	}

	// clip the crossing line
	for ( h = 0; h < in->height; h++ )
	{
		dv = &f->verts[ h * f->width + split + 1 ];
		v1 = &in->verts[ h * in->width + split ];
		v2 = &in->verts[ h * in->width + split + 1 ];

		frac = d[h][split] / ( d[h][split] - d[h][split + 1] );

		/* interpolate */
		//%	for( i = 0; i < 10; i++ )
		//%		dv->xyz[ i ] = v1->xyz[ i ] + frac * (v2->xyz[ i ] - v1->xyz[ i ]);
		//%	dv->xyz[10] = 0;	// set all 4 colors to 0
		LerpDrawVertAmount( v1, v2, frac, dv );

		if ( frontAprox ) {
			f->verts[ h * f->width + split + 2 ] = *dv;
		}
		b->verts[ h * b->width ] = *dv;
		if ( backAprox ) {
			b->verts[ h * b->width + 1 ] = *dv;
		}
	}

	/*
	   PrintMesh( in );
	   Sys_Printf("\n");
	   PrintMesh( f );
	   Sys_Printf("\n");
	   PrintMesh( b );
	   Sys_Printf("\n");
	 */

	FreeMesh( in );
}
Esempio n. 2
0
/*
=================
SubdivideMeshQuads
=================
*/
mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *widthtable, int *heighttable )
{
    int                i, j, k, w, h, maxsubdivisions, subdivisions;
    vec3_t            dir;
    float            length, maxLength, amount;
    mesh_t            out;
    bspDrawVert_t    expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];

    out.width = in->width;
    out.height = in->height;

    for ( i = 0 ; i < in->width ; i++ ) {
        for ( j = 0 ; j < in->height ; j++ ) {
            expand[j][i] = in->verts[j*in->width+i];
        }
    }

    if (maxsize > MAX_EXPANDED_AXIS)
        Error("SubdivideMeshQuads: maxsize > MAX_EXPANDED_AXIS");

    // horizontal subdivisions

    maxsubdivisions = (maxsize - in->width) / (in->width - 1);

    for ( w = 0, j = 0 ; w < in->width - 1; w++, j += subdivisions + 1) {
        maxLength = 0;
        for ( i = 0 ; i < out.height ; i++ ) {
            VectorSubtract(expand[i][j+1].xyz, expand[i][j].xyz, dir);
            length = VectorLength( dir );
            if (length > maxLength) {
                maxLength = length;
            }
        }
        
        subdivisions = (int) (maxLength / minLength);
        if (subdivisions > maxsubdivisions)
            subdivisions = maxsubdivisions;

        widthtable[w] = subdivisions + 1;
        if (subdivisions <= 0)
            continue;

        out.width += subdivisions;

        for ( i = 0 ; i < out.height ; i++ ) {
            for ( k = out.width - 1 ; k > j + subdivisions; k-- ) {
                expand[i][k] = expand[i][k-subdivisions];
            }
            for (k = 1; k <= subdivisions; k++)
            {
                amount = (float) k / (subdivisions + 1);
                LerpDrawVertAmount(&expand[i][j], &expand[i][j+subdivisions+1], amount, &expand[i][j+k]);
            }
        }
    }

    maxsubdivisions = (maxsize - in->height) / (in->height - 1);

    for ( h = 0, j = 0 ; h < in->height - 1; h++, j += subdivisions + 1) {
        maxLength = 0;
        for ( i = 0 ; i < out.width ; i++ ) {
            VectorSubtract(expand[j+1][i].xyz, expand[j][i].xyz, dir);
            length = VectorLength( dir );
            if (length  > maxLength) {
                maxLength = length;
            }
        }
        
        subdivisions = (int) (maxLength / minLength);
        if (subdivisions > maxsubdivisions)
            subdivisions = maxsubdivisions;

        heighttable[h] = subdivisions + 1;
        if (subdivisions <= 0)
            continue;

        out.height += subdivisions;

        for ( i = 0 ; i < out.width ; i++ ) {
            for ( k = out.height - 1 ; k > j + subdivisions; k-- ) {
                expand[k][i] = expand[k-subdivisions][i];
            }
            for (k = 1; k <= subdivisions; k++)
            {
                amount = (float) k / (subdivisions + 1);
                LerpDrawVertAmount(&expand[j][i], &expand[j+subdivisions+1][i], amount, &expand[j+k][i]);
            }
        }
    }

    // collapse the verts
    out.verts = &expand[0][0];
    for ( i = 1 ; i < out.height ; i++ ) {
        memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) );
    }

    return CopyMesh(&out);
}
void FixMetaTJunctions( void ){
	int i, j, k, f, fOld, start, vertIndex, triIndex, numTJuncs;
	metaTriangle_t  *tri, *newTri;
	shaderInfo_t    *si;
	bspDrawVert_t   *a, *b, *c, junc;
	float dist, amount;
	vec3_t pt;
	vec4_t plane;
	edge_t edges[ 3 ];


	/* this code is crap; revisit later */
	return;

	/* note it */
	Sys_FPrintf( SYS_VRB, "--- FixMetaTJunctions ---\n" );

	/* init pacifier */
	fOld = -1;
	start = I_FloatTime();

	/* walk triangle list */
	numTJuncs = 0;
	for ( i = 0; i < numMetaTriangles; i++ )
	{
		/* get triangle */
		tri = &metaTriangles[ i ];

		/* print pacifier */
		f = 10 * i / numMetaTriangles;
		if ( f != fOld ) {
			fOld = f;
			Sys_FPrintf( SYS_VRB, "%d...", f );
		}

		/* attempt to early out */
		si = tri->si;
		if ( ( si->compileFlags & C_NODRAW ) || si->autosprite || si->notjunc ) {
			continue;
		}

		/* calculate planes */
		VectorCopy( tri->plane, plane );
		plane[ 3 ] = tri->plane[ 3 ];
		CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] );
		CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] );
		CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] );

		/* walk meta vert list */
		for ( j = 0; j < numMetaVerts; j++ )
		{
			/* get vert */
			VectorCopy( metaVerts[ j ].xyz, pt );

			/* debug code: darken verts */
			if ( i == 0 ) {
				VectorSet( metaVerts[ j ].color[ 0 ], 8, 8, 8 );
			}

			/* determine if point lies in the triangle's plane */
			dist = DotProduct( pt, plane ) - plane[ 3 ];
			if ( fabs( dist ) > TJ_PLANE_EPSILON ) {
				continue;
			}

			/* skip this point if it already exists in the triangle */
			for ( k = 0; k < 3; k++ )
			{
				if ( fabs( pt[ 0 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 0 ] ) <= TJ_POINT_EPSILON &&
					 fabs( pt[ 1 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 1 ] ) <= TJ_POINT_EPSILON &&
					 fabs( pt[ 2 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 2 ] ) <= TJ_POINT_EPSILON ) {
					break;
				}
			}
			if ( k < 3 ) {
				continue;
			}

			/* walk edges */
			for ( k = 0; k < 3; k++ )
			{
				/* ignore bogus edges */
				if ( fabs( edges[ k ].kingpinLength ) < TJ_EDGE_EPSILON ) {
					continue;
				}

				/* determine if point lies on the edge */
				dist = DotProduct( pt, edges[ k ].plane ) - edges[ k ].plane[ 3 ];
				if ( fabs( dist ) > TJ_EDGE_EPSILON ) {
					continue;
				}

				/* determine how far along the edge the point lies */
				amount = ( pt[ edges[ k ].kingpin ] - edges[ k ].origin[ edges[ k ].kingpin ] ) / edges[ k ].kingpinLength;
				if ( amount <= 0.0f || amount >= 1.0f ) {
					continue;
				}

				#if 0
				dist = DotProduct( pt, edges[ k ].edge ) - edges[ k ].edge[ 3 ];
				if ( dist <= -0.0f || dist >= edges[ k ].length ) {
					continue;
				}
				amount = dist / edges[ k ].length;
				#endif

				/* debug code: brighten this point */
				//%	metaVerts[ j ].color[ 0 ][ 0 ] += 5;
				//%	metaVerts[ j ].color[ 0 ][ 1 ] += 4;
				VectorSet( metaVerts[ tri->indexes[ k ] ].color[ 0 ], 255, 204, 0 );
				VectorSet( metaVerts[ tri->indexes[ ( k + 1 ) % 3 ] ].color[ 0 ], 255, 204, 0 );


				/* the edge opposite the zero-weighted vertex was hit, so use that as an amount */
				a = &metaVerts[ tri->indexes[ k % 3 ] ];
				b = &metaVerts[ tri->indexes[ ( k + 1 ) % 3 ] ];
				c = &metaVerts[ tri->indexes[ ( k + 2 ) % 3 ] ];

				/* make new vert */
				LerpDrawVertAmount( a, b, amount, &junc );
				VectorCopy( pt, junc.xyz );

				/* compare against existing verts */
				if ( VectorCompare( junc.xyz, a->xyz ) || VectorCompare( junc.xyz, b->xyz ) || VectorCompare( junc.xyz, c->xyz ) ) {
					continue;
				}

				/* see if we can just re-use the existing vert */
				if ( !memcmp( &metaVerts[ j ], &junc, sizeof( junc ) ) ) {
					vertIndex = j;
				}
				else
				{
					/* find new vertex (note: a and b are invalid pointers after this) */
					firstSearchMetaVert = numMetaVerts;
					vertIndex = FindMetaVertex( &junc );
					if ( vertIndex < 0 ) {
						continue;
					}
				}

				/* make new triangle */
				triIndex = AddMetaTriangle();
				if ( triIndex < 0 ) {
					continue;
				}

				/* get triangles */
				tri = &metaTriangles[ i ];
				newTri = &metaTriangles[ triIndex ];

				/* copy the triangle */
				memcpy( newTri, tri, sizeof( *tri ) );

				/* fix verts */
				tri->indexes[ ( k + 1 ) % 3 ] = vertIndex;
				newTri->indexes[ k ] = vertIndex;

				/* recalculate edges */
				CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] );
				CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] );
				CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] );

				/* debug code */
				metaVerts[ vertIndex ].color[ 0 ][ 0 ] = 255;
				metaVerts[ vertIndex ].color[ 0 ][ 1 ] = 204;
				metaVerts[ vertIndex ].color[ 0 ][ 2 ] = 0;

				/* add to counter and end processing of this vert */
				numTJuncs++;
				break;
			}
		}
	}

	/* print time */
	Sys_FPrintf( SYS_VRB, " (%d)\n", (int) ( I_FloatTime() - start ) );

	/* emit some stats */
	Sys_FPrintf( SYS_VRB, "%9d T-junctions added\n", numTJuncs );
}