mirror of
https://github.com/XProger/OpenLara.git
synced 2025-03-13 23:59:41 +01:00
#1 resolved
This commit is contained in:
parent
07e2b99ead
commit
460f3be4c5
BIN
bin/OpenLara.exe
BIN
bin/OpenLara.exe
Binary file not shown.
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
21
src/format.h
21
src/format.h
@ -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
|
||||
|
||||
|
52
src/level.h
52
src/level.h
@ -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);
|
||||
|
||||
|
227
src/mesh.h
227
src/mesh.h
@ -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 };
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user