diff --git a/src/camera.h b/src/camera.h index fda4f61..698d247 100644 --- a/src/camera.h +++ b/src/camera.h @@ -153,6 +153,29 @@ struct Camera : ICamera { timer = 0.0f; } + bool updateFirstPerson() { + if (!firstPerson || viewIndex != -1) + return false; + + Basis head = owner->animation.getJoints(owner->getMatrix(), 14, true); + Basis eye(quat(0.0f, 0.0f, 0.0f, 1.0f), vec3(0.0f, -40.0f, 10.0f)); + eye = head * eye; + mViewInv.identity(); + + //prevBasis = prevBasis.lerp(eye, 15.0f * Core::deltaTime); + + mViewInv.setRot(eye.rot); + mViewInv.setPos(eye.pos); + mViewInv.rotateY(advAngle.y); + mViewInv.rotateX(advAngle.x + PI); + + pos = mViewInv.getPos(); + checkRoom(); + updateListener(); + return true; + } + + virtual void update() { if (shake > 0.0f) shake = max(0.0f, shake - Core::deltaTime); @@ -173,6 +196,9 @@ struct Camera : ICamera { } } + if (updateFirstPerson()) + return; + TR::CameraFrame *frameA = &level->cameraFrames[indexA]; TR::CameraFrame *frameB = &level->cameraFrames[indexB]; @@ -242,24 +268,8 @@ struct Camera : ICamera { vec3 viewPoint = getViewPoint(); - if (firstPerson && viewIndex == -1) { - Basis head = owner->animation.getJoints(owner->getMatrix(), 14, true); - Basis eye(quat(0.0f, 0.0f, 0.0f, 1.0f), vec3(0.0f, -40.0f, 10.0f)); - eye = head * eye; - mViewInv.identity(); - - //prevBasis = prevBasis.lerp(eye, 15.0f * Core::deltaTime); - - mViewInv.setRot(eye.rot); - mViewInv.setPos(eye.pos); - mViewInv.rotateY(advAngle.y); - mViewInv.rotateX(advAngle.x + PI); - - pos = mViewInv.getPos(); - checkRoom(); - updateListener(); + if (updateFirstPerson()) return; - } float lerpFactor = lookAt ? 10.0f : 6.0f; vec3 dir; diff --git a/src/controller.h b/src/controller.h index a6ae3b0..e06805d 100644 --- a/src/controller.h +++ b/src/controller.h @@ -11,6 +11,7 @@ #define SPRITE_FPS 10.0f #define MAX_LAYERS 4 +#define MAX_SPHERES 32 #define UNLIMITED_AMMO 10000 @@ -371,6 +372,8 @@ struct Controller { void getSpheres(Sphere *spheres, int &count) { TR::Model *m = getModel(); + ASSERT(m->mCount <= MAX_SPHERES); + Basis basis(getMatrix()); // TODO: optimize (check frame index for animation updates, use joints array) count = 0; @@ -394,8 +397,8 @@ struct Controller { ASSERT(a->mCount <= 34); ASSERT(b->mCount <= 34); - Sphere aSpheres[34]; - Sphere bSpheres[34]; + Sphere aSpheres[MAX_SPHERES]; + Sphere bSpheres[MAX_SPHERES]; int aCount, bCount; getSpheres(aSpheres, aCount); diff --git a/src/core.h b/src/core.h index 03c2dd2..3489bfb 100644 --- a/src/core.h +++ b/src/core.h @@ -686,7 +686,7 @@ namespace Core { // init settings settings.detail.setFilter (Core::Settings::HIGH); settings.detail.setLighting (Core::Settings::HIGH); - settings.detail.setShadows (Core::Settings::MEDIUM); + settings.detail.setShadows (Core::Settings::HIGH); settings.detail.setWater (Core::Settings::HIGH); settings.audio.music = 0.7f; diff --git a/src/debug.h b/src/debug.h index 51a3cc3..2010a43 100644 --- a/src/debug.h +++ b/src/debug.h @@ -534,7 +534,7 @@ namespace Debug { Box box = controller->getBoundingBoxLocal(); Debug::Draw::box(matrix, box.min, box.max, bboxIntersect ? vec4(1, 0, 0, 1): vec4(1)); - Sphere spheres[34]; + Sphere spheres[MAX_SPHERES]; int count; controller->getSpheres(spheres, count); diff --git a/src/inventory.h b/src/inventory.h index 56cdb84..2dacea6 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -134,7 +134,7 @@ struct Inventory { TR::Level *level = game->getLevel(); TR::Model &m = level->models[desc.model]; - Basis joints[34]; + Basis joints[MAX_SPHERES]; anim->getJoints(basis, -1, true, joints); diff --git a/src/lara.h b/src/lara.h index 764e02b..1f00606 100644 --- a/src/lara.h +++ b/src/lara.h @@ -167,8 +167,8 @@ struct Lara : Character { STATE_SURF_BACK, STATE_SURF_LEFT, STATE_SURF_RIGHT, - STATE_USE_MIDAS, - STATE_DIE_MIDAS, + STATE_MIDAS_USE, + STATE_MIDAS_DEATH, STATE_SWAN_DIVE, STATE_FAST_DIVE, STATE_HANDSTAND, @@ -513,6 +513,8 @@ struct Lara : Character { } void reset(int room, const vec3 &pos, float angle, Stand forceStand = STAND_GROUND) { + visibleMask = 0xFFFFFFFF; + if (room == TR::NO_ROOM) { stand = STAND_AIR; room = getRoomByPos(pos); @@ -1262,7 +1264,7 @@ struct Lara : Character { if (box.intersect(m, from, v, t)) { v = v.normal(); - Sphere spheres[34]; + Sphere spheres[MAX_SPHERES]; int count; target->getSpheres(spheres, count); for (int i = 0; i < count; i++) @@ -1319,6 +1321,17 @@ struct Lara : Character { } } + void addSparks(uint32 mask) { + Sphere spheres[MAX_SPHERES]; + int count; + getSpheres(spheres, count); + for (int i = 0; i < count; i++) + if (mask & (1 << i)) { + vec3 sprPos = spheres[i].center + (vec3(randf(), randf(), randf()) * 2.0f - 1.0f) * spheres[i].radius; + Sprite::add(game, TR::Entity::SPARKLES, getRoomIndex(), int(sprPos.x), int(sprPos.y), int(sprPos.z), Sprite::FRAME_ANIMATED); + } + } + void addBlood(const vec3 &sprPos, const vec3 &sprVel) { int index = Sprite::add(game, TR::Entity::BLOOD, getRoomIndex(), int(sprPos.x), int(sprPos.y), int(sprPos.z), Sprite::FRAME_ANIMATED); if (index > -1) @@ -2337,7 +2350,7 @@ struct Lara : Character { virtual int getStateDeath() { velocity = vec3(0.0f); - return (stand == STAND_UNDERWATER || stand == STAND_ONWATER) ? STATE_UNDERWATER_DEATH : STATE_DEATH; + return (stand == STAND_UNDERWATER || stand == STAND_ONWATER) ? STATE_UNDERWATER_DEATH : (state == STATE_MIDAS_DEATH ? STATE_MIDAS_DEATH : STATE_DEATH); } virtual int getStateDefault() { @@ -2486,6 +2499,19 @@ struct Lara : Character { else if (specular > 0.0f) specular = max(0.0f, specular - LARA_WET_TIMER * Core::deltaTime); + + if (state == STATE_MIDAS_DEATH || state == STATE_MIDAS_USE) { + uint32 sparklesMask = getMidasMask(); + + if (state == STATE_MIDAS_DEATH) + visibleMask = sparklesMask ^ 0xFFFFFFFF; + + timer += Core::deltaTime; + if (timer >= 1.0f / 30.0f) { + timer -= 1.0f / 30.0f; + addSparks(sparklesMask); + } + } } virtual void updateVelocity() { @@ -2878,7 +2904,10 @@ struct Lara : Character { velocity = v * (sink.speed * 8.0f); } - uint32 getMidasDeathMask() { + uint32 getMidasMask() { + if (state == STATE_MIDAS_USE) + return BODY_ARM_L3 | BODY_ARM_R3; + uint32 mask = 0; int frame = animation.frameIndex; if (frame > 4 ) mask |= BODY_LEG_L3 | BODY_LEG_R3; @@ -2926,13 +2955,13 @@ struct Lara : Character { Core::setBlending(bmNone); } - if (state == STATE_DIE_MIDAS) { + if (state == STATE_MIDAS_DEATH) { game->setRoomParams(getRoomIndex(), Shader::MIRROR, 1.2f, 1.0f, 0.2f, 1.0f, false); environment->bind(sEnvironment); Core::setBlending(bmAlpha); - visibleMask = getMidasDeathMask(); + visibleMask ^= 0xFFFFFFFF; Controller::render(frustum, mesh, type, caustics); - visibleMask = 0xFFFFFFFF; + visibleMask ^= 0xFFFFFFFF; Core::setBlending(bmNone); } } diff --git a/src/level.h b/src/level.h index 46a383b..0a5c85b 100644 --- a/src/level.h +++ b/src/level.h @@ -885,7 +885,7 @@ struct Level : IGame { type = Shader::MIRROR; if (type == Shader::SPRITE) { - float alpha = (entity.type == TR::Entity::SMOKE || entity.type == TR::Entity::WATER_SPLASH) ? 0.75f : 1.0f; + float alpha = (entity.type == TR::Entity::SMOKE || entity.type == TR::Entity::WATER_SPLASH || entity.type == TR::Entity::SPARKLES) ? 0.75f : 1.0f; float diffuse = entity.isPickup() ? 1.0f : 0.5f; setRoomParams(roomIndex, type, diffuse, intensityf(lum), controller->specular, alpha, isModel ? !mesh->models[entity.modelIndex - 1].opaque : true); } else diff --git a/src/shaders/shader.glsl b/src/shaders/shader.glsl index 57b57f0..6c38483 100644 --- a/src/shaders/shader.glsl +++ b/src/shaders/shader.glsl @@ -448,11 +448,11 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha rSpecular *= rShadow; light += vAmbient + uLightColor[0].xyz * (vLight.x * rShadow); #endif - + #ifdef TYPE_ROOM light += mix(vAmbient.x, vLight.x, rShadow); #endif - + #ifdef TYPE_SPRITE light += vLight.x; #endif