Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 33 additions & 51 deletions Generals/Code/Libraries/Source/WWVegas/WW3D2/meshmatdesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,8 @@ void MeshMatDescClass::Install_UV_Array(int pass,int stage,Vector2 * uvs,int cou
}


// TheSuperHackers @bugfix Cryo 10/09/2026 Skip null materials to prevent crashes and
// use each vertex's material colors to avoid incorrect ambient/emissive vertex colors.
void MeshMatDescClass::Post_Load_Process(bool lighting_enabled,MeshModelClass * parent)
{
/*
Expand Down Expand Up @@ -680,66 +682,38 @@ void MeshMatDescClass::Post_Load_Process(bool lighting_enabled,MeshModelClass *

if (!ColorArray[0] && !ColorArray[1]) continue; // If no color arrays, we don't have a problem

Vector3 single_diffuse(0.0f,0.0f,0.0f);
Vector3 single_ambient(0.0f,0.0f,0.0f);
Vector3 single_emissive(0.0f,0.0f,0.0f);
float single_opacity=1.0f;
bool single_diffuse_used=true;
bool single_ambient_used=true;
bool single_emissive_used=true;
bool single_opacity_used=true;
bool diffuse_used=false;
bool ambient_used=false;
bool emissive_used=false;
bool opacity_used=false;

Vector3 mtl_diffuse;
Vector3 mtl_ambient;
Vector3 mtl_emissive;
float mtl_opacity = 1.0f;

VertexMaterialClass * prev_mtl = nullptr;
VertexMaterialClass * mtl = Peek_Material(0, pass);
if (mtl) {
mtl->Get_Diffuse(&single_diffuse);
single_opacity = mtl->Get_Opacity();
mtl->Get_Ambient(&single_ambient);
mtl->Get_Emissive(&single_emissive);

if (single_diffuse.X || single_diffuse.Y || single_diffuse.Z) diffuse_used=true;
if (single_ambient.X || single_ambient.Y || single_ambient.Z) ambient_used=true;
if (single_emissive.X || single_emissive.Y || single_emissive.Z) emissive_used=true;
if (single_opacity!=1.0f) opacity_used=true;
}

for (int vidx=0; vidx<VertexCount; vidx++) {
mtl = Peek_Material(vidx,pass);
if (mtl != prev_mtl) {
VertexMaterialClass* prev_mtl = nullptr;
for (int vidx=0; vidx<VertexCount; vidx++)
{
VertexMaterialClass* mtl = Peek_Material(vidx,pass);
if (mtl == nullptr)
{
continue;
}

if (mtl != prev_mtl)
{
prev_mtl = mtl;
Vector3 mtl_diffuse;
Vector3 mtl_ambient;
Vector3 mtl_emissive;
mtl->Get_Diffuse(&mtl_diffuse);
mtl_opacity = mtl->Get_Opacity();
mtl->Get_Ambient(&mtl_ambient);
mtl->Get_Emissive(&mtl_emissive);
}

if (mtl_diffuse.X!=single_diffuse.X || mtl_diffuse.Y!=single_diffuse.Y || mtl_diffuse.Z!=single_diffuse.Z) {
single_diffuse_used=false;
}
if (mtl_ambient.X!=single_ambient.X || mtl_ambient.Y!=single_ambient.Y || mtl_ambient.Z!=single_ambient.Z) {
single_ambient_used=false;
}
if (mtl_emissive.X!=single_emissive.X || mtl_emissive.Y!=single_emissive.Y || mtl_emissive.Z!=single_emissive.Z) {
single_emissive_used=false;
}
if (mtl_opacity!=single_opacity) {
single_opacity_used=false;
}

if (mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z) diffuse_used=true;
if (mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z) ambient_used=true;
if (mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z) emissive_used=true;
if (mtl_opacity!=1.0f) opacity_used=true;
diffuse_used = diffuse_used || mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z;
ambient_used = ambient_used || mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z;
emissive_used = emissive_used || mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z;

if (diffuse_used && ambient_used && emissive_used)
{
break;
}
}
}

// If both DCG and DIG arrays are submitted, multiply them together to DCG channel
Expand All @@ -762,17 +736,25 @@ void MeshMatDescClass::Post_Load_Process(bool lighting_enabled,MeshModelClass *
if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != nullptr)) {
unsigned * diffuse_array = ColorArray[0]->Get_Array();
Vector3 mtl_diffuse;
float mtl_opacity = 1.0f;
Vector3 mtl_ambient;
Vector3 mtl_emissive;
float mtl_opacity;

VertexMaterialClass * prev_mtl = nullptr;
VertexMaterialClass * mtl = Peek_Material(0,pass);

for (int vidx=0; vidx<VertexCount; vidx++) {

mtl = Peek_Material(vidx,pass);
if (mtl == nullptr) {
continue;
}

if (mtl != prev_mtl) {
prev_mtl = mtl;
mtl->Get_Diffuse(&mtl_diffuse);
mtl->Get_Ambient(&mtl_ambient);
mtl->Get_Emissive(&mtl_emissive);
mtl_opacity = mtl->Get_Opacity();
}

Expand Down
157 changes: 71 additions & 86 deletions GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/meshmatdesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,8 @@ void MeshMatDescClass::Install_UV_Array(int pass,int stage,Vector2 * uvs,int cou
}


// TheSuperHackers @bugfix Cryo 10/09/2026 Skip null materials to prevent crashes and
// use each vertex's material colors to avoid incorrect ambient/emissive vertex colors.
void MeshMatDescClass::Post_Load_Process(bool lighting_enabled,MeshModelClass * parent)
{
/*
Expand Down Expand Up @@ -682,66 +684,38 @@ void MeshMatDescClass::Post_Load_Process(bool lighting_enabled,MeshModelClass *

if (!ColorArray[0] && !ColorArray[1]) continue; // If no color arrays, we don't have a problem

Vector3 single_diffuse(0.0f,0.0f,0.0f);
Vector3 single_ambient(0.0f,0.0f,0.0f);
Vector3 single_emissive(0.0f,0.0f,0.0f);
float single_opacity=1.0f;
bool single_diffuse_used=true;
bool single_ambient_used=true;
bool single_emissive_used=true;
bool single_opacity_used=true;
bool diffuse_used=false;
bool ambient_used=false;
bool emissive_used=false;
bool opacity_used=false;

Vector3 mtl_diffuse;
Vector3 mtl_ambient;
Vector3 mtl_emissive;
float mtl_opacity = 1.0f;

VertexMaterialClass * prev_mtl = nullptr;
VertexMaterialClass * mtl = Peek_Material(0, pass);
if (mtl) {
mtl->Get_Diffuse(&single_diffuse);
single_opacity = mtl->Get_Opacity();
mtl->Get_Ambient(&single_ambient);
mtl->Get_Emissive(&single_emissive);

if (single_diffuse.X || single_diffuse.Y || single_diffuse.Z) diffuse_used=true;
if (single_ambient.X || single_ambient.Y || single_ambient.Z) ambient_used=true;
if (single_emissive.X || single_emissive.Y || single_emissive.Z) emissive_used=true;
if (single_opacity!=1.0f) opacity_used=true;
}

for (int vidx=0; vidx<VertexCount; vidx++) {
mtl = Peek_Material(vidx,pass);
if (mtl != prev_mtl) {
VertexMaterialClass* prev_mtl = nullptr;
for (int vidx=0; vidx<VertexCount; vidx++)
{
VertexMaterialClass* mtl = Peek_Material(vidx,pass);
if (mtl == nullptr)
{
continue;
}

if (mtl != prev_mtl)
{
prev_mtl = mtl;
Vector3 mtl_diffuse;
Vector3 mtl_ambient;
Vector3 mtl_emissive;
mtl->Get_Diffuse(&mtl_diffuse);
mtl_opacity = mtl->Get_Opacity();
mtl->Get_Ambient(&mtl_ambient);
mtl->Get_Emissive(&mtl_emissive);
}

if (mtl_diffuse.X!=single_diffuse.X || mtl_diffuse.Y!=single_diffuse.Y || mtl_diffuse.Z!=single_diffuse.Z) {
single_diffuse_used=false;
}
if (mtl_ambient.X!=single_ambient.X || mtl_ambient.Y!=single_ambient.Y || mtl_ambient.Z!=single_ambient.Z) {
single_ambient_used=false;
}
if (mtl_emissive.X!=single_emissive.X || mtl_emissive.Y!=single_emissive.Y || mtl_emissive.Z!=single_emissive.Z) {
single_emissive_used=false;
}
if (mtl_opacity!=single_opacity) {
single_opacity_used=false;
}

if (mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z) diffuse_used=true;
if (mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z) ambient_used=true;
if (mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z) emissive_used=true;
if (mtl_opacity!=1.0f) opacity_used=true;
diffuse_used = diffuse_used || mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z;
ambient_used = ambient_used || mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z;
emissive_used = emissive_used || mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z;

if (diffuse_used && ambient_used && emissive_used)
{
break;
}
}
}

// If both DCG and DIG arrays are submitted, multiply them together to DCG channel
Expand All @@ -764,17 +738,25 @@ void MeshMatDescClass::Post_Load_Process(bool lighting_enabled,MeshModelClass *
if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != nullptr)) {
unsigned * diffuse_array = ColorArray[0]->Get_Array();
Vector3 mtl_diffuse;
float mtl_opacity = 1.0f;
Vector3 mtl_ambient;
Vector3 mtl_emissive;
float mtl_opacity;

VertexMaterialClass * prev_mtl = nullptr;
VertexMaterialClass * mtl = Peek_Material(0,pass);

for (int vidx=0; vidx<VertexCount; vidx++) {

mtl = Peek_Material(vidx,pass);
if (mtl == nullptr) {
continue;
}

if (mtl != prev_mtl) {
prev_mtl = mtl;
mtl->Get_Diffuse(&mtl_diffuse);
mtl->Get_Ambient(&mtl_ambient);
mtl->Get_Emissive(&mtl_emissive);
mtl_opacity = mtl->Get_Opacity();
}

Expand Down Expand Up @@ -884,54 +866,57 @@ void MeshMatDescClass::Post_Load_Process(bool lighting_enabled,MeshModelClass *
}
// Set lighting to false if requested in all passes...
else if (set_lighting_to_false) {
Vector3 single_diffuse(0.0f,0.0f,0.0f);
Vector3 single_ambient(0.0f,0.0f,0.0f);
Vector3 single_emissive(0.0f,0.0f,0.0f);
bool diffuse_used=false;
bool ambient_used=false;
bool emissive_used=false;

Vector3 mtl_diffuse;
Vector3 mtl_ambient;
Vector3 mtl_emissive;

VertexMaterialClass * prev_mtl = nullptr;
VertexMaterialClass * mtl = Peek_Material(0, pass);
if (mtl) {
mtl->Get_Diffuse(&single_diffuse);
mtl->Get_Ambient(&single_ambient);
mtl->Get_Emissive(&single_emissive);

if (single_diffuse.X || single_diffuse.Y || single_diffuse.Z) diffuse_used=true;
if (single_ambient.X || single_ambient.Y || single_ambient.Z) ambient_used=true;
if (single_emissive.X || single_emissive.Y || single_emissive.Z) emissive_used=true;
}
VertexMaterialClass* prev_mtl = nullptr;
for (int vidx=0; vidx<VertexCount; vidx++)
{
VertexMaterialClass* mtl = Peek_Material(vidx,pass);
if (mtl == nullptr)
{
continue;
}

for (int vidx=0; vidx<VertexCount; vidx++) {
mtl = Peek_Material(vidx,pass);
if (mtl != prev_mtl) {
if (mtl != prev_mtl)
{
prev_mtl = mtl;
Vector3 mtl_diffuse;
Vector3 mtl_ambient;
Vector3 mtl_emissive;
mtl->Get_Diffuse(&mtl_diffuse);
mtl->Get_Ambient(&mtl_ambient);
mtl->Get_Emissive(&mtl_emissive);
}

if (mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z) diffuse_used=true;
if (mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z) ambient_used=true;
if (mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z) emissive_used=true;
diffuse_used = diffuse_used || mtl_diffuse.X || mtl_diffuse.Y || mtl_diffuse.Z;
ambient_used = ambient_used || mtl_ambient.X || mtl_ambient.Y || mtl_ambient.Z;
emissive_used = emissive_used || mtl_emissive.X || mtl_emissive.Y || mtl_emissive.Z;
Comment thread
CryoTheRenegade marked this conversation as resolved.

if (diffuse_used && ambient_used && emissive_used)
{
break;
}
}
}

if ((DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != nullptr)) {
VertexMaterialClass * prev_mtl = nullptr;
VertexMaterialClass * mtl = Peek_Material(0,pass);
for (int vidx=0; vidx<VertexCount; vidx++) {
mtl = Peek_Material(vidx,pass);
if (mtl != prev_mtl) {
// Turn off lighting only for emissive-only materials using vertex colors.
if (!diffuse_used && !ambient_used && emissive_used &&
(DCGSource[pass] != VertexMaterialClass::MATERIAL) && (ColorArray[0] != nullptr))
{
VertexMaterialClass* prev_mtl = nullptr;
for (int vidx=0; vidx<VertexCount; vidx++)
{
VertexMaterialClass* mtl = Peek_Material(vidx,pass);
if (mtl == nullptr)
{
continue;
}

if (mtl != prev_mtl)
{
prev_mtl = mtl;
// If only emissive is used apply emissive to color channel, set diffuse source to color 1, and turn off lighting
if (!diffuse_used && !ambient_used && emissive_used) {
mtl->Set_Lighting(false);
}
mtl->Set_Lighting(false);
}
}
}
Expand Down
Loading