From a6aafee45b3a2ab46cbefd79c38810c873b72eff Mon Sep 17 00:00:00 2001 From: XProger Date: Fri, 1 Sep 2017 08:02:08 +0300 Subject: [PATCH] #3 fix lookAt; #11 fix PCX loader for NPOT and async load; #15 async data loading for Web version --- src/camera.h | 3 ++- src/character.h | 2 +- src/inventory.h | 35 ++++++++++++++++++++++------------ src/level.h | 16 ++++++++++------ src/platform/web/build.bat | 2 +- src/platform/web/index.html | 2 -- src/platform/web/main.cpp | 29 ++++++++++++++++++++++++++++ src/sound.h | 1 - src/texture.h | 38 +++++++++++++++++++++++++++---------- src/utils.h | 28 +++++++++++++++++++++++---- 10 files changed, 118 insertions(+), 38 deletions(-) diff --git a/src/camera.h b/src/camera.h index 66c7cd8..378bc16 100644 --- a/src/camera.h +++ b/src/camera.h @@ -203,7 +203,8 @@ struct Camera : Controller { owner->lookAt(lookAt = owner->viewTarget); else owner->lookAt(lookAt = viewTarget); - } + } else + owner->lookAt(NULL); vec3 viewPoint = getViewPoint(); diff --git a/src/character.h b/src/character.h index c3e3cac..5a9e60d 100644 --- a/src/character.h +++ b/src/character.h @@ -45,7 +45,7 @@ struct Character : Controller { Collision collision; - Character(IGame *game, int entity, float health) : Controller(game, entity), health(health), tilt(0.0f), stand(STAND_GROUND), lastInput(0), viewTarget(NULL), jointChest(-1), jointHead(-1), velocity(0.0f), angleExt(0.0f) { + Character(IGame *game, int entity, float health) : Controller(game, entity), health(health), tilt(0.0f), stand(STAND_GROUND), lastInput(0), viewTarget(NULL), jointChest(-1), jointHead(-1), velocity(0.0f), angleExt(0.0f), speed(0.0f) { stepHeight = 256; dropHeight = -256; diff --git a/src/inventory.h b/src/inventory.h index c531813..9c4259e 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -131,6 +131,14 @@ struct Inventory { } *items[INVENTORY_MAX_ITEMS]; + static void loadTitleBG(Stream *stream, void *userData) { + if (!stream) return; + Inventory *inv = (Inventory*)userData; + + inv->background[0] = Texture::LoadPCX(*stream); + delete stream; + } + Inventory(IGame *game) : game(game), active(false), chosen(false), index(0), targetIndex(0), page(PAGE_OPTION), targetPage(PAGE_OPTION), itemsCount(0) { TR::LevelID id = game->getLevel()->id; @@ -163,7 +171,8 @@ struct Inventory { add(TR::Entity::INV_HOME); memset(background, 0, sizeof(background)); - background[0] = Texture::LoadPCX("data/TITLEH.PCX"); + + new Stream("data/TITLEH.PCX", loadTitleBG, this); } phaseRing = phasePage = phaseChoose = phaseSelect = 0.0f; @@ -596,19 +605,21 @@ struct Inventory { // background Core::setDepthTest(false); - background[0]->bind(sDiffuse); // orignal image - if (background[1]) { - game->setShader(Core::passFilter, Shader::FILTER_MIXER, false, false); - Core::active.shader->setParam(uParam, vec4(phaseRing, 1.0f - phaseRing * 0.4f, 0, 0));; - background[1]->bind(sNormal); // blured grayscale image - } else { - game->setShader(Core::passFilter, Shader::DEFAULT, false, false); + if (background[0]) { + background[0]->bind(sDiffuse); // orignal image + if (background[1]) { + game->setShader(Core::passFilter, Shader::FILTER_MIXER, false, false); + Core::active.shader->setParam(uParam, vec4(phaseRing, 1.0f - phaseRing * 0.4f, 0, 0));; + background[1]->bind(sNormal); // blured grayscale image + } else { + game->setShader(Core::passFilter, Shader::DEFAULT, false, false); - float aspect1 = float(background[0]->width) / float(background[0]->height); - float aspect2 = float(Core::width) / float(Core::height); - Core::active.shader->setParam(uParam, vec4(aspect2 / aspect1, -1.0f, 0, 0));; + float aspect1 = float(background[0]->width) / float(background[0]->height); + float aspect2 = float(Core::width) / float(Core::height); + Core::active.shader->setParam(uParam, vec4(aspect2 / aspect1, -1.0f, 0, 0)); + } + game->getMesh()->renderQuad(); } - game->getMesh()->renderQuad(); Core::setDepthTest(true); Core::setBlending(bmAlpha); diff --git a/src/level.h b/src/level.h index 43bc5b1..35fc449 100644 --- a/src/level.h +++ b/src/level.h @@ -191,10 +191,16 @@ struct Level : IGame { } } + static void playAsync(Stream *stream, void *userData) { + if (!stream) return; + Level *level = (Level*)userData; + + level->sndSoundtrack = Sound::play(stream, vec3(0.0f), 0.01f, 1.0f, 0); + if (level->sndSoundtrack) + level->sndSoundtrack->setVolume(1.0f, 0.2f); + } + virtual void playTrack(int track, bool restart = false) { - #ifndef WIN32 - return; - #endif if (track == 0) track = TR::LEVEL_INFO[level.id].ambientTrack; @@ -219,9 +225,7 @@ struct Level : IGame { char title[32]; sprintf(title, "audio/track_%02d.ogg", track); - sndSoundtrack = Sound::play(new Stream(title), vec3(0.0f), 0.01f, 1.0f, track == TR::LEVEL_INFO[level.id].ambientTrack ? Sound::Flags::LOOP : 0); - if (sndSoundtrack) - sndSoundtrack->setVolume(1.0f, 0.2f); + new Stream(title, playAsync, this); } virtual void stopTrack() { diff --git a/src/platform/web/build.bat b/src/platform/web/build.bat index 91ab70e..21ff77e 100644 --- a/src/platform/web/build.bat +++ b/src/platform/web/build.bat @@ -1,6 +1,6 @@ @echo off cls -set SRC=main.cpp +set SRC=main.cpp ../../libs/stb_vorbis/stb_vorbis.c set PROJ=OpenLara set FLAGS=-O3 -Wno-deprecated-register --llvm-opts 2 -fmax-type-align=2 -std=c++11 -Wall -I../../ set PRELOAD=./LEVEL2.PSX diff --git a/src/platform/web/index.html b/src/platform/web/index.html index 7d71cd7..fa9fafa 100644 --- a/src/platform/web/index.html +++ b/src/platform/web/index.html @@ -101,8 +101,6 @@ }; - - diff --git a/src/platform/web/main.cpp b/src/platform/web/main.cpp index a7fd40b..2a1d9ec 100644 --- a/src/platform/web/main.cpp +++ b/src/platform/web/main.cpp @@ -233,6 +233,35 @@ EM_BOOL mouseCallback(int eventType, const EmscriptenMouseEvent *e, void *userDa return 1; } +const char *IDB = "db"; + +void onError(void *str) { + LOG("! IDB error: %s\n", str); +} + +void onLoad(void *arg, void *data, int size) { + Stream *stream = (Stream*)arg; + stream->data = (char*)data; + stream->size = size; + stream->callback(stream, stream->userData); +} + +void onLoadAndStore(void *arg, void *data, int size) { + onLoad(arg, data, size); + emscripten_idb_async_store(IDB, ((Stream*)arg)->name, data, size, NULL, NULL, onError); +} + +void onExists(void *arg, int exists) { + if (exists) + emscripten_idb_async_load(IDB, ((Stream*)arg)->name, arg, onLoad, onError); + else + emscripten_async_wget_data(((Stream*)arg)->name, arg, onLoadAndStore, onError); +} + +void osDownload(Stream *stream) { + emscripten_idb_async_exists(IDB, stream->name, stream, onExists, onError); +} + char Stream::cacheDir[255]; char Stream::contentDir[255]; diff --git a/src/sound.h b/src/sound.h index 778a0a9..cc3e1f4 100644 --- a/src/sound.h +++ b/src/sound.h @@ -8,7 +8,6 @@ #ifdef __EMSCRIPTEN__ // TODO: http streaming #undef DECODE_MP3 - #undef DECODE_OGG #endif #include "utils.h" diff --git a/src/texture.h b/src/texture.h index fc70353..050c85d 100644 --- a/src/texture.h +++ b/src/texture.h @@ -126,9 +126,7 @@ struct Texture { } } - static Texture* LoadPCX(const char *fileName) { - Stream stream(fileName); - + static Texture* LoadPCX(Stream &stream) { struct Color24 { uint8 r, g, b; }; @@ -155,7 +153,10 @@ struct Texture { int i = 0; int size = pcx.width * pcx.height; - uint8 *buffer = new uint8[size + 256 * 3 + size * 4]; + int dw = Core::support.texNPOT ? pcx.width : nextPow2(pcx.width); + int dh = Core::support.texNPOT ? pcx.height : nextPow2(pcx.height); + + uint8 *buffer = new uint8[size + 256 * 3 + dw * dh * 4]; while (i < size) { uint8 n; @@ -177,15 +178,32 @@ struct Texture { stream.raw(palette, 256 * 3); Color32 *data = (Color32*)&palette[256]; - for (i = 0; i < size; i++) { + memset(data, 0, dw * dh * 4); + + Color32 *ptr = data; + /* + for (i = 0; i < pcx.height * pcx.width; i++) { Color24 &c = palette[buffer[i]]; - data[i].r = c.r; - data[i].g = c.g; - data[i].b = c.b; - data[i].a = 255; + ptr[i].r = c.r; + ptr[i].g = c.g; + ptr[i].b = c.b; + ptr[i].a = 255; + } + */ + + i = 0; + for (int y = 0; y < pcx.height; y++) { + for (int x = 0; x < pcx.width; x++) { + Color24 &c = palette[buffer[i++]]; + ptr[x].r = c.r; + ptr[x].g = c.g; + ptr[x].b = c.b; + ptr[x].a = 255; + } + ptr += dw; } - Texture *tex = new Texture(pcx.width, pcx.height, Texture::RGBA, false, data); + Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data); delete[] buffer; return tex; diff --git a/src/utils.h b/src/utils.h index ae2594a..009ba76 100644 --- a/src/utils.h +++ b/src/utils.h @@ -967,13 +967,18 @@ struct Stream { static char cacheDir[255]; static char contentDir[255]; + typedef void (Callback)(Stream *stream, void *userData); + Callback *callback; + void *userData; + FILE *f; - const char *data; + char *data; int size, pos; + char *name; - Stream(const void *data, int size) : f(NULL), data((char*)data), size(size), pos(0) {} + Stream(const void *data, int size) : callback(NULL), userData(NULL), f(NULL), data((char*)data), size(size), pos(0), name(NULL) {} - Stream(const char *name) : data(NULL), size(-1), pos(0) { + Stream(const char *name, Callback *callback = NULL, void *userData = NULL) : callback(callback), userData(userData), data(NULL), size(-1), pos(0), name(NULL) { if (contentDir[0]) { char path[255]; path[0] = 0; @@ -983,15 +988,30 @@ struct Stream { } else f = fopen(name, "rb"); - if (!f) LOG("error loading file \"%s\"\n", name); + if (!f) { + #ifdef __EMSCRIPTEN__ + this->name = new char[64]; + strcpy(this->name, name); + + extern void osDownload(Stream *stream); + osDownload(this); + return; + #else + LOG("error loading file \"%s\"\n", name); + #endif + } ASSERT(f != NULL); fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); + + if (callback) + callback(this, userData); } ~Stream() { + delete[] name; if (f) fclose(f); }