Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
shdlegacyw3d.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 : WWSHADE *
24 * *
25 * $Archive:: wwshade/shdlegacyw3d.cpp $*
26 * *
27 * $Org Author:: Jani_p
28 *
29 * $Author:: Jani_p
30 *
31 * $Modtime:: 7/12/02 3:12p $*
32 * *
33 * $Revision:: 1 $*
34 * *
35 *---------------------------------------------------------------------------------------------*
36 * Functions: *
37 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
38
39#include <d3dx8math.h>
40#include "dx8fvf.h"
41#include "dx8wrapper.h"
42#include "assetmgr.h"
43
44#include "shdlegacyw3d.h"
45
46#include "editable.h"
47#include "chunkio.h"
48#include "w3d_util.h"
49#include "persistfactory.h"
50#include "wwhack.h"
51
52#include "shdclassids.h"
53#include "shddeffactory.h"
54#include "shdinterface.h"
55#include "shdhwshader.h"
56
57
58DECLARE_FORCE_LINK(LegacyW3DShader);
60
61
62// Save-Load methods for ShdDefClass
63enum
64{
66
75
84
86
91
96
105
114
117};
118
119
122 PassCount(0)
123{
124 // init defaults
125 for (int pass_index=0; pass_index < MeshMatDescClass::MAX_PASSES; pass_index++) {
126 memset(&(Shaders[pass_index]),0,sizeof(W3dShaderStruct));
127 memset(&(Materials[pass_index]),0,sizeof(W3dVertexMaterialStruct));
128
129 for (int stage_index=0; stage_index < MeshMatDescClass::MAX_TEX_STAGES; stage_index++) {
130 TextureAttributes[pass_index][stage_index] = 0;
131 MapChannel[pass_index][stage_index] = 0;
132 }
133 }
134}
135
137: ShdDefClass(that),
138 PassCount(that.PassCount)
139{
140 // init defaults
141 for (int pass_index=0; pass_index < MeshMatDescClass::MAX_PASSES; pass_index++) {
142 memset(&(Shaders[pass_index]),0,sizeof(W3dShaderStruct));
143 memset(&(Materials[pass_index]),0,sizeof(W3dVertexMaterialStruct));
144
145 for (int stage_index=0; stage_index < MeshMatDescClass::MAX_TEX_STAGES; stage_index++) {
146 TextureAttributes[pass_index][stage_index] = 0;
147 MapChannel[pass_index][stage_index] = 0;
148 }
149 }
150
151 for (int pass=0;pass<PassCount;++pass) {
152 for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
153 TextureNames[pass][stage]=that.TextureNames[pass][stage];
154 }
155// Shaders[pass]=that.Shaders[pass];
156// Materials[pass]=that.Materials[pass];
157 }
158}
159
163
165{
166 return true;
167}
168
170{
171 for (int pass=0; pass<PassCount; pass++) {
172 for (int stage=0; stage<MeshMatDescClass::MAX_TEX_STAGES; stage++) {
173 if (MapChannel[pass][stage] == i) {
174 return true;
175 }
176 }
177 }
178 return false;
179}
180
182{
183 // Call parent class
184 ShdDefClass::Save(csave);
185
186 // Save our variables
188 Save_Variables(csave);
189 csave.End_Chunk();
190
191 // Save any mapper args and texture names present
192 for (int pass_index=0; pass_index<PassCount; pass_index++) {
193 for (int stage_index=0; stage_index<2; stage_index++) {
194
195 // Write the texture name
196 if (!TextureNames[pass_index][stage_index].Is_Empty()) {
197
198/* (gth) need to save entire path for Max to work properly right???
199 char fname[_MAX_PATH];
200 char extension[_MAX_PATH];
201 _splitpath(TextureNames[pass_index][stage_index].Peek_Buffer(),NULL,NULL,fname,extension);
202 strcat(fname,extension);
203*/
204 int chunk_id = SHDLEGACY_CHUNKID_TEXTURE_NAME00 + pass_index * 2 + stage_index;
205 WRITE_WWSTRING_CHUNK(csave,chunk_id,TextureNames[pass_index][stage_index]);
206 }
207
208 // Write the mapper args
209 if (!MapperArgs[pass_index][stage_index].Is_Empty()) {
210 int chunk_id = SHDLEGACY_CHUNKID_MAPPERARGS00 + pass_index * 2 + stage_index;
211 WRITE_WWSTRING_CHUNK(csave,chunk_id,MapperArgs[pass_index][stage_index])
212 }
213 }
214 }
215
216 return false;
217}
218
220{
221 int offset = 0;
222 int pass = 0;
223 int stage = 0;
224
225 // Call parent class
226 ShdDefClass::Load(cload);
227
228 // Read in the chunks
229 while (cload.Open_Chunk()) {
230 switch (cload.Cur_Chunk_ID())
231 {
233 Load_Variables(cload);
234 break;
235
245 pass = offset / 2;
246 stage = offset % 2;
247 cload.Read(TextureNames[pass][stage].Get_Buffer(cload.Cur_Chunk_Length()),cload.Cur_Chunk_Length());
248 break;
249
259 pass = offset / 2;
260 stage = offset % 2;
261 cload.Read(MapperArgs[pass][stage].Get_Buffer(cload.Cur_Chunk_Length()),cload.Cur_Chunk_Length());
262 break;
263
264 default:
265 break;
266 }
267
268 cload.Close_Chunk();
269 }
270
271 return true;
272}
273
274bool ShdLegacyW3DDefClass::Save_Variables(ChunkSaveClass &csave)
275{
276 WRITE_MICRO_CHUNK(csave, VARID_PASS_COUNT, PassCount);
277
278 for (int pass_index=0; pass_index<PassCount; pass_index++) {
279
280 // Write the shader and vertex material
281 WRITE_MICRO_CHUNK(csave, VARID_SHADER0 + pass_index, Shaders[pass_index]);
282 WRITE_MICRO_CHUNK(csave, VARID_MATERIAL0 + pass_index, Materials[pass_index]);
283
284 for (int stage_index=0; stage_index<2; stage_index++) {
285
286 // Write the texture attributes
287 if (TextureAttributes[pass_index][stage_index] != 0) {
288 WRITE_MICRO_CHUNK(csave, VARID_TEXTURE_ATTRIBUTES00 + pass_index*2 + stage_index, TextureAttributes[pass_index][stage_index]);
289 }
290
291 // Write the map channels
292 if (MapChannel[pass_index][stage_index] != 0) {
293 WRITE_MICRO_CHUNK(csave, VARID_MAPCHANNEL00 + pass_index*2 + stage_index, MapChannel[pass_index][stage_index]);
294 }
295
296 }
297 }
298 return true;
299}
300
301bool ShdLegacyW3DDefClass::Load_Variables(ChunkLoadClass &cload)
302{
303 int offset = 0;
304 int pass = 0;
305 int stage = 0;
306
307 while (cload.Open_Micro_Chunk())
308 {
309 switch (cload.Cur_Micro_Chunk_ID())
310 {
311 READ_MICRO_CHUNK(cload, VARID_PASS_COUNT, PassCount);
312
313 case VARID_SHADER0:
314 case VARID_SHADER1:
315 case VARID_SHADER2:
316 case VARID_SHADER3:
317 pass = cload.Cur_Micro_Chunk_ID() - VARID_SHADER0;
318 cload.Read(&Shaders[pass],sizeof(Shaders[pass]));
319 break;
320
321 case VARID_MATERIAL0:
322 case VARID_MATERIAL1:
323 case VARID_MATERIAL2:
324 case VARID_MATERIAL3:
325 pass = cload.Cur_Micro_Chunk_ID() - VARID_MATERIAL0;
326 cload.Read(&Materials[pass],sizeof(Materials[pass]));
327 break;
328
338 pass = offset / 2;
339 stage = offset % 2;
340 cload.Read(&TextureAttributes[pass][stage],sizeof(TextureAttributes[pass][stage]));
341 break;
342
351 offset = cload.Cur_Micro_Chunk_ID() - VARID_MAPCHANNEL00;
352 pass = offset / 2;
353 stage = offset % 2;
354 cload.Read(&MapChannel[pass][stage],sizeof(MapChannel[pass][stage]));
355 break;
356 }
357
358 cload.Close_Micro_Chunk();
359 }
360 return true;
361}
362
363
368
373
378
381 PassCount(0)
382{
383 int pass;
384 int stage;
385 for (pass=0;pass<MeshMatDescClass::MAX_PASSES;++pass) {
386 Materials[pass]=NULL;
387 for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
388 Textures[pass][stage]=NULL;
389 }
390 }
391
393 PassCount=Definition->Get_Pass_Count();
394
395 for (pass=0;pass<PassCount;++pass) {
396
397 // Set up the shaders
398 W3dUtilityClass::Convert_Shader(Definition->Get_Shader(pass),&(Shaders[pass]));
399
400 // Set up the vertex materials
402 vmat->Parse_W3dVertexMaterialStruct(Definition->Get_Material(pass));
403
404 char * map0_args = NULL;
405 char * map1_args = NULL;
406 if (!Definition->Get_Mapper_Args(pass,0).Is_Empty()) {
407 map0_args = Definition->Get_Mapper_Args(pass,0).Peek_Buffer();
408 }
409 if (!Definition->Get_Mapper_Args(pass,1).Is_Empty()) {
410 map1_args = Definition->Get_Mapper_Args(pass,1).Peek_Buffer();
411 }
412 vmat->Parse_Mapping_Args(Definition->Get_Material(pass),map0_args,map1_args);
413 vmat->Set_UV_Source(0,Definition->Get_Map_Channel(pass,0));
414 vmat->Set_UV_Source(1,Definition->Get_Map_Channel(pass,1));
415 vmat->Set_Lighting(true);
416 REF_PTR_SET(Materials[pass],vmat);
417 REF_PTR_RELEASE(vmat);
418
419 // Set up the textures
420 for (stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
421 StringClass tex_name=Definition->Get_Texture_Name(pass,stage);
422 if (tex_name!="") {
423 Textures[pass][stage]=WW3DAssetManager::Get_Instance()->Get_Texture(tex_name);
424 }
425 else {
426 Textures[pass][stage]=NULL;
427 }
428 }
429 }
430}
431
433{
434 for (int pass=0;pass<PassCount;++pass) {
435 for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
436 REF_PTR_RELEASE(Textures[pass][stage]);
437 }
439 }
440}
441
445
449
451{
452 // By class
453 if (s.Get_Class_ID()!=Get_Class_ID()) {
454 return s.Get_Class_ID()>Get_Class_ID();
455 }
456
457 const Shd6LegacyW3DClass* src=static_cast<const Shd6LegacyW3DClass*>(&s);
458
459 // If same class, sort by textures
460 if (src->Textures[pass][0]!=Textures[pass][0]) {
461 return src->Textures[pass][0]>Textures[pass][0];
462 }
463
464 // If same texture, sort by materials
465 if (src->Materials[pass]!=Materials[pass]) {
466 return src->Materials[pass]>Materials[pass];
467 }
468
469 // If same material, sort by shaders
470 if (src->Shaders[pass].Get_Bits()!=(unsigned)Shaders[pass].Get_Bits()) {
471 return src->Shaders[pass].Get_Bits()>Shaders[pass].Get_Bits();
472 }
473
474 return false;
475}
476
477
478
479/**********************************************************************************************
481
484{
485 SNAPSHOT_SAY(("Shd6LegacyW3DClass::Apply_Shared(pass: %d)\n",pass));
486 // fixed function uses pass through by default
487 DX8Wrapper::Set_DX8_Texture_Stage_State(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU);
488}
489
490//**********************************************************************************************
492
495{
496 SNAPSHOT_SAY(("Shd6LegacyW3DClass::Apply_Instance(pass: %d)\n",cur_pass));
497
498 // set vertex shader
499 StringClass str;
500 SNAPSHOT_SAY(("legacyshader:DX8Wrapper::Set_Shader(%s)\n",Shaders[cur_pass].Get_Description(str)));
502
504
505 SNAPSHOT_SAY(("legacyshader:DX8Wrapper::Set_Material(%s)\n",Materials[cur_pass] ? Materials[cur_pass]->Get_Name() : "NULL"));
507
508 for (int stage=0;stage<MeshMatDescClass::MAX_TEX_STAGES;++stage) {
509 SNAPSHOT_SAY(("legacyshader:DX8Wrapper::Set_Texture(%d,%s)\n",stage,Textures[cur_pass][stage] ? Textures[cur_pass][stage]->Get_Full_Path() : "NULL"));
510 DX8Wrapper::Set_Texture(stage, Textures[cur_pass][stage]);
511 }
512}
513
515{
516 return 1;
517}
518
519unsigned Shd6LegacyW3DClass::Get_Vertex_Size(unsigned stream) const
520{
521 FVFInfoClass fvf_info(FVF);
522 return fvf_info.Get_FVF_Size();
523}
524
526(
527 unsigned stream,
528 void* dest_buffer,
529 const VertexStreamStruct& vss,
530 unsigned vertex_count
531)
532{
533 FVFInfoClass fi(FVF);
534
535 /*
536 ** Append the UV coordinates to the vertex buffer
537 */
538 int uvcount = 0;
539 if ((FVF&D3DFVF_TEX1) == D3DFVF_TEX1) {
540 uvcount = 1;
541 }
542 if ((FVF&D3DFVF_TEX2) == D3DFVF_TEX2) {
543 uvcount = 2;
544 }
545 if ((FVF&D3DFVF_TEX3) == D3DFVF_TEX3) {
546 uvcount = 3;
547 }
548 if ((FVF&D3DFVF_TEX4) == D3DFVF_TEX4) {
549 uvcount = 4;
550 }
551 if ((FVF&D3DFVF_TEX5) == D3DFVF_TEX5) {
552 uvcount = 5;
553 }
554 if ((FVF&D3DFVF_TEX6) == D3DFVF_TEX6) {
555 uvcount = 6;
556 }
557 if ((FVF&D3DFVF_TEX7) == D3DFVF_TEX7) {
558 uvcount = 7;
559 }
560 if ((FVF&D3DFVF_TEX8) == D3DFVF_TEX8) {
561 uvcount = 8;
562 }
563
564 unsigned char* vb=(unsigned char*)dest_buffer;
565
566 for (unsigned i=0; i<vertex_count; ++i)
567 {
568 if ((FVF&D3DFVF_XYZ)==D3DFVF_XYZ) {
569 if (vss.Locations)
570 {
571 *(Vector3*)(vb+fi.Get_Location_Offset())=vss.Locations[i];
572 }
573 else
574 {
575 *(Vector3*)(vb+fi.Get_Location_Offset())=Vector3(0.0f,0.0f,0.0f);
576 }
577 }
578
579 if ((FVF&D3DFVF_DIFFUSE)==D3DFVF_DIFFUSE) {
580 if (vss.DiffuseInt)
581 {
582 *(unsigned int*)(vb+fi.Get_Diffuse_Offset())=vss.DiffuseInt[i];
583 }
584 else
585 {
586 *(unsigned int*)(vb+fi.Get_Diffuse_Offset())=0xffffffff;
587 }
588 }
589
590 if ((FVF&D3DFVF_NORMAL)==D3DFVF_NORMAL) {
591 if (vss.Normals)
592 {
593 *(Vector3*)(vb+fi.Get_Normal_Offset())=vss.Normals[i];
594 }
595 else
596 {
597 *(Vector3*)(vb+fi.Get_Normal_Offset())=Vector3(0.0f,0.0f,0.0f);
598 }
599 }
600
601
602 for (int j=0; j<uvcount; j++) {
603 const Vector2*uvs=vss.UV[j];
604 if (uvs) {
605 *(Vector2*)(vb+fi.Get_Tex_Offset(j))=uvs[i];
606 }
607 else {
608 *(Vector2*)(vb+fi.Get_Tex_Offset(j))=Vector2(0.0f,0.0f);
609 }
610 }
611
612 vb+=fi.Get_FVF_Size();
613 }
614}
615
#define NULL
Definition BaseType.h:92
#define WRITE_MICRO_CHUNK(csave, id, var)
Definition chunkio.h:293
#define READ_MICRO_CHUNK(cload, id, var)
Definition chunkio.h:334
#define WRITE_WWSTRING_CHUNK(csave, id, var)
Definition chunkio.h:249
bool Close_Micro_Chunk()
Definition chunkio.cpp:585
bool Close_Chunk()
Definition chunkio.cpp:448
uint32 Cur_Chunk_ID()
Definition chunkio.cpp:484
uint32 Cur_Chunk_Length()
Definition chunkio.cpp:503
uint32 Cur_Micro_Chunk_ID()
Definition chunkio.cpp:622
uint32 Read(void *buf, uint32 nbytes)
Definition chunkio.cpp:692
bool Open_Chunk()
Definition chunkio.cpp:412
bool Open_Micro_Chunk()
Definition chunkio.cpp:557
bool Begin_Chunk(uint32 id)
Definition chunkio.cpp:108
bool End_Chunk()
Definition chunkio.cpp:148
static void Set_Texture(unsigned stage, TextureBaseClass *texture)
static void Set_DX8_Texture_Stage_State(unsigned stage, D3DTEXTURESTAGESTATETYPE state, unsigned value)
Definition dx8wrapper.h:899
static void Set_Vertex_Shader(DWORD vertex_shader)
Definition dx8wrapper.h:719
static void Set_Material(const VertexMaterialClass *material)
static void Set_Shader(const ShaderClass &shader)
unsigned Get_Tex_Offset(unsigned int n) const
Definition dx8fvf.h:274
unsigned Get_FVF_Size() const
Definition dx8fvf.h:280
unsigned Get_Diffuse_Offset() const
Definition dx8fvf.h:277
unsigned Get_Location_Offset() const
Definition dx8fvf.h:269
unsigned Get_Normal_Offset() const
Definition dx8fvf.h:270
unsigned int Get_Bits(void) const
Definition shader.h:263
virtual ~Shd6LegacyW3DClass()
virtual void Copy_Vertex_Stream(unsigned stream, void *dest_buffer, const VertexStreamStruct &vss, unsigned vertex_count)
static void Shutdown()
virtual void Apply_Instance(int cur_pass, RenderInfoClass &rinfo)
Apply per instance states for 1 pass DX6.
Shd6LegacyW3DClass(const ShdDefClass *def)
virtual bool Greater_Than(const ShdInterfaceClass &s, int pass) const
VertexMaterialClass * Materials[MeshMatDescClass::MAX_PASSES]
virtual unsigned Get_Vertex_Stream_Count() const
ShaderClass Shaders[MeshMatDescClass::MAX_PASSES]
virtual void Apply_Shared(int cur_pass, RenderInfoClass &rinfo)
TextureClass * Textures[MeshMatDescClass::MAX_PASSES][MeshMatDescClass::MAX_TEX_STAGES]
virtual unsigned Get_Vertex_Size(unsigned stream) const
ShdDefClass(uint32 class_id)
Definition shddef.cpp:45
virtual bool Load(ChunkLoadClass &cload)
Load this ShdDef from a chunk loader.
Definition shddef.cpp:160
virtual bool Save(ChunkSaveClass &csave)
Serialize this ShdDef into a chunk saver.
Definition shddef.cpp:140
ShdInterfaceClass(const ShdDefClass *def, int class_id)
Constructor.
WWINLINE int Get_Class_ID() const
const ShdDefClass * Definition
virtual bool Uses_UV_Channel(int i) const
virtual bool Load(ChunkLoadClass &cload)
Load this ShdDef from a chunk loader.
virtual bool Save(ChunkSaveClass &csave)
Serialize this ShdDef into a chunk saver.
virtual ShdInterfaceClass * Create() const
virtual void Shutdown()
virtual bool Is_Valid_Config(StringClass &message)
virtual ~ShdLegacyW3DDefClass()
void Set_Lighting(bool lighting)
void Parse_W3dVertexMaterialStruct(const W3dVertexMaterialStruct &vmat)
void Parse_Mapping_Args(const W3dVertexMaterialStruct &vmat, char *mapping0_arg_buffer, char *mapping1_arg_buffer)
void Set_UV_Source(int stage, int array_index)
static void Convert_Shader(const W3dShaderStruct &shader, ShaderClass *set)
Definition w3d_util.cpp:106
virtual TextureClass * Get_Texture(const char *filename, MipCountType mip_level_count=MIP_LEVELS_ALL, WW3DFormat texture_format=WW3D_FORMAT_UNKNOWN, bool allow_compression=true, TextureBaseClass::TexAssetType type=TextureBaseClass::TEX_REGULAR, bool allow_reduction=true)
static WW3DAssetManager * Get_Instance(void)
Definition assetmgr.h:205
#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
@ VARID_DIFFUSE_COLOR
@ VARID_AMBIENT_COLOR
@ SHDDEF_CLASSID_LEGACYW3D
Definition shdclassids.h:54
#define REGISTER_SHDDEF(T, ID, NAME)
@ VARID_SHADER2
@ SHDLEGACY_CHUNKID_TEXTURE_NAME31
@ SHDLEGACY_CHUNKID_MAPPERARGS21
@ VARID_TEXTURE_ATTRIBUTES21
@ VARID_TEXTURE_ATTRIBUTES10
@ VARID_SHADER0
@ VARID_MATERIAL2
@ VARID_TEXTURE_ATTRIBUTES20
@ VARID_MAPCHANNEL30
@ SHDLEGACY_CHUNKID_MAPPERARGS31
@ VARID_MATERIAL3
@ VARID_MATERIAL1
@ VARID_TEXTURE_ATTRIBUTES30
@ SHDLEGACY_CHUNKID_MAPPERARGS30
@ VARID_MAPCHANNEL21
@ VARID_MAPCHANNEL00
@ SHDLEGACY_CHUNKID_TEXTURE_NAME30
@ VARID_MAPCHANNEL20
@ VARID_SHADER3
@ VARID_PASS_COUNT
@ SHDLEGACY_CHUNKID_MAPPERARGS10
@ SHDLEGACY_CHUNKID_MAPPERARGS01
@ VARID_TEXTURE_ATTRIBUTES31
@ VARID_TEXTURE_ATTRIBUTES00
@ VARID_MAPCHANNEL11
@ SHDLEGACY_CHUNKID_TEXTURE_NAME20
@ SHDLEGACY_CHUNKID_TEXTURE_NAME00
@ SHDLEGACY_CHUNKID_TEXTURE_NAME10
@ VARID_MAPCHANNEL10
@ VARID_TEXTURE_ATTRIBUTES11
@ VARID_TEXTURE_ATTRIBUTES01
@ VARID_MAPCHANNEL31
@ SHDLEGACY_CHUNKID_VARIABLES
@ VARID_MAPCHANNEL01
@ VARID_MATERIAL0
@ SHDLEGACY_CHUNKID_TEXTURE_NAME11
@ SHDLEGACY_CHUNKID_MAPPERARGS11
@ VARID_SHADER1
@ SHDLEGACY_CHUNKID_MAPPERARGS00
@ SHDLEGACY_CHUNKID_MAPPERARGS20
@ SHDLEGACY_CHUNKID_TEXTURE_NAME01
@ SHDLEGACY_CHUNKID_TEXTURE_NAME21
const Vector3 * Normals
const Vector2 * UV[MAX_TEXTURE_STAGES]
const unsigned * DiffuseInt
const Vector3 * Locations
#define SNAPSHOT_SAY(x)
Definition ww3d.h:68
#define DECLARE_FORCE_LINK(module)
Definition wwhack.h:48