void gl_InitPortals() { FPortalMap collection; if (numnodes == 0) return; for(int i=0;i<numnodes;i++) { node_t *no = &nodes[i]; double fdx = (double)no->dx; double fdy = (double)no->dy; no->len = (float)sqrt(fdx * fdx + fdy * fdy); } CollectPortalSectors(collection); portals.Clear(); FPortalMap::Iterator it(collection); FPortalMap::Pair *pair; int c = 0; int planeflags = 0; while (it.NextPair(pair)) { for(unsigned i=0;i<pair->Value.Size(); i++) { if (pair->Value[i].mPlane == sector_t::floor) planeflags |= 1; else if (pair->Value[i].mPlane == sector_t::ceiling) planeflags |= 2; } for (int i=1;i<=2;i<<=1) { // For now, add separate portals for floor and ceiling. They can be merged once // proper plane clipping is in. if (planeflags & i) { FPortal *portal = new FPortal; portal->xDisplacement = pair->Key.mXDisplacement; portal->yDisplacement = pair->Key.mYDisplacement; portal->plane = (i==1? sector_t::floor : sector_t::ceiling); /**/ portal->glportal = NULL; portals.Push(portal); for(unsigned j=0;j<pair->Value.Size(); j++) { sector_t *sec = pair->Value[j].mSub; int plane = pair->Value[j].mPlane; if (portal->plane == plane) { for(int k=0;k<sec->subsectorcount; k++) { subsector_t *sub = sec->subsectors[k]; gl_BuildPortalCoverage(&sub->portalcoverage[plane], sub, portal); } sec->portals[plane] = portal; } } } } } }
void gl_InitPortals() { FPortalMap collection; if (level.nodes.Size() == 0) return; CollectPortalSectors(collection); glSectorPortals.Clear(); FPortalMap::Iterator it(collection); FPortalMap::Pair *pair; int c = 0; int planeflags = 0; while (it.NextPair(pair)) { for(unsigned i=0;i<pair->Value.Size(); i++) { if (pair->Value[i].mPlane == sector_t::floor) planeflags |= 1; else if (pair->Value[i].mPlane == sector_t::ceiling) planeflags |= 2; } for (int i=1;i<=2;i<<=1) { // add separate glSectorPortals for floor and ceiling. if (planeflags & i) { FPortal *portal = new FPortal; portal->mDisplacement = pair->Key.mDisplacement; portal->plane = (i==1? sector_t::floor : sector_t::ceiling); /**/ portal->glportal = NULL; glSectorPortals.Push(portal); for(unsigned j=0;j<pair->Value.Size(); j++) { sector_t *sec = pair->Value[j].mSub; int plane = pair->Value[j].mPlane; if (portal->plane == plane) { for(int k=0;k<sec->subsectorcount; k++) { subsector_t *sub = sec->subsectors[k]; gl_BuildPortalCoverage(&sub->portalcoverage[plane], sub, pair->Key.mDisplacement); } sec->portals[plane] = portal; } } } } } // Now group the line glSectorPortals (each group must be a continuous set of colinear linedefs with no gaps) glLinePortals.Clear(); linePortalToGL.Clear(); TArray<int> tempindex; tempindex.Reserve(linePortals.Size()); memset(&tempindex[0], -1, linePortals.Size() * sizeof(int)); for (unsigned i = 0; i < linePortals.Size(); i++) { auto port = linePortals[i]; bool gotsome; if (tempindex[i] == -1) { tempindex[i] = glLinePortals.Size(); line_t *pSrcLine = linePortals[i].mOrigin; line_t *pLine = linePortals[i].mDestination; FGLLinePortal &glport = glLinePortals[glLinePortals.Reserve(1)]; glport.lines.Push(&linePortals[i]); // We cannot do this grouping for non-linked glSectorPortals because they can be changed at run time. if (linePortals[i].mType == PORTT_LINKED && pLine != nullptr) { glport.v1 = pLine->v1; glport.v2 = pLine->v2; do { // now collect all other colinear lines connected to this one. We run this loop as long as it still finds a match gotsome = false; for (unsigned j = 0; j < linePortals.Size(); j++) { if (tempindex[j] == -1) { line_t *pSrcLine2 = linePortals[j].mOrigin; line_t *pLine2 = linePortals[j].mDestination; // angular precision is intentionally reduced to 32 bit BAM to account for precision problems (otherwise many not perfectly horizontal or vertical glSectorPortals aren't found here.) unsigned srcang = pSrcLine->Delta().Angle().BAMs(); unsigned dstang = pLine->Delta().Angle().BAMs(); if ((pSrcLine->v2 == pSrcLine2->v1 && pLine->v1 == pLine2->v2) || (pSrcLine->v1 == pSrcLine2->v2 && pLine->v2 == pLine2->v1)) { // The line connects, now check the translation unsigned srcang2 = pSrcLine2->Delta().Angle().BAMs(); unsigned dstang2 = pLine2->Delta().Angle().BAMs(); if (srcang == srcang2 && dstang == dstang2) { // The lines connect and both source and destination are colinear, so this is a match gotsome = true; tempindex[j] = tempindex[i]; if (pLine->v1 == pLine2->v2) glport.v1 = pLine2->v1; else glport.v2 = pLine2->v2; glport.lines.Push(&linePortals[j]); } } } } } while (gotsome); } } } linePortalToGL.Resize(linePortals.Size()); for (unsigned i = 0; i < linePortals.Size(); i++) { linePortalToGL[i] = &glLinePortals[tempindex[i]]; /* Printf("portal at line %d translates to GL portal %d, range = %f,%f to %f,%f\n", int(linePortals[i].mOrigin - lines), tempindex[i], linePortalToGL[i]->v1->fixX() / 65536., linePortalToGL[i]->v1->fixY() / 65536., linePortalToGL[i]->v2->fixX() / 65536., linePortalToGL[i]->v2->fixY() / 65536.); */ } }