From 3ec8a91f30d881f66630dff9ac2d29a6f727c145 Mon Sep 17 00:00:00 2001 From: Stan Date: Thu, 31 Dec 2020 16:17:58 +0000 Subject: [PATCH] Fix incorrect prop height for floating objects. Differential Revision: https://code.wildfiregames.com/D3033 This was SVN commit r24491. --- source/graphics/Model.cpp | 46 +++++++++++++++++++-------------- source/graphics/Model.h | 4 +-- source/graphics/ObjectEntry.cpp | 9 +++++-- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index f9e8a6fd3b..1a1f483bf1 100644 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -40,6 +40,7 @@ #include "renderer/RenderingOptions.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpTerrain.h" +#include "simulation2/components/ICmpWaterManager.h" ///////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -381,13 +382,27 @@ void CModel::ValidatePosition() // that doing so will cause a revalidation of this model (see recursion above). m_PositionValid = true; - // re-position and validate all props - for (size_t j = 0; j < m_Props.size(); ++j) + CMatrix3D translate; + CVector3D objTranslation = m_Transform.GetTranslation(); + float objectHeight = 0.0f; + + CmpPtr cmpTerrain(m_Simulation, SYSTEM_ENTITY); + if (cmpTerrain) + objectHeight = cmpTerrain->GetExactGroundLevel(objTranslation.X, objTranslation.Z); + + // Object height is incorrect for floating objects. We use water height instead. + CmpPtr cmpWaterManager(m_Simulation, SYSTEM_ENTITY); + if (cmpWaterManager) { - const Prop& prop=m_Props[j]; + float waterHeight = cmpWaterManager->GetExactWaterLevel(objTranslation.X, objTranslation.Z); + if (waterHeight >= objectHeight && m_Flags & MODELFLAG_FLOATONWATER) + objectHeight = waterHeight; + } + // re-position and validate all props + for (const Prop& prop : m_Props) + { CMatrix3D proptransform = prop.m_Point->m_Transform; - if (prop.m_Point->m_BoneIndex != 0xff) { CMatrix3D boneMatrix = m_BoneMatrices[prop.m_Point->m_BoneIndex]; @@ -402,22 +417,13 @@ void CModel::ValidatePosition() } // Adjust prop height to terrain level when needed - if (prop.m_MaxHeight != 0.f || prop.m_MinHeight != 0.f) + if (cmpTerrain && (prop.m_MaxHeight != 0.f || prop.m_MinHeight != 0.f)) { - CVector3D propTranslation = proptransform.GetTranslation(); - CVector3D objTranslation = m_Transform.GetTranslation(); - - CmpPtr cmpTerrain(m_Simulation, SYSTEM_ENTITY); - if (cmpTerrain) - { - float objTerrain = cmpTerrain->GetExactGroundLevel(objTranslation.X, objTranslation.Z); - float propTerrain = cmpTerrain->GetExactGroundLevel(propTranslation.X, propTranslation.Z); - float translateHeight = std::min(prop.m_MaxHeight, - std::max(prop.m_MinHeight, propTerrain - objTerrain)); - CMatrix3D translate = CMatrix3D(); - translate.SetTranslation(0.f, translateHeight, 0.f); - proptransform.Concatenate(translate); - } + const CVector3D& propTranslation = proptransform.GetTranslation(); + const float propTerrain = cmpTerrain->GetExactGroundLevel(propTranslation.X, propTranslation.Z); + const float translateHeight = std::min(prop.m_MaxHeight, std::max(prop.m_MinHeight, propTerrain - objectHeight)); + translate.SetTranslation(0.f, translateHeight, 0.f); + proptransform.Concatenate(translate); } prop.m_Model->SetTransform(proptransform); diff --git a/source/graphics/Model.h b/source/graphics/Model.h index 8bf254fb87..cc21fdff05 100644 --- a/source/graphics/Model.h +++ b/source/graphics/Model.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -41,7 +41,7 @@ class CSimulation2; #define MODELFLAG_SILHOUETTE_DISPLAY (1<<2) #define MODELFLAG_SILHOUETTE_OCCLUDER (1<<3) #define MODELFLAG_IGNORE_LOS (1<<4) - +#define MODELFLAG_FLOATONWATER (1<<5) /////////////////////////////////////////////////////////////////////////////// // CModel: basically, a mesh object - holds the texturing and skinning // information for a model in game diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index 254163da91..c48053a21d 100644 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -246,10 +246,15 @@ bool CObjectEntry::BuildVariation(const std::vector >& selections LOGERROR("Failed to find matching prop point called \"%s\" in model \"%s\" for actor \"%s\"", ppn, m_ModelName.string8(), utf8_from_wstring(m_Base->m_ShortName)); } - // setup flags + // Setup flags. if (m_Base->m_Properties.m_CastShadows) { - model->SetFlags(model->GetFlags()|MODELFLAG_CASTSHADOWS); + model->SetFlags(model->GetFlags() | MODELFLAG_CASTSHADOWS); + } + + if (m_Base->m_Properties.m_FloatOnWater) + { + model->SetFlags(model->GetFlags() | MODELFLAG_FLOATONWATER); } return true;