Index: source/renderer/WaterManager.cpp =================================================================== --- source/renderer/WaterManager.cpp +++ source/renderer/WaterManager.cpp @@ -40,6 +40,8 @@ #include "simulation2/components/ICmpRangeManager.h" #include +#include +#include struct CoastalPoint { @@ -57,10 +59,10 @@ CVector3D m_RetreatPosition; CVector2D m_PerpVect; - u8 m_UV[3]; + std::array m_UV; // pad to a power of two - u8 m_Padding[5]; + std::array m_Padding; }; cassert(sizeof(SWavesVertex) == 64); @@ -409,6 +411,82 @@ ComputeDirection(m_DistanceHeightmap.get(), heightmap, m_WaterHeight, SideSize, maxLevel); } +/** + * @param vertices Were to write the new vertices to. + */ +static CBoundingBoxAligned AddShoreVertices(std::vector& vertices, const CTerrain& terrain, + const float waterHeight, const float outmost, const int sign, const u16 width, const u16 a, + const CVector2D perp, const CVector2D pos) +{ + struct ProtoVertex + { + // Coresponding to m_BasePosition, m_ApexPosition, m_SplashPosition and m_RetreatPosition. + std::array, 4> data; + u8 index; + }; + constexpr std::array protoVertices = + {{ + {{{{9.7f, 0.0f}, {9.5f, 0.0f}, {9.0f, 0.0f}, {9.0f, 0.0f}}}, 0}, + {{{{6.6f, 0.2f}, {3.6f, 0.2f}, {3.6f, 0.0f}, {3.8f, 0.0f}}}, 1}, + {{{{6.5f, 0.6f}, {3.3f, 0.6f}, {2.2f, 0.0f}, {2.7f, 0.0f}}}, 2}, + {{{{6.4f, 0.85f}, {3.0f, 0.85f}, {1.3f, 0.03f}, {1.9f, 0.0f}}}, 3}, + {{{{6.3f, 0.9f}, {2.4f, 0.9f}, {0.6f, 0.1f}, {1.7f, 0.0f}}}, 4}, + {{{{6.2f, 0.8f}, {2.3f, 0.8f}, {0.0f, 0.1f}, {1.5f, 0.0f}}}, 5}, + {{{{6.1f, 0.5f}, {2.2f, 0.5f}, {-0.2f, 0.0f}, {1.2f, 0.0f}}}, 6}, + {{{{6.05f, 0.2f}, {2.1f, 0.2f}, {0.7f, -0.4f}, {2.1f, 0.0f}}}, 7}, + {{{{6.0f, 0.0f}, {2.0f, 0.0f}, {1.1f, -0.8f}, {2.0f, 0.0f}}}, 8} + }}; + + constexpr float baseHeight = 0.04f; + + const float halfWidth = (width - 1.0f) / 2.0f; + const float sideNess = std::sqrt(Clamp((halfWidth - std::abs(a - halfWidth)) / 3.0f, 0.0f, 1.0f)); + + // Coresponding to m_BasePosition, m_ApexPosition, m_SplashPosition and m_RetreatPosition. + const std::array scaledOutmostArr + { + outmost, outmost, outmost * sideNess, outmost + }; + + const auto calculatePosition = [&](const std::array protoN, const float scaledOutmost) + { + const float terrHeight + { + 0.05f + terrain.GetExactGroundLevel( + pos.X + sign * perp.X * (std::get<0>(protoN) + scaledOutmost), + pos.Y + sign * perp.Y * (std::get<0>(protoN) + scaledOutmost)) + }; + + return CVector3D + { + pos.X + sign * perp.X * (std::get<0>(protoN) + scaledOutmost), + baseHeight + std::get<1>(protoN) * sideNess + std::max(waterHeight, terrHeight), + pos.Y + sign * perp.Y * (std::get<0>(protoN) + scaledOutmost) + }; + }; + + for (const ProtoVertex& protoV : protoVertices) + { + vertices.push_back(SWavesVertex + { + calculatePosition(std::get<0>(protoV.data), std::get<0>(scaledOutmostArr)), + calculatePosition(std::get<1>(protoV.data), std::get<1>(scaledOutmostArr)), + calculatePosition(std::get<2>(protoV.data), std::get<2>(scaledOutmostArr)), + calculatePosition(std::get<3>(protoV.data), std::get<3>(scaledOutmostArr)), + perp, + {static_cast(a), protoV.index, 0} + }); + } + + CBoundingBoxAligned ret; + ret += (vertices.end() - 9)->m_SplashPosition; + ret += (vertices.end() - 9)->m_BasePosition; + ret += (vertices.end() - 1)->m_SplashPosition; + ret += (vertices.end() - 1)->m_BasePosition; + ret += (vertices.end() - 5)->m_ApexPosition; + return ret; +} + // This requires m_DistanceHeightmap to be defined properly. void WaterManager::CreateWaveMeshes() { @@ -689,85 +767,8 @@ perp /= nb; perp = CVector2D(-perp.Y,perp.X).Normalized(); - SWavesVertex point[9]; - - float baseHeight = 0.04f; - - float halfWidth = (width-1.0f)/2.0f; - float sideNess = sqrtf(Clamp( (halfWidth - fabsf(a - halfWidth)) / 3.0f, 0.0f, 1.0f)); - - point[0].m_UV[0] = a; point[0].m_UV[1] = 8; - point[1].m_UV[0] = a; point[1].m_UV[1] = 7; - point[2].m_UV[0] = a; point[2].m_UV[1] = 6; - point[3].m_UV[0] = a; point[3].m_UV[1] = 5; - point[4].m_UV[0] = a; point[4].m_UV[1] = 4; - point[5].m_UV[0] = a; point[5].m_UV[1] = 3; - point[6].m_UV[0] = a; point[6].m_UV[1] = 2; - point[7].m_UV[0] = a; point[7].m_UV[1] = 1; - point[8].m_UV[0] = a; point[8].m_UV[1] = 0; - - point[0].m_PerpVect = perp; - point[1].m_PerpVect = perp; - point[2].m_PerpVect = perp; - point[3].m_PerpVect = perp; - point[4].m_PerpVect = perp; - point[5].m_PerpVect = perp; - point[6].m_PerpVect = perp; - point[7].m_PerpVect = perp; - point[8].m_PerpVect = perp; - - static const float perpT1[9] = { 6.0f, 6.05f, 6.1f, 6.2f, 6.3f, 6.4f, 6.5f, 6.6f, 9.7f }; - static const float perpT2[9] = { 2.0f, 2.1f, 2.2f, 2.3f, 2.4f, 3.0f, 3.3f, 3.6f, 9.5f }; - static const float perpT3[9] = { 1.1f, 0.7f, -0.2f, 0.0f, 0.6f, 1.3f, 2.2f, 3.6f, 9.0f }; - static const float perpT4[9] = { 2.0f, 2.1f, 1.2f, 1.5f, 1.7f, 1.9f, 2.7f, 3.8f, 9.0f }; - - static const float heightT1[9] = { 0.0f, 0.2f, 0.5f, 0.8f, 0.9f, 0.85f, 0.6f, 0.2f, 0.0 }; - static const float heightT2[9] = { -0.8f, -0.4f, 0.0f, 0.1f, 0.1f, 0.03f, 0.0f, 0.0f, 0.0 }; - static const float heightT3[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0 }; - - for (size_t t = 0; t < 9; ++t) - { - float terrHeight = 0.05f + terrain->GetExactGroundLevel(pos.X+sign*perp.X*(perpT1[t]+outmost), - pos.Y+sign*perp.Y*(perpT1[t]+outmost)); - point[t].m_BasePosition = CVector3D(pos.X+sign*perp.X*(perpT1[t]+outmost), baseHeight + heightT1[t]*sideNess + std::max(m_WaterHeight,terrHeight), - pos.Y+sign*perp.Y*(perpT1[t]+outmost)); - } - for (size_t t = 0; t < 9; ++t) - { - float terrHeight = 0.05f + terrain->GetExactGroundLevel(pos.X+sign*perp.X*(perpT2[t]+outmost), - pos.Y+sign*perp.Y*(perpT2[t]+outmost)); - point[t].m_ApexPosition = CVector3D(pos.X+sign*perp.X*(perpT2[t]+outmost), baseHeight + heightT1[t]*sideNess + std::max(m_WaterHeight,terrHeight), - pos.Y+sign*perp.Y*(perpT2[t]+outmost)); - } - for (size_t t = 0; t < 9; ++t) - { - float terrHeight = 0.05f + terrain->GetExactGroundLevel(pos.X+sign*perp.X*(perpT3[t]+outmost*sideNess), - pos.Y+sign*perp.Y*(perpT3[t]+outmost*sideNess)); - point[t].m_SplashPosition = CVector3D(pos.X+sign*perp.X*(perpT3[t]+outmost*sideNess), baseHeight + heightT2[t]*sideNess + std::max(m_WaterHeight,terrHeight), pos.Y+sign*perp.Y*(perpT3[t]+outmost*sideNess)); - } - for (size_t t = 0; t < 9; ++t) - { - float terrHeight = 0.05f + terrain->GetExactGroundLevel(pos.X+sign*perp.X*(perpT4[t]+outmost), - pos.Y+sign*perp.Y*(perpT4[t]+outmost)); - point[t].m_RetreatPosition = CVector3D(pos.X+sign*perp.X*(perpT4[t]+outmost), baseHeight + heightT3[t]*sideNess + std::max(m_WaterHeight,terrHeight), - pos.Y+sign*perp.Y*(perpT4[t]+outmost)); - } - - vertices.push_back(point[8]); - vertices.push_back(point[7]); - vertices.push_back(point[6]); - vertices.push_back(point[5]); - vertices.push_back(point[4]); - vertices.push_back(point[3]); - vertices.push_back(point[2]); - vertices.push_back(point[1]); - vertices.push_back(point[0]); - - shoreWave->m_AABB += point[8].m_SplashPosition; - shoreWave->m_AABB += point[8].m_BasePosition; - shoreWave->m_AABB += point[0].m_SplashPosition; - shoreWave->m_AABB += point[0].m_BasePosition; - shoreWave->m_AABB += point[4].m_ApexPosition; + shoreWave->m_AABB += AddShoreVertices(vertices, *terrain, m_WaterHeight, outmost, + sign, width, a, perp, pos); } if (sign == 1)