Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
meshmatdesc.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 : ww3d *
24 * *
25 * $Archive:: /Commando/Code/ww3d2/meshmatdesc.cpp $*
26 * *
27 * Original Author:: Greg Hjelstrom *
28 * *
29 * $Author:: Greg_h $*
30 * *
31 * $Modtime:: 1/18/02 8:03p $*
32 * *
33 * $Revision:: 28 $*
34 * *
35 *---------------------------------------------------------------------------------------------*
36 * Functions: *
37 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
38
39#include "meshmatdesc.h"
40#include "texture.h"
41#include "vertmaterial.h"
42#include "realcrc.h"
43#include "dx8wrapper.h"
44#include "dx8caps.h"
45#include "meshmdl.h"
46
47
48/**************************************************************************************************
49**
50**
51** MatBufferClass Implementation
52**
53**
54**************************************************************************************************/
57{
58 // add a reference for each pointer that was copied...
59 for (int i=0; i<Count; i++) {
60 if (Array[i]) {
61 Array[i]->Add_Ref();
62 }
63 }
64}
65
67{
68 for (int i=0; i<Count; i++) {
70 }
71}
72
74{
75 REF_PTR_SET(Array[index],mat);
76}
77
79{
80 if (Array[index]) {
81 Array[index]->Add_Ref();
82 }
83 return Array[index];
84}
85
87{
88 return Array[index];
89}
90
91
92/**************************************************************************************************
93**
94**
95** TexBufferClass Implementation
96**
97**
98**************************************************************************************************/
101{
102 // add a reference for each pointer that was copied...
103 for (int i=0; i<Count; i++) {
104 if (Array[i]) {
105 Array[i]->Add_Ref();
106 }
107 }
108}
109
111{
112 for (int i=0;i<Count;i++) {
114 }
115}
116
118{
119 REF_PTR_SET(Array[index],tex);
120}
121
123{
124 if (Array[index]) {
125 Array[index]->Add_Ref();
126 }
127 return Array[index];
128}
129
131{
132 return Array[index];
133}
134
135
136/**************************************************************************************************
137**
138**
139** UVBufferClass Implementation
140**
141**
142**************************************************************************************************/
145{
146 CRC = that.CRC;
147}
148
150{
151 // NOTE: this only works if you've properly called Update_CRC after filling the array
152 return (CRC == that.CRC);
153}
154
156{
157 // NOTE: this only works if you've properly called Update_CRC after filling the array
158 return (CRC == that.CRC);
159}
160
161
163{
164 CRC = CRC_Memory((unsigned char *)Get_Array(),Get_Count() * sizeof(Vector2));
165}
166
167
168
169/**************************************************************************************************
170**
171**
172** MeshMatDescClass Implementation
173**
174**
175**************************************************************************************************/
176ShaderClass MeshMatDescClass::NullShader(0); // Used to mark no shader data
177
179 PassCount(1),
180 VertexCount(0),
181 PolyCount(0)
182{
183 for (int array=0;array < MAX_COLOR_ARRAYS; array++) {
184 ColorArray[array] = NULL;
185 }
186
187 for (int uvarray=0;uvarray<MAX_UV_ARRAYS;uvarray++) {
188 UV[uvarray] = NULL;
189 }
190
191 for (int pass=0; pass < MAX_PASSES; pass++) {
192 for (int stage=0; stage < MAX_TEX_STAGES; stage++) {
193 UVSource[pass][stage] = -1;
194 Texture[pass][stage] = NULL;
195 TextureArray[pass][stage] = NULL;
196 }
199
200 Shader[pass] = 0; //ShaderClass::_PresetOpaqueSolidShader;
201 Material[pass] = NULL;
202 ShaderArray[pass] = NULL;
203 MaterialArray[pass] = NULL;
204 }
205}
206
208 PassCount(1),
209 VertexCount(0),
210 PolyCount(0)
211{
212 int pass;
213 int stage;
214 int array;
215
216 // init everything to NULL
217 for (array=0;array < MAX_COLOR_ARRAYS; array++) {
218 ColorArray[array] = NULL;
219 }
220 for (array=0;array < MAX_UV_ARRAYS; array++) {
221 UV[array] = NULL;
222 }
223
224 for (pass=0; pass < MAX_PASSES; pass++) {
225 for (stage=0; stage < MAX_TEX_STAGES; stage++) {
226 UVSource[pass][stage] = -1;
227 Texture[pass][stage] = NULL;
228 TextureArray[pass][stage] = NULL;
229 }
232
233 Shader[pass] = 0; //ShaderClass::_PresetOpaqueSolidShader;
234 Material[pass] = NULL;
235 ShaderArray[pass] = NULL;
236 MaterialArray[pass] = NULL;
237 }
238
239 *this = that;
240}
241
244{
245 if (this != &that) {
246
247 PassCount = that.PassCount;
249 PolyCount = that.PolyCount;
250
251 for (int array=0; array<MAX_COLOR_ARRAYS; array++) {
252 REF_PTR_SET(ColorArray[array],that.ColorArray[array]);
253 }
254
255 for (int uvarray=0; uvarray<MAX_UV_ARRAYS; uvarray++) {
256 REF_PTR_SET(UV[uvarray],that.UV[uvarray]);
257 }
258
259 for (int pass=0; pass<MAX_PASSES; pass++) {
260 for (int stage=0; stage < MAX_TEX_STAGES; stage++) {
261 UVSource[pass][stage] = that.UVSource[pass][stage];
262 REF_PTR_SET(Texture[pass][stage],that.Texture[pass][stage]);
263
264 // make our own array of texture pointers.
265 REF_PTR_RELEASE(TextureArray[pass][stage]);
266 if (that.TextureArray[pass][stage]) {
267 TextureArray[pass][stage] = NEW_REF(TexBufferClass,(*that.TextureArray[pass][stage]));
268 }
269 }
270
271 DCGSource[pass] = that.DCGSource[pass];
272 DIGSource[pass] = that.DIGSource[pass];
273
274 Shader[pass] = that.Shader[pass];
275 REF_PTR_SET(Material[pass],that.Material[pass]);
276
277 // make our own arrays of shaders and vertex material pointers
278 // NOTE: We don't just add-ref these arrays, we make our own copies.
279 // The only time we add-ref these arrays are when we make alternate material
280 // representations within this mesh... Then we re-use the same arrays in different
281 // passes...
283 if (that.MaterialArray[pass]) {
284 MaterialArray[pass] = NEW_REF(MatBufferClass,(*that.MaterialArray[pass]));
285 }
287 if (that.ShaderArray[pass]) {
289 }
290 }
291 }
292 return *this;
293}
294
296{
297 Reset(0,0,0);
298}
299
301{
302 if (Texture[pass][stage]) {
303 Texture[pass][stage]->Add_Ref();
304 }
305 return Texture[pass][stage];
306}
307
308void MeshMatDescClass::Reset(int polycount,int vertcount,int passcount)
309{
310 PolyCount = polycount;
311 VertexCount = vertcount;
312 PassCount = passcount;
313
314 for (int array=0; array<MAX_COLOR_ARRAYS; array++) {
316 }
317
318 for (int uvarray=0; uvarray<MAX_UV_ARRAYS; uvarray++) {
319 REF_PTR_RELEASE(UV[uvarray]);
320 }
321
322 for (int pass=0;pass<MAX_PASSES;pass++) {
323 for (int stage=0; stage < MAX_TEX_STAGES; stage++) {
324 UVSource[pass][stage] = -1;
325 REF_PTR_RELEASE(Texture[pass][stage]);
326 REF_PTR_RELEASE(TextureArray[pass][stage]);
327 }
328
331 Shader[pass] = 0;
333
336
337 }
338}
339
340void MeshMatDescClass::Init_Alternate(MeshMatDescClass & default_materials,MeshMatDescClass & alternate_materials)
341{
342 // just copy the counts
343 PassCount = default_materials.PassCount;
344 VertexCount = default_materials.VertexCount;
345 PolyCount = default_materials.PolyCount;
346
347 // Color arrays
348 for (int array=0; array<MAX_COLOR_ARRAYS; array++) {
349 if (alternate_materials.ColorArray[array] != NULL) {
350 REF_PTR_SET(ColorArray[array],alternate_materials.ColorArray[array]);
351 } else {
352 REF_PTR_SET(ColorArray[array],default_materials.ColorArray[array]);
353 }
354 }
355
356 // Copy the uv-arrays from the alternate materials to start. Needed uv arrays from
357 // the default material set will be brought over as encountered below
358 for (int i=0; i<alternate_materials.Get_UV_Array_Count(); i++) {
359 REF_PTR_SET(UV[i],alternate_materials.UV[i]);
360 }
361
362 // add-ref the arrays in default_materials except when the same array is present in alternate_materials
363 for (int pass = 0; pass < MAX_PASSES; pass++) {
364 for (int stage = 0; stage < MAX_TEX_STAGES; stage++) {
365
366 // UV Coorindate arrays, Each UVSource[pass][stage] which is -1 in the alternate_materials
367 // but not -1 in the default_materials causes us to copy over a uv array from the default_materials
368 // and set its index into our UVSource array.
369 if (alternate_materials.UVSource[pass][stage] == -1) {
370 if (default_materials.UVSource[pass][stage] != -1) {
371
372 // Look up the uv array in default_materials that we need to bring over.
373 int default_uv_source = default_materials.UVSource[pass][stage];
374 UVBufferClass * uvarray = default_materials.UV[default_uv_source];
375 int found_index = -1;
376
377 // Check if we already have it.
378 for (int i=0; i<Get_UV_Array_Count(); i++) {
379 if (uvarray->Get_CRC() == UV[i]->Get_CRC()) {
380 found_index = i;
381 break;
382 }
383 }
384
385 // If we already have it, just set the source index. Otherwise add-ref it
386 // into a new slot in our uv array and set that index.
387 if (found_index != -1) {
388 UVSource[pass][stage] = found_index;
389 } else {
390 int new_index = Get_UV_Array_Count();
391 REF_PTR_SET(UV[new_index],default_materials.UV[default_uv_source]);
392 UVSource[pass][stage] = new_index;
393 }
394 }
395 } else {
396 UVSource[pass][stage] = alternate_materials.UVSource[pass][stage];
397 }
398
399 // Texture pointer(s): If alternate_materials has either a single texture or an array of textures,
400 // then add-ref only the texture data it contains. Otherwise, add-ref the data in default_materials.
401 if ((alternate_materials.Texture[pass][stage] != NULL) || (alternate_materials.TextureArray[pass][stage])) {
402 REF_PTR_SET(Texture[pass][stage] , alternate_materials.Texture[pass][stage]);
403 REF_PTR_SET(TextureArray[pass][stage] , alternate_materials.TextureArray[pass][stage]);
404 } else {
405 REF_PTR_SET(Texture[pass][stage] , default_materials.Texture[pass][stage]);
406 REF_PTR_SET(TextureArray[pass][stage] , default_materials.TextureArray[pass][stage]);
407 }
408 }
409
410 // Vertex color configuration
411 if (alternate_materials.DCGSource[pass] == VertexMaterialClass::MATERIAL) {
412 DCGSource[pass] = default_materials.DCGSource[pass];
413 } else {
414 DCGSource[pass] = alternate_materials.DCGSource[pass];
415 }
416
417 // Shaders, currently I can't tell if the alternate data has a shader... Can't override the shader for now.
418 Shader[pass] = default_materials.Shader[pass];
419 REF_PTR_SET(ShaderArray[pass],default_materials.ShaderArray[pass]);
420
421 // Vertex Materials. If alternate_materials has either a single or array of materials, then copy them
422 if ((alternate_materials.Material[pass] != NULL) || (alternate_materials.MaterialArray[pass] != NULL)) {
423 REF_PTR_SET(Material[pass],alternate_materials.Material[pass]);
424 REF_PTR_SET(MaterialArray[pass],alternate_materials.MaterialArray[pass]);
425 } else {
426 // Dont share vertex materials! (because the UVSources can be different!)
427 if (default_materials.Material[pass]) {
428 Material[pass] = NEW_REF(VertexMaterialClass,(*(default_materials.Material[pass])));
429 } else {
430 if (default_materials.MaterialArray[pass]) {
431 WWDEBUG_SAY(("Unimplemented case: mesh has more than one default vertex material but no alternate vertex materials have been defined.\r\n"));
432 }
433 Material[pass] = NULL;
434 }
435 }
436 }
437}
438
440{
441 for (int array=0; array<MAX_COLOR_ARRAYS; array++) {
442 if (ColorArray[array] != NULL) return false;
443 }
444
445 for (int uvarray=0; uvarray<MAX_UV_ARRAYS; uvarray++) {
446 if (UV[uvarray] != NULL) return false;
447 }
448
449 for (int pass=0; pass<MAX_PASSES; pass++) {
450 for (int stage=0; stage<MAX_TEX_STAGES; stage++) {
451 if (Texture[pass][stage] != NULL) return false;
452 if (TextureArray[pass][stage] != NULL) return false;
453 }
454
455// if (UVIndex[pass] != NULL) return false;
456 if (Material[pass] != NULL) return false;
457 if (MaterialArray[pass] != NULL) return false;
458
459 }
460
461 return true;
462}
463
465{
466 REF_PTR_SET(Material[pass],vmat);
467}
468
470{
471 REF_PTR_SET(Texture[pass][stage],tex);
472}
473
475{
476 Shader[pass] = shader;
477}
478
480{
481 MatBufferClass * mats = Get_Material_Array(pass,true);
482 mats->Set_Element(vidx,vmat);
483}
484
485void MeshMatDescClass::Set_Shader(int pidx,ShaderClass shader,int pass)
486{
487 ShaderClass * shaders = Get_Shader_Array(pass,true);
488 shaders[pidx] = shader;
489}
490
491void MeshMatDescClass::Set_Texture(int pidx,TextureClass * tex,int pass,int stage)
492{
493 TexBufferClass * textures = Get_Texture_Array(pass,stage,true);
494 textures->Set_Element(pidx,tex);
495}
496
498{
499 if (MaterialArray[pass]) {
500
501 return MaterialArray[pass]->Get_Element(vidx);
502
503 } else if (Material[pass] != NULL) {
504
505 Material[pass]->Add_Ref();
506 return Material[pass];
507
508 }
509 return NULL;
510}
511
513{
514 if (ShaderArray[pass]) {
515 return ShaderArray[pass]->Get_Element(pidx);
516 }
517 return Shader[pass];
518}
519
520TextureClass * MeshMatDescClass::Get_Texture(int pidx,int pass,int stage) const
521{
522 if (TextureArray[pass][stage]) {
523
524 return TextureArray[pass][stage]->Get_Element(pidx);
525
526 } else if (Texture[pass][stage] != NULL) {
527
528 Texture[pass][stage]->Add_Ref();
529 return Texture[pass][stage];
530
531 }
532 return NULL;
533}
534
536{
537 if (MaterialArray[pass]) {
538 return MaterialArray[pass]->Peek_Element(vidx);
539 }
540 return Material[pass];
541}
542
543TextureClass * MeshMatDescClass::Peek_Texture(int pidx,int pass,int stage) const
544{
545 if (TextureArray[pass][stage]) {
546 return TextureArray[pass][stage]->Peek_Element(pidx);
547 }
548 return Texture[pass][stage];
549}
550
552{
553 if (create && TextureArray[pass][stage] == NULL) {
554 TextureArray[pass][stage] = NEW_REF(TexBufferClass,(PolyCount, "MeshMatDescClass::TextureArray"));
555 }
556 return TextureArray[pass][stage];
557}
558
560{
561 if (create && MaterialArray[pass] == NULL) {
562 MaterialArray[pass] = NEW_REF(MatBufferClass,(VertexCount, "MeshMatDescClass::MaterialArray"));
563 }
564 return MaterialArray[pass];
565}
566
568{
569 if (create && ShaderArray[pass] == NULL) {
570 ShaderArray[pass] = NEW_REF(ShareBufferClass<ShaderClass>,(PolyCount, "MeshMatDescClass::ShaderArray"));
571 ShaderArray[pass]->Clear();
572 }
573 if (ShaderArray[pass]) {
574 return ShaderArray[pass]->Get_Array();
575 }
576 return NULL;
577}
578
580{
581 int uvindex = UVSource[pass][stage];
582 if (UV[uvindex]->Num_Refs() > 1) {
583 UVBufferClass * unique_uv = NEW_REF(UVBufferClass,(*UV[uvindex]));
584 UV[uvindex]->Release_Ref();
585 UV[uvindex] = unique_uv;
586 }
587}
588
590{
591 if ((ColorArray[array] != NULL) && (ColorArray[array]->Num_Refs() > 1)) {
593 ColorArray[array]->Release_Ref();
594 ColorArray[array] = unique_color_array;
595 }
596}
597
598void MeshMatDescClass::Install_UV_Array(int pass,int stage,Vector2 * uvs,int count)
599{
600 /*
601 ** Compute the crc of this uv array
602 */
603 unsigned int crc = CRC_Memory((unsigned char *)uvs,count * sizeof(Vector2));
604
605 /*
606 ** See if there is an existing uv-array that matches the one just loaded
607 */
608 bool found = false;
609
610 for (int i=0; i<Get_UV_Array_Count(); i++) {
611 if (UV[i]->Get_CRC() == crc) {
612 found = true;
613 Set_UV_Source(pass,stage,i);
614 break;
615 }
616 }
617
618 /*
619 ** If there was no existing uv array, install this one
620 */
621 if (found == false) {
622
623 /*
624 ** Find the first empty UV-array slot
625 */
626 int new_index = 0;
627 while ((UV[new_index] != NULL) && (new_index < MAX_UV_ARRAYS)) {
628 new_index++;
629 }
630
631 if (new_index < MAX_UV_ARRAYS) {
632
633 WWASSERT(UV[new_index] == NULL);
634 UV[new_index] = NEW_REF(UVBufferClass,(count, "MeshMatDescClass::UV"));
635 memcpy(UV[new_index]->Get_Array(),uvs,count * sizeof(Vector2));
636 UV[new_index]->Update_CRC(); // update the crc for future comparision
637 Set_UV_Source(pass,stage,new_index);
638 }
639 }
640}
641
642
643void MeshMatDescClass::Post_Load_Process(bool lighting_enabled,MeshModelClass * parent)
644{
645 /*
646 ** Configure all vertex materials to source the uv coordinates and colors from the correct arrays
647 ** Pre-multiply the vertex color arrays.
648 */
649 bool set_lighting_to_false=true;
650 for (int pass=0; pass<PassCount; pass++) {
651
652 /*
653 ** If this pass doesn't have a vertex material, create one
654 */
655 if ((Material[pass] == NULL) && (MaterialArray[pass] == NULL)) {
657 }
658
659 /*
660 ** Configure the materials to source the uv coordinates and colors
661 */
662 if (Material[pass] != NULL) {
663
664 Configure_Material(Material[pass],pass,lighting_enabled);
665
666 } else {
667 VertexMaterialClass * prev_mtl = NULL;
668 VertexMaterialClass * mtl = Peek_Material(pass,0);
669
670 for (int vidx=0; vidx<VertexCount; vidx++) {
671
672 mtl = Peek_Material(vidx,pass);
673 if ((mtl != prev_mtl) && (mtl != NULL)) {
674 Configure_Material(mtl,pass,lighting_enabled);
675 prev_mtl = mtl;
676 }
677 }
678 }
679
680 // Analyze material array types and apply hacks for supporting SR-lighting pipeline if possible.
681
682 if (!ColorArray[0] && !ColorArray[1]) continue; // If no color arrays, we don't have a problem
683
684 Vector3 single_diffuse(0.0f,0.0f,0.0f);
685 Vector3 single_ambient(0.0f,0.0f,0.0f);
686 Vector3 single_emissive(0.0f,0.0f,0.0f);
687 float single_opacity=1.0f;
688 bool single_diffuse_used=true;
689 bool single_ambient_used=true;
690 bool single_emissive_used=true;
691 bool single_opacity_used=true;
692 bool diffuse_used=false;
693 bool ambient_used=false;
694 bool emissive_used=false;
695 bool opacity_used=false;
696
697 Vector3 mtl_diffuse;
698 Vector3 mtl_ambient;
699 Vector3 mtl_emissive;
700 float mtl_opacity = 1.0f;
701
702 VertexMaterialClass * prev_mtl = NULL;
703 VertexMaterialClass * mtl = Peek_Material(0, pass);
704 if (mtl) {
705 mtl->Get_Diffuse(&single_diffuse);
706 single_opacity = mtl->Get_Opacity();
707 mtl->Get_Ambient(&single_ambient);
708 mtl->Get_Emissive(&single_emissive);
709
710 if (single_diffuse.X || single_diffuse.Y || single_diffuse.Z) diffuse_used=true;
711 if (single_ambient.X || single_ambient.Y || single_ambient.Z) ambient_used=true;
712 if (single_emissive.X || single_emissive.Y || single_emissive.Z) emissive_used=true;
713 if (single_opacity!=1.0f) opacity_used=true;
714 }
715
716 for (int vidx=0; vidx<VertexCount; vidx++) {
717 mtl = Peek_Material(vidx,pass);
718 if (mtl != prev_mtl) {
719 prev_mtl = mtl;
720 mtl->Get_Diffuse(&mtl_diffuse);
721 mtl_opacity = mtl->Get_Opacity();
722 mtl->Get_Ambient(&mtl_ambient);
723 mtl->Get_Emissive(&mtl_emissive);
724 }
725
726 if (mtl_diffuse.X!=single_diffuse.X || mtl_diffuse.Y!=single_diffuse.Y || mtl_diffuse.Z!=single_diffuse.Z) {
727 single_diffuse_used=false;
728 }
729 if (mtl_ambient.X!=single_ambient.X || mtl_ambient.Y!=single_ambient.Y || mtl_ambient.Z!=single_ambient.Z) {
730 single_ambient_used=false;
731 }
732 if (mtl_emissive.X!=single_emissive.X || mtl_emissive.Y!=single_emissive.Y || mtl_emissive.Z!=single_emissive.Z) {
733 single_emissive_used=false;
734 }
735 if (mtl_opacity!=single_opacity) {
736 single_opacity_used=false;
737 }
738
739 if (mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z) diffuse_used=true;
740 if (mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z) ambient_used=true;
741 if (mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z) emissive_used=true;
742 if (mtl_opacity!=1.0f) opacity_used=true;
743
744 }
745
746 // If both DCG and DIG arrays are submitted, multiply them together to DCG channel
747 if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != NULL) &&
749 unsigned * diffuse_array = ColorArray[0]->Get_Array();
750 unsigned * emissive_array = ColorArray[1]->Get_Array();
751
752 for (int vidx=0; vidx<VertexCount; vidx++) {
753 Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
754 Vector4 emissive=DX8Wrapper::Convert_Color(emissive_array[vidx]);
755 diffuse.X *= emissive.X;
756 diffuse.Y *= emissive.Y;
757 diffuse.Z *= emissive.Z;
758 diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
759 }
760 }
761 DIGSource[pass]=VertexMaterialClass::MATERIAL; // DIG channel no more
762
763 if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != NULL)) {
764 unsigned * diffuse_array = ColorArray[0]->Get_Array();
765 Vector3 mtl_diffuse;
766 float mtl_opacity = 1.0f;
767
768 VertexMaterialClass * prev_mtl = NULL;
769 VertexMaterialClass * mtl = Peek_Material(0,pass);
770
771 for (int vidx=0; vidx<VertexCount; vidx++) {
772
773 mtl = Peek_Material(vidx,pass);
774 if (mtl != prev_mtl) {
775 prev_mtl = mtl;
776 mtl->Get_Diffuse(&mtl_diffuse);
777 mtl_opacity = mtl->Get_Opacity();
778 }
779
780 // If only diffuse is used apply diffuse to color channel and set diffuse source to color 1
781 if (diffuse_used && !ambient_used && !emissive_used) {
782 Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
783 diffuse.X *= mtl_diffuse.X;
784 diffuse.Y *= mtl_diffuse.Y;
785 diffuse.Z *= mtl_diffuse.Z;
786 diffuse.W *= mtl_opacity;
787 diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
788
792 }
793
794 // If diffuse and ambient are used, apply diffuse to color channel and set diffuse
795 // and ambient sources to color 1. (this is not completely correct if diffuse and
796 // ambient are different but is probably the most reasonable thing to do. Why set
797 // diffuse and ambient differently anyway?)
798 if (diffuse_used && ambient_used && !emissive_used) {
799 Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
800 diffuse.X *= mtl_diffuse.X;
801 diffuse.Y *= mtl_diffuse.Y;
802 diffuse.Z *= mtl_diffuse.Z;
803 diffuse.W *= mtl_opacity;
804 diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
805
809 }
810
811 // If only ambient is used apply ambient to color channel and set ambient source to color 1
812 if (!diffuse_used && ambient_used && !emissive_used) {
813 Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
814 diffuse.X *= mtl_ambient.X;
815 diffuse.Y *= mtl_ambient.Y;
816 diffuse.Z *= mtl_ambient.Z;
817 diffuse.W *= mtl_opacity;
818 diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
819
823 }
824
825 // If only emissive is used apply emissive to color channel, set diffuse source to color 1, and turn off lighting
826 if (!diffuse_used && !ambient_used && emissive_used) {
827 Vector4 diffuse=DX8Wrapper::Convert_Color(diffuse_array[vidx]);
828 diffuse.X *= mtl_emissive.X;
829 diffuse.Y *= mtl_emissive.Y;
830 diffuse.Z *= mtl_emissive.Z;
831 diffuse.W *= mtl_opacity;
832 diffuse_array[vidx]=DX8Wrapper::Convert_Color(diffuse);
833
837// mtl->Set_Lighting(false);
838 }
839 else {
840 if (PassCount!=1) {
841 set_lighting_to_false=false; // Lighting can only be set to false if ALL passes and ALL materials are requesting it
842 }
843 }
844 }
845 }
846 }
847
848
849 /*
850 ** HACK: Kill BUMPENV passes on hardware that doesn't support BUMPENV
851 ** HACK: Set lighting to false on all passes if all passes are of type NO DIFFUSE, NO AMBIENT, YES EMISSIVE
852 */
853 for (pass=0; pass<PassCount; pass++) {
854 bool kill_pass = false;
855
856 /*
857 // HY: Earth and beyond uses a different fallback from Renegade with regards to bump environment maps
858 // we keep the pass but change it to an unbumped environment
859 if ( (Shader[pass].Get_Primary_Gradient() == ShaderClass::GRADIENT_BUMPENVMAP) &&
860 (!DX8Wrapper::Is_Initted() || DX8Wrapper::Get_Current_Caps()->Support_Bump_Envmap() == false) )
861 {
862 kill_pass = true;
863 }
864
865 if ( (Shader[pass].Get_Primary_Gradient() == ShaderClass::GRADIENT_BUMPENVMAPLUMINANCE) &&
866 (!DX8Wrapper::Is_Initted() || DX8Wrapper::Get_Current_Caps()->Support_Bump_Envmap_Luminance() == false) )
867 {
868 kill_pass = true;
869 }
870 */
871
872 if (kill_pass) {
873 if (Material[pass] != NULL) {
874 Material[pass]->Set_Ambient(0,0,0);
875 Material[pass]->Set_Diffuse(0,0,0);
876 Material[pass]->Set_Emissive(0,0,0);
877 Material[pass]->Set_Specular(0,0,0);
878 }
879
880 Shader[pass].Set_Texturing(ShaderClass::TEXTURING_DISABLE);
881 Shader[pass].Set_Post_Detail_Color_Func(ShaderClass::DETAILCOLOR_DISABLE);
882 Shader[pass].Set_Post_Detail_Alpha_Func(ShaderClass::DETAILALPHA_DISABLE);
883 }
884 // Set lighting to false if requested in all passes...
885 else if (set_lighting_to_false) {
886 Vector3 single_diffuse(0.0f,0.0f,0.0f);
887 Vector3 single_ambient(0.0f,0.0f,0.0f);
888 Vector3 single_emissive(0.0f,0.0f,0.0f);
889 bool diffuse_used=false;
890 bool ambient_used=false;
891 bool emissive_used=false;
892
893 Vector3 mtl_diffuse;
894 Vector3 mtl_ambient;
895 Vector3 mtl_emissive;
896
897 VertexMaterialClass * prev_mtl = NULL;
898 VertexMaterialClass * mtl = Peek_Material(0, pass);
899 if (mtl) {
900 mtl->Get_Diffuse(&single_diffuse);
901 mtl->Get_Ambient(&single_ambient);
902 mtl->Get_Emissive(&single_emissive);
903
904 if (single_diffuse.X || single_diffuse.Y || single_diffuse.Z) diffuse_used=true;
905 if (single_ambient.X || single_ambient.Y || single_ambient.Z) ambient_used=true;
906 if (single_emissive.X || single_emissive.Y || single_emissive.Z) emissive_used=true;
907 }
908
909 for (int vidx=0; vidx<VertexCount; vidx++) {
910 mtl = Peek_Material(vidx,pass);
911 if (mtl != prev_mtl) {
912 prev_mtl = mtl;
913 mtl->Get_Diffuse(&mtl_diffuse);
914 mtl->Get_Ambient(&mtl_ambient);
915 mtl->Get_Emissive(&mtl_emissive);
916 }
917
918 if (mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z) diffuse_used=true;
919 if (mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z) ambient_used=true;
920 if (mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z) emissive_used=true;
921 }
922
923 if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != NULL)) {
924 VertexMaterialClass * prev_mtl = NULL;
925 VertexMaterialClass * mtl = Peek_Material(0,pass);
926 for (int vidx=0; vidx<VertexCount; vidx++) {
927 mtl = Peek_Material(vidx,pass);
928 if (mtl != prev_mtl) {
929 prev_mtl = mtl;
930 // If only emissive is used apply emissive to color channel, set diffuse source to color 1, and turn off lighting
931 if (!diffuse_used && !ambient_used && emissive_used) {
932 mtl->Set_Lighting(false);
933 }
934 }
935 }
936 }
937 }
938 }
939}
940
941void MeshMatDescClass::Configure_Material(VertexMaterialClass * mtl,int pass,bool lighting_enabled)
942{
945
946 mtl->Set_Lighting(lighting_enabled);
947
948 for (int stage=0; stage<MAX_TEX_STAGES; stage++) {
949 int src = UVSource[pass][stage];
950 if (src == -1) {
951 src = 0;
952 }
953 mtl->Set_UV_Source(stage,src);
954 }
955}
956
958{
959 if (DX8Wrapper::Is_Initted() && DX8Wrapper::Get_Current_Caps()->Support_NPatches() && WW3D::Get_NPatches_Level()>1) return true;
960
961 for (int pass=0; pass<PassCount; pass++) {
962 /*
963 ** Check the materials on this pass to see if any have mappers which require normals
964 */
965 if (Material[pass] != NULL) {
966
967 if (Material[pass]->Do_Mappers_Need_Normals()) return true;
968
969 } else {
970 VertexMaterialClass * prev_mtl = NULL;
971 VertexMaterialClass * mtl = Peek_Material(pass,0);
972
973 for (int vidx=0; vidx<VertexCount; vidx++) {
974
975 mtl = Peek_Material(vidx,pass);
976 if ((mtl != prev_mtl) && (mtl != NULL)) {
977
978 if (mtl->Do_Mappers_Need_Normals()) return true;
979 prev_mtl = mtl;
980 }
981 }
982 }
983 }
984
985 return false;
986}
#define NULL
Definition BaseType.h:92
#define WWASSERT
unsigned long CRC_Memory(const unsigned char *data, unsigned long length, unsigned long crc)
Definition realcrc.cpp:126
static bool Is_Initted(void)
Definition dx8wrapper.h:270
static const DX8Caps * Get_Current_Caps()
Definition dx8wrapper.h:536
static Vector4 Convert_Color(unsigned color)
Definition dx8wrapper.h:958
VertexMaterialClass * Peek_Element(int index)
VertexMaterialClass * Get_Element(int index)
void Set_Element(int index, VertexMaterialClass *mat)
MatBufferClass(int count, const char *msg)
TextureClass * Texture[MAX_PASSES][MAX_TEX_STAGES]
VertexMaterialClass * Peek_Material(int vidx, int pass=0) const
friend class MeshModelClass
void Install_UV_Array(int pass, int stage, Vector2 *uvs, int count)
TexBufferClass * TextureArray[MAX_PASSES][MAX_TEX_STAGES]
VertexMaterialClass * Material[MAX_PASSES]
MatBufferClass * Get_Material_Array(int pass, bool create=true)
void Set_Texture(int pidx, TextureClass *tex, int pass=0, int stage=0)
ShareBufferClass< ShaderClass > * ShaderArray[MAX_PASSES]
ShaderClass Shader[MAX_PASSES]
TextureClass * Get_Single_Texture(int pass=0, int stage=0) const
void Reset(int polycount, int vertcount, int passcount)
void Set_Single_Texture(TextureClass *tex, int pass=0, int stage=0)
void Set_Shader(int pidx, ShaderClass shader, int pass=0)
VertexMaterialClass::ColorSourceType DCGSource[MAX_PASSES]
TextureClass * Get_Texture(int pidx, int pass=0, int stage=0) const
void Configure_Material(VertexMaterialClass *mtl, int pass, bool lighting_enabled)
ShaderClass Get_Shader(int pidx, int pass=0) const
static ShaderClass NullShader
TexBufferClass * Get_Texture_Array(int pass, int stage, bool create=true)
ShaderClass * Get_Shader_Array(int pass, bool create=true)
int Get_UV_Array_Count(void)
void Post_Load_Process(bool enable_lighting=true, MeshModelClass *parent=NULL)
UVBufferClass * UV[MAX_UV_ARRAYS]
MeshMatDescClass & operator=(const MeshMatDescClass &that)
void Make_Color_Array_Unique(int index)
void Set_UV_Source(int pass, int stage, int sourceindex)
MatBufferClass * MaterialArray[MAX_PASSES]
VertexMaterialClass * Get_Material(int vidx, int pass=0) const
bool Do_Mappers_Need_Normals(void)
void Set_Material(int vidx, VertexMaterialClass *vmat, int pass=0)
void Init_Alternate(MeshMatDescClass &def_mat_desc, MeshMatDescClass &alternate_desc)
void Make_UV_Array_Unique(int pass, int stage)
void Set_Single_Material(VertexMaterialClass *vmat, int pass=0)
TextureClass * Peek_Texture(int pidx, int pass=0, int stage=0) const
bool Is_Empty(void)
void Set_Single_Shader(ShaderClass shader, int pass=0)
VertexMaterialClass::ColorSourceType DIGSource[MAX_PASSES]
ShareBufferClass< unsigned > * ColorArray[2]
int UVSource[MAX_PASSES][MAX_TEX_STAGES]
@ DETAILCOLOR_DISABLE
Definition shader.h:139
@ DETAILALPHA_DISABLE
Definition shader.h:130
@ TEXTURING_DISABLE
Definition shader.h:219
ShareBufferClass(int count, const char *msg)
Definition sharebuf.h:91
Vector2 * Get_Array(void)
Definition sharebuf.h:63
TextureClass * Get_Element(int index)
TexBufferClass(int count, const char *msg)
void Set_Element(int index, TextureClass *mat)
TextureClass * Peek_Element(int index)
void Update_CRC(void)
unsigned int Get_CRC(void)
UVBufferClass(int count, const char *msg)
bool operator==(const UVBufferClass &that)
bool Is_Equal_To(const UVBufferClass &that)
float X
Definition vector3.h:90
float Z
Definition vector3.h:92
float Y
Definition vector3.h:91
float Y
Definition vector4.h:67
float Z
Definition vector4.h:68
float X
Definition vector4.h:66
float W
Definition vector4.h:69
void Set_Lighting(bool lighting)
bool Do_Mappers_Need_Normals(void) const
void Get_Diffuse(Vector3 *set_color) const
void Set_Ambient_Color_Source(ColorSourceType src)
void Get_Emissive(Vector3 *set_color) const
void Get_Ambient(Vector3 *set_color) const
void Set_Emissive_Color_Source(ColorSourceType src)
float Get_Opacity(void) const
void Set_Diffuse_Color_Source(ColorSourceType src)
void Set_UV_Source(int stage, int array_index)
static unsigned Get_NPatches_Level()
Definition ww3d.h:254
#define REF_PTR_RELEASE(x)
Definition refcount.h:80
#define REF_PTR_SET(dst, src)
Definition refcount.h:79
#define NEW_REF(C, P)
Definition refcount.h:62
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114