Ejemplo n.º 1
0
/*
 * @brief
 */
static void FinishSubdividePatch(patch_t *patch, patch_t *newp) {

	VectorCopy(patch->normal, newp->normal);

	VectorCopy(patch->light, newp->light);

	patch->area = WindingArea(patch->winding);

	if (patch->area < 1.0)
		patch->area = 1.0;

	newp->area = WindingArea(newp->winding);

	if (newp->area < 1.0)
		newp->area = 1.0;

	WindingCenter(patch->winding, patch->origin);

	// nudge the patch origin out along the normal
	VectorMA(patch->origin, 2.0, patch->normal, patch->origin);

	WindingCenter(newp->winding, newp->origin);

	// nudge the patch origin out along the normal
	VectorMA(newp->origin, 2.0, newp->normal, newp->origin);
}
Ejemplo n.º 2
0
void MarkLeakTrail (portal_t *n2)
{
    int		i, j;
    vec3_t	p1, p2, dir;
    float	len;
    portal_t *n1;

    if (hullnum)
        return;

    n1 = prevleaknode;
    prevleaknode = n2;

    if (!n1)
        return;

    WindingCenter (n2->winding, p1);
    WindingCenter (n1->winding, p2);

    fprintf (linefile, "%f %f %f\n", p1[0], p1[1], p1[2]);

    VectorSubtract (p2, p1, dir);
    len = VectorLength (dir);
    VectorNormalize (dir);

    while (len > 2)
    {
        fprintf (pointfile,"%f %f %f\n", p1[0], p1[1], p1[2]);
        for (i=0 ; i<3 ; i++)
            p1[i] += dir[i]*2;
        len -= 2;
    }

}
Ejemplo n.º 3
0
void FinishSplit( patch_t *patch, patch_t *newp ){
	dleaf_t     *leaf;

	VectorCopy( patch->baselight, newp->baselight );
	VectorCopy( patch->totallight, newp->totallight );
	VectorCopy( patch->reflectivity, newp->reflectivity );
	newp->plane = patch->plane;
	newp->sky = patch->sky;

	patch->area = WindingArea( patch->winding );
	newp->area = WindingArea( newp->winding );

	if ( patch->area <= 1 ) {
		patch->area = 1;
	}
	if ( newp->area <= 1 ) {
		newp->area = 1;
	}

	WindingCenter( patch->winding, patch->origin );
	VectorAdd( patch->origin, patch->plane->normal, patch->origin );
	leaf = Rad_PointInLeaf( patch->origin );
	patch->cluster = leaf->cluster;
	if ( patch->cluster == -1 ) {
		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" );
	}

	WindingCenter( newp->winding, newp->origin );
	VectorAdd( newp->origin, newp->plane->normal, newp->origin );
	leaf = Rad_PointInLeaf( newp->origin );
	newp->cluster = leaf->cluster;
	if ( newp->cluster == -1 ) {
		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" );
	}
}
Ejemplo n.º 4
0
/*
 * @brief
 */
static void BuildPatch(int32_t fn, winding_t *w) {
	patch_t *patch;
	d_bsp_plane_t *plane;

	patch = (patch_t *) Mem_Malloc(sizeof(*patch));

	face_patches[fn] = patch;

	patch->face = &d_bsp.faces[fn];
	patch->winding = w;

	// resolve the normal
	plane = &d_bsp.planes[patch->face->plane_num];

	if (patch->face->side)
		VectorNegate(plane->normal, patch->normal);
	else
		VectorCopy(plane->normal, patch->normal);

	WindingCenter(w, patch->origin);

	// nudge the origin out along the normal
	VectorMA(patch->origin, 2.0, patch->normal, patch->origin);

	patch->area = WindingArea(w);

	if (patch->area < 1.0) // clamp area
		patch->area = 1.0;

	EmissiveLight(patch); // surface light
}
Ejemplo n.º 5
0
/**
 * @brief Build a patch for a surface that emits light
 * @note This is called in the lighting stage
 * @param fn The face number of the surface that emits the light
 * @param w The winding
 * @sa BuildLights
 */
static void BuildPatch (int fn, winding_t* w)
{
	patch_t* patch;
	dBspPlane_t* plane;

	patch = Mem_AllocType(patch_t);

	face_patches[fn] = patch;

	patch->face = &curTile->faces[fn];
	patch->winding = w;

	/* resolve the normal */
	plane = &curTile->planes[patch->face->planenum];

	if (patch->face->side)
		VectorNegate(plane->normal, patch->normal);
	else
		VectorCopy(plane->normal, patch->normal);

	WindingCenter(w, patch->origin);

	/* nudge the origin out along the normal */
	VectorMA(patch->origin, 2.0, patch->normal, patch->origin);

	patch->area = WindingArea(w);

	if (patch->area < 1.0)  /* clamp area */
		patch->area = 1.0;

	EmissiveLight(patch);  /* surface light */
}
Ejemplo n.º 6
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_FlipAreaFaces(tmp_area_t *tmparea)
{
	int side;
	tmp_face_t *face;
	plane_t *plane;
	vec3_t wcenter, acenter = {0, 0, 0};
	//winding_t *w;
	float n;

	for (n = 0, face = tmparea->tmpfaces; face; face = face->next[side])
	{
		if (!face->frontarea) Error("face %d has no front area\n", face->num);
		//side of the face the area is on
		side = face->frontarea != tmparea;
		WindingCenter(face->winding, wcenter);
		VectorAdd(acenter, wcenter, acenter);
		n++;
	} //end for
	n = 1 / n;
	VectorScale(acenter, n, acenter);
	for (face = tmparea->tmpfaces; face; face = face->next[side])
	{
		//side of the face the area is on
		side = face->frontarea != tmparea;

		plane = &mapplanes[face->planenum ^ side];

		if (DotProduct(plane->normal, acenter) - plane->dist < 0)
		{
			Log_Print("area %d face %d flipped: front area %d, back area %d\n", tmparea->areanum, face->num,
					face->frontarea ? face->frontarea->areanum : 0,
					face->backarea ? face->backarea->areanum : 0);
			/*
			face->planenum = face->planenum ^ 1;
			w = face->winding;
			face->winding = ReverseWinding(w);
			FreeWinding(w);
			*/
		} //end if
#ifdef L_DEBUG
		{
			float dist;
			vec3_t normal;

			//check if the winding plane is the same as the face plane
			WindingPlane(face->winding, normal, &dist);
			plane = &mapplanes[face->planenum];
			if (fabs(dist - plane->dist) > 0.4 ||
					fabs(normal[0] - plane->normal[0]) > 0.0001 ||
					fabs(normal[1] - plane->normal[1]) > 0.0001 ||
					fabs(normal[2] - plane->normal[2]) > 0.0001)
			{
				Log_Write("area %d face %d winding plane unequal to face plane\r\n",
											tmparea->areanum, face->num);
			} //end if
		}
#endif
	} //end for
} //end of the function AAS_FlipAreaFaces
Ejemplo n.º 7
0
/*
=============
LeakFile

Finds the shortest possible chain of portals
that leads from the outside leaf to a specifically
occupied leaf
=============
*/
void LeakFile (tree_t *tree)
{
	vec3_t	mid;
	FILE	*linefile;
	char	filename[1024];
	node_t	*node;
	int		count;

	if (!tree->outside_node.occupied)
		return;

	qprintf ("--- LeakFile ---\n");

	//
	// write the points to the file
	//
	sprintf (filename, "%s.lin", source);
	qprintf ("%s\n", filename);
	linefile = fopen (filename, "w");
	if (!linefile)
		Error ("Couldn't open %s\n", filename);

	count = 0;
	node = &tree->outside_node;
	while (node->occupied > 1)
	{
		int			next;
		portal_t	*p, *nextportal;
		node_t		*nextnode;
		int			s;

		// find the best portal exit
		next = node->occupied;
		for (p=node->portals ; p ; p = p->next[!s])
		{
			s = (p->nodes[0] == node);
			if (p->nodes[s]->occupied
				&& p->nodes[s]->occupied < next)
			{
				nextportal = p;
				nextnode = p->nodes[s];
				next = nextnode->occupied;
			}
		}
		node = nextnode;
		WindingCenter (nextportal->winding, mid);
		fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
		count++;
	}
	// add the occupant center
	GetVectorForKey (node->occupant, "origin", mid);

	fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
	qprintf ("%5i point linefile\n", count+1);

	fclose (linefile);
}
Ejemplo n.º 8
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_CheckArea(tmp_area_t *tmparea)
{
	int side;
	tmp_face_t *face;
	plane_t *plane;
	vec3_t wcenter, acenter = {0, 0, 0};
	vec3_t normal;
	float n, dist;

	if (tmparea->invalid) Log_Print("AAS_CheckArea: invalid area\n");
	for (n = 0, face = tmparea->tmpfaces; face; face = face->next[side])
	{
		//side of the face the area is on
		side = face->frontarea != tmparea;
		WindingCenter(face->winding, wcenter);
		VectorAdd(acenter, wcenter, acenter);
		n++;
	} //end for
	n = 1 / n;
	VectorScale(acenter, n, acenter);
	for (face = tmparea->tmpfaces; face; face = face->next[side])
	{
		//side of the face the area is on
		side = face->frontarea != tmparea;

#ifdef L_DEBUG
		if (WindingError(face->winding))
		{
			Log_Write("AAS_CheckArea: area %d face %d: %s\r\n", tmparea->areanum,
						face->num, WindingErrorString());
		} //end if
#endif

		plane = &mapplanes[face->planenum ^ side];

		if (DotProduct(plane->normal, acenter) - plane->dist < 0)
		{
			Log_Print("AAS_CheckArea: area %d face %d is flipped\n", tmparea->areanum, face->num);
			Log_Print("AAS_CheckArea: area %d center is %f %f %f\n", tmparea->areanum, acenter[0], acenter[1], acenter[2]);
		} //end if
		//check if the winding plane is the same as the face plane
		WindingPlane(face->winding, normal, &dist);
		plane = &mapplanes[face->planenum];
#ifdef L_DEBUG
		if (fabs(dist - plane->dist) > 0.4 ||
				fabs(normal[0] - plane->normal[0]) > 0.0001 ||
				fabs(normal[1] - plane->normal[1]) > 0.0001 ||
				fabs(normal[2] - plane->normal[2]) > 0.0001)
		{
			Log_Write("AAS_CheckArea: area %d face %d winding plane unequal to face plane\r\n",
										tmparea->areanum, face->num);
		} //end if
#endif
	} //end for
} //end of the function AAS_CheckArea
Ejemplo n.º 9
0
//-----------------------------------------------------------------------------
// Display portal error
//-----------------------------------------------------------------------------
static void DisplayPortalError( portal_t *p, int viscontents )
{
	char contents[3][1024];
	PrintBrushContentsToString( p->nodes[0]->contents, contents[0], sizeof( contents[0] ) );
	PrintBrushContentsToString( p->nodes[1]->contents, contents[1], sizeof( contents[1] ) );
	PrintBrushContentsToString( viscontents, contents[2], sizeof( contents[2] ) );

	Vector center;
	WindingCenter( p->winding, center );
	Warning( "\nFindPortalSide: Couldn't find a good match for which brush to assign to a portal near (%.1f %.1f %.1f)\n", center.x, center.y, center.z);
	Warning( "Leaf 0 contents: %s\n", contents[0] );
	Warning( "Leaf 1 contents: %s\n", contents[1] );
	Warning( "viscontents (node 0 contents ^ node 1 contents): %s\n", contents[2] );
	Warning( "This means that none of the brushes in leaf 0 or 1 that touches the portal has %s\n", contents[2] );
	Warning( "Check for a huge brush enclosing the coordinates above that has contents %s\n", contents[2] );
	Warning( "Candidate brush IDs: " );

	CUtlVector<int> listed;
	for (int j=0 ; j<2 ; j++)
	{
		node_t *n = p->nodes[j];
		for (bspbrush_t *bb=n->brushlist ; bb ; bb=bb->next)
		{
			mapbrush_t *brush = bb->original;
			if ( brush->contents & viscontents )
			{
				if ( listed.Find( brush->brushnum ) == -1 )
				{
					listed.AddToTail( brush->brushnum );
					Warning( "Brush %d: ", brush->id );
				}
			}
		}
	}
	Warning( "\n\n" );
}
Ejemplo n.º 10
0
//-----------------------------------------------------------------------------
// Purpose: Recursively filter a face into the tree leaving references to the
//			original face in any visible leaves that a clipped fragment falls
//			into.
// Input  : *node - current head of tree
//			*face - clipped face fragment
//			*original - unclipped original face
// Output : Returns true if any references were left
//-----------------------------------------------------------------------------
bool MergeFace_r( node_t *node, face_t *face, face_t *original )
{
	bool referenced = false;

	if ( node->planenum == PLANENUM_LEAF )
	{
		if ( node->contents & CONTENTS_SOLID )
		{
			FreeFace( face );
			return false;
		}

		leafface_t *plist = new leafface_t;
		plist->pFace = original;
		plist->pNext = node->leaffacelist;
		node->leaffacelist = plist;

		referenced = true;
	}
	else
	{
		// UNDONE: Don't copy the faces each time unless it's necessary!?!?!
		plane_t *plane = &g_MainMap->mapplanes[node->planenum];
		winding_t *frontwinding, *backwinding, *onwinding;

		Vector offset;
		WindingCenter( face->w, offset );

		// UNDONE: Export epsilon from original face clipping code
		ClassifyWindingEpsilon_Offset(face->w, plane->normal, plane->dist, 0.001, &frontwinding, &backwinding, &onwinding, -offset);

		if ( onwinding )
		{
			// face is in the split plane, go down the appropriate side according to the facing direction
			assert( frontwinding == NULL );
			assert( backwinding == NULL );

			if ( DotProduct( g_MainMap->mapplanes[face->planenum].normal, g_MainMap->mapplanes[node->planenum].normal ) > 0 )
			{
				frontwinding = onwinding;
			}
			else
			{
				backwinding = onwinding;
			}
		}

		if ( frontwinding )
		{
			face_t *tmp = NewFaceFromFace( face );
			tmp->w = frontwinding;
			referenced = MergeFace_r( node->children[0], tmp, original );
		}
		if ( backwinding )
		{
			face_t *tmp = NewFaceFromFace( face );
			tmp->w = backwinding;
			bool test = MergeFace_r( node->children[1], tmp, original );
			referenced = referenced || test;
		}
	}
	FreeFace( face );

	return referenced;
}
Ejemplo n.º 11
0
void LeakFile(tree_t * tree)
#endif
{
	vec3_t          mid;
	FILE           *linefile;
	char            filename[1024];
	node_t         *node;
	int             count;

#if defined(USE_XML)
	xmlNodePtr      xml_node, point;
#endif

	if(!tree->outside_node.occupied)
	{
#if defined(USE_XML)
		return NULL;
#endif
	}

	Sys_FPrintf(SYS_VRB, "--- LeakFile ---\n");

	//
	// write the points to the file
	//
	sprintf(filename, "%s.lin", source);
	linefile = fopen(filename, "w");
	if(!linefile)
		Error("Couldn't open %s", filename);

#if defined(USE_XML)
	xml_node = xmlNewNode(NULL, "polyline");
#endif

	count = 0;
	node = &tree->outside_node;
	while(node->occupied > 1)
	{
		int             next;
		portal_t       *p, *nextportal = NULL; // STFU, compiler
		node_t         *nextnode = NULL; // STFU, compiler
		int             s;

		// find the best portal exit
		next = node->occupied;
		for(p = node->portals; p; p = p->next[!s])
		{
			s = (p->nodes[0] == node);
			if(p->nodes[s]->occupied && p->nodes[s]->occupied < next)
			{
				nextportal = p;
				nextnode = p->nodes[s];
				next = nextnode->occupied;
			}
		}
		node = nextnode;
		WindingCenter(nextportal->winding, mid);
		fprintf(linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
#if defined(USE_XML)
		point = xml_NodeForVec(mid);
		xmlAddChild(xml_node, point);
#endif
		count++;
	}
	// add the occupant center
	GetVectorForKey(node->occupant, "origin", mid);

	fprintf(linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
#if defined(USE_XML)
	point = xml_NodeForVec(mid);
	xmlAddChild(xml_node, point);
#endif
	Sys_FPrintf(SYS_VRB, "%9d point linefile\n", count + 1);

	fclose(linefile);

#if defined(USE_XML)
	return xml_node;
#endif
}
Ejemplo n.º 12
0
/*
=============
SubdividePatch
=============
*/
void	SubdividePatch (patch_t *patch)
{
	winding_t *w, *o1, *o2;
	vec3_t	total;
	vec3_t	split;
	vec_t	dist;
	vec_t	widest = -1;
	int		i, j, widest_axis = -1;
	int		subdivide_it = 0;
	vec_t	v;
	patch_t	*newp;

	w = patch->winding;

	VectorSubtract (patch->maxs, patch->mins, total);
	for (i=0 ; i<3 ; i++)
	{
		if ( total[i] > widest )
			{
			widest_axis = i;
			widest = total[i];
			}
		if ( total[i] > patch->chop
		  || (patch->face_maxs[i] == patch->maxs[i] || patch->face_mins[i] == patch->mins[i] )
		  && total[i] > minchop )
		{
			subdivide_it = 1;
		}
	}

	if ( subdivide_it )
	{
		//
		// split the winding
		//
		VectorCopy (vec3_origin, split);
		split[widest_axis] = 1;
		dist = (patch->mins[widest_axis] + patch->maxs[widest_axis])*0.5f;
		ClipWinding (w, split, dist, &o1, &o2);

		//
		// create a new patch
		//
		if (num_patches == MAX_PATCHES)
			Error ("MAX_PATCHES");
		newp = &patches[num_patches];

		newp->next = patch->next;
		patch->next = newp;

		patch->winding = o1;
		newp->winding = o2;

		VectorCopy( patch->face_mins, newp->face_mins );
		VectorCopy( patch->face_maxs, newp->face_maxs );

		VectorCopy( patch->baselight, newp->baselight );
		VectorCopy( patch->directlight, newp->directlight );
		VectorCopy( patch->totallight, newp->totallight );
		VectorCopy( patch->reflectivity, newp->reflectivity );
		newp->plane = patch->plane;
		newp->sky = patch->sky;
		newp->chop = patch->chop;
		newp->faceNumber = patch->faceNumber;

		num_patches++;

		patch->area = WindingArea (patch->winding);
		newp->area = WindingArea (newp->winding);

		WindingCenter (patch->winding, patch->origin);
		WindingCenter (newp->winding, newp->origin);

#ifdef PHONG_NORMAL_PATCHES
// This seems to be a bad idea for some reason.  Leave it turned off for now.
		// Set (Copy or Calculate) the synthetic normal for these new patches
		VectorAdd (patch->origin, patch->plane->normal, patch->origin);
		VectorAdd (newp->origin, newp->plane->normal, newp->origin);
		GetPhongNormal( patch->faceNumber, patch->origin, patch->normal );
		GetPhongNormal( newp->faceNumber, newp->origin, newp->normal );
		VectorSubtract( patch->origin, patch->plane->normal, patch->origin);
		VectorSubtract( newp->origin, newp->plane->normal, newp->origin);
#else
		VectorCopy( patch->plane->normal, patch->normal );
		VectorCopy( newp->plane->normal, newp->normal );
#endif
		VectorAdd( patch->origin, patch->normal, patch->origin );
		VectorAdd( newp->origin, newp->normal, newp->origin );

		WindingBounds(patch->winding, patch->mins, patch->maxs);
		WindingBounds(newp->winding, newp->mins, newp->maxs);

		// Subdivide patch even more if on the edge of the face; this is a hack!
		VectorSubtract (patch->maxs, patch->mins, total);
		if ( total[0] < patch->chop && total[1] < patch->chop && total[2] < patch->chop )
			for ( i=0; i<3; i++ )
				if ( (patch->face_maxs[i] == patch->maxs[i] || patch->face_mins[i] == patch->mins[i] )
				  && total[i] > minchop )
				{
					patch->chop = max( minchop, patch->chop / 2 );
					break;
				}

		SubdividePatch (patch);

		// Subdivide patch even more if on the edge of the face; this is a hack!
		VectorSubtract (newp->maxs, newp->mins, total);
		if ( total[0] < newp->chop && total[1] < newp->chop && total[2] < newp->chop )
			for ( i=0; i<3; i++ )
				if ( (newp->face_maxs[i] == newp->maxs[i] || newp->face_mins[i] == newp->mins[i] )
				  && total[i] > minchop )
				{
					newp->chop = max( minchop, newp->chop / 2 );
					break;
				}

		SubdividePatch (newp);
	}
}
Ejemplo n.º 13
0
void MakePatchForFace (int fn, winding_t *w)
{
	dface_t *f = dfaces + fn;

	// No patches at all for the sky!
	if ( !IsSky(f) )
	{
		float	area;
		patch_t		*patch;
		vec3_t light;
		vec3_t		centroid = {0,0,0};
		int			i, j;
		texinfo_t	*tx = &texinfo[f->texinfo];

		area = WindingArea (w);
		totalarea += area;

		patch = &patches[num_patches];
		if (num_patches == MAX_PATCHES)
			Error ("num_patches == MAX_PATCHES");
		patch->next = face_patches[fn];
		face_patches[fn] = patch;

		if ( texscale )
			{
			// Compute the texture "scale" in s,t
			for( i=0; i<2; i++ )
				{
				patch->scale[i] = 0.0;
				for( j=0; j<3; j++ )
					patch->scale[i] += tx->vecs[i][j] * tx->vecs[i][j];
				patch->scale[i] = sqrt( patch->scale[i] );
				}
			}
		else
			patch->scale[0] = patch->scale[1] = 1.0;

		patch->area = area;
		patch->chop = maxchop / (int)((patch->scale[0]+patch->scale[1])/2);
		patch->sky = FALSE;

		patch->winding = w;

		if (f->side)
			patch->plane = &backplanes[f->planenum];
		else
			patch->plane = &dplanes[f->planenum];

		for (j=0 ; j<f->numedges ; j++)
		{
			int edge = dsurfedges[ f->firstedge + j ];
			int edge2 = dsurfedges[ j==f->numedges-1 ? f->firstedge : f->firstedge + j + 1 ];

			if (edge > 0)
			{
				VectorAdd( dvertexes[dedges[edge].v[0]].point, centroid, centroid );
				VectorAdd( dvertexes[dedges[edge].v[1]].point, centroid, centroid );
			}
			else
			{
				VectorAdd( dvertexes[dedges[-edge].v[1]].point, centroid, centroid );
				VectorAdd( dvertexes[dedges[-edge].v[0]].point, centroid, centroid );
			}
		}
		VectorScale( centroid, 1.0 / (f->numedges * 2), centroid );
		VectorCopy( centroid, face_centroids[fn] );  // Save them for generating the patch normals later.

		patch->faceNumber = fn;
		WindingCenter (w, patch->origin);

#ifdef PHONG_NORMAL_PATCHES
// This seems to be a bad idea for some reason.  Leave it turned off for now.
		VectorAdd (patch->origin, patch->plane->normal, patch->origin);
		GetPhongNormal( fn, patch->origin, patch->normal );
		VectorSubtract (patch->origin, patch->plane->normal, patch->origin);
		if ( !VectorCompare( patch->plane->normal, patch->normal ) )
			patch->chop = 16; // Chop it fine!
#else
		VectorCopy( patch->plane->normal, patch->normal );
#endif
		VectorAdd (patch->origin, patch->normal, patch->origin);

		WindingBounds (w, patch->face_mins, patch->face_maxs);
		VectorCopy( patch->face_mins, patch->mins );
		VectorCopy( patch->face_maxs, patch->maxs );

		BaseLightForFace( f, light, patch->reflectivity );
		VectorCopy( light, patch->totallight );
		VectorCopy( light, patch->baselight );

		// Chop all texlights very fine.
		if ( !VectorCompare( light, vec3_origin ) )
			patch->chop = extra ? minchop / 2 : minchop;

		num_patches++;
	}
}
Ejemplo n.º 14
0
static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si,
    float scale, float subdivide, qboolean original, radWinding_t *rw, clipWork_t *cw )
{
    int                i, style;
    float            dist, area, value;
    vec3_t            mins, maxs, normal, d1, d2, cross, color, gradient;
    light_t            *light, *splash;
    winding_t        *w;
    
    
    /* dummy check */
    if( rw == NULL || rw->numVerts < 3 )
        return;
    
    /* get bounds for winding */
    ClearBounds( mins, maxs );
    for( i = 0; i < rw->numVerts; i++ )
        AddPointToBounds( rw->verts[ i ].xyz, mins, maxs );
    
    /* subdivide if necessary */
    for( i = 0; i < 3; i++ )
    {
        if( maxs[ i ] - mins[ i ] > subdivide )
        {
            radWinding_t    front, back;
            
            
            /* make axial plane */
            VectorClear( normal );
            normal[ i ] = 1;
            dist = (maxs[ i ] + mins[ i ]) * 0.5f;
            
            /* clip the winding */
            RadClipWindingEpsilon( rw, normal, dist, RADIOSITY_CLIP_EPSILON, &front, &back, cw );
            
            /* recurse */
            RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qfalse, &front, cw );
            RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qfalse, &back, cw );
            return;
        }
    }
    
    /* check area */
    area = 0.0f;
    for( i = 2; i < rw->numVerts; i++ )
    {
        VectorSubtract( rw->verts[ i - 1 ].xyz, rw->verts[ 0 ].xyz, d1 );
        VectorSubtract( rw->verts[ i ].xyz, rw->verts[ 0 ].xyz, d2 );
        CrossProduct( d1, d2, cross );
        area += 0.5f * VectorLength( cross );
    }
    if( area < 1.0f || area > 20000000.0f )
        return;
    
    /* more subdivision may be necessary */
    if( bouncing )
    {
        /* get color sample for the surface fragment */
        RadSample( lightmapNum, ds, lm, si, rw, color, gradient, &style );
        
        /* if color gradient is too high, subdivide again */
        if( subdivide > minDiffuseSubdivide && 
            (gradient[ 0 ] > RADIOSITY_MAX_GRADIENT || gradient[ 1 ] > RADIOSITY_MAX_GRADIENT || gradient[ 2 ] > RADIOSITY_MAX_GRADIENT) )
        {
            RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, (subdivide / 2.0f), qfalse, rw, cw );
            return;
        }
    }
    
    /* create a regular winding and an average normal */
    w = AllocWinding( rw->numVerts );
    w->numpoints = rw->numVerts;
    VectorClear( normal );
    for( i = 0; i < rw->numVerts; i++ )
    {
        VectorCopy( rw->verts[ i ].xyz, w->p[ i ] );
        VectorAdd( normal, rw->verts[ i ].normal, normal );
    }
    VectorScale( normal, (1.0f / rw->numVerts), normal );
    if( VectorNormalize( normal, normal ) == 0.0f )
        return;
    
    /* early out? */
    if( bouncing && VectorLength( color ) < RADIOSITY_MIN )
        return;
    
    /* debug code */
    //%    Sys_Printf( "Size: %d %d %d\n", (int) (maxs[ 0 ] - mins[ 0 ]), (int) (maxs[ 1 ] - mins[ 1 ]), (int) (maxs[ 2 ] - mins[ 2 ]) );
    //%    Sys_Printf( "Grad: %f %f %f\n", gradient[ 0 ], gradient[ 1 ], gradient[ 2 ] );
    
    /* increment counts */
    numDiffuseLights++;
    switch( ds->surfaceType )
    {
        case MST_PLANAR:
            numBrushDiffuseLights++;
            break;
        
        case MST_TRIANGLE_SOUP:
            numTriangleDiffuseLights;
            break;
        
        case MST_PATCH:
            numPatchDiffuseLights++;
            break;
    }
    
    /* create a light */
    light = safe_malloc( sizeof( *light ) );
    memset( light, 0, sizeof( *light ) );
    
    /* attach it */
    ThreadLock();
    light->next = lights;
    lights = light;
    ThreadUnlock();
    
    /* initialize the light */
    light->flags = LIGHT_AREA_DEFAULT;
    light->type = EMIT_AREA;
    light->si = si;
    light->fade = 1.0f;
    light->w = w;
    
    /* set falloff threshold */
    light->falloffTolerance = falloffTolerance;
    
    /* bouncing light? */
    if( bouncing == qfalse )
    {
        /* handle first-pass lights in normal q3a style */
        value = si->value;
        light->photons = value * area * areaScale;
        light->add = value * formFactorValueScale * areaScale;
        VectorCopy( si->color, light->color );
        VectorScale( light->color, light->add, light->emitColor );
        light->style = noStyles ? LS_NORMAL : si->lightStyle;
        if( light->style < LS_NORMAL || light->style >= LS_NONE )
            light->style = LS_NORMAL;
        
        /* set origin */
        VectorAdd( mins, maxs, light->origin );
        VectorScale( light->origin, 0.5f, light->origin );
        
        /* nudge it off the plane a bit */
        VectorCopy( normal, light->normal );
        VectorMA( light->origin, 1.0f, light->normal, light->origin );
        light->dist = DotProduct( light->origin, normal );
        
        /* optionally create a point splashsplash light for first pass */
        if( original && si->backsplashFraction > 0 )
        {
            /* allocate a new point light */
            splash = safe_malloc( sizeof( *splash ) );
            memset( splash, 0, sizeof( *splash ) );
            splash->next = lights;
            lights = splash;
            
            /* set it up */
            splash->flags = LIGHT_Q3A_DEFAULT;
            splash->type = EMIT_POINT;
            splash->photons = light->photons * si->backsplashFraction;
            splash->fade = 1.0f;
            splash->si = si;
            VectorMA( light->origin, si->backsplashDistance, normal, splash->origin );
            VectorCopy( si->color, splash->color );
            splash->falloffTolerance = falloffTolerance;
            splash->style = noStyles ? LS_NORMAL : light->style;
            
            /* add to counts */
            numPointLights++;
        }
    }
    else
    {
        /* handle bounced light (radiosity) a little differently */
        value = RADIOSITY_VALUE * si->bounceScale * 0.375f;
        light->photons = value * area * bounceScale;
        light->add = value * formFactorValueScale * bounceScale;
        VectorCopy( color, light->color );
        VectorScale( light->color, light->add, light->emitColor );
        light->style = noStyles ? LS_NORMAL : style;
        if( light->style < LS_NORMAL || light->style >= LS_NONE )
            light->style = LS_NORMAL;
        
        /* set origin */
        WindingCenter( w, light->origin );
        
        /* nudge it off the plane a bit */
        VectorCopy( normal, light->normal );
        VectorMA( light->origin, 1.0f, light->normal, light->origin );
        light->dist = DotProduct( light->origin, normal );
    }
    
    /* emit light from both sides? */
    if( si->compileFlags & C_FOG || si->twoSided )
        light->flags |= LIGHT_TWOSIDED;
    
    //%    Sys_Printf( "\nAL: C: (%6f, %6f, %6f) [%6f] N: (%6f, %6f, %6f) %s\n",
    //%        light->color[ 0 ], light->color[ 1 ], light->color[ 2 ], light->add,
    //%        light->normal[ 0 ], light->normal[ 1 ], light->normal[ 2 ],
    //%        light->si->shader );
}
Ejemplo n.º 15
0
void MakePatchForFace( int fn, winding_t *w ){
	dface_t *f;
	float area;
	patch_t     *patch;
	dplane_t    *pl;
	int i;
	vec3_t color;
	dleaf_t     *leaf;

	f = &dfaces[fn];

	area = WindingArea( w );
	totalarea += area;

	patch = &patches[num_patches];
	if ( num_patches == MAX_PATCHES ) {
		Error( "num_patches == MAX_PATCHES" );
	}
	patch->next = face_patches[fn];
	face_patches[fn] = patch;

	patch->winding = w;

	if ( f->side ) {
		patch->plane = &backplanes[f->planenum];
	}
	else{
		patch->plane = &dplanes[f->planenum];
	}
	if ( face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] ) { // origin offset faces must create new planes
		if ( numplanes + fakeplanes >= MAX_MAP_PLANES ) {
			Error( "numplanes + fakeplanes >= MAX_MAP_PLANES" );
		}
		pl = &dplanes[numplanes + fakeplanes];
		fakeplanes++;

		*pl = *( patch->plane );
		pl->dist += DotProduct( face_offset[fn], pl->normal );
		patch->plane = pl;
	}

	WindingCenter( w, patch->origin );
	VectorAdd( patch->origin, patch->plane->normal, patch->origin );
	leaf = Rad_PointInLeaf( patch->origin );
	patch->cluster = leaf->cluster;
	if ( patch->cluster == -1 ) {
		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" );
	}

	patch->area = area;
	if ( patch->area <= 1 ) {
		patch->area = 1;
	}
	patch->sky = IsSky( f );

	VectorCopy( texture_reflectivity[f->texinfo], patch->reflectivity );

	// non-bmodel patches can emit light
	if ( fn < dmodels[0].numfaces ) {
		BaseLightForFace( f, patch->baselight );

		ColorNormalize( patch->reflectivity, color );

		for ( i = 0 ; i < 3 ; i++ )
			patch->baselight[i] *= color[i];

		VectorCopy( patch->baselight, patch->totallight );
	}
	num_patches++;
}
Ejemplo n.º 16
0
radial_t *BuildPatchRadial( int facenum )
{
	int             j;
	radial_t        *rad;
	CPatch	        *patch;
	faceneighbor_t  *fn;
	Vector2D        mins, maxs;
	bool			needsBumpmap, neighborNeedsBumpmap;

	needsBumpmap = texinfo[g_pFaces[facenum].texinfo].flags & SURF_BUMPLIGHT ? true : false;

	rad = AllocateRadial( facenum );
	
	fn = &faceneighbor[ rad->facenum ];

	CPatch *pNextPatch;

	if( g_FacePatches.Element( rad->facenum ) != g_FacePatches.InvalidIndex() )
	{
		for( patch = &g_Patches.Element( g_FacePatches.Element( rad->facenum ) ); patch; patch = pNextPatch )
		{
			// next patch
			pNextPatch = NULL;
			if( patch->ndxNext != g_Patches.InvalidIndex() )
			{
				pNextPatch = &g_Patches.Element( patch->ndxNext );
			}
			
			// skip patches with children
			if (patch->child1 != g_Patches.InvalidIndex() )
				continue;
			
			// get the range of patch lightmap texture coords
			int ndxPatch = patch - g_Patches.Base();
			PatchLightmapCoordRange( rad, ndxPatch, mins, maxs );
			
			if (patch->numtransfers == 0)
			{
				// Error, using patch that was never evaluated or has no samples
				// patch->totallight[1] = 255;
			}
			
			//
			// displacement surface patch origin position and normal vectors have been changed to
			// represent the displacement surface position and normal -- for radial "blending"
			// we need to get the base surface patch origin!
			//
			if( ValidDispFace( &g_pFaces[facenum] ) )
			{
				Vector patchOrigin;
				WindingCenter (patch->winding, patchOrigin );
				AddBouncedToRadial( rad, patchOrigin, mins, maxs, patch->totallight.light,  
					needsBumpmap, needsBumpmap );			
			}
			else
			{
				AddBouncedToRadial( rad, patch->origin, mins, maxs, patch->totallight.light, 
					needsBumpmap, needsBumpmap );
			}
		}
	}

	for (j=0 ; j<fn->numneighbors; j++)
	{
		if( g_FacePatches.Element( fn->neighbor[j] ) != g_FacePatches.InvalidIndex() )
		{
			for( patch = &g_Patches.Element( g_FacePatches.Element( fn->neighbor[j] ) ); patch; patch = pNextPatch )
			{
				// next patch
				pNextPatch = NULL;
				if( patch->ndxNext != g_Patches.InvalidIndex() )
				{
					pNextPatch = &g_Patches.Element( patch->ndxNext );
				}
				
				// skip patches with children
				if (patch->child1 != g_Patches.InvalidIndex() )
					continue;
				
				// get the range of patch lightmap texture coords
				int ndxPatch = patch - g_Patches.Base();
				PatchLightmapCoordRange( rad, ndxPatch, mins, maxs  );
				
				neighborNeedsBumpmap = texinfo[g_pFaces[facenum].texinfo].flags & SURF_BUMPLIGHT ? true : false;
				
				//
				// displacement surface patch origin position and normal vectors have been changed to
				// represent the displacement surface position and normal -- for radial "blending"
				// we need to get the base surface patch origin!
				//
				if( ValidDispFace( &g_pFaces[fn->neighbor[j]] ) )
				{
					Vector patchOrigin;
					WindingCenter (patch->winding, patchOrigin );
					AddBouncedToRadial( rad, patchOrigin, mins, maxs, patch->totallight.light, 
						needsBumpmap, needsBumpmap );			
				}
				else
				{
					AddBouncedToRadial( rad, patch->origin, mins, maxs, patch->totallight.light,
						needsBumpmap, needsBumpmap );
				}
			}
		}
	}

	return rad;
}