bool Primitive_Parse( brush_t *pBrush ){ char *token = Token(); GetToken( true ); if ( !strcmp( token, "patchDef2" ) ) { pBrush->patchBrush = true; pBrush->pPatch = Patch_Alloc(); pBrush->pPatch->pSymbiot = pBrush; Patch_Parse( pBrush->pPatch ); GetToken( true ); //} // A patchdef should never be loaded from a quake2 map file // so we just return false and the brush+patch gets freed // and the user gets told. if ( g_MapVersion != MAPVERSION_Q3 ) { // FIXME: Hydra - I wanted to write out a line number here, but I can't because there's no API to access the core's "scriptline" variable. Syn_Printf( "ERROR: patchDef2's are not supported in Quake%d format .map files!\n",g_MapVersion ); abortcode = MAP_WRONGVERSION; return false; } } else if ( !strcmp( token, "brushDef" ) ) { pBrush->bBrushDef = true; GetToken( true ); // { while ( 1 ) { face_t *f = pBrush->brush_faces; pBrush->brush_faces = Face_Alloc(); Face_Parse( pBrush->brush_faces, true ); pBrush->brush_faces->next = f; // check for end of brush GetToken( true ); if ( strcmp( token,"}" ) == 0 ) { break; } UnGetToken(); } GetToken( true ); // } } else { UnGetToken(); while ( 1 ) { face_t *f = pBrush->brush_faces; pBrush->brush_faces = Face_Alloc(); Face_Parse( pBrush->brush_faces ); pBrush->brush_faces->next = f; // check for end of brush GetToken( true ); if ( strcmp( token,"}" ) == 0 ) { break; } UnGetToken(); } } return true; }
face_t* MakePlaneList(face_t* top, face_t* bottom) { face_t* fList; face_t* curFace; face_t* newTop; face_t* newBot; int i; int j; int k; vec3_t t1, t2, t3; fList = NULL; newTop = Face_Alloc(); CopyFace(top, newTop); newBot = Face_Alloc(); CopyFace(bottom, newBot); WrapFaces(newTop, newBot); for (i = 0; i<newTop->face_winding->numpoints; i++) { if (i == (newTop->face_winding->numpoints - 1)) { j = 0; } else { j = i + 1; } curFace = Face_Alloc(); VectorCopy(newTop->face_winding->points[j],curFace->planepts[0]); VectorCopy(newTop->face_winding->points[i],curFace->planepts[1]); VectorCopy(newBot->face_winding->points[i],curFace->planepts[2]); for (k=0 ; k<3 ; k++) { t1[k] = curFace->planepts[0][k] - curFace->planepts[1][k]; t2[k] = curFace->planepts[2][k] - curFace->planepts[1][k]; t3[k] = curFace->planepts[1][k]; } CrossProduct(t1,t2, curFace->plane.normal); if (VectorCompare (curFace->plane.normal, vec3_origin)) { printf ("WARNING: brush plane with no normal\n"); } VectorNormalize (curFace->plane.normal); curFace->plane.dist = DotProduct (t3, curFace->plane.normal); curFace->next = fList; fList = curFace; } // for loop return fList; }
void WINAPI QERApp_AddFaceData(LPVOID pv, _QERFaceData *pData) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv); if (pBrush != NULL) { face_t *f = Face_Alloc(); f->texdef = g_qeglobals.d_texturewin.texdef; f->texdef.flags = pData->m_nFlags; f->texdef.contents = pData->m_nContents; f->texdef.value = pData->m_nValue; f->texdef.rotate = pData->m_fRotate; f->texdef.shift[0] = pData->m_fShift[0]; f->texdef.shift[1] = pData->m_fShift[1]; f->texdef.scale[0] = pData->m_fScale[0]; f->texdef.scale[1] = pData->m_fScale[1]; //strcpy(f->texdef.name, pData->m_TextureName); f->texdef.SetName(pData->m_TextureName); f->next = pBrush->brush_faces; pBrush->brush_faces = f; VectorCopy (pData->m_v1, f->planepts[0]); VectorCopy (pData->m_v2, f->planepts[1]); VectorCopy (pData->m_v3, f->planepts[2]); Sys_MarkMapModified(); // PGM } }
brush_t *BrushFromMapBrush(idMapBrush *mapbrush, idVec3 origin) { brush_t *b = NULL; if (mapbrush) { b = Brush_Alloc(); int count = mapbrush->GetNumSides(); for (int i = 0; i < count; i++) { idMapBrushSide *side = mapbrush->GetSide(i); face_t *f = Face_Alloc(); f->next = NULL; if (!b->brush_faces) { b->brush_faces = f; } else { face_t *scan; for (scan = b->brush_faces; scan->next; scan = scan->next) { ; } scan->next = f; } f->plane = side->GetPlane(); f->originalPlane = f->plane; f->dirty = false; // ---> sikk - Old Brush Format /* idWinding w; w.BaseForPlane(f->plane); for (int j = 0; j < 3; j++) { f->planepts[j].x = w[j].x + origin.x; f->planepts[j].y = w[j].y + origin.y; f->planepts[j].z = w[j].z + origin.z; }*/ side->GetPlanePoints( f->planepts[0], f->planepts[1], f->planepts[2] ); for ( int j = 0; j < 3; j++ ) { f->planepts[j] += origin; } // <--- sikk - Old Brush Format idVec3 mat[2]; side->GetTextureMatrix(mat[0], mat[1]); f->brushprimit_texdef.coords[0][0] = mat[0][0]; f->brushprimit_texdef.coords[0][1] = mat[0][1]; f->brushprimit_texdef.coords[0][2] = mat[0][2]; f->brushprimit_texdef.coords[1][0] = mat[1][0]; f->brushprimit_texdef.coords[1][1] = mat[1][1]; f->brushprimit_texdef.coords[1][2] = mat[1][2]; f->texdef.SetName(side->GetMaterial()); } } return b; }
face_t *Face_Clone (face_t *f) { face_t *n; n = Face_Alloc(); n->texdef = f->texdef; memcpy (n->planepts, f->planepts, sizeof(n->planepts)); // all other fields are derived, and will be set by Brush_Build return n; }
void Brush_XMLParse( brush_t *pBrush, xmlNodePtr primitive ){ face_t *f; for ( xmlNodePtr current = primitive->children; current != NULL; current = current->next ) { if ( current->type != XML_ELEMENT_NODE ) { continue; } f = pBrush->brush_faces; pBrush->brush_faces = Face_Alloc(); Face_XMLParse( pBrush->brush_faces, current ); pBrush->brush_faces->next = f; } }
void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3) { brush_t *bp = FindBrushHandle(vp); if (bp != NULL) { face_t *f = Face_Alloc(); f->texdef = g_qeglobals.d_texturewin.texdef; f->texdef.flags &= ~SURF_KEEP; f->texdef.contents &= ~CONTENTS_KEEP; f->next = bp->brush_faces; bp->brush_faces = f; VectorCopy (v1, f->planepts[0]); VectorCopy (v2, f->planepts[1]); VectorCopy (v3, f->planepts[2]); } }
/* Makes the current brushhave the given number of 2d sides */ void Brush_MakeSided(int sides) { int i; vec3_t mins, maxs; brush_t *b; texdef_t *texdef; face_t *f; vec3_t mid; float width,sv,cv; if(sides < 3) { Sys_Status ("Bad sides number", 0); return; } else if(!QE_SingleBrush()) { Sys_Status ("Must have a single brush selected", 0 ); return; } b = selected_brushes.next; Math_VectorCopy(b->mins,mins); Math_VectorCopy(b->maxs,maxs); texdef = &g_qeglobals.d_texturewin.texdef; Brush_Free (b); // find center of brush width = 8; for (i=0 ; i<2 ; i++) { mid[i] = (maxs[i] + mins[i])*0.5; if (maxs[i] - mins[i] > width) width = maxs[i] - mins[i]; } width /= 2; b = qmalloc (sizeof(brush_t)); // create top face f = Face_Alloc(); f->texdef = *texdef; f->next = b->brush_faces; b->brush_faces = f; f->planepts[2][0] = mins[0];f->planepts[2][1] = mins[1];f->planepts[2][2] = maxs[2]; f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = maxs[2]; f->planepts[0][0] = maxs[0];f->planepts[0][1] = maxs[1];f->planepts[0][2] = maxs[2]; // create bottom face f = Face_Alloc(); f->texdef = *texdef; f->next = b->brush_faces; b->brush_faces = f; f->planepts[0][0] = mins[0];f->planepts[0][1] = mins[1];f->planepts[0][2] = mins[2]; f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = mins[2]; f->planepts[2][0] = maxs[0];f->planepts[2][1] = maxs[1];f->planepts[2][2] = mins[2]; for (i=0 ; i<sides ; i++) { f = Face_Alloc(); f->texdef = *texdef; f->next = b->brush_faces; b->brush_faces = f; sv = sin (i*3.14159265*2/sides); cv = cos (i*3.14159265*2/sides); f->planepts[0][0] = floor(mid[0]+width*cv+0.5); f->planepts[0][1] = floor(mid[1]+width*sv+0.5); f->planepts[0][2] = mins[2]; f->planepts[1][0] = f->planepts[0][0]; f->planepts[1][1] = f->planepts[0][1]; f->planepts[1][2] = maxs[2]; f->planepts[2][0] = floor(f->planepts[0][0] - width*sv + 0.5); f->planepts[2][1] = floor(f->planepts[0][1] + width*cv + 0.5); f->planepts[2][2] = maxs[2]; } Brush_AddToList (b, &selected_brushes); Entity_LinkBrush (world_entity, b); Brush_Build( b ); Sys_UpdateWindows (W_ALL); }
/* Create non-textured blocks for entities The brush is NOT linked to any list */ brush_t *Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef) { int i, j; vec3_t pts[4][2]; face_t *f; brush_t *b; for (i=0 ; i<3 ; i++) if (maxs[i] < mins[i]) Error ("Brush_InitSolid: backwards"); b = (brush_t*)qmalloc(sizeof(brush_t)); pts[0][0][0] = mins[0]; pts[0][0][1] = mins[1]; pts[1][0][0] = mins[0]; pts[1][0][1] = maxs[1]; pts[2][0][0] = maxs[0]; pts[2][0][1] = maxs[1]; pts[3][0][0] = maxs[0]; pts[3][0][1] = mins[1]; for (i=0 ; i<4 ; i++) { pts[i][0][2] = mins[2]; pts[i][1][0] = pts[i][0][0]; pts[i][1][1] = pts[i][0][1]; pts[i][1][2] = maxs[2]; } for (i=0 ; i<4 ; i++) { f = Face_Alloc(); f->texdef = *texdef; f->next = b->brush_faces; b->brush_faces = f; j = (i+1)%4; Math_VectorCopy(pts[j][1],f->planepts[0]); Math_VectorCopy(pts[i][1],f->planepts[1]); Math_VectorCopy(pts[i][0],f->planepts[2]); } f = Face_Alloc(); f->texdef = *texdef; f->next = b->brush_faces; b->brush_faces = f; Math_VectorCopy(pts[0][1],f->planepts[0]); Math_VectorCopy(pts[1][1],f->planepts[1]); Math_VectorCopy(pts[2][1],f->planepts[2]); f = Face_Alloc(); f->texdef = *texdef; f->next = b->brush_faces; b->brush_faces = f; Math_VectorCopy(pts[2][0],f->planepts[0]); Math_VectorCopy(pts[1][0],f->planepts[1]); Math_VectorCopy(pts[0][0],f->planepts[2]); return b; }
/* The brush is NOT linked to any list */ brush_t *Brush_Parse(void) { brush_t *b; face_t *f; int i,j; g_qeglobals.d_parsed_brushes++; b = (brush_t*)qmalloc(sizeof(brush_t)); do { if(!GetToken (TRUE)) break; if(!strcmp (token, "}") ) break; f = Face_Alloc(); // add the brush to the end of the chain, so // loading and saving a map doesn't reverse the order f->next = NULL; if (!b->brush_faces) b->brush_faces = f; else { face_t *scan; for (scan=b->brush_faces ; scan->next ; scan=scan->next) ; scan->next = f; } // read the three point plane definition for (i=0 ; i<3 ; i++) { if (i != 0) GetToken (TRUE); if (strcmp (token, "(") ) Error ("parsing brush"); for (j=0 ; j<3 ; j++) { GetToken (false); f->planepts[i][j] = atoi(token); } GetToken (false); if (strcmp (token, ")") ) Error ("parsing brush"); } // read the texturedef GetToken(false); strcpy(f->texdef.name,token); GetToken(false); f->texdef.shift[0] = atoi(token); GetToken(false); f->texdef.shift[1] = atoi(token); GetToken(false); f->texdef.rotate = atoi(token); GetToken(false); f->texdef.scale[0] = atof(token); GetToken(false); f->texdef.scale[1] = atof(token); // the flags and value field aren't necessarily present f->d_texture = Texture_ForName( f->texdef.name ); f->texdef.flags = f->d_texture->flags; f->texdef.value = f->d_texture->value; f->texdef.contents = f->d_texture->contents; if (TokenAvailable ()) { GetToken(false); f->texdef.contents = atoi(token); GetToken(false); f->texdef.flags = atoi(token); GetToken(false); f->texdef.value = atoi(token); } } while (1); return b; }
/* ============= Brush_MergeList Tries to merge all brushes in the list into one new brush. The input brush list stays intact. Returns NULL if no merged brush can be created. To create a new brush the brushes in the list may not overlap and the outer faces of the brushes together should make a new convex brush. if onlyshape is true then the merge is allowed based on the shape only otherwise the texture references of faces in the same plane have to be the same as well. ============= */ brush_t *Brush_MergeList(brush_t *brushlist, int onlyshape) { brush_t *brush1, *brush2, *brush3, *newbrush; face_t *face1, *face2, *face3, *newface, *f; if (!brushlist) return NULL; for (brush1 = brushlist; brush1; brush1 = brush1->next) { // check if the new brush would be convex... flipped planes make a brush concave for (face1 = brush1->brush_faces; face1; face1 = face1->next) { // don't check face1 if it touches another brush for (brush2 = brushlist; brush2; brush2 = brush2->next) { if (brush2 == brush1) continue; for (face2 = brush2->brush_faces; face2; face2 = face2->next) { if (Plane_Equal(&face1->plane, &face2->plane, true)) { break; } } if (face2) break; } // if face1 touches another brush if (brush2) continue; // for (brush2 = brush1->next; brush2; brush2 = brush2->next) { // don't check the faces of brush 2 touching another brush for (face2 = brush2->brush_faces; face2; face2 = face2->next) { for (brush3 = brushlist; brush3; brush3 = brush3->next) { if (brush3 == brush2) continue; for (face3 = brush3->brush_faces; face3; face3 = face3->next) { if (Plane_Equal(&face2->plane, &face3->plane, true)) break; } if (face3) break; } // if face2 touches another brush if (brush3) continue; // if (Plane_Equal(&face1->plane, &face2->plane, false)) { //if the texture references should be the same but are not if (!onlyshape && stricmp(face1->texdef.name, face2->texdef.name) != 0) return NULL; continue; } // if (Winding_PlanesConcave(face1->face_winding, face2->face_winding, face1->plane.normal, face2->plane.normal, face1->plane.dist, face2->plane.dist)) { return NULL; } } } } } // newbrush = Brush_Alloc(); // for (brush1 = brushlist; brush1; brush1 = brush1->next) { for (face1 = brush1->brush_faces; face1; face1 = face1->next) { // don't add face1 to the new brush if it touches another brush for (brush2 = brushlist; brush2; brush2 = brush2->next) { if (brush2 == brush1) continue; for (face2 = brush2->brush_faces; face2; face2 = face2->next) { if (Plane_Equal(&face1->plane, &face2->plane, true)) { break; } } if (face2) break; } if (brush2) continue; // don't add faces with the same plane twice for (f = newbrush->brush_faces; f; f = f->next) { if (Plane_Equal(&face1->plane, &f->plane, false)) break; if (Plane_Equal(&face1->plane, &f->plane, true)) break; } if (f) continue; // newface = Face_Alloc(); newface->texdef = face1->texdef; VectorCopy(face1->planepts[0], newface->planepts[0]); VectorCopy(face1->planepts[1], newface->planepts[1]); VectorCopy(face1->planepts[2], newface->planepts[2]); newface->plane = face1->plane; newface->next = newbrush->brush_faces; newbrush->brush_faces = newface; } } // link the new brush to an entity Entity_LinkBrush (brushlist->owner, newbrush); // build windings for the faces Brush_BuildWindings( newbrush); return newbrush; }
/* ============= Brush_Merge Returns a new brush that is created by merging brush1 and brush2. May return NULL if brush1 and brush2 do not create a convex brush when merged. The input brushes brush1 and brush2 stay intact. if onlyshape is true then the merge is allowed based on the shape only otherwise the texture references of faces in the same plane have to be the same as well. ============= */ brush_t *Brush_Merge(brush_t *brush1, brush_t *brush2, int onlyshape) { int i, shared; brush_t *newbrush; face_t *face1, *face2, *newface, *f; // check for bounding box overlapp for (i = 0; i < 3; i++) { if (brush1->mins[i] > brush2->maxs[i] + ON_EPSILON || brush1->maxs[i] < brush2->mins[i] - ON_EPSILON) { // never merge if the brushes overlap return NULL; } } // shared = 0; // check if the new brush would be convex... flipped planes make a brush non-convex for (face1 = brush1->brush_faces; face1; face1 = face1->next) { // don't check the faces of brush 1 and 2 touching each other for (face2 = brush2->brush_faces; face2; face2 = face2->next) { if (Plane_Equal(&face1->plane, &face2->plane, true)) { shared++; // there may only be ONE shared side if (shared > 1) return NULL; break; } } // if this face plane is shared if (face2) continue; // for (face2 = brush2->brush_faces; face2; face2 = face2->next) { // don't check the faces of brush 1 and 2 touching each other for (f = brush1->brush_faces; f; f = f->next) { if (Plane_Equal(&face2->plane, &f->plane, true)) break; } if (f) continue; // if (Plane_Equal(&face1->plane, &face2->plane, false)) { //if the texture references should be the same but are not if (!onlyshape && stricmp(face1->texdef.name, face2->texdef.name) != 0) return NULL; continue; } // if (Winding_PlanesConcave(face1->face_winding, face2->face_winding, face1->plane.normal, face2->plane.normal, face1->plane.dist, face2->plane.dist)) { return NULL; } //end if } //end for } //end for // newbrush = Brush_Alloc(); // for (face1 = brush1->brush_faces; face1; face1 = face1->next) { // don't add the faces of brush 1 and 2 touching each other for (face2 = brush2->brush_faces; face2; face2 = face2->next) { if (Plane_Equal(&face1->plane, &face2->plane, true)) break; } if (face2) continue; // don't add faces with the same plane twice for (f = newbrush->brush_faces; f; f = f->next) { if (Plane_Equal(&face1->plane, &f->plane, false)) break; if (Plane_Equal(&face1->plane, &f->plane, true)) break; } if (f) continue; // newface = Face_Alloc(); newface->texdef = face1->texdef; VectorCopy(face1->planepts[0], newface->planepts[0]); VectorCopy(face1->planepts[1], newface->planepts[1]); VectorCopy(face1->planepts[2], newface->planepts[2]); newface->plane = face1->plane; newface->next = newbrush->brush_faces; newbrush->brush_faces = newface; } // for (face2 = brush2->brush_faces; face2; face2 = face2->next) { // don't add the faces of brush 1 and 2 touching each other for (face1 = brush1->brush_faces; face1; face1 = face1->next) { if (Plane_Equal(&face2->plane, &face1->plane, true)) break; } if (face1) continue; // don't add faces with the same plane twice for (f = newbrush->brush_faces; f; f = f->next) { if (Plane_Equal(&face2->plane, &f->plane, false)) break; if (Plane_Equal(&face2->plane, &f->plane, true)) break; } if (f) continue; // newface = Face_Alloc(); newface->texdef = face2->texdef; VectorCopy(face2->planepts[0], newface->planepts[0]); VectorCopy(face2->planepts[1], newface->planepts[1]); VectorCopy(face2->planepts[2], newface->planepts[2]); newface->plane = face2->plane; newface->next = newbrush->brush_faces; newbrush->brush_faces = newface; } // link the new brush to an entity Entity_LinkBrush (brush1->owner, newbrush); // build windings for the faces Brush_BuildWindings(newbrush); return newbrush; }
// // ======================================================================================================================= // parse a brush in brush primitive format // ======================================================================================================================= // void BrushPrimit_Parse(brush_t *b, bool newFormat, const idVec3 origin) { face_t *f; int i, j; GetToken(true); if (strcmp(token, "{")) { Warning("parsing brush primitive"); return; } do { if (!GetToken(true)) { break; } if (!strcmp(token, "}")) { break; } // reading of b->epairs if any if (strcmp(token, "(")) { ParseEpair(&b->epairs); } else { // it's a face f = Face_Alloc(); f->next = NULL; if (!b->brush_faces) { b->brush_faces = f; } else { face_t *scan; for (scan = b->brush_faces; scan->next; scan = scan->next) ; scan->next = f; } if (newFormat) { // read the three point plane definition idPlane plane; for (j = 0; j < 4; j++) { GetToken(false); plane[j] = atof(token); } f->plane = plane; f->originalPlane = plane; f->dirty = false; //idWinding *w = Brush_MakeFaceWinding(b, f, true); idWinding w; w.BaseForPlane( plane ); for (j = 0; j < 3; j++) { f->planepts[j].x = w[j].x + origin.x; f->planepts[j].y = w[j].y + origin.y; f->planepts[j].z = w[j].z + origin.z; } GetToken(false); } else { for (i = 0; i < 3; i++) { if (i != 0) { GetToken(true); } if (strcmp(token, "(")) { Warning("parsing brush"); return; } for (j = 0; j < 3; j++) { GetToken(false); f->planepts[i][j] = atof(token); } GetToken(false); if (strcmp(token, ")")) { Warning("parsing brush"); return; } } } // texture coordinates GetToken(false); if (strcmp(token, "(")) { Warning("parsing brush primitive"); return; } GetToken(false); if (strcmp(token, "(")) { Warning("parsing brush primitive"); return; } for (j = 0; j < 3; j++) { GetToken(false); f->brushprimit_texdef.coords[0][j] = atof(token); } GetToken(false); if (strcmp(token, ")")) { Warning("parsing brush primitive"); return; } GetToken(false); if (strcmp(token, "(")) { Warning("parsing brush primitive"); return; } for (j = 0; j < 3; j++) { GetToken(false); f->brushprimit_texdef.coords[1][j] = atof(token); } GetToken(false); if (strcmp(token, ")")) { Warning("parsing brush primitive"); return; } GetToken(false); if (strcmp(token, ")")) { Warning("parsing brush primitive"); return; } // read the texturedef GetToken(false); // strcpy(f->texdef.name, token); if (g_qeglobals.mapVersion < 2.0) { f->texdef.SetName(va("textures/%s", token)); } else { f->texdef.SetName(token); } if (TokenAvailable()) { GetToken(false); GetToken(false); GetToken(false); f->texdef.value = atoi(token); } } } while (1); }
void WrapFaces( face_t* top, face_t* bottom) { face_t* tempFace; int i; float maxX; float maxY; int pointFlag; tempFace = Face_Alloc(); //wrap the top face points the other way CopyFace(top, tempFace); for ( i = 0; i<top->face_winding->numpoints; i++) { VectorCopy(top->face_winding->points[top->face_winding->numpoints-1-i],tempFace->face_winding->points[i]); } CopyFace(tempFace,top); // top and bottom are now wrapped with normals pointing upward // now grab the point in top with most positive x (and y if there are more than one) maxX = top->face_winding->points[0][0]; maxY = top->face_winding->points[0][1]; pointFlag = 0; for ( i = 1; i<top->face_winding->numpoints; i++) { if ( maxX > top->face_winding->points[i][0] ) { continue; } else { if ( maxX == top->face_winding->points[i][0] ) { if (top->face_winding->points[i][1] > maxY) { maxY = top->face_winding->points[i][1]; pointFlag = i; } } else { maxX = top->face_winding->points[i][0]; maxY = top->face_winding->points[i][1]; pointFlag = i; } } } // now, starting at the point[pointflag] in top, write the sequence starting at [0] in tempFace for ( i = 0; i<top->face_winding->numpoints; i++) { if (pointFlag == top->face_winding->numpoints) { pointFlag = 0; } VectorCopy(top->face_winding->points[pointFlag], tempFace->face_winding->points[i]); pointFlag++; } CopyFace(tempFace,top); //repeat with bottom CopyFace(bottom, tempFace); maxX = bottom->face_winding->points[0][0]; maxY = bottom->face_winding->points[0][1]; pointFlag = 0; for ( i = 1; i<bottom->face_winding->numpoints; i++) { if ( maxX > bottom->face_winding->points[i][0] ) { continue; } else { if ( maxX == bottom->face_winding->points[i][0] ) { if (bottom->face_winding->points[i][1] > maxY) { maxY = bottom->face_winding->points[i][1]; pointFlag = i; } } else { maxX = bottom->face_winding->points[i][0]; maxY = bottom->face_winding->points[i][1]; pointFlag = i; } } } // now, starting at the point[pointflag] in bottom, write the sequence starting at [0] in tempFace for ( i = 0; i<bottom->face_winding->numpoints; i++) { if (pointFlag == bottom->face_winding->numpoints) { pointFlag = 0; } VectorCopy(bottom->face_winding->points[pointFlag], tempFace->face_winding->points[i]); pointFlag++; } CopyFace(tempFace,bottom); Face_Free(tempFace); return; }
void DoTower(void) { brush_t* brush1 = NULL; brush_t* brush2 = NULL; brush_t* newBrush = NULL; brush_t* tempBrush = NULL; face_t* topFace = NULL; face_t* bottomFace = NULL; face_t* curFace; face_t* faceList; int zFlag = 0; int i = 0; // loop counter if (g_qeglobals.d_select_count != 2) { Sys_Printf ("Error: you must have exactly 2 brushes selected\n"); Sys_Beep (); return; } brush1 = selected_brushes.next; brush2 = selected_brushes.next->next; // establish brush1 as the upper brush if (brush2->maxs[2] > brush1->mins[2]) { tempBrush = brush1; brush1 = brush2; brush2 = tempBrush; } // test to insure brushes do not "overlap" in the Z direction if (brush2->maxs[2] > brush1->mins[2]) { Sys_Printf ("Brushes are not separated in the Z direction!"); Sys_Beep(); return; } // find the bottom Z plane (topFace) in 1 and top Z plane in 2 (bottomFace) topFace = brush1->brush_faces; while (topFace != NULL) { zFlag = 0; for (i = 0; i<3; i++) { if (abs(topFace->planepts[i][2] - brush1->mins[2]) < TOWER_EPSILON) { zFlag++; } } if (zFlag == 3) { break; } else { topFace = topFace->next; } } if (topFace == NULL) { Sys_Printf("Couldn't find flat bottom-face in top brush", 0); Sys_Beep(); return; } bottomFace = brush2->brush_faces; while (bottomFace != NULL) { zFlag = 0; for (i = 0; i<3; i++) { if (abs(bottomFace->planepts[i][2] - brush2->maxs[2]) < TOWER_EPSILON) { zFlag++; } } if (zFlag == 3) { break; } else { bottomFace = bottomFace->next; } } if (bottomFace == NULL) { Sys_Printf ("Couldn't find flat top-face in bottom brush", 0); Sys_Beep(); return; } // count vertices on top and bottom planes to make sure they are equal if (topFace->face_winding->numpoints != bottomFace->face_winding->numpoints) { Sys_Printf ("Top and Bottom faces don't have same #'s of vertices!", 0); Sys_Beep(); return; } // put top and bottom faces on brush // reverse winding for top and bottom faceList = Face_Alloc(); for ( i = 0; i<3; i++) { VectorCopy(topFace->planepts[2-i],faceList->planepts[i]); } curFace = Face_Alloc(); for ( i = 0; i < 3; i++) { VectorCopy(bottomFace->planepts[2-i],curFace->planepts[i]); } curFace->next = faceList; faceList = curFace; curFace = MakePlaneList(topFace, bottomFace); if (curFace == NULL) { Sys_Printf ("Couldn't make planes for tower!", 0); Sys_Beep(); return; } else { faceList->next->next = curFace; } newBrush = (brush_t*)qmalloc(sizeof(brush_t)); newBrush->brush_faces = faceList; Select_Deselect(); Brush_AddToList (newBrush, &selected_brushes); Entity_LinkBrush (world_entity, newBrush); Brush_Build(newBrush); // UNDO_FinishBrushAdd("&Undo Tower"); Sys_UpdateWindows(W_ALL); return; }