Program Listing for File tangentCalculator.cpp

↰ Return to documentation for file (PrismEngine/src/tangentCalculator.cpp)

#include "tangentCalculator.h"

void prism::PGC::L3::TangentCalculator::generateTangents(Vertex* verticesBegin, size_t verticesCount, uint32_t* indicesBegin, size_t indicesCount)
{
    if (!verticesCount || !indicesCount) return;
    if (indicesCount % 3 != 0) {
        throw std::invalid_argument("Index buffer must contain triangulated faces (size % 3 == 0)");
    }

    MikkTSpaceData data{ verticesBegin, verticesCount, indicesBegin, indicesCount };

    SMikkTSpaceInterface iface{};
    iface.m_getNumFaces = getNumFaces;
    iface.m_getNumVerticesOfFace = getNumVertsOfFace;
    iface.m_getPosition = getPosition;
    iface.m_getNormal = getNormal;
    iface.m_getTexCoord = getTexCoord;
    iface.m_setTSpaceBasic = setTSpaceBasic;

    SMikkTSpaceContext ctx{};
    ctx.m_pInterface = &iface;
    ctx.m_pUserData = &data;

    if (!genTangSpaceDefault(&ctx)) {
        throw std::runtime_error("MikkTSpace: tangent generation failed");
    }
}

int prism::PGC::L3::TangentCalculator::getNumFaces(const SMikkTSpaceContext* pCtx)
{
    auto* mesh = static_cast<MikkTSpaceData*>(pCtx->m_pUserData);
    return static_cast<int>(mesh->indicesCount / 3);
}

int prism::PGC::L3::TangentCalculator::getNumVertsOfFace(const SMikkTSpaceContext*, int)
{
    return 3;
}

void prism::PGC::L3::TangentCalculator::getPosition(const SMikkTSpaceContext* pCtx, float fvPosOut[], int iFace, int iVert)
{
    auto* mesh = static_cast<MikkTSpaceData*>(pCtx->m_pUserData);
    int idx = mesh->indicesBegin[iFace * 3 + iVert];
    fvPosOut[0] = mesh->verticesBegin[idx].pos[0];
    fvPosOut[1] = mesh->verticesBegin[idx].pos[1];
    fvPosOut[2] = mesh->verticesBegin[idx].pos[2];
}

void prism::PGC::L3::TangentCalculator::getNormal(const SMikkTSpaceContext* pCtx, float fvNormOut[], int iFace, int iVert)
{
    auto* mesh = static_cast<MikkTSpaceData*>(pCtx->m_pUserData);
    int idx = mesh->indicesBegin[iFace * 3 + iVert];
    fvNormOut[0] = mesh->verticesBegin[idx].normal[0];
    fvNormOut[1] = mesh->verticesBegin[idx].normal[1];
    fvNormOut[2] = mesh->verticesBegin[idx].normal[2];
}

void prism::PGC::L3::TangentCalculator::getTexCoord(const SMikkTSpaceContext* pCtx, float fvTexcOut[], int iFace, int iVert)
{
    auto* mesh = static_cast<MikkTSpaceData*>(pCtx->m_pUserData);
    int idx = mesh->indicesBegin[iFace * 3 + iVert];
    fvTexcOut[0] = mesh->verticesBegin[idx].texCoord[0];
    fvTexcOut[1] = mesh->verticesBegin[idx].texCoord[1];
}

void prism::PGC::L3::TangentCalculator::setTSpaceBasic(const SMikkTSpaceContext* pCtx, const float fvTangent[], const float fSign, int iFace, int iVert)
{
    auto* mesh = static_cast<MikkTSpaceData*>(pCtx->m_pUserData);
    int idx = mesh->indicesBegin[iFace * 3 + iVert];
    mesh->verticesBegin[idx].tangent[0] = fvTangent[0];
    mesh->verticesBegin[idx].tangent[1] = fvTangent[1];
    mesh->verticesBegin[idx].tangent[2] = fvTangent[2];
    mesh->verticesBegin[idx].tangent[3] = fSign;
}