summaryrefslogtreecommitdiff
path: root/src/JSystem/JParticle/JPAEmitterManager.cpp
blob: 75b7f86ab6e8cf75c3924fc9eef4a4a238ac819d (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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#include "JSystem/JParticle/JPAList.h"
#include "JSystem/JSupport/JSUList.h"
#include "egg/core/eggHeap.h"
#include "JSystem/JParticle/JPAEmitterManager.h"
#include "JSystem/JParticle/JPAEmitter.h"
#include "JSystem/JParticle/JPAParticle.h"
#include "JSystem/JParticle/JPAResourceManager.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "egg/math/eggVector.h"
#include "rvl/GX/GXTransform.h"
#include "rvl/GX/GXTypes.h"
#include "rvl/GX.h"

JPAEmitterManager::JPAEmitterManager(u32 i_ptclNum, u32 i_emtrNum, EGG::Heap* pHeap, u8 i_gidMax,
                                     u8 i_ridMax) {
    emtrNum = i_emtrNum;
    ptclNum = i_ptclNum;
    gidMax = i_gidMax;
    ridMax = i_ridMax;

    JUT_ASSERT(40, emtrNum && ptclNum && gidMax && ridMax);

    JPABaseEmitter* p_emtr_link = new (pHeap, 4) JPABaseEmitter[emtrNum];
    JUT_ASSERT(44, p_emtr_link);
    for (u32 i = 0; i < emtrNum; i++)
        mFreeEmtrList.prepend(&p_emtr_link[i].mLink);

    JPANode<JPABaseParticle>* p_ptcl_node = new (pHeap, 4) JPANode<JPABaseParticle>[ptclNum];
    JUT_ASSERT(51, p_ptcl_node);
    for (u32 i = 0; i < ptclNum; i++)
        mPtclPool.push_back(&p_ptcl_node[i]);

    pEmtrUseList = new (pHeap, 4) JSUList<JPABaseEmitter>[gidMax];
    JUT_ASSERT(58, pEmtrUseList);
    pResMgrAry = new (pHeap, 4) JPAResourceManager*[ridMax];
    JUT_ASSERT(62, pResMgrAry)
    for (int i = 0; i < ridMax; i++) {
        pResMgrAry[i] = NULL;
    }

    pWd = new (pHeap, 4) JPAEmitterWorkData();
    JUT_ASSERT(67, pWd);
}

JPABaseEmitter* JPAEmitterManager::createSimpleEmitterID(EGG::Vector3f const& pos,
                                                         u16 resID, u8 group_id, u8 res_mgr_id,
                                                         JPAEmitterCallBack* emtrCB,
                                                         JPAParticleCallBack* ptclCB) {
    JUT_ASSERT(88, group_id < gidMax);
    JUT_ASSERT(89, res_mgr_id < ridMax);
    JUT_ASSERT(90, pResMgrAry[res_mgr_id] != NULL);
    JPAResource* pRes = pResMgrAry[res_mgr_id]->getResource(resID);

    if (pRes == NULL) {
        JUT_WARN_DEVICE(94, 3, "JPA : User Index %d is NOT exist\n", resID);
    } else if (mFreeEmtrList.getNumLinks() == 0) {
        JUT_WARN_DEVICE(97, 3, "JPA : Can NOT create emitter more\n");
    } else {
        JSULink<JPABaseEmitter>* pLink = mFreeEmtrList.getFirst();
        mFreeEmtrList.remove(pLink);
        pEmtrUseList[group_id].append(pLink);
        JPABaseEmitter* emtr = pLink->getObject();
        emtr->init(this, pRes);
        emtr->mpPtclPool = &mPtclPool;
        emtr->mpEmtrCallBack = emtrCB;
        emtr->mpPtclCallBack = ptclCB;
        emtr->mGroupID = group_id;
        emtr->mResMgrID = res_mgr_id;
        emtr->mGlobalTrs.set(pos);
        return emtr;
    }

    return NULL;
}

// SS addition
void JPAEmitterManager::fn_80320E20(u8 group_id, f32 of_x, f32 of_z) {
    JSULink<JPABaseEmitter> *pNext = NULL;
    for (JSULink<JPABaseEmitter> *pLink = pEmtrUseList[group_id].getFirst(); pLink != pEmtrUseList[group_id].getEnd();
         pLink = pNext) {
        pNext = pLink->getNext();
        JPABaseEmitter *pEmit = pLink->getObject();

        EGG::Vector3f offset;
        JPANode<JPABaseParticle> *pNextBase = NULL;

        for (JPANode<JPABaseParticle> *baseLink = pEmit->mAlivePtclBase.getFirst();
             baseLink != pEmit->mAlivePtclBase.getEnd(); baseLink = pNextBase) {
            pNextBase = baseLink->getNext();
        
            JPABaseParticle *o = baseLink->getObject();
            o->getOffsetPosition(offset);
            offset.x += of_x;
            offset.z += of_z;
            o->setOffsetPosition(offset);
        }

        for (JPANode<JPABaseParticle> *childLink = pEmit->mAlivePtclChld.getFirst();
             childLink != pEmit->mAlivePtclChld.getEnd(); childLink = pNextBase) {
            pNextBase = childLink->getNext();

            JPABaseParticle *o = childLink->getObject();
            o->getOffsetPosition(offset);
            offset.x += of_x;
            offset.z += of_z;
            o->setOffsetPosition(offset);
        }
    }
}

void JPAEmitterManager::calc(u8 group_id) {
    JUT_ASSERT(154, group_id < gidMax);
    JSULink<JPABaseEmitter>* pNext = NULL;
    for (JSULink<JPABaseEmitter>* pLink = pEmtrUseList[group_id].getFirst();
         pLink != pEmtrUseList[group_id].getEnd(); pLink = pNext) {
        pNext = pLink->getNext();

        JPABaseEmitter* emtr = pLink->getObject();

        if (emtr->pRes->calc(pWd, emtr) && !emtr->checkStatus(0x200))
            forceDeleteEmitter(emtr);
    }
}

void JPAEmitterManager::draw(JPADrawInfo const* drawInfo, u8 group_id) {
    JUT_ASSERT(192, group_id < gidMax);
    drawInfo->getCamMtx(pWd->mPosCamMtx);
    drawInfo->getPrjMtx(pWd->mPrjMtx);
    calcYBBCam();
    GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXEnableTexOffsets(GX_TEXCOORD0, GX_TRUE, GX_TRUE);
    GXEnableTexOffsets(GX_TEXCOORD1, GX_TRUE, GX_TRUE);
    GXEnableTexOffsets(GX_TEXCOORD2, GX_TRUE, GX_TRUE);
    GXSetCullMode(GX_CULL_NONE);
    GXSetCoPlanar(GX_FALSE);
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
    GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
    GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0);
    GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
    GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
    GXSetCurrentMtx(GX_PNMTX0);
    GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE,
                  GX_AF_NONE);
    GXSetChanCtrl(GX_COLOR1A1, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE,
                  GX_AF_NONE);
    GXSetNumChans(0);

    for (JSULink<JPABaseEmitter>* pLink = pEmtrUseList[group_id].getFirst();
         pLink != pEmtrUseList[group_id].getEnd(); pLink = pLink->getNext()) {
        JPABaseEmitter* emtr = pLink->getObject();
        if (!emtr->checkStatus(0x04)) {
            pWd->mpResMgr = pResMgrAry[emtr->mResMgrID];
            emtr->pRes->draw(pWd, emtr);
        }
    }

    GXSetClipMode(GX_CLIP_ENABLE);
}

void JPAEmitterManager::forceDeleteAllEmitter() {
    for (u8 i = 0; i < gidMax; i++)
        forceDeleteGroupEmitter(i);
}

void JPAEmitterManager::forceDeleteGroupEmitter(u8 group_id) {
    JUT_ASSERT(288, group_id < gidMax);
    while (pEmtrUseList[group_id].getNumLinks())
        forceDeleteEmitter(pEmtrUseList[group_id].getLast()->getObject());
}

void JPAEmitterManager::forceDeleteEmitter(JPABaseEmitter* emtr) {
    emtr->deleteAllParticle();
    emtr->setStatus(0x300);
    pEmtrUseList[emtr->getGroupID()].remove(&emtr->mLink);
    mFreeEmtrList.prepend(&emtr->mLink);
}

void JPAEmitterManager::entryResourceManager(JPAResourceManager* resMgr, u8 resMgrID) {
    JUT_ASSERT_MSG_F(325, resMgrID < ridMax && (pResMgrAry[resMgrID]) == NULL,
                     "res_id %d res_id_max %d array[%d] = %x", resMgrID, ridMax, resMgrID,
                     pResMgrAry[resMgrID]);
    pResMgrAry[resMgrID] = resMgr;
}

void JPAEmitterManager::clearResourceManager(u8 res_mgr_id) {
    JUT_ASSERT(339, res_mgr_id < ridMax);
    for (u8 i = 0; i < gidMax; i++) {
        JSULink<JPABaseEmitter>* pNext = NULL;
        for (JSULink<JPABaseEmitter>* pLink = pEmtrUseList[i].getFirst();
             pLink != pEmtrUseList[i].getEnd(); pLink = pNext) {
            pNext = pLink->getNext();

            if (res_mgr_id == pLink->getObject()->getResourceManagerID())
                forceDeleteEmitter(pLink->getObject());
        }
    }

    pResMgrAry[res_mgr_id] = NULL;
}

void JPAEmitterManager::calcYBBCam() {
    EGG::Vector3f v(0.0f, pWd->mPosCamMtx[1][1], pWd->mPosCamMtx[2][1]);
    JUT_ASSERT(367, !v.isZero());
    v.normalise();
    pWd->mYBBCamMtx[0][0] = 1.0f;
    pWd->mYBBCamMtx[0][1] = 0.0f;
    pWd->mYBBCamMtx[0][2] = 0.0f;
    pWd->mYBBCamMtx[0][3] = pWd->mPosCamMtx[0][3];
    pWd->mYBBCamMtx[1][0] = 0.0f;
    pWd->mYBBCamMtx[1][1] = v.y;
    pWd->mYBBCamMtx[1][2] = -v.z;
    pWd->mYBBCamMtx[1][3] = pWd->mPosCamMtx[1][3];
    pWd->mYBBCamMtx[2][0] = 0.0f;
    pWd->mYBBCamMtx[2][1] = v.z;
    pWd->mYBBCamMtx[2][2] = v.y;
    pWd->mYBBCamMtx[2][3] = pWd->mPosCamMtx[2][3];
}