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:
289
src/format.h
289
src/format.h
@@ -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;
|
||||
|
||||
@@ -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++;
|
||||
|
@@ -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);
|
||||
|
12
src/level.h
12
src/level.h
@@ -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();
|
||||
|
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_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) {
|
||||
|
@@ -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;
|
||||
|
6
src/ui.h
6
src/ui.h
@@ -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
|
||||
|
Reference in New Issue
Block a user