1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 23:54:09 +02:00

WebGL platform

This commit is contained in:
XProger
2016-08-30 02:32:41 +03:00
16 changed files with 2640 additions and 2658 deletions

View File

@@ -39,7 +39,9 @@ struct Controller {
void update() {
float rot = 0.0f;
enum { LEFT = 1, RIGHT = 2, FORTH = 4, BACK = 8, JUMP = 16, WALK = 32, ACTION = 64, WEAPON = 128, ROLL = 256, GROUND = 512, WATER = 1024, DEATH = 2048,
enum { LEFT = 1, RIGHT = 2, FORTH = 4, BACK = 8,
JUMP = 16, WALK = 32, ACTION = 64, WEAPON = 128, ROLL = 256,
GROUND = 512, WATER = 1024, DEATH = 2048,
PULL = 4096, PICKUP = 8192, SWITCH_ON = 16 * 1024, SWITCH_OFF = 32 * 1024, KEY = 64 * 1024, PUZZLE = 128 * 1024, HANG = 256 * 1024, FALL = 512 * 1024, COMPRESS = 1024 * 1024};
int mask = 0;
@@ -56,12 +58,10 @@ struct Controller {
if (velocity.y > 2048) mask |= FALL;
if (anim->state == TR::STATE_COMPRESS) mask |= COMPRESS;
int origMask = mask;
if (origMask & (FORTH | BACK))
mask &= ~(LEFT | RIGHT);
int stateMask[TR::STATE_MAX];
for (int i = 0; i < TR::STATE_MAX; i++)
stateMask[i] = -1;
@@ -209,7 +209,7 @@ struct Controller {
int16 sx = *ptr++;
int16 sy = *ptr++;
int16 sz = *ptr++;
LOG("move: %d %d\n", (int)sx, (int)sy, (int)sz);
LOG("move: %d %d %d\n", (int)sx, (int)sy, (int)sz);
break;
}
case 0x02 : { // cmd jump speed
@@ -273,7 +273,6 @@ struct Controller {
fCount = anim->frameEnd - anim->frameStart + 1;
}
move(velocity * dt);
collide();
@@ -333,6 +332,8 @@ struct Controller {
for (int i = 0; i < level->modelsCount; i++)
if (entity.id == level->models[i].id)
return level->models[i];
ASSERT(false);
return level->models[0];
}
TR::Room& getRoom() {
@@ -358,13 +359,10 @@ struct Controller {
TR::Room::Sector &s = getSector(dx, dz);
TR::Entity &entity = getEntity();
float bottom = s.floor * 256;
float bottom = (int)s.floor * 256;
float fx = dx / 1024.0f, fz = dz / 1024.0f;
// dx -= 512;
// dz -= 512;
uint16 cmd, *d = &level->floors[s.floorIndex];
if (s.floorIndex)
@@ -416,7 +414,6 @@ struct Controller {
}
case 4 : {
/*
//*d++; // trigger setup
if (sub == 0x00) LOG("trigger\n");
if (sub == 0x01) LOG("pad\n");
if (sub == 0x02) LOG("switch\n");

View File

@@ -136,7 +136,7 @@ namespace Core {
break;
}
if (mode != bmNone)
if (mode != cfNone)
glEnable(GL_CULL_FACE);
}

View File

@@ -183,33 +183,39 @@ namespace TR {
uint32 size; // Number of data words (uint16_t's)
int16 vCount;
int16 rCount;
int16 tCount;
int16 sCount;
struct Vertex {
TR::Vertex vertex;
int16 lighting; // 0 (bright) .. 0x1FFF (dark)
} *vertices;
int16 rCount;
Rectangle *rectangles;
int16 tCount;
Triangle *triangles;
int16 sCount;
struct Sprite {
int16 vertex;
int16 texture;
} *sprites;
} data;
int16 portalsCount;
uint16 portalsCount;
uint16 zSectors;
uint16 xSectors;
uint16 ambient; // 0 (bright) .. 0x1FFF (dark)
uint16 lightsCount;
uint16 meshesCount;
int16 alternateRoom;
int16 flags;
struct Portal {
uint16 roomIndex;
Vertex normal;
Vertex vertices[4];
} *portals;
uint16 zSectors;
uint16 xSectors;
struct Sector {
uint16 floorIndex; // Index into FloorData[]
uint16 boxIndex; // Index into Boxes[] (-1 if none)
@@ -219,25 +225,20 @@ namespace TR {
int8 ceiling; // Absolute height of ceiling * 256
} *sectors;
int16 ambient; // 0 (bright) .. 0x1FFF (dark)
int16 lightsCount;
struct Light {
int32 x, y, z; // Position of light, in world coordinates
uint16 Intensity; // Light intensity
uint32 fade; // Falloff value
int32 x, y, z;
uint16 align; // ! not exists in file !
uint16 intensity;
uint32 attenuation;
} *lights;
uint16 meshesCount;
struct Mesh {
int32 x, y, z;
uint16 rotation; // (rotation >> 14) * 90
uint16 intensity; // 0 (bright) .. 0x1FFF (dark)
uint16 rotation;
uint16 intensity;
uint16 meshID;
uint16 align; // ! not exists in file !
} *meshes;
int16 alternateRoom;
int16 flags;
};
struct Mesh {
@@ -275,6 +276,7 @@ namespace TR {
uint16 flags; // 0x0100 indicates "initially invisible", 0x3e00 is Activation Mask
// 0x3e00 indicates "open" or "activated"; these can be XORed with
// related FloorData::FDlist fields (e.g. for switches)
uint16 align; // ! not exists in file !
};
struct Animation {
@@ -337,6 +339,7 @@ namespace TR {
uint32 node; // offset into MeshTree[]
uint32 frame; // byte offset into Frames[] (divide by 2 for Frames[i])
uint16 animation; // offset into Animations[]
uint16 align; // ! not exists in file !
};
struct StaticMesh {
@@ -415,6 +418,7 @@ namespace TR {
uint16 chance; // If !=0 and ((rand()&0x7fff) > Chance), this sound is not played
uint16 flags; // Bits 0-1: Looped flag, bits 2-5: num samples, bits 6-7: UNUSED
};
#pragma pack(pop)
struct Level {
char *data;
@@ -538,12 +542,26 @@ namespace TR {
// ambient light luminance
stream.read(r.ambient);
// lights
stream.read(r.lights, stream.read(r.lightsCount));
r.lights = new Room::Light[stream.read(r.lightsCount)];
for (int i = 0; i < r.lightsCount; i++) {
TR::Room::Light &light = r.lights[i];
stream.read(light.x);
stream.read(light.y);
stream.read(light.z);
stream.read(light.intensity);
stream.read(light.attenuation);
}
// stream.read(r.lights, stream.read(r.lightsCount));
// meshes
stream.read(r.meshes, stream.read(r.meshesCount));
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);
}
// floors
stream.read(floors, stream.read(floorsCount));
// meshes
@@ -557,7 +575,10 @@ namespace TR {
stream.read(nodesData, stream.read(nodesDataSize));
stream.read(frameData, stream.read(frameDataSize));
// models
stream.read(models, stream.read(modelsCount));
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));
@@ -579,12 +600,17 @@ namespace TR {
// animated textures
stream.read(animTexturesData, stream.read(animTexturesDataSize));
// entities (enemies, items, lara etc.)
stream.read(entities, stream.read(entitiesCount));
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
#ifndef TR1_DEMO
stream.read(palette, 256);
#endif
// cinematic frames for cameras
stream.read(cameraFrames, stream.read(cameraFramesCount));
// demo data
@@ -650,7 +676,6 @@ namespace TR {
delete[] soundOffsets;
}
};
#pragma pack(pop)
}
#endif

View File

@@ -12,7 +12,8 @@ namespace Game {
void init() {
Core::init();
level = new Level("data\\LEVEL2_DEMO.PHD");
Stream stream("LEVEL2_DEMO.PHD");
level = new Level(stream);
}
void free() {

View File

@@ -37,8 +37,9 @@ struct Level {
int32 radius;
} *meshInfo;
Level(const char *name) : level(Stream(name)), time(0.0f) {
Level(Stream &stream) : level{stream}, time(0.0f) {
shader = new Shader(SHADER);
initAtlas();
initMesh();
@@ -120,6 +121,7 @@ struct Level {
vCount += d.rCount * 4 + d.tCount * 3;
rangeRooms[i].iCount = iCount - rangeRooms[i].iStart;
}
// get objects mesh info
#define OFFSET(bytes) (ptr = (TR::Mesh*)((char*)ptr + (bytes) - sizeof(char*)))
@@ -149,8 +151,9 @@ struct Level {
iCount += ptr->ctCount * 3;
vCount += ptr->ctCount * 3;
OFFSET(ptr->ctCount * sizeof(TR::Triangle) + sizeof(TR::Mesh));
ptr = (TR::Mesh*)(((int)ptr + 3) & ~3);
ptr = (TR::Mesh*)(((int)ptr + 3) & -4);
}
meshInfo = new MeshInfo[mCount];
Index *indices = new Index[iCount];
@@ -190,7 +193,8 @@ struct Level {
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, 0x7FFF };
vertices[vCount].texCoord = { (int16)((tx + (int)t.vertices[k].Xpixel) << 5) + 16, (int16)((ty + (int)t.vertices[k].Ypixel) << 5) + 16};
vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16;
vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16;
vCount++;
}
}
@@ -218,7 +222,8 @@ struct Level {
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, 0x7FFF };
vertices[vCount].texCoord = { (int16)((tx + (int)t.vertices[k].Xpixel) << 5) + 16, (int16)((ty + (int)t.vertices[k].Ypixel) << 5) + 16};
vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16;
vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16;
vCount++;
}
}
@@ -233,7 +238,7 @@ struct Level {
info.vStart = vCount;
info.iStart = iCount;
info.center = ptr->center;
info.radius = ptr->radius;
// info.radius = ptr->radius;
TR::Vertex *mVertices = (TR::Vertex*)&ptr->vertices;
@@ -287,7 +292,8 @@ struct Level {
vertices[vCount].normal = { 0, 0, 0, 255 };
vertices[vCount].color = { a, a, a, 255 };
}
vertices[vCount].texCoord = { (int16)((tx + (int)t.vertices[k].Xpixel) << 5) + 16, (int16)((ty + (int)t.vertices[k].Ypixel) << 5) + 16};
vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16;
vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16;
vCount++;
}
}
@@ -323,7 +329,8 @@ struct Level {
vertices[vCount].normal = { 0, 0, 0, 255 };
vertices[vCount].color = { a, a, a, 255 };
}
vertices[vCount].texCoord = { ((tx + t.vertices[k].Xpixel) << 5) + 16, ((ty + t.vertices[k].Ypixel) << 5) + 16 };
vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16;
vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16;
vCount++;
}
}
@@ -399,7 +406,7 @@ struct Level {
}
OFFSET(ptr->ctCount * sizeof(TR::Triangle) + sizeof(TR::Mesh));
ptr = (TR::Mesh*)(((int)ptr + 3) & ~3);
ptr = (TR::Mesh*)(((int)ptr + 3) & -4);
info.iCount = iCount - info.iStart;
}
@@ -435,16 +442,14 @@ struct Level {
mesh->render(rangeRooms[index]);
Core::mModel = m;
// meshes
for (int j = 0; j < room.meshesCount; j++) {
auto rMesh = room.meshes[j];
auto sMesh = getMeshByID(rMesh.meshID);
TR::Room::Mesh &rMesh = room.meshes[j];
TR::StaticMesh *sMesh = getMeshByID(rMesh.meshID);
ASSERT(sMesh != NULL);
mat4 m = Core::mModel;
Core::mModel.translate(vec3(rMesh.x, rMesh.y, rMesh.z));
// Core::mModel.rotateY((rMesh.rotation >> 14) * 90.0f * DEG2RAD);
Core::mModel.rotateY(rMesh.rotation / 16384.0f * PI * 0.5f);
getLight(vec3(rMesh.x, rMesh.y, rMesh.z), index);
@@ -453,6 +458,7 @@ struct Level {
Core::mModel = m;
}
/*
// sprites
Core::setBlending(bmAlpha);
@@ -510,7 +516,6 @@ struct Level {
float a = 1.0f - v.lighting / (float)0x1FFF;
/*
glColor3f(a, a, a);
glPushMatrix();
glTranslatef(v.vertex.x + room.info.x, v.vertex.y, v.vertex.z + room.info.z);
@@ -647,27 +652,28 @@ struct Level {
int getLightIndex(const vec3 &pos, int &room) {
int idx = -1;
float dist;
for (int j = 0; j < level.roomsCount; j++)
// for (int j = 0; j < level.roomsCount; j++)
int j = room;
for (int i = 0; i < level.rooms[j].lightsCount; i++) {
TR::Room::Light &light = level.rooms[j].lights[i];
float d = (pos - vec3(light.x, light.y, light.z)).length();
float d = (pos - vec3(light.x, light.y, light.z)).length2();
if (idx == -1 || d < dist) {
idx = i;
dist = d;
room = j;
// room = j;
}
}
return idx;
}
void getLight(const vec3 &pos, int roomIndex) {
int room;
int room = roomIndex;
int idx = getLightIndex(pos, room);
if (idx > -1) {
TR::Room::Light &light = level.rooms[room].lights[idx];
float c = level.rooms[room].lights[idx].Intensity / 8191.0f;
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.fade * light.fade);
Core::lightColor = vec4(c, c, c, light.attenuation * light.attenuation);
} else {
Core::lightPos = vec3(0.0f);
Core::lightColor = vec4(0.0f);
@@ -907,64 +913,7 @@ struct Level {
glEnd();
}
#endif
/*
void debugEntity() {
Core::setCulling(cfNone);
Core::active.shader = NULL;
glUseProgram(0);
mat4 mProj;
glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat*)&mProj);
glPushMatrix();
glScalef(-SCALE, -SCALE, SCALE);
for (int i = 0; i < entities.count; i++) {
tr_entity *entity = &entities[i];
glPushMatrix();
glTranslatef(entity->x, entity->y, entity->z);
for (int i = 0; i < models.count; i++)
if (entity->id == models[i].id) {
glRotatef((entity->rotation >> 14) * 90.0f, 0, 1, 0);
tr_anim_frame *frame = (tr_anim_frame*)&frames[models[i].frame >> 1];
glTranslatef(frame->x, frame->y, frame->z);
break;
}
mat4 mView, mViewProj;
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&mView);
mViewProj = mProj * mView;
vec4 p = mViewProj * vec4(0, 0, 0, 1);
if (p.w > 0) {
p.xyz /= p.w;
p.y = -p.y;
p.xy = (p.xy * 0.5f + 0.5f) * vec2(Core::width, Core::height);
char buf[16];
sprintf(buf, "%d", entity->id);
UI::begin();
font->print(p.xy, vec4(1, 0, 0, 1), buf);
UI::end();
}
glPopMatrix();
}
glPopMatrix();
Core::setCulling(cfFront);
Core::active.shader = NULL;
glUseProgram(0);
}
bool isInsideRoom(const vec3 pos, tr_room *room) {
vec3 min = vec3(room->info.x, room->info.yTop, room->info.z);
Box box(min, min + vec3(room->xSectors * 1024, room->info.yBottom - room->info.yTop, room->zSectors * 1024));
return box.intersect(vec3(-pos.x, -pos.y, pos.z) / SCALE);
}
*/
float tickTextureAnimation = 0.0f;
void update() {
@@ -972,6 +921,7 @@ struct Level {
lara->update();
camera.update();
/*
if (tickTextureAnimation > 0.25f) {
tickTextureAnimation = 0.0f;
@@ -989,6 +939,7 @@ struct Level {
}
} else
tickTextureAnimation += Core::deltaTime;
*/
}
void render() {
@@ -1004,9 +955,10 @@ struct Level {
shader->setParam(uViewProj, Core::mViewProj);
shader->setParam(uModel, Core::mModel);
Core::setCulling(cfFront);
glEnable(GL_DEPTH_TEST);
Core::setCulling(cfFront);
Core::mModel.identity();
for (int i = 0; i < level.roomsCount; i++)
@@ -1022,7 +974,6 @@ struct Level {
debugRooms();
// debugLights();
debugPortals();
// debugEntity();
Debug::Draw::end();
#endif
}

View File

@@ -34,12 +34,12 @@ varying vec4 vColor;
discard;
color *= vColor * uColor;
// #ifdef LIGHTING
color.xyz = pow(color.xyz, vec3(2.2));
color.xyz = pow(abs(color.xyz), vec3(2.2));
float lum = dot(normalize(vNormal.xyz), normalize(vLightVec));
float att = max(0.0, 1.0 - dot(vLightVec, vLightVec) / uLightColor.w);
vec3 light = uLightColor.xyz * max(vNormal.w, lum * att) + uAmbient;
color.xyz *= light;
color.xyz = pow(color.xyz, vec3(1.0/2.2));
color.xyz = pow(abs(color.xyz), vec3(1.0/2.2));
// #endif
gl_FragColor = color;
}

View File

@@ -16,7 +16,11 @@ struct Shader {
GLint uID[uMAX];
Shader(const char *text) {
#define GLSL_DEFINE "#version 110\n"
#ifdef MOBILE
#define GLSL_DEFINE "precision highp float;\n" "#define MOBILE\n"
#else
#define GLSL_DEFINE "#version 120\n"
#endif
const int type[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
const char *code[2][2] = {

View File

@@ -445,6 +445,7 @@ struct Stream {
Stream(const char *name) : pos(0) {
f = fopen(name, "rb");
if (!f) LOG("error loading file\n");
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);

View File

@@ -1,2 +1,2 @@
set SRC=main.cpp
em++ %SRC% -O2 --llvm-opts 2 --closure 1 -std=c++11 -o OpenLara.js --preload-file ./../../bin/data/LEVEL2_DEMO.PHD -I..\
em++ %SRC% -O2 --llvm-opts 2 --closure 1 -std=c++11 -o OpenLara.js --preload-file ./LEVEL2_DEMO.PHD -I..\

View File

@@ -27,6 +27,9 @@ void main_loop() {
FPS = 0;
}
int f;
emscripten_get_canvas_size(&Core::width, &Core::height, &f);
Game::update();
Game::render();
eglSwapBuffers(display, surface);