Index: ps/trunk/source/graphics/Model.h =================================================================== --- ps/trunk/source/graphics/Model.h +++ ps/trunk/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 @@ #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 Index: ps/trunk/source/graphics/Model.cpp =================================================================== --- ps/trunk/source/graphics/Model.cpp +++ ps/trunk/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 @@ // that doing so will cause a revalidation of this model (see recursion above). m_PositionValid = true; + 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) + { + float waterHeight = cmpWaterManager->GetExactWaterLevel(objTranslation.X, objTranslation.Z); + if (waterHeight >= objectHeight && m_Flags & MODELFLAG_FLOATONWATER) + objectHeight = waterHeight; + } + // re-position and validate all props - for (size_t j = 0; j < m_Props.size(); ++j) + for (const Prop& prop : m_Props) { - const Prop& prop=m_Props[j]; - 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 @@ } // 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); Index: ps/trunk/source/graphics/ObjectEntry.cpp =================================================================== --- ps/trunk/source/graphics/ObjectEntry.cpp +++ ps/trunk/source/graphics/ObjectEntry.cpp @@ -246,10 +246,15 @@ 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;