diff --git a/CHANGELOG.md b/CHANGELOG.md index be0471aad..d0beb91c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,6 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added muzzle glow effect for firearms. ### Bug fixes -* Fixed crashes when shooting, if gunflash or gunshell objects are not present in a level. -* Fixed crashes when Lara is on a vehicle unreachable by friendly NPCs. * Fixed Teleporter object. * Fixed Wraith objects not working correctly in flipped rooms. * Fixed lensflare enabled status not saved in a savegame. @@ -22,6 +20,9 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed caustics not rendered correctly if texture compression was enabled. * Fixed exclusion blend mode not working correctly. * Fixed SSAO incorrectly applied through alpha blended textures. +* Fixed static meshes not interpolating when dynamically changing their positional data. +* Fixed crashes when shooting, if gunflash or gunshell objects are not present in a level. +* Fixed crashes when Lara is on a vehicle unreachable by friendly NPCs. * Removed legacy TR5 search object code which caused issues with meshswaps. ### Lua API changes diff --git a/TombEngine/Game/effects/debris.cpp b/TombEngine/Game/effects/debris.cpp index 4139bb33b..df0b63e2b 100644 --- a/TombEngine/Game/effects/debris.cpp +++ b/TombEngine/Game/effects/debris.cpp @@ -61,7 +61,7 @@ void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num, short roomNumbe { int meshIndex = 0; short yRot = 0; - float scale; + Vector3 scale; Vector3 pos; bool isStatic; @@ -74,7 +74,7 @@ void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num, short roomNumbe meshIndex = Statics[mesh->staticNumber].meshNumber; yRot = mesh->pos.Orientation.y; pos = Vector3(mesh->pos.Position.x, mesh->pos.Position.y, mesh->pos.Position.z); - scale = mesh->scale; + scale = mesh->pos.Scale; if (mesh->HitPoints <= 0) mesh->flags &= ~StaticMeshFlags::SM_VISIBLE; @@ -89,7 +89,7 @@ void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num, short roomNumbe meshIndex = item->meshIndex; yRot = item->yRot; pos = item->sphere.Center; - scale = 1.0f; + scale = Vector3::One; } auto fragmentsMesh = &g_Level.Meshes[meshIndex]; diff --git a/TombEngine/Game/room.cpp b/TombEngine/Game/room.cpp index f2ce9fa21..018a48ff0 100644 --- a/TombEngine/Game/room.cpp +++ b/TombEngine/Game/room.cpp @@ -255,11 +255,11 @@ GameBoundingBox& GetBoundsAccurate(const MESH_INFO& mesh, bool getVisibilityBox) if (getVisibilityBox) { - bounds = Statics[mesh.staticNumber].visibilityBox * mesh.scale; + bounds = Statics[mesh.staticNumber].visibilityBox * mesh.pos.Scale; } else { - bounds = Statics[mesh.staticNumber].collisionBox * mesh.scale; + bounds = Statics[mesh.staticNumber].collisionBox * mesh.pos.Scale; } return bounds; diff --git a/TombEngine/Game/room.h b/TombEngine/Game/room.h index a43e2c428..763b245e1 100644 --- a/TombEngine/Game/room.h +++ b/TombEngine/Game/room.h @@ -77,7 +77,6 @@ struct MESH_INFO { Pose pos; int roomNumber; - float scale; short staticNumber; short flags; Vector4 color; diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 941a5e83a..bff1931c0 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -1081,7 +1081,6 @@ const std::vector SaveGame::Build() Save::StaticMeshInfoBuilder staticMesh{ fbb }; staticMesh.add_pose(&FromPose(room->mesh[j].pos)); - staticMesh.add_scale(room->mesh[j].scale); staticMesh.add_color(&FromVector4(room->mesh[j].color)); staticMesh.add_flags(room->mesh[j].flags); @@ -2516,7 +2515,6 @@ static void ParseLevel(const Save::SaveGame* s, bool hubMode) room->mesh[number].pos = ToPose(*staticMesh->pose()); room->mesh[number].roomNumber = staticMesh->room_number(); - room->mesh[number].scale = staticMesh->scale(); room->mesh[number].color = ToVector4(staticMesh->color()); room->mesh[number].flags = staticMesh->flags(); diff --git a/TombEngine/Math/Objects/GameBoundingBox.cpp b/TombEngine/Math/Objects/GameBoundingBox.cpp index 60177a6da..5ce31a140 100644 --- a/TombEngine/Math/Objects/GameBoundingBox.cpp +++ b/TombEngine/Math/Objects/GameBoundingBox.cpp @@ -167,6 +167,14 @@ Z1 * scalar, Z2 * scalar); } + GameBoundingBox GameBoundingBox::operator *(Vector3 scalar) const + { + return GameBoundingBox( + X1 * scalar.x, X2 * scalar.x, + Y1 * scalar.y, Y2 * scalar.y, + Z1 * scalar.z, Z2 * scalar.z); + } + GameBoundingBox GameBoundingBox::operator /(float scalar) const { return GameBoundingBox( @@ -174,4 +182,12 @@ Y1 / scalar, Y2 / scalar, Z1 / scalar, Z2 / scalar); } + + GameBoundingBox GameBoundingBox::operator /(Vector3 scalar) const + { + return GameBoundingBox( + X1 / scalar.x, X2 / scalar.x, + Y1 / scalar.y, Y2 / scalar.y, + Z1 / scalar.z, Z2 / scalar.z); + } //} diff --git a/TombEngine/Math/Objects/GameBoundingBox.h b/TombEngine/Math/Objects/GameBoundingBox.h index ff819239d..90cda2dbc 100644 --- a/TombEngine/Math/Objects/GameBoundingBox.h +++ b/TombEngine/Math/Objects/GameBoundingBox.h @@ -57,6 +57,8 @@ struct ObjectInfo; GameBoundingBox operator -(const GameBoundingBox& bounds) const; GameBoundingBox operator -(const Pose& pose) const; GameBoundingBox operator *(float scalar) const; + GameBoundingBox operator *(Vector3 scalar) const; GameBoundingBox operator /(float scalar) const; + GameBoundingBox operator /(Vector3 scalar) const; }; //} diff --git a/TombEngine/Renderer/RendererCompatibility.cpp b/TombEngine/Renderer/RendererCompatibility.cpp index 25c44ac36..f77460bb0 100644 --- a/TombEngine/Renderer/RendererCompatibility.cpp +++ b/TombEngine/Renderer/RendererCompatibility.cpp @@ -292,12 +292,11 @@ namespace TEN::Renderer staticInfo->RoomNumber = oldMesh->roomNumber; staticInfo->Color = oldMesh->color; staticInfo->AmbientLight = r->AmbientLight; - staticInfo->Pose = oldMesh->pos; - staticInfo->Scale = oldMesh->scale; + staticInfo->Pose = staticInfo->PrevPose = oldMesh->pos; staticInfo->OriginalSphere = Statics[staticInfo->ObjectNumber].visibilityBox.ToLocalBoundingSphere(); staticInfo->IndexInRoom = l; - staticInfo->Update(); + staticInfo->Update(GetInterpolationFactor()); } } diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index d8d0fcdb0..c8ce913c9 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -527,10 +527,9 @@ namespace TEN::Renderer mesh->Color = nativeMesh->color; mesh->OriginalSphere = Statics[mesh->ObjectNumber].visibilityBox.ToLocalBoundingSphere(); mesh->Pose = nativeMesh->pos; - mesh->Scale = nativeMesh->scale; - mesh->Update(); + mesh->Update(GetInterpolationFactor()); - nativeMesh->Dirty = false; + nativeMesh->Dirty = (mesh->PrevPose != mesh->Pose); } if (!(nativeMesh->flags & StaticMeshFlags::SM_VISIBLE)) @@ -931,5 +930,11 @@ namespace TEN::Renderer effect.PrevRotation = effect.Rotation; effect.PrevScale = effect.Scale; } + + for (auto& room : _rooms) + { + for (auto& stat : room.Statics) + stat.PrevPose = stat.Pose; + } } } diff --git a/TombEngine/Renderer/Structures/RendererStatic.h b/TombEngine/Renderer/Structures/RendererStatic.h index 03ae26f0f..9a3f4ea39 100644 --- a/TombEngine/Renderer/Structures/RendererStatic.h +++ b/TombEngine/Renderer/Structures/RendererStatic.h @@ -15,6 +15,7 @@ namespace TEN::Renderer::Structures int ObjectNumber; int RoomNumber; int IndexInRoom; + Pose PrevPose; Pose Pose; Matrix World; Vector4 Color; @@ -24,14 +25,15 @@ namespace TEN::Renderer::Structures bool CacheLights; BoundingSphere OriginalSphere; BoundingSphere Sphere; - float Scale; - void Update() + void Update(float interpolationFactor) { - World = (Pose.Orientation.ToRotationMatrix() * - Matrix::CreateScale(Scale) * - Matrix::CreateTranslation(Pose.Position.x, Pose.Position.y, Pose.Position.z)); - Sphere = BoundingSphere(Vector3::Transform(OriginalSphere.Center, World), OriginalSphere.Radius * Scale); + auto pos = Vector3::Lerp(PrevPose.Position.ToVector3(), Pose.Position.ToVector3(), interpolationFactor); + auto scale = Vector3::Lerp(PrevPose.Scale, Pose.Scale, interpolationFactor); + auto orient = Matrix::Lerp(PrevPose.Orientation.ToRotationMatrix(), Pose.Orientation.ToRotationMatrix(), interpolationFactor); + + World = (orient * Matrix::CreateScale(scale) * Matrix::CreateTranslation(pos)); + Sphere = BoundingSphere(Vector3::Transform(OriginalSphere.Center, World), OriginalSphere.Radius * std::max(std::max(Pose.Scale.x, Pose.Scale.y), Pose.Scale.z)); CacheLights = true; } }; diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Static/StaticObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Static/StaticObject.cpp index 90a1f47de..f91e981c7 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Static/StaticObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Static/StaticObject.cpp @@ -98,7 +98,8 @@ namespace TEN::Scripting // @treturn float World scale. float Static::GetScale() const { - return _static.scale; + // TODO: Decide what to return when Vector3 scale is also exposed. + return _static.pos.Scale.x; } /// Get this static's color. @@ -193,7 +194,7 @@ namespace TEN::Scripting // @tparam float scale New world scale. void Static::SetScale(float scale) { - _static.scale = scale; + _static.pos.Scale = Vector3(scale); _static.Dirty = true; } diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp index bc6c48665..ab207f3be 100644 --- a/TombEngine/Specific/level.cpp +++ b/TombEngine/Specific/level.cpp @@ -732,7 +732,7 @@ void LoadDynamicRoomData() mesh.pos.Orientation.y = ReadUInt16(); mesh.pos.Orientation.x = ReadUInt16(); mesh.pos.Orientation.z = ReadUInt16(); - mesh.scale = ReadFloat(); + mesh.pos.Scale = Vector3(ReadFloat()); mesh.flags = ReadUInt16(); mesh.color = ReadVector4(); mesh.staticNumber = ReadUInt16(); diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h index 5a17a89ab..391bc92d8 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h @@ -5205,7 +5205,6 @@ struct StaticMeshInfoT : public flatbuffers::NativeTable { int32_t number = 0; int32_t room_number = 0; std::unique_ptr pose{}; - float scale = 0.0f; std::unique_ptr color{}; int32_t hit_points = 0; int32_t flags = 0; @@ -5219,10 +5218,9 @@ struct StaticMeshInfo FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_NUMBER = 4, VT_ROOM_NUMBER = 6, VT_POSE = 8, - VT_SCALE = 10, - VT_COLOR = 12, - VT_HIT_POINTS = 14, - VT_FLAGS = 16 + VT_COLOR = 10, + VT_HIT_POINTS = 12, + VT_FLAGS = 14 }; int32_t number() const { return GetField(VT_NUMBER, 0); @@ -5233,9 +5231,6 @@ struct StaticMeshInfo FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const TEN::Save::Pose *pose() const { return GetStruct(VT_POSE); } - float scale() const { - return GetField(VT_SCALE, 0.0f); - } const TEN::Save::Vector4 *color() const { return GetStruct(VT_COLOR); } @@ -5250,7 +5245,6 @@ struct StaticMeshInfo FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_NUMBER) && VerifyField(verifier, VT_ROOM_NUMBER) && VerifyField(verifier, VT_POSE) && - VerifyField(verifier, VT_SCALE) && VerifyField(verifier, VT_COLOR) && VerifyField(verifier, VT_HIT_POINTS) && VerifyField(verifier, VT_FLAGS) && @@ -5274,9 +5268,6 @@ struct StaticMeshInfoBuilder { void add_pose(const TEN::Save::Pose *pose) { fbb_.AddStruct(StaticMeshInfo::VT_POSE, pose); } - void add_scale(float scale) { - fbb_.AddElement(StaticMeshInfo::VT_SCALE, scale, 0.0f); - } void add_color(const TEN::Save::Vector4 *color) { fbb_.AddStruct(StaticMeshInfo::VT_COLOR, color); } @@ -5302,7 +5293,6 @@ inline flatbuffers::Offset CreateStaticMeshInfo( int32_t number = 0, int32_t room_number = 0, const TEN::Save::Pose *pose = 0, - float scale = 0.0f, const TEN::Save::Vector4 *color = 0, int32_t hit_points = 0, int32_t flags = 0) { @@ -5310,7 +5300,6 @@ inline flatbuffers::Offset CreateStaticMeshInfo( builder_.add_flags(flags); builder_.add_hit_points(hit_points); builder_.add_color(color); - builder_.add_scale(scale); builder_.add_pose(pose); builder_.add_room_number(room_number); builder_.add_number(number); @@ -10788,7 +10777,6 @@ inline void StaticMeshInfo::UnPackTo(StaticMeshInfoT *_o, const flatbuffers::res { auto _e = number(); _o->number = _e; } { auto _e = room_number(); _o->room_number = _e; } { auto _e = pose(); if (_e) _o->pose = std::unique_ptr(new TEN::Save::Pose(*_e)); } - { auto _e = scale(); _o->scale = _e; } { auto _e = color(); if (_e) _o->color = std::unique_ptr(new TEN::Save::Vector4(*_e)); } { auto _e = hit_points(); _o->hit_points = _e; } { auto _e = flags(); _o->flags = _e; } @@ -10805,7 +10793,6 @@ inline flatbuffers::Offset CreateStaticMeshInfo(flatbuffers::Fla auto _number = _o->number; auto _room_number = _o->room_number; auto _pose = _o->pose ? _o->pose.get() : 0; - auto _scale = _o->scale; auto _color = _o->color ? _o->color.get() : 0; auto _hit_points = _o->hit_points; auto _flags = _o->flags; @@ -10814,7 +10801,6 @@ inline flatbuffers::Offset CreateStaticMeshInfo(flatbuffers::Fla _number, _room_number, _pose, - _scale, _color, _hit_points, _flags); diff --git a/TombEngine/Specific/savegame/schema/ten_savegame.fbs b/TombEngine/Specific/savegame/schema/ten_savegame.fbs index bd2adc629..f2bd003cd 100644 --- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs +++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs @@ -372,7 +372,6 @@ table StaticMeshInfo { number: int32; room_number: int32; pose: Pose; - scale: float; color: Vector4; hit_points: int32; flags: int32;