Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "Decal.h"
21 :
22 : #include "graphics/Terrain.h"
23 : #include "maths/MathUtil.h"
24 : #include "ps/CStrInternStatic.h"
25 :
26 0 : CModelAbstract* CModelDecal::Clone() const
27 : {
28 0 : CModelDecal* clone = new CModelDecal(m_Terrain, m_Decal);
29 0 : return clone;
30 : }
31 :
32 0 : void CModelDecal::CalcVertexExtents(ssize_t& i0, ssize_t& j0, ssize_t& i1, ssize_t& j1)
33 : {
34 0 : CVector3D corner0(m_Decal.m_OffsetX + m_Decal.m_SizeX/2, 0, m_Decal.m_OffsetZ + m_Decal.m_SizeZ/2);
35 0 : CVector3D corner1(m_Decal.m_OffsetX + m_Decal.m_SizeX/2, 0, m_Decal.m_OffsetZ - m_Decal.m_SizeZ/2);
36 0 : CVector3D corner2(m_Decal.m_OffsetX - m_Decal.m_SizeX/2, 0, m_Decal.m_OffsetZ - m_Decal.m_SizeZ/2);
37 0 : CVector3D corner3(m_Decal.m_OffsetX - m_Decal.m_SizeX/2, 0, m_Decal.m_OffsetZ + m_Decal.m_SizeZ/2);
38 :
39 0 : corner0 = GetTransform().Transform(corner0);
40 0 : corner1 = GetTransform().Transform(corner1);
41 0 : corner2 = GetTransform().Transform(corner2);
42 0 : corner3 = GetTransform().Transform(corner3);
43 :
44 0 : i0 = floor(std::min(std::min(corner0.X, corner1.X), std::min(corner2.X, corner3.X)) / TERRAIN_TILE_SIZE);
45 0 : j0 = floor(std::min(std::min(corner0.Z, corner1.Z), std::min(corner2.Z, corner3.Z)) / TERRAIN_TILE_SIZE);
46 0 : i1 = ceil(std::max(std::max(corner0.X, corner1.X), std::max(corner2.X, corner3.X)) / TERRAIN_TILE_SIZE);
47 0 : j1 = ceil(std::max(std::max(corner0.Z, corner1.Z), std::max(corner2.Z, corner3.Z)) / TERRAIN_TILE_SIZE);
48 :
49 0 : i0 = Clamp<ssize_t>(i0, 0, m_Terrain->GetVerticesPerSide() - 1);
50 0 : j0 = Clamp<ssize_t>(j0, 0, m_Terrain->GetVerticesPerSide() - 1);
51 0 : i1 = Clamp<ssize_t>(i1, 0, m_Terrain->GetVerticesPerSide() - 1);
52 0 : j1 = Clamp<ssize_t>(j1, 0, m_Terrain->GetVerticesPerSide() - 1);
53 0 : }
54 :
55 0 : void CModelDecal::CalcBounds()
56 : {
57 : ssize_t i0, j0, i1, j1;
58 0 : CalcVertexExtents(i0, j0, i1, j1);
59 0 : m_WorldBounds = m_Terrain->GetVertexesBound(i0, j0, i1, j1);
60 0 : }
61 :
62 0 : void CModelDecal::SetTerrainDirty(ssize_t i0, ssize_t j0, ssize_t i1, ssize_t j1)
63 : {
64 : // Check if there's no intersection between the dirty range and this decal
65 : ssize_t bi0, bj0, bi1, bj1;
66 0 : CalcVertexExtents(bi0, bj0, bi1, bj1);
67 0 : if (bi1 < i0 || bi0 > i1 || bj1 < j0 || bj0 > j1)
68 0 : return;
69 :
70 0 : SetDirty(RENDERDATA_UPDATE_VERTICES);
71 : }
72 :
73 0 : void CModelDecal::InvalidatePosition()
74 : {
75 0 : m_PositionValid = false;
76 0 : }
77 :
78 0 : void CModelDecal::ValidatePosition()
79 : {
80 0 : if (m_PositionValid)
81 : {
82 0 : ENSURE(!m_Parent || m_Parent->m_PositionValid);
83 0 : return;
84 : }
85 :
86 0 : if (m_Parent && !m_Parent->m_PositionValid)
87 : {
88 : // Make sure we don't base our calculations on
89 : // a parent animation state that is out of date.
90 0 : m_Parent->ValidatePosition();
91 :
92 : // Parent will recursively call our validation.
93 0 : ENSURE(m_PositionValid);
94 0 : return;
95 : }
96 :
97 0 : m_PositionValid = true;
98 : }
99 :
100 0 : void CModelDecal::SetTransform(const CMatrix3D& transform)
101 : {
102 : // Since decals are assumed to be horizontal and projected downwards
103 : // onto the terrain, use just the Y-axis rotation and the translation
104 0 : CMatrix3D newTransform;
105 0 : newTransform.SetYRotation(transform.GetYRotation() + m_Decal.m_Angle);
106 0 : newTransform.Translate(transform.GetTranslation());
107 :
108 0 : CRenderableObject::SetTransform(newTransform);
109 0 : InvalidatePosition();
110 0 : }
111 :
112 0 : void CModelDecal::RemoveShadows()
113 : {
114 0 : m_Decal.m_Material.AddShaderDefine(str_DISABLE_RECEIVE_SHADOWS, str_1);
115 3 : }
|