Example #1
0
/*
================
DrawSurfaceForMesh
================
*/
mapDrawSurface_t	*DrawSurfaceForMesh( mesh_t *m ) {
	mapDrawSurface_t	*ds;
	int				i, j;
	mesh_t			*copy;

	// to make valid normals for patches with degenerate edges,
	// we need to make a copy of the mesh and put the aproximating
	// points onto the curve
	copy = CopyMesh( m );
	PutMeshOnCurve( *copy );
	MakeMeshNormals( *copy );
	for ( j = 0 ; j < m->width ; j++ ) {
		for ( i = 0 ; i < m->height ; i++ ) {
			VectorCopy( copy->verts[i*m->width+j].normal, m->verts[i*m->width+j].normal );
		}
	}
	FreeMesh( copy );

	ds = AllocDrawSurf();
	ds->mapBrush = NULL;
	ds->side = NULL;

	ds->patch = qtrue;
	ds->patchWidth = m->width;
	ds->patchHeight = m->height;
	ds->numVerts = ds->patchWidth * ds->patchHeight;
	ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
	memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );

	ds->lightmapNum = -1;
	ds->fogNum = -1;

	return ds;
}
MeshRenderer::~MeshRenderer(){

	FreeMaterial();
	
	FreeMesh();	

	DestroyVertexArrayObject();
}
Example #3
0
/*
====================
FacetsForPatch
====================
*/
void FacetsForPatch( dsurface_t *dsurf, shaderInfo_t *si, surfaceTest_t *test ) {
	int			i, j;
	drawVert_t	*v1, *v2, *v3, *v4;
	int			count;
	mesh_t		srcMesh, *subdivided, *mesh;

	srcMesh.width = dsurf->patchWidth;
	srcMesh.height = dsurf->patchHeight;
	srcMesh.verts = &drawVerts[ dsurf->firstVert ];

	//subdivided = SubdivideMesh( mesh, CURVE_FACET_ERROR, 9999 );
	mesh = SubdivideMesh( srcMesh, 8, 999 );
	PutMeshOnCurve( *mesh );
	MakeMeshNormals( *mesh );

	subdivided = RemoveLinearMeshColumnsRows( mesh );
	FreeMesh(mesh);

	test->patch = qtrue;
	test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2;
	test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets );
	test->shader = si;

	count = 0;
	for ( i = 0 ; i < subdivided->width - 1 ; i++ ) {
		for ( j = 0 ; j < subdivided->height - 1 ; j++ ) {

			v1 = subdivided->verts + j * subdivided->width + i;
			v2 = v1 + 1;
			v3 = v1 + subdivided->width + 1;
			v4 = v1 + subdivided->width;

			if ( CM_GenerateFacetFor4Points( &test->facets[count], v1, v4, v3, v2 ) ) {
				count++;
			} else {
				if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v4, v3 ))
					count++;
				if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v3, v2 ))
					count++;
			}
		}
	}
	test->numFacets = count;
	FreeMesh(subdivided);
}
Example #4
0
bool csMeshList::Remove (iMeshWrapper *obj)
{
  FreeMesh (obj);
  const char* name = obj->QueryObject ()->GetName ();
  CS::Threading::ScopedWriteLock lock(meshLock);
  if (name)
    meshes_hash.Delete (name, obj);
  obj->QueryObject ()->RemoveNameChangeListener (listener);
  list.Delete (obj);
  return true;
}
Example #5
0
void csMeshList::RemoveAll ()
{
  CS::Threading::ScopedWriteLock lock(meshLock);
  size_t i;
  for (i = 0 ; i < list.GetSize () ; i++)
  {
    list[i]->QueryObject ()->RemoveNameChangeListener (listener);
    FreeMesh (list[i]);
  }
  meshes_hash.DeleteAll ();
  list.DeleteAll ();
}
Example #6
0
UNITY_NATIVE_EXPORT void FreeMeshSet( )
{
	if( !g_LoadedDataset )
		return;

	for( auto meshData : g_LoadedDataset->meshes )
	{
		FreeMesh( meshData );
	}

	delete g_LoadedDataset;
	g_LoadedDataset = nullptr;
}
Example #7
0
mesh_t *TransposeMesh( mesh_t *in ) {
    int            w, h;
    mesh_t        *out;

    out = safe_malloc( sizeof( *out ) );
    out->width = in->height;
    out->height = in->width;
    out->verts = safe_malloc( out->width * out->height * sizeof( bspDrawVert_t ) );

    for ( h = 0 ; h < in->height ; h++ ) {
        for ( w = 0 ; w < in->width ; w++ ) {
            out->verts[ w * in->height + h ] = in->verts[ h * in->width + w ];
        }
    }

    FreeMesh( in );

    return out;
}
Example #8
0
File: fog.c Project: otty/cake3
/*
====================
SplitMeshByPlane
====================
*/
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];
	drawVert_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 = 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 = malloc(sizeof(f->verts[0]) * f->width * f->height);

	b = 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 = 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]);
		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 
		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);
}
Example #9
0
File: fog.c Project: otty/cake3
/*
====================
ChopPatchByBrush
====================
*/
qboolean ChopPatchByBrush(drawSurface_t * ds, bspBrush_t * b)
{
	int             i, j;
	side_t         *s;
	plane_t        *plane;
	mesh_t         *outside[MAX_BRUSH_SIDES];
	int             numOutside;
	mesh_t         *m, *front, *back;
	drawSurface_t  *newds;

	m = DrawSurfToMesh(ds);
	numOutside = 0;

	// only split by the top and bottom planes to avoid
	// some messy patch clipping issues

	for(i = 4; i <= 5; i++)
	{
		s = &b->sides[i];
		plane = &mapPlanes[s->planenum];

		SplitMeshByPlane(m, plane->normal, plane->dist, &front, &back);

		if(!back)
		{
			// nothing actually contained inside
			for(j = 0; j < numOutside; j++)
			{
				FreeMesh(outside[j]);
			}
			return qfalse;
		}
		m = back;

		if(front)
		{
			if(numOutside == MAX_BRUSH_SIDES)
			{
				Error("MAX_BRUSH_SIDES");
			}
			outside[numOutside] = front;
			numOutside++;
		}
	}

	// all of outside fragments become seperate drawsurfs
	c_fogPatchFragments += numOutside;
	for(i = 0; i < numOutside; i++)
	{
		newds = DrawSurfaceForMesh(outside[i]);
		newds->shaderInfo = ds->shaderInfo;
		FreeMesh(outside[i]);
	}

	// replace ds with m
	ds->patchWidth = m->width;
	ds->patchHeight = m->height;
	ds->numVerts = m->width * m->height;
	free(ds->verts);
	ds->verts = malloc(ds->numVerts * sizeof(*ds->verts));
	memcpy(ds->verts, m->verts, ds->numVerts * sizeof(*ds->verts));

	FreeMesh(m);

	return qtrue;
}
Example #10
0
static void PopulateWithBSPModel(bspModel_t * model, matrix_t transform)
{
	int             i, j, x, y, pw[5], r, nodeNum;
	bspDrawSurface_t *ds;
	surfaceInfo_t  *info;
	bspDrawVert_t  *verts;
	int            *indexes;
	mesh_t          srcMesh, *mesh, *subdivided;
	traceInfo_t     ti;
	traceWinding_t  tw;


	/* dummy check */
	if(model == NULL || transform == NULL)
		return;

	/* walk the list of surfaces in this model and fill out the info structs */
	for(i = 0; i < model->numBSPSurfaces; i++)
	{
		/* get surface and info */
		ds = &bspDrawSurfaces[model->firstBSPSurface + i];
		info = &surfaceInfos[model->firstBSPSurface + i];
		if(info->si == NULL)
			continue;

		/* no shadows */
		if(!info->castShadows)
			continue;

		/* patchshadows? */
		if(ds->surfaceType == MST_PATCH && patchShadows == qfalse)
			continue;

		/* some surfaces in the bsp might have been tagged as nodraw, with a bogus shader */
		if((bspShaders[ds->shaderNum].contentFlags & noDrawContentFlags) ||
		   (bspShaders[ds->shaderNum].surfaceFlags & noDrawSurfaceFlags))
			continue;

		/* translucent surfaces that are neither alphashadow or lightfilter don't cast shadows */
		if((info->si->compileFlags & C_NODRAW))
			continue;
		if((info->si->compileFlags & C_TRANSLUCENT) &&
		   !(info->si->compileFlags & C_ALPHASHADOW) && !(info->si->compileFlags & C_LIGHTFILTER))
			continue;

		/* setup trace info */
		ti.si = info->si;
		ti.castShadows = info->castShadows;
		ti.surfaceNum = model->firstBSPBrush + i;
		ti.skipGrid = (ds->surfaceType == MST_PATCH);

		/* choose which node (normal or skybox) */
		if(info->parentSurfaceNum >= 0)
		{
			nodeNum = skyboxNodeNum;

			/* sky surfaces in portal skies are ignored */
			if(info->si->compileFlags & C_SKY)
				continue;
		}
		else
			nodeNum = headNodeNum;

		/* setup trace winding */
		memset(&tw, 0, sizeof(tw));
		tw.infoNum = AddTraceInfo(&ti);
		tw.numVerts = 3;

		/* switch on type */
		switch (ds->surfaceType)
		{
				/* handle patches */
			case MST_PATCH:
				/* subdivide the surface */
				srcMesh.width = ds->patchWidth;
				srcMesh.height = ds->patchHeight;
				srcMesh.verts = &bspDrawVerts[ds->firstVert];
				//% subdivided = SubdivideMesh( srcMesh, 8, 512 );
				subdivided = SubdivideMesh2(srcMesh, info->patchIterations);

				/* fit it to the curve and remove colinear verts on rows/columns */
				PutMeshOnCurve(*subdivided);
				mesh = RemoveLinearMeshColumnsRows(subdivided);
				FreeMesh(subdivided);

				/* set verts */
				verts = mesh->verts;

				/* subdivide each quad to place the models */
				for(y = 0; y < (mesh->height - 1); y++)
				{
					for(x = 0; x < (mesh->width - 1); x++)
					{
						/* set indexes */
						pw[0] = x + (y * mesh->width);
						pw[1] = x + ((y + 1) * mesh->width);
						pw[2] = x + 1 + ((y + 1) * mesh->width);
						pw[3] = x + 1 + (y * mesh->width);
						pw[4] = x + (y * mesh->width);	/* same as pw[ 0 ] */

						/* set radix */
						r = (x + y) & 1;

						/* make first triangle */
						VectorCopy(verts[pw[r + 0]].xyz, tw.v[0].xyz);
						Vector2Copy(verts[pw[r + 0]].st, tw.v[0].st);
						VectorCopy(verts[pw[r + 1]].xyz, tw.v[1].xyz);
						Vector2Copy(verts[pw[r + 1]].st, tw.v[1].st);
						VectorCopy(verts[pw[r + 2]].xyz, tw.v[2].xyz);
						Vector2Copy(verts[pw[r + 2]].st, tw.v[2].st);
						MatrixTransformPoint2(transform, tw.v[0].xyz);
						MatrixTransformPoint2(transform, tw.v[1].xyz);
						MatrixTransformPoint2(transform, tw.v[2].xyz);
						FilterTraceWindingIntoNodes_r(&tw, nodeNum);

						/* make second triangle */
						VectorCopy(verts[pw[r + 0]].xyz, tw.v[0].xyz);
						Vector2Copy(verts[pw[r + 0]].st, tw.v[0].st);
						VectorCopy(verts[pw[r + 2]].xyz, tw.v[1].xyz);
						Vector2Copy(verts[pw[r + 2]].st, tw.v[1].st);
						VectorCopy(verts[pw[r + 3]].xyz, tw.v[2].xyz);
						Vector2Copy(verts[pw[r + 3]].st, tw.v[2].st);
						MatrixTransformPoint2(transform, tw.v[0].xyz);
						MatrixTransformPoint2(transform, tw.v[1].xyz);
						MatrixTransformPoint2(transform, tw.v[2].xyz);
						FilterTraceWindingIntoNodes_r(&tw, nodeNum);
					}
				}

				/* free the subdivided mesh */
				FreeMesh(mesh);
				break;

				/* handle triangle surfaces */
			case MST_TRIANGLE_SOUP:
			case MST_PLANAR:
				/* set verts and indexes */
				verts = &bspDrawVerts[ds->firstVert];
				indexes = &bspDrawIndexes[ds->firstIndex];

				/* walk the triangle list */
				for(j = 0; j < ds->numIndexes; j += 3)
				{
					VectorCopy(verts[indexes[j]].xyz, tw.v[0].xyz);
					Vector2Copy(verts[indexes[j]].st, tw.v[0].st);
					VectorCopy(verts[indexes[j + 1]].xyz, tw.v[1].xyz);
					Vector2Copy(verts[indexes[j + 1]].st, tw.v[1].st);
					VectorCopy(verts[indexes[j + 2]].xyz, tw.v[2].xyz);
					Vector2Copy(verts[indexes[j + 2]].st, tw.v[2].st);
					MatrixTransformPoint2(transform, tw.v[0].xyz);
					MatrixTransformPoint2(transform, tw.v[1].xyz);
					MatrixTransformPoint2(transform, tw.v[2].xyz);
					FilterTraceWindingIntoNodes_r(&tw, nodeNum);
				}
				break;

				/* other surface types do not cast shadows */
			default:
				break;
		}
	}
}
Example #11
0
File: fog.c Project: Elzair/q3map2
qboolean ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
	int i, j;
	side_t      *s;
	plane_t     *plane;
	mesh_t      *outside[MAX_BRUSH_SIDES];
	int numOutside;
	mesh_t      *m, *front, *back;
	mapDrawSurface_t    *newds;

	m = DrawSurfToMesh( ds );
	numOutside = 0;

	// only split by the top and bottom planes to avoid
	// some messy patch clipping issues

	for ( i = 4 ; i <= 5 ; i++ ) {
		s = &b->sides[ i ];
		plane = &mapplanes[ s->planenum ];

		SplitMeshByPlane( m, plane->normal, plane->dist, &front, &back );

		if ( !back ) {
			// nothing actually contained inside
			for ( j = 0 ; j < numOutside ; j++ ) {
				FreeMesh( outside[j] );
			}
			return qfalse;
		}
		m = back;

		if ( front ) {
			if ( numOutside == MAX_BRUSH_SIDES ) {
				Error( "MAX_BRUSH_SIDES" );
			}
			outside[ numOutside ] = front;
			numOutside++;
		}
	}

	/* all of outside fragments become seperate drawsurfs */
	numFogPatchFragments += numOutside;
	for ( i = 0; i < numOutside; i++ )
	{
		/* transpose and invert the chopped patch (fixes potential crash. fixme: why?) */
		outside[ i ] = TransposeMesh( outside[ i ] );
		InvertMesh( outside[ i ] );

		/* ydnar: do this the hacky right way */
		newds = AllocDrawSurface( SURFACE_PATCH );
		memcpy( newds, ds, sizeof( *ds ) );
		newds->patchWidth = outside[ i ]->width;
		newds->patchHeight = outside[ i ]->height;
		newds->numVerts = outside[ i ]->width * outside[ i ]->height;
		newds->verts = safe_malloc( newds->numVerts * sizeof( *newds->verts ) );
		memcpy( newds->verts, outside[ i ]->verts, newds->numVerts * sizeof( *newds->verts ) );

		/* free the source mesh */
		FreeMesh( outside[ i ] );
	}

	/* only rejigger this patch if it was chopped */
	//%	Sys_Printf( "Inside: %d x %d\n", m->width, m->height );
	if ( numOutside > 0 ) {
		/* transpose and invert the chopped patch (fixes potential crash. fixme: why?) */
		m = TransposeMesh( m );
		InvertMesh( m );

		/* replace ds with m */
		ds->patchWidth = m->width;
		ds->patchHeight = m->height;
		ds->numVerts = m->width * m->height;
		free( ds->verts );
		ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
		memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
	}

	/* free the source mesh and return */
	FreeMesh( m );
	return qtrue;
}
Example #12
0
void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw )
{
    int                    i, x, y, v, t, pw[ 5 ], r;
    bspDrawSurface_t    *ds;
    surfaceInfo_t        *info;
    bspDrawVert_t        *bogus;
    bspDrawVert_t        *dv[ 4 ];
    mesh_t                src, *subdivided, *mesh;
    float                *radVertexLuxel;
    float                dist;
    vec4_t                plane;
    qboolean            planar;
    radWinding_t        rw;
    
    
    /* get surface */
    ds = &bspDrawSurfaces[ num ];
    info = &surfaceInfos[ num ];
    
    /* construct a bogus vert list with color index stuffed into color[ 0 ] */
    bogus = safe_malloc( ds->numVerts * sizeof( bspDrawVert_t ) );
    memcpy( bogus, &yDrawVerts[ ds->firstVert ], ds->numVerts * sizeof( bspDrawVert_t ) );
    for( i = 0; i < ds->numVerts; i++ )
        bogus[ i ].color[ 0 ][ 0 ] = i;
    
    /* build a subdivided mesh identical to shadow facets for this patch */
    /* this MUST MATCH FacetsForPatch() identically! */
    src.width = ds->patchWidth;
    src.height = ds->patchHeight;
    src.verts = bogus;
    //%    subdivided = SubdivideMesh( src, 8, 512 );
    subdivided = SubdivideMesh2( src, info->patchIterations );
    PutMeshOnCurve( *subdivided );
    //%    MakeMeshNormals( *subdivided );
    mesh = RemoveLinearMeshColumnsRows( subdivided );
    FreeMesh( subdivided );
    free( bogus );
    
    /* FIXME: build interpolation table into color[ 1 ] */
    
    /* fix up color indexes */
    for( i = 0; i < (mesh->width * mesh->height); i++ )
    {
        dv[ 0 ] = &mesh->verts[ i ];
        if( dv[ 0 ]->color[ 0 ][ 0 ] >= ds->numVerts )
            dv[ 0 ]->color[ 0 ][ 0 ] = ds->numVerts - 1;
    }
    
    /* iterate through the mesh quads */
    for( y = 0; y < (mesh->height - 1); y++ )
    {
        for( x = 0; x < (mesh->width - 1); x++ )
        {
            /* set indexes */
            pw[ 0 ] = x + (y * mesh->width);
            pw[ 1 ] = x + ((y + 1) * mesh->width);
            pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
            pw[ 3 ] = x + 1 + (y * mesh->width);
            pw[ 4 ] = x + (y * mesh->width);    /* same as pw[ 0 ] */
            
            /* set radix */
            r = (x + y) & 1;
            
            /* get drawverts */
            dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
            dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
            dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
            dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
            
            /* planar? */
            planar = PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz );
            if( planar )
            {
                dist = DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ];
                if( fabs( dist ) > PLANAR_EPSILON )
                    planar = qfalse;
            }
            
            /* generate a quad */
            if( planar )
            {
                rw.numVerts = 4;
                for( v = 0; v < 4; v++ )
                {
                    /* get most everything */
                    memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) );
                    
                    /* fix colors */
                    for( i = 0; i < MAX_LIGHTMAPS; i++ )
                    {
                        radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
                        VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] );
                        rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ];
                    }
                }
                
                /* subdivide into area lights */
                RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw );
            }
            
            /* generate 2 tris */
            else
            {
                rw.numVerts = 3;
                for( t = 0; t < 2; t++ )
                {
                    for( v = 0; v < 3 + t; v++ )
                    {
                        /* get "other" triangle (stupid hacky logic, but whatevah) */
                        if( v == 1 && t == 1 )
                            v++;

                        /* get most everything */
                        memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) );
                        
                        /* fix colors */
                        for( i = 0; i < MAX_LIGHTMAPS; i++ )
                        {
                            radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
                            VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] );
                            rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ];
                        }
                    }
                    
                    /* subdivide into area lights */
                    RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw );
                }
            }
        }
    }
    
    /* free the mesh */
    FreeMesh( mesh );
}
void TriangulatePatchSurface( mapDrawSurface_t *ds ){
	int iterations, x, y, pw[ 5 ], r;
	mapDrawSurface_t    *dsNew;
	mesh_t src, *subdivided, *mesh;


	/* try to early out */
	if ( ds->numVerts == 0 || ds->type != SURFACE_PATCH || patchMeta == qfalse ) {
		return;
	}

	/* make a mesh from the drawsurf */
	src.width = ds->patchWidth;
	src.height = ds->patchHeight;
	src.verts = ds->verts;
	//%	subdivided = SubdivideMesh( src, 8, 999 );
	iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions );
	subdivided = SubdivideMesh2( src, iterations ); //%	ds->maxIterations

	/* fit it to the curve and remove colinear verts on rows/columns */
	PutMeshOnCurve( *subdivided );
	mesh = RemoveLinearMeshColumnsRows( subdivided );
	FreeMesh( subdivided );
	//% MakeMeshNormals( mesh );

	/* make a copy of the drawsurface */
	dsNew = AllocDrawSurface( SURFACE_META );
	memcpy( dsNew, ds, sizeof( *ds ) );

	/* if the patch is nonsolid, then discard it */
	if ( !( ds->shaderInfo->compileFlags & C_SOLID ) ) {
		ClearSurface( ds );
	}

	/* set new pointer */
	ds = dsNew;

	/* basic transmogrification */
	ds->type = SURFACE_META;
	ds->numIndexes = 0;
	ds->indexes = safe_malloc( mesh->width * mesh->height * 6 * sizeof( int ) );

	/* copy the verts in */
	ds->numVerts = ( mesh->width * mesh->height );
	ds->verts = mesh->verts;

	/* iterate through the mesh quads */
	for ( y = 0; y < ( mesh->height - 1 ); y++ )
	{
		for ( x = 0; x < ( mesh->width - 1 ); x++ )
		{
			/* set indexes */
			pw[ 0 ] = x + ( y * mesh->width );
			pw[ 1 ] = x + ( ( y + 1 ) * mesh->width );
			pw[ 2 ] = x + 1 + ( ( y + 1 ) * mesh->width );
			pw[ 3 ] = x + 1 + ( y * mesh->width );
			pw[ 4 ] = x + ( y * mesh->width );    /* same as pw[ 0 ] */

			/* set radix */
			r = ( x + y ) & 1;

			/* make first triangle */
			ds->indexes[ ds->numIndexes++ ] = pw[ r + 0 ];
			ds->indexes[ ds->numIndexes++ ] = pw[ r + 1 ];
			ds->indexes[ ds->numIndexes++ ] = pw[ r + 2 ];

			/* make second triangle */
			ds->indexes[ ds->numIndexes++ ] = pw[ r + 0 ];
			ds->indexes[ ds->numIndexes++ ] = pw[ r + 2 ];
			ds->indexes[ ds->numIndexes++ ] = pw[ r + 3 ];
		}
	}

	/* free the mesh, but not the verts */
	free( mesh );

	/* add to count */
	numPatchMetaSurfaces++;

	/* classify it */
	ClassifySurfaces( 1, ds );
}
Example #14
0
void ProcessDecals( void )
{
	int			i, j, x, y, pw[ 5 ], r, iterations;
	float			distance;
	vec4_t			projection, plane;
	vec3_t			origin, target, delta;
	entity_t			*e, *e2;
	parseMesh_t		*p;
	mesh_t			*mesh, *subdivided;
	bspDrawVert_t		*dv[4];
	const char		*value;
	
	
	/* note it */
	MsgDev( D_NOTE, "--- ProcessDecals ---\n" );
	
	/* walk entity list */
	for( i = 0; i < numEntities; i++ )
	{
		/* get entity */
		e = &entities[ i ];
		value = ValueForKey( e, "classname" );
		if( com.stricmp( value, "_decal" ) )
			continue;
		
		/* any patches? */
		if( e->patches == NULL )
		{
			MsgDev( D_WARN, "Decal entity without any patch meshes, ignoring.\n" );
			e->epairs = NULL;	/* fixme: leak! */
			continue;
		}
		
		/* find target */
		value = ValueForKey( e, "target" );
		e2 = FindTargetEntity( value );
		
		/* no target? */
		if( e2 == NULL )
		{
			MsgDev( D_WARN, "Decal entity without a valid target, ignoring.\n" );
			continue;
		}
		
		/* walk entity patches */
		for( p = e->patches; p != NULL; p = e->patches )
		{
			/* setup projector */
			if( VectorCompare( e->origin, vec3_origin ) )
			{
				VectorAdd( p->eMins, p->eMaxs, origin );
				VectorScale( origin, 0.5f, origin );
			}
			else VectorCopy( e->origin, origin );
			
			VectorCopy( e2->origin, target );
			VectorSubtract( target, origin, delta );
			
			/* setup projection plane */
			distance = VectorNormalizeLength2( delta, projection );
			projection[ 3 ] = DotProduct( origin, projection );
			
			/* create projectors */
			if( distance > 0.125f )
			{
				/* tesselate the patch */
				iterations = IterationsForCurve( p->longestCurve, patch_subdivide->integer );
				subdivided = SubdivideMesh2( p->mesh, iterations );
				
				/* fit it to the curve and remove colinear verts on rows/columns */
				PutMeshOnCurve( *subdivided );
				mesh = RemoveLinearMeshColumnsRows( subdivided );
				FreeMesh( subdivided );
				
				/* offset by projector origin */
				for( j = 0; j < (mesh->width * mesh->height); j++ )
					VectorAdd( mesh->verts[ j ].xyz, e->origin, mesh->verts[ j ].xyz );
				
				/* iterate through the mesh quads */
				for( y = 0; y < (mesh->height - 1); y++ )
				{
					for( x = 0; x < (mesh->width - 1); x++ )
					{
						/* set indexes */
						pw[ 0 ] = x + (y * mesh->width);
						pw[ 1 ] = x + ((y + 1) * mesh->width);
						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
						pw[ 3 ] = x + 1 + (y * mesh->width);
						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
						
						/* set radix */
						r = (x + y) & 1;
						
						/* get drawverts */
						dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
						dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
						dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
						dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
						
						/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
						plane[ 0 ] = 0.0f;	/* stupid msvc */
						if( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) &&
							fabs( DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ] ) <= PLANAR_EPSILON )
						{
							/* make a quad projector */
							MakeDecalProjector( p->shaderInfo, projection, distance, 4, dv );
						}
						else
						{
							/* make first triangle */
							MakeDecalProjector( p->shaderInfo, projection, distance, 3, dv );
							
							/* make second triangle */
							dv[ 1 ] = dv[ 2 ];
							dv[ 2 ] = dv[ 3 ];
							MakeDecalProjector( p->shaderInfo, projection, distance, 3, dv );
						}
					}
				}
				
				/* clean up */
				Mem_Free( mesh );
			}
			
			/* remove patch from entity (fixme: leak!) */
			e->patches = p->next;
			
			/* push patch to worldspawn (enable this to debug projectors) */
#if 0
			p->next = entities[ 0 ].patches;
			entities[ 0 ].patches = p;
#endif
		}
	}
	
	/* emit some stats */
	MsgDev( D_NOTE, "%9d decal projectors\n", numProjectors );
}
Example #15
0
void AllocateLightmapForPatch( mapDrawSurface_t *ds ) {
	int			i, j, k;
	drawVert_t	*verts;
	int			w, h;
	int			x, y;
	float		s, t;
	mesh_t		mesh, *subdividedMesh, *tempMesh, *newmesh;
	int			widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize;

	verts = ds->verts;

	mesh.width = ds->patchWidth;
	mesh.height = ds->patchHeight;
	mesh.verts = verts;
	newmesh = SubdivideMesh( mesh, 8, 999 );

	PutMeshOnCurve( *newmesh );
	tempMesh = RemoveLinearMeshColumnsRows( newmesh );
	FreeMesh(newmesh);

	ssize = samplesize;
	if (ds->shaderInfo->lightmapSampleSize)
		ssize = ds->shaderInfo->lightmapSampleSize;

#ifdef LIGHTMAP_PATCHSHIFT
	subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable);
#else
	subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable);
#endif

	w = subdividedMesh->width;
	h = subdividedMesh->height;

#ifdef LIGHTMAP_PATCHSHIFT
	w++;
	h++;
#endif

	FreeMesh(subdividedMesh);

	// allocate the lightmap
	c_exactLightmap += w * h;

	if ( !AllocLMBlock( w, h, &x, &y ) ) {
		PrepareNewLightmap();
		if ( !AllocLMBlock( w, h, &x, &y ) ) {
			Error("Entity %i, brush %i: Lightmap allocation failed", 
				ds->mapBrush->entitynum, ds->mapBrush->brushnum );
		}
	}

#ifdef LIGHTMAP_PATCHSHIFT
	w--;
	h--;
#endif

	// set the lightmap texture coordinates in the drawVerts
	ds->lightmapNum = numLightmaps - 1;
	ds->lightmapWidth = w;
	ds->lightmapHeight = h;
	ds->lightmapX = x;
	ds->lightmapY = y;

	for ( i = 0 ; i < ds->patchWidth ; i++ ) {
		for ( k = 0 ; k < w ; k++ ) {
			if ( originalWidths[k] >= i ) {
				break;
			}
		}
		if (k >= w)
			k = w-1;
		s = x + k;
		for ( j = 0 ; j < ds->patchHeight ; j++ ) {
			for ( k = 0 ; k < h ; k++ ) {
				if ( originalHeights[k] >= j ) {
					break;
				}
			}
			if (k >= h)
				k = h-1;
			t = y + k;
			verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH;
			verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT;
		}
	}
}
Example #16
0
static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds )
{
	int			x, y, pw[ 5 ], r, iterations;
	vec4_t		plane;
	float		d;
	mesh_t		src, *mesh, *subdivided;
	winding_t	*w;
	
	
	/* backface check */
	if( ds->planar )
	{
		VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
		plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
		d = DotProduct( dp->planes[ 0 ], plane );
		if( d < -0.0001f )
			return;
	}
	
	/* tesselate the patch */
	src.width = ds->patchWidth;
	src.height = ds->patchHeight;
	src.verts = ds->verts;
	iterations = IterationsForCurve( ds->longestCurve, patch_subdivide->integer );
	subdivided = SubdivideMesh2( src, iterations );
	
	/* fit it to the curve and remove colinear verts on rows/columns */
	PutMeshOnCurve( *subdivided );
	mesh = RemoveLinearMeshColumnsRows( subdivided );
	FreeMesh( subdivided );
	
	/* iterate through the mesh quads */
	for( y = 0; y < (mesh->height - 1); y++ )
	{
		for( x = 0; x < (mesh->width - 1); x++ )
		{
			/* set indexes */
			pw[ 0 ] = x + (y * mesh->width);
			pw[ 1 ] = x + ((y + 1) * mesh->width);
			pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
			pw[ 3 ] = x + 1 + (y * mesh->width);
			pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
			
			/* set radix */
			r = (x + y) & 1;
			
			/* generate decal for first triangle */
			w = AllocWinding( 3 );
			w->numpoints = 3;
			VectorCopy( mesh->verts[ pw[ r + 0 ] ].xyz, w->p[ 0 ] );
			VectorCopy( mesh->verts[ pw[ r + 1 ] ].xyz, w->p[ 1 ] );
			VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 2 ] );
			ProjectDecalOntoWinding( dp, ds, w );
			
			/* generate decal for second triangle */
			w = AllocWinding( 3 );
			w->numpoints = 3;
			VectorCopy( mesh->verts[ pw[ r + 0 ] ].xyz, w->p[ 0 ] );
			VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 1 ] );
			VectorCopy( mesh->verts[ pw[ r + 3 ] ].xyz, w->p[ 2 ] );
			ProjectDecalOntoWinding( dp, ds, w );
		}
	}
	
	/* clean up */
	Mem_Free( mesh );
}
Example #17
0
void ProcessDecals( void )
{
	int					i, j, x, y, pw[ 5 ], r, iterations, smoothNormals;
	float				distance, lightmapScale, backfaceAngle;
	vec4_t				projection, plane;
	vec3_t				origin, target, delta, lightmapAxis;
	vec3_t              minlight, minvertexlight, ambient, colormod;
	entity_t			*e, *e2;
	parseMesh_t			*p;
	mesh_t				*mesh, *subdivided;
	bspDrawVert_t		*dv[ 4 ];
	const char			*value;
	
	
	/* note it */
	Sys_FPrintf( SYS_VRB, "--- ProcessDecals ---\n" );

	/* no decals */
	if (nodecals)
	{
		for( i = 0; i < numEntities; i++ )
		{	
			/* get entity */
			e = &entities[ i ];
			value = ValueForKey( e, "classname" );
			if( Q_stricmp( value, "_decal" ) && Q_stricmp( value, "misc_decal" ) )
				continue;

			/* clear entity patches */
			e->patches = NULL; // fixme: LEAK!
		}
		return;
	}
	
	/* walk entity list */
	for( i = 0; i < numEntities; i++ )
	{
		/* get entity */
		e = &entities[ i ];
		value = ValueForKey( e, "classname" );
		if( Q_stricmp( value, "_decal" ) && Q_stricmp( value, "misc_decal" ) )
			continue;
		
		/* any patches? */
		if( e->patches == NULL )
		{
			Sys_Warning( e->mapEntityNum, "Decal entity without any patch meshes, ignoring." );
			e->epairs = NULL;	/* fixme: leak! */
			continue;
		}
		
		/* find target */
		value = ValueForKey( e, "target" );
		e2 = FindTargetEntity( value );
		
		/* no target? */
		if( e2 == NULL )
		{
			Sys_Warning( e->mapEntityNum, "Decal entity without a valid target, ignoring." );
			continue;
		}

		/* vortex: get lightmap scaling value for this entity */
		GetEntityLightmapScale( e, &lightmapScale, 0);

		/* vortex: get lightmap axis for this entity */
		GetEntityLightmapAxis( e, lightmapAxis, NULL );

		/* vortex: per-entity normal smoothing */
		GetEntityNormalSmoothing( e, &smoothNormals, 0);

		/* vortex: per-entity _minlight, _ambient, _color, _colormod */
		GetEntityMinlightAmbientColor( e, NULL, minlight, minvertexlight, ambient, colormod, qtrue );
		
		/* vortex: _backfacecull */
		if ( KeyExists(e, "_backfacecull") )
			backfaceAngle = FloatForKey(e, "_backfacecull");
		else if ( KeyExists(e, "_bfc") )
			backfaceAngle = FloatForKey(e, "_bfc");
		else
			backfaceAngle = 90.0f;

		/* walk entity patches */
		for( p = e->patches; p != NULL; p = e->patches )
		{
			/* setup projector */
			if( VectorCompare( e->origin, vec3_origin ) )
			{
				VectorAdd( p->eMins, p->eMaxs, origin );
				VectorScale( origin, 0.5f, origin );
			}
			else
				VectorCopy( e->origin, origin );
			
			VectorCopy( e2->origin, target );
			VectorSubtract( target, origin, delta );
			
			/* setup projection plane */
			distance = VectorNormalize( delta, projection );
			projection[ 3 ] = DotProduct( origin, projection );
			
			/* create projectors */
			if( distance > 0.125f )
			{
				/* tesselate the patch */
				iterations = IterationsForCurve( p->longestCurve, patchSubdivisions );
				subdivided = SubdivideMesh2( p->mesh, iterations );
				
				/* fit it to the curve and remove colinear verts on rows/columns */
				PutMeshOnCurve( *subdivided );
				mesh = RemoveLinearMeshColumnsRows( subdivided );
				FreeMesh( subdivided );
				
				/* offset by projector origin */
				for( j = 0; j < (mesh->width * mesh->height); j++ )
					VectorAdd( mesh->verts[ j ].xyz, e->origin, mesh->verts[ j ].xyz );
				
				/* iterate through the mesh quads */
				for( y = 0; y < (mesh->height - 1); y++ )
				{
					for( x = 0; x < (mesh->width - 1); x++ )
					{
						/* set indexes */
						pw[ 0 ] = x + (y * mesh->width);
						pw[ 1 ] = x + ((y + 1) * mesh->width);
						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
						pw[ 3 ] = x + 1 + (y * mesh->width);
						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
						
						/* set radix */
						r = (x + y) & 1;
						
						/* get drawverts */
						dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
						dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
						dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
						dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
						
						/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
						plane[ 0 ] = 0.0f;	/* stupid msvc */
						if( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) && fabs( DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ] ) <= PLANAR_EPSILON )
						{
							/* make a quad projector */
							MakeDecalProjector( i, p->shaderInfo, projection, distance, 4, dv, cos(backfaceAngle / 180.0f * Q_PI), lightmapScale, lightmapAxis, minlight, minvertexlight, ambient, colormod, smoothNormals);
						}
						else
						{
							/* make first triangle */
							MakeDecalProjector( i, p->shaderInfo, projection, distance, 3, dv, cos(backfaceAngle / 180.0f * Q_PI), lightmapScale, lightmapAxis, minlight, minvertexlight, ambient, colormod, smoothNormals);
							
							/* make second triangle */
							dv[ 1 ] = dv[ 2 ];
							dv[ 2 ] = dv[ 3 ];
							MakeDecalProjector( i, p->shaderInfo, projection, distance, 3, dv, cos(backfaceAngle / 180.0f * Q_PI), lightmapScale, lightmapAxis, minlight, minvertexlight, ambient, colormod, smoothNormals);
						}
					}
				}
				
				/* clean up */
				free( mesh );
			}
			
			/* remove patch from entity (fixme: leak!) */
			e->patches = p->next;
			
			/* push patch to worldspawn (enable this to debug projectors) */
			#if 0
				p->next = entities[ 0 ].patches;
				entities[ 0 ].patches = p;
			#endif
		}
	}
	
	/* emit some stats */
	Sys_FPrintf( SYS_VRB, "%9d decal projectors\n", numProjectors );
}