Created
May 16, 2015 10:07
-
-
Save ikrima/5568c60d812a2a593c71 to your computer and use it in GitHub Desktop.
Alembic Tangent Calculation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Split Normals & UVs | |
//NOTE: ikrimae: THIS HAS TO HAPPEN AFTER UVS, NORMALS, POSITIONS ELSE HAS BEEN COMPUTED | |
//TODO: ikrimae: this is horrible; clean up into something not convoluted | |
{ | |
//For easy debugging | |
struct SplitVertex { | |
UINT32 vertIdx; | |
UINT32 vertFaceIdx; | |
V3f pos; | |
V3f normal; | |
V4f tanX; | |
V2f uv; | |
UINT32 uvDataArrayIdx; | |
UINT32 nDataArrayIdx; | |
UINT32 remappedVertIdx; | |
}; | |
const IN3fGeomParam nParam = curNode->m_polyMesh.getSchema().getNormalsParam(); | |
const IN3fGeomParam::Sample nSamp = nParam.getIndexedValue(ss); | |
const UInt32ArraySamplePtr nFacesArraySmplPtr = nSamp.getIndices(); | |
const size_t nFacesArraySize = nFacesArraySmplPtr->size(); | |
const UINT32 * nFacesArray = nFacesArraySmplPtr->get(); | |
const N3fArraySamplePtr nDataArrayPtr = nSamp.getVals(); | |
const size_t nDataArraySize = nDataArrayPtr->size(); | |
const V3f* nDataArray = nDataArrayPtr->get(); | |
const IV2fGeomParam uvParam = curNode->m_polyMesh.getSchema().getUVsParam(); | |
const IV2fGeomParam::Sample uvsamp = uvParam.getIndexedValue(ss); | |
const UInt32ArraySamplePtr uvFacesArraySmplPtr = uvsamp.getIndices(); | |
const size_t uvFacesArraySize = uvFacesArraySmplPtr->size(); | |
const UINT32 * uvFacesArray = uvFacesArraySmplPtr->get(); | |
const V2fArraySamplePtr uvDataArrayPtr = uvsamp.getVals(); | |
const size_t uvDataArraySize = uvDataArrayPtr->size(); | |
const V2f* uvDataArray = uvDataArrayPtr->get(); | |
const int * meshFacesArray = curNode->m_meshIndices->get(); | |
const size_t meshFacesArraySize = curNode->m_meshIndices->size(); | |
const V3f* posArray = curNode->m_meshP->get(); | |
const size_t posArraySize = curNode->m_meshP->size(); | |
const size_t numPoints = curNode->m_meshP->size(); | |
//HACK: ikrimae: Temp stub | |
curNode->m_customTangentX.resize(numPoints); | |
//Indexed by the vertex index, not the vertex face index | |
std::vector<std::vector<SplitVertex>> splitVerticesStructure; | |
splitVerticesStructure.resize(numPoints); | |
//Loop over faces | |
for (auto& curTri : curNode->m_triangles) | |
{ | |
for (int i = 0; i < 3; ++i) | |
{ | |
UINT32* curTriVertIdx = &(curTri.vertIdx[i]); | |
const UINT32& curTriVertFaceIdx = curTri.vertFaceIdx[i]; | |
SplitVertex splitVertCandidate; | |
{ | |
//For easy debugging | |
splitVertCandidate.vertIdx = *curTriVertIdx; | |
splitVertCandidate.remappedVertIdx = *curTriVertIdx; | |
splitVertCandidate.vertFaceIdx = curTriVertFaceIdx; | |
splitVertCandidate.pos = posArray [meshFacesArray[curTriVertFaceIdx]]; | |
splitVertCandidate.normal = nDataArray [nFacesArray [curTriVertFaceIdx]].normalized(); | |
splitVertCandidate.uv = uvDataArray[uvFacesArray [curTriVertFaceIdx]]; | |
splitVertCandidate.tanX = curNode->m_customTangentX [*curTriVertIdx]; //Special b/c this is computed | |
splitVertCandidate.uvDataArrayIdx = uvFacesArray[curTriVertFaceIdx]; | |
splitVertCandidate.nDataArrayIdx = nFacesArray [curTriVertFaceIdx]; | |
} | |
std::vector<SplitVertex>& splitVertices = splitVerticesStructure[splitVertCandidate.vertIdx]; | |
if (splitVertices.size() == 0) | |
{ | |
splitVertices.push_back(splitVertCandidate); | |
curNode->m_customUV[splitVertCandidate.vertIdx] = splitVertCandidate.uv; | |
curNode->m_customN[splitVertCandidate.vertIdx] = splitVertCandidate.normal; | |
} | |
else | |
{ | |
//Loop through list of split vertices for this vertindex | |
bool bNeedToSplit = true; | |
//See if we have a vertex with matching UVs | |
for (const auto& existingSplitVert : splitVertices) | |
{ | |
//UV Face Index uniquely identifies UVs for face sets. Same with Normal Face Index | |
if (splitVertCandidate.uvDataArrayIdx == existingSplitVert.uvDataArrayIdx | |
&& splitVertCandidate.nDataArrayIdx == existingSplitVert.nDataArrayIdx) | |
{ | |
bNeedToSplit = false; | |
//We have to set this because this vertex could've been remapped | |
//If it hasn't, remappedVertIdx contains the original vertIdx | |
*curTriVertIdx = existingSplitVert.remappedVertIdx; | |
curNode->m_customUV[existingSplitVert.remappedVertIdx] = existingSplitVert.uv; | |
curNode->m_customN[existingSplitVert.remappedVertIdx] = existingSplitVert.normal; | |
break; | |
} | |
} | |
if (bNeedToSplit) | |
{ | |
//Remap to the new index | |
splitVertCandidate.remappedVertIdx = curNode->m_customP.size(); | |
*curTriVertIdx = splitVertCandidate.remappedVertIdx; | |
//Duplicate the vertex data | |
curNode->m_customP.push_back(splitVertCandidate.pos); | |
curNode->m_customN.push_back(splitVertCandidate.normal); | |
curNode->m_customUV.push_back(splitVertCandidate.uv); | |
curNode->m_customTangentX.push_back(splitVertCandidate.tanX); | |
splitVertices.push_back(splitVertCandidate); | |
} | |
} | |
} | |
} | |
} | |
//Calculate Tangents | |
//TODO: ikrimae: Use Mikkelson's tangent generation code by calling KLDbgNode::CalcTangents (function itself is untested so test that too) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment