1
0
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:
XProger
2018-11-09 06:44:16 +03:00
parent 01943a3e53
commit eef6fe100c
6 changed files with 235 additions and 137 deletions

View File

@@ -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];
} }

View File

@@ -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);

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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