ref: 64be9ec2f0fc074cdbbc0e9c8eda6ada27148fb1
parent: 8c5dd9f934fff1961ce71e7d28739ab5bcf96f1c
author: unknown <fabien@fabien-PC.(none)>
date: Sat Dec 15 18:51:07 EST 2012
Added A LOT of comments to explain methods: scansector,inside,bunchfront and wallfront.
--- a/Engine/src/build.h
+++ b/Engine/src/build.h
@@ -207,6 +207,8 @@
EXTERN uint8_t automapping;
EXTERN uint8_t gotpic[(MAXTILES+7)>>3];
+
+//This is the bit vector that marks visited sector during portal flooding. Size is hence (MAXSECTORS / 8)
EXTERN uint8_t gotsector[(MAXSECTORS+7)>>3];
/*************************************************************************
--- a/Engine/src/engine.c
+++ b/Engine/src/engine.c
@@ -101,25 +101,6 @@
char kensmessage[128];
-
-
-/* rcg02132001 Cygwin support. */
-#if (defined C_IDENTIFIERS_UNDERSCORED)
-#define SYM_sqrtable "_sqrtable"
-#define SYM_walock "_walock"
-#define SYM_shlookup "_shlookup"
-#define SYM_pow2char "_pow2char"
-#define SYM_gotpic "_gotpic"
-#define SYM_dmval "_dmval"
-#else
-#define SYM_sqrtable "sqrtable"
-#define SYM_walock "walock"
-#define SYM_shlookup "shlookup"
-#define SYM_pow2char "pow2char"
-#define SYM_gotpic "gotpic"
-#define SYM_dmval "dmval"
-#endif
-
uint8_t britable[16][64];
uint8_t textfont[1024], smalltextfont[1024];
@@ -187,8 +168,10 @@
int32_t globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx;
int32_t globalx, globaly, globalz;
-//Those two variables are using during portal flooding:
+//FCS:
+// Those two variables are using during portal flooding:
// sectorBorder is the stack and sectorbordercnt is the stack counter.
+// There is no really point to have this on the heap. That would have been better on the stack.
static short sectorborder[256], sectorbordercnt;
static uint8_t tablesloaded = 0;
@@ -228,8 +211,14 @@
static permfifotype permfifo[MAXPERMS];
static int32_t permhead = 0, permtail = 0;
-short numscans, numhits, numbunches;
+//FCS: Num walls to potentially render.
+short numscans ;
+short numbunches;
+
+//FCS: Number of colums to draw. ALWAYS set to the screen dimension width.
+short numhits;
+
short editstatus = 0;
short searchit;
int32_t searchx = -1, searchy; /* search input */
@@ -344,7 +333,7 @@
}
}
- //Mark the current sector as "visited"
+ //Mark the current sector bit as "visited" in the bitvector
gotsector[sectnum>>3] |= pow2char[sectnum&7];
bunchfrst = numbunches;
@@ -2445,19 +2434,34 @@
}
}
-//FCS: Geez one more horrible algorithm to decipher :| :/ :( cry smiley.....
-int wallfront(int32_t l1, int32_t l2)
+
+/*
+ FCS: Geez one more horrible algorithm to decipher :| :/ :( cry smiley.....
+ Algorithm:
+
+ 1.
+ Take wall 1 vector [point1,point2] and using two cross products determine if the two endpoints of wall 2 are on the same side of Wall 1 plan.
+ If they are then we can determine according to globalposx and globalposy if wall2 is before or after wall1's plan.
+
+ 2. Do the same thing again but this time with wall2's plan. Try to find if wall1 is in front of behind wall2's plan.
+
+ Key concept: If a cross-product is equal to 0 this mean they are parallel.
+
+ Return: pvWallID1 in the potentially visible wall list is in front of pvWallID2 (in the same potentially visible list)
+*/
+int wallfront(int32_t pvWallID1, int32_t pvWallID2)
{
walltype *wal;
int32_t x11, y11, x21, y21, x12, y12, x22, y22, dx, dy, t1, t2;
- wal = &wall[thewall[l1]];
+ //It seems we are going to work in Worldspace coordinates.
+ wal = &wall[thewall[pvWallID1]];
x11 = wal->x;
y11 = wal->y;
wal = &wall[wal->point2];
x21 = wal->x;
y21 = wal->y;
- wal = &wall[thewall[l2]];
+ wal = &wall[thewall[pvWallID2]];
x12 = wal->x;
y12 = wal->y;
wal = &wall[wal->point2];
@@ -2464,67 +2468,119 @@
x22 = wal->x;
y22 = wal->y;
+
+ //This is part 1
+
+ //Wall 1's vector
dx = x21-x11;
dy = y21-y11;
+
+ //This is a cross-product between Wall 1 vector and the [Wall 1 Point 1-> Wall 2 Point 1] vector
t1 = dmulscale2(x12-x11,dy,-dx,y12-y11); /* p1(l2) vs. l1 */
+ //This is a cross-product between Wall 1 vector and the [Wall 1 Point 1-> Wall 2 Point 2] vector
t2 = dmulscale2(x22-x11,dy,-dx,y22-y11); /* p2(l2) vs. l1 */
+ //If the vectors a parallel, then the cross-product is zero.
if (t1 == 0) {
+ //wall2's point1 is on wall1's plan.
t1 = t2;
- if (t1 == 0)
+ if (t1 == 0) // Those two walls are on the same plan.
+ {
+ //Wall 2's point 2 is on wall1's plan.
return(-1);
+ }
}
+ if (t2 == 0)
+ t2 = t1;
- if (t2 == 0) t2 = t1;
+
+ //This XOR just determine if the cross-product have the same sign and hence if both points are on the same side of wall 1 plan.
+ //Test if both points of wall2 are on the same side of wall 1 (in front or behind).
if ((t1^t2) >= 0)
{
+ //cross-product have the same sign: Both points of wall2 are on the same side of wall1 : An answer is possible !!
+
+ //Now is time to take into account the camera position and determine which of wall1 or wall2 is seen first.
t2 = dmulscale2(globalposx-x11,dy,-dx,globalposy-y11); /* pos vs. l1 */
+
+ //Test the cross product sign difference.
+ //If (t2^t1) >= 0 then both cross product had different sign so wall1 is in front of wall2
+ //otherwise wall2 is in front of wall1
return((t2^t1) >= 0);
}
+
+ //This is part 2
+ //Do it again but this time will wall2's plan.
+
+ //Wall 2's vector
dx = x22-x12;
dy = y22-y12;
+
t1 = dmulscale2(x11-x12,dy,-dx,y11-y12); /* p1(l1) vs. l2 */
t2 = dmulscale2(x21-x12,dy,-dx,y21-y12); /* p2(l1) vs. l2 */
if (t1 == 0) {
t1 = t2;
- if (t1 == 0) return(-1);
+ if (t1 == 0)
+ return(-1);
}
- if (t2 == 0) t2 = t1;
+ if (t2 == 0)
+ t2 = t1;
if ((t1^t2) >= 0)
{
t2 = dmulscale2(globalposx-x12,dy,-dx,globalposy-y12); /* pos vs. l2 */
return((t2^t1) < 0);
}
+
+ //FCS: No wall is in front of the other's plan: This means they are crossing.
return(-2);
}
-//Return 1 if bunch b1 is in from of bunch b2.
-static int bunchfront(int32_t b1, int32_t b2)
+//Return 1 if bunch firstBunchID is in from of bunch secondBunchID.
+static int bunchfront(int32_t firstBunchID, int32_t secondBunchID)
{
- int32_t x1b1, x2b1, x1b2, x2b2, b1f, b2f, i;
+ int32_t x1b1, x2b1, x1b2, x2b2, b2f;
- b1f = bunchfirst[b1];
- x1b1 = xb1[b1f];
- x2b2 = xb2[bunchlast[b2]]+1;
+ x1b1 = xb1[bunchfirst[firstBunchID]];
+ x2b2 = xb2[bunchlast[secondBunchID]]+1;
if (x1b1 >= x2b2)
+ {
+ //Bunch 1 left side is completely on the right of bunch2's right in screenspace: They do not overlap.
return(-1);
+ }
+
- b2f = bunchfirst[b2];
- x1b2 = xb1[b2f];
- x2b1 = xb2[bunchlast[b1]]+1;
- if (x1b2 >= x2b1) return(-1);
+ x1b2 = xb1[bunchfirst[secondBunchID]];
+ x2b1 = xb2[bunchlast[firstBunchID]]+1;
+ if (x1b2 >= x2b1)
+ {
+ //Bunch 2 left side is completely on the right of bunch 1 right side: They do not overlap.
+ return(-1);
+ }
+
if (x1b1 >= x1b2)
{
- for(i=b2f; xb2[i]<x1b1; i=p2[i]);
- return(wallfront(b1f,i));
+ //Get the last wall in the bunch2.
+ int lastWallID;
+ for(lastWallID=bunchfirst[secondBunchID];
+ xb2[lastWallID]<x1b1;
+ lastWallID=p2[lastWallID]);
+
+ return(wallfront(bunchfirst[firstBunchID],lastWallID));
}
-
- for(i=b1f; xb2[i]<x1b2; i=p2[i]);
- return(wallfront(i,b2f));
+ else
+ {
+ //Get the last wall in the bunch.
+ int lastWallID;
+ for(lastWallID=bunchfirst[firstBunchID];
+ xb2[lastWallID]<x1b2;
+ lastWallID=p2[lastWallID]);
+
+ return(wallfront(lastWallID,bunchfirst[secondBunchID]));
+ }
}
int pixelRenderable = 100000000;
@@ -2531,7 +2587,9 @@
void drawrooms(int32_t daposx, int32_t daposy, int32_t daposz,
short daang, int32_t dahoriz, short dacursectnum)
{
- int32_t i, j, z, cz, fz, closest;
+ int32_t i, j, z, closest;
+ //Ceiling and Floor height at the player position.
+ int32_t cz, fz;
short *shortptr1, *shortptr2;
// When visualizing the rendering process, part of the screen
@@ -2617,8 +2675,10 @@
frameoffset = frameplace+viewoffset;
+ //Clear the bit vector that keep track of what sector has been flooded in.
clearbufbyte(&gotsector[0],(long)((numsectors+7)>>3),0L);
+ //Clear the occlusion array.
shortptr1 = (short *)&startumost[windowx1];
shortptr2 = (short *)&startdmost[windowx1];
i = xdimen-1;
@@ -2631,8 +2691,11 @@
umost[0] = shortptr1[0]-windowy1;
dmost[0] = shortptr2[0]-windowy1;
+ //NumHits is the number of column to draw.
numhits = xdimen;
+ //Num walls to potentially render.
numscans = 0;
+
numbunches = 0;
maskwallcnt = 0;
smostwallcnt = 0;
@@ -2643,17 +2706,25 @@
globalcursectnum -= MAXSECTORS;
else
{
+ // Even if the player leaves the map, the engine will keep on rendering from the last visited sector.
+ // Save it.
i = globalcursectnum;
updatesector(globalposx,globalposy,&globalcursectnum);
- if (globalcursectnum < 0) globalcursectnum = i;
+ //Seem the player has left the map since updatesector cannot locate him -> Restore to the last known sector.
+ if (globalcursectnum < 0)
+ globalcursectnum = i;
}
globparaceilclip = 1;
globparaflorclip = 1;
+
+ //Update the ceiling and floor Z coordinate for the player's 2D position.
getzsofslope(globalcursectnum,globalposx,globalposy,&cz,&fz);
+
if (globalposz < cz) globparaceilclip = 0;
if (globalposz > fz) globparaflorclip = 0;
+ //Build the list of potentially visible wall in to "bunches".
scansector(globalcursectnum);
if (inpreparemirror)
@@ -2698,31 +2769,42 @@
mirrorsy2 = max(dmost[mirrorsx1],dmost[mirrorsx2]);
}
- // Scan sector has generated bunches, it is not time to see which one to render.
- // numhits is the number of column to draw (if the screen is 320x200) then numhits starts at 200.
- // Due to rounding error, not all column may be drawn so an additional stop condition is here:
+ // scansector has generated the bunches, it is now time to see which ones to render.
+ // numhits is the number of column of pixels to draw: (if the screen is 320x200 then numhits starts at 200).
+ // Due to rounding error, not all columns may be drawn so an additional stop condition is here:
// When every bunches have been tested for rendition.
while ((numbunches > 0) && (numhits > 0))
{
// tempbuf is used to mark which bunches have been elected as "closest".
- // if tempbug[x] == 1 then it should be discarded.
+ // if tempbug[x] == 1 then it should be skipped.
clearbuf(&tempbuf[0],(long)((numbunches+3)>>2),0L);
- tempbuf[0] = 1;
- closest = 0; /* Almost works, but not quite :( */
+ /* Almost works, but not quite :( */
+ closest = 0;
+ tempbuf[closest] = 1;
for(i=1; i<numbunches; i++)
{
- if ((j = bunchfront(i,closest)) < 0) continue;
+ if ((j = bunchfront(i,closest)) < 0)
+ continue;
tempbuf[i] = 1;
- if (j == 0) tempbuf[closest] = 1, closest = i;
+ if (j == 0){
+ tempbuf[closest] = 1;
+ closest = i;
+ }
}
- for(i=0; i<numbunches; i++) /* Double-check */
+ /* Double-check */
+ for(i=0; i<numbunches; i++)
{
- if (tempbuf[i]) continue;
- if ((j = bunchfront(i,closest)) < 0) continue;
+ if (tempbuf[i])
+ continue;
+ if ((j = bunchfront(i,closest)) < 0)
+ continue;
tempbuf[i] = 1;
- if (j == 0) tempbuf[closest] = 1, closest = i, i = 0;
+ if (j == 0){
+ tempbuf[closest] = 1;
+ closest = i, i = 0;
+ }
}
//Draw every solid walls with ceiling/floor in the bunch "closest"
@@ -2734,7 +2816,7 @@
show2dwall[thewall[z]>>3] |= pow2char[thewall[z]&7];
}
- //Since we just rendered a bunch, lower the current stack element
+ //Since we just rendered a bunch, lower the current stack element so we can treat the next item
numbunches--;
//...and move the bunch at the top of the stack so we won't iterate on it again...
bunchfirst[closest] = bunchfirst[numbunches];
--- a/Engine/src/mmulti_stable.cpp
+++ b/Engine/src/mmulti_stable.cpp
@@ -486,15 +486,12 @@
{
for(i = 0; i < gcom->numplayers-1; ++i)
{
- ENetPeer *peer;
+
char szHostName[64];
-
address.host = allowed_addresses[i].host; //ip;
address.port = allowed_addresses[i].port; //m_nPort;
-
-
enet_address_get_host(&address, szHostName, 64);
printf("Creating peer: %s:%d\n", szHostName, address.port);
@@ -750,7 +747,7 @@
{
PacketPeerGreeting packet;
unsigned int nPeerIndex;
- int i;
+
if(pEvent->packet->data[0] != HEADER_PEER_GREETING)
{