Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
metalmap.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : G *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/metalmap.cpp $*
26 * *
27 * $Org Author:: Hector_y $*
28 * *
29 * $Author:: Kenny_m $*
30 * *
31 * $Modtime:: 08/05/02 10:44a $*
32 * *
33 * $Revision:: 4 $*
34 * *
35 * 08/05/02 KM Texture class redesign
36 *---------------------------------------------------------------------------------------------*
37 * Functions: *
38 * MMMC::MetalMapManagerClass -- Create metal map manager according to given metal parameters*
39 * MMMC::MetalMapManagerClass -- Create metal map manager from INI *
40 * MMMC::~MetalMapManagerClass -- MetalMapManagerClass destructor *
41 * MMMC::Get_Metal_Map -- Get the texture for a metal map by id number *
42 * MMMC::Metal_Map_Count -- Get the number of metal maps in the manager *
43 * MMMC::Update_Lighting -- Update the lighting parameters used for generating the maps *
44 * MMMC::Update_Textures -- Update metal map textures (call once/frame before rendering) *
45 * MMMC::initialize_normal_table -- Utility function to initialize the normal table *
46 * MMMC::initialize_metal_params -- Utility function (shared CTor code) *
47 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
48
49#include "metalmap.h"
50#include "texture.h"
51#include "ww3dformat.h"
52#include "ww3d.h"
53#include <vp.h>
54#include <ini.h>
55#include <point.h>
56#include <stdio.h>
57#include <hashtemplate.h>
58#include <wwstring.h>
59#include <wwmath.h>
60
61/*
62** Class static members:
63*/
64Vector3 * MetalMapManagerClass::_NormalTable = 0;
65
66/***********************************************************************************************
67 * MMMC::MetalMapManagerClass -- Create metal map manager from INI *
68 * *
69 * *
70 * INPUT: *
71 * *
72 * OUTPUT: *
73 * *
74 * WARNINGS: *
75 * *
76 * HISTORY: *
77 * 11/23/1999 NH : Created. *
78 *=============================================================================================*/
80 MapCount(0),
81 Textures(0),
82 MetalParameters(0),
83 CurrentAmbient(0.0f, 0.0f, 0.0f),
84 CurrentMainLightColor(0.0f, 0.0f, 0.0f),
85 CurrentMainLightDir(1.0f, 0.0f, 0.0f),
86 CurrentCameraDir(1.0f,0.0f,0.0f),
87 Use16Bit(false)
88{
89
90 // If the static normal table has not been initialized yet, initialize it
91 if (!_NormalTable) {
92 initialize_normal_table();
93 }
94
95 // Determine how many metals are in this file
96 char section[255];
97
98 for (int lp = 0; ; lp++) {
99 sprintf(section, "Metal%02d", lp);
100 if (!ini.Find_Section(section)) {
101 break; // NAK - Mar 8, 2000: changed to a break to fix off by one error in lp
102 }
103 }
104
105 if (lp > 0) {
106 // Create metal params structs and fill from INI:
107 MetalParams *metal_params = W3DNEWARRAY MetalParams[lp];
108 TPoint3D<float> white_tpoint(255.0f, 255.0f, 255.0f);
109 Vector3 white(1.0f, 1.0f, 1.0f);
110 Vector3 black(0.0f, 0.0f, 0.0f);
111 for (int i = 0; i < lp; i++) {
112 sprintf(section, "Metal%02d", i);
113 static const float cf = 0.003921568627451f; // 1 / 255
114 TPoint3D<float> color;
115 color = ini.Get_Point(section, "AmbientColor", white_tpoint);
116 metal_params[i].AmbientColor.Set(color.X * cf, color.Y * cf, color.Z * cf);
117 metal_params[i].AmbientColor.Update_Min(white);
118 metal_params[i].AmbientColor.Update_Max(black);
119 color = ini.Get_Point(section, "DiffuseColor", white_tpoint);
120 metal_params[i].DiffuseColor.Set(color.X * cf, color.Y * cf, color.Z * cf);
121 metal_params[i].AmbientColor.Update_Min(white);
122 metal_params[i].AmbientColor.Update_Max(black);
123 color = ini.Get_Point(section, "SpecularColor", white_tpoint);
124 metal_params[i].SpecularColor.Set(color.X * cf, color.Y * cf, color.Z * cf);
125 metal_params[i].AmbientColor.Update_Min(white);
126 metal_params[i].AmbientColor.Update_Max(black);
127 float shininess = ini.Get_Float(section, "Shininess", 0.0f);
128 metal_params[i].Shininess = WWMath::Clamp(shininess, 0.0f, 127.0f);
129 }
130
131 initialize_metal_params(lp, metal_params);
132 delete [] metal_params;
133 } else {
134 assert(0);
135 }
136
137 int w,h,bits;
138 bool windowed;
139
140 WW3D::Get_Device_Resolution(w,h,bits,windowed);
141 Use16Bit=(bits<=16);
142
144
145
146 for (int i = 0; i < lp; i++) {
148 Textures[i]->Get_Filter().Set_U_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_CLAMP);
149 Textures[i]->Get_Filter().Set_V_Addr_Mode(TextureFilterClass::TEXTURE_ADDRESS_CLAMP);
150 StringClass tex_name;
151 tex_name.Format("!m%02d.tga", i);
152 Textures[i]->Set_Texture_Name(tex_name);
153 }
154}
155
156
157/***********************************************************************************************
158 * MMMC::~MetalMapManagerClass -- MetalMapManagerClass destructor *
159 * *
160 * *
161 * INPUT: *
162 * *
163 * OUTPUT: *
164 * *
165 * WARNINGS: *
166 * *
167 * HISTORY: *
168 * 11/19/1999 NH : Created. *
169 *=============================================================================================*/
171{
172 if (Textures) {
173 for (int i = 0; i < MapCount; i++) {
174 REF_PTR_RELEASE(Textures[i]);
175 }
176 delete [] Textures;
177 Textures = 0;
178 }
179 if (MetalParameters) {
180 delete [] MetalParameters;
181 MetalParameters = 0;
182 }
183}
184
185
186/***********************************************************************************************
187 * MMMC::Get_Metal_Map -- Get the texture for a metal map by id number *
188 * *
189 * *
190 * INPUT: *
191 * *
192 * OUTPUT: *
193 * *
194 * WARNINGS: *
195 * *
196 * HISTORY: *
197 * 11/19/1999 NH : Created. *
198 *=============================================================================================*/
200{
201 if (id < 0 || id >= MapCount) return 0;
202 Textures[id]->Add_Ref();
203 return Textures[id];
204}
205
206
207/***********************************************************************************************
208 * MMMC::Metal_Map_Count -- Get the number of metal maps in the manager *
209 * *
210 * *
211 * INPUT: *
212 * *
213 * OUTPUT: *
214 * *
215 * WARNINGS: *
216 * *
217 * HISTORY: *
218 * 11/19/1999 NH : Created. *
219 *=============================================================================================*/
221{
222 return MapCount;
223}
224
225
226/***********************************************************************************************
227 * MMMC::Update_Lighting -- Update the lighting parameters used for generating the maps *
228 * *
229 * *
230 * INPUT: *
231 * *
232 * OUTPUT: *
233 * *
234 * WARNINGS: *
235 * *
236 * HISTORY: *
237 * 11/19/1999 NH : Created. *
238 *=============================================================================================*/
239void MetalMapManagerClass::Update_Lighting(const Vector3& ambient, const Vector3& main_light_color,
240 const Vector3& main_light_dir, const Vector3& camera_dir)
241{
242 CurrentAmbient = ambient;
243 CurrentMainLightColor = main_light_color;
244 CurrentMainLightDir = main_light_dir;
245 CurrentCameraDir= camera_dir;
246}
247
248/***********************************************************************************************
249 * MMMC::Update_Textures -- Update metal map textures (call once/frame before rendering) *
250 * *
251 * *
252 * INPUT: *
253 * *
254 * OUTPUT: *
255 * *
256 * WARNINGS: *
257 * *
258 * HISTORY: *
259 * 11/19/1999 NH : Created. *
260 *=============================================================================================*/
262{
263 // Currently the lighting is done using a simple Phong (actually Blinn) model.
264 Vector3 &l = CurrentMainLightDir;
265 Vector3 &v = CurrentCameraDir;
266
267 // Calculate halfway vector
268 Vector3 h = l+v;
269 h.Normalize();
270
271 // NOTE: when our lighting equation gets more complicated we might want to do some testing to
272 // detect zero components...
273
274 // Calculate quantities which are the same for all metal maps
275 float n_dot_l[METALMAP_SIZE_2];
276 float n_dot_h[METALMAP_SIZE_2];
277
278 VectorProcessorClass::DotProduct(n_dot_l,l,_NormalTable,METALMAP_SIZE_2);
279 VectorProcessorClass::ClampMin(n_dot_l, n_dot_l, 0.0f, METALMAP_SIZE_2);
280 VectorProcessorClass::DotProduct(n_dot_h,h,_NormalTable, METALMAP_SIZE_2);
281 VectorProcessorClass::ClampMin(n_dot_h, n_dot_h, 0.0f, METALMAP_SIZE_2);
282
283 // Loop over each metal map and update it
284 for (int i = 0; i < MapCount; i++) {
285 MetalParams &cur_params = MetalParameters[i];
286
287 // If shinyness > 1, apply it to specular value array
288 float *specular = 0;
289 float temp_specular[METALMAP_SIZE_2];
290 float shinyness = cur_params.Shininess;
291 if (shinyness > 1.0f) {
292 VectorProcessorClass::Power(temp_specular, n_dot_h, shinyness, METALMAP_SIZE_2);
293 specular = &(temp_specular[0]);
294 } else {
295 specular = &(n_dot_h[0]);
296 }
297
298 // Generate metal map row by row
299 Vector3 specular_color(cur_params.SpecularColor.X * CurrentMainLightColor.X,
300 cur_params.SpecularColor.Y * CurrentMainLightColor.Y,
301 cur_params.SpecularColor.Z * CurrentMainLightColor.Z);
302 Vector3 diffuse_color(cur_params.DiffuseColor.X * CurrentMainLightColor.X,
303 cur_params.DiffuseColor.Y * CurrentMainLightColor.Y,
304 cur_params.DiffuseColor.Z * CurrentMainLightColor.Z);
305 Vector3 ambient_color(cur_params.AmbientColor.X * CurrentAmbient.X,
306 cur_params.AmbientColor.Y * CurrentAmbient.Y,
307 cur_params.AmbientColor.Z * CurrentAmbient.Z);
308 Vector3 white(1.0f, 1.0f, 1.0f);
309
310 SurfaceClass * metal_map_surface = Textures[i]->Get_Surface_Level(0);
311 int pitch;
312 unsigned char *map=(unsigned char *) metal_map_surface->Lock(&pitch);
313 int idx=0;
314 for (int y = 0; y < METALMAP_SIZE; y++) {
315 for (int x = 0; x < METALMAP_SIZE; x++) {
316 Vector3 result = ambient_color + (diffuse_color * n_dot_l[idx]) + (specular_color * specular[idx]);
317 result.Update_Min(white); // Clamp to white
318
319 unsigned char b,g,r,a;
320 b= (unsigned char)WWMath::Floor(result.Z * 255.99f); // B
321 g= (unsigned char)WWMath::Floor(result.Y * 255.99f); // G
322 r= (unsigned char)WWMath::Floor(result.X * 255.99f); // R
323 a= 0xFF; // A
324
325 if (Use16Bit) {
326 unsigned short tmp;
327 tmp=(a&0xf0)<<8;
328 tmp|=(r&0xf0)<<4;
329 tmp|=(g&0xf0);
330 tmp|=(b&0xf0)>>4;
331 *(unsigned short*)&map[2*x]=tmp;
332 } else {
333 map[4*x]=b;
334 map[4*x+1]=g;
335 map[4*x+2]=r;
336 map[4*x+3]=a;
337 }
338 idx++;
339 }
340 map+=pitch;
341 }
342 metal_map_surface->Unlock();
343 REF_PTR_RELEASE(metal_map_surface);
344 } // for i
345}
346
347/***********************************************************************************************
348 * MMMC::initialize_normal_table -- Utility function to initialize the normal table *
349 * *
350 * *
351 * INPUT: *
352 * *
353 * OUTPUT: *
354 * *
355 * WARNINGS: *
356 * *
357 * HISTORY: *
358 * 11/19/1999 NH : Created. *
359 *=============================================================================================*/
360void MetalMapManagerClass::initialize_normal_table(void)
361{
362 // NOTE: changing the actual static _NormalTable member must be the last thing this function
363 // does to avoid synchronization errors.
364
365 static Vector3 _normal_table[METALMAP_SIZE_2];
366
367 // Calculate vectors (area outside sphere should be filled with a radial fill of the vectors at
368 // the sphere's edge to avoid aliasing artifacts)
369 float step = 2.0f / (float)METALMAP_SIZE;
370 int idx = 0;
371 for (int y = 0; y < METALMAP_SIZE; y++) {
372 for (int x = 0; x < METALMAP_SIZE; x++) {
373 Vector3 &normal = _normal_table[idx];
374 // Set vector to point to surface of unit sphere
375 normal.Set((step * (float)x) - 1.0f, (step * (float)y) - 1.0f, 0.0f);
376 float z2 = 1 - ((normal.X * normal.X) + (normal.Y * normal.Y));
377 z2 = MAX(z2, 0.0f); // If outside the sphere, treat as if on its edge
378 normal.Z = sqrt(z2);
379 normal.Normalize(); // Needed for "outside sphere" case and for safety's sake
380
381 idx++;
382 }
383 }
384
385 _NormalTable = &(_normal_table[0]);
386
387}
388
389/***********************************************************************************************
390 * MMMC::initialize_metal_params -- Utility function (shared CTor code) *
391 * *
392 * *
393 * INPUT: *
394 * *
395 * OUTPUT: *
396 * *
397 * WARNINGS: *
398 * *
399 * HISTORY: *
400 * 11/23/1999 NH : Created. *
401 *=============================================================================================*/
402void MetalMapManagerClass::initialize_metal_params(int map_count, MetalParams *metal_params)
403{
404 MapCount = map_count;
405 if (MapCount > 0) {
406 Textures = W3DNEWARRAY TextureClass *[MapCount];
407 MetalParameters = W3DNEWARRAY MetalParams[MapCount];
408
409 for (int i = 0; i < MapCount; i++) {
410
411 // Copy metal parameters (assert if invalid)
412 MetalParameters[i] = metal_params[i];
413 assert(MetalParameters[i].AmbientColor.X >= 0.0f && MetalParameters[i].AmbientColor.X <= 1.0f);
414 assert(MetalParameters[i].AmbientColor.Y >= 0.0f && MetalParameters[i].AmbientColor.Y <= 1.0f);
415 assert(MetalParameters[i].AmbientColor.Z >= 0.0f && MetalParameters[i].AmbientColor.Z <= 1.0f);
416 assert(MetalParameters[i].DiffuseColor.X >= 0.0f && MetalParameters[i].DiffuseColor.X <= 1.0f);
417 assert(MetalParameters[i].DiffuseColor.Y >= 0.0f && MetalParameters[i].DiffuseColor.Y <= 1.0f);
418 assert(MetalParameters[i].DiffuseColor.Z >= 0.0f && MetalParameters[i].DiffuseColor.Z <= 1.0f);
419 assert(MetalParameters[i].SpecularColor.X >= 0.0f && MetalParameters[i].SpecularColor.X <= 1.0f);
420 assert(MetalParameters[i].SpecularColor.Y >= 0.0f && MetalParameters[i].SpecularColor.Y <= 1.0f);
421 assert(MetalParameters[i].SpecularColor.Z >= 0.0f && MetalParameters[i].SpecularColor.Z <= 1.0f);
422 assert(MetalParameters[i].Shininess > 0.0f);
423 }
424 }
425}
Color white
#define W3DNEWARRAY
Definition always.h:110
#define MAX(a, b)
Definition always.h:185
@ false
Definition bool.h:59
Definition INI.H:80
TPoint3D< int > const Get_Point(char const *section, char const *entry, TPoint3D< int > const &defvalue) const
Definition ini.cpp:2080
float Get_Float(char const *section, char const *entry, float defvalue=0.0f) const
Definition ini.cpp:1486
INISection * Find_Section(char const *section) const
Definition ini.cpp:720
int Metal_Map_Count(void)
Definition metalmap.cpp:220
void Update_Lighting(const Vector3 &ambient, const Vector3 &main_light_color, const Vector3 &main_light_dir, const Vector3 &camera_dir)
Definition metalmap.cpp:239
void Update_Textures(void)
Definition metalmap.cpp:261
MetalMapManagerClass(INIClass &ini)
Definition metalmap.cpp:79
TextureClass * Get_Metal_Map(int id)
Definition metalmap.cpp:199
void Add_Ref(void) const
Definition refcount.cpp:171
int _cdecl Format(const TCHAR *format,...)
Definition wwstring.cpp:273
void Unlock(void)
void * Lock(int *pitch)
float X
Definition vector3.h:90
WWINLINE void Update_Max(const Vector3 &a)
Definition vector3.h:617
WWINLINE void Update_Min(const Vector3 &a)
Definition vector3.h:597
float Z
Definition vector3.h:92
float Y
Definition vector3.h:91
void Normalize(void)
Definition vector3.h:417
WWINLINE void Set(float x, float y, float z)
Definition vector3.h:103
static void ClampMin(float *dst, float *src, const float min, const int count)
Definition vp.cpp:529
static void Power(float *dst, float *src, const float pow, const int count)
Definition vp.cpp:535
static void DotProduct(float *dst, const Vector3 &a, const Vector3 *b, const int count)
Definition vp.cpp:523
static void Get_Device_Resolution(int &set_w, int &set_h, int &get_bits, bool &get_windowed)
Definition ww3d.cpp:670
static float Clamp(float val, float min=0.0f, float max=1.0f)
Definition wwmath.h:208
static float Floor(float val)
Definition wwmath.h:153
#define METALMAP_SIZE
Definition metalmap.h:61
#define METALMAP_SIZE_2
Definition metalmap.h:62
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
#define NEW_REF(C, P)
Definition refcount.h:62
@ MIP_LEVELS_1
WW3DFormat
Definition ww3dformat.h:75
@ WW3D_FORMAT_A4R4G4B4
Definition ww3dformat.h:83
@ WW3D_FORMAT_A8R8G8B8
Definition ww3dformat.h:78