Tetra *MakeTetra(Face *f,Point3 *v[], int n) { Plane p,Mp; boolean found=FALSE; double Radius=BIGNUMBER, rad; Line Lc; int pind=0; Tetra *t; Point3 Center, c; int i; if(!CalcPlane(f->v[0],f->v[1],f->v[2],&p)) Error("MakeTetra, Face with collinar vertices!\n",EXIT); CalcLineofCenter(f->v[0],f->v[1],f->v[2],&Lc); for(i=0;i<n;i++) { if((v[i]!=f->v[0]) && (v[i]!=f->v[1]) && (v[i]!=f->v[2]) && RightSide(&p,v[i]) ) { CalcMiddlePlane(v[i],f->v[0],&Mp); if(CalcLinePlaneInter(&Lc,&Mp,&c)) { rad=V3SquaredDistanceBetween2Points(&c, v[i]); if(!RightSide(&p,&c)) rad=-rad; if(rad==Radius) Error("MakeTetra, Five cocircular points!\n",EXIT); if(rad<Radius) { found=TRUE; Radius=rad; Center=c; pind=i; } } } } if(!found) return NULL; t=BuildTetra(f,v[pind]); if(CheckFlag) CheckTetra(t,v,n); if(StatFlag) {Point3 C; CalcSphereCenter(f->v[0], f->v[1], f->v[2], v[pind], &C); SI.Radius+=V3DistanceBetween2Points(&C, v[pind]); } return t; }
int InitGLObjects() // Initialize Objects { if (!ReadObject("Data/Object2.txt", &obj)) // Read Object2 Into obj { return FALSE; // If Failed Return False } SetConnectivity(&obj); // Set Face To Face Connectivity for (unsigned int i=0;i<obj.nPlanes;i++) // Loop Through All Object Planes CalcPlane(obj, &(obj.planes[i])); // Compute Plane Equations For All Faces return TRUE; // Return True }
Line *CalcLineofCenter(Point3 *p1, Point3 *p2, Point3 *p3, Line *l) { Plane pl1,pl2,pl3; CalcMiddlePlane(p1,p2,&pl1); CalcMiddlePlane(p1,p3,&pl2); CalcPlane(p1,p2,p3,&pl3); CalcPlaneInter(&pl1,&pl2,&pl3,&(l->Lu)); l->Lv=pl3.N; return l; }
Tetra *FirstTetra(Point3 *v[], int n) { int i, MinIndex=0; double Radius, MinRadius=BIGNUMBER; Tetra *t; Plane p[3], Mp; Line Lc; Face f; Point3 c; boolean found=FALSE; f.v[0]=v[n/2-1]; /* The first point of the face is the */ /* nearest to middle plane in negative */ /* halfspace. */ /* The 2nd point of the face is the */ /* euclidean nearest to first point */ for(i=n/2;i<n;i++) /* that is in the positive halfspace */ { Radius=V3SquaredDistanceBetween2Points(f.v[0], v[i]); if(Radius<MinRadius) { MinRadius=Radius; MinIndex=i; } } f.v[1]=v[MinIndex]; /* The 3rd point is that with previous */ /* ones builds the smallest circle. */ CalcMiddlePlane(f.v[0],f.v[1], &(p[0])); MinRadius=BIGNUMBER; for(i=0;i<n;i++) if(v[i]!=f.v[0] && v[i]!=f.v[1]) { CalcMiddlePlane(f.v[0], v[i],&(p[1])); if(CalcPlane(f.v[0],f.v[1],v[i],&(p[2]))) if(CalcPlaneInter(&(p[0]), &(p[1]), &(p[2]), &c)) { Radius=V3DistanceBetween2Points(&c, f.v[0]); if(Radius<MinRadius) { MinRadius=Radius; MinIndex=i; } } } f.v[2]=v[MinIndex]; /* The first tetrahedron construction is analogous to normal */ /* MakeTetra, only we dont limit search to an halfspace. */ MinRadius=BIGNUMBER; CalcPlane(f.v[0], f.v[1], f.v[2],&p[0]); CalcLineofCenter(f.v[0], f.v[1], f.v[2], &Lc); for(i=0;i<n;i++) if(v[i]!=f.v[0] && v[i]!=f.v[1] && v[i]!=f.v[2] ) { CalcMiddlePlane(v[i], f.v[0], &Mp); if(CalcLinePlaneInter(&Lc, &Mp, &c)) { Radius=V3SquaredDistanceBetween2Points(&c, v[i]); if(MinRadius==Radius) Error("FirstTetra, Five cocircular points!\n",EXIT); if(Radius<MinRadius) { found=TRUE; MinRadius=Radius; MinIndex=i; } } } if(!found) Error("FirstTetra, Planar dataset, unable to build first tetrahedron.\n",EXIT); if(!RightSide(&p[0],v[MinIndex])) ReverseFace(&f); t=BuildTetra(&f, v[MinIndex]); CheckTetra(t,v,n); ReverseFace(t->f[0]); /* First Face in first Tetra */ /* must be outward oriented */ return t; }
static void LoadWalls (walltype *walls, int numwalls, sectortype *bsec) { int i, j; // Setting numvertexes to the same as numwalls is overly conservative, // but the extra vertices will be removed during the BSP building pass. numsides = numvertexes = numwalls; numlines = 0; sides = new side_t[numsides]; memset (sides, 0, numsides*sizeof(side_t)); vertexes = new vertex_t[numvertexes]; numvertexes = 0; // First mark each sidedef with the sector it belongs to for (i = 0; i < numsectors; ++i) { if (bsec[i].wallptr >= 0) { for (j = 0; j < bsec[i].wallnum; ++j) { sides[j + bsec[i].wallptr].sector = sectors + i; } } } // Now copy wall properties to their matching sidedefs for (i = 0; i < numwalls; ++i) { char tnam[9]; FTextureID overpic, pic; mysnprintf (tnam, countof(tnam), "BTIL%04d", LittleShort(walls[i].picnum)); pic = TexMan.GetTexture (tnam, FTexture::TEX_Build); mysnprintf (tnam, countof(tnam), "BTIL%04d", LittleShort(walls[i].overpicnum)); overpic = TexMan.GetTexture (tnam, FTexture::TEX_Build); walls[i].x = LittleLong(walls[i].x); walls[i].y = LittleLong(walls[i].y); walls[i].point2 = LittleShort(walls[i].point2); walls[i].cstat = LittleShort(walls[i].cstat); walls[i].nextwall = LittleShort(walls[i].nextwall); walls[i].nextsector = LittleShort(walls[i].nextsector); sides[i].SetTextureXOffset(walls[i].xpanning << FRACBITS); sides[i].SetTextureYOffset(walls[i].ypanning << FRACBITS); sides[i].SetTexture(side_t::top, pic); sides[i].SetTexture(side_t::bottom, pic); if (walls[i].nextsector < 0 || (walls[i].cstat & 32)) { sides[i].SetTexture(side_t::mid, pic); } else if (walls[i].cstat & 16) { sides[i].SetTexture(side_t::mid, overpic); } else { sides[i].SetTexture(side_t::mid, FNullTextureID()); } sides[i].TexelLength = walls[i].xrepeat * 8; sides[i].SetTextureYScale(walls[i].yrepeat << (FRACBITS - 3)); sides[i].SetTextureXScale(FRACUNIT); sides[i].SetLight(SHADE2LIGHT(walls[i].shade)); sides[i].Flags = WALLF_ABSLIGHTING; sides[i].RightSide = walls[i].point2; sides[walls[i].point2].LeftSide = i; if (walls[i].nextwall >= 0 && walls[i].nextwall <= i) { sides[i].linedef = sides[walls[i].nextwall].linedef; } else { sides[i].linedef = (line_t*)(intptr_t)(numlines++); } } // Set line properties that Doom doesn't store per-sidedef lines = new line_t[numlines]; memset (lines, 0, numlines*sizeof(line_t)); for (i = 0, j = -1; i < numwalls; ++i) { if (walls[i].nextwall >= 0 && walls[i].nextwall <= i) { continue; } j = int(intptr_t(sides[i].linedef)); lines[j].sidedef[0] = (side_t*)(intptr_t)i; lines[j].sidedef[1] = (side_t*)(intptr_t)walls[i].nextwall; lines[j].v1 = FindVertex (walls[i].x, walls[i].y); lines[j].v2 = FindVertex (walls[walls[i].point2].x, walls[walls[i].point2].y); lines[j].frontsector = sides[i].sector; lines[j].flags |= ML_WRAP_MIDTEX; if (walls[i].nextsector >= 0) { lines[j].backsector = sectors + walls[i].nextsector; lines[j].flags |= ML_TWOSIDED; } else { lines[j].backsector = NULL; } P_AdjustLine (&lines[j]); if (walls[i].cstat & 128) { if (walls[i].cstat & 512) { lines[j].Alpha = FRACUNIT/3; } else { lines[j].Alpha = FRACUNIT*2/3; } } if (walls[i].cstat & 1) { lines[j].flags |= ML_BLOCKING; } if (walls[i].nextwall < 0) { if (walls[i].cstat & 4) { lines[j].flags |= ML_DONTPEGBOTTOM; } } else { if (walls[i].cstat & 4) { lines[j].flags |= ML_DONTPEGTOP; } else { lines[j].flags |= ML_DONTPEGBOTTOM; } } if (walls[i].cstat & 64) { lines[j].flags |= ML_BLOCKEVERYTHING; } } // Finish setting sector properties that depend on walls for (i = 0; i < numsectors; ++i, ++bsec) { SlopeWork slope; slope.wal = &walls[bsec->wallptr]; slope.wal2 = &walls[slope.wal->point2]; slope.dx = slope.wal2->x - slope.wal->x; slope.dy = slope.wal2->y - slope.wal->y; slope.i = long (sqrt ((double)(slope.dx*slope.dx+slope.dy*slope.dy))) << 5; if (slope.i == 0) { continue; } if ((bsec->floorstat & 2) && (bsec->floorheinum != 0)) { // floor is sloped slope.heinum = -LittleShort(bsec->floorheinum); slope.z[0] = slope.z[1] = slope.z[2] = -bsec->floorz; CalcPlane (slope, sectors[i].floorplane); } if ((bsec->ceilingstat & 2) && (bsec->ceilingheinum != 0)) { // ceiling is sloped slope.heinum = -LittleShort(bsec->ceilingheinum); slope.z[0] = slope.z[1] = slope.z[2] = -bsec->ceilingz; CalcPlane (slope, sectors[i].ceilingplane); } int linenum = int(intptr_t(sides[bsec->wallptr].linedef)); int sidenum = int(intptr_t(lines[linenum].sidedef[1])); if (bsec->floorstat & 64) { // floor is aligned to first wall P_AlignFlat (linenum, sidenum == bsec->wallptr, 0); } if (bsec->ceilingstat & 64) { // ceiling is aligned to first wall P_AlignFlat (linenum, sidenum == bsec->wallptr, 0); } } for (i = 0; i < numlines; i++) { intptr_t front = intptr_t(lines[i].sidedef[0]); intptr_t back = intptr_t(lines[i].sidedef[1]); lines[i].sidedef[0] = front >= 0 ? &sides[front] : NULL; lines[i].sidedef[1] = back >= 0 ? &sides[back] : NULL; } for (i = 0; i < numsides; i++) { assert(sides[i].sector != NULL); sides[i].linedef = &lines[intptr_t(sides[i].linedef)]; } }
Tetra *FastMakeTetra(Face *f, Point3 *v, int n, UG *G) { Plane p; Tetra *t; float CellBoxRadius= 0.0, /* Radius of Cell Box to scan for dd-nearest */ BoxRadius, FaceRadius, MinRadius=BIGNUMBER; struct argGroup args; Line Lc; IntPoint3 vn,vp, start, end, inc; int Index=-1; boolean Found=FALSE; SI.MakeTetra++; UGResetMark(G); if(!CalcPlane(&(v[f->v[0]]),&(v[f->v[1]]),&(v[f->v[2]]),&p)) Error("Faccia composta da tre punti allineati!!\n",EXIT); CalcLineofCenter(&(v[f->v[0]]),&(v[f->v[1]]),&(v[f->v[2]]),&Lc); FaceRadius=V3DistanceBetween2Points(&(Lc.Lu), &(v[f->v[0]])); args.f = f; args.Lc = &Lc; args.p = &p; args.G = G; // printf("checkpoint 0\n"); do { CellBoxRadius++; BoxRadius=CalcBox(f,v,&Lc,G,&vn,&vp, CellBoxRadius*FaceRadius); Found=ScanCellBox(&vn, &vp, v,&args,&Index, &MinRadius); } while(!Found && CellBoxRadius <= 1); //printf("checkpoint 1\n"); // printf("MinRadius = %f BoxRadius = %f\n",MinRadius, BoxRadius); if(Found && MinRadius>BoxRadius) {float oldMinRadius=MinRadius; SI.SecondBox++; // printf("f->v[0] = %d, f->v[1] = %d, f->v[2] = %d, sqrt(MinRadius) = %f\n",f->v[0],f->v[1],f->v[2], sqrt(MinRadius)); BoxRadius=CalcBox(f,v,&Lc,G,&vn,&vp, sqrt(MinRadius)); // printf("checkpoint 2\n"); //printf("vn->x = %d ,vn->y = %d, vn->z = %d, vp->x = %d, vp->y = %d, vp->z = %d, radius = %f\n",vn.x, vn.y, vn.z, vp.x, vp.y,vp.z,MinRadius); ScanCellBox(&vn, &vp, v, &args, &Index, &MinRadius); //printf("checkpoint 2.1\n"); if(oldMinRadius>MinRadius) SI.UsefulSecondBox++; } if(!Found) { //printf("checkpoint 3\n"); SI.EmptyBox++; CalcLastScan(G, &start, &end, &inc, &p); //printf("checkpoint 4\n"); Found=MakeLastScan(&start, &end, &inc, v, &args, &Index,&MinRadius); } //printf("chekpoint 5\n"); if(!Found) return NULL; if(MinRadius>0) { SI.MinRadius+=sqrt(MinRadius); SI.MinRadiusNum++; } t=BuildTetra(f,Index); if(StatFlag) {Point3 C; CalcSphereCenter(&(v[f->v[0]]),&(v[f->v[1]]),&(v[f->v[2]]),&(v[Index]),&C); SI.Radius+=V3DistanceBetween2Points(&C, &(v[Index])); } if(CheckFlag) CheckTetra(t,v,n); return t; }