1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-03-13 23:59:41 +01:00
This commit is contained in:
XProger 2016-09-08 22:27:37 +03:00
parent 07e2b99ead
commit 460f3be4c5
10 changed files with 292 additions and 159 deletions

Binary file not shown.

View File

@ -3,9 +3,11 @@
#include "format.h"
#define GRAVITY 7.0f
#define GRAVITY 6.0f
#define NO_OVERLAP 0x7FFFFFFF
#define SND_SECRET 13
struct Controller {
TR::Level *level;
int entity;
@ -64,7 +66,9 @@ struct Controller {
}
TR::Room& getRoom() {
return level->rooms[getEntity().room];
int index = getEntity().room;
ASSERT(index >= 0 && index < level->roomsCount);
return level->rooms[index];
}
TR::Room::Sector& getSector(int x, int z, int &dx, int &dz) {
@ -119,31 +123,34 @@ struct Controller {
int roomNext, roomBelow, roomAbove;
};
int getOverlap(int fromX, int fromY, int fromZ, int toX, int toZ) {
int getOverlap(int fromX, int fromY, int fromZ, int toX, int toZ, int &delta) {
int dx, dz;
TR::Room::Sector &s = getSector(fromX, fromZ, dx, dz);
if (s.boxIndex == 0xFFFF) return NO_OVERLAP;
TR::Box &b = level->boxes[s.boxIndex];
if (b.contains(toX, toZ))
if (b.contains(toX, toZ)) {
delta = 0;
return b.floor;
}
int floor = NO_OVERLAP;
int delta = 0x7FFFFFFF;
delta = floor;
TR::Overlap *o = &level->overlaps[b.overlap & 0x7FFF];
do {
TR::Box &b = level->boxes[o->boxIndex];
if (b.contains(toX, toZ)) { // get min delta
int d = abs(fromY - b.floor);
TR::Box &ob = level->boxes[o->boxIndex];
if (ob.contains(toX, toZ)) { // get min delta
int d = abs(ob.floor - b.floor);
if (d < delta) {
floor = b.floor;
floor = ob.floor;
delta = d;
}
}
} while (!(o++)->end);
delta = floor - b.floor;
return floor;
}
@ -213,6 +220,10 @@ struct Controller {
break;
}
case TR::FD_KILL :
health = 0;
break;
default : LOG("unknown func: %d\n", cmd.func);
}
@ -221,6 +232,18 @@ struct Controller {
return info;
}
void playSound(int id) {
int16 a = level->soundsMap[id];
TR::SoundInfo &b = level->soundsInfo[a];
if (b.chance == 0 || (rand() & 0x7fff) <= b.chance) {
uint32 c = level->soundOffsets[b.offset + rand() % ((b.flags & 0xFF) >> 2)];
void *p = &level->soundData[c];
#ifdef WIN32
PlaySound((LPSTR)p, NULL, SND_ASYNC | SND_MEMORY);
#endif
}
}
};
@ -240,9 +263,11 @@ struct Lara : Controller {
bool lState;
Lara(TR::Level *level, int entity) : Controller(level, entity) {
/*
pos = vec3(70067, -256, 29104);
angle = vec3(0.0f, -0.68f, 0.0f);
getEntity().room = 15;
getEntity().room = 15;
*/
}
virtual void update() {
@ -250,7 +275,7 @@ struct Lara : Controller {
TR::Animation *anim = &level->anims[model.animation];
fTime += Core::deltaTime;
// return;
float rot = 0.0f;
enum { LEFT = 1 << 1,
@ -283,7 +308,9 @@ struct Lara : Controller {
int state = anim->state;
if ((mask & (GROUND | WATER)) == (GROUND | WATER)) { // on water surface
if (mask & DEATH)
state = TR::STATE_DEATH;
else if ((mask & (GROUND | WATER)) == (GROUND | WATER)) { // on water surface
angle.x = 0.0f;
state = TR::STATE_SURF_TREAD;
@ -398,7 +425,15 @@ struct Lara : Controller {
#ifdef _DEBUG
// show state transitions for current animation
if (Input::down[ikEnter]) {
if (!lState) {
lState = true;
static int snd_id = 0;
playSound(snd_id);
LOG("sound: %d\n", snd_id++);
}
/*
LOG("state: %d\n", anim->state);
for (int i = 0; i < anim->scCount; i++) {
auto &sc = level->states[anim->scOffset + i];
@ -408,8 +443,9 @@ struct Lara : Controller {
LOG("%d ", range.nextAnimation);
}
LOG("\n");
}
}
}*/
} else
lState = false;
#endif
// calculate turn tilt
@ -500,11 +536,13 @@ struct Lara : Controller {
} else
velocity.y += GRAVITY * dt;
// apply animation commands
int16 *ptr = &level->commands[anim->animCommand];
for (int i = 0; i < anim->acCount; i++) {
switch (*ptr++) {
int cmd = *ptr++;
switch (cmd) {
case 0x01 : { // cmd position
int16 sx = *ptr++;
int16 sy = *ptr++;
@ -538,17 +576,7 @@ struct Lara : Controller {
// LOG("play sound at %d current %d last %d (%d)\n", idx, fIndex, lastFrame, (int)id);
if (idx > lastFrame && idx <= fIndex) {
int16 a = level->soundsMap[id];
TR::SoundInfo &b = level->soundsInfo[a];
if (b.chance == 0 || (rand() & 0x7fff) <= b.chance) {
uint32 c = level->soundOffsets[b.offset + rand() % ((b.flags & 0xFF) >> 2)];
void *p = &level->soundData[c];
#ifdef WIN32
// LOG("play\n");
PlaySound((LPSTR)p, NULL, SND_ASYNC | SND_MEMORY);
#endif
}
playSound(id);
}
break;
}
@ -561,7 +589,7 @@ struct Lara : Controller {
ptr += 2;
break;
default :
LOG("unknown animation command\n");
LOG("unknown animation command %d\n", cmd);
}
}
@ -574,10 +602,10 @@ struct Lara : Controller {
}
move(velocity * dt);
collide();
lastFrame = fIndex;
}
@ -585,14 +613,15 @@ struct Lara : Controller {
vec3 p = pos;
pos = pos + offset;
int d = getOverlap((int)p.x, (int)p.y, (int)p.z, (int)pos.x, (int)pos.z);
int delta;
int d = getOverlap((int)p.x, (int)p.y, (int)p.z, (int)pos.x, (int)pos.z, delta);
int state = level->anims[getModel().animation].state;
bool stop = false;
if ((d == NO_OVERLAP) ||
((state == TR::STATE_WALK || state == TR::STATE_BACK || state == TR::STATE_STEP_LEFT || state == TR::STATE_STEP_RIGHT) && (int)p.y - d < -256) ||
((int)p.y - d > 256)) {
((state == TR::STATE_WALK || state == TR::STATE_BACK || state == TR::STATE_STEP_LEFT || state == TR::STATE_STEP_RIGHT) && delta > 256) /*||
(delta < -256) */) {
pos = p;

View File

@ -40,6 +40,7 @@
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLUNIFORM1IVPROC glUniform1iv;
PFNGLUNIFORM2FVPROC glUniform2fv;
PFNGLUNIFORM3FVPROC glUniform3fv;
PFNGLUNIFORM4FVPROC glUniform4fv;
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
@ -104,6 +105,7 @@ namespace Core {
GetProcOGL(glGetShaderInfoLog);
GetProcOGL(glGetUniformLocation);
GetProcOGL(glUniform1iv);
GetProcOGL(glUniform2fv);
GetProcOGL(glUniform3fv);
GetProcOGL(glUniform4fv);
GetProcOGL(glUniformMatrix4fv);

View File

@ -113,10 +113,11 @@ namespace Debug {
namespace Level {
void debugFloor(const TR::Level &level, const vec3 &f, const vec3 &c, int floorIndex, int boxIndex, bool current) {
if (floorIndex == 0) return;
vec3 vf[4] = { f, f + vec3(1024, 0, 0), f + vec3(1024, 0, 1024), f + vec3(0, 0, 1024) };
vec3 vc[4] = { c, c + vec3(1024, 0, 0), c + vec3(1024, 0, 1024), c + vec3(0, 0, 1024) };
if (current)
glColor3f(1, 1, 1);
else
@ -280,6 +281,7 @@ namespace Debug {
glDisable(GL_DEPTH_TEST);
glColor4f(0.0f, 1.0f, 0.0f, 0.25f);
debugBox(level.boxes[s.boxIndex]);
glColor4f(1.0f, 1.0f, 0.0f, 0.25f);
debugOverlaps(level, s.boxIndex);
glEnable(GL_DEPTH_TEST);
}

View File

@ -6,6 +6,7 @@
#define TR1_DEMO
namespace TR {
enum : int32 {
ROOM_FLAG_WATER = 0x0001,
ROOM_FLAG_VISIBLE = 0x8000
@ -16,6 +17,7 @@ namespace TR {
FD_FLOOR = 2,
FD_CEILING = 3,
FD_TRIGGER = 4,
FD_KILL = 5,
};
#define DATA_PORTAL 0x01
@ -348,8 +350,8 @@ namespace TR {
};
struct AnimTexture {
int16 tCount; // Actually, this is the number of texture ID's - 1
int16 textures[0]; // offsets into ObjectTextures[], in animation order
int16 count; // number of texture offsets - 1 in group
int16 textures[0]; // offsets into objectTextures[]
};
struct Node {
@ -375,9 +377,13 @@ namespace TR {
uint16 flags;
};
struct Tile {
uint16 index:14, undefined:1, triangle:1; // undefined - need check is animated, animated - is animated
};
struct ObjectTexture {
uint16 attribute; // 0 - opaque, 1 - transparent, 2 - blend additive
uint16 tileAndFlag; // 0..14 - tile, 15 - is triangle
Tile tile; // 0..14 - tile, 15 - is triangle
struct {
uint8 Xcoordinate; // 1 if Xpixel is the low value, 255 if Xpixel is the high value in the object texture
uint8 Xpixel;
@ -423,8 +429,8 @@ namespace TR {
};
struct Box {
int32 minZ, maxZ; // Horizontal dimensions in global units
int32 minX, maxX;
uint32 minZ, maxZ; // Horizontal dimensions in global units
uint32 minX, maxX;
int16 floor; // Height value in global units
uint16 overlap; // Index into Overlaps[].
@ -451,8 +457,6 @@ namespace TR {
#pragma pack(pop)
struct Level {
char *data;
uint32 version; // version (4 bytes)
int32 tilesCount;
@ -586,7 +590,6 @@ namespace TR {
r.meshes = new Room::Mesh[stream.read(r.meshesCount)];
for (int i = 0; i < r.meshesCount; i++)
stream.raw(&r.meshes[i], sizeof(r.meshes[i]) - sizeof(r.meshes[i].align));
// stream.read(r.meshes, stream.read(r.meshesCount));
// misc flags
stream.read(r.alternateRoom);
stream.read(r.flags);
@ -608,7 +611,6 @@ namespace TR {
models = new Model[stream.read(modelsCount)];
for (int i = 0; i < modelsCount; i++)
stream.raw(&models[i], sizeof(models[i]) - sizeof(models[i].align));
// stream.read(models, stream.read(modelsCount));
stream.read(staticMeshes, stream.read(staticMeshesCount));
// textures & UV
stream.read(objectTextures, stream.read(objectTexturesCount));
@ -633,7 +635,6 @@ namespace TR {
entities = new Entity[stream.read(entitiesCount)];
for (int i = 0; i < entitiesCount; i++)
stream.raw(&entities[i], sizeof(entities[i]) - sizeof(entities[i].align));
// stream.read(entities, stream.read(entitiesCount));
// palette
stream.seek(32 * 256); // skip lightmap palette

View File

@ -29,13 +29,10 @@ struct Level {
Camera camera;
Level(Stream &stream) : level{stream}, time(0.0f) {
shaders[shStatic] = new Shader(SHADER);
shaders[shCaustics] = new Shader(SHADER, "#define CAUSTICS\n");
shaders[shSprite] = new Shader(SHADER, "#define SPRITE\n");
initAtlas();
mesh = new MeshBuilder(level);
initAtlas();
initShaders();
int entity = 0;
for (int i = 0; i < level.entitiesCount; i++)
@ -99,6 +96,17 @@ struct Level {
delete[] data;
}
void initShaders() {
char def[255], ext[255];
sprintf(def, "#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n", mesh->animTexRangesCount, mesh->animTexOffsetsCount);
shaders[shStatic] = new Shader(SHADER, def);
sprintf(ext, "%s#define CAUSTICS\n", def);
shaders[shCaustics] = new Shader(SHADER, ext);
sprintf(ext, "%s#define SPRITE\n", def);
shaders[shSprite] = new Shader(SHADER, ext);
}
TR::StaticMesh* getMeshByID(int id) {
for (int i = 0; i < level.staticMeshesCount; i++)
if (level.staticMeshes[i].id == id)
@ -117,6 +125,8 @@ struct Level {
}
void renderRoom(int index) {
ASSERT(index >= 0 && index < level.roomsCount);
TR::Room &room = level.rooms[index];
if (room.flags & TR::ROOM_FLAG_VISIBLE) return; // already rendered
@ -360,10 +370,10 @@ struct Level {
TR::Room::Light &light = level.rooms[room].lights[idx];
float c = level.rooms[room].lights[idx].intensity / 8191.0f;
Core::lightPos = vec3(light.x, light.y, light.z);
Core::lightColor = vec4(c, c, c, light.attenuation * light.attenuation);
Core::lightColor = vec4(c, c, c, (float)light.attenuation * (float)light.attenuation);
} else {
Core::lightPos = vec3(0.0f);
Core::lightColor = vec4(0.0f);
Core::lightPos = vec3(0);
Core::lightColor = vec4(0, 0, 0, 1);
}
Core::ambient = vec3(1.0f - level.rooms[roomIndex].ambient / 8191.0f);
Core::active.shader->setParam(uAmbient, Core::ambient);
@ -430,26 +440,6 @@ struct Level {
camera.targetDeltaPos = lara->inWater ? vec3(0.0f, -256.0f, 0.0f) : vec3(0.0f, -768.0f, 0.0f);
camera.targetAngle = vec3(lara->angle.x, -lara->angle.y, 0.0f); //-lara->angle.z);
camera.update();
/*
if (tickTextureAnimation > 0.25f) {
tickTextureAnimation = 0.0f;
if (level.animTexturesDataSize) {
uint16 *ptr = &level.animTexturesData[0];
int count = *ptr++;
for (int i = 0; i < count; i++) {
auto animTex = (TR::AnimTexture*)ptr;
auto id = level.objectTextures[animTex->textures[0]];
for (int j = 0; j < animTex->tCount; j++) // tCount = count of textures in animation group - 1 (!!!)
level.objectTextures[animTex->textures[j]] = level.objectTextures[animTex->textures[j + 1]];
level.objectTextures[animTex->textures[animTex->tCount]] = id;
ptr += (sizeof(TR::AnimTexture) + sizeof(animTex->textures[0]) * (animTex->tCount + 1)) / sizeof(uint16);
}
}
} else
tickTextureAnimation += Core::deltaTime;
*/
}
int getCameraRoomIndex() {
@ -473,7 +463,9 @@ struct Level {
shaders[i]->setParam(uViewProj, Core::mViewProj);
shaders[i]->setParam(uViewInv, Core::mViewInv);
shaders[i]->setParam(uViewPos, Core::viewPos);
shaders[i]->setParam(uParam, vec4(time, sinf(time * 1024.0f), 0, 0));
shaders[i]->setParam(uParam, vec4(time, 0, 0, 0));
shaders[i]->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount);
shaders[i]->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount);
}
glEnable(GL_DEPTH_TEST);

View File

@ -7,10 +7,10 @@
typedef unsigned short Index;
struct Vertex {
short3 coord;
short2 texCoord;
short4 normal;
ubyte4 color;
short4 coord; // xyz - position
short4 texCoord; // xy - texture coordinates, z - anim tex range index, w - anim tex frame index
short4 normal; // xyz - vertex normal, w - disable lighting (0, 1)
ubyte4 color; // rgba - color
};
struct MeshRange {
@ -47,8 +47,8 @@ struct Mesh {
void render(const MeshRange &range) {
Vertex *v = (Vertex*)(range.vStart * sizeof(Vertex));
glVertexAttribPointer(aCoord, 3, GL_SHORT, false, sizeof(Vertex), &v->coord);
glVertexAttribPointer(aTexCoord, 2, GL_SHORT, true, sizeof(Vertex), &v->texCoord);
glVertexAttribPointer(aCoord, 4, GL_SHORT, false, sizeof(Vertex), &v->coord);
glVertexAttribPointer(aTexCoord, 4, GL_SHORT, false, sizeof(Vertex), &v->texCoord);
glVertexAttribPointer(aNormal, 4, GL_SHORT, false, sizeof(Vertex), &v->normal);
glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), &v->color);
glDrawElements(GL_TRIANGLES, range.iCount, GL_UNSIGNED_SHORT, (GLvoid*)(range.iStart * sizeof(Index)));
@ -79,7 +79,31 @@ struct MeshBuilder {
// indexed mesh
Mesh *mesh;
MeshBuilder(const TR::Level &level) {
vec2 *animTexRanges;
vec2 *animTexOffsets;
int animTexRangesCount;
int animTexOffsetsCount;
TR::Level *level;
MeshBuilder(TR::Level &level) : level(&level) {
initAnimTextures(level);
// create dummy white object textures for non-textured (colored) geometry
TR::ObjectTexture whiteTileQuad;
whiteTileQuad.attribute = 0;
whiteTileQuad.tile.index = 15;
whiteTileQuad.tile.triangle = 0;
whiteTileQuad.vertices[0] =
whiteTileQuad.vertices[1] =
whiteTileQuad.vertices[2] =
whiteTileQuad.vertices[3] = { 0, 253, 0, 253 };
TR::ObjectTexture whiteTileTri = whiteTileQuad;
whiteTileTri.tile.triangle = 1;
// allocate room geometry ranges
roomRanges = new RoomRange[level.roomsCount];
int iCount = 0, vCount = 0;
@ -158,37 +182,27 @@ struct MeshBuilder {
// rooms geometry
int vStart = vCount;
for (int j = 0; j < d.rCount; j++) {
auto &f = d.rectangles[j];
auto &t = level.objectTextures[f.texture];
TR::Rectangle &f = d.rectangles[j];
TR::ObjectTexture &t = level.objectTextures[f.texture];
int tile = t.tileAndFlag & 0x7FFF;
int tx = (tile % 4) * 256;
int ty = (tile / 4) * 256;
addQuad(indices, iCount, vCount, vStart);
addQuad(indices, iCount, vCount, vStart, vertices, &t);
for (int k = 0; k < 4; k++) {
auto &v = d.vertices[f.vertices[k]];
TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]];
uint8 a = 255 - (v.lighting >> 5);
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z };
vertices[vCount].color = { a, a, a, 255 };
vertices[vCount].normal = { 0, 0, 0, 1 };
vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16;
vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16;
vCount++;
}
}
for (int j = 0; j < d.tCount; j++) {
auto &f = d.triangles[j];
auto &t = level.objectTextures[f.texture];
TR::Triangle &f = d.triangles[j];
TR::ObjectTexture &t = level.objectTextures[f.texture];
int tile = t.tileAndFlag & 0x7FFF;
int tx = (tile % 4) * 256;
int ty = (tile / 4) * 256;
addTriangle(indices, iCount, vCount, vStart);
addTriangle(indices, iCount, vCount, vStart, vertices, &t);
for (int k = 0; k < 3; k++) {
auto &v = d.vertices[f.vertices[k]];
@ -197,8 +211,6 @@ struct MeshBuilder {
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z };
vertices[vCount].color = { a, a, a, 255 };
vertices[vCount].normal = { 0, 0, 0, 1 };
vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16;
vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16;
vCount++;
}
}
@ -210,6 +222,7 @@ struct MeshBuilder {
TR::Room::Data::Sprite &f = d.sprites[j];
TR::Room::Data::Vertex &v = d.vertices[f.vertex];
TR::SpriteTexture &sprite = level.spriteTextures[f.texture];
uint8 intensity = 255 - (v.lighting >> 5);
addSprite(indices, vertices, iCount, vCount, vStart, v.vertex.x, v.vertex.y, v.vertex.z, sprite, intensity);
}
@ -245,14 +258,10 @@ struct MeshBuilder {
int vStart = vCount;
// rectangles
for (int j = 0; j < ptr->rCount; j++) {
auto &f = ((TR::Rectangle*)&ptr->rectangles)[j];
auto &t = level.objectTextures[f.texture];
TR::Rectangle &f = ((TR::Rectangle*)&ptr->rectangles)[j];
TR::ObjectTexture &t = level.objectTextures[f.texture];
int tile = t.tileAndFlag & 0x7FFF;
int tx = (tile % 4) * 256;
int ty = (tile / 4) * 256;
addQuad(indices, iCount, vCount, vStart);
addQuad(indices, iCount, vCount, vStart, vertices, &t);
for (int k = 0; k < 4; k++) {
auto &v = mVertices[f.vertices[k]];
@ -268,8 +277,6 @@ struct MeshBuilder {
vertices[vCount].normal = { 0, 0, 0, 1 };
vertices[vCount].color = { a, a, a, 255 };
}
vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16;
vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16;
vCount++;
}
}
@ -277,14 +284,10 @@ struct MeshBuilder {
// triangles
for (int j = 0; j < ptr->tCount; j++) {
auto &f = ((TR::Triangle*)&ptr->triangles)[j];
auto &t = level.objectTextures[f.texture];
TR::Triangle &f = ((TR::Triangle*)&ptr->triangles)[j];
TR::ObjectTexture &t = level.objectTextures[f.texture];
int tile = t.tileAndFlag & 0x7FFF;
int tx = (tile % 4) * 256;
int ty = (tile / 4) * 256;
addTriangle(indices, iCount, vCount, vStart);
addTriangle(indices, iCount, vCount, vStart, vertices, &t);
for (int k = 0; k < 3; k++) {
auto &v = mVertices[f.vertices[k]];
@ -299,8 +302,6 @@ struct MeshBuilder {
vertices[vCount].normal = { 0, 0, 0, 1 };
vertices[vCount].color = { a, a, a, 255 };
}
vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16;
vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16;
vCount++;
}
}
@ -308,15 +309,15 @@ struct MeshBuilder {
// color rectangles
for (int j = 0; j < ptr->crCount; j++) {
auto &f = ((TR::Rectangle*)&ptr->crectangles)[j];
auto &c = level.palette[f.texture & 0xFF];
TR::Rectangle &f = ((TR::Rectangle*)&ptr->crectangles)[j];
TR::RGB &c = level.palette[f.texture & 0xFF];
addQuad(indices, iCount, vCount, vStart);
addQuad(indices, iCount, vCount, vStart, vertices, &whiteTileQuad);
for (int k = 0; k < 4; k++) {
auto &v = mVertices[f.vertices[k]];
vertices[vCount].coord = { v.x, v.y, v.z };
vertices[vCount].coord = { v.x, v.y, v.z, 0 };
if (nCount > 0) {
TR::Vertex &n = normals[f.vertices[k]];
@ -327,7 +328,6 @@ struct MeshBuilder {
vertices[vCount].normal = { 0, 0, 0, 1 };
vertices[vCount].color = { a, a, a, 255 }; // TODO: apply color
}
vertices[vCount].texCoord = { 1022 << 5, 1022 << 5 };
vCount++;
}
}
@ -335,15 +335,15 @@ struct MeshBuilder {
// color triangles
for (int j = 0; j < ptr->ctCount; j++) {
auto &f = ((TR::Triangle*)&ptr->ctriangles)[j];
auto &c = level.palette[f.texture & 0xFF];
TR::Triangle &f = ((TR::Triangle*)&ptr->ctriangles)[j];
TR::RGB &c = level.palette[f.texture & 0xFF];
addTriangle(indices, iCount, vCount, vStart);
addTriangle(indices, iCount, vCount, vStart, vertices, &whiteTileTri);
for (int k = 0; k < 3; k++) {
auto &v = mVertices[f.vertices[k]];
vertices[vCount].coord = { v.x, v.y, v.z };
vertices[vCount].coord = { v.x, v.y, v.z, 0 };
if (nCount > 0) {
TR::Vertex &n = normals[f.vertices[k]];
@ -354,7 +354,6 @@ struct MeshBuilder {
vertices[vCount].normal = { 0, 0, 0, 1 };
vertices[vCount].color = { a, a, a, 255 }; // TODO: apply color
}
vertices[vCount].texCoord = { 1022 << 5, 1022 << 5 };
vCount++;
}
}
@ -377,13 +376,105 @@ struct MeshBuilder {
}
~MeshBuilder() {
delete[] animTexRanges;
delete[] animTexOffsets;
delete[] roomRanges;
delete[] meshInfo;
delete[] spriteRanges;
delete mesh;
}
void addTriangle(Index *indices, int &iCount, int vCount, int vStart) {
vec2 getTexCoord(const TR::ObjectTexture &tex) {
int tile = tex.tile.index;
int tx = (tile % 4) * 256;
int ty = (tile / 4) * 256;
return vec2( ((tx + tex.vertices[0].Xpixel) << 5) + 16,
((ty + tex.vertices[0].Ypixel) << 5) + 16 );
}
void initAnimTextures(TR::Level &level) {
if (!level.animTexturesDataSize) {
animTexRangesCount = animTexOffsetsCount = 1;
animTexRanges = new vec2[1];
animTexOffsets = new vec2[1];
animTexRanges[0] = vec2(0.0f, 1.0f);
animTexOffsets[0] = vec2(0.0f);
}
uint16 *ptr = &level.animTexturesData[0];
animTexRangesCount = *ptr++ + 1;
animTexRanges = new vec2[animTexRangesCount];
animTexRanges[0] = vec2(0.0f, 1.0f);
animTexOffsetsCount = 1;
for (int i = 1; i < animTexRangesCount; i++) {
TR::AnimTexture *animTex = (TR::AnimTexture*)ptr;
int start = animTexOffsetsCount;
animTexOffsetsCount += animTex->count + 1;
animTexRanges[i] = vec2((float)start, (float)(animTexOffsetsCount - start));
ptr += (sizeof(TR::AnimTexture) + sizeof(animTex->textures[0]) * (animTex->count + 1)) / sizeof(uint16);
}
animTexOffsets = new vec2[animTexOffsetsCount];
animTexOffsets[0] = vec2(0.0f);
animTexOffsetsCount = 1;
ptr = &level.animTexturesData[1];
for (int i = 1; i < animTexRangesCount; i++) {
int start = animTexOffsetsCount;
TR::AnimTexture *animTex = (TR::AnimTexture*)ptr;
vec2 first = getTexCoord(level.objectTextures[animTex->textures[0]]);
animTexOffsets[animTexOffsetsCount++] = vec2(0.0f); // first - first for first frame %)
for (int j = 1; j <= animTex->count; j++)
animTexOffsets[animTexOffsetsCount++] = getTexCoord(level.objectTextures[animTex->textures[j]]) - first;
ptr += (sizeof(TR::AnimTexture) + sizeof(animTex->textures[0]) * (animTex->count + 1)) / sizeof(uint16);
}
}
TR::ObjectTexture* getAnimTexture(TR::ObjectTexture *tex, int &range, int &frame) {
range = frame = 0;
if (!level->animTexturesDataSize)
return tex;
uint16 *ptr = &level->animTexturesData[1];
for (int i = 1; i < animTexRangesCount; i++) {
TR::AnimTexture *animTex = (TR::AnimTexture*)ptr;
for (int j = 0; j <= animTex->count; j++)
if (tex == &level->objectTextures[animTex->textures[j]]) {
range = i;
frame = j;
return &level->objectTextures[animTex->textures[0]];
}
ptr += (sizeof(TR::AnimTexture) + sizeof(animTex->textures[0]) * (animTex->count + 1)) / sizeof(uint16);
}
return tex;
}
void addTexCoord(Vertex *vertices, int vCount, TR::ObjectTexture *tex) {
int range, frame;
tex = getAnimTexture(tex, range, frame);
int tile = tex->tile.index;
int tx = (tile % 4) * 256;
int ty = (tile / 4) * 256;
int count = tex->tile.triangle ? 3 : 4;
for (int i = 0; i < count; i++) {
Vertex &v = vertices[vCount + i];
v.texCoord.x = ((tx + tex->vertices[i].Xpixel) << 5) + 16;
v.texCoord.y = ((ty + tex->vertices[i].Ypixel) << 5) + 16;
v.texCoord.z = range;
v.texCoord.w = frame;
}
}
void addTriangle(Index *indices, int &iCount, int vCount, int vStart, Vertex *vertices, TR::ObjectTexture *tex) {
int vIndex = vCount - vStart;
indices[iCount + 0] = vIndex + 0;
@ -391,9 +482,11 @@ struct MeshBuilder {
indices[iCount + 2] = vIndex + 2;
iCount += 3;
}
void addQuad(Index *indices, int &iCount, int vCount, int vStart) {
if (tex) addTexCoord(vertices, vCount, tex);
}
void addQuad(Index *indices, int &iCount, int vCount, int vStart, Vertex *vertices, TR::ObjectTexture *tex) {
int vIndex = vCount - vStart;
indices[iCount + 0] = vIndex + 0;
@ -405,14 +498,17 @@ struct MeshBuilder {
indices[iCount + 5] = vIndex + 3;
iCount += 6;
if (tex) addTexCoord(vertices, vCount, tex);
}
void addSprite(Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 x, int16 y, int16 z, const TR::SpriteTexture &sprite, uint8 intensity) {
addQuad(indices, iCount, vCount, vStart);
addQuad(indices, iCount, vCount, vStart, NULL, NULL);
Vertex *quad = &vertices[vCount];
quad[0].coord = quad[1].coord = quad[2].coord = quad[3].coord = { x, y, z };
quad[0].coord = quad[1].coord = quad[2].coord = quad[3].coord = { x, y, z, 0 };
quad[0].normal = quad[1].normal = quad[2].normal = quad[3].normal = { 0, 0, 0, 0 };
int tx = (sprite.tile % 4) * 256;
int ty = (sprite.tile / 4) * 256;
@ -422,15 +518,10 @@ struct MeshBuilder {
int16 u1 = u0 + (sprite.w >> 3);
int16 v1 = v0 + (sprite.h >> 3);
quad[0].texCoord = { u0, v0 };
quad[1].texCoord = { u1, v0 };
quad[2].texCoord = { u1, v1 };
quad[3].texCoord = { u0, v1 };
quad[0].normal = { sprite.r, sprite.t, 0, 0 };
quad[1].normal = { sprite.l, sprite.t, 0, 0 };
quad[2].normal = { sprite.l, sprite.b, 0, 0 };
quad[3].normal = { sprite.r, sprite.b, 0, 0 };
quad[0].texCoord = { u0, v0, sprite.r, sprite.t };
quad[1].texCoord = { u1, v0, sprite.l, sprite.t };
quad[2].texCoord = { u1, v1, sprite.l, sprite.b };
quad[3].texCoord = { u0, v1, sprite.r, sprite.b };
quad[0].color = quad[1].color = quad[2].color = quad[3].color = { intensity, intensity, intensity, 255 };

View File

@ -10,26 +10,29 @@ varying vec4 vColor;
#ifdef VERTEX
uniform mat4 uViewProj;
uniform mat4 uModel;
uniform vec4 uColor;
#ifndef SPRITE
uniform vec3 uViewPos;
uniform vec3 uViewPos;
uniform vec3 uLightPos;
uniform vec2 uAnimTexRanges[MAX_RANGES];
uniform vec2 uAnimTexOffsets[MAX_OFFSETS];
#else
uniform mat4 uViewInv;
uniform mat4 uViewInv;
#endif
#ifdef CAUSTICS
uniform vec4 uParam;
#endif
uniform vec4 uParam; // x - time
attribute vec3 aCoord;
attribute vec2 aTexCoord;
attribute vec4 aCoord;
attribute vec4 aTexCoord;
attribute vec4 aNormal;
attribute vec4 aColor;
#define TEXCOORD_SCALE (1.0 / 32767.0)
void main() {
vec4 coord = uModel * vec4(aCoord, 1.0);
vTexCoord = aTexCoord;
vColor = aColor;
vec4 coord = uModel * vec4(aCoord.xyz, 1.0);
vColor = aColor * uColor;
#ifdef CAUSTICS
float sum = coord.x + coord.y + coord.z;
@ -37,17 +40,25 @@ varying vec4 vColor;
#endif
#ifndef SPRITE
// animated texture coordinates
vec2 range = uAnimTexRanges[int(aTexCoord.z)]; // x - start index, y - count
float f = fract((aTexCoord.w + uParam.x * 4.0 - range.x) / range.y) * range.y;
vec2 offset = uAnimTexOffsets[int(range.x + f)]; // texCoord offset from first frame
vTexCoord = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated
vViewVec = uViewPos - coord.xyz;
vLightVec = uLightPos - coord.xyz;
vNormal = uModel * aNormal;
#else
coord.xyz -= uViewInv[0].xyz * aNormal.x + uViewInv[1].xyz * aNormal.y;
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
coord.xyz -= uViewInv[0].xyz * aTexCoord.z + uViewInv[1].xyz * aTexCoord.w;
#endif
gl_Position = uViewProj * coord;
}
#else
uniform sampler2D sDiffuse;
uniform vec4 uColor;
#ifndef SPRITE
uniform vec3 uAmbient;
@ -56,10 +67,10 @@ varying vec4 vColor;
void main() {
vec4 color = texture2D(sDiffuse, vTexCoord);
if (color.w < 0.9)
if (color.w < 0.6)
discard;
color *= vColor;
color *= uColor;
#ifndef SPRITE
color.xyz = pow(abs(color.xyz), vec3(2.2));
float lum = dot(normalize(vNormal.xyz), normalize(vLightVec));

View File

@ -5,11 +5,11 @@
enum AttribType { aCoord, aTexCoord, aNormal, aColor, aMAX };
enum SamplerType { sDiffuse, sMAX };
enum UniformType { uViewProj, uViewInv, uModel, uColor, uAmbient, uViewPos, uLightPos, uLightColor, uParam, uMAX };
enum UniformType { uViewProj, uViewInv, uModel, uParam, uColor, uAmbient, uViewPos, uLightPos, uLightColor, uAnimTexRanges, uAnimTexOffsets, uMAX };
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal", "aColor" };
const char *SamplerName[sMAX] = { "sDiffuse" };
const char *UniformName[uMAX] = { "uViewProj", "uViewInv", "uModel", "uColor", "uAmbient", "uViewPos", "uLightPos", "uLightColor", "uParam" };
const char *UniformName[uMAX] = { "uViewProj", "uViewInv", "uModel", "uParam", "uColor", "uAmbient", "uViewPos", "uLightPos", "uLightColor", "uAnimTexRanges", "uAnimTexOffsets" };
struct Shader {
GLuint ID;
@ -68,6 +68,11 @@ struct Shader {
Core::active.shader = this;
}
void setParam(UniformType uType, const vec2 &value, int count = 1) {
if (uID[uType] != -1)
glUniform2fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const vec3 &value, int count = 1) {
if (uID[uType] != -1)
glUniform3fv(uID[uType], count, (GLfloat*)&value);

View File

@ -19,8 +19,8 @@
#else
#define ASSERT(expr)
#define LOG(...) ((void)0)
// #define LOG(...) printf(__VA_ARGS__)
// #define LOG(...) ((void)0)
#define LOG(...) printf(__VA_ARGS__)
#endif