void RenderPolyScene::AddModel(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 pos) { if (PolyRenderer::Instance()->Level->nodes.Size() == 0) { subsector_t *sub = &PolyRenderer::Instance()->Level->subsectors[0]; if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentThing>(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue)); } else { void *node = PolyRenderer::Instance()->Level->HeadNode(); while (!((size_t)node & 1)) // Keep going until found a subsector { node_t *bsp = (node_t *)node; DVector2 planePos(FIXED2DBL(bsp->x), FIXED2DBL(bsp->y)); DVector2 planeNormal = DVector2(FIXED2DBL(-bsp->dy), FIXED2DBL(bsp->dx)); double planeD = planeNormal | planePos; int side = (pos | planeNormal) > planeD; node = bsp->children[side]; } subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentThing>(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, 0.0f, 1.0f, CurrentViewpoint->StencilValue)); } }
void RenderPolyScene::AddSprite(PolyRenderThread *thread, AActor *thing, double sortDistance, DVector2 left, DVector2 right, double t1, double t2, void *node) { while (!((size_t)node & 1)) // Keep going until found a subsector { node_t *bsp = (node_t *)node; DVector2 planePos(FIXED2DBL(bsp->x), FIXED2DBL(bsp->y)); DVector2 planeNormal = DVector2(FIXED2DBL(-bsp->dy), FIXED2DBL(bsp->dx)); double planeD = planeNormal | planePos; int sideLeft = (left | planeNormal) > planeD; int sideRight = (right | planeNormal) > planeD; if (sideLeft != sideRight) { double dotLeft = planeNormal | left; double dotRight = planeNormal | right; double t = (planeD - dotLeft) / (dotRight - dotLeft); DVector2 mid = left * (1.0 - t) + right * t; double tmid = t1 * (1.0 - t) + t2 * t; AddSprite(thread, thing, sortDistance, mid, right, tmid, t2, bsp->children[sideRight]); right = mid; t2 = tmid; } node = bsp->children[sideLeft]; } subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); if (Cull.SubsectorDepths[sub->Index()] != 0xffffffff) thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentThing>(thing, sub, Cull.SubsectorDepths[sub->Index()], sortDistance, (float)t1, (float)t2, CurrentViewpoint->StencilValue)); }
double floatvalue(const svalue_t &v) { return v.type == svt_string ? atof(v.string) : v.type == svt_fixed ? FIXED2DBL(v.value.f) : v.type == svt_mobj ? -1. : (double)v.value.i; }
uint32_t VisibleSpriteList::FindSubsectorDepth(RenderThread *thread, const DVector2 &worldPos, void *node) { while (!((size_t)node & 1)) // Keep going until found a subsector { node_t *bsp = (node_t *)node; DVector2 planePos(FIXED2DBL(bsp->x), FIXED2DBL(bsp->y)); DVector2 planeNormal = DVector2(FIXED2DBL(-bsp->dy), FIXED2DBL(bsp->dx)); double planeD = planeNormal | planePos; int side = (worldPos | planeNormal) > planeD; node = bsp->children[side]; } subsector_t *sub = (subsector_t *)((uint8_t *)node - 1); return thread->OpaquePass->GetSubsectorDepth(sub->Index()); }
bool APathFollower::Interpolate () { fixed_t dx = 0, dy = 0, dz = 0; if ((args[2] & 8) && Time > 0.f) { dx = X(); dy = Y(); dz = Z(); } if (CurrNode->Next==NULL) return false; UnlinkFromWorld (); fixed_t x, y, z; if (args[2] & 1) { // linear x = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->X()), FIXED2FLOAT(CurrNode->Next->X()))); y = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->Y()), FIXED2FLOAT(CurrNode->Next->Y()))); z = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->Z()), FIXED2FLOAT(CurrNode->Next->Z()))); } else { // spline if (CurrNode->Next->Next==NULL) return false; x = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->X()), FIXED2FLOAT(CurrNode->X()), FIXED2FLOAT(CurrNode->Next->X()), FIXED2FLOAT(CurrNode->Next->Next->X()))); y = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->Y()), FIXED2FLOAT(CurrNode->Y()), FIXED2FLOAT(CurrNode->Next->Y()), FIXED2FLOAT(CurrNode->Next->Next->Y()))); z = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->Z()), FIXED2FLOAT(CurrNode->Z()), FIXED2FLOAT(CurrNode->Next->Z()), FIXED2FLOAT(CurrNode->Next->Next->Z()))); } SetXYZ(x, y, z); LinkToWorld (); if (args[2] & 6) { if (args[2] & 8) { if (args[2] & 1) { // linear dx = CurrNode->Next->X() - CurrNode->X(); dy = CurrNode->Next->Y() - CurrNode->Y(); dz = CurrNode->Next->Z() - CurrNode->Z(); } else if (Time > 0.f) { // spline dx = x - dx; dy = y - dy; dz = z - dz; } else { int realarg = args[2]; args[2] &= ~(2|4|8); Time += 0.1f; dx = x; dy = y; dz = z; Interpolate (); Time -= 0.1f; args[2] = realarg; dx = x - dx; dy = y - dy; dz = z - dz; x -= dx; y -= dy; z -= dz; SetXYZ(x, y, z); } if (args[2] & 2) { // adjust yaw angle = R_PointToAngle2 (0, 0, dx, dy); } if (args[2] & 4) { // adjust pitch; use floats for precision double fdx = FIXED2DBL(dx); double fdy = FIXED2DBL(dy); double fdz = FIXED2DBL(-dz); double dist = sqrt (fdx*fdx + fdy*fdy); double ang = dist != 0.f ? atan2 (fdz, dist) : 0; pitch = (fixed_t)RAD2ANGLE(ang); } } else { if (args[2] & 2) { // interpolate angle float angle1 = (float)CurrNode->angle; float angle2 = (float)CurrNode->Next->angle; if (angle2 - angle1 <= -2147483648.f) { float lerped = Lerp (angle1, angle2 + 4294967296.f); if (lerped >= 4294967296.f) { angle = xs_CRoundToUInt(lerped - 4294967296.f); } else { angle = xs_CRoundToUInt(lerped); } } else if (angle2 - angle1 >= 2147483648.f) { float lerped = Lerp (angle1, angle2 - 4294967296.f); if (lerped < 0.f) { angle = xs_CRoundToUInt(lerped + 4294967296.f); } else { angle = xs_CRoundToUInt(lerped); } } else { angle = xs_CRoundToUInt(Lerp (angle1, angle2)); } } if (args[2] & 1) { // linear if (args[2] & 4) { // interpolate pitch pitch = FLOAT2FIXED(Lerp (FIXED2FLOAT(CurrNode->pitch), FIXED2FLOAT(CurrNode->Next->pitch))); } } else { // spline if (args[2] & 4) { // interpolate pitch pitch = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->pitch), FIXED2FLOAT(CurrNode->pitch), FIXED2FLOAT(CurrNode->Next->pitch), FIXED2FLOAT(CurrNode->Next->Next->pitch))); } } } } return true; }
void gl_InitPortals() { FPortalMap collection; if (numnodes == 0) return; for(int i=0;i<numnodes;i++) { node_t *no = &nodes[i]; // Must be converted because the len value is also needed for polyobjects. double fdx = FIXED2DBL(no->dx); double fdy = FIXED2DBL(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) { // add separate portals 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; 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, pair->Key.mDisplacement); } sec->portals[plane] = portal; } } } } } // Now group the line portals (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 portals 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 portals 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.); */ } }
static bool R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static { int boxx; int boxy; int boxpos; double x1, y1, x2, y2; double rx1, ry1, rx2, ry2; int sx1, sx2; cliprange_t* start; // Find the corners of the box // that define the edges from current viewpoint. if (ViewPos.X <= FIXED2DBL(bspcoord[BOXLEFT])) boxx = 0; else if (ViewPos.X < FIXED2DBL(bspcoord[BOXRIGHT])) boxx = 1; else boxx = 2; if (ViewPos.Y >= FIXED2DBL(bspcoord[BOXTOP])) boxy = 0; else if (ViewPos.Y > FIXED2DBL(bspcoord[BOXBOTTOM])) boxy = 1; else boxy = 2; boxpos = (boxy<<2)+boxx; if (boxpos == 5) return true; x1 = FIXED2DBL(bspcoord[checkcoord[boxpos][0]]) - ViewPos.X; y1 = FIXED2DBL(bspcoord[checkcoord[boxpos][1]]) - ViewPos.Y; x2 = FIXED2DBL(bspcoord[checkcoord[boxpos][2]]) - ViewPos.X; y2 = FIXED2DBL(bspcoord[checkcoord[boxpos][3]]) - ViewPos.Y; // check clip list for an open space // Sitting on a line? if (y1 * (x1 - x2) + x1 * (y2 - y1) >= -EQUAL_EPSILON) return true; rx1 = x1 * ViewSin - y1 * ViewCos; rx2 = x2 * ViewSin - y2 * ViewCos; ry1 = x1 * ViewTanCos + y1 * ViewTanSin; ry2 = x2 * ViewTanCos + y2 * ViewTanSin; if (MirrorFlags & RF_XFLIP) { double t = -rx1; rx1 = -rx2; rx2 = t; swapvalues(ry1, ry2); } if (rx1 >= -ry1) { if (rx1 > ry1) return false; // left edge is off the right side if (ry1 == 0) return false; sx1 = xs_RoundToInt(CenterX + rx1 * CenterX / ry1); } else { if (rx2 < -ry2) return false; // wall is off the left side if (rx1 - rx2 - ry2 + ry1 == 0) return false; // wall does not intersect view volume sx1 = 0; } if (rx2 <= ry2) { if (rx2 < -ry2) return false; // right edge is off the left side if (ry2 == 0) return false; sx2 = xs_RoundToInt(CenterX + rx2 * CenterX / ry2); } else { if (rx1 > ry1) return false; // wall is off the right side if (ry2 - ry1 - rx2 + rx1 == 0) return false; // wall does not intersect view volume sx2 = viewwidth; } // Find the first clippost that touches the source post // (adjacent pixels are touching). // Does not cross a pixel. if (sx2 <= sx1) return false; start = solidsegs; while (start->last < sx2) start++; if (sx1 >= start->first && sx2 <= start->last) { // The clippost contains the new span. return false; } return true; }