Quantcast

Jump to content

» «
Photo

Mutual exclusion problem of Night Vertex Color and External Illumination...

Best Answer DK22Pac, A week ago

Well, from your experiments you can clearly see that it's not possible to combine dynamic lighting with NVC in original game.

There's a special flag that is used to determ if an object (building/road etc.) can be affected by 'dynamic' lights (vehicle lights, lampposts etc.).
https://github.com/D...a/CEntity.h#L59

You can see how it works @0x553DC0

// 0x553DC0 1.0US, virtual CEntity method ; not overloaded for CBuilding
bool CEntity::SetupLighting() {
    if (!m_nFlags.bLightObject)
        return false;
    ActivateDirectional();
    SetLightColoursForPedsCarsAndObjects(
        CPointLights::GenerateLightsAffectingObject(GetPosition(), nullptr, this) * 0.5f);
    return true;
}
And to understand how this flag is set we should look @0x533EB7
// 0x533EB7 1.0US, CEntity::CreateRwObject +0x187
if (!CCustomBuildingRenderer::IsCBPCPipelineAttached(m_pRwAtomic))
    m_nFlags.bLightObject = true; // set by default to false in CEntity constructor
// 0x5D7F40 1.0US, static method
bool CCustomBuildingRenderer::IsCBPCPipelineAttached(RpAtomic *atomic) {
  int pipelineId = GetPipelineID(atomic);
  return pipelineId == 0x53F2009C // custom (default building) rendering pipeline
      || pipelineId == 0x53F20098 // or custom (day&night lighting) rendering pipeline
      || CCustomBuildingDNPipeline::GetExtraVertColourPtr(atomic->geometry) // or has NVC
      && atomic->geometry->preLitLum); // and has prelit
}
Go to the full post


5 replies to this topic
MMK_033
  • MMK_033

    Потраченн&

  • Members
  • Joined: 05 Apr 2016
  • Russia

#1

Posted A week ago

Good day, here's my problem. I used to export objects with "NOR" option enabled in Kam's DFF IO, it makes them influenced from external light sources. That is, they might be illuminated by sun (with mods), by vehicle lights and street lights, just like peds and cars. I noticed a detail that the objects exported via Kam's DFF IO are considered by the game as "dynamic" objects - they depend from AMB_OBJ timecycle color, not from AMB. Probably illuminability originates from the same cause.

 

But when I add the NVC section in DFF file through RWAnalyze, the night-time colors appear, but that external illumination feature is getting lack (and object becomes "static").

Spoiler

 

The same conflict happens when I use NVCMerge. According to some comparsions with NVCMerge's DFF, the data could be exported to the NVC section and the result could be visible in-game after first 12 bytes of the header is deleted.

Spoiler


 

But either way leads to the same thing - NVC appears, but illumination dependence disappears. Is there any way to add NVC and preserve dependence on external light sources? In the game it looks like this.

02e06a2d7a58.jpg

  • DK22Pac likes this

DK22Pac
  • DK22Pac

    𝘉eчнo 𝘔oлoдoй...

  • Feroci
  • Joined: 12 Apr 2009
  • Ukraine
  • Best WIP Mod 2014 [Grand Theft Auto 3D Contribution]
    Contribution Award [Mods]
    Helpfulness Award [Mods]

#2

Posted A week ago   Best Answer Edited by DK22Pac, A week ago.

Well, from your experiments you can clearly see that it's not possible to combine dynamic lighting with NVC in original game.

There's a special flag that is used to determ if an object (building/road etc.) can be affected by 'dynamic' lights (vehicle lights, lampposts etc.).
https://github.com/D...a/CEntity.h#L59

You can see how it works @0x553DC0
// 0x553DC0 1.0US, virtual CEntity method ; not overloaded for CBuilding
bool CEntity::SetupLighting() {
    if (!m_nFlags.bLightObject)
        return false;
    ActivateDirectional();
    SetLightColoursForPedsCarsAndObjects(
        CPointLights::GenerateLightsAffectingObject(GetPosition(), nullptr, this) * 0.5f);
    return true;
}
And to understand how this flag is set we should look @0x533EB7
// 0x533EB7 1.0US, CEntity::CreateRwObject +0x187
if (!CCustomBuildingRenderer::IsCBPCPipelineAttached(m_pRwAtomic))
    m_nFlags.bLightObject = true; // set by default to false in CEntity constructor
// 0x5D7F40 1.0US, static method
bool CCustomBuildingRenderer::IsCBPCPipelineAttached(RpAtomic *atomic) {
  int pipelineId = GetPipelineID(atomic);
  return pipelineId == 0x53F2009C // custom (default building) rendering pipeline
      || pipelineId == 0x53F20098 // or custom (day&night lighting) rendering pipeline
      || CCustomBuildingDNPipeline::GetExtraVertColourPtr(atomic->geometry) // or has NVC
      && atomic->geometry->preLitLum); // and has prelit
}
  • MMK_033 likes this

MMK_033
  • MMK_033

    Потраченн&

  • Members
  • Joined: 05 Apr 2016
  • Russia

#3

Posted A week ago Edited by MMK_033, A week ago.

I may ask stupid question, but did I get this right if all those return conditions after getting pipeline ID (at 0x5D7F40) return "true" (that is, they don't fit the condition under which the dynamic lighting flag should work)? I'm asking purely for understanding.


DK22Pac
  • DK22Pac

    𝘉eчнo 𝘔oлoдoй...

  • Feroci
  • Joined: 12 Apr 2009
  • Ukraine
  • Best WIP Mod 2014 [Grand Theft Auto 3D Contribution]
    Contribution Award [Mods]
    Helpfulness Award [Mods]

#4

Posted A week ago

I may ask stupid question, but did I get this right if all those return conditions after getting pipeline ID (at 0x5D7F40) return "true" (that is, they don't fit the condition under which the dynamic lighting flag should work)?

Yes. In general, IsCBPCPipelineAttached (I guess 'CBPC' means 'Custom Building PC') returns true if an atomic (RenderWare graphics object) uses static day or day/night lighting.
However, it doesn't check for a case when there's day static lighting only and no pipeline ID attached to atomic. So that could be a way to combine day-only lighting with dynamic lights.
  • MMK_033 likes this

MMK_033
  • MMK_033

    Потраченн&

  • Members
  • Joined: 05 Apr 2016
  • Russia

#5

Posted A week ago Edited by MMK_033, A week ago.

Alright, thanks for the explanation. Although using NVC for a single model appears to be more compact than making an additional night timed object for a main object, and gradual change of brightness of glowing windows seems to be more realistic in comparsion to timed objects which go off instantly, it's still kinda hard for me to choose what is preferable between external dynamic lighting and NVC. Although as an option, I can use timed objects from 20 to 7 (when the transition to/from NVC only begins) or use vertex color for windows in such a way that during the day it would be not very noticeable.


DK22Pac
  • DK22Pac

    𝘉eчнo 𝘔oлoдoй...

  • Feroci
  • Joined: 12 Apr 2009
  • Ukraine
  • Best WIP Mod 2014 [Grand Theft Auto 3D Contribution]
    Contribution Award [Mods]
    Helpfulness Award [Mods]

#6

Posted A week ago

In case if you want to test 'how it would look if', check my example :p

#include "plugin.h"
#include "common.h"
#include "CPointLights.h"

using namespace plugin;

class TestDynamicLightingWithNVC {
public:
    TestDynamicLightingWithNVC() {
        // Remove IsCBPCPipelineAttached() check and set flag 'bLightObject' to 'true' in any case
        patch::Nop(0x533EB7, 13);

        // Generate normals for all loaded models

        static bool bDoINeedToGenerateNormals = false;

        // Check if this model has normals and enable them
        RpGeometry *(*createGeometryCheckNormals)(int, int, unsigned int) = [](int numVerts, int numTriangles, unsigned int format) {
            if (format & rpGEOMETRYNORMALS)
                bDoINeedToGenerateNormals = false;
            else
                bDoINeedToGenerateNormals = true;
            return RpGeometryCreate(numVerts, numTriangles, format|rpGEOMETRYNORMALS);
        };

        // Generate normals (if needed)
        static CdeclEvent<AddressList<0x74D5A8, H_CALL>, PRIORITY_AFTER, ArgPickN<RpGeometry *, 0>, void*(RpGeometry*)> onGeometryLoaded;

        onGeometryLoaded.before += [](RpGeometry *geometry) { // this is called before geometry unlocked, so we don't need to lock it
            if (bDoINeedToGenerateNormals) { // should we generate normals or model already has normals?
                // Use a simple method to generate normals
                for (int i = 0; i < geometry->numMorphTargets; i++) {
                    if (geometry->morphTarget[i].normals) {
                        memset(geometry->morphTarget[i].normals, 0, geometry->numVertices * 12);
                        for (int tri = 0; tri < geometry->numTriangles; tri++) {
                            CVector verts[3], normals[3];
                            for (int v = 0; v < 3; v++) {
                                verts[v].FromRwV3d(geometry->morphTarget[i].verts[geometry->triangles[tri].vertIndex[v]]);
                                normals[v].FromRwV3d(geometry->morphTarget[i].normals[geometry->triangles[tri].vertIndex[v]]);
                            }
                            CVector normal;
                            normal.Cross(verts[0] - verts[1], verts[0] - verts[2]);
                            if (normal.NormaliseAndMag() != 0.0f) {
                                for (int n = 0; n < 3; n++) {
                                    normals[n] += normal;
                                    geometry->morphTarget[i].normals[geometry->triangles[tri].vertIndex[n]] = normals[n].ToRwV3d();
                                }
                            }
                        }
                    }
                }
            }
        };

        patch::RedirectCall(0x74D234, createGeometryCheckNormals);

        Events::gameProcessEvent += [] {
            CPed *playa = FindPlayerPed(0);
            if (playa) {
                // Create a green POINT light at player position when 'G' key pressed
                if (KeyPressed('G'))
                    CPointLights::AddLight(0, FindPlayerCoors(0), CVector(0.0f, 0.0f, 0.0f), 50.0f, 0, 255, 0, 0, false, nullptr);
                // Create a red DIRECT light at player position when 'R' key pressed
                else if (KeyPressed('R')) {
                    CPointLights::AddLight(1, FindPlayerCoors(0), playa->TransformFromObjectSpace(CVector(0.0f, 1.0f, 0.0f)) -
                        playa->TransformFromObjectSpace(CVector(0.0f, 0.0f, 0.0f)), 50.0f, 255, 0, 0, 0, false, nullptr);
                }
            }
        };
    }
} testDynamicLightingWithNVC;
Compiled version: Link
  • MMK_033 likes this




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users