1
\$\begingroup\$

[enter image description here][[1]]2

there's problem calculating tangent space and look.... it seems there is no problem with UV code and my shader is 100% no problem. I just copy and pasted tutorial code which works well..

I loaded fbx file and exported to obj file which uses only trianglelists and I parsed it my own OBJparser after parsing I optimize it. find out same vertices and remove it and make index list. here my code

#pragma once
#include"stdafx.h"
#include "ObjLoader.h"
#include <iostream>
// 2017 정윤성

ObjLoader::ObjLoader(char* path, bool istriangle)
{
    file.open(path);
    m_triangle = istriangle;
}

ObjLoader::ObjLoader()
{
}


ObjLoader::~ObjLoader()
{
    file.close();
}

void ObjLoader::openFile(char * path, bool istriangle)
{
    file.open(path);
    m_triangle = istriangle;
}

void ObjLoader::closeFile()
{
    file.close();
    m_vt.clear();
    m_vn.clear();
    m_uv.clear();
    m_idx.clear();
    m_vertice.clear();
    m_indice.clear();
    m_refinedVertice.clear();
}

void ObjLoader::parseOBJ()
{

    XYZ point;
    UV uv;
    int index = 0;
    string line;
    string token;
    char buff;
    char str[256];
    while (!file.eof())
    {
        file.get(buff);
        switch (buff)
        {
        case 'v':
            file.get(buff);
            switch (buff)
            {
            case ' ':
                file >> point.x >> point.y >> point.z;
                point.z = -point.z;
                m_vt.push_back(point);
                break;
            case 't':
                file >> uv.u >> uv.v;
                uv.v = 1.0f - uv.v;
                m_uv.push_back(uv);
                break;
            case 'n':
                file >> point.x >> point.y >> point.z;
                point.z = -point.z;
                m_vn.push_back(point);
                break;
            }
            break;
        case 'f':
            file.get(buff);
            if (m_triangle)
            {
                if (buff == ' ')
                {
                    //f v/vt/vn v/vt/vn v/vt/vn v/vt/vn

                    faceindex index;
                    file.getline(str, sizeof(str));
                    line = str;
                    int idx = 0;
                    faceindex temp[3];
                    for (int i = 0; i < 3; i++)
                    {
                        idx = line.find(' ');
                        token = line.substr(0, idx);
                        sscanf(token.c_str(), "%d/%d/%d", &index.idxV, &index.idxVt, &index.idxVn);
                        index.idxV--;
                        index.idxVn--;
                        index.idxVt--;
                        temp[i] = index;
                        line.erase(0, idx + 1);
                    }
                    m_idx.push_back(temp[0]);
                    m_idx.push_back(temp[2]);
                    m_idx.push_back(temp[1]);
                }
            }
            else
            {
                if (buff == ' ')
                {
                    //f v/vt/vn v/vt/vn v/vt/vn v/vt/vn

                    faceindex index;
                    file.getline(str, sizeof(str));
                    line = str;
                    int idx = 0;
                    faceindex temp[4];
                    for (int i = 0; i < 4; i++)
                    {
                        idx = line.find(' ');
                        token = line.substr(0, idx);
                        sscanf(token.c_str(), "%d/%d/%d", &index.idxV, &index.idxVt, &index.idxVn);
                        index.idxV--;
                        index.idxVn--;
                        index.idxVt--;
                        temp[i] = index;
                        line.erase(0, idx + 1);
                    }
                    m_idx.push_back(temp[0]);
                    m_idx.push_back(temp[2]);
                    m_idx.push_back(temp[1]);


                    m_idx.push_back(temp[0]);
                    m_idx.push_back(temp[3]);
                    m_idx.push_back(temp[2]);
                }
            }
            break;
        default:
            break;
        }


    }
}

void ObjLoader::check()
{
    for each (XYZ var in m_vt)
    {
        printf("%f,%f,%f\n", var.x, var.y, var.z);
    }

    for each(UV var in m_uv)
    {
        printf("%f,%f\n", var.u, var.v);

    }

    for each (XYZ var in m_vn)
    {
        printf("%f,%f,%f\n", var.x, var.y, var.z);
    }

    for each(faceindex var in m_idx)
    {
        printf("%d,%d,%d\n", var.idxV,  var.idxVt, var.idxVn);

    }

}

void ObjLoader::checkingoptimize()
{
    //cout << "오리지날 : "<< m_vertice.size() << endl;
    //cout << "최적화 : "<<m_refinedVertice.size() <<endl;
    //cout << "인덱스 : "<<m_indice.size() << endl;
    //meshData lastunopdata =  m_vertice[m_vertice.size() - 1];
    //meshData lastopdata = m_refinedVertice[m_indice[m_indice.size() - 1]];
    //meshData firstOpdata = m_refinedVertice[m_indice[0]];
    //
    //cout << "오리지날 마지막 데이타" << endl;
    //showPos(lastunopdata);
    //cout << "최적화 마지막 데이타" << endl;
    //showPos(lastopdata);
    //cout << "최적화 처음  데이타" << endl;
    //showPos(firstOpdata);
    //
    //for each (unsigned int var in m_indice)
    //{
    //  cout << var << endl;
    //}




}

void ObjLoader::showPos(meshData data)
{

    //cout << "x : " << data.pos.x << "y: " << data.pos.y << "z: " << data.pos.z << endl;
    cout << "x : " << data.tangent.x << "y: " << data.tangent.y << "z: " << data.tangent.z << endl;

}

void ObjLoader::calculateTangent()
{
    assert(m_refinedVertice.size() && "최적화 파싱먼저 하시오");
    assert(!(m_indice.size() % 3) && "3으로 나누어 떨어지지 않는 삼각형 리스트가 있을리가 없지.");

    struct data {
        XMFLOAT3 pos;
        XMFLOAT2 uv;
        data() { pos = XMFLOAT3(0, 0, 0); uv = XMFLOAT2(0, 0); }
        data operator-(data& in)
        {
            data result;
            result.pos.x = pos.x - in.pos.x;
            result.pos.y = pos.y - in.pos.y;
            result.pos.z = pos.z - in.pos.z;

            result.uv.x = uv.x - in.uv.x;
            result.uv.y = uv.y - in.uv.y;
            return result;
        }
    };

    struct tangent {
        XMFLOAT3 tan;
        XMFLOAT3 binor;
        XMFLOAT3 normal;
        int addCount;
        tangent() { normal = XMFLOAT3(0, 0, 0); tan = XMFLOAT3(0, 0, 0); addCount = 0; binor = XMFLOAT3(0, 0, 0); }
    };


    vector<tangent> verPerTan;
    verPerTan.assign(m_refinedVertice.size(), tangent());

    data triagle[3];
    int loopcnt = m_indice.size() / 3;
    for(int i=0;i<loopcnt;i++)
    {
        for (int k = 0; k < 3; k++)
        {
            triagle[k].pos = m_refinedVertice[m_indice[(i*3)+k]].pos;
            triagle[k].uv = m_refinedVertice[m_indice[(i*3)+k]].UV;
        }

        XMVECTOR v[3];
        XMVECTOR uv[3];
        for (int i = 0; i < 3; i++)
        {
            v[i] = XMLoadFloat3(&triagle[i].pos);
            uv[i] = XMLoadFloat2(&triagle[i].uv);
        }

        XMVECTOR e0, e1,dUv0,dUv1;
        e0 = v[1] - v[0];
        e1 = v[2] - v[0];
        dUv0 = uv[1] - uv[0];
        dUv1 = uv[2] - uv[0];
        XMVECTOR Normal = XMVector3Cross(e0, e1);

        float det = dUv0.m128_f32[0] * dUv1.m128_f32[1] - dUv0.m128_f32[1] * dUv1.m128_f32[0];
        XMVECTOR nullvector = XMVectorSet(0, 0, 0, 0);
        XMMATRIX uvMatrix, eMatrix, TBMatrix;
        // rowmajor matrix
        uvMatrix = XMMATRIX(dUv0, dUv1 ,nullvector, nullvector);
        eMatrix = XMMATRIX(e0, e1, nullvector, nullvector);
        TBMatrix = XMMATRIX(nullvector, nullvector, nullvector, nullvector);
        // cal det
        float temp = uvMatrix.r[0].m128_f32[0];
        uvMatrix.r[0].m128_f32[0] = uvMatrix.r[1].m128_f32[1];
        uvMatrix.r[1].m128_f32[1] = temp;
        temp = uvMatrix.r[0].m128_f32[1];
        uvMatrix.r[0].m128_f32[1] = -uvMatrix.r[1].m128_f32[0];
        uvMatrix.r[1].m128_f32[0] = -temp;
        //

        //calculate TB
        uvMatrix *= det;
        TBMatrix = uvMatrix*eMatrix;

        XMVECTOR tan;
        XMVECTOR bi;
        XMVECTOR XMverpertan;
        XMVECTOR XMverperbi;
        XMVECTOR XMNormal;
        // averaging TBN
        for (int k = 0; k < 3; k++)
        {
            XMverpertan = XMLoadFloat3(&verPerTan[m_indice[(i * 3) + k]].tan);
            XMverperbi = XMLoadFloat3(&verPerTan[m_indice[(i * 3) + k]].binor);
            XMNormal = XMLoadFloat3(&verPerTan[m_indice[(i * 3) + k]].normal);
            XMverpertan += TBMatrix.r[0];
            XMverperbi += TBMatrix.r[1];
            XMNormal += Normal;
            XMStoreFloat3(&verPerTan[m_indice[(i * 3) + k]].tan, XMverpertan);
            XMStoreFloat3(&verPerTan[m_indice[(i * 3) + k]].binor, XMverperbi);
            XMStoreFloat3(&verPerTan[m_indice[(i * 3) + k]].normal, XMNormal);
            verPerTan[m_indice[(i * 3) + k]].addCount++;
        }
    }

    // averaging TBN
    for each (tangent var in verPerTan)
    {
        int addcount = var.addCount;
        var.binor.x /= addcount;
        var.binor.y /= addcount;
        var.binor.z /= addcount;

        var.tan.x /= addcount;
        var.tan.y /= addcount;
        var.tan.z /= addcount;
    }

    //Gram-Schmidt 
    for (int i = 0; i < m_refinedVertice.size(); i++)
    {
        XMVECTOR N, T, B;
        N = XMLoadFloat3(&verPerTan[i].normal);
        T = XMLoadFloat3(&verPerTan[i].tan);
        B = XMLoadFloat3(&verPerTan[i].binor);

        N = XMVector3Normalize(N);
        T = XMVector3Normalize(T);
        B = XMVector3Normalize(B);

        T = XMVector3Normalize(T - (XMVector3Dot(N, T)*N));
        B = XMVector3Normalize(B - (XMVector3Dot(T, B)*T));
        B = XMVector3Normalize(B - (XMVector3Dot(N, B)*N));



        XMStoreFloat3(&m_refinedVertice[i].tangent, T);
        XMStoreFloat3(&m_refinedVertice[i].normal, N);
    }





    ////test//
    //XMMATRIX rowMajor, columnMajor;
    //
    //rowMajor = XMMATRIX(1.0f, 1.0f, 1.0f, 1.0f
    //  , 0.0f, 0.0f, 0.0f, 0.0f
    //  , 0.0f, 0.0f, 0.0f, 0.0f
    //  , 0.0f, 0.0f, 0.0f, 0.0f);
    //columnMajor = XMMATRIX(1, 0, 0, 0,
    //  1, 0, 0, 0,
    //  1, 0, 0, 0,
    //  1, 0, 0, 0);
    //
    //XMMATRIX result;
    //
    //result=rowMajor*columnMajor;
    // m[1,1] = 4
    // row*column
    // vector의 dot product를 이용한다.


}

void ObjLoader::loadVertex()
{
    meshData vertex;

    auto it = m_idx.begin();
    for (; it != m_idx.end(); it++)
    {
        vertex.pos.x = m_vt[it->idxV].x;
        vertex.pos.y = m_vt[it->idxV].y;
        vertex.pos.z = m_vt[it->idxV].z;

        vertex.normal.x = m_vn[it->idxVn].x;
        vertex.normal.y = m_vn[it->idxVn].y;
        vertex.normal.z = m_vn[it->idxVn].z;

        vertex.UV.x = m_uv[it->idxVt].u;
        vertex.UV.y = m_uv[it->idxVt].v;
        m_vertice.push_back(vertex);

    }
}

// optimize the vertex
// by findout same vertice , remove it and replace it by indexing
void ObjLoader::optimize()
{
    unsigned int* deleteindex = new unsigned int[m_vertice.size()];
    unsigned int* indice = new unsigned int[m_vertice.size()];
    unsigned int numofpoints = 0;
    memset(deleteindex, 0, sizeof(deleteindex));
    for (int i = 0; i < m_vertice.size(); i++)
    {

        bool found = false;
        meshData pivot = m_vertice[i];

        for (int k = 0; k < m_vertice.size(); k++)
        {

            if (pivot == m_vertice[k] && i != k)
            {

                if (i < k)
                {
                    break;
                }
                else
                {
                    found = true;
                    indice[i] = indice[k];
                    deleteindex[i] = true;
                    break;
                }
            }
        }


        if (found == false)
        {
            deleteindex[i] = false;
            indice[i] = numofpoints;
            numofpoints++;
        }
    }

    for (int i = 0; i < m_vertice.size() ; i++)
    {
        m_indice.push_back(indice[i]);
    }

    for (int i = 0; i < m_vertice.size() ; i++)
    {
        if (!deleteindex[i])
        {
            m_refinedVertice.push_back(m_vertice[i]);
        }
    }



    delete[] deleteindex;
    delete[] indice;
}

any debug suggestion for this? plz...

\$\endgroup\$
  • \$\begingroup\$ How are your UVs laid out? What does your normal map look like? \$\endgroup\$ – DMGregory Aug 15 '17 at 11:32
  • \$\begingroup\$ Have you looked at the code in DirectXMesh? \$\endgroup\$ – Chuck Walbourn Aug 15 '17 at 18:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.