[
][
]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...