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 "TerrainTextureEntry.h"
21 :
22 : #include "graphics/MaterialManager.h"
23 : #include "graphics/Terrain.h"
24 : #include "graphics/TerrainProperties.h"
25 : #include "graphics/TerrainTextureManager.h"
26 : #include "graphics/TextureManager.h"
27 : #include "lib/utf8.h"
28 : #include "ps/CLogger.h"
29 : #include "ps/CStrInternStatic.h"
30 : #include "ps/Filesystem.h"
31 : #include "ps/XML/Xeromyces.h"
32 : #include "renderer/Renderer.h"
33 : #include "renderer/SceneRenderer.h"
34 :
35 : #include <map>
36 :
37 0 : CTerrainTextureEntry::CTerrainTextureEntry(CTerrainPropertiesPtr properties, const VfsPath& path):
38 : m_pProperties(properties),
39 : m_BaseColor(0),
40 0 : m_BaseColorValid(false)
41 : {
42 0 : ENSURE(properties);
43 :
44 0 : CXeromyces XeroFile;
45 0 : if (XeroFile.Load(g_VFS, path, "terrain_texture") != PSRETURN_OK)
46 : {
47 0 : LOGERROR("Terrain xml not found (%s)", path.string8());
48 0 : return;
49 : }
50 :
51 : #define EL(x) int el_##x = XeroFile.GetElementID(#x)
52 : #define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
53 0 : EL(tag);
54 0 : EL(terrain);
55 0 : EL(texture);
56 0 : EL(textures);
57 0 : EL(material);
58 0 : EL(props);
59 0 : EL(alphamap);
60 0 : AT(file);
61 0 : AT(name);
62 : #undef AT
63 : #undef EL
64 :
65 0 : XMBElement root = XeroFile.GetRoot();
66 :
67 0 : if (root.GetNodeName() != el_terrain)
68 : {
69 0 : LOGERROR("Invalid terrain format (unrecognised root element '%s')", XeroFile.GetElementString(root.GetNodeName()));
70 0 : return;
71 : }
72 :
73 0 : std::vector<std::pair<CStr, VfsPath> > samplers;
74 0 : VfsPath alphamap("standard");
75 0 : m_Tag = utf8_from_wstring(path.Basename().string());
76 :
77 0 : XERO_ITER_EL(root, child)
78 : {
79 0 : int child_name = child.GetNodeName();
80 :
81 0 : if (child_name == el_textures)
82 : {
83 0 : XERO_ITER_EL(child, textures_element)
84 : {
85 0 : ENSURE(textures_element.GetNodeName() == el_texture);
86 :
87 0 : CStr name;
88 0 : VfsPath terrainTexturePath;
89 0 : XERO_ITER_ATTR(textures_element, relativePath)
90 : {
91 0 : if (relativePath.Name == at_file)
92 0 : terrainTexturePath = VfsPath("art/textures/terrain") / relativePath.Value.FromUTF8();
93 0 : else if (relativePath.Name == at_name)
94 0 : name = relativePath.Value;
95 : }
96 0 : samplers.emplace_back(name, terrainTexturePath);
97 0 : if (name == str_baseTex.string())
98 0 : m_DiffuseTexturePath = terrainTexturePath;
99 : }
100 :
101 : }
102 0 : else if (child_name == el_material)
103 : {
104 0 : VfsPath mat = VfsPath("art/materials") / child.GetText().FromUTF8();
105 0 : if (CRenderer::IsInitialised())
106 0 : m_Material = g_Renderer.GetSceneRenderer().GetMaterialManager().LoadMaterial(mat);
107 : }
108 0 : else if (child_name == el_alphamap)
109 : {
110 0 : alphamap = child.GetText().FromUTF8();
111 : }
112 0 : else if (child_name == el_props)
113 : {
114 0 : CTerrainPropertiesPtr ret (new CTerrainProperties(properties));
115 0 : ret->LoadXml(child, &XeroFile, path);
116 0 : if (ret) m_pProperties = ret;
117 : }
118 0 : else if (child_name == el_tag)
119 : {
120 0 : m_Tag = child.GetText();
121 : }
122 : }
123 :
124 0 : for (size_t i = 0; i < samplers.size(); ++i)
125 : {
126 0 : CTextureProperties texture(samplers[i].second);
127 0 : texture.SetAddressMode(Renderer::Backend::Sampler::AddressMode::REPEAT);
128 0 : texture.SetAnisotropicFilter(true);
129 :
130 0 : if (CRenderer::IsInitialised())
131 : {
132 0 : CTexturePtr texptr = g_Renderer.GetTextureManager().CreateTexture(texture);
133 0 : m_Material.AddSampler(CMaterial::TextureSampler(samplers[i].first, texptr));
134 : }
135 : }
136 :
137 0 : if (CRenderer::IsInitialised())
138 0 : m_TerrainAlpha = g_TexMan.LoadAlphaMap(alphamap);
139 :
140 0 : float texAngle = 0.f;
141 0 : float texSize = 1.f;
142 :
143 0 : if (m_pProperties)
144 : {
145 0 : m_Groups = m_pProperties->GetGroups();
146 0 : texAngle = m_pProperties->GetTextureAngle();
147 0 : texSize = m_pProperties->GetTextureSize();
148 : }
149 :
150 0 : m_TextureMatrix.SetZero();
151 0 : m_TextureMatrix._11 = cosf(texAngle) / texSize;
152 0 : m_TextureMatrix._13 = -sinf(texAngle) / texSize;
153 0 : m_TextureMatrix._21 = -sinf(texAngle) / texSize;
154 0 : m_TextureMatrix._23 = -cosf(texAngle) / texSize;
155 0 : m_TextureMatrix._44 = 1.f;
156 :
157 0 : GroupVector::iterator it=m_Groups.begin();
158 0 : for (;it!=m_Groups.end();++it)
159 0 : (*it)->AddTerrain(this);
160 : }
161 :
162 0 : CTerrainTextureEntry::~CTerrainTextureEntry()
163 : {
164 0 : for (GroupVector::iterator it=m_Groups.begin();it!=m_Groups.end();++it)
165 0 : (*it)->RemoveTerrain(this);
166 0 : }
167 :
168 : // BuildBaseColor: calculate the root color of the texture, used for coloring minimap, and store
169 : // in m_BaseColor member
170 0 : void CTerrainTextureEntry::BuildBaseColor()
171 : {
172 : // Use the explicit properties value if possible
173 0 : if (m_pProperties && m_pProperties->HasBaseColor())
174 : {
175 0 : m_BaseColor=m_pProperties->GetBaseColor();
176 0 : m_BaseColorValid = true;
177 0 : return;
178 : }
179 :
180 : // Use the texture color if available
181 0 : if (GetTexture()->TryLoad())
182 : {
183 0 : m_BaseColor = GetTexture()->GetBaseColor();
184 0 : m_BaseColorValid = true;
185 : }
186 3 : }
|