#include "d/col/bg/d_bg_w_kcol.h"

#include "d/col/bg/d_bg_s.h"
#include "d/col/bg/d_bg_s_gnd_chk.h"
#include "d/col/bg/d_bg_s_lin_chk.h"
#include "d/d_sc_game.h"

char STAGE_FS_A[] = "D201";
char STAGE_FS_B[] = "D201_1";
char STAGE_SSH[] = "D301";

dBgWKCol::dBgWKCol() : mpKCHead(nullptr) {
    mNumPrism = 0;
    mpTri = 0;
}

dBgWKCol::~dBgWKCol() {
    mpKCHead = nullptr;
    mpTri = 0;
}

void dBgWKCol::initKCollision(void *pFile) {
    KCol_Header *pHeader = (KCol_Header *)pFile;
    pkcdata *pData = (pkcdata *)pFile;

    pData->mpPositionData = (mVec3_c *)((u32)pFile + pHeader->pos_data_offset);
    pData->mpNormalData = (mVec3_c *)((u32)pFile + pHeader->nrm_data_offset);
    pData->mpPrismData = (KC_PrismData *)((u32)pFile + pHeader->prism_data_offset);
    pData->mpBlockData = (u32 *)((u32)pFile + pHeader->block_data_offset);
}

void dBgWKCol::Set(void *pKcl, void *pPlc) {
    ClrDBgWBase();
    mpKCHead = (pkcdata *)pKcl;
    mNumPrism = ((u32)mpKCHead->mpBlockData - (u32)mpKCHead->mpPrismData) / sizeof(KC_PrismData) + 1;
    mCode.setBase(pPlc);
    // Z,Y,X important?
    f32 z = mpKCHead->mAreaMinPos.z;
    f32 y = mpKCHead->mAreaMinPos.y;
    f32 x = mpKCHead->mAreaMinPos.x;
    u32 mz = mpKCHead->mAreaWidthMaskZ;
    u32 my = mpKCHead->mAreaWidthMaskY;
    u32 mx = mpKCHead->mAreaWidthMaskX;
    mBnd.Set(mVec3_c(x, y, z), mVec3_c(x + ~mx, y + ~my, z + ~mz));

    vt_0x3C();
    mAreaWidthMaskX = ~mpKCHead->mAreaWidthMaskX;
    mAreaWidthMaskY = ~mpKCHead->mAreaWidthMaskY;
    mAreaWidthMaskZ = ~mpKCHead->mAreaWidthMaskZ;
}

void dBgWKCol::GetTriNrm(KC_PrismData *pd, mVec3_c **ppTriNrm) const {
    *ppTriNrm = GetTriNrm(pd);
}

bool dBgWKCol::ChkNotReady() const {
    return mpKCHead == nullptr;
}

bool dBgWKCol::ChkLock() const {
    return false;
}

bool dBgWKCol::ChkMoveBg() const {
    return false;
}

u32 dBgWKCol::ChkMoveFlag() const {
    return 0;
}

void dBgWKCol::GetTriPla(cBgS_PolyInfo const &polyInf, cM3dGPla *plane) const {
    mVec3_c *pFaceNrm;
    KC_PrismData *pPrismData = GetPrismData(polyInf.GetPolyIndex());
    GetTriNrm(pPrismData, &pFaceNrm);

    mVec3_c *pPos = GetTriPos(pPrismData);
    plane->mNormal = *pFaceNrm;
    plane->mD = -VEC3Dot(plane->mNormal, *pPos);
}

bool dBgWKCol::GetTriPnt(cBgS_PolyInfo const &polyInf, mVec3_c *v1, mVec3_c *v2, mVec3_c *v3) const {
    return GetTriPnt(polyInf.GetPolyIndex(), v1, v2, v3);
}

bool dBgWKCol::GetTriPnt(int poly_index, mVec3_c *v1, mVec3_c *v2, mVec3_c *v3) const {
    return GetTriPnt(GetPrismData(poly_index), v1, v2, v3);
}

bool dBgWKCol::GetTriPnt(KC_PrismData const *pPrism, mVec3_c *v1, mVec3_c *v2, mVec3_c *v3) const {
    *v1 = *GetTriPos(pPrism);

    mVec3_c face_nrm1, face_nrm2;
    mVec3_c *pFaceNrm = GetTriNrm(pPrism);
    mVec3_c *pEdgeNrm3 = GetEdgeNrm3(pPrism);
    VEC3Cross(face_nrm1, pFaceNrm, GetEdgeNrm1(pPrism));
    f32 mag = VEC3Dot(face_nrm1, pEdgeNrm3);
    if (cM3d_IsZero(mag)) {
        return false;
    }

    mag = pPrism->mHeight / mag;

    VEC3Scale(face_nrm1, face_nrm1, mag);
    VEC3Add(v3, face_nrm1, v1);

    VEC3Cross(face_nrm2, GetEdgeNrm2(pPrism), pFaceNrm);

    mag = VEC3Dot(face_nrm1, pEdgeNrm3);

    if (cM3d_IsZero(mag)) {
        return false;
    }

    mag = pPrism->mHeight / mag;
    VEC3Scale(face_nrm2, face_nrm2, mag);
    VEC3Add(v2, face_nrm2, v1);

    return true;
}

const cM3dGAab *dBgWKCol::GetBnd() const {
    return &mBnd;
}

u32 dBgWKCol::GetGrpInf(cBgS_PolyInfo const &pi) const {
    return mCode.getGrpCode(GetPrismData(pi.GetPolyIndex())->mAttribute);
}

void dBgWKCol::OffMoveFlag() {}

bool dBgWKCol::ChkPolyThrough(int id, dBgPc *, cBgS_Chk *) {
    // TODO - false return to satisify warnings
    return false;
}

bool dBgWKCol::ChkPolyThroughGnd(int id, dBgPc *, cBgS_Chk *) {
    // TODO - false return to satisify warnings
    return false;
}

void dBgWKCol::vt_0x3C() {
    mPartitionInfo.fn_803391f0(&mBnd);
}

bool dBgWKCol::LineCheck(cBgS_LinChk *pLine) {
    mVec3_c diff;
    VEC3Sub(diff, pLine->mLin.GetStartP(), pLine->mLin.GetEndP());
    f32 mag = VECMag(diff);
    if (mag < 500.0f) {
        int tmp0 = (int)(mag * 0.002f) + 1;
        f32 tmp1 = mag / (tmp0 + 1);
        VEC3Scale(diff, diff, tmp1 / mag);
    }

    // TODO Later lmao
}

bool dBgWKCol::GroundCross(cBgS_GndChk *pGnd) {
    // TODO - false return to satisify warnings
    return false;
}

void dBgWKCol::ShdwDraw(cBgS_ShdwDraw *pShdw) {}

void dBgWKCol::CaptPoly(dBgS_CaptPoly &capt) {}

bool dBgWKCol::WallCorrectSort(dBgS_Acch *pAcch) {
    // TODO - false return to satisify warnings
    return false;
}

bool dBgWKCol::WallCorrect(dBgS_Acch *pAcch) {
    // TODO - false return to satisify warnings
    return false;
}

bool dBgWKCol::RoofChk(dBgS_RoofChk *pRoof) {
    // TODO - false return to satisify warnings
    return false;
}

bool dBgWKCol::SplGrpChk(dBgS_SplGrpChk *) {
    // TODO - false return to satisify warnings
    return false;
}

bool dBgWKCol::SphChk(dBgS_SphChk *, void *) {
    // TODO - false return to satisify warnings
    return false;
}

void dBgWKCol::GetTopUnder(f32 *pOutTop, f32 *pOutUnder) const {
    f32 pos = mpKCHead->mAreaMinPos.y;
    *pOutUnder = pos;
    *pOutTop = pos + mAreaWidthMaskY;
}

s32 dBgWKCol::GetGrpRoomIndex(cBgS_PolyInfo const &info) const {
    return GetPolyCode(info.GetPolyIndex())->getGrpRoomIdx();
}

s32 dBgWKCol::GetExitId(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getExitId();
}

s32 dBgWKCol::GetZTargetThrough(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getTargetThrough();
}

int dBgWKCol::GetSpecialCode(cBgS_PolyInfo const &info) {
    return GetSpecialCode(info.GetPolyIndex());
}

int dBgWKCol::GetSpecialCode(int polyIdx) {
    return GetPolyCode(polyIdx)->getSpecialCode();
}

int dBgWKCol::GetCode0_0x30000000(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getCode0_0x30000000();
}

int dBgWKCol::GetCode0_0x80000000(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getCode0_0x80000000();
}

u32 dBgWKCol::GetPolyObjThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getObjThrough();
}

u32 dBgWKCol::GetPolyCamThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getCamThrough();
}

u32 dBgWKCol::GetPolyLinkThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getLinkThrough();
}

u32 dBgWKCol::GetPolyArrowThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getArrowThrough();
}

u32 dBgWKCol::GetPolySlingshotThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getSlingshotThrough();
}

u32 dBgWKCol::GetPolyBeetleThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getBeetleThrough();
}

u32 dBgWKCol::GetPolyClawshotThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getClawshotThrough();
}

u32 dBgWKCol::GetPolyBombThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getBombThrough();
}

u32 dBgWKCol::GetPolyWhipThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getWhipThrough();
}

u32 dBgWKCol::GetUnderwaterRoofCode(int polyIdx) {
    return GetPolyCode(polyIdx)->getUnderwaterRoof();
}

u32 dBgWKCol::GetShdwThrough(int polyIdx) {
    return GetPolyCode(polyIdx)->getShdwThrough();
}

int dBgWKCol::GetLinkNo(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getLinkNo();
}

s32 dBgWKCol::GetWallCode(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getWallCode();
}

int dBgWKCol::GetPolyAtt0Material(cBgS_PolyInfo const &info) {
    int mat = GetPolyCode(info.GetPolyIndex())->getAtt0Code();
    if (mat >= 0x20) {
        mat -= 0x20;
    }
    return mat;
}

int dBgWKCol::GetPolyAtt1(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getAtt1Code();
}

int dBgWKCol::GetGroundCode(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getGroundCode();
}

u32 dBgWKCol::GetCode1_0x02000000(int polyIdx) {
    return GetPolyCode(polyIdx)->getCode1_0x02000000();
}

u32 dBgWKCol::GetCode1_0x04000000(int polyIdx) {
    return GetPolyCode(polyIdx)->getCode1_0x04000000();
}

u32 dBgWKCol::GetCode1_0x08000000(int polyIdx) {
    return GetPolyCode(polyIdx)->getCode1_0x08000000();
}

u32 dBgWKCol::GetLightingCode(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getLightingCode();
}

s32 dBgWKCol::GetCamMoveBG(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getCamMoveBG();
}

s32 dBgWKCol::GetRoomCamId(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getRoomCam();
}

s32 dBgWKCol::GetRoomPathId(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getRoomPath();
}

s32 dBgWKCol::GetRoomPathPntNo(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getRoomPathPnt();
}

void dBgWKCol::CrrPos(cBgS_PolyInfo const &, void *, bool, mVec3_c *, mAng3_c *, mAng3_c *) {}

void dBgWKCol::TransPos(cBgS_PolyInfo const &, void *, bool, mVec3_c *, mAng3_c *, mAng3_c *) {}

void dBgWKCol::MatrixCrrPos(cBgS_PolyInfo const &, void *, bool, mVec3_c *, mAng3_c *, mAng3_c *) {}

int dBgWKCol::GetMapCode(KC_PrismData *prism, int *pOut) {
    cBgS_PolyInfo info;

    if (mpKCHead->mpNormalData[prism->mFaceNrmIdx].y <= 0.f) {
        return true;
    }

    if (mpTri != nullptr) {
        int idx = GetPrismIdx(prism);
        KC_Tri &tri = mpTri[idx];
        mVec3_c a, b, c;
        VEC3Sub(a, tri.mB, tri.mA);
        VEC3Sub(b, tri.mC, tri.mB);
        VEC3Sub(c, tri.mA, tri.mC);

        if (cM3d_IsZero(VEC3Len(a))) {
            return true;
        }
        if (cM3d_IsZero(VEC3Len(b))) {
            return true;
        }
        if (cM3d_IsZero(VEC3Len(c))) {
            return true;
        }
    }
    info.SetPolyIndex(prism - mpKCHead->mpPrismData);
    int att0 = GetPolyAtt0(info);
    int att1 = GetPolyAtt1(info);
    bool target = GetZTargetThrough(info);
    if (att0 >= 0x20) {
        *pOut = dBgS::GetMapCode(att0 - 0x20, att1, target);
        return false;
    } else {
        return true;
    }
}

bool dBgWKCol::UpdateDraw(mAllocator_c *alloc) {
    // TODO
    // To Generate Weak Ct and Dt of KC_Tri
    mpTri = new (alloc) KC_Tri[mNumPrism];
    if (mpTri == nullptr) {
        return false;
    }

    KC_PrismData *startPrism = mpKCHead->mpPrismData;
    KC_PrismData *currPrism = startPrism + 1;
    mBnd.ClearForMinMax();
    do {
        //
        mVec3_c a, b, c;
        if (!GetTriPnt(currPrism, &a, &b, &c)) {
            a = mpKCHead->mpPositionData[currPrism->mPosIdx];
            b = a;
            c = a;
        }
        int idx = currPrism - mpKCHead->mpPrismData;
        mpTri[idx].mA = a;
        mpTri[idx].mB = b;
        mpTri[idx].mC = c;

        mBnd.SetMinMax(a);
        mBnd.SetMinMax(b);
        mBnd.SetMinMax(c);
        currPrism++;
    } while (currPrism < (KC_PrismData *)mpKCHead->mpBlockData);
    mBnd.PlusR(1.0f);
    vt_0x3C();

    ClearMapCount();

    currPrism = mpKCHead->mpPrismData + 1;
    do {
        int mapCode = 0;
        if (!GetMapCode(currPrism, &mapCode)) {
            mMapRelated[mapCode].mCount++;
        }
        currPrism++;
    } while (currPrism < (KC_PrismData *)mpKCHead->mpBlockData);

    for (int i = 0; i < 0x1F; i++) {
        if (mMapRelated[i].mCount > 0) {
            mMapRelated[i].mpIdx = new (alloc) int[mMapRelated[i].mCount];
            if (mMapRelated[i].mpIdx == nullptr) {
                return false;
            }
        }
    }

    int local_cnt[0x1F];
    for (int i = 0; i < 0x1F; i++) {
        local_cnt[i] = 0;
    }
    currPrism = mpKCHead->mpPrismData + 1;
    do {
        int mapCode = 0;
        if (!GetMapCode(currPrism, &mapCode)) {
            mMapRelated[mapCode].mpIdx[local_cnt[mapCode]] = currPrism - mpKCHead->mpPrismData;
            local_cnt[mapCode]++;
        }
        currPrism++;
    } while (currPrism < (KC_PrismData *)mpKCHead->mpBlockData);

    return true;
}

int dBgWKCol::GetPolyAtt0(cBgS_PolyInfo const &info) {
    return GetPolyCode(info.GetPolyIndex())->getAtt0Code();
}

bool dBgWKCol::GetIsDraw(int idx) {
    if (mMapRelated[idx].mCount <= 0) {
        return false;
    }
    return mpTri != nullptr;
}

void dBgWKCol::DrawMapSection(int idx, f32 yPos, f32 upper, f32 lower) {
    int all = mMapRelated[idx].mCount;
    int count = 0;
    for (int i = 0; i < all; i++) {
        KC_Tri &tri = mpTri[mMapRelated[idx].mpIdx[i]];
        if (
            // If Tri height is not above or below the limits
            !((tri.mA.y > upper) && (tri.mB.y > upper) && (tri.mC.y > upper)) &&
            !((tri.mA.y < lower) && (tri.mB.y < lower) && (tri.mC.y < lower))) {
            count++;
        }
    };

    GXBegin(GX_TRIANGLES, GX_VTXFMT0, count * 3);
    for (int i = 0; i < all; i++) {
        KC_Tri &tri = mpTri[mMapRelated[idx].mpIdx[i]];
        if (
            // If Tri height is not above or below the limits
            !((tri.mA.y > upper) && (tri.mB.y > upper) && (tri.mC.y > upper)) &&
            !((tri.mA.y < lower) && (tri.mB.y < lower) && (tri.mC.y < lower))) 
        {
            f32 BAx = tri.mB.x - tri.mA.x;
            f32 CBx = tri.mC.x - tri.mB.x;
            f32 ACx = tri.mA.x - tri.mC.x;

            f32 BAz = tri.mB.z - tri.mA.z;
            f32 CBz = tri.mC.z - tri.mB.z;
            f32 ACz = tri.mA.z - tri.mC.z;

            f32 tmp0 = nw4r::math::FSqrt(BAx * BAx + BAz * BAz);
            f32 tmp1 = nw4r::math::FSqrt(CBx * CBx + CBz * CBz);
            f32 tmp2 = nw4r::math::FSqrt(ACx * ACx + ACz * ACz);

            tmp0 = cM3d_IsZero(tmp0) ? 0.0f : 10.0f / tmp0;
            tmp1 = cM3d_IsZero(tmp1) ? 0.0f : 10.0f / tmp1;
            tmp2 = cM3d_IsZero(tmp2) ? 0.0f : 10.0f / tmp2;

            f32 t0x = BAx * tmp0;
            f32 t0z = BAz * tmp0;

            f32 t1z = CBz * tmp1;
            f32 t1x = CBx * tmp1;

            f32 t2x = ACx * tmp2;
            f32 t2z = ACz * tmp2;

            f32 x0 = t2x + (tri.mA.x - t0x);
            f32 z0 = t2z + (tri.mA.z - t0z);

            f32 x2 = t0x + (tri.mB.x - t1x);
            f32 z2 = t0z + (tri.mB.z - t1z);

            f32 x1 = t1x + (tri.mC.x - t2x);
            f32 z1 = t1z + (tri.mC.z - t2z);

            GXPosition3f32(x0, yPos, z0);
            GXPosition3f32(x1, yPos, z1);
            GXPosition3f32(x2, yPos, z2);
        }
    }
}

void dBgWKCol::DrawOnMap(int idx, bool param2) {
    // uhhhhhh

    if (!GetIsDraw(idx)) {
        return;
    }

    if (param2) {
        // FS Room 9 /* Spiral Staircase  */
        if (GetRoomId() == 9 && (dScGame_c::isCurrentStage(STAGE_FS_A) || dScGame_c::isCurrentStage(STAGE_FS_B))) {
            int all = mMapRelated[idx].mCount;
            mVec3_c AB, CA, BC;
            mVec3_c v0, v1, v2;
            // Pass 1
            int count = 0;
            for (int i = 0; i < all; i++) {
                KC_Tri &tri = mpTri[mMapRelated[idx].mpIdx[i]];
                if (!((tri.mA.y < -550.0f) && (tri.mB.y < -550.0f) && (tri.mC.y < -550.0f))) {
                    count++;
                }
            }
            GXBegin(GX_TRIANGLES, GX_VTXFMT0, count * 3);
            for (int i = 0; i < all; i++) {
                KC_Tri &tri = mpTri[mMapRelated[idx].mpIdx[i]];
                if (!((tri.mA.y < -550.0f) && (tri.mB.y < -550.0f) && (tri.mC.y < -550.0f))) {
                    VEC3Sub(AB, tri.mB, tri.mA);
                    VEC3Sub(CA, tri.mA, tri.mC);
                    VEC3Sub(BC, tri.mC, tri.mB);

                    f32 len0 = VEC3Len(AB);
                    f32 len1 = VEC3Len(CA);
                    f32 len2 = VEC3Len(BC);

                    VEC3Scale(AB, AB, 10.0f / len0);
                    VEC3Scale(CA, CA, 10.0f / len1);
                    VEC3Scale(BC, BC, 10.0f / len2);

                    VEC3Sub(v0, tri.mA, AB);
                    VEC3Sub(v1, tri.mC, CA);
                    VEC3Sub(v2, tri.mB, BC);

                    VEC3Add(v0, v0, CA);
                    VEC3Add(v1, v1, BC);
                    VEC3Add(v2, v2, AB);

                    GXPosition3f32(v0.x, v0.y, v0.z);
                    GXPosition3f32(v1.x, v1.y, v1.z);
                    GXPosition3f32(v2.x, v2.y, v2.z);
                }
            }
            // Pass 2
            count = 0;
            for (int i = 0; i < all; i++) {
                KC_Tri &tri = mpTri[mMapRelated[idx].mpIdx[i]];
                if (!((tri.mA.y > -550.0f) && (tri.mB.y > -550.0f) && (tri.mC.y > -550.0f))) {
                    count++;
                }
            }
            GXBegin(GX_TRIANGLES, GX_VTXFMT0, count * 3);
            for (int i = 0; i < all; i++) {
                KC_Tri &tri = mpTri[mMapRelated[idx].mpIdx[i]];
                if (!((tri.mA.y > -550.0f) && (tri.mB.y > -550.0f) && (tri.mC.y > -550.0f))) {
                    VEC3Sub(AB, tri.mB, tri.mA);
                    VEC3Sub(CA, tri.mA, tri.mC);
                    VEC3Sub(BC, tri.mC, tri.mB);

                    f32 len0 = VEC3Len(AB);
                    f32 len1 = VEC3Len(CA);
                    f32 len2 = VEC3Len(BC);

                    VEC3Scale(AB, AB, 10.0f / len0);
                    VEC3Scale(CA, CA, 10.0f / len1);
                    VEC3Scale(BC, BC, 10.0f / len2);

                    VEC3Sub(v0, tri.mA, AB);
                    VEC3Sub(v2, tri.mB, BC);
                    VEC3Sub(v1, tri.mC, CA);

                    VEC3Add(v0, v0, CA);
                    VEC3Add(v1, v1, BC);
                    VEC3Add(v2, v2, AB);

                    // v0.y = (v0.y + 6500.0f) * 0.1680672f - 6500.0f;
                    // v1.y = (v1.y + 6500.0f) * 0.1680672f - 6500.0f;
                    // v2.y = (v2.y + 6500.0f) * 0.1680672f - 6500.0f;

                    GXPosition3f32(v0.x, (v0.y + 6500.0f) * 0.1680672f - 6500.0f, v0.z);
                    GXPosition3f32(v1.x, (v1.y + 6500.0f) * 0.1680672f - 6500.0f, v1.z);
                    GXPosition3f32(v2.x, (v2.y + 6500.0f) * 0.1680672f - 6500.0f, v2.z);
                    // GXPosition3f32(v0.x, v0.y, v0.z);
                    // GXPosition3f32(v1.x, v1.y, v1.z);
                    // GXPosition3f32(v2.x, v2.y, v2.z);
                }
            }
        }
        // Normal
        else {
            int all = mMapRelated[idx].mCount;
            GXBegin(GX_TRIANGLES, GX_VTXFMT0, all * 3);
            for (int i = 0; i < all; i++) {
                KC_Tri &tri = mpTri[mMapRelated[idx].mpIdx[i]];

                mVec3_c AB, CA, BC;
                mVec3_c v0, v1, v2;

                VEC3Sub(AB, tri.mB, tri.mA);
                VEC3Sub(CA, tri.mA, tri.mC);
                VEC3Sub(BC, tri.mC, tri.mB);

                f32 len0 = VEC3Len(AB);
                f32 len1 = VEC3Len(CA);
                f32 len2 = VEC3Len(BC);

                VEC3Scale(AB, AB, 10.0f / len0);
                VEC3Scale(CA, CA, 10.0f / len1);
                VEC3Scale(BC, BC, 10.0f / len2);

                VEC3Sub(v0, tri.mA, AB);
                VEC3Sub(v1, tri.mC, CA);
                VEC3Sub(v2, tri.mB, BC);

                VEC3Add(v0, v0, CA);
                VEC3Add(v1, v1, BC);
                VEC3Add(v2, v2, AB);

                GXPosition3f32(v0.x, v0.y, v0.z);
                GXPosition3f32(v1.x, v1.y, v1.z);
                GXPosition3f32(v2.x, v2.y, v2.z);
            }
        }
    }
    // Sections
    else {
        const cM3dGAab *bnd = GetBnd();
        f32 yPos = (bnd->GetMinP()->y + bnd->GetMaxP()->y) * 0.5f;

        // Sandship
        if (GetRoomId() == 15 && dScGame_c::isCurrentStage(STAGE_SSH)) {
            yPos = 0.0f;
        }
        if (idx == 0x12 /* Abyss `Common/tex/naraku.bti`)*/) {
            yPos -= 1.0f;
        }
        if (dScGame_c::isCurrentStage(STAGE_FS_A) || dScGame_c::isCurrentStage(STAGE_FS_B)) {
            int room = GetRoomId();
            /* FS Room 9 - Spiral Staircse */
            if (room == 9) {
                DrawMapSection(idx, yPos, 1e9f, -550.0f);
                DrawMapSection(idx, -6000.0f, -550.0f, -1e9f);
                return;
            }
            /* FS Room 6 - Bridges */
            if (room == 6) {
                DrawMapSection(idx, yPos, 1e9f, -5500.0f);
                DrawMapSection(idx, -6000.0f, -550.0f, -1e9f);
                return;
            }
        }
        DrawMapSection(idx, yPos, 1e9f, -1e9f);
    }
}

int dBgWKCol::GetPrismIdx(const KC_PrismData *pPrismData) {
    return (pPrismData - mpKCHead->mpPrismData);
}
