Merge branch 'develop_60fps' of https://github.com/MontyTRC89/TombEngine into develop_60fps

This commit is contained in:
MontyTRC89 2024-05-17 13:39:10 +02:00
commit be95d77d92
8 changed files with 81 additions and 81 deletions

View file

@ -110,10 +110,10 @@ local strings =
total_secrets_found = { "Secrets Found Total" }, total_secrets_found = { "Secrets Found Total" },
use = { "Use" }, use = { "Use" },
used_medipacks = { "Medipacks Used" }, used_medipacks = { "Medipacks Used" },
variable_framerate = { "Variable Framerate" },
vehicle_actions = { "Vehicle Actions" }, vehicle_actions = { "Vehicle Actions" },
view = { "View" }, view = { "View" },
volumetric_fog = { "Volumetric Fog" }, volumetric_fog = { "Volumetric Fog" },
variable_framerate = { "Variable Framerate" },
waiting_for_input = { "Waiting For Input" }, waiting_for_input = { "Waiting For Input" },
window_title = { "TombEngine" }, window_title = { "TombEngine" },
windowed = { "Windowed" }, windowed = { "Windowed" },

View file

@ -48,7 +48,7 @@ namespace TEN::Hud
void SpeedometerController::Draw() const void SpeedometerController::Draw() const
{ {
constexpr auto POS = Vector2(DISPLAY_SPACE_RES.x - (DISPLAY_SPACE_RES.x / 6), DISPLAY_SPACE_RES.y - (DISPLAY_SPACE_RES.y / 10)); constexpr auto POS = Vector2(DISPLAY_SPACE_RES.x - (DISPLAY_SPACE_RES.x / 6), DISPLAY_SPACE_RES.y - (DISPLAY_SPACE_RES.y / 10));
constexpr auto ORIENT_OFFSET = ANGLE(90.0f); constexpr auto POINTER_ANGLE_OFFSET = ANGLE(90.0f);
constexpr auto SCALE = Vector2(0.35f); constexpr auto SCALE = Vector2(0.35f);
constexpr auto DIAL_ELEMENT_SPRITE_ID = 0; constexpr auto DIAL_ELEMENT_SPRITE_ID = 0;
constexpr auto POINTER_ELEMENT_SPRITE_ID = 1; constexpr auto POINTER_ELEMENT_SPRITE_ID = 1;
@ -60,9 +60,8 @@ namespace TEN::Hud
if (_life <= 0.0f) if (_life <= 0.0f)
return; return;
// TODO: Interpolation. short pointerAngle = (short)Lerp(_prevPointerAngle, _pointerAngle, g_Renderer.GetInterpolationFactor());
auto color = Color(1.0f, 1.0f, 1.0f, Lerp(_prevOpacity, _opacity, g_Renderer.GetInterpolationFactor()));
auto color = Color(1.0f, 1.0f, 1.0f, _opacity);
// Draw dial. // Draw dial.
AddDisplaySprite( AddDisplaySprite(
@ -74,7 +73,7 @@ namespace TEN::Hud
// Draw pointer. // Draw pointer.
AddDisplaySprite( AddDisplaySprite(
ID_SPEEDOMETER, POINTER_ELEMENT_SPRITE_ID, ID_SPEEDOMETER, POINTER_ELEMENT_SPRITE_ID,
POS, _pointerAngle + ORIENT_OFFSET, SCALE, color, POS, pointerAngle + POINTER_ANGLE_OFFSET, SCALE, color,
POINTER_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend, POINTER_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend,
DisplaySpritePhase::Draw); DisplaySpritePhase::Draw);
} }

View file

@ -630,12 +630,6 @@ void UpdateLara(ItemInfo* item, bool isTitle)
// Control player. // Control player.
InItemControlLoop = true; InItemControlLoop = true;
// Copy current state to old state for interpolation
//memcpy(&item->OldPose, &item->Pose, sizeof(Pose));
//memcpy(&item->OldLocation, &item->Location, sizeof(Vector3i));
//memcpy(&item->OldAnimation, &item->Animation, sizeof(EntityAnimationData));
//memcpy(&OldLara, &Lara, sizeof(LaraInfo));
LaraControl(item, &LaraCollision); LaraControl(item, &LaraCollision);
HandlePlayerFlyCheat(*item); HandlePlayerFlyCheat(*item);
InItemControlLoop = false; InItemControlLoop = false;

View file

@ -153,20 +153,18 @@ GameStatus ControlPhase()
SetupInterpolation(); SetupInterpolation();
g_Renderer.SaveOldState(); g_Renderer.SaveOldState();
// Controls are polled before OnLoop, so input data could be // Controls are polled before OnLoop to allow input data to be overwritten by script API methods.
// overwritten by script API methods.
HandleControls(isTitle); HandleControls(isTitle);
// Pre-loop script and event handling. // Pre-loop script and event handling.
g_GameScript->OnLoop(DELTA_TIME, false); // TODO: Don't use DELTA_TIME constant with variable framerate g_GameScript->OnLoop(DELTA_TIME, false); // TODO: Don't use DELTA_TIME constant with variable framerate
HandleAllGlobalEvents(EventType::Loop, (Activator)LaraItem->Index); HandleAllGlobalEvents(EventType::Loop, (Activator)LaraItem->Index);
// Control lock is processed after handling scripts, because builder may want to // Control lock is processed after handling scripts because builder may want to process input externally while locking player from input.
// process input externally, while still locking Lara from input.
if (!isTitle && Lara.Control.IsLocked) if (!isTitle && Lara.Control.IsLocked)
ClearAllActions(); ClearAllActions();
// Handle inventory / pause / load / save screens. // Handle inventory, pause, load, save screens.
auto result = HandleMenuCalls(isTitle); auto result = HandleMenuCalls(isTitle);
if (result != GameStatus::Normal) if (result != GameStatus::Normal)
return result; return result;
@ -176,9 +174,8 @@ GameStatus ControlPhase()
if (result != GameStatus::Normal) if (result != GameStatus::Normal)
return result; return result;
// Queued input actions are read again and cleared after UI // Queued input actions are read again and cleared after UI interrupts are processed,
// interrupts are processed, so first frame after exiting UI // so first game frame after exiting UI will still register it.
// will still register it.
ApplyActionQueue(); ApplyActionQueue();
ClearActionQueue(); ClearActionQueue();
@ -188,14 +185,14 @@ GameStatus ControlPhase()
g_GameScriptEntities->TestCollidingObjects(); g_GameScriptEntities->TestCollidingObjects();
// Draw flyby cameras.
if (UseSpotCam) if (UseSpotCam)
{ {
// Draw flyby cameras.
CalculateSpotCameras(); CalculateSpotCameras();
} }
// Do standard camera.
else else
{ {
// Do the standard camera.
TrackCameraInit = false; TrackCameraInit = false;
CalculateCamera(LaraCollision); CalculateCamera(LaraCollision);
} }
@ -206,11 +203,11 @@ GameStatus ControlPhase()
// Smash shatters and clear stopper flags under them. // Smash shatters and clear stopper flags under them.
UpdateShatters(); UpdateShatters();
// Clear last selected item in inventory (need to be after on loop event handling, so they can detect that). // Clear last selected item in inventory (must be after on loop event handling, so they can detect that).
g_Gui.CancelInventorySelection(); g_Gui.CancelInventorySelection();
// Control lock is processed after handling scripts, because builder may want to // Control lock is processed after handling scripts because builder may want to
// process input externally, while still locking Lara from input. // process input externally while locking player from input.
if (!isTitle && Lara.Control.IsLocked) if (!isTitle && Lara.Control.IsLocked)
ClearAllActions(); ClearAllActions();
@ -286,22 +283,26 @@ GameStatus ControlPhase()
unsigned CALLBACK GameMain(void *) unsigned CALLBACK GameMain(void *)
{ {
TENLog("Starting GameMain...", LogLevel::Info); TENLog("Starting GameMain()...", LogLevel::Info);
TimeInit(); TimeInit();
// Do a fixed time title image. // Do fixed-time title image.
if (g_GameFlow->IntroImagePath.empty()) if (g_GameFlow->IntroImagePath.empty())
TENLog("Intro image path is not set.", LogLevel::Warning); {
TENLog("Intro image path not set.", LogLevel::Warning);
}
else else
{
g_Renderer.RenderTitleImage(); g_Renderer.RenderTitleImage();
}
// Execute the Lua gameflow and play the game. // Execute Lua gameflow and play game.
g_GameFlow->DoFlow(); g_GameFlow->DoFlow();
DoTheGame = false; DoTheGame = false;
// Finish the thread. // Finish thread.
PostMessage(WindowsHandle, WM_CLOSE, NULL, NULL); PostMessage(WindowsHandle, WM_CLOSE, NULL, NULL);
EndThread(); EndThread();
@ -317,7 +318,7 @@ GameStatus DoLevel(int levelIndex, bool loadGame)
// Load level. Fall back to title if unsuccessful. // Load level. Fall back to title if unsuccessful.
if (!LoadLevelFile(levelIndex)) if (!LoadLevelFile(levelIndex))
return isTitle ? GameStatus::ExitGame : GameStatus::ExitToTitle; return (isTitle ? GameStatus::ExitGame : GameStatus::ExitToTitle);
// Initialize items, effects, lots, and cameras. // Initialize items, effects, lots, and cameras.
HairEffect.Initialize(); HairEffect.Initialize();
@ -374,13 +375,17 @@ void KillMoveItems()
{ {
for (int i = 0; i < ItemNewRoomNo; i++) for (int i = 0; i < ItemNewRoomNo; i++)
{ {
short itemNumber = ItemNewRooms[2 * i]; int itemNumber = ItemNewRooms[i * 2];
if (itemNumber >= 0) if (itemNumber >= 0)
ItemNewRoom(itemNumber, ItemNewRooms[2 * i + 1]); {
ItemNewRoom(itemNumber, ItemNewRooms[(i * 2) + 1]);
}
else else
{
KillItem(itemNumber & 0x7FFF); KillItem(itemNumber & 0x7FFF);
} }
} }
}
ItemNewRoomNo = 0; ItemNewRoomNo = 0;
} }
@ -391,13 +396,17 @@ void KillMoveEffects()
{ {
for (int i = 0; i < ItemNewRoomNo; i++) for (int i = 0; i < ItemNewRoomNo; i++)
{ {
short itemNumber = ItemNewRooms[2 * i]; int itemNumber = ItemNewRooms[i * 2];
if (itemNumber >= 0) if (itemNumber >= 0)
EffectNewRoom(itemNumber, ItemNewRooms[2 * i + 1]); {
EffectNewRoom(itemNumber, ItemNewRooms[(i * 2) + 1]);
}
else else
{
KillEffect(itemNumber & 0x7FFF); KillEffect(itemNumber & 0x7FFF);
} }
} }
}
ItemNewRoomNo = 0; ItemNewRoomNo = 0;
} }
@ -417,13 +426,13 @@ void CleanUp()
// Reset oscillator seed. // Reset oscillator seed.
Wibble = 0; Wibble = 0;
// Needs to be cleared, otherwise controls will lock if user exits to title while playing flyby with locked controls. // Clear player lock, otherwise controls will lock if user exits to title while playing flyby with locked controls.
Lara.Control.IsLocked = false; Lara.Control.IsLocked = false;
// Resets lightning and wind parameters to avoid holding over previous weather to new level. // Resets lightning and wind parameters to avoid holding over previous weather to new level.
Weather.Clear(); Weather.Clear();
// Needs to be cleared, otherwise a list of active creatures from previous level will spill into new level. // Clear creatures, otherwise list of active creatures from previous level will spill into new level.
ActiveCreatures.clear(); ActiveCreatures.clear();
// Clear ropes. // Clear ropes.
@ -473,26 +482,27 @@ void InitializeScripting(int levelIndex, LevelLoadType type)
g_GameStringsHandler->ClearDisplayStrings(); g_GameStringsHandler->ClearDisplayStrings();
g_GameScript->ResetScripts(!levelIndex || type != LevelLoadType::New); g_GameScript->ResetScripts(!levelIndex || type != LevelLoadType::New);
auto* level = g_GameFlow->GetLevel(levelIndex); const auto& level = *g_GameFlow->GetLevel(levelIndex);
// Run level script if it exists. // Run level script if it exists.
if (!level->ScriptFileName.empty()) if (!level.ScriptFileName.empty())
{ {
g_GameScript->ExecuteScriptFile(g_GameFlow->GetGameDir() + level->ScriptFileName); g_GameScript->ExecuteScriptFile(g_GameFlow->GetGameDir() + level.ScriptFileName);
g_GameScript->InitCallbacks(); g_GameScript->InitCallbacks();
g_GameStringsHandler->SetCallbackDrawString([](const std::string& key, D3DCOLOR color, const Vec2& pos, float scale, int flags) g_GameStringsHandler->SetCallbackDrawString([](const std::string& key, D3DCOLOR color, const Vec2& pos, float scale, int flags)
{ {
g_Renderer.AddString( g_Renderer.AddString(
key, key,
Vector2(((float)pos.x / (float)g_Configuration.ScreenWidth * DISPLAY_SPACE_RES.x), Vector2(
((float)pos.y / (float)g_Configuration.ScreenHeight * DISPLAY_SPACE_RES.y)), (pos.x / g_Configuration.ScreenWidth) * DISPLAY_SPACE_RES.x,
(pos.y / g_Configuration.ScreenHeight) * DISPLAY_SPACE_RES.y),
Color(color), scale, flags); Color(color), scale, flags);
}); });
} }
// Play default background music. // Play default background music.
if (type != LevelLoadType::Load) if (type != LevelLoadType::Load)
PlaySoundTrack(level->GetAmbientTrack(), SoundTrackType::BGM); PlaySoundTrack(level.GetAmbientTrack(), SoundTrackType::BGM);
} }
void DeInitializeScripting(int levelIndex, GameStatus reason) void DeInitializeScripting(int levelIndex, GameStatus reason)
@ -503,7 +513,7 @@ void DeInitializeScripting(int levelIndex, GameStatus reason)
g_GameScript->FreeLevelScripts(); g_GameScript->FreeLevelScripts();
g_GameScriptEntities->FreeEntities(); g_GameScriptEntities->FreeEntities();
if (!levelIndex) if (levelIndex == 0)
g_GameScript->ResetScripts(true); g_GameScript->ResetScripts(true);
} }
@ -512,7 +522,7 @@ void InitializeOrLoadGame(bool loadGame)
g_Gui.SetInventoryItemChosen(NO_VALUE); g_Gui.SetInventoryItemChosen(NO_VALUE);
g_Gui.SetEnterInventory(NO_VALUE); g_Gui.SetEnterInventory(NO_VALUE);
// Restore the game? // Restore game?
if (loadGame) if (loadGame)
{ {
SaveGame::Load(g_GameFlow->SelectedSaveGame); SaveGame::Load(g_GameFlow->SelectedSaveGame);
@ -533,7 +543,7 @@ void InitializeOrLoadGame(bool loadGame)
} }
else else
{ {
// If not loading a savegame, clear all info. // If not loading savegame, clear all info.
SaveGame::Statistics.Level = {}; SaveGame::Statistics.Level = {};
if (InitializeGame) if (InitializeGame)
@ -559,19 +569,19 @@ void InitializeOrLoadGame(bool loadGame)
GameStatus DoGameLoop(int levelIndex) GameStatus DoGameLoop(int levelIndex)
{ {
int numFrames = LOOP_FRAME_COUNT; constexpr auto CONTROL_FRAME_TIME = 1000.0f / 30.0f;
int frameCount = LOOP_FRAME_COUNT;
auto& status = g_GameFlow->LastGameStatus; auto& status = g_GameFlow->LastGameStatus;
// Before entering actual game loop, ControlPhase must be // Before entering actual game loop, ControlPhase() must be
// called once to sort out various runtime shenanigangs (e.g. hair). // called once to sort out various runtime shenanigangs (e.g. hair).
status = ControlPhase(); status = ControlPhase();
LARGE_INTEGER lastTime; LARGE_INTEGER lastTime;
LARGE_INTEGER currentTime; LARGE_INTEGER currentTime;
double controlLag = 0; double controlLag = 0;
double frameTime = 0; double frameTime = 0;
constexpr auto controlFrameTime = 1000.0f / 30.0f;
LARGE_INTEGER frequency; LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency); QueryPerformanceFrequency(&frequency);
@ -600,21 +610,21 @@ GameStatus DoGameLoop(int levelIndex)
controlLag += frameTime; controlLag += frameTime;
} }
while (controlLag >= controlFrameTime) while (controlLag >= CONTROL_FRAME_TIME)
{ {
#if _DEBUG #if _DEBUG
constexpr auto DEBUG_SKIP_FRAMES = 10; constexpr auto DEBUG_SKIP_FRAMES = 10;
if (controlLag >= DEBUG_SKIP_FRAMES * controlFrameTime) if (controlLag >= DEBUG_SKIP_FRAMES * CONTROL_FRAME_TIME)
{ {
TENLog("Game loop is running too slow!", LogLevel::Warning); TENLog("Game loop is running too slow.", LogLevel::Warning);
App.ResetClock = true; App.ResetClock = true;
break; break;
} }
#endif #endif
status = ControlPhase(); status = ControlPhase();
controlLag -= controlFrameTime; controlLag -= CONTROL_FRAME_TIME;
controlCalls++; controlCalls++;
legacy30FpsDoneDraw = false; legacy30FpsDoneDraw = false;
@ -634,7 +644,7 @@ GameStatus DoGameLoop(int levelIndex)
} }
else else
{ {
float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); float interpolationFactor = std::min((float)controlLag / (float)CONTROL_FRAME_TIME, 1.0f);
DrawPhase(!levelIndex, interpolationFactor); DrawPhase(!levelIndex, interpolationFactor);
drawCalls++; drawCalls++;
} }
@ -658,9 +668,7 @@ void EndGameLoop(int levelIndex, GameStatus reason)
void SetupInterpolation() void SetupInterpolation()
{ {
for (int i = 0; i < g_Level.Items.size(); i++) for (int i = 0; i < g_Level.Items.size(); i++)
{
g_Level.Items[i].DisableInterpolation = false; g_Level.Items[i].DisableInterpolation = false;
}
} }
void HandleControls(bool isTitle) void HandleControls(bool isTitle)
@ -675,10 +683,10 @@ void HandleControls(bool isTitle)
GameStatus HandleMenuCalls(bool isTitle) GameStatus HandleMenuCalls(bool isTitle)
{ {
auto result = GameStatus::Normal; auto gameStatus = GameStatus::Normal;
if (ScreenFading) if (ScreenFading)
return result; return gameStatus;
if (isTitle) if (isTitle)
{ {
@ -697,10 +705,10 @@ GameStatus HandleMenuCalls(bool isTitle)
return GameStatus::ExitGame; return GameStatus::ExitGame;
} }
return result; return gameStatus;
} }
// Does the player want to enter inventory? // Handle inventory.
if (IsClicked(In::Save) && LaraItem->HitPoints > 0 && if (IsClicked(In::Save) && LaraItem->HitPoints > 0 &&
g_Gui.GetInventoryMode() != InventoryMode::Save && g_Gui.GetInventoryMode() != InventoryMode::Save &&
g_GameFlow->IsLoadSaveEnabled()) g_GameFlow->IsLoadSaveEnabled())
@ -717,28 +725,28 @@ GameStatus HandleMenuCalls(bool isTitle)
g_Gui.SetInventoryMode(InventoryMode::Load); g_Gui.SetInventoryMode(InventoryMode::Load);
if (g_Gui.CallInventory(LaraItem, false)) if (g_Gui.CallInventory(LaraItem, false))
result = GameStatus::LoadGame; gameStatus = GameStatus::LoadGame;
} }
else if (IsClicked(In::Pause) && LaraItem->HitPoints > 0 && else if (IsClicked(In::Pause) && LaraItem->HitPoints > 0 &&
g_Gui.GetInventoryMode() != InventoryMode::Pause) g_Gui.GetInventoryMode() != InventoryMode::Pause)
{ {
if (g_Gui.CallPause()) if (g_Gui.CallPause())
result = GameStatus::ExitToTitle; gameStatus = GameStatus::ExitToTitle;
} }
else if ((IsClicked(In::Inventory) || g_Gui.GetEnterInventory() != NO_VALUE) && else if ((IsClicked(In::Inventory) || g_Gui.GetEnterInventory() != NO_VALUE) &&
LaraItem->HitPoints > 0 && !Lara.Control.Look.IsUsingBinoculars) LaraItem->HitPoints > 0 && !Lara.Control.Look.IsUsingBinoculars)
{ {
if (g_Gui.CallInventory(LaraItem, true)) if (g_Gui.CallInventory(LaraItem, true))
result = GameStatus::LoadGame; gameStatus = GameStatus::LoadGame;
} }
if (result != GameStatus::Normal) if (gameStatus != GameStatus::Normal)
{ {
StopAllSounds(); StopAllSounds();
StopRumble(); StopRumble();
} }
return result; return gameStatus;
} }
GameStatus HandleGlobalInputEvents(bool isTitle) GameStatus HandleGlobalInputEvents(bool isTitle)

View file

@ -3588,8 +3588,8 @@ namespace TEN::Gui
auto needleOrient = EulerAngles(0, CompassNeedleAngle, 0); auto needleOrient = EulerAngles(0, CompassNeedleAngle, 0);
needleOrient.Lerp(EulerAngles(0, item->Pose.Orientation.y, 0), LERP_ALPHA); needleOrient.Lerp(EulerAngles(0, item->Pose.Orientation.y, 0), LERP_ALPHA);
float wibble = std::sin(((float)(GameTimer & 0x3F) / (float)0x3F) * PI_MUL_2); float wibble = std::sin((float(GameTimer & 0x3F) / (float)0x3F) * PI_MUL_2);
CompassNeedleAngle = needleOrient.y + ANGLE(wibble); CompassNeedleAngle = needleOrient.y + ANGLE(wibble / 2);
// HACK: Needle is rotated in the draw function. // HACK: Needle is rotated in the draw function.
const auto& invObject = InventoryObjectTable[INV_OBJECT_COMPASS]; const auto& invObject = InventoryObjectTable[INV_OBJECT_COMPASS];

View file

@ -3547,8 +3547,8 @@ namespace TEN::Renderer
void Renderer::DrawItemSorted(RendererSortableObject* objectInfo, RendererObjectType lastObjectType, RenderView& view) void Renderer::DrawItemSorted(RendererSortableObject* objectInfo, RendererObjectType lastObjectType, RenderView& view)
{ {
UINT stride = sizeof(Vertex); unsigned int stride = sizeof(Vertex);
UINT offset = 0; unsigned int offset = 0;
_context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset);
_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_context->IASetInputLayout(_inputLayout.Get()); _context->IASetInputLayout(_inputLayout.Get());
@ -3561,25 +3561,24 @@ namespace TEN::Renderer
_context->VSSetShader(_vsItems.Get(), nullptr, 0); _context->VSSetShader(_vsItems.Get(), nullptr, 0);
_context->PSSetShader(_psItems.Get(), nullptr, 0); _context->PSSetShader(_psItems.Get(), nullptr, 0);
ItemInfo* nativeItem = &g_Level.Items[objectInfo->Item->ItemNumber]; // Bind main item properties.
RendererRoom* room = &_rooms[objectInfo->Item->RoomNumber];
RendererObject& moveableObj = *_moveableObjects[objectInfo->Item->ObjectNumber];
// Bind item main properties
_stItem.World = objectInfo->Item->InterpolatedWorld; _stItem.World = objectInfo->Item->InterpolatedWorld;
_stItem.Color = objectInfo->Item->Color; _stItem.Color = objectInfo->Item->Color;
_stItem.AmbientLight = objectInfo->Item->AmbientLight; _stItem.AmbientLight = objectInfo->Item->AmbientLight;
memcpy(_stItem.BonesMatrices, objectInfo->Item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); memcpy(_stItem.BonesMatrices, objectInfo->Item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES);
const auto& moveableObj = *_moveableObjects[objectInfo->Item->ObjectNumber];
for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++) for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++)
_stItem.BoneLightModes[k] = (int)moveableObj.ObjectMeshes[k]->LightMode; _stItem.BoneLightModes[k] = (int)moveableObj.ObjectMeshes[k]->LightMode;
BindMoveableLights(objectInfo->Item->LightsToDraw, objectInfo->Item->RoomNumber, objectInfo->Item->PrevRoomNumber, objectInfo->Item->LightFade); BindMoveableLights(objectInfo->Item->LightsToDraw, objectInfo->Item->RoomNumber, objectInfo->Item->PrevRoomNumber, objectInfo->Item->LightFade);
_cbItem.UpdateData(_stItem, _context.Get()); _cbItem.UpdateData(_stItem, _context.Get());
BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[objectInfo->Bucket->Texture]), BindTexture(
TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[objectInfo->Bucket->Texture]),
SamplerStateRegister::AnisotropicClamp); SamplerStateRegister::AnisotropicClamp);
BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[objectInfo->Bucket->Texture]), BindTexture(
TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[objectInfo->Bucket->Texture]),
SamplerStateRegister::AnisotropicClamp); SamplerStateRegister::AnisotropicClamp);
_sortedPolygonsIndexBuffer.Update(_context.Get(), _sortedPolygonsIndices, 0, (int)_sortedPolygonsIndices.size()); _sortedPolygonsIndexBuffer.Update(_context.Get(), _sortedPolygonsIndices, 0, (int)_sortedPolygonsIndices.size());