Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

aas_facemerging.c (9058B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 #include "qbsp.h"
     24 #include "../botlib/aasfile.h"
     25 #include "aas_create.h"
     26 
     27 //===========================================================================
     28 //
     29 // Parameter:				-
     30 // Returns:					-
     31 // Changes Globals:		-
     32 //===========================================================================
     33 int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2)
     34 {
     35 	winding_t *neww;
     36 
     37 #ifdef DEBUG
     38 	if (!face1->winding) Error("face1 %d without winding", face1->num);
     39 	if (!face2->winding) Error("face2 %d without winding", face2->num);
     40 #endif //DEBUG
     41 	//
     42 	if (face1->faceflags != face2->faceflags) return false;
     43 	//NOTE: if the front or back area is zero this doesn't mean there's
     44 	//a real area. It means there's solid at that side of the face
     45 	//if both faces have the same front area
     46 	if (face1->frontarea == face2->frontarea)
     47 	{
     48 		//if both faces have the same back area
     49 		if (face1->backarea == face2->backarea)
     50 		{
     51 			//if the faces are in the same plane
     52 			if (face1->planenum == face2->planenum)
     53 			{
     54 				//if they have both a front and a back area (no solid on either side)
     55 				if (face1->frontarea && face1->backarea)
     56 				{
     57 					neww = MergeWindings(face1->winding, face2->winding,
     58 								mapplanes[face1->planenum].normal);
     59 				} //end if
     60 				else
     61 				{
     62 					//this function is to be found in l_poly.c
     63 					neww = TryMergeWinding(face1->winding, face2->winding,
     64 									mapplanes[face1->planenum].normal);
     65 				} //end else
     66 				if (neww)
     67 				{
     68 					FreeWinding(face1->winding);
     69 					face1->winding = neww;
     70 					if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea);
     71 					if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea);
     72 					AAS_FreeTmpFace(face2);
     73 					return true;
     74 				} //end if
     75 			} //end if
     76 			else if ((face1->planenum & ~1) == (face2->planenum & ~1))
     77 			{
     78 				Log_Write("face %d and %d, same front and back area but flipped planes\r\n",
     79 							face1->num, face2->num);
     80 			} //end if
     81 		} //end if
     82 	} //end if
     83 	return false;
     84 } //end of the function AAS_TryMergeFaces
     85 /*
     86 int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2)
     87 {
     88 	winding_t *neww;
     89 
     90 #ifdef DEBUG
     91 	if (!face1->winding) Error("face1 %d without winding", face1->num);
     92 	if (!face2->winding) Error("face2 %d without winding", face2->num);
     93 #endif //DEBUG
     94 	//if the faces are in the same plane
     95 	if ((face1->planenum & ~1) != (face2->planenum & ~1)) return false;
     96 //	if (face1->planenum != face2->planenum) return false;
     97 	//NOTE: if the front or back area is zero this doesn't mean there's
     98 	//a real area. It means there's solid at that side of the face
     99 	//if both faces have the same front area
    100 	if (face1->frontarea != face2->frontarea ||
    101 		face1->backarea != face2->backarea)
    102 	{
    103 		if (!face1->frontarea || !face1->backarea ||
    104 				!face2->frontarea || !face2->backarea) return false;
    105 		else if (face1->frontarea != face2->backarea ||
    106 					face1->backarea != face2->frontarea) return false;
    107 //		return false;
    108 	} //end if
    109 	//this function is to be found in l_poly.c
    110 	neww = TryMergeWinding(face1->winding, face2->winding,
    111 					mapplanes[face1->planenum].normal);
    112 	if (!neww) return false;
    113 	//
    114 	FreeWinding(face1->winding);
    115 	face1->winding = neww;
    116 	//remove face2
    117 	if (face2->frontarea)
    118 		AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->frontarea]);
    119 	if (face2->backarea)
    120 		AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->backarea]);
    121 	return true;
    122 } //end of the function AAS_TryMergeFaces*/
    123 //===========================================================================
    124 //
    125 // Parameter:				-
    126 // Returns:					-
    127 // Changes Globals:		-
    128 //===========================================================================
    129 void AAS_MergeAreaFaces(void)
    130 {
    131 	int num_facemerges = 0;
    132 	int side1, side2, restart;
    133 	tmp_area_t *tmparea, *lasttmparea;
    134 	tmp_face_t *face1, *face2;
    135 
    136 	Log_Write("AAS_MergeAreaFaces\r\n");
    137 	qprintf("%6d face merges", num_facemerges);
    138 	//NOTE: first convex area is a dummy
    139 	lasttmparea = tmpaasworld.areas;
    140 	for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
    141 	{
    142 		restart = false;
    143 		//
    144 		if (tmparea->invalid) continue;
    145 		//
    146 		for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
    147 		{
    148 			side1 = face1->frontarea != tmparea;
    149 			for (face2 = face1->next[side1]; face2; face2 = face2->next[side2])
    150 			{
    151 				side2 = face2->frontarea != tmparea;
    152 				//if succesfully merged
    153 				if (AAS_TryMergeFaces(face1, face2))
    154 				{
    155 					//start over again after merging two faces
    156 					restart = true;
    157 					num_facemerges++;
    158 					qprintf("\r%6d", num_facemerges);
    159 					AAS_CheckArea(tmparea);
    160 					break;
    161 				} //end if
    162 			} //end for
    163 			if (restart)
    164 			{
    165 				tmparea = lasttmparea;
    166 				break;
    167 			} //end if
    168 		} //end for
    169 		lasttmparea = tmparea;
    170 	} //end for
    171 	qprintf("\n");
    172 	Log_Write("%6d face merges\r\n", num_facemerges);
    173 } //end of the function AAS_MergeAreaFaces
    174 //===========================================================================
    175 //
    176 // Parameter:				-
    177 // Returns:					-
    178 // Changes Globals:		-
    179 //===========================================================================
    180 void AAS_MergePlaneFaces(tmp_area_t *tmparea, int planenum)
    181 {
    182 	tmp_face_t *face1, *face2, *nextface2;
    183 	winding_t *neww;
    184 	int side1, side2;
    185 
    186 	for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
    187 	{
    188 		side1 = face1->frontarea != tmparea;
    189 		if (face1->planenum != planenum) continue;
    190 		//
    191 		for (face2 = face1->next[side1]; face2; face2 = nextface2)
    192 		{
    193 			side2 = face2->frontarea != tmparea;
    194 			nextface2 = face2->next[side2];
    195 			//
    196 			if ((face2->planenum & ~1) != (planenum & ~1)) continue;
    197 			//
    198 			neww = MergeWindings(face1->winding, face2->winding,
    199 								mapplanes[face1->planenum].normal);
    200 			FreeWinding(face1->winding);
    201 			face1->winding = neww;
    202 			if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea);
    203 			if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea);
    204 			AAS_FreeTmpFace(face2);
    205 			//
    206 			nextface2 = face1->next[side1];
    207 		} //end for
    208 	} //end for
    209 } //end of the function AAS_MergePlaneFaces
    210 //===========================================================================
    211 //
    212 // Parameter:				-
    213 // Returns:					-
    214 // Changes Globals:		-
    215 //===========================================================================
    216 int AAS_CanMergePlaneFaces(tmp_area_t *tmparea, int planenum)
    217 {
    218 	tmp_area_t *frontarea, *backarea;
    219 	tmp_face_t *face1;
    220 	int side1, merge, faceflags;
    221 
    222 	frontarea = backarea = NULL;
    223 	merge = false;
    224 	for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
    225 	{
    226 		side1 = face1->frontarea != tmparea;
    227 		if ((face1->planenum & ~1) != (planenum & ~1)) continue;
    228 		if (!frontarea && !backarea)
    229 		{
    230 			frontarea = face1->frontarea;
    231 			backarea = face1->backarea;
    232 			faceflags = face1->faceflags;
    233 		} //end if
    234 		else
    235 		{
    236 			if (frontarea != face1->frontarea) return false;
    237 			if (backarea != face1->backarea) return false;
    238 			if (faceflags != face1->faceflags) return false;
    239 			merge = true;
    240 		} //end else
    241 	} //end for
    242 	return merge;
    243 } //end of the function AAS_CanMergePlaneFaces
    244 //===========================================================================
    245 //
    246 // Parameter:				-
    247 // Returns:					-
    248 // Changes Globals:		-
    249 //===========================================================================
    250 void AAS_MergeAreaPlaneFaces(void)
    251 {
    252 	int num_facemerges = 0;
    253 	int side1;
    254 	tmp_area_t *tmparea, *nexttmparea;
    255 	tmp_face_t *face1;
    256 
    257 	Log_Write("AAS_MergePlaneFaces\r\n");
    258 	qprintf("%6d plane face merges", num_facemerges);
    259 	//NOTE: first convex area is a dummy
    260 	for (tmparea = tmpaasworld.areas; tmparea; tmparea = nexttmparea)
    261 	{
    262 		nexttmparea = tmparea->l_next;
    263 		//
    264 		if (tmparea->invalid) continue;
    265 		//
    266 		for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
    267 		{
    268 			side1 = face1->frontarea != tmparea;
    269 			//
    270 			if (AAS_CanMergePlaneFaces(tmparea, face1->planenum))
    271 			{
    272 				AAS_MergePlaneFaces(tmparea, face1->planenum);
    273 				nexttmparea = tmparea;
    274 				num_facemerges++;
    275 				qprintf("\r%6d", num_facemerges);
    276 				break;
    277 			} //end if
    278 		} //end for
    279 	} //end for
    280 	qprintf("\n");
    281 	Log_Write("%6d plane face merges\r\n", num_facemerges);
    282 } //end of the function AAS_MergeAreaPlaneFaces