1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-14 00:54:05 +02:00

floor & ceiling triangulation for TR3 (WIP)

This commit is contained in:
XProger
2018-11-29 09:23:31 +03:00
parent 5835b77cfc
commit a7e732752b
2 changed files with 179 additions and 73 deletions

View File

@@ -411,20 +411,93 @@ struct Controller {
info.roomNext = (*fd++).value; info.roomNext = (*fd++).value;
break; break;
case TR::FloorData::FLOOR : // floor & ceiling case TR::FloorData::FLOOR :
case TR::FloorData::CEILING : { case TR::FloorData::FLOOR_NW_SE_SOLID :
TR::FloorData::Slant slant = (*fd++).slant; case TR::FloorData::FLOOR_NE_SW_SOLID :
int sx = (int)slant.x; case TR::FloorData::FLOOR_NW_SE_PORTAL_SE :
int sz = (int)slant.z; case TR::FloorData::FLOOR_NW_SE_PORTAL_NW :
case TR::FloorData::FLOOR_NE_SW_PORTAL_SW :
case TR::FloorData::FLOOR_NE_SW_PORTAL_NE : {
int sx, sz;
if (cmd.func == TR::FloorData::FLOOR) { if (cmd.func == TR::FloorData::FLOOR) {
info.slantX = sx; sx = fd->slantX;
info.slantZ = sz; sz = fd->slantZ;
info.floor -= sx * (sx > 0 ? (dx - 1024) : dx) >> 2;
info.floor -= sz * (sz > 0 ? (dz - 1024) : dz) >> 2;
} else { } else {
info.ceiling -= sx * (sx < 0 ? (dx - 1024) : dx) >> 2; if (cmd.func == TR::FloorData::FLOOR_NW_SE_SOLID ||
info.ceiling += sz * (sz > 0 ? (dz - 1024) : dz) >> 2; cmd.func == TR::FloorData::FLOOR_NW_SE_PORTAL_SE ||
cmd.func == TR::FloorData::FLOOR_NW_SE_PORTAL_NW) {
if (dx <= 1024 - dz) {
info.floor += cmd.triangle.b * 256;
sx = fd->a - fd->b;
sz = fd->c - fd->b;
} else {
info.floor += cmd.triangle.a * 256;
sx = fd->d - fd->c;
sz = fd->d - fd->a;
}
} else {
if (dx <= dz) {
info.floor += cmd.triangle.b * 256;
sx = fd->d - fd->c;
sz = fd->c - fd->b;
} else {
info.floor += cmd.triangle.a * 256;
sx = fd->a - fd->b;
sz = fd->d - fd->a;
}
}
} }
fd++;
info.slantX = sx;
info.slantZ = sz;
info.floor -= sx * (sx > 0 ? (dx - 1023) : dx) >> 2;
info.floor -= sz * (sz > 0 ? (dz - 1023) : dz) >> 2;
break;
}
case TR::FloorData::CEILING :
case TR::FloorData::CEILING_NE_SW_SOLID :
case TR::FloorData::CEILING_NW_SE_SOLID :
case TR::FloorData::CEILING_NE_SW_PORTAL_SW :
case TR::FloorData::CEILING_NE_SW_PORTAL_NE :
case TR::FloorData::CEILING_NW_SE_PORTAL_SE :
case TR::FloorData::CEILING_NW_SE_PORTAL_NW : {
int sx, sz;
if (cmd.func == TR::FloorData::CEILING) {
sx = fd->slantX;
sz = fd->slantZ;
} else {
if (cmd.func == TR::FloorData::CEILING_NW_SE_SOLID ||
cmd.func == TR::FloorData::CEILING_NW_SE_PORTAL_SE ||
cmd.func == TR::FloorData::CEILING_NW_SE_PORTAL_NW) {
if (dx <= 1024 - dz) {
info.ceiling += cmd.triangle.b * 256;
sx = fd->c - fd->d;
sz = fd->b - fd->c;
} else {
info.ceiling += cmd.triangle.a * 256;
sx = fd->b - fd->a;
sz = fd->a - fd->d;
}
} else {
if (dx <= dz) {
info.ceiling += cmd.triangle.b * 256;
sx = fd->b - fd->a;
sz = fd->b - fd->c;
} else {
info.ceiling += cmd.triangle.a * 256;
sx = fd->c - fd->d;
sz = fd->a - fd->d;
}
}
}
fd++;
info.ceiling -= sx * (sx < 0 ? (dx - 1023) : dx) >> 2;
info.ceiling += sz * (sz > 0 ? (dz - 1023) : dz) >> 2;
break; break;
} }
@@ -457,23 +530,9 @@ struct Controller {
info.climb = cmd.sub; // climb mask info.climb = cmd.sub; // climb mask
break; break;
case 0x07 : case TR::FloorData::MONKEY : break;
case 0x08 : case TR::FloorData::MINECART_LEFT :
case 0x09 : case TR::FloorData::MINECART_RIGHT : break;
case 0x0A :
case 0x0B :
case 0x0C :
case 0x0D :
case 0x0E :
case 0x0F :
case 0x10 :
case 0x11 :
case 0x12 : fd++; break; // TODO TR3 triangulation
case 0x13 : break; // TODO TR3 monkeyswing
case 0x14 :
case 0x15 : break; // TODO TR3 minecart
default : LOG("unknown func: %d\n", cmd.func); default : LOG("unknown func: %d\n", cmd.func);
} }

View File

@@ -1440,12 +1440,20 @@ namespace TR {
union FloorData { union FloorData {
uint16 value; uint16 value;
struct Command { union Command {
uint16 func:5, tri:3, sub:7, end:1; struct {
uint16 func:5, tri:3, sub:7, end:1;
};
struct {
int16 :5, a:5, b:5, :1;
} triangle;
} cmd; } cmd;
struct Slant { struct {
int8 x:8, z:8; int16 slantX:8, slantZ:8;
} slant; };
struct {
uint16 a:4, b:4, c:4, d:4;
};
struct TriggerInfo { struct TriggerInfo {
uint16 timer:8, once:1, mask:5, :2; uint16 timer:8, once:1, mask:5, :2;
} triggerInfo; } triggerInfo;
@@ -1459,13 +1467,28 @@ namespace TR {
} triggerCmd; } triggerCmd;
enum { enum {
NONE , NONE
PORTAL , , PORTAL
FLOOR , , FLOOR
CEILING , , CEILING
TRIGGER , , TRIGGER
LAVA , , LAVA
CLIMB , , CLIMB
, FLOOR_NW_SE_SOLID
, FLOOR_NE_SW_SOLID
, CEILING_NW_SE_SOLID
, CEILING_NE_SW_SOLID
, FLOOR_NW_SE_PORTAL_SE
, FLOOR_NW_SE_PORTAL_NW
, FLOOR_NE_SW_PORTAL_SW
, FLOOR_NE_SW_PORTAL_NE
, CEILING_NW_SE_PORTAL_SE
, CEILING_NW_SE_PORTAL_NW
, CEILING_NE_SW_PORTAL_SW
, CEILING_NE_SW_PORTAL_NE
, MONKEY
, MINECART_LEFT
, MINECART_RIGHT
}; };
}; };
@@ -5495,6 +5518,21 @@ namespace TR {
fd++; fd++;
break; break;
case FloorData::FLOOR_NW_SE_SOLID :
case FloorData::FLOOR_NE_SW_SOLID :
case FloorData::CEILING_NW_SE_SOLID :
case FloorData::CEILING_NE_SW_SOLID :
case FloorData::FLOOR_NW_SE_PORTAL_NW :
case FloorData::FLOOR_NW_SE_PORTAL_SE :
case FloorData::FLOOR_NE_SW_PORTAL_NE :
case FloorData::FLOOR_NE_SW_PORTAL_SW :
case FloorData::CEILING_NW_SE_PORTAL_NW :
case FloorData::CEILING_NW_SE_PORTAL_SE :
case FloorData::CEILING_NE_SW_PORTAL_NE :
case FloorData::CEILING_NE_SW_PORTAL_SW :
fd++;
break;
case FloorData::TRIGGER : case FloorData::TRIGGER :
fd++; fd++;
do {} while (!(*fd++).triggerCmd.end); do {} while (!(*fd++).triggerCmd.end);
@@ -5502,26 +5540,11 @@ namespace TR {
case FloorData::LAVA : case FloorData::LAVA :
case FloorData::CLIMB : case FloorData::CLIMB :
case FloorData::MONKEY :
case FloorData::MINECART_LEFT :
case FloorData::MINECART_RIGHT :
break; break;
case 0x07 :
case 0x08 :
case 0x09 :
case 0x0A :
case 0x0B :
case 0x0C :
case 0x0D :
case 0x0E :
case 0x0F :
case 0x10 :
case 0x11 :
case 0x12 : fd++; break; // TODO TR3 triangulation
case 0x13 : break; // TODO TR3 monkeyswing
case 0x14 :
case 0x15 : break; // TODO TR3 minecart
default : LOG("unknown func to skip: %d\n", func); default : LOG("unknown func to skip: %d\n", func);
} }
} }
@@ -5531,9 +5554,33 @@ namespace TR {
if (!sector->floorIndex) return NO_ROOM; if (!sector->floorIndex) return NO_ROOM;
FloorData *fd = &floors[sector->floorIndex]; FloorData *fd = &floors[sector->floorIndex];
// floor data always in this order // floor data always in this order
if (!fd->cmd.end && fd->cmd.func == FloorData::FLOOR) fd += 2; // skip floor slant info if ( fd->cmd.func == FloorData::FLOOR
if (!fd->cmd.end && fd->cmd.func == FloorData::CEILING) fd += 2; // skip ceiling slant info || fd->cmd.func == FloorData::FLOOR_NW_SE_SOLID
if (fd->cmd.func == FloorData::PORTAL) return (++fd)->value; || fd->cmd.func == FloorData::FLOOR_NE_SW_SOLID
|| fd->cmd.func == FloorData::FLOOR_NW_SE_PORTAL_SE
|| fd->cmd.func == FloorData::FLOOR_NW_SE_PORTAL_NW
|| fd->cmd.func == FloorData::FLOOR_NE_SW_PORTAL_SW
|| fd->cmd.func == FloorData::FLOOR_NE_SW_PORTAL_NE) {
if (fd->cmd.end) return NO_ROOM;
fd += 2;
}
if ( fd->cmd.func == FloorData::CEILING
|| fd->cmd.func == FloorData::CEILING_NE_SW_SOLID
|| fd->cmd.func == FloorData::CEILING_NW_SE_SOLID
|| fd->cmd.func == FloorData::CEILING_NE_SW_PORTAL_SW
|| fd->cmd.func == FloorData::CEILING_NE_SW_PORTAL_NE
|| fd->cmd.func == FloorData::CEILING_NW_SE_PORTAL_SE
|| fd->cmd.func == FloorData::CEILING_NW_SE_PORTAL_NW) {
if (fd->cmd.end) return NO_ROOM;
fd += 2;
}
if (fd->cmd.func == FloorData::PORTAL)
return (++fd)->value;
return NO_ROOM; return NO_ROOM;
} }
@@ -5630,12 +5677,12 @@ namespace TR {
cmd = (*fd++).cmd; cmd = (*fd++).cmd;
switch (cmd.func) { switch (cmd.func) {
case FloorData::FLOOR : { case FloorData::FLOOR : { // TODO: triangulation
FloorData::Slant slant = (*fd++).slant; int sx = fd->slantX;
int sx = (int)slant.x; int sz = fd->slantZ;
int sz = (int)slant.z; fd++;
int dx = x % 1024; int dx = x & 1023;
int dz = z % 1024; int dz = z & 1023;
floor -= sx * (sx > 0 ? (dx - 1023) : dx) >> 2; floor -= sx * (sx > 0 ? (dx - 1023) : dx) >> 2;
floor -= sz * (sz > 0 ? (dz - 1023) : dz) >> 2; floor -= sz * (sz > 0 ? (dz - 1023) : dz) >> 2;
break; break;
@@ -5682,12 +5729,12 @@ namespace TR {
fd += 2; // skip floor slant fd += 2; // skip floor slant
} }
if (fd->cmd.func == FloorData::CEILING) { if (fd->cmd.func == FloorData::CEILING) { // TODO: triangulation
FloorData::Slant slant = (++fd)->slant; int sx = fd->slantX;
int sx = (int)slant.x; int sz = fd->slantZ;
int sz = (int)slant.z; fd++;
int dx = x % 1024; int dx = x & 1023;
int dz = z % 1024; int dz = z & 1023;
ceiling -= sx * (sx < 0 ? (dx - 1023) : dx) >> 2; ceiling -= sx * (sx < 0 ? (dx - 1023) : dx) >> 2;
ceiling += sz * (sz > 0 ? (dz - 1023) : dz) >> 2; ceiling += sz * (sz > 0 ? (dz - 1023) : dz) >> 2;
} }