static void PrepMObj(mobj_t *thing) { Fixed Trx,Try,Trz; Word lump; LongWord Offset; vissprite_t *vis; state_t *StatePtr; void **PatchHandle; patch_t *patch; int x1, x2; /* This is a HACK, so I don't draw the player for the 3DO version */ if (thing->player) { /* Don't draw the player */ return; } /* Transform the origin point */ vis = vissprite_p; if (vis == &vissprites[MAXVISSPRITES]) { /* Too many? */ return; /* sprite overload, don't draw it */ } Trx = thing->x - viewx; /* Get the point in 3 Space */ Try = thing->y - viewy; Trz = IMFixMul(Trx,viewcos); /* Rotate around the camera */ Trz += IMFixMul(Try,viewsin); /* Add together */ if (Trz < MINZ) { /* Too large? */ return; /* Exit now */ } Trx = IMFixMul(Trx,viewsin); /* Calc the 3Space x coord */ Trx -= IMFixMul(Try,viewcos); if (Trx > (Trz<<2) || Trx < -(Trz<<2) ) { return; /* Greater than 45 degrees off the side */ } /* Decide which patch to use for sprite relative to player */ StatePtr = thing->state; lump = StatePtr->SpriteFrame>>FF_SPRITESHIFT; /* Get the resource # */ PatchHandle = LoadAResourceHandle(lump); /* Get the sprite group */ patch = (patch_t *)*PatchHandle; /* Deref the handle */ Offset = ((LongWord *)patch)[StatePtr->SpriteFrame & FF_FRAMEMASK]; if (Offset&PT_NOROTATE) { /* Do I rotate? */ angle_t ang; angle_t rot; patch = (patch_t *)&((Byte *)patch)[Offset & 0x3FFFFFFF]; /* Get pointer to rotation list */ ang = PointToAngle(viewx,viewy,thing->x,thing->y); /* Get angle to critter */ ang -= thing->angle; /* Adjust for object's facing */ rot = (ang+(angle_t)((ANG45/2)*9U))>>29; /* Get rotation offset */ Offset = ((LongWord *)patch)[rot]; /* Use the rotated offset */ }
int FNodeBuilder::CloseSubsector (TArray<seg_t> &segs, int subsector, vertex_t *outVerts) { FPrivSeg *seg, *prev; angle_t prevAngle; double accumx, accumy; fixed_t midx, midy; int firstVert; DWORD first, max, count, i, j; first = Subsectors[subsector].firstline; max = first + Subsectors[subsector].numlines; count = 0; accumx = accumy = 0.0; for (i = first; i < max; ++i) { seg = &Segs[SegList[i].SegNum]; accumx += double(Vertices[seg->v1].x) + double(Vertices[seg->v2].x); accumy += double(Vertices[seg->v1].y) + double(Vertices[seg->v2].y); } midx = fixed_t(accumx / (max - first) / 2); midy = fixed_t(accumy / (max - first) / 2); seg = &Segs[SegList[first].SegNum]; prevAngle = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); seg->storedseg = PushGLSeg (segs, seg, outVerts); count = 1; prev = seg; firstVert = seg->v1; for (i = first + 1; i < max; ++i) { angle_t bestdiff = ANGLE_MAX; FPrivSeg *bestseg = NULL; DWORD bestj = DWORD_MAX; j = first; do { seg = &Segs[SegList[j].SegNum]; angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); angle_t diff = prevAngle - ang; if (seg->v1 == prev->v2) { bestdiff = diff; bestseg = seg; bestj = j; break; } if (diff < bestdiff && diff > 0) { bestdiff = diff; bestseg = seg; bestj = j; } } while (++j < max); // Is a NULL bestseg actually okay? if (bestseg != NULL) { seg = bestseg; } if (prev->v2 != seg->v1) { // Add a new miniseg to connect the two segs PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[seg->v1]); count++; } prevAngle -= bestdiff; seg->storedseg = PushGLSeg (segs, seg, outVerts); count++; prev = seg; if (seg->v2 == firstVert) { prev = seg; break; } } if (prev->v2 != firstVert) { PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[firstVert]); count++; } return count; }
int FNodeBuilder::CloseSubsector (TArray<glseg_t> &segs, int subsector, vertex_t *outVerts) { FPrivSeg *seg, *prev; angle_t prevAngle; double accumx, accumy; fixed_t midx, midy; int firstVert; uint32_t first, max, count, i, j; bool diffplanes; int firstplane; first = (uint32_t)(size_t)Subsectors[subsector].firstline; max = first + Subsectors[subsector].numlines; count = 0; accumx = accumy = 0.0; diffplanes = false; firstplane = Segs[SegList[first].SegNum].planenum; // Calculate the midpoint of the subsector and also check for degenerate subsectors. // A subsector is degenerate if it exists in only one dimension, which can be // detected when all the segs lie in the same plane. This can happen if you have // outward-facing lines in the void that don't point toward any sector. (Some of the // polyobjects in Hexen are constructed like this.) for (i = first; i < max; ++i) { seg = &Segs[SegList[i].SegNum]; accumx += double(Vertices[seg->v1].x) + double(Vertices[seg->v2].x); accumy += double(Vertices[seg->v1].y) + double(Vertices[seg->v2].y); if (firstplane != seg->planenum) { diffplanes = true; } } midx = fixed_t(accumx / (max - first) / 2); midy = fixed_t(accumy / (max - first) / 2); seg = &Segs[SegList[first].SegNum]; prevAngle = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); seg->storedseg = PushGLSeg (segs, seg, outVerts); count = 1; prev = seg; firstVert = seg->v1; #ifdef DD Printf(PRINT_LOG, "--%d--\n", subsector); for (j = first; j < max; ++j) { seg = &Segs[SegList[j].SegNum]; angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); Printf(PRINT_LOG, "%d%c %5d(%5d,%5d)->%5d(%5d,%5d) - %3.5f %d,%d [%08x,%08x]-[%08x,%08x]\n", j, seg->linedef == -1 ? '+' : ':', seg->v1, Vertices[seg->v1].x>>16, Vertices[seg->v1].y>>16, seg->v2, Vertices[seg->v2].x>>16, Vertices[seg->v2].y>>16, double(ang/2)*180/(1<<30), seg->planenum, seg->planefront, Vertices[seg->v1].x, Vertices[seg->v1].y, Vertices[seg->v2].x, Vertices[seg->v2].y); } #endif if (diffplanes) { // A well-behaved subsector. Output the segs sorted by the angle formed by connecting // the subsector's center to their first vertex. D(Printf(PRINT_LOG, "Well behaved subsector\n")); for (i = first + 1; i < max; ++i) { angle_t bestdiff = ANGLE_MAX; FPrivSeg *bestseg = NULL; uint32_t bestj = DWORD_MAX; j = first; do { seg = &Segs[SegList[j].SegNum]; angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); angle_t diff = prevAngle - ang; if (seg->v1 == prev->v2) { bestdiff = diff; bestseg = seg; bestj = j; break; } if (diff < bestdiff && diff > 0) { bestdiff = diff; bestseg = seg; bestj = j; } } while (++j < max); // Is a NULL bestseg actually okay? if (bestseg != NULL) { seg = bestseg; } if (prev->v2 != seg->v1) { // Add a new miniseg to connect the two segs PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[seg->v1]); count++; } #ifdef DD Printf(PRINT_LOG, "+%d\n", bestj); #endif prevAngle -= bestdiff; seg->storedseg = PushGLSeg (segs, seg, outVerts); count++; prev = seg; if (seg->v2 == firstVert) { prev = seg; break; } } #ifdef DD Printf(PRINT_LOG, "\n"); #endif } else { // A degenerate subsector. These are handled in three stages: // Stage 1. Proceed in the same direction as the start seg until we // hit the seg furthest from it. // Stage 2. Reverse direction and proceed until we hit the seg // furthest from the start seg. // Stage 3. Reverse direction again and insert segs until we get // to the start seg. // A dot product serves to determine distance from the start seg. D(Printf(PRINT_LOG, "degenerate subsector\n")); // Stage 1. Go forward. count += OutputDegenerateSubsector (segs, subsector, true, 0, prev, outVerts); // Stage 2. Go backward. count += OutputDegenerateSubsector (segs, subsector, false, DBL_MAX, prev, outVerts); // Stage 3. Go forward again. count += OutputDegenerateSubsector (segs, subsector, true, -DBL_MAX, prev, outVerts); } if (prev->v2 != firstVert) { PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[firstVert]); count++; } #ifdef DD Printf(PRINT_LOG, "Output GL subsector %d:\n", subsector); for (i = segs.Size() - count; i < (int)segs.Size(); ++i) { Printf(PRINT_LOG, " Seg %5d%c(%5d,%5d)-(%5d,%5d) [%08x,%08x]-[%08x,%08x]\n", i, segs[i].linedef == NULL ? '+' : ' ', segs[i].v1->fixX()>>16, segs[i].v1->fixY()>>16, segs[i].v2->fixX()>>16, segs[i].v2->fixY()>>16, segs[i].v1->fixX(), segs[i].v1->fixY(), segs[i].v2->fixX(), segs[i].v2->fixY()); } #endif return count; }
int FNodeBuilder::CloseSubsector (TArray<seg_t> &segs, int subsector, vertex_t *outVerts) { FPrivSeg *seg, *prev; angle_t prevAngle; double accumx, accumy; fixed_t midx, midy; int firstVert; DWORD first, max, count, i, j; bool diffplanes; int firstplane; first = Subsectors[subsector].firstline; max = first + Subsectors[subsector].numlines; count = 0; accumx = accumy = 0.0; diffplanes = false; firstplane = Segs[SegList[first].SegNum].planenum; // Calculate the midpoint of the subsector and also check for degenerate subsectors. // A subsector is degenerate if it exists in only one dimension, which can be // detected when all the segs lie in the same plane. This can happen if you have // outward-facing lines in the void that don't point toward any sector. (Some of the // polyobjects in Hexen are constructed like this.) for (i = first; i < max; ++i) { seg = &Segs[SegList[i].SegNum]; accumx += double(Vertices[seg->v1].x) + double(Vertices[seg->v2].x); accumy += double(Vertices[seg->v1].y) + double(Vertices[seg->v2].y); if (firstplane != seg->planenum) { diffplanes = true; } } midx = fixed_t(accumx / (max - first) / 2); midy = fixed_t(accumy / (max - first) / 2); seg = &Segs[SegList[first].SegNum]; prevAngle = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); seg->storedseg = PushGLSeg (segs, seg, outVerts); count = 1; prev = seg; firstVert = seg->v1; if (diffplanes) { // A well-behaved subsector. Output the segs sorted by the angle formed by connecting // the subsector's center to their first vertex. for (i = first + 1; i < max; ++i) { angle_t bestdiff = ANGLE_MAX; FPrivSeg *bestseg = NULL; DWORD bestj = DWORD_MAX; j = first; do { seg = &Segs[SegList[j].SegNum]; angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); angle_t diff = prevAngle - ang; if (seg->v1 == prev->v2) { bestdiff = diff; bestseg = seg; bestj = j; break; } if (diff < bestdiff && diff > 0) { bestdiff = diff; bestseg = seg; bestj = j; } } while (++j < max); // Is a NULL bestseg actually okay? if (bestseg != NULL) { seg = bestseg; } if (prev->v2 != seg->v1) { // Add a new miniseg to connect the two segs PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[seg->v1]); count++; } prevAngle -= bestdiff; seg->storedseg = PushGLSeg (segs, seg, outVerts); count++; prev = seg; if (seg->v2 == firstVert) { prev = seg; break; } } } else { // A degenerate subsector. These are handled in three stages: // Stage 1. Proceed in the same direction as the start seg until we // hit the seg furthest from it. // Stage 2. Reverse direction and proceed until we hit the seg // furthest from the start seg. // Stage 3. Reverse direction again and insert segs until we get // to the start seg. // A dot product serves to determine distance from the start seg. // Stage 1. Go forward. count += OutputDegenerateSubsector (segs, subsector, true, 0, prev, outVerts); // Stage 2. Go backward. count += OutputDegenerateSubsector (segs, subsector, false, DBL_MAX, prev, outVerts); // Stage 3. Go forward again. count += OutputDegenerateSubsector (segs, subsector, true, -DBL_MAX, prev, outVerts); } if (prev->v2 != firstVert) { PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[firstVert]); count++; } return count; }