From d52b478e31abd13a3d20beb2f3c4296dbfbb254f Mon Sep 17 00:00:00 2001 From: XProger Date: Fri, 30 Dec 2016 02:29:11 +0300 Subject: [PATCH] #8 playing cutscenes, #23 hide shadow from back of walls --- src/camera.h | 65 +++++++++++++++++++++++++++++------------------- src/controller.h | 16 ++++++++---- src/format.h | 33 +++++++++++++++++++++--- src/lara.h | 8 ++++-- src/level.h | 16 ++++++------ src/shader.glsl | 32 ++++++++++++++++++++++-- src/utils.h | 6 +++++ 7 files changed, 130 insertions(+), 46 deletions(-) diff --git a/src/camera.h b/src/camera.h index 3ee1a1f..e013b99 100644 --- a/src/camera.h +++ b/src/camera.h @@ -61,7 +61,7 @@ struct Camera : Controller { virtual void update() { #ifndef LEVEL_EDITOR if (cutscene) { // cutscene - + /* vec3 orig = owner->pos; float rotY = 0.0f; @@ -83,14 +83,29 @@ struct Camera : Controller { rotY = PI * 0.5f; break; } - + */ timer += Core::deltaTime * 30; + float t = timer - int(timer); int indexA = int(timer) % level->cameraFramesCount; - TR::CameraFrame *frame = &level->cameraFrames[indexA]; + int indexB = min(indexA + 1, level->cameraFramesCount - 1); + TR::CameraFrame *frameA = &level->cameraFrames[indexA]; + TR::CameraFrame *frameB = &level->cameraFrames[indexB]; + + const int eps = 128; + + if (abs(frameA->pos.x - frameB->pos.x) > eps || abs(frameA->pos.y - frameB->pos.y) > eps || abs(frameA->pos.z - frameB->pos.z) > eps) { + pos = frameA->pos; + target = frameA->target; + fov = frameA->fov / 32767.0f * 120.0f; + } else { + pos = vec3(frameA->pos).lerp(frameB->pos, t); + target = vec3(frameA->target).lerp(frameB->target, t); + fov = lerp(frameA->fov / 32767.0f * 120.0f, frameB->fov / 32767.0f * 120.0f, t); + } + + pos = level->cutMatrix * pos; + target = level->cutMatrix * target; - pos = orig + vec3(frame->pos).rotateY(-rotY); - target = orig + vec3(frame->target).rotateY(-rotY); - //fov = float(frame->fov) / 32767.0f * 120.0f; // TODO: frame->roll } else #endif @@ -181,29 +196,29 @@ struct Camera : Controller { room = destRoom; } pos = pos.lerp(destPos, Core::deltaTime * lerpFactor); - } - if (actCamera <= -1) { - TR::Level::FloorInfo info; - level->getFloorInfo(room, (int)pos.x, (int)pos.y, (int)pos.z, info); + if (actCamera <= -1) { + TR::Level::FloorInfo info; + level->getFloorInfo(room, (int)pos.x, (int)pos.y, (int)pos.z, info); - if (info.roomNext != 255) - room = info.roomNext; + if (info.roomNext != 255) + room = info.roomNext; - if (pos.y < info.roomCeiling) { - if (info.roomAbove != 255) - room = info.roomAbove; - else - if (info.roomCeiling != 0xffff8100) - pos.y = (float)info.roomCeiling; - } + if (pos.y < info.roomCeiling) { + if (info.roomAbove != 255) + room = info.roomAbove; + else + if (info.roomCeiling != 0xffff8100) + pos.y = (float)info.roomCeiling; + } - if (pos.y > info.roomFloor) { - if (info.roomBelow != 255) - room = info.roomBelow; - else - if (info.roomFloor != 0xffff8100) - pos.y = (float)info.roomFloor; + if (pos.y > info.roomFloor) { + if (info.roomBelow != 255) + room = info.roomBelow; + else + if (info.roomFloor != 0xffff8100) + pos.y = (float)info.roomFloor; + } } } diff --git a/src/controller.h b/src/controller.h index fabbc84..4969cb1 100644 --- a/src/controller.h +++ b/src/controller.h @@ -426,11 +426,17 @@ struct Controller { */ mat4 getMatrix() { mat4 matrix; - matrix.identity(); - matrix.translate(pos); - if (angle.y != 0.0f) matrix.rotateY(angle.y - (animation.flip ? PI * animation.delta : 0.0f)); - if (angle.x != 0.0f) matrix.rotateX(angle.x); - if (angle.z != 0.0f) matrix.rotateZ(angle.z); + + TR::Entity &e = getEntity(); + if (e.type < TR::Entity::CUT_1 || e.type > TR::Entity::CUT_3) { // TODO: move to ctor + matrix.identity(); + matrix.translate(pos); + if (angle.y != 0.0f) matrix.rotateY(angle.y - (animation.flip ? PI * animation.delta : 0.0f)); + if (angle.x != 0.0f) matrix.rotateX(angle.x); + if (angle.z != 0.0f) matrix.rotateZ(angle.z); + } else + matrix = level->cutMatrix; + return matrix; } diff --git a/src/format.h b/src/format.h index 909342d..cdaea19 100644 --- a/src/format.h +++ b/src/format.h @@ -412,7 +412,9 @@ namespace TR { GEARS_2 = 75, GEARS_3 = 76, - LARA_CUT = 77, + CUT_1 = 77, + CUT_2 = 78, + CUT_3 = 79, CRYSTAL = 83, // sprite WEAPON_PISTOLS = 84, // sprite @@ -813,13 +815,16 @@ namespace TR { bool secrets[MAX_SECRETS_COUNT]; void *cameraController; + int cutEntity; + mat4 cutMatrix; + struct { int16 muzzleFlash; int16 puzzleSet; int16 weapons[4]; } extra; - Level(Stream &stream, bool demo) { + Level(Stream &stream, bool demo) : cutEntity(-1) { tiles4 = NULL; Tile8 *tiles8 = NULL; cluts = NULL; @@ -975,6 +980,8 @@ namespace TR { e.align = 0; e.controller = NULL; e.modelIndex = getModelIndex(e.type); + if (e.type == Entity::CUT_1) + cutEntity = i; } for (int i = entitiesBaseCount; i < entitiesCount; i++) { entities[i].type = Entity::NONE; @@ -1026,6 +1033,26 @@ namespace TR { case Entity::LARA_UZIS : extra.weapons[3] = i; break; default : ; } + // init cutscene transform + cutMatrix.identity(); + if (cutEntity > -1) { + Entity &e = entities[cutEntity]; + switch (cameraFramesCount) { // HACK to detect cutscene level number + case 1600 : // CUT1 + cutMatrix.translate(vec3(36668, float(e.y), 63180)); + cutMatrix.rotateY(-23312.0f / float(0x4000) * PI * 0.5f); + break; + case 1000 : // CUT2 + cutMatrix.translate(vec3(51962, float(e.y), 53760)); + cutMatrix.rotateY(16380.0f / float(0x4000) * PI * 0.5f); + break; + case 400 : // CUT3 + case 1890 : // CUT4 + cutMatrix.translate(vec3(float(e.x), float(e.y), float(e.z))); + cutMatrix.rotateY(PI * 0.5f); + break; + } + } } ~Level() { @@ -1669,7 +1696,7 @@ namespace TR { }; // struct Level bool castShadow(Entity::Type type) { - return (type >= Entity::ENEMY_TWIN && type <= Entity::ENEMY_LARSON) || type == Entity::LARA || type == Entity::LARA_CUT; + return (type >= Entity::ENEMY_TWIN && type <= Entity::ENEMY_LARSON) || type == Entity::LARA || (type >= Entity::CUT_1 && type <= Entity::CUT_3); } } diff --git a/src/lara.h b/src/lara.h index cd4cd46..cdc8069 100644 --- a/src/lara.h +++ b/src/lara.h @@ -600,6 +600,8 @@ struct Lara : Character { } void updateWeapon() { + if (level->cutEntity > -1) return; + if (input & DEATH) { arms[0].shotTimer = arms[1].shotTimer = MUZZLE_FLASH_TIME + 1.0f; animation.overrideMask = 0; @@ -889,6 +891,7 @@ struct Lara : Character { virtual void cmdEffect(int fx) { switch (fx) { + case TR::EFFECT_FLIP_MAP : break; // TODO case TR::EFFECT_LARA_HANDSFREE : break;//meshSwap(1, level->extra.weapons[wpnCurrent], BODY_LEG_L1 | BODY_LEG_R1); break; case TR::EFFECT_DRAW_RIGHTGUN : case TR::EFFECT_DRAW_LEFTGUN : drawGun(fx == TR::EFFECT_DRAW_RIGHTGUN); break; @@ -1419,6 +1422,7 @@ struct Lara : Character { } virtual int getInput() { // TODO: updateInput + if (level->cutEntity > -1) return 0; input = Character::getInput(); if (input & DEATH) return input; @@ -1601,7 +1605,7 @@ struct Lara : Character { if (velocity.length() >= 0.001f) move(); - /* + if (getEntity().type != TR::Entity::LARA) { TR::Entity &e = getEntity(); vec3 &p = getPos(); @@ -1611,7 +1615,7 @@ struct Lara : Character { checkRoom(); updateEntity(); } - */ + } virtual vec3& getPos() { diff --git a/src/level.h b/src/level.h index 7245c5a..621c28e 100644 --- a/src/level.h +++ b/src/level.h @@ -161,9 +161,9 @@ struct Level { void getAmbient(int room, const vec3 &pos, Cube &value) { TR::Room &r = level->level.rooms[room]; - int sx = (int(pos.x) - r.info.x) / 1024; - int sz = (int(pos.z) - r.info.z) / 1024; - + int sx = clamp((int(pos.x) - r.info.x) / 1024, 0, r.xSectors - 1); + int sz = clamp((int(pos.z) - r.info.z) / 1024, 0, r.zSectors - 1); + int sector = sx * r.zSectors + sz; Cube *a = getAmbient(room, sector); if (a) { @@ -232,11 +232,9 @@ struct Level { TR::Entity &entity = level.entities[i]; switch (entity.type) { case TR::Entity::LARA : + case TR::Entity::CUT_1 : entity.controller = (lara = new Lara(&level, i, home)); break; - case TR::Entity::LARA_CUT : - entity.controller = (lara = new Lara(&level, i, false)); - break; case TR::Entity::ENEMY_WOLF : entity.controller = new Wolf(&level, i); break; @@ -789,7 +787,7 @@ struct Level { } bool setupLightCamera() { - vec3 pos = (lara->animation.getJoints(lara->getMatrix(), 0, false, NULL)).pos; + vec3 pos = lara->getPos(); // omni-spot light shadows int room = lara->getRoomIndex(); @@ -903,7 +901,7 @@ struct Level { // Debug::Level::sectors(level, lara->getRoomIndex(), (int)lara->pos.y); // Debug::Level::portals(level); // Debug::Level::meshes(level); - // Debug::Level::entities(level); + Debug::Level::entities(level); static int dbg_ambient = 0; dbg_ambient = int(time * 2) % 4; @@ -916,7 +914,7 @@ struct Level { glColor3f(1, 1, 1); for (int j = 0; j < 6; j++) { glPushMatrix(); - vec3 p = lara->getPos(); + vec3 p = lara->pos;//getPos(); glTranslatef(p.x, p.y - 1024, p.z); switch (j) { case 0 : glRotatef( 90, 0, 1, 0); break; diff --git a/src/shader.glsl b/src/shader.glsl index d40fb62..d50d32a 100644 --- a/src/shader.glsl +++ b/src/shader.glsl @@ -217,8 +217,26 @@ uniform int uType; sqr.y * mix(uAmbient[3], uAmbient[2], pos.y) + sqr.z * mix(uAmbient[5], uAmbient[4], pos.z); } - #endif + #endif +/* + float getLuminance(vec3 color) { + return dot(color.xyz, vec3(0.299, 0.587, 0.114)); + } + + vec3 getNormal() { + const vec2 size = vec2(2.0, 0.0); + const vec3 off = vec3(-1, 0, 1) / 1024.0; + + float s01 = getLuminance(texture2D(sDiffuse, vTexCoord + off.xy).xyz); + float s21 = getLuminance(texture2D(sDiffuse, vTexCoord + off.zy).xyz); + float s10 = getLuminance(texture2D(sDiffuse, vTexCoord + off.yx).xyz); + float s12 = getLuminance(texture2D(sDiffuse, vTexCoord + off.yz).xyz); + vec3 va = vec3(size.xy * 0.25, s21-s01); + vec3 vb = vec3(size.yx * 0.25, s12-s10); + return normalize(cross(va, vb)); + } +*/ void main() { vec4 color = texture2D(sDiffuse, vTexCoord); if (color.w < 0.6) @@ -242,9 +260,16 @@ uniform int uType; // calc point lights if (uType != TYPE_FLASH) { vec3 normal = normalize(vNormal.xyz); + + //vec3 n = getNormal();; + //vec3 b = normalize(cross(n, vec3(.0, -1.0, 0.0))); + //vec3 t = normalize(cross(b, n)); + //normal = normalize(normal.x * t + normal.y * b + normal.z * n); + vec3 viewVec = normalize(vViewVec); vec3 light = vec3(0.0); + for (int i = 1; i < MAX_LIGHTS; i++) // additional lights light += calcLight(normal, uLightPos[i], uLightColor[i]); @@ -254,7 +279,9 @@ uniform int uType; } if (uType == TYPE_ROOM) { - light += mix(min(uColor.w, vColor.w), vColor.w, getShadow(vLightProj)); + float rShadow = dot(normal, uLightPos[0].xyz - vCoord) > 0.0 ? getShadow(vLightProj) : 1.0; + //light += calcLight(normal, uLightPos[0], uLightColor[0]); + light += mix(min(uColor.w, vColor.w), vColor.w, rShadow); } if (uType == TYPE_ENTITY) { @@ -271,6 +298,7 @@ uniform int uType; } color.xyz *= light; +//color.xyz = normal * 0.5 + 0.5; } else { color.w = uColor.w; } diff --git a/src/utils.h b/src/utils.h index 85ca2a5..e17f0a3 100644 --- a/src/utils.h +++ b/src/utils.h @@ -70,6 +70,12 @@ inline void swap(T &a, T &b) { b = tmp; } +float lerp(float a, float b, float t) { + if (t <= 0.0f) return a; + if (t >= 1.0f) return b; + return a + (b - a) * t; +} + float clampAngle(float a) { return a < -PI ? a + PI2 : (a >= PI ? a - PI2 : a); }