Skip to content

Instantly share code, notes, and snippets.

@ikrima
Created May 16, 2015 10:07
Show Gist options
  • Save ikrima/5568c60d812a2a593c71 to your computer and use it in GitHub Desktop.
Save ikrima/5568c60d812a2a593c71 to your computer and use it in GitHub Desktop.
Alembic Tangent Calculation
//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