mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-15 17:44:25 +02:00
#138 fix textures for static meshes, fix texture flip
This commit is contained in:
199
src/format.h
199
src/format.h
@@ -1123,11 +1123,6 @@ namespace TR {
|
|||||||
operator short3() const { return *((short3*)this); }
|
operator short3() const { return *((short3*)this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
union Tile {
|
|
||||||
struct { uint16 index:14, undefined:1, triangle:1; };
|
|
||||||
uint16 value;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum TextureType {
|
enum TextureType {
|
||||||
TEX_TYPE_ROOM,
|
TEX_TYPE_ROOM,
|
||||||
TEX_TYPE_ITEM,
|
TEX_TYPE_ITEM,
|
||||||
@@ -1139,11 +1134,13 @@ namespace TR {
|
|||||||
TextureType type;
|
TextureType type;
|
||||||
uint16 index;
|
uint16 index;
|
||||||
uint16 clut;
|
uint16 clut;
|
||||||
Tile tile;
|
uint16 tile;
|
||||||
uint16 attribute:15, animated:1; // 0 - opaque, 1 - transparent, 2 - blend additive, animated
|
uint32 attribute:15, animated:1; // 0 - opaque, 1 - transparent, 2 - blend additive, animated, triangle
|
||||||
short2 texCoord[4];
|
short2 texCoord[4];
|
||||||
short2 texCoordAtlas[4];
|
short2 texCoordAtlas[4];
|
||||||
|
|
||||||
|
uint16 i1, i2, i3, i4, i5;
|
||||||
|
|
||||||
short4 getMinMax() const {
|
short4 getMinMax() const {
|
||||||
return short4(
|
return short4(
|
||||||
min(min(texCoord[0].x, texCoord[1].x), texCoord[2].x),
|
min(min(texCoord[0].x, texCoord[1].x), texCoord[2].x),
|
||||||
@@ -1193,7 +1190,7 @@ namespace TR {
|
|||||||
|
|
||||||
short3 normal;
|
short3 normal;
|
||||||
uint16 vertices[4];
|
uint16 vertices[4];
|
||||||
uint8 water:1, colored:1, vCount:6;
|
uint8 water:1, colored:1, flip:1, vCount:5;
|
||||||
|
|
||||||
static int cmp(const Face &a, const Face &b) {
|
static int cmp(const Face &a, const Face &b) {
|
||||||
int aIndex = a.flags.texture;
|
int aIndex = a.flags.texture;
|
||||||
@@ -1209,9 +1206,9 @@ namespace TR {
|
|||||||
ObjectTexture &ta = gObjectTextures[aIndex];
|
ObjectTexture &ta = gObjectTextures[aIndex];
|
||||||
ObjectTexture &tb = gObjectTextures[bIndex];
|
ObjectTexture &tb = gObjectTextures[bIndex];
|
||||||
|
|
||||||
if (ta.tile.index < tb.tile.index)
|
if (ta.tile < tb.tile)
|
||||||
return -1;
|
return -1;
|
||||||
if (ta.tile.index > tb.tile.index)
|
if (ta.tile > tb.tile)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#ifdef SPLIT_BY_CLUT
|
#ifdef SPLIT_BY_CLUT
|
||||||
@@ -3004,18 +3001,14 @@ namespace TR {
|
|||||||
uint8 data[3];
|
uint8 data[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SPAL {
|
|
||||||
uint8 data[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32 tsubCount = 0;
|
uint32 tsubCount = 0;
|
||||||
uint8 *tsub = NULL;
|
uint8 *tsub = NULL;
|
||||||
|
|
||||||
uint32 tpalCount = 0;
|
uint32 tpalCount = 0;
|
||||||
TPAL *tpal = NULL;
|
TPAL *tpal = NULL;
|
||||||
|
|
||||||
uint32 spalCount = 0;
|
int32 spalCount = 0;
|
||||||
SPAL *spal = NULL;
|
uint16 *spal = NULL;
|
||||||
|
|
||||||
Room *room = NULL;
|
Room *room = NULL;
|
||||||
|
|
||||||
@@ -3041,30 +3034,68 @@ namespace TR {
|
|||||||
for (int i = 0; i < roomTexturesCount; i++)
|
for (int i = 0; i < roomTexturesCount; i++)
|
||||||
readObjectTex(stream, roomTextures[i], TEX_TYPE_ROOM);
|
readObjectTex(stream, roomTextures[i], TEX_TYPE_ROOM);
|
||||||
break;
|
break;
|
||||||
case CHUNK("ROOMTQTR") :
|
case CHUNK("ROOMTQTR") : {
|
||||||
ASSERTV(stream.readBE32() == 0x00000001);
|
ASSERTV(stream.readBE32() == 0x00000001);
|
||||||
roomTexturesDataSize = stream.readBE32();
|
roomTexturesDataSize = stream.readBE32();
|
||||||
roomTexturesData = roomTexturesDataSize ? new uint8[roomTexturesDataSize] : NULL;
|
roomTexturesData = roomTexturesDataSize ? new uint8[roomTexturesDataSize] : NULL;
|
||||||
stream.raw(roomTexturesData, roomTexturesDataSize);
|
stream.raw(roomTexturesData, roomTexturesDataSize);
|
||||||
|
/*
|
||||||
|
int32 count = stream.readBE32();
|
||||||
|
stream.seek(count);
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CHUNK("ROOMTSUB") :
|
case CHUNK("ROOMTSUB") :
|
||||||
ASSERTV(stream.readBE32() == 0x00000001);
|
ASSERTV(stream.readBE32() == 0x00000001);
|
||||||
|
/*
|
||||||
|
roomTexturesDataSize = stream.readBE32();
|
||||||
|
roomTexturesData = roomTexturesDataSize ? new uint8[roomTexturesDataSize] : NULL;
|
||||||
|
stream.raw(roomTexturesData, roomTexturesDataSize);
|
||||||
|
*/
|
||||||
|
|
||||||
tsubCount = stream.readBE32();
|
tsubCount = stream.readBE32();
|
||||||
tsub = new uint8[tsubCount];
|
tsub = new uint8[tsubCount];
|
||||||
stream.raw(tsub, sizeof(uint8) * tsubCount);
|
stream.raw(tsub, sizeof(uint8) * tsubCount);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CHUNK("ROOMTPAL") :
|
case CHUNK("ROOMTPAL") : {
|
||||||
ASSERTV(stream.readBE32() == 0x00000003);
|
ASSERTV(stream.readBE32() == 0x00000003);
|
||||||
tpalCount = stream.readBE32();
|
tpalCount = stream.readBE32();
|
||||||
tpal = new TPAL[tpalCount];
|
tpal = new TPAL[tpalCount];
|
||||||
stream.raw(tpal, sizeof(TPAL) * tpalCount);
|
stream.raw(tpal, sizeof(TPAL) * tpalCount);
|
||||||
|
|
||||||
|
uint8 *data = new uint8[roomTexturesDataSize];
|
||||||
|
for (int i = 0; i < roomTexturesDataSize; i++) {
|
||||||
|
TPAL *p = tpal + roomTexturesData[i];
|
||||||
|
data[i] = uint8((int(p->data[0]) + int(p->data[1]) + int(p->data[2])) / 3);
|
||||||
|
}
|
||||||
|
FILE *f = fopen("room_data.dmp", "wb");
|
||||||
|
fwrite(data, 1, roomTexturesDataSize, f);
|
||||||
|
fclose(f);
|
||||||
|
delete[] data;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CHUNK("ROOMSPAL") :
|
}
|
||||||
|
case CHUNK("ROOMSPAL") : {
|
||||||
ASSERTV(stream.readLE32() == 0x02000000);
|
ASSERTV(stream.readLE32() == 0x02000000);
|
||||||
spalCount = stream.readBE32();
|
spalCount = stream.readBE32();
|
||||||
spal = new SPAL[spalCount];
|
spal = new uint16[spalCount];
|
||||||
stream.raw(spal, sizeof(SPAL) * spalCount);
|
for (int i = 0; i < spalCount; i++)
|
||||||
|
spal[i] = stream.readBE16();
|
||||||
|
|
||||||
|
uint8 *data = new uint8[roomTexturesDataSize];
|
||||||
|
for (int i = 0; i < roomTexturesDataSize; i++) {
|
||||||
|
Color32 c = Color16(spal[roomTexturesData[i]]);
|
||||||
|
data[i] = uint8((int(c.r) + int(c.g) + int(c.b)) / 3);
|
||||||
|
}
|
||||||
|
FILE *f = fopen("room_data_16.dmp", "wb");
|
||||||
|
fwrite(data, 1, roomTexturesDataSize, f);
|
||||||
|
fclose(f);
|
||||||
|
delete[] data;
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CHUNK("ROOMDATA") :
|
case CHUNK("ROOMDATA") :
|
||||||
ASSERTV(stream.readBE32() == 0x00000044);
|
ASSERTV(stream.readBE32() == 0x00000044);
|
||||||
roomsCount = stream.readBE32();
|
roomsCount = stream.readBE32();
|
||||||
@@ -3164,6 +3195,10 @@ namespace TR {
|
|||||||
f.vertices[3] = 0;
|
f.vertices[3] = 0;
|
||||||
ASSERT(f.vertices[0] < data.vCount && f.vertices[1] < data.vCount && f.vertices[2] < data.vCount);
|
ASSERT(f.vertices[0] < data.vCount && f.vertices[1] < data.vCount && f.vertices[2] < data.vCount);
|
||||||
f.flags.value = stream.readBE16();
|
f.flags.value = stream.readBE16();
|
||||||
|
if (type == TYPE_T_INVISIBLE) {
|
||||||
|
fIndex--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
data.tCount++;
|
data.tCount++;
|
||||||
break;
|
break;
|
||||||
case TYPE_R_INVISIBLE :
|
case TYPE_R_INVISIBLE :
|
||||||
@@ -3176,19 +3211,28 @@ namespace TR {
|
|||||||
f.vertices[3] = (stream.readBE16() >> 4);
|
f.vertices[3] = (stream.readBE16() >> 4);
|
||||||
ASSERT(f.vertices[0] < data.vCount && f.vertices[1] < data.vCount && f.vertices[2] < data.vCount && f.vertices[3] < data.vCount);
|
ASSERT(f.vertices[0] < data.vCount && f.vertices[1] < data.vCount && f.vertices[2] < data.vCount && f.vertices[3] < data.vCount);
|
||||||
f.flags.value = stream.readBE16();
|
f.flags.value = stream.readBE16();
|
||||||
|
if (type == TYPE_R_INVISIBLE) {
|
||||||
|
fIndex--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
data.rCount++;
|
data.rCount++;
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
LOG("! unknown face type: %d\n", type);
|
LOG("! unknown face type: %d\n", type);
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
||||||
if (type == TYPE_R_INVISIBLE || type == TYPE_T_INVISIBLE)
|
//if (type == TYPE_R_TRANSP)
|
||||||
f.flags.value = 0;
|
// f.flags.value = 0;
|
||||||
//ASSERT(f.flags.value % 16 == 0);
|
//ASSERT(f.flags.value % 16 == 0);
|
||||||
//ASSERT(f.flags.value / 16 < roomTexturesCount);
|
//ASSERT(f.flags.value / 16 < roomTexturesCount);
|
||||||
f.flags.value /= 16;
|
f.flags.value /= 16;
|
||||||
f.water = false;
|
f.water = false;
|
||||||
f.colored = false;
|
f.colored = false;
|
||||||
|
f.flip = false;
|
||||||
|
|
||||||
|
if (type == TYPE_R_TRANSP) {
|
||||||
|
roomTextures[f.flags.texture].attribute = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.fCount = fIndex;
|
data.fCount = fIndex;
|
||||||
@@ -3380,7 +3424,7 @@ namespace TR {
|
|||||||
animTex.count = last - first + 1;
|
animTex.count = last - first + 1;
|
||||||
animTex.textures = new uint16[animTex.count];
|
animTex.textures = new uint16[animTex.count];
|
||||||
for (int j = 0; j < animTex.count; j++)
|
for (int j = 0; j < animTex.count; j++)
|
||||||
animTex.textures[j] = first + j;
|
animTex.textures[j] = last - j;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3572,7 +3616,7 @@ namespace TR {
|
|||||||
objectTexturesCount = stream.readBE32();
|
objectTexturesCount = stream.readBE32();
|
||||||
objectTextures = objectTexturesCount ? new ObjectTexture[objectTexturesCount] : NULL;
|
objectTextures = objectTexturesCount ? new ObjectTexture[objectTexturesCount] : NULL;
|
||||||
for (int i = 0; i < objectTexturesCount; i++)
|
for (int i = 0; i < objectTexturesCount; i++)
|
||||||
readObjectTex(stream, objectTextures[i]);
|
readObjectTex(stream, objectTextures[i], TEX_TYPE_OBJECT);
|
||||||
break;
|
break;
|
||||||
case CHUNK("OTEXTDAT") : {
|
case CHUNK("OTEXTDAT") : {
|
||||||
ASSERTV(stream.readBE32() == 0x00000001);
|
ASSERTV(stream.readBE32() == 0x00000001);
|
||||||
@@ -3960,6 +4004,7 @@ namespace TR {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
f.water = false;
|
f.water = false;
|
||||||
|
f.flip = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void readRoom(Stream &stream, int roomIndex) {
|
void readRoom(Stream &stream, int roomIndex) {
|
||||||
@@ -4199,6 +4244,7 @@ namespace TR {
|
|||||||
f.vertices[3] >>= 2;
|
f.vertices[3] >>= 2;
|
||||||
f.colored = false;
|
f.colored = false;
|
||||||
f.water = false;
|
f.water = false;
|
||||||
|
f.flip = false;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
for (int i = 0; i < d.rCount; i++) readFace(stream, d.faces[idx++], false, false);
|
for (int i = 0; i < d.rCount; i++) readFace(stream, d.faces[idx++], false, false);
|
||||||
@@ -4218,6 +4264,8 @@ namespace TR {
|
|||||||
f.vertices[2] >>= 2;
|
f.vertices[2] >>= 2;
|
||||||
f.vertices[3] = 0;
|
f.vertices[3] = 0;
|
||||||
f.colored = false;
|
f.colored = false;
|
||||||
|
f.water = false;
|
||||||
|
f.flip = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < d.tCount; i++)
|
for (int i = 0; i < d.tCount; i++)
|
||||||
@@ -4454,15 +4502,16 @@ namespace TR {
|
|||||||
mesh.tCount = mesh.rCount = 0;
|
mesh.tCount = mesh.rCount = 0;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TYPE_T_UNKNOWN1 = 2,
|
TYPE_T_TEX = 2,
|
||||||
TYPE_T_COLOR = 4,
|
TYPE_T_COLOR = 4,
|
||||||
TYPE_T_PALETTE = 8,
|
TYPE_T_PALETTE = 8,
|
||||||
TYPE_T_UNKNOWN2 = 16,
|
TYPE_T_UNKNOWN2 = 16,
|
||||||
TYPE_R_UNKNOWN1 = 17,
|
|
||||||
TYPE_R_COLOR = 5,
|
TYPE_R_COLOR = 5,
|
||||||
TYPE_R_TEX = 9,
|
TYPE_R_TEX = 9,
|
||||||
TYPE_R_TRANSP = 49,
|
TYPE_R_TRANSP = 17,
|
||||||
TYPE_R_UNKNOWN2 = 57,
|
TYPE_R_FLIP_TEX = 49,
|
||||||
|
TYPE_R_FLIP_TRANSP = 57,
|
||||||
};
|
};
|
||||||
|
|
||||||
int divisor = 16;
|
int divisor = 16;
|
||||||
@@ -4479,7 +4528,7 @@ namespace TR {
|
|||||||
ASSERT(fIndex < mesh.fCount);
|
ASSERT(fIndex < mesh.fCount);
|
||||||
Face &f = mesh.faces[fIndex++];
|
Face &f = mesh.faces[fIndex++];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_T_UNKNOWN1 :
|
case TYPE_T_TEX :
|
||||||
case TYPE_T_COLOR :
|
case TYPE_T_COLOR :
|
||||||
case TYPE_T_PALETTE :
|
case TYPE_T_PALETTE :
|
||||||
case TYPE_T_UNKNOWN2 :
|
case TYPE_T_UNKNOWN2 :
|
||||||
@@ -4491,12 +4540,13 @@ namespace TR {
|
|||||||
f.flags.value = stream.readBE16();
|
f.flags.value = stream.readBE16();
|
||||||
ASSERT(f.vertices[0] < mesh.vCount && f.vertices[1] < mesh.vCount && f.vertices[2] < mesh.vCount);
|
ASSERT(f.vertices[0] < mesh.vCount && f.vertices[1] < mesh.vCount && f.vertices[2] < mesh.vCount);
|
||||||
mesh.tCount++;
|
mesh.tCount++;
|
||||||
|
f.colored = true;
|
||||||
break;
|
break;
|
||||||
case TYPE_R_COLOR :
|
case TYPE_R_COLOR :
|
||||||
case TYPE_R_TEX :
|
case TYPE_R_TEX :
|
||||||
case TYPE_R_TRANSP :
|
case TYPE_R_TRANSP :
|
||||||
case TYPE_R_UNKNOWN1 :
|
case TYPE_R_FLIP_TEX :
|
||||||
case TYPE_R_UNKNOWN2 :
|
case TYPE_R_FLIP_TRANSP :
|
||||||
f.vCount = 4;
|
f.vCount = 4;
|
||||||
f.vertices[0] = (stream.readBE16() >> 5);
|
f.vertices[0] = (stream.readBE16() >> 5);
|
||||||
f.vertices[1] = (stream.readBE16() >> 5);
|
f.vertices[1] = (stream.readBE16() >> 5);
|
||||||
@@ -4512,7 +4562,9 @@ namespace TR {
|
|||||||
}
|
}
|
||||||
if (type == TYPE_T_COLOR || type == TYPE_R_COLOR || type == TYPE_T_PALETTE || type == TYPE_T_UNKNOWN2) {
|
if (type == TYPE_T_COLOR || type == TYPE_R_COLOR || type == TYPE_T_PALETTE || type == TYPE_T_UNKNOWN2) {
|
||||||
if (type == TYPE_T_PALETTE)
|
if (type == TYPE_T_PALETTE)
|
||||||
f.flags.value = 0;
|
f.flags.value = 0xFFFF; // TODO
|
||||||
|
if (type == TYPE_T_UNKNOWN2)
|
||||||
|
f.flags.value = 0xFF80; // TODO
|
||||||
f.colored = true;
|
f.colored = true;
|
||||||
} else {
|
} else {
|
||||||
ASSERT(f.flags.value % 16 == 0);
|
ASSERT(f.flags.value % 16 == 0);
|
||||||
@@ -4520,6 +4572,11 @@ namespace TR {
|
|||||||
f.flags.value /= divisor;
|
f.flags.value /= divisor;
|
||||||
f.colored = false;
|
f.colored = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == TYPE_R_TRANSP || type == TYPE_R_FLIP_TRANSP)
|
||||||
|
objectTextures[f.flags.texture].attribute = 1;
|
||||||
|
|
||||||
|
f.flip = (type == TYPE_R_FLIP_TEX || type == TYPE_R_FLIP_TRANSP);
|
||||||
f.water = false;
|
f.water = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4813,7 +4870,8 @@ namespace TR {
|
|||||||
case VER_TR1_SAT : {
|
case VER_TR1_SAT : {
|
||||||
struct {
|
struct {
|
||||||
uint16 attribute;
|
uint16 attribute;
|
||||||
Tile tile;
|
uint16 tile;
|
||||||
|
uint8 triangle;
|
||||||
uint16 clut;
|
uint16 clut;
|
||||||
uint8 w, h;
|
uint8 w, h;
|
||||||
uint8 x0, y0;
|
uint8 x0, y0;
|
||||||
@@ -4828,27 +4886,37 @@ namespace TR {
|
|||||||
if (type == TEX_TYPE_ITEM)
|
if (type == TEX_TYPE_ITEM)
|
||||||
index = stream.readBE16();
|
index = stream.readBE16();
|
||||||
|
|
||||||
d.tile.value = stream.readBE16(); // offset to 4-bit indices
|
d.triangle = false;
|
||||||
|
d.tile = stream.readBE16(); // offset to 4-bit indices
|
||||||
uint16 i1 = stream.readBE16();
|
uint16 i1 = stream.readBE16();
|
||||||
uint16 i2 = stream.readBE16();
|
uint16 i2 = stream.readBE16();
|
||||||
uint16 i3 = stream.readBE16();
|
uint16 i3 = stream.readBE16();
|
||||||
uint16 i4 = stream.readBE16();
|
uint16 i4 = stream.readBE16();
|
||||||
d.clut = stream.readBE16() + d.tile.value; // offset to color palette
|
d.clut = stream.readBE16() + d.tile; // offset to color palette
|
||||||
d.w = stream.read();
|
d.w = stream.read() << 3;
|
||||||
d.h = stream.read();
|
d.h = stream.read();
|
||||||
uint16 i5 = stream.readBE16();
|
uint16 i5 = stream.readBE16();
|
||||||
|
|
||||||
//LOG("%d %d %d %d %d\n", i1, i2, i3, i4, i5);
|
//if (type == TEX_TYPE_OBJECT && d.w == 80 && d.h == 56) {
|
||||||
|
// LOG("%d %d %d %d %d\n", i1, i2, i3, i4, i5);
|
||||||
|
//}
|
||||||
|
|
||||||
if (type == TEX_TYPE_ITEM)
|
if (type == TEX_TYPE_ITEM)
|
||||||
stream.seek(2);
|
stream.seek(2);
|
||||||
|
|
||||||
d.x0 = d.y0 = d.x3 = d.y1 = 0;
|
d.x0 = d.y0 = d.x3 = d.y1 = 0;
|
||||||
d.x1 = d.x2 = max(0, (d.w << 3) - 1);
|
d.x1 = d.x2 = max(0, d.w - 1);
|
||||||
d.y2 = d.y3 = max(0, d.h - 1);
|
d.y2 = d.y3 = max(0, d.h - 1);
|
||||||
|
|
||||||
SET_PARAMS(t, d, d.clut);
|
SET_PARAMS(t, d, d.clut);
|
||||||
|
|
||||||
|
t.i1 = i1;
|
||||||
|
t.i2 = i2;
|
||||||
|
t.i3 = i3;
|
||||||
|
t.i4 = i4;
|
||||||
|
t.i5 = i5;
|
||||||
|
|
||||||
|
|
||||||
t.index = index;
|
t.index = index;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -4858,7 +4926,7 @@ namespace TR {
|
|||||||
case VER_TR3_PC : {
|
case VER_TR3_PC : {
|
||||||
struct {
|
struct {
|
||||||
uint16 attribute;
|
uint16 attribute;
|
||||||
Tile tile;
|
uint16 tile:14, :2;
|
||||||
uint8 xh0, x0, yh0, y0;
|
uint8 xh0, x0, yh0, y0;
|
||||||
uint8 xh1, x1, yh1, y1;
|
uint8 xh1, x1, yh1, y1;
|
||||||
uint8 xh2, x2, yh2, y2;
|
uint8 xh2, x2, yh2, y2;
|
||||||
@@ -4875,9 +4943,9 @@ namespace TR {
|
|||||||
uint8 x0, y0;
|
uint8 x0, y0;
|
||||||
uint16 clut;
|
uint16 clut;
|
||||||
uint8 x1, y1;
|
uint8 x1, y1;
|
||||||
Tile tile;
|
uint16 tile:14, :2;
|
||||||
uint8 x2, y2;
|
uint8 x2, y2;
|
||||||
uint16 unknown;
|
uint16 unknown2;
|
||||||
uint8 x3, y3;
|
uint8 x3, y3;
|
||||||
uint16 attribute;
|
uint16 attribute;
|
||||||
} d;
|
} d;
|
||||||
@@ -5095,18 +5163,10 @@ namespace TR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillObjectTexture(Tile32 *dst, const short4 &uv, int16 tileIndex, int16 clutIndex, TextureType type) {
|
void fillObjectTexture(Tile32 *dst, const short4 &uv, int16 tileIndex, int32 clutIndex, TextureType type) {
|
||||||
// convert to RGBA
|
// convert to RGBA
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case VER_TR1_SAT : {
|
case VER_TR1_SAT : {
|
||||||
/*
|
|
||||||
if (type == TEX_TYPE_ROOM) {
|
|
||||||
for (int y = uv.y; y < uv.w; y++)
|
|
||||||
for (int x = uv.x; x < uv.z; x++)
|
|
||||||
dst->color[y * 256 + x] = Color32(255, 0, 255, 255);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
uint32 iOffset = uint32(uint16(tileIndex)) << 3;
|
uint32 iOffset = uint32(uint16(tileIndex)) << 3;
|
||||||
uint32 cOffset = uint32(uint16(clutIndex)) << 3;
|
uint32 cOffset = uint32(uint16(clutIndex)) << 3;
|
||||||
|
|
||||||
@@ -5123,14 +5183,37 @@ namespace TR {
|
|||||||
ColorIndex4 *indices = (ColorIndex4*) (data + iOffset);
|
ColorIndex4 *indices = (ColorIndex4*) (data + iOffset);
|
||||||
CLUT *clut = (CLUT*) (data + cOffset);
|
CLUT *clut = (CLUT*) (data + cOffset);
|
||||||
|
|
||||||
|
int h = uv.w - uv.y;
|
||||||
int w = uv.z - uv.x;
|
int w = uv.z - uv.x;
|
||||||
|
ASSERT(w <= 256 && h <= 256);
|
||||||
for (int y = uv.y; y < uv.w; y++)
|
/*
|
||||||
for (int x = uv.x; x < uv.z; x++) {
|
if (type == TEX_TYPE_OBJECT && w == 80 && h == 56) {
|
||||||
ColorIndex4 *index = indices + ((y - uv.y) * w + (x - uv.x)) / 2;
|
for (int y = 0; y < h; y++)
|
||||||
Color16 &c = clut->color[(x % 2) ? index->a : index->b];
|
for (int x = 0; x < h; x++)
|
||||||
dst->color[y * 256 + x] = Color16(swap16(c.value));
|
dst->color[y * 256 + x] = Color32(255, 0, 255, 255);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
for (int y = 0; y < h; y++)
|
||||||
|
for (int x = 0; x < w; x++) {
|
||||||
|
ColorIndex4 *index = indices + (y * w + x) / 2;
|
||||||
|
int idx = (x % 2) ? index->a : index->b;
|
||||||
|
Color16 &c = clut->color[idx];
|
||||||
|
|
||||||
|
if (idx == 0 && (c.value == 0x1BF4 || c.value == 0x0080)) {
|
||||||
|
dst->color[y * 256 + x].a = 0;// = Color32(255, 0, 0, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->color[y * 256 + x] = Color16(swap16(c.value));
|
||||||
|
/*
|
||||||
|
if (dst->color[y * 256 + x].a != 255) {
|
||||||
|
dst->color[y * 256 + x] = Color32(0, 255, 0, 255);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VER_TR1_PC : {
|
case VER_TR1_PC : {
|
||||||
@@ -5205,7 +5288,7 @@ namespace TR {
|
|||||||
ObjectTexture &t = objectTextures[texture & 0x7FFF];
|
ObjectTexture &t = objectTextures[texture & 0x7FFF];
|
||||||
int idx = (t.texCoord[0].y * 256 + t.texCoord[0].x) / 2;
|
int idx = (t.texCoord[0].y * 256 + t.texCoord[0].x) / 2;
|
||||||
int part = t.texCoord[0].x % 2;
|
int part = t.texCoord[0].x % 2;
|
||||||
Tile4 &tile = tiles4[t.tile.index];
|
Tile4 &tile = tiles4[t.tile];
|
||||||
CLUT &clut = cluts[t.clut];
|
CLUT &clut = cluts[t.clut];
|
||||||
return clut.color[part ? tile.index[idx].b : tile.index[idx].a];
|
return clut.color[part ? tile.index[idx].b : tile.index[idx].a];
|
||||||
}
|
}
|
||||||
|
@@ -936,6 +936,7 @@ namespace TR {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (version) {
|
switch (version) {
|
||||||
|
case VER_TR1_SAT :
|
||||||
case VER_TR1_PC :
|
case VER_TR1_PC :
|
||||||
case VER_TR1_PSX :
|
case VER_TR1_PSX :
|
||||||
sprintf(title, "audio/1/track_%02d.ogg", track);
|
sprintf(title, "audio/1/track_%02d.ogg", track);
|
||||||
|
@@ -1145,6 +1145,7 @@ struct Level : IGame {
|
|||||||
src = owner->tileData->color;
|
src = owner->tileData->color;
|
||||||
uv = t.texCoordAtlas;
|
uv = t.texCoordAtlas;
|
||||||
uvCount = 4;
|
uvCount = 4;
|
||||||
|
if (data)
|
||||||
level->fillObjectTexture(owner->tileData, tile.uv, tile.tile, tile.clut, t.type);
|
level->fillObjectTexture(owner->tileData, tile.uv, tile.tile, tile.clut, t.type);
|
||||||
} else {
|
} else {
|
||||||
id -= level->objectTexturesCount;
|
id -= level->objectTexturesCount;
|
||||||
@@ -1155,6 +1156,7 @@ struct Level : IGame {
|
|||||||
src = owner->tileData->color;
|
src = owner->tileData->color;
|
||||||
uv = t.texCoordAtlas;
|
uv = t.texCoordAtlas;
|
||||||
uvCount = 2;
|
uvCount = 2;
|
||||||
|
if (data)
|
||||||
level->fillObjectTexture(owner->tileData, tile.uv, tile.tile, tile.clut, TR::TextureType::TEX_TYPE_SPRITE);
|
level->fillObjectTexture(owner->tileData, tile.uv, tile.tile, tile.clut, TR::TextureType::TEX_TYPE_SPRITE);
|
||||||
} else { // common (generated) textures
|
} else { // common (generated) textures
|
||||||
id -= level->spriteTexturesCount;
|
id -= level->spriteTexturesCount;
|
||||||
@@ -1302,7 +1304,7 @@ struct Level : IGame {
|
|||||||
uv.z = max(max(t.texCoord[0].x, t.texCoord[1].x), t.texCoord[2].x) + 1;
|
uv.z = max(max(t.texCoord[0].x, t.texCoord[1].x), t.texCoord[2].x) + 1;
|
||||||
uv.w = max(max(t.texCoord[0].y, t.texCoord[1].y), t.texCoord[2].y) + 1;
|
uv.w = max(max(t.texCoord[0].y, t.texCoord[1].y), t.texCoord[2].y) + 1;
|
||||||
|
|
||||||
tiles->add(texIdx++, uv, t.tile.index, t.clut);
|
tiles->add(texIdx++, t.type, uv, t.tile, t.clut);
|
||||||
}
|
}
|
||||||
// add sprites
|
// add sprites
|
||||||
for (int i = 0; i < level.spriteTexturesCount; i++) {
|
for (int i = 0; i < level.spriteTexturesCount; i++) {
|
||||||
@@ -1314,12 +1316,12 @@ struct Level : IGame {
|
|||||||
uv.z = t.texCoord[1].x + 1;
|
uv.z = t.texCoord[1].x + 1;
|
||||||
uv.w = t.texCoord[1].y + 1;
|
uv.w = t.texCoord[1].y + 1;
|
||||||
|
|
||||||
tiles->add(texIdx++, uv, t.tile, t.clut);
|
tiles->add(texIdx++, TR::TEX_TYPE_SPRITE, uv, t.tile, t.clut);
|
||||||
}
|
}
|
||||||
// add common textures
|
// add common textures
|
||||||
const short2 bar[UI::BAR_MAX] = { short2(0, 4), short2(0, 4), short2(0, 4), short2(4, 4), short2(0, 0) };
|
const short2 bar[UI::BAR_MAX] = { short2(0, 4), short2(0, 4), short2(0, 4), short2(4, 4), short2(0, 0) };
|
||||||
for (int i = 0; i < UI::BAR_MAX; i++)
|
for (int i = 0; i < UI::BAR_MAX; i++)
|
||||||
tiles->add(texIdx++, short4(i * 32, 4096, i * 32 + bar[i].x, 4096 + bar[i].y));
|
tiles->add(texIdx++, TR::TEX_TYPE_SPRITE, short4(i * 32, 4096, i * 32 + bar[i].x, 4096 + bar[i].y));
|
||||||
|
|
||||||
// get result texture
|
// get result texture
|
||||||
tileData = new TR::Tile32();
|
tileData = new TR::Tile32();
|
||||||
|
50
src/mesh.h
50
src/mesh.h
@@ -17,6 +17,8 @@ TR::ObjectTexture &whiteTile = barTile[4]; // BAR_WHITE
|
|||||||
#define WATER_VOLUME_HEIGHT (768 * 2)
|
#define WATER_VOLUME_HEIGHT (768 * 2)
|
||||||
#define WATER_VOLUME_OFFSET 4
|
#define WATER_VOLUME_OFFSET 4
|
||||||
|
|
||||||
|
const TR::Color32 COLOR_WHITE( 255, 255, 255, 255 );
|
||||||
|
|
||||||
struct Mesh : GAPI::Mesh {
|
struct Mesh : GAPI::Mesh {
|
||||||
int aIndex;
|
int aIndex;
|
||||||
|
|
||||||
@@ -365,8 +367,6 @@ struct MeshBuilder {
|
|||||||
int vStartModel = vCount;
|
int vStartModel = vCount;
|
||||||
aCount++;
|
aCount++;
|
||||||
|
|
||||||
TR::Color32 COLOR_WHITE(255, 255, 255, 255);
|
|
||||||
|
|
||||||
for (int i = 0; i < level.modelsCount; i++) {
|
for (int i = 0; i < level.modelsCount; i++) {
|
||||||
TR::Model &model = level.models[i];
|
TR::Model &model = level.models[i];
|
||||||
|
|
||||||
@@ -487,7 +487,7 @@ struct MeshBuilder {
|
|||||||
quad.iStart = iCount;
|
quad.iStart = iCount;
|
||||||
quad.iCount = 2 * 3;
|
quad.iCount = 2 * 3;
|
||||||
|
|
||||||
addQuad(indices, iCount, vCount, vStartCommon, vertices, &whiteTile, false);
|
addQuad(indices, iCount, vCount, vStartCommon, vertices, &whiteTile, false, false);
|
||||||
vertices[vCount + 0].coord = short4( -32767, 32767, 0, 1 );
|
vertices[vCount + 0].coord = short4( -32767, 32767, 0, 1 );
|
||||||
vertices[vCount + 1].coord = short4( 32767, 32767, 1, 1 );
|
vertices[vCount + 1].coord = short4( 32767, 32767, 1, 1 );
|
||||||
vertices[vCount + 2].coord = short4( 32767, -32767, 1, 0 );
|
vertices[vCount + 2].coord = short4( 32767, -32767, 1, 0 );
|
||||||
@@ -926,8 +926,8 @@ struct MeshBuilder {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!geom.validForTile(t.tile.index, t.clut))
|
if (!geom.validForTile(t.tile, t.clut))
|
||||||
geom.getNextRange(vStart, iCount, t.tile.index, t.clut);
|
geom.getNextRange(vStart, iCount, t.tile, t.clut);
|
||||||
|
|
||||||
ADD_ROOM_FACE(indices, iCount, vCount, vStart, vertices, f, t);
|
ADD_ROOM_FACE(indices, iCount, vCount, vStart, vertices, f, t);
|
||||||
}
|
}
|
||||||
@@ -959,7 +959,6 @@ struct MeshBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool buildMesh(Geometry &geom, int blendMask, const TR::Mesh &mesh, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 joint, int x, int y, int z, int dir, const TR::Color32 &light) {
|
bool buildMesh(Geometry &geom, int blendMask, const TR::Mesh &mesh, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 joint, int x, int y, int z, int dir, const TR::Color32 &light) {
|
||||||
TR::Color24 COLOR_WHITE( 255, 255, 255 );
|
|
||||||
bool isOpaque = true;
|
bool isOpaque = true;
|
||||||
|
|
||||||
for (int j = 0; j < mesh.fCount; j++) {
|
for (int j = 0; j < mesh.fCount; j++) {
|
||||||
@@ -973,8 +972,8 @@ struct MeshBuilder {
|
|||||||
if (!(blendMask & getBlendMask(t.attribute)))
|
if (!(blendMask & getBlendMask(t.attribute)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!geom.validForTile(t.tile.index, t.clut))
|
if (!geom.validForTile(t.tile, t.clut))
|
||||||
geom.getNextRange(vStart, iCount, t.tile.index, t.clut);
|
geom.getNextRange(vStart, iCount, t.tile, t.clut);
|
||||||
|
|
||||||
TR::Color32 c = f.colored ? level.getColor(f.flags.value) : COLOR_WHITE;
|
TR::Color32 c = f.colored ? level.getColor(f.flags.value) : COLOR_WHITE;
|
||||||
|
|
||||||
@@ -1001,7 +1000,7 @@ struct MeshBuilder {
|
|||||||
return isOpaque;
|
return isOpaque;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTexCoord(Vertex *vertices, int vCount, TR::ObjectTexture *tex, bool triangle) {
|
void addTexCoord(Vertex *vertices, int vCount, TR::ObjectTexture *tex, bool triangle, bool flip) {
|
||||||
int count = triangle ? 3 : 4;
|
int count = triangle ? 3 : 4;
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
Vertex &v = vertices[vCount + i];
|
Vertex &v = vertices[vCount + i];
|
||||||
@@ -1010,9 +1009,14 @@ struct MeshBuilder {
|
|||||||
|
|
||||||
if (((level->version & TR::VER_PSX)) && !triangle) // TODO: swap vertices instead of rectangle indices and vertices.texCoords (WRONG lighting in TR2!)
|
if (((level->version & TR::VER_PSX)) && !triangle) // TODO: swap vertices instead of rectangle indices and vertices.texCoords (WRONG lighting in TR2!)
|
||||||
swap(vertices[vCount + 2].texCoord, vertices[vCount + 3].texCoord);
|
swap(vertices[vCount + 2].texCoord, vertices[vCount + 3].texCoord);
|
||||||
|
|
||||||
|
if (flip) {
|
||||||
|
swap(vertices[vCount + 0].texCoord, vertices[vCount + 1].texCoord);
|
||||||
|
swap(vertices[vCount + 2].texCoord, vertices[vCount + 3].texCoord);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTriangle(Index *indices, int &iCount, int vCount, int vStart, Vertex *vertices, TR::ObjectTexture *tex, bool doubleSided) {
|
void addTriangle(Index *indices, int &iCount, int vCount, int vStart, Vertex *vertices, TR::ObjectTexture *tex, bool doubleSided, bool flip) {
|
||||||
int vIndex = vCount - vStart;
|
int vIndex = vCount - vStart;
|
||||||
|
|
||||||
indices[iCount + 0] = vIndex + 0;
|
indices[iCount + 0] = vIndex + 0;
|
||||||
@@ -1028,10 +1032,10 @@ struct MeshBuilder {
|
|||||||
iCount += 3;
|
iCount += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tex) addTexCoord(vertices, vCount, tex, true);
|
if (tex) addTexCoord(vertices, vCount, tex, true, flip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addQuad(Index *indices, int &iCount, int vCount, int vStart, Vertex *vertices, TR::ObjectTexture *tex, bool doubleSided) {
|
void addQuad(Index *indices, int &iCount, int vCount, int vStart, Vertex *vertices, TR::ObjectTexture *tex, bool doubleSided, bool flip) {
|
||||||
int vIndex = vCount - vStart;
|
int vIndex = vCount - vStart;
|
||||||
|
|
||||||
indices[iCount + 0] = vIndex + 0;
|
indices[iCount + 0] = vIndex + 0;
|
||||||
@@ -1056,12 +1060,12 @@ struct MeshBuilder {
|
|||||||
iCount += 6;
|
iCount += 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tex) addTexCoord(vertices, vCount, tex, false);
|
if (tex) addTexCoord(vertices, vCount, tex, false, flip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addQuad(Index *indices, int &iCount, int &vCount, int vStart, Vertex *vertices, TR::ObjectTexture *tex, bool doubleSided,
|
void addQuad(Index *indices, int &iCount, int &vCount, int vStart, Vertex *vertices, TR::ObjectTexture *tex, bool doubleSided, bool flip,
|
||||||
const short3 &c0, const short3 &c1, const short3 &c2, const short3 &c3) {
|
const short3 &c0, const short3 &c1, const short3 &c2, const short3 &c3) {
|
||||||
addQuad(indices, iCount, vCount, vStart, vertices, tex, doubleSided);
|
addQuad(indices, iCount, vCount, vStart, vertices, tex, doubleSided, flip);
|
||||||
|
|
||||||
vec3 a = c0 - c1;
|
vec3 a = c0 - c1;
|
||||||
vec3 b = c3 - c2;
|
vec3 b = c3 - c2;
|
||||||
@@ -1099,9 +1103,9 @@ struct MeshBuilder {
|
|||||||
|
|
||||||
void addFace(Index *indices, int &iCount, int &vCount, int vStart, Vertex *vertices, const TR::Face &f, TR::ObjectTexture *tex, const short3 &a, const short3 &b, const short3 &c, const short3 &d) {
|
void addFace(Index *indices, int &iCount, int &vCount, int vStart, Vertex *vertices, const TR::Face &f, TR::ObjectTexture *tex, const short3 &a, const short3 &b, const short3 &c, const short3 &d) {
|
||||||
if (f.vCount == 4)
|
if (f.vCount == 4)
|
||||||
addQuad(indices, iCount, vCount, vStart, vertices, tex, f.flags.doubleSided, a, b, c, d);
|
addQuad(indices, iCount, vCount, vStart, vertices, tex, f.flags.doubleSided, f.flip, a, b, c, d);
|
||||||
else
|
else
|
||||||
addTriangle(indices, iCount, vCount, vStart, vertices, tex, f.flags.doubleSided);
|
addTriangle(indices, iCount, vCount, vStart, vertices, tex, f.flags.doubleSided, f.flip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1114,7 +1118,7 @@ struct MeshBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addSprite(Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 x, int16 y, int16 z, const TR::SpriteTexture &sprite, const TR::Color32 &tColor, const TR::Color32 &bColor, bool expand = false) {
|
void addSprite(Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 x, int16 y, int16 z, const TR::SpriteTexture &sprite, const TR::Color32 &tColor, const TR::Color32 &bColor, bool expand = false) {
|
||||||
addQuad(indices, iCount, vCount, vStart, NULL, NULL, false);
|
addQuad(indices, iCount, vCount, vStart, NULL, NULL, false, false);
|
||||||
|
|
||||||
Vertex *quad = &vertices[vCount];
|
Vertex *quad = &vertices[vCount];
|
||||||
|
|
||||||
@@ -1161,7 +1165,7 @@ struct MeshBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addBar(Index *indices, Vertex *vertices, int &iCount, int &vCount, const TR::ObjectTexture &tile, const vec2 &pos, const vec2 &size, uint32 color, uint32 color2 = 0) {
|
void addBar(Index *indices, Vertex *vertices, int &iCount, int &vCount, const TR::ObjectTexture &tile, const vec2 &pos, const vec2 &size, uint32 color, uint32 color2 = 0) {
|
||||||
addQuad(indices, iCount, vCount, 0, vertices, NULL, false);
|
addQuad(indices, iCount, vCount, 0, vertices, NULL, false, false);
|
||||||
|
|
||||||
int16 minX = int16(pos.x);
|
int16 minX = int16(pos.x);
|
||||||
int16 minY = int16(pos.y);
|
int16 minY = int16(pos.y);
|
||||||
@@ -1214,8 +1218,8 @@ struct MeshBuilder {
|
|||||||
v.texCoord = uv;
|
v.texCoord = uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
addQuad(indices, iCount, vCount, 0, vertices, NULL, false); vCount += 4;
|
addQuad(indices, iCount, vCount, 0, vertices, NULL, false, false); vCount += 4;
|
||||||
addQuad(indices, iCount, vCount, 0, vertices, NULL, false); vCount += 4;
|
addQuad(indices, iCount, vCount, 0, vertices, NULL, false, false); vCount += 4;
|
||||||
|
|
||||||
vertices[vCount + 0].coord = short4( minX, int16(maxY - 1), 0, 0 );
|
vertices[vCount + 0].coord = short4( minX, int16(maxY - 1), 0, 0 );
|
||||||
vertices[vCount + 1].coord = short4( maxX, int16(maxY - 1), 0, 0 );
|
vertices[vCount + 1].coord = short4( maxX, int16(maxY - 1), 0, 0 );
|
||||||
@@ -1234,8 +1238,8 @@ struct MeshBuilder {
|
|||||||
v.texCoord = uv;
|
v.texCoord = uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
addQuad(indices, iCount, vCount, 0, vertices, NULL, false); vCount += 4;
|
addQuad(indices, iCount, vCount, 0, vertices, NULL, false, false); vCount += 4;
|
||||||
addQuad(indices, iCount, vCount, 0, vertices, NULL, false); vCount += 4;
|
addQuad(indices, iCount, vCount, 0, vertices, NULL, false, false); vCount += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderBuffer(Index *indices, int iCount, Vertex *vertices, int vCount) {
|
void renderBuffer(Index *indices, int iCount, Vertex *vertices, int vCount) {
|
||||||
|
@@ -683,9 +683,10 @@ struct Texture : GAPI::Texture {
|
|||||||
|
|
||||||
struct Atlas {
|
struct Atlas {
|
||||||
struct Tile {
|
struct Tile {
|
||||||
int32 id;
|
uint16 id;
|
||||||
int16 tile;
|
uint16 type;
|
||||||
int16 clut;
|
uint16 tile;
|
||||||
|
uint16 clut;
|
||||||
short4 uv;
|
short4 uv;
|
||||||
} *tiles;
|
} *tiles;
|
||||||
|
|
||||||
@@ -760,9 +761,9 @@ struct Atlas {
|
|||||||
delete[] tiles;
|
delete[] tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(int32 id, short4 uv, int16 tile = 0, int16 clut = 0) {
|
void add(uint16 id, uint16 type, short4 uv, uint16 tile = 0, uint16 clut = 0) {
|
||||||
for (int i = 0; i < tilesCount; i++)
|
for (int i = 0; i < tilesCount; i++)
|
||||||
if (tiles[i].uv == uv && tiles[i].tile == tile && tiles[i].clut == clut) {
|
if (tiles[i].uv == uv && tiles[i].type == type && tiles[i].tile == tile && tiles[i].clut == clut) {
|
||||||
uv.x = 0x7FFF;
|
uv.x = 0x7FFF;
|
||||||
uv.y = tiles[i].id;
|
uv.y = tiles[i].id;
|
||||||
uv.z = uv.w = 0;
|
uv.z = uv.w = 0;
|
||||||
@@ -770,6 +771,7 @@ struct Atlas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tiles[tilesCount].id = id;
|
tiles[tilesCount].id = id;
|
||||||
|
tiles[tilesCount].type = type;
|
||||||
tiles[tilesCount].tile = tile;
|
tiles[tilesCount].tile = tile;
|
||||||
tiles[tilesCount].clut = clut;
|
tiles[tilesCount].clut = clut;
|
||||||
tiles[tilesCount].uv = uv;
|
tiles[tilesCount].uv = uv;
|
||||||
|
6
src/ui.h
6
src/ui.h
@@ -413,6 +413,9 @@ namespace UI {
|
|||||||
|
|
||||||
int frame = charRemap(c);
|
int frame = charRemap(c);
|
||||||
|
|
||||||
|
if (frame >= level->spriteSequences[seq].sCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (buffer.iCount == MAX_CHARS * 6)
|
if (buffer.iCount == MAX_CHARS * 6)
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
@@ -468,6 +471,9 @@ namespace UI {
|
|||||||
if (buffer.iCount == MAX_CHARS * 6)
|
if (buffer.iCount == MAX_CHARS * 6)
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
|
if (specChar >= level->spriteSequences[seq].sCount)
|
||||||
|
return;
|
||||||
|
|
||||||
TR::SpriteTexture &sprite = level->spriteTextures[level->spriteSequences[seq].sStart + specChar];
|
TR::SpriteTexture &sprite = level->spriteTextures[level->spriteSequences[seq].sStart + specChar];
|
||||||
|
|
||||||
#ifdef SPLIT_BY_TILE
|
#ifdef SPLIT_BY_TILE
|
||||||
|
Reference in New Issue
Block a user