1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-13 16:44:50 +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); }
};
union Tile {
struct { uint16 index:14, undefined:1, triangle:1; };
uint16 value;
};
enum TextureType {
TEX_TYPE_ROOM,
TEX_TYPE_ITEM,
@@ -1138,11 +1133,13 @@ namespace TR {
struct ObjectTexture {
TextureType type;
uint16 index;
uint16 clut;
Tile tile;
uint16 attribute:15, animated:1; // 0 - opaque, 1 - transparent, 2 - blend additive, animated
short2 texCoord[4];
short2 texCoordAtlas[4];
uint16 clut;
uint16 tile;
uint32 attribute:15, animated:1; // 0 - opaque, 1 - transparent, 2 - blend additive, animated, triangle
short2 texCoord[4];
short2 texCoordAtlas[4];
uint16 i1, i2, i3, i4, i5;
short4 getMinMax() const {
return short4(
@@ -1193,7 +1190,7 @@ namespace TR {
short3 normal;
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) {
int aIndex = a.flags.texture;
@@ -1209,9 +1206,9 @@ namespace TR {
ObjectTexture &ta = gObjectTextures[aIndex];
ObjectTexture &tb = gObjectTextures[bIndex];
if (ta.tile.index < tb.tile.index)
if (ta.tile < tb.tile)
return -1;
if (ta.tile.index > tb.tile.index)
if (ta.tile > tb.tile)
return 1;
#ifdef SPLIT_BY_CLUT
@@ -1234,7 +1231,7 @@ namespace TR {
#define FACE3_SIZE (FACE4_SIZE - sizeof(uint16))
struct ColorIndex4 {
uint8 a:4, b:4;
uint8 a:4, b:4;
};
struct Tile4 {
@@ -3004,18 +3001,14 @@ namespace TR {
uint8 data[3];
};
struct SPAL {
uint8 data[2];
};
uint32 tsubCount = 0;
uint8 *tsub = NULL;
uint32 tpalCount = 0;
TPAL *tpal = NULL;
uint32 spalCount = 0;
SPAL *spal = NULL;
int32 spalCount = 0;
uint16 *spal = NULL;
Room *room = NULL;
@@ -3025,7 +3018,7 @@ namespace TR {
char buf[9];
memcpy(buf, &chunkType, 8);
buf[8] = 0;
LOG("chunk: \"%s\"\n", buf);
LOG("chunk: \"%s\"\n", buf);
}
switch (chunkType) {
@@ -3041,30 +3034,68 @@ namespace TR {
for (int i = 0; i < roomTexturesCount; i++)
readObjectTex(stream, roomTextures[i], TEX_TYPE_ROOM);
break;
case CHUNK("ROOMTQTR") :
case CHUNK("ROOMTQTR") : {
ASSERTV(stream.readBE32() == 0x00000001);
roomTexturesDataSize = stream.readBE32();
roomTexturesData = roomTexturesDataSize ? new uint8[roomTexturesDataSize] : NULL;
stream.raw(roomTexturesData, roomTexturesDataSize);
/*
int32 count = stream.readBE32();
stream.seek(count);
*/
break;
}
case CHUNK("ROOMTSUB") :
ASSERTV(stream.readBE32() == 0x00000001);
/*
roomTexturesDataSize = stream.readBE32();
roomTexturesData = roomTexturesDataSize ? new uint8[roomTexturesDataSize] : NULL;
stream.raw(roomTexturesData, roomTexturesDataSize);
*/
tsubCount = stream.readBE32();
tsub = new uint8[tsubCount];
stream.raw(tsub, sizeof(uint8) * tsubCount);
break;
case CHUNK("ROOMTPAL") :
case CHUNK("ROOMTPAL") : {
ASSERTV(stream.readBE32() == 0x00000003);
tpalCount = stream.readBE32();
tpal = new 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;
case CHUNK("ROOMSPAL") :
}
case CHUNK("ROOMSPAL") : {
ASSERTV(stream.readLE32() == 0x02000000);
spalCount = stream.readBE32();
spal = new SPAL[spalCount];
stream.raw(spal, sizeof(SPAL) * spalCount);
spal = new uint16[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;
}
case CHUNK("ROOMDATA") :
ASSERTV(stream.readBE32() == 0x00000044);
roomsCount = stream.readBE32();
@@ -3164,6 +3195,10 @@ namespace TR {
f.vertices[3] = 0;
ASSERT(f.vertices[0] < data.vCount && f.vertices[1] < data.vCount && f.vertices[2] < data.vCount);
f.flags.value = stream.readBE16();
if (type == TYPE_T_INVISIBLE) {
fIndex--;
continue;
}
data.tCount++;
break;
case TYPE_R_INVISIBLE :
@@ -3176,19 +3211,28 @@ namespace TR {
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);
f.flags.value = stream.readBE16();
if (type == TYPE_R_INVISIBLE) {
fIndex--;
continue;
}
data.rCount++;
break;
default :
LOG("! unknown face type: %d\n", type);
ASSERT(false);
}
if (type == TYPE_R_INVISIBLE || type == TYPE_T_INVISIBLE)
f.flags.value = 0;
//if (type == TYPE_R_TRANSP)
// f.flags.value = 0;
//ASSERT(f.flags.value % 16 == 0);
//ASSERT(f.flags.value / 16 < roomTexturesCount);
f.flags.value /= 16;
f.water = false;
f.colored = false;
f.flip = false;
if (type == TYPE_R_TRANSP) {
roomTextures[f.flags.texture].attribute = 1;
}
}
}
data.fCount = fIndex;
@@ -3380,7 +3424,7 @@ namespace TR {
animTex.count = last - first + 1;
animTex.textures = new uint16[animTex.count];
for (int j = 0; j < animTex.count; j++)
animTex.textures[j] = first + j;
animTex.textures[j] = last - j;
}
break;
}
@@ -3572,7 +3616,7 @@ namespace TR {
objectTexturesCount = stream.readBE32();
objectTextures = objectTexturesCount ? new ObjectTexture[objectTexturesCount] : NULL;
for (int i = 0; i < objectTexturesCount; i++)
readObjectTex(stream, objectTextures[i]);
readObjectTex(stream, objectTextures[i], TEX_TYPE_OBJECT);
break;
case CHUNK("OTEXTDAT") : {
ASSERTV(stream.readBE32() == 0x00000001);
@@ -3960,6 +4004,7 @@ namespace TR {
#endif
f.water = false;
f.flip = false;
}
void readRoom(Stream &stream, int roomIndex) {
@@ -4199,6 +4244,7 @@ namespace TR {
f.vertices[3] >>= 2;
f.colored = false;
f.water = false;
f.flip = false;
}
} else
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[3] = 0;
f.colored = false;
f.water = false;
f.flip = false;
}
} else {
for (int i = 0; i < d.tCount; i++)
@@ -4420,7 +4468,7 @@ namespace TR {
mesh.radius = swap16(mesh.radius);
mesh.flags.value = swap16(mesh.flags.value);
mesh.vCount = swap16(mesh.vCount);
}
}
}
switch (version) {
@@ -4454,15 +4502,16 @@ namespace TR {
mesh.tCount = mesh.rCount = 0;
enum {
TYPE_T_UNKNOWN1 = 2,
TYPE_T_COLOR = 4,
TYPE_T_PALETTE = 8,
TYPE_T_UNKNOWN2 = 16,
TYPE_R_UNKNOWN1 = 17,
TYPE_R_COLOR = 5,
TYPE_R_TEX = 9,
TYPE_R_TRANSP = 49,
TYPE_R_UNKNOWN2 = 57,
TYPE_T_TEX = 2,
TYPE_T_COLOR = 4,
TYPE_T_PALETTE = 8,
TYPE_T_UNKNOWN2 = 16,
TYPE_R_COLOR = 5,
TYPE_R_TEX = 9,
TYPE_R_TRANSP = 17,
TYPE_R_FLIP_TEX = 49,
TYPE_R_FLIP_TRANSP = 57,
};
int divisor = 16;
@@ -4479,7 +4528,7 @@ namespace TR {
ASSERT(fIndex < mesh.fCount);
Face &f = mesh.faces[fIndex++];
switch (type) {
case TYPE_T_UNKNOWN1 :
case TYPE_T_TEX :
case TYPE_T_COLOR :
case TYPE_T_PALETTE :
case TYPE_T_UNKNOWN2 :
@@ -4491,12 +4540,13 @@ namespace TR {
f.flags.value = stream.readBE16();
ASSERT(f.vertices[0] < mesh.vCount && f.vertices[1] < mesh.vCount && f.vertices[2] < mesh.vCount);
mesh.tCount++;
f.colored = true;
break;
case TYPE_R_COLOR :
case TYPE_R_TEX :
case TYPE_R_TRANSP :
case TYPE_R_UNKNOWN1 :
case TYPE_R_UNKNOWN2 :
case TYPE_R_COLOR :
case TYPE_R_TEX :
case TYPE_R_TRANSP :
case TYPE_R_FLIP_TEX :
case TYPE_R_FLIP_TRANSP :
f.vCount = 4;
f.vertices[0] = (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_PALETTE)
f.flags.value = 0;
f.flags.value = 0xFFFF; // TODO
if (type == TYPE_T_UNKNOWN2)
f.flags.value = 0xFF80; // TODO
f.colored = true;
} else {
ASSERT(f.flags.value % 16 == 0);
@@ -4520,6 +4572,11 @@ namespace TR {
f.flags.value /= divisor;
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;
}
}
@@ -4813,7 +4870,8 @@ namespace TR {
case VER_TR1_SAT : {
struct {
uint16 attribute;
Tile tile;
uint16 tile;
uint8 triangle;
uint16 clut;
uint8 w, h;
uint8 x0, y0;
@@ -4828,27 +4886,37 @@ namespace TR {
if (type == TEX_TYPE_ITEM)
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 i2 = stream.readBE16();
uint16 i3 = stream.readBE16();
uint16 i4 = stream.readBE16();
d.clut = stream.readBE16() + d.tile.value; // offset to color palette
d.w = stream.read();
d.clut = stream.readBE16() + d.tile; // offset to color palette
d.w = stream.read() << 3;
d.h = stream.read();
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)
stream.seek(2);
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);
SET_PARAMS(t, d, d.clut);
t.i1 = i1;
t.i2 = i2;
t.i3 = i3;
t.i4 = i4;
t.i5 = i5;
t.index = index;
break;
@@ -4858,7 +4926,7 @@ namespace TR {
case VER_TR3_PC : {
struct {
uint16 attribute;
Tile tile;
uint16 tile:14, :2;
uint8 xh0, x0, yh0, y0;
uint8 xh1, x1, yh1, y1;
uint8 xh2, x2, yh2, y2;
@@ -4875,9 +4943,9 @@ namespace TR {
uint8 x0, y0;
uint16 clut;
uint8 x1, y1;
Tile tile;
uint16 tile:14, :2;
uint8 x2, y2;
uint16 unknown;
uint16 unknown2;
uint8 x3, y3;
uint16 attribute;
} d;
@@ -4919,7 +4987,7 @@ namespace TR {
t.b = d.b;\
}
switch (version) {
switch (version) {
case VER_TR1_SAT : {
struct {
uint16 tile;
@@ -4941,39 +5009,39 @@ namespace TR {
t.texCoord[1] = t.texCoordAtlas[1] = short2( ((int16)d.w << 3) - 1, ((int16)d.h) - 1 );
break;
}
case VER_TR1_PC :
case VER_TR2_PC :
case VER_TR3_PC : {
struct {
uint16 tile;
uint8 u, v;
uint16 w, h;
int16 l, t, r, b;
} d;
stream.raw(&d, sizeof(d));
SET_PARAMS(t, d, 0);
t.texCoord[0] = t.texCoordAtlas[0] = short2( d.u, d.v );
t.texCoord[1] = t.texCoordAtlas[1] = short2( (uint8)(d.u + (d.w >> 8)), (uint8)(d.v + (d.h >> 8)) );
break;
}
case VER_TR1_PSX :
case VER_TR2_PSX :
case VER_TR3_PSX : {
struct {
int16 l, t, r, b;
uint16 clut;
uint16 tile;
uint8 u0, v0;
uint8 u1, v1;
} d;
stream.raw(&d, sizeof(d));
SET_PARAMS(t, d, d.clut);
t.texCoord[0] = t.texCoordAtlas[0] = short2( d.u0, d.v0 );
t.texCoord[1] = t.texCoordAtlas[1] = short2( d.u1, d.v1 );
break;
}
default : ASSERT(false);
case VER_TR1_PC :
case VER_TR2_PC :
case VER_TR3_PC : {
struct {
uint16 tile;
uint8 u, v;
uint16 w, h;
int16 l, t, r, b;
} d;
stream.raw(&d, sizeof(d));
SET_PARAMS(t, d, 0);
t.texCoord[0] = t.texCoordAtlas[0] = short2( d.u, d.v );
t.texCoord[1] = t.texCoordAtlas[1] = short2( (uint8)(d.u + (d.w >> 8)), (uint8)(d.v + (d.h >> 8)) );
break;
}
case VER_TR1_PSX :
case VER_TR2_PSX :
case VER_TR3_PSX : {
struct {
int16 l, t, r, b;
uint16 clut;
uint16 tile;
uint8 u0, v0;
uint8 u1, v1;
} d;
stream.raw(&d, sizeof(d));
SET_PARAMS(t, d, d.clut);
t.texCoord[0] = t.texCoordAtlas[0] = short2( d.u0, d.v0 );
t.texCoord[1] = t.texCoordAtlas[1] = short2( d.u1, d.v1 );
break;
}
default : ASSERT(false);
}
#undef SET_PARAMS
}
@@ -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
switch (version) {
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 cOffset = uint32(uint16(clutIndex)) << 3;
@@ -5123,14 +5183,37 @@ namespace TR {
ColorIndex4 *indices = (ColorIndex4*) (data + iOffset);
CLUT *clut = (CLUT*) (data + cOffset);
int h = uv.w - uv.y;
int w = uv.z - uv.x;
ASSERT(w <= 256 && h <= 256);
/*
if (type == TEX_TYPE_OBJECT && w == 80 && h == 56) {
for (int y = 0; y < h; y++)
for (int x = 0; x < h; x++)
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;
}
for (int y = uv.y; y < uv.w; y++)
for (int x = uv.x; x < uv.z; x++) {
ColorIndex4 *index = indices + ((y - uv.y) * w + (x - uv.x)) / 2;
Color16 &c = clut->color[(x % 2) ? index->a : index->b];
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;
}
case VER_TR1_PC : {
@@ -5205,7 +5288,7 @@ namespace TR {
ObjectTexture &t = objectTextures[texture & 0x7FFF];
int idx = (t.texCoord[0].y * 256 + 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];
return clut.color[part ? tile.index[idx].b : tile.index[idx].a];
}
@@ -5278,7 +5361,7 @@ namespace TR {
void floorSkipCommand(FloorData* &fd, int func) {
switch (func) {
case FloorData::PORTAL :
case FloorData::PORTAL :
case FloorData::FLOOR :
case FloorData::CEILING :
fd++;

View File

@@ -936,6 +936,7 @@ namespace TR {
}
} else {
switch (version) {
case VER_TR1_SAT :
case VER_TR1_PC :
case VER_TR1_PSX :
sprintf(title, "audio/1/track_%02d.ogg", track);

View File

@@ -1145,7 +1145,8 @@ struct Level : IGame {
src = owner->tileData->color;
uv = t.texCoordAtlas;
uvCount = 4;
level->fillObjectTexture(owner->tileData, tile.uv, tile.tile, tile.clut, t.type);
if (data)
level->fillObjectTexture(owner->tileData, tile.uv, tile.tile, tile.clut, t.type);
} else {
id -= level->objectTexturesCount;
@@ -1155,7 +1156,8 @@ struct Level : IGame {
src = owner->tileData->color;
uv = t.texCoordAtlas;
uvCount = 2;
level->fillObjectTexture(owner->tileData, tile.uv, tile.tile, tile.clut, TR::TextureType::TEX_TYPE_SPRITE);
if (data)
level->fillObjectTexture(owner->tileData, tile.uv, tile.tile, tile.clut, TR::TextureType::TEX_TYPE_SPRITE);
} else { // common (generated) textures
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.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
for (int i = 0; i < level.spriteTexturesCount; i++) {
@@ -1314,12 +1316,12 @@ struct Level : IGame {
uv.z = t.texCoord[1].x + 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
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++)
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
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_OFFSET 4
const TR::Color32 COLOR_WHITE( 255, 255, 255, 255 );
struct Mesh : GAPI::Mesh {
int aIndex;
@@ -365,8 +367,6 @@ struct MeshBuilder {
int vStartModel = vCount;
aCount++;
TR::Color32 COLOR_WHITE(255, 255, 255, 255);
for (int i = 0; i < level.modelsCount; i++) {
TR::Model &model = level.models[i];
@@ -487,7 +487,7 @@ struct MeshBuilder {
quad.iStart = iCount;
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 + 1].coord = short4( 32767, 32767, 1, 1 );
vertices[vCount + 2].coord = short4( 32767, -32767, 1, 0 );
@@ -926,8 +926,8 @@ struct MeshBuilder {
continue;
}
if (!geom.validForTile(t.tile.index, t.clut))
geom.getNextRange(vStart, iCount, t.tile.index, t.clut);
if (!geom.validForTile(t.tile, t.clut))
geom.getNextRange(vStart, iCount, t.tile, t.clut);
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) {
TR::Color24 COLOR_WHITE( 255, 255, 255 );
bool isOpaque = true;
for (int j = 0; j < mesh.fCount; j++) {
@@ -973,8 +972,8 @@ struct MeshBuilder {
if (!(blendMask & getBlendMask(t.attribute)))
continue;
if (!geom.validForTile(t.tile.index, t.clut))
geom.getNextRange(vStart, iCount, t.tile.index, t.clut);
if (!geom.validForTile(t.tile, t.clut))
geom.getNextRange(vStart, iCount, t.tile, t.clut);
TR::Color32 c = f.colored ? level.getColor(f.flags.value) : COLOR_WHITE;
@@ -1001,7 +1000,7 @@ struct MeshBuilder {
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;
for (int i = 0; i < count; 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!)
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;
indices[iCount + 0] = vIndex + 0;
@@ -1028,10 +1032,10 @@ struct MeshBuilder {
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;
indices[iCount + 0] = vIndex + 0;
@@ -1056,12 +1060,12 @@ struct MeshBuilder {
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) {
addQuad(indices, iCount, vCount, vStart, vertices, tex, doubleSided);
addQuad(indices, iCount, vCount, vStart, vertices, tex, doubleSided, flip);
vec3 a = c0 - c1;
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) {
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
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) {
addQuad(indices, iCount, vCount, vStart, NULL, NULL, false);
addQuad(indices, iCount, vCount, vStart, NULL, NULL, false, false);
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) {
addQuad(indices, iCount, vCount, 0, vertices, NULL, false);
addQuad(indices, iCount, vCount, 0, vertices, NULL, false, false);
int16 minX = int16(pos.x);
int16 minY = int16(pos.y);
@@ -1214,8 +1218,8 @@ struct MeshBuilder {
v.texCoord = uv;
}
addQuad(indices, iCount, vCount, 0, vertices, NULL, false); vCount += 4;
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, false); vCount += 4;
vertices[vCount + 0].coord = short4( minX, 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;
}
addQuad(indices, iCount, vCount, 0, vertices, NULL, false); vCount += 4;
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, false); vCount += 4;
}
void renderBuffer(Index *indices, int iCount, Vertex *vertices, int vCount) {

View File

@@ -683,9 +683,10 @@ struct Texture : GAPI::Texture {
struct Atlas {
struct Tile {
int32 id;
int16 tile;
int16 clut;
uint16 id;
uint16 type;
uint16 tile;
uint16 clut;
short4 uv;
} *tiles;
@@ -760,9 +761,9 @@ struct Atlas {
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++)
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.y = tiles[i].id;
uv.z = uv.w = 0;
@@ -770,6 +771,7 @@ struct Atlas {
}
tiles[tilesCount].id = id;
tiles[tilesCount].type = type;
tiles[tilesCount].tile = tile;
tiles[tilesCount].clut = clut;
tiles[tilesCount].uv = uv;

View File

@@ -413,6 +413,9 @@ namespace UI {
int frame = charRemap(c);
if (frame >= level->spriteSequences[seq].sCount)
continue;
if (buffer.iCount == MAX_CHARS * 6)
flush();
@@ -468,6 +471,9 @@ namespace UI {
if (buffer.iCount == MAX_CHARS * 6)
flush();
if (specChar >= level->spriteSequences[seq].sCount)
return;
TR::SpriteTexture &sprite = level->spriteTextures[level->spriteSequences[seq].sStart + specChar];
#ifdef SPLIT_BY_TILE