//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== tmp_node_t *AAS_SubdivideArea_r( tmp_node_t *tmpnode ) { int planenum; tmp_area_t *frontarea, *backarea; tmp_node_t *tmpnode1, *tmpnode2; vec3_t normal; float dist; if ( AAS_FindBestAreaSplitPlane( tmpnode->tmparea, normal, &dist ) ) { qprintf( "\r%6d", ++numgravitationalsubdivisions ); // planenum = FindFloatPlane( normal, dist, 0, NULL ); //split the area AAS_SplitArea( tmpnode->tmparea, planenum, &frontarea, &backarea ); // tmpnode->tmparea = NULL; tmpnode->planenum = FindFloatPlane( normal, dist, 0, NULL ); // tmpnode1 = AAS_AllocTmpNode(); tmpnode1->planenum = 0; tmpnode1->tmparea = frontarea; // tmpnode2 = AAS_AllocTmpNode(); tmpnode2->planenum = 0; tmpnode2->tmparea = backarea; //subdivide the areas created by splitting recursively tmpnode->children[0] = AAS_SubdivideArea_r( tmpnode1 ); tmpnode->children[1] = AAS_SubdivideArea_r( tmpnode2 ); } //end if return tmpnode; } //end of the function AAS_SubdivideArea_r
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== tmp_node_t *AAS_CreateAreas_r( node_t *node ) { tmp_node_t *tmpnode; //recurse down to leafs if ( node->planenum != PLANENUM_LEAF ) { //the first tmp node is a dummy tmpnode = AAS_AllocTmpNode(); tmpnode->planenum = node->planenum; tmpnode->children[0] = AAS_CreateAreas_r( node->children[0] ); tmpnode->children[1] = AAS_CreateAreas_r( node->children[1] ); return tmpnode; } //end if //areas won't be created for solid leafs if ( node->contents & CONTENTS_SOLID ) { //just return zero for a solid leaf (in tmp AAS NULL is a solid leaf) return NULL; } //end if return AAS_CreateArea( node ); } //end of the function AAS_CreateAreas_r
//=========================================================================== // 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
//=========================================================================== // find an area with ladder faces and ground faces that are not connected // split the area with a horizontal plane at the lowest vertex of all // ladder faces in the area // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== tmp_node_t *AAS_LadderSubdivideArea_r( tmp_node_t *tmpnode ) { int side1, i, planenum; int foundladderface, foundgroundface; float dist; tmp_area_t *tmparea, *frontarea, *backarea; tmp_face_t *face1; tmp_node_t *tmpnode1, *tmpnode2; vec3_t lowestpoint, normal = {0, 0, 1}; plane_t *plane; winding_t *w; tmparea = tmpnode->tmparea; //skip areas with a liquid if ( tmparea->contents & ( AREACONTENTS_WATER | AREACONTENTS_LAVA | AREACONTENTS_SLIME ) ) { return tmpnode; } //must be possible to stand in the area if ( !( tmparea->presencetype & PRESENCE_NORMAL ) ) { return tmpnode; } // foundladderface = false; foundgroundface = false; lowestpoint[2] = 99999; // for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] ) { //side of the face the area is on side1 = face1->frontarea != tmparea; //if the face is a ladder face if ( face1->faceflags & FACE_LADDER ) { plane = &mapplanes[face1->planenum]; //the ladder face plane should be pretty much vertical if ( DotProduct( plane->normal, normal ) > -0.1 ) { foundladderface = true; //find lowest point for ( i = 0; i < face1->winding->numpoints; i++ ) { if ( face1->winding->p[i][2] < lowestpoint[2] ) { VectorCopy( face1->winding->p[i], lowestpoint ); } //end if } //end for } //end if } //end if else if ( face1->faceflags & FACE_GROUND ) { foundgroundface = true; } //end else if } //end for // if ( ( !foundladderface ) || ( !foundgroundface ) ) { return tmpnode; } // for ( face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1] ) { //side of the face the area is on side1 = face1->frontarea != tmparea; //if the face isn't a ground face if ( !( face1->faceflags & FACE_GROUND ) ) { continue; } //the ground plane plane = &mapplanes[face1->planenum]; //get the difference between the ground plane and the lowest point dist = DotProduct( plane->normal, lowestpoint ) - plane->dist; //if the lowest point is very near one of the ground planes if ( dist > -1 && dist < 1 ) { return tmpnode; } //end if } //end for // dist = DotProduct( normal, lowestpoint ); planenum = FindFloatPlane( normal, dist, 1, (vec3_t*)&lowestpoint ); // w = AAS_SplitWinding( tmparea, planenum ); if ( !w ) { return tmpnode; } FreeWinding( w ); //split the area with a horizontal plane through the lowest point qprintf( "\r%6d", ++numladdersubdivisions ); // AAS_SplitArea( tmparea, planenum, &frontarea, &backarea ); // tmpnode->tmparea = NULL; tmpnode->planenum = planenum; // tmpnode1 = AAS_AllocTmpNode(); tmpnode1->planenum = 0; tmpnode1->tmparea = frontarea; // tmpnode2 = AAS_AllocTmpNode(); tmpnode2->planenum = 0; tmpnode2->tmparea = backarea; //subdivide the areas created by splitting recursively tmpnode->children[0] = AAS_LadderSubdivideArea_r( tmpnode1 ); tmpnode->children[1] = AAS_LadderSubdivideArea_r( tmpnode2 ); //refresh the tree AAS_RefreshLadderSubdividedTree_r( tmpaasworld.nodes, tmparea, tmpnode1, tmpnode2, planenum ); // return tmpnode; } //end of the function AAS_LadderSubdivideArea_r
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