summaryrefslogtreecommitdiff
path: root/include/nw4r/g3d/g3d_light.h
blob: 2cd6291e1908022d25051487cfcb62359e7a2f2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#ifndef NW4R_G3D_LIGHT_H
#define NW4R_G3D_LIGHT_H
#include <nw4r/types_nw4r.h>

#include "nw4r/g3d/g3d_state.h"
#include "nw4r/g3d/res/g3d_rescommon.h"

#include "rvl/GX.h" // IWYU pragma: export

namespace nw4r {
namespace g3d {

/******************************************************************************
 *
 * LightObj
 *
 ******************************************************************************/
class LightObj {
public:
    LightObj() : mFlag(0) {}
    ~LightObj() {}

    LightObj &operator=(const LightObj &rOther);

    operator GXLightObj *() {
        return &mObj;
    }
    operator const GXLightObj *() const {
        return &mObj;
    }

    void Clear();

    void InitLightColor(GXColor color);
    void InitLightPos(f32 x, f32 y, f32 z);
    void InitLightDir(f32 nx, f32 ny, f32 nz);
    void InitSpecularDir(f32 nx, f32 ny, f32 nz);
    void InitLightSpot(f32 cutoff, GXSpotFn spotFn);
    void InitLightAttnA(f32 aa, f32 ab, f32 ac);
    void InitLightDistAttn(f32 distance, f32 brightness, GXDistAttnFn distAttnFn);
    void InitLightAttnK(f32 ka, f32 kb, f32 kc);
    void InitLightShininess(f32 shininess);

    void GetLightPos(math::VEC3 *pPos) const;
    void GetLightDir(math::VEC3 *pDir) const;

    void ApplyViewMtx(const math::MTX34 &rCamera);

    void Enable() {
        mFlag |= FLAG_ENABLE_LIGHT;
    }
    void Disable() {
        mFlag &= ~FLAG_ENABLE_LIGHT;
    }

    bool IsEnable() const {
        return (mFlag & FLAG_ENABLE_LIGHT) ? true : false;
    }

    bool IsSpotLight() const {
        return (mFlag & FLAG_SPOT) ? true : false;
    }
    bool IsSpecularLight() const {
        return (mFlag & FLAG_SPECULAR) ? true : false;
    }
    bool IsSpecularDir() const {
        return (mFlag & FLAG_SPECULAR_DIR) ? true : false;
    }

    bool IsColorEnable() const {
        return !(mFlag & FLAG_DISABLE_COLOR);
    }
    void DisableColor() {
        mFlag |= FLAG_DISABLE_COLOR;
    }

    bool IsAlphaEnable() const {
        return !(mFlag & FLAG_DISABLE_ALPHA);
    }
    void DisableAlpha() {
        mFlag |= FLAG_DISABLE_ALPHA;
    }

    bool IsDiffuseLight() const {
        return !IsSpotLight() && !IsSpecularLight();
    }

private:
    enum LightObjFlag {
        FLAG_SPOT = (1 << 0),
        FLAG_SPECULAR = (1 << 1),
        FLAG_ENABLE_LIGHT = (1 << 2),
        FLAG_SPECULAR_DIR = (1 << 3),
        FLAG_DISABLE_COLOR = (1 << 4),
        FLAG_DISABLE_ALPHA = (1 << 5)
    };

private:
    u32 mFlag;       // at 0x0
    GXLightObj mObj; // at 0x4
};

/******************************************************************************
 *
 * LightSet
 *
 ******************************************************************************/
struct LightSetData {
    s8 idxLight[G3DState::NUM_LIGHT_IN_LIGHT_SET]; // at 0x0
    s8 idxAmbLight;                                // at 0x8
    u8 PADDING_0x9[0xC - 0X9];                     // at 0x9
};

class LightSet {
public:
    LightSet(LightSetting *pSetting, LightSetData *pData) : mpSetting(pSetting), mpLightSetData(pData) {}
    ~LightSet() {}

    bool IsValid() const {
        return mpSetting != NULL && mpLightSetData != NULL;
    }

    bool SelectLightObj(u32 lightIdx, int lightObjIdx);
    bool SelectAmbLightObj(int lightObjIdx);

private:
    LightSetting *mpSetting;      // at 0x0
    LightSetData *mpLightSetData; // at 0x4
};

/******************************************************************************
 *
 * LightSetting
 *
 ******************************************************************************/
struct AmbLightObj {
    u8 r, g, b, a;
};

class LightSetting {
public:
    LightSetting(
        LightObj *pLightObjArray, AmbLightObj *pAmbLightObjArray, u32 numLight, LightSetData *pLightSetDataArray,
        u32 numLightSet
    );
    ~LightSetting() {}

    bool Import(const LightSetting &rSetting);
    void ApplyViewMtx(const math::MTX34 &rCamera, u32 numLight);

    u32 GetNumLightObj() const {
        return mNumLight;
    }
    u32 GetNumLightSet() const {
        return mNumLightSet;
    }

    LightObj *GetLightObjArray() const {
        return mpLightObjArray;
    }
    AmbLightObj *GetAmbLightObjArray() const {
        return mpAmbLightObjArray;
    }

    LightSet GetLightSet(int idx) {
        if (idx < mNumLightSet && idx >= 0) {
            return LightSet(this, &mpLightSetDataArray[idx]);
        }

        return LightSet(this, NULL);
    }

private:
    u16 mNumLight;                     // at 0x0
    u16 mNumLightSet;                  // at 0x2
    LightObj *mpLightObjArray;         // at 0x4
    AmbLightObj *mpAmbLightObjArray;   // at 0x8
    LightSetData *mpLightSetDataArray; // at 0xC
};

} // namespace g3d
} // namespace nw4r

#endif