//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_CheckFaceWindingPlane(tmp_face_t *face) { float dist, sign1, sign2; vec3_t normal; plane_t *plane; winding_t *w; //check if the winding plane is the same as the face plane WindingPlane(face->winding, normal, &dist); plane = &mapplanes[face->planenum]; // sign1 = DotProduct(plane->normal, normal); // 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) { VectorInverse(normal); dist = -dist; 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_CheckFaceWindingPlane: face %d winding plane unequal to face plane\r\n", face->num); // sign2 = DotProduct(plane->normal, normal); if((sign1 < 0 && sign2 > 0) || (sign1 > 0 && sign2 < 0)) { Log_Write("AAS_CheckFaceWindingPlane: face %d winding reversed\r\n", face->num); w = face->winding; face->winding = ReverseWinding(w); FreeWinding(w); } //end if } //end if else { Log_Write("AAS_CheckFaceWindingPlane: face %d winding reversed\r\n", face->num); w = face->winding; face->winding = ReverseWinding(w); FreeWinding(w); } //end else } //end if } //end of the function AAS_CheckFaceWindingPlane
/* Saves all of the faces in the outside list to the bsp plane list */ static void SaveOutside( tree_t *tree, bool mirror ) { int planenum; face_t *f, *next, *newf; for( f = outside; f; f = next ) { next = f->next; numcsgfaces++; planenum = f->planenum; if( mirror ) { newf = NewFaceFromFace( f ); newf->planeside = f->planeside ^ 1; // reverse side newf->contents[0] = f->contents[1]; newf->contents[1] = f->contents[0]; newf->winding = ReverseWinding( f->winding ); tree->validfaces[planenum] = MergeFaceToList_r( newf, tree->validfaces[planenum] ); } tree->validfaces[planenum] = MergeFaceToList_r( f, tree->validfaces[planenum]); tree->validfaces[planenum] = FreeMergeListScraps( tree->validfaces[planenum] ); } }
/* ============= OutputPortal ============= */ void OutputPortal(portal_t *p, FILE *glview) { winding_t *w; int sides; sides = PortalVisibleSides(p); if (!sides) { return; } c_glfaces++; w = p->winding; if (sides == 2) // back side { w = ReverseWinding(w); } OutputWinding(w, glview); if (sides == 2) { FreeWinding(w); } }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_FlipFace(tmp_face_t *face) { tmp_area_t *frontarea, *backarea; winding_t *w; frontarea = face->frontarea; backarea = face->backarea; //must have an area at both sides before flipping is allowed if(!frontarea || !backarea) { return; } //flip the face winding w = face->winding; face->winding = ReverseWinding(w); FreeWinding(w); //flip the face plane face->planenum ^= 1; //flip the face areas AAS_RemoveFaceFromArea(face, frontarea); AAS_RemoveFaceFromArea(face, backarea); AAS_AddFaceSideToArea(face, 1, frontarea); AAS_AddFaceSideToArea(face, 0, backarea); } //end of the function AAS_FlipFace
static void DrawPortal(portal_t * p, qboolean areaportal) { winding_t *w; int sides; sides = PortalVisibleSides(p); if(!sides) return; w = p->winding; if(sides == 2) // back side w = ReverseWinding(w); if(areaportal) { Draw_AuxWinding(w); } else { Draw_Winding(w); } if(sides == 2) FreeWinding(w); }
static face_t* FaceFromPortal (portal_t* p, bool pside) { face_t* f; side_t* side = p->side; /* portal does not bridge different visible contents */ if (!side) return nullptr; /* nodraw/caulk faces */ if (side->surfaceFlags & SURF_NODRAW) return nullptr; f = AllocFace(); f->texinfo = side->texinfo; f->planenum = (side->planenum & ~1) | pside; f->portal = p; if ((p->nodes[pside]->contentFlags & CONTENTS_WINDOW) && VisibleContents(p->nodes[!pside]->contentFlags ^ p->nodes[pside]->contentFlags) == CONTENTS_WINDOW) return nullptr; /* don't show insides of windows */ /* do back-clipping */ if (!config.nobackclip && mapplanes[f->planenum].normal[2] < -0.9) { /* this face is not visible from birds view - optimize away * but only if it's not light emitting surface */ const entity_t* e = &entities[side->brush->entitynum]; if (!Q_streq(ValueForKey(e, "classname"), "func_rotating")) { if (!(curTile->texinfo[f->texinfo].surfaceFlags & SURF_LIGHT)) { /* e.g. water surfaces are removed if we set the surfaceFlags * to SURF_NODRAW for this side */ /*side->surfaceFlags |= SURF_NODRAW;*/ return nullptr; } } } if (pside) { f->w = ReverseWinding(p->winding); f->contentFlags = p->nodes[1]->contentFlags; } else { f->w = CopyWinding(p->winding); f->contentFlags = p->nodes[0]->contentFlags; } return f; }
/* ============= OutputPortal ============= */ void OutputPortal (portal_t *p, FileHandle_t glview) { winding_t *w; int sides; sides = PortalVisibleSides (p); if (!sides) return; c_glfaces++; w = p->winding; if (sides == 2) // back side w = ReverseWinding (w); OutputWinding (w, glview); if (sides == 2) FreeWinding(w); }
//=========================================================================== // create a tmp AAS area from a leaf node // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== tmp_node_t *AAS_CreateArea(node_t *node) { int pside; int areafaceflags; portal_t *p; tmp_face_t *tmpface; tmp_area_t *tmparea; tmp_node_t *tmpnode; //create an area from this leaf tmparea = AAS_AllocTmpArea(); tmparea->tmpfaces = NULL; //clear the area face flags areafaceflags = 0; //make aas faces from the portals for (p = node->portals; p; p = p->next[pside]) { pside = (p->nodes[1] == node); //don't create faces from very small portals // if (WindingArea(p->winding) < 1) continue; //if there's already a face created for this portal if (p->tmpface) { //add the back side of the face to the area AAS_AddFaceSideToArea(p->tmpface, 1, tmparea); } //end if else { tmpface = AAS_AllocTmpFace(); //set the face pointer at the portal so we can see from //the portal there's a face created for it p->tmpface = tmpface; //FIXME: test this change //tmpface->planenum = (p->planenum & ~1) | pside; tmpface->planenum = p->planenum ^ pside; if (pside) tmpface->winding = ReverseWinding(p->winding); else tmpface->winding = CopyWinding(p->winding); #ifdef L_DEBUG // AAS_CheckFaceWindingPlane(tmpface); #endif //L_DEBUG //if there's solid at the other side of the portal if (p->nodes[!pside]->contents & (CONTENTS_SOLID | CONTENTS_PLAYERCLIP)) { tmpface->faceflags |= FACE_SOLID; } //end if //else there is no solid at the other side and if there //is a liquid at this side else if (node->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA)) { tmpface->faceflags |= FACE_LIQUID; //if there's no liquid at the other side if (!(p->nodes[!pside]->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA))) { tmpface->faceflags |= FACE_LIQUIDSURFACE; } //end if } //end else //if there's ladder contents at other side of the portal if ((p->nodes[pside]->contents & CONTENTS_LADDER) || (p->nodes[!pside]->contents & CONTENTS_LADDER)) { //NOTE: doesn't have to be solid at the other side because // when standing one can use a crouch area (which is not solid) // as a ladder // imagine a ladder one can walk underthrough, // under the ladder against the ladder is a crouch area // the (vertical) sides of this crouch area area also used as // ladder sides when standing (not crouched) tmpface->faceflags |= FACE_LADDER; } //end if //if it is possible to stand on the face if (AAS_GroundFace(tmpface)) { tmpface->faceflags |= FACE_GROUND; } //end if // areafaceflags |= tmpface->faceflags; //no aas face number yet (zero is a dummy in the aasworld faces) tmpface->aasfacenum = 0; //add the front side of the face to the area AAS_AddFaceSideToArea(tmpface, 0, tmparea); } //end else } //end for qprintf("\r%6d", tmparea->areanum); //presence type in the area tmparea->presencetype = ~node->expansionbboxes & cfg.allpresencetypes; // tmparea->contents = 0; if (node->contents & CONTENTS_CLUSTERPORTAL) tmparea->contents |= AREACONTENTS_CLUSTERPORTAL; if (node->contents & CONTENTS_MOVER) tmparea->contents |= AREACONTENTS_MOVER; if (node->contents & CONTENTS_TELEPORTER) tmparea->contents |= AREACONTENTS_TELEPORTER; if (node->contents & CONTENTS_JUMPPAD) tmparea->contents |= AREACONTENTS_JUMPPAD; if (node->contents & CONTENTS_DONOTENTER) tmparea->contents |= AREACONTENTS_DONOTENTER; if (node->contents & CONTENTS_WATER) tmparea->contents |= AREACONTENTS_WATER; if (node->contents & CONTENTS_LAVA) tmparea->contents |= AREACONTENTS_LAVA; if (node->contents & CONTENTS_SLIME) tmparea->contents |= AREACONTENTS_SLIME; if (node->contents & CONTENTS_NOTTEAM1) tmparea->contents |= AREACONTENTS_NOTTEAM1; if (node->contents & CONTENTS_NOTTEAM2) tmparea->contents |= AREACONTENTS_NOTTEAM2; //store the bsp model that's inside this node tmparea->modelnum = node->modelnum; //sorta check for flipped area faces (remove??) AAS_FlipAreaFaces(tmparea); //check if the area is ok (remove??) AAS_CheckArea(tmparea); // tmpnode = AAS_AllocTmpNode(); tmpnode->planenum = 0; tmpnode->children[0] = 0; tmpnode->children[1] = 0; tmpnode->tmparea = tmparea; // return tmpnode; } //end of the function AAS_CreateArea
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int AAS_StoreArea( tmp_area_t *tmparea ) { int side, edgenum, i; plane_t *plane; tmp_face_t *tmpface; aas_area_t *aasarea; aas_edge_t *edge; aas_face_t *aasface; aas_faceindex_t aasfacenum; vec3_t facecenter; winding_t *w; //when the area is merged go to the merged area //FIXME: this isn't necessary anymore because the tree // is refreshed after area merging while ( tmparea->mergedarea ) tmparea = tmparea->mergedarea; // if ( tmparea->invalid ) { Error( "AAS_StoreArea: tried to store invalid area" ); } //if there is an aas area already stored for this tmp area if ( tmparea->aasareanum ) { return -tmparea->aasareanum; } // if ( ( *aasworld ).numareas >= max_aas.max_areas ) { Error( "AAS_MAX_AREAS = %d", max_aas.max_areas ); } //end if //area zero is a dummy if ( ( *aasworld ).numareas == 0 ) { ( *aasworld ).numareas = 1; } //create an area from this leaf aasarea = &( *aasworld ).areas[( *aasworld ).numareas]; aasarea->areanum = ( *aasworld ).numareas; aasarea->numfaces = 0; aasarea->firstface = ( *aasworld ).faceindexsize; ClearBounds( aasarea->mins, aasarea->maxs ); VectorClear( aasarea->center ); // // Log_Write("tmparea %d became aasarea %d\r\n", tmparea->areanum, aasarea->areanum); //store the aas area number at the tmp area tmparea->aasareanum = aasarea->areanum; // for ( tmpface = tmparea->tmpfaces; tmpface; tmpface = tmpface->next[side] ) { side = tmpface->frontarea != tmparea; //if there's an aas face created for the tmp face already if ( tmpface->aasfacenum ) { //we're at the back of the face so use a negative index aasfacenum = -tmpface->aasfacenum; #ifdef DEBUG if ( tmpface->aasfacenum < 0 || tmpface->aasfacenum > max_aas.max_faces ) { Error( "AAS_CreateTree_r: face number out of range" ); } //end if #endif //DEBUG aasface = &( *aasworld ).faces[tmpface->aasfacenum]; aasface->backarea = aasarea->areanum; } //end if else { plane = &mapplanes[tmpface->planenum ^ side]; if ( side ) { w = tmpface->winding; tmpface->winding = ReverseWinding( tmpface->winding ); } //end if if ( !AAS_GetFace( tmpface->winding, plane, 0, &aasfacenum ) ) { continue; } if ( side ) { FreeWinding( tmpface->winding ); tmpface->winding = w; } //end if aasface = &( *aasworld ).faces[aasfacenum]; aasface->frontarea = aasarea->areanum; aasface->backarea = 0; aasface->faceflags = tmpface->faceflags; //set the face number at the tmp face tmpface->aasfacenum = aasfacenum; } //end else //add face points to the area bounds and //calculate the face 'center' VectorClear( facecenter ); for ( edgenum = 0; edgenum < aasface->numedges; edgenum++ ) { edge = &( *aasworld ).edges[abs( ( *aasworld ).edgeindex[aasface->firstedge + edgenum] )]; for ( i = 0; i < 2; i++ ) { AddPointToBounds( ( *aasworld ).vertexes[edge->v[i]], aasarea->mins, aasarea->maxs ); VectorAdd( ( *aasworld ).vertexes[edge->v[i]], facecenter, facecenter ); } //end for } //end for VectorScale( facecenter, 1.0 / ( aasface->numedges * 2.0 ), facecenter ); //add the face 'center' to the area 'center' VectorAdd( aasarea->center, facecenter, aasarea->center ); // if ( ( *aasworld ).faceindexsize >= max_aas.max_faceindexsize ) { Error( "AAS_MAX_FACEINDEXSIZE = %d", max_aas.max_faceindexsize ); } //end if ( *aasworld ).faceindex[( *aasworld ).faceindexsize++] = aasfacenum; aasarea->numfaces++; } //end for //if the area has no faces at all (return 0, = solid leaf) if ( !aasarea->numfaces ) { return 0; } // VectorScale( aasarea->center, 1.0 / aasarea->numfaces, aasarea->center ); //Log_Write("area %d center %f %f %f\r\n", (*aasworld).numareas, // aasarea->center[0], aasarea->center[1], aasarea->center[2]); //store the area settings AAS_StoreAreaSettings( tmparea->settings ); // //Log_Write("tmp area %d became aas area %d\r\n", tmpareanum, aasarea->areanum); qprintf( "\r%6d", aasarea->areanum ); // if ( ( *aasworld ).areasettings[aasarea->areanum].contents & AREACONTENTS_CLUSTERPORTAL ) { static int num; Log_Write( "***** area %d is a cluster portal %d\n", aasarea->areanum, num++ ); } //end if // ( *aasworld ).numareas++; return -( ( *aasworld ).numareas - 1 ); } //end of the function AAS_StoreArea
tmp_node_t *AAS_CreateArea( node_t *node ) { int pside; int areafaceflags; portal_t *p; tmp_face_t *tmpface; tmp_area_t *tmparea; tmp_node_t *tmpnode; vec3_t up = {0, 0, 1}; // vec3_t mins, maxs; // qboolean allowFreeIfSmall = 1; // VectorClear( mins ); // VectorClear( maxs ); //create an area from this leaf tmparea = AAS_AllocTmpArea(); tmparea->tmpfaces = NULL; //clear the area face flags areafaceflags = 0; //make aas faces from the portals for ( p = node->portals; p; p = p->next[pside] ) { pside = ( p->nodes[1] == node ); //don't create faces from very small portals // if (WindingArea(p->winding) < 1) continue; //if there's already a face created for this portal if ( p->tmpface ) { //add the back side of the face to the area AAS_AddFaceSideToArea( p->tmpface, 1, tmparea ); } //end if else { tmpface = AAS_AllocTmpFace(); //set the face pointer at the portal so we can see from //the portal there's a face created for it p->tmpface = tmpface; //FIXME: test this change //tmpface->planenum = (p->planenum & ~1) | pside; tmpface->planenum = p->planenum ^ pside; if ( pside ) { tmpface->winding = ReverseWinding( p->winding ); } else { tmpface->winding = CopyWinding( p->winding );} #ifdef L_DEBUG // AAS_CheckFaceWindingPlane( tmpface ); #endif //L_DEBUG //if there's solid at the other side of the portal if ( p->nodes[!pside]->contents & ( CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP ) ) { tmpface->faceflags |= FACE_SOLID; } //end if //else there is no solid at the other side and if there //is a liquid at this side else if ( node->contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) { tmpface->faceflags |= FACE_LIQUID; //if there's no liquid at the other side if ( !( p->nodes[!pside]->contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) ) { tmpface->faceflags |= FACE_LIQUIDSURFACE; } //end if } //end else //if there's ladder contents at other side of the portal if ( ( p->nodes[pside]->contents & CONTENTS_LADDER ) || ( p->nodes[!pside]->contents & CONTENTS_LADDER ) ) { //NOTE: doesn't have to be solid at the other side because // when standing one can use a crouch area (which is not solid) // as a ladder // imagine a ladder one can walk underthrough, // under the ladder against the ladder is a crouch area // the (vertical) sides of this crouch area area also used as // ladder sides when standing (not crouched) tmpface->faceflags |= FACE_LADDER; } //end if //if it is possible to stand on the face if ( AAS_GroundFace( tmpface ) ) { tmpface->faceflags |= FACE_GROUND; } //end if // areafaceflags |= tmpface->faceflags; //no aas face number yet (zero is a dummy in the aasworld faces) tmpface->aasfacenum = 0; //add the front side of the face to the area AAS_AddFaceSideToArea( tmpface, 0, tmparea ); } //end else /* // RF, add this face to the bounds if (p->tmpface->faceflags & FACE_GROUND) { WindingBounds( p->winding, mins, maxs ); } // RF, if this face has a solid at the other side, and it is not a GROUND, then we cannot free if its too small if (allowFreeIfSmall && (p->tmpface->faceflags & FACE_SOLID) && !(p->tmpface->faceflags & FACE_GROUND)) { // make sure it's not a ceiling if (!(DotProduct(cfg.phys_gravitydirection, mapplanes[p->tmpface->planenum].normal) > cfg.phys_maxsteepness)) { allowFreeIfSmall = 0; } } */ } //end for qprintf( "\r%6d", tmparea->areanum ); //presence type in the area tmparea->presencetype = ~node->expansionbboxes & cfg.allpresencetypes; // tmparea->contents = 0; if ( node->contents & CONTENTS_CLUSTERPORTAL ) { tmparea->contents |= AREACONTENTS_CLUSTERPORTAL; } if ( node->contents & CONTENTS_MOVER ) { tmparea->contents |= AREACONTENTS_MOVER; } if ( node->contents & CONTENTS_TELEPORTER ) { tmparea->contents |= AREACONTENTS_TELEPORTER; } if ( node->contents & CONTENTS_JUMPPAD ) { tmparea->contents |= AREACONTENTS_JUMPPAD; } if ( node->contents & CONTENTS_DONOTENTER ) { tmparea->contents |= AREACONTENTS_DONOTENTER; } if ( node->contents & CONTENTS_DONOTENTER_LARGE ) { tmparea->contents |= AREACONTENTS_DONOTENTER_LARGE; } if ( node->contents & CONTENTS_WATER ) { tmparea->contents |= AREACONTENTS_WATER; } if ( node->contents & CONTENTS_LAVA ) { tmparea->contents |= AREACONTENTS_LAVA; } if ( node->contents & CONTENTS_SLIME ) { tmparea->contents |= AREACONTENTS_SLIME; } /* // RF, if we are using only ground areas, then ignore areas that arent grounded or attached to ladders, or underwater if (groundonly && !(areafaceflags & (FACE_GROUND|FACE_LADDER)) && !(tmparea->contents & (AREACONTENTS_WATER|AREACONTENTS_SLIME|AREACONTENTS_LAVA))) { numGroundOnlyFreed++; tmparea->invalid = true; } */ /* // RF, if this is a really small area, and it is surrounded by non-solid portals, then nuke it if (allowFreeIfSmall && !(areafaceflags & (FACE_LADDER)) && VectorDistance( mins, maxs ) < 32) { numTinyFreed++; tmparea->invalid = true; } */ //store the bsp model that's inside this node tmparea->modelnum = node->modelnum; //sorta check for flipped area faces (remove??) AAS_FlipAreaFaces( tmparea ); //check if the area is ok (remove??) AAS_CheckArea( tmparea ); // tmpnode = AAS_AllocTmpNode(); tmpnode->planenum = 0; tmpnode->children[0] = 0; tmpnode->children[1] = 0; tmpnode->tmparea = tmparea; // return tmpnode; } //end of the function AAS_CreateArea