51 #include "MeshCompiler.hh"
59 #ifdef ACG_MC_USE_STL_HASH
60 #include <unordered_map>
63 #endif // ACG_MC_USE_STL_HASH
65 #include <ACG/Geometry/GPUCacheOptimizer.hh>
66 #include <ACG/Geometry/Triangulator.hh>
112 MeshCompilerVertexCompare MeshCompiler::defaultVertexCompare;
114 void MeshCompiler::AdjacencyList::init(
int n )
122 count =
new unsigned char[n];
127 memset(start, -1, n *
sizeof(
int));
130 memset(count, 0, n *
sizeof(
unsigned char));
133 int MeshCompiler::AdjacencyList::getAdj(
const int i,
const int k )
const
135 assert(k < count[i]);
144 int MeshCompiler::AdjacencyList::getCount(
const int i )
const
149 void MeshCompiler::AdjacencyList::clear()
152 delete [] start; start = 0;
153 delete [] buf; buf = 0;
154 delete [] count; count = 0;
160 void MeshCompiler::computeAdjacency()
162 const int numVerts = input_[inputIDPos_].
count;
173 adjacencyVert_.init(numVerts);
176 for (
int i = 0; i < numFaces_; ++i)
180 for (
int k = 0; k < nCorners; ++k)
183 int vertex = getInputIndex(i, k, inputIDPos_);
185 adjacencyVert_.count[vertex]++;
193 for (
int i = 0; i < numVerts; ++i)
195 adjacencyVert_.start[i] = nCounter;
197 nCounter += adjacencyVert_.count[i];
199 adjacencyVert_.count[i] = 0;
203 adjacencyVert_.buf =
new int[nCounter];
204 adjacencyVert_.bufSize = nCounter;
207 for (
int i = 0; i < numFaces_; ++i)
211 for (
int k = 0; k < nCorners; ++k)
214 int vertex = getInputIndex(i, k, inputIDPos_);
215 int adjIdx = adjacencyVert_.start[vertex] + adjacencyVert_.count[vertex]++;
217 adjacencyVert_.buf[ adjIdx ] = i;
261 setAttribVec(inputIDPos_, _num, _data, _stride, _internalCopy, _fmt, _elementSize);
266 setAttribVec(inputIDNorm_, _num, _data, _stride, _internalCopy, _fmt, _elementSize);
271 setAttribVec(inputIDTexC_, _num, _data, _stride, _internalCopy, _fmt, _elementSize);
301 delete [] inbuf->internalBuf;
302 inbuf->internalBuf =
new char[size * _num];
303 inbuf->data = inbuf->internalBuf;
305 inbuf->stride = size;
310 for (
int i = 0; i < _num; ++i)
312 memcpy(inbuf->internalBuf + (
size_t)(size * i),
313 (
const char*)_data + (
size_t)(_stride * i),
321 inbuf->data = (
const char*)_data;
322 inbuf->stride = _stride ? _stride : size;
324 delete [] inbuf->internalBuf;
325 inbuf->internalBuf = 0;
330 inbuf->elementSize = _elementSize;
333 void MeshCompiler::WeldList::add(
const int _face,
const int _corner)
335 const int stride = meshComp->getVertexDeclaration()->getVertexStride();
338 char* vtx0 = workBuf + stride * list.size();
339 char* vtx1 = workBuf;
342 meshComp->getInputFaceVertexData(_face, _corner, vtx0);
344 bool matched =
false;
347 for (
size_t i = 0; i < list.size() && !matched; ++i)
349 WeldListEntry* it = &list[i];
353 if (cmpFunc->equalVertex(vtx0, vtx1, meshComp->getVertexDeclaration()))
359 e.faceId = _face; e.cornerId = _corner;
360 e.refFaceId = it->refFaceId; e.refCornerId = it->refCornerId;
374 e.faceId = _face; e.cornerId = _corner;
375 e.refFaceId = _face; e.refCornerId = _corner;
382 void MeshCompiler::weldVertices()
384 const int numVerts = input_[inputIDPos_].
count;
387 vertexWeldMapFace_.resize(numIndices_, -1);
388 vertexWeldMapCorner_.resize(numIndices_, -1);
392 for (
int i = 0; i < numVerts; ++i)
394 const int n = getAdjVertexFaceCount(i);
395 maxAdjCount = std::max(n, maxAdjCount);
400 char* vtxCompBuf =
new char[decl_.
getVertexStride() * (maxAdjCount + 1)];
403 weldList.meshComp =
this;
404 weldList.cmpFunc = vertexCompare_;
405 weldList.workBuf = vtxCompBuf;
407 weldList.list.reserve(maxAdjCount);
409 for (
int i = 0; i < numVerts; ++i)
413 weldList.list.clear();
416 for (
int k = 0; k < getAdjVertexFaceCount(i); ++k)
418 const int adjFace = getAdjVertexFace(i, k);
421 int adjCornerId = -1;
424 const int adjVertex = getInputIndex(adjFace, m, inputIDPos_);
433 assert(adjCornerId != -1);
437 const int weldMapOffset = getInputFaceOffset(adjFace) + adjCornerId;
439 if (vertexWeldMapFace_[weldMapOffset] >= 0)
442 weldList.add(adjFace, adjCornerId);
448 for (
size_t e = 0; e < weldList.list.size(); ++e)
450 const WeldListEntry* it = &weldList.list[e];
451 const int weldMapOffset = getInputFaceOffset(it->faceId) + it->cornerId;
453 if (vertexWeldMapFace_[weldMapOffset] >= 0)
457 vertexWeldMapFace_[weldMapOffset] = it->refFaceId;
458 vertexWeldMapCorner_[weldMapOffset] = it->refCornerId;
519 delete [] vtxCompBuf;
522 void MeshCompiler::fixWeldMap()
524 for (
int i = 0; i < numFaces_; ++i)
527 for (
int k = 0; k < fsize; ++k)
529 const int weldMapOffset = getInputFaceOffset(i) + k;
533 if (vertexWeldMapFace_[weldMapOffset] < 0)
535 vertexWeldMapFace_[weldMapOffset] = i;
536 vertexWeldMapCorner_[weldMapOffset] = k;
542 void MeshCompiler::findIsolatedVertices()
544 const int nVerts = input_[inputIDPos_].
count;
550 for (
int i = 0; i < nVerts; ++i)
556 isolatedVertices_.clear();
558 for (
int i = 0; i < nVerts; ++i)
561 isolatedVertices_.push_back(i);
565 void MeshCompiler::splitVertices()
597 const int numPositions = input_[inputIDPos_].
count;
600 int estimatedSplitCount = 0;
601 int numDifferentInputCounts = 0;
606 for (
int i = 0; i < numAttributes_; ++i)
608 if (i != inputIDPos_)
610 if (input_[i].count > numPositions)
612 const int diff = input_[i].
count - numPositions;
616 estimatedSplitCount = std::max(diff, estimatedSplitCount);
617 ++numDifferentInputCounts;
623 if (numDifferentInputCounts > 1)
626 estimatedSplitCount = int(
float(estimatedSplitCount) * 1.2f);
629 assert(estimatedSplitCount >= 0);
634 int maxSplitCount = 0;
638 if (numIndices_ > numPositions)
639 maxSplitCount = numIndices_ - numPositions;
646 if (constantFaceSize_)
647 sumFaceSize = numFaces_ * maxFaceSize_;
650 for (
int i = 0; i < numFaces_; ++i)
654 if (sumFaceSize > numPositions)
655 maxSplitCount = sumFaceSize - numPositions;
658 estimatedSplitCount = std::min(estimatedSplitCount, maxSplitCount);
666 numPositions + estimatedSplitCount,
669 faceBufSplit_.resize(numIndices_, -1);
674 for (
int i = 0; i < numFaces_; ++i)
677 for (
int k = 0; k < fsize; ++k)
688 const int idx = splitter_->
split(vertex);
691 setInputIndexSplit(i, k, idx);
703 findIsolatedVertices();
709 std::vector<int> IsoFix(splitter_->
numVerts, 0);
712 for (
int i = 0; i < splitter_->
numVerts; ++i)
717 IsoFix[i] = fixIndex;
727 for (
int i = 0; i < numFaces_; ++i)
730 for (
int k = 0; k < fsize; ++k)
733 int idx = getInputIndexSplit(i, k);
740 setInputIndexSplit(i, k, idx);
747 bool MeshCompiler_forceUnsharedFaceVertex_InnerValenceSorter(
const std::pair<int, int>& a,
const std::pair<int, int>& b )
749 return a.second > b.second;
752 void MeshCompiler::forceUnsharedFaceVertex()
762 std::vector<int> sharedVertices;
763 sharedVertices.resize(maxFaceSize_);
766 std::vector<int> tmpFaceVerts;
767 tmpFaceVerts.resize(maxFaceSize_);
797 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
800 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
807 std::vector< std::pair<int, int> > vertexPriorities(faceSize);
811 const int faceTris = faceSize - 2;
813 std::vector<RingTriangle> remainingTris(faceTris);
814 for (
int i = 0; i < faceTris; ++i)
815 remainingTris[i] = RingTriangle(i, &remainingTris[(i + faceTris - 1) % faceTris], &remainingTris[(i + 1) % faceTris]);
818 RingTriangle* currentTri = &remainingTris[0];
819 int numTrisCovered = 0;
821 while (numTrisCovered < faceTris)
824 for (
int k = 0; k < faceSize; ++k)
825 vertexPriorities[k] = std::pair<int, int>(k, 0);
827 RingTriangle* startTri = currentTri;
828 int numRemainingTris = faceTris - numTrisCovered;
829 for (
int t = 0; t < numRemainingTris; ++t)
831 for (
int k = 0; k < 3; ++k)
833 int cornerID = -1 - triIndexBuffer_[(triCounter + currentTri->id) * 3 + k];
834 ++vertexPriorities[cornerID].second;
836 currentTri = currentTri->next;
838 assert(currentTri == startTri);
841 std::sort(vertexPriorities.begin(), vertexPriorities.end(), MeshCompiler_forceUnsharedFaceVertex_InnerValenceSorter);
845 int goodVertexID = -1;
846 int bestValence = -1;
847 for (
int k = 0; k < faceSize && vertexPriorities[k].second; ++k)
849 int cornerID = vertexPriorities[k].first;
850 int vertexID = getInputIndexSplit(faceID, cornerID);
852 int valence = vertexPriorities[k].second;
854 if (vertexID >= numInitialVerts || (VertexUsed[vertexID] == faceID))
858 goodCorner = cornerID;
859 goodVertexID = vertexID;
860 bestValence = valence;
863 else if (VertexUsed[vertexID] < 0 && bestValence < valence)
865 goodCorner = cornerID;
866 goodVertexID = vertexID;
867 bestValence = valence;
878 goodCorner = vertexPriorities[0].first;
882 setInputIndexSplit(faceID, goodCorner, goodVertexID);
887 VertexUsed[goodVertexID] = faceID;
891 for (
int t = 0; t < numRemainingTris; ++t)
894 for (
int k = 0; k < 3; ++k)
896 int cornerID = -1 - triIndexBuffer_[(triCounter + currentTri->id) * 3 + k];
898 if (cornerID == goodCorner)
901 int rotCount = 3 - k;
906 triIndexBuffer_[(triCounter + currentTri->id) * 3],
907 triIndexBuffer_[(triCounter + currentTri->id) * 3 + 1],
908 triIndexBuffer_[(triCounter + currentTri->id) * 3 + 2],
912 for (
int i = 0; i < 3; ++i)
913 triIndexBuffer_[(triCounter + currentTri->id) * 3 + (i + rotCount) % 3] = tmpTriVerts[i];
919 currentTri->prev->next = currentTri->next;
920 currentTri->next->prev = currentTri->prev;
925 currentTri = currentTri->next;
931 triCounter += faceSize - 2;
935 numInitialVerts = VertexUsed.size();
938 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
940 int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
946 memset(&sharedVertices[0], 0,
sizeof(
int) * maxFaceSize_);
950 for (
int v0 = 0; v0 < numCorners && numShared < numCorners; ++v0)
952 if (sharedVertices[v0])
955 const int vertexID0 = getInputIndexSplit(faceID, v0);
959 if (vertexID0 < numInitialVerts && (VertexUsed[vertexID0] >= 0 && VertexUsed[vertexID0] != faceID))
961 sharedVertices[v0] =
true;
968 if (numShared == numCorners)
977 else if (sharedVertices[0])
981 for (
int i = 0; i < numCorners; ++i)
982 x += sharedVertices[i];
983 assert(x < numCorners);
989 for (
int i = 0; i < numCorners; ++i)
990 tmpFaceVerts[i] = getInputIndexSplit(faceID, i);
995 for (; rotCount < numCorners; ++rotCount)
997 if (!sharedVertices[rotCount % numCorners])
999 if (tmpFaceVerts[rotCount] < numInitialVerts)
1000 VertexUsed[tmpFaceVerts[rotCount]] = faceID;
1005 assert(rotCount < numCorners);
1008 rotCount = numCorners - rotCount;
1010 for (
int i = 0; i < numCorners; ++i)
1014 triIndexBuffer_[triCounter * 3 + i] = tmpFaceVerts[(i + numCorners - rotCount) % numCorners];
1020 const int idx = getInputIndexSplit(faceID, 0);
1021 if (idx < numInitialVerts)
1022 VertexUsed[idx] = faceID;
1026 triCounter += numCorners - 2;
1035 _out[k] = getInputIndex(_face, _corner, k);
1044 if (!vertexWeldMapFace_.empty())
1046 const int offset = getInputFaceOffset(i);
1048 face = vertexWeldMapFace_[offset + j];
1049 corner = vertexWeldMapCorner_[offset + j];
1053 _out[k] = getInputIndex(face, corner, k);
1058 for (
int i = 0; i < numAttributes_; ++i)
1062 const int idx = getInputIndex(_faceId, _corner, i);
1075 deleteFaceInputeData_ =
false;
1083 curFaceInputPos_ = 0;
1089 constantFaceSize_ =
false;
1091 provokingVertex_ = -1;
1092 provokingVertexSetByUser_ =
false;
1096 inputIDNorm_ = inputIDPos_ = inputIDTexC_ = -1;
1112 vertexCompare_ = &defaultVertexCompare;
1116 MeshCompiler::~MeshCompiler()
1118 if (deleteFaceInputeData_)
1125 int MeshCompiler::getInputIndexOffset(
const int _face,
const int _corner )
const
1128 assert(_face < numFaces_);
1131 const int baseIdx = int(faceStart_.empty() ? maxFaceSize_ * _face : faceStart_[_face]);
1132 return baseIdx + _corner;
1136 void MeshCompiler::setInputIndexSplit(
const int _face,
const int _corner,
const int _val )
1138 const int offset = getInputIndexOffset(_face, _corner);
1144 faceBufSplit_[offset] = _val;
1147 int MeshCompiler::getInputIndexSplit(
const int _face,
const int _corner )
const
1149 const int offset = getInputIndexOffset(_face, _corner);
1151 return faceBufSplit_[offset];
1157 MeshCompilerDefaultFaceInput::MeshCompilerDefaultFaceInput(
int _numFaces,
int _numIndices)
1158 : numFaces_(_numFaces), numIndices_(_numIndices)
1160 faceOffset_.resize(numFaces_, -1);
1161 faceSize_.resize(numFaces_, 0);
1162 faceData_[0].reserve(_numIndices);
1173 numFaces_ = _numFaces;
1175 faceInput_ = internalInput;
1176 deleteFaceInputeData_ =
true;
1183 if (!_v || _attrID < 0)
return;
1191 input->setFaceData(_i, _numEdges, _v, _attrID);
1197 int tmp[3] = {_v0, _v1, _v2};
1203 MeshCompiler::VertexSplitter::VertexSplitter(
int _numAttribs,
1206 float _estBufferIncrease)
1207 : numAttribs(_numAttribs), numVerts(_numVerts), numBaseVerts(_numVerts)
1209 if (_numWorstCase <= 0)
1210 _numWorstCase = int(
float(_numVerts) * (_estBufferIncrease + 1.0f));
1212 const int maxCount = (_numAttribs + 1) * (_numWorstCase + 1);
1215 splits.resize(maxCount, -1);
1223 MeshCompiler::VertexSplitter::~VertexSplitter()
1230 int pos = vertex[0];
1231 int next = getNext(pos);
1238 setAttribs(pos, vertex);
1247 int bSearchSplit = 1;
1250 while (pos >= 0 && bSearchSplit)
1253 if (!memcmp(vertex, getAttribs(pos), numAttribs *
sizeof(
int)))
1260 next = getNext(pos);
1262 if (next < 0)
break;
1263 if (next == pos)
break;
1271 int newID = numVerts++;
1273 setNext(pos, newID);
1274 setAttribs(newID, vertex);
1286 int MeshCompiler::VertexSplitter::getNext(
const int id)
1290 const int entryIdx =
id * (1 + numAttribs);
1293 if (entryIdx >= (
int)splits.size())
1295 splits.resize(entryIdx + numAttribs * 100, -1);
1299 return splits[entryIdx];
1302 void MeshCompiler::VertexSplitter::setNext(
const int id,
const int next)
1306 const int entryIdx =
id * (1 + numAttribs);
1309 if (entryIdx >= (
int)splits.size())
1311 splits.resize(entryIdx + numAttribs * 100, -1);
1315 splits[entryIdx] = next;
1318 int* MeshCompiler::VertexSplitter::getAttribs(
const int id)
1322 const int entryIdx =
id * (1 + numAttribs) + 1;
1325 if (entryIdx + numAttribs >= (
int)splits.size())
1327 splits.resize(entryIdx + numAttribs * 100, -1);
1331 return &splits[0] + entryIdx;
1334 void MeshCompiler::VertexSplitter::setAttribs(
const int id,
int* attr )
1336 memcpy(getAttribs(
id), attr, numAttribs *
sizeof(
int));
1341 return (vertexPosID < numBaseVerts) && (getNext(vertexPosID) < 0);
1346 MeshCompiler::VertexElementInput::VertexElementInput()
1347 : internalBuf(0), data(0),
1348 count(0), stride(0), attrSize(0),
1349 fmt(0), elementSize(-1)
1353 MeshCompiler::VertexElementInput::~VertexElementInput()
1355 delete [] internalBuf;
1365 void MeshCompiler::triangulate()
1371 for (
int i = 0; i < numFaces_; ++i)
1376 triIndexBuffer_.resize(numTris * 3);
1388 int indexCounter = 0;
1390 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
1393 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1402 for (
int k = 0; k < 3; ++k)
1403 triIndexBuffer_[indexCounter++] = -1 - k;
1408 std::vector<Vec3f> poly(faceSize);
1409 for (
int k = 0; k < faceSize; ++k)
1411 VertexElement posElement;
1412 posElement.type_ = GL_FLOAT;
1413 posElement.numElements_ = 3;
1415 posElement.pointer_ = 0;
1416 posElement.shaderInputName_ = 0;
1417 posElement.divisor_ = 0;
1418 posElement.vbo_ = 0;
1419 int posID = getInputIndexSplit(faceID, k);
1420 input_[inputIDPos_].
getElementData(posID, &poly[k], &posElement);
1422 Triangulator tris(poly);
1429 for (
int k = 0; k < 3; ++k)
1430 triIndexBuffer_[indexCounter++] = -1 - k;
1432 for (
int k = 3; k < faceSize; ++k)
1437 triIndexBuffer_[indexCounter++] = -1;
1438 triIndexBuffer_[indexCounter++] = -1 - (k - 1);
1439 triIndexBuffer_[indexCounter++] = -1 - k;
1447 for (
int i = 0; i < tris.numTriangles(); ++i)
1450 for (
int k = 0; k < 3; ++k)
1452 int cornerID = tris.index(i * 3 + k);
1454 triIndexBuffer_[indexCounter++] = -1 - cornerID;
1464 for (
int i = 0; i < numSubsets_; ++i)
1466 subsets_[i].startIndex = 0xffffffff;
1467 subsets_[i].numTris = 0;
1472 for (
int i = 0; i < numTris; ++i)
1474 const int faceID = mapTriToInputFace(i);
1484 for (
int i = 0; i < numSubsets_; ++i)
1487 subsets_[i].startIndex = subsets_[i-1].startIndex + subsets_[i-1].numTris * 3;
1489 subsets_[i].startIndex = 0;
1495 void MeshCompiler::resolveTriangulation()
1499 if (provokingVertex_ >= 0)
1501 for (
int i = 0; i < numTris_; ++i)
1503 for (
int k = 0; k < 3 - provokingVertex_; ++k)
1505 const int tmp = triIndexBuffer_[i*3];
1506 triIndexBuffer_[i*3] = triIndexBuffer_[i*3 + 1];
1507 triIndexBuffer_[i*3 + 1] = triIndexBuffer_[i*3 + 2];
1508 triIndexBuffer_[i*3 + 2] = tmp;
1514 for (
int drawTriID = 0; drawTriID < numTris_; ++drawTriID)
1516 if (triIndexBuffer_[drawTriID * 3] < 0)
1523 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1525 for (
int k = 0; k < 3; ++k)
1527 int negCornerID = triIndexBuffer_[drawTriID * 3 + k];
1528 int cornerID = -1 - negCornerID;
1529 triIndexBuffer_[drawTriID * 3 + k] = getInputIndexSplit(faceID, cornerID);
1535 void MeshCompiler::sortFacesByGroup()
1542 std::map<int, unsigned int> GroupIDs;
1545 for (
int face = 0; face < numFaces_; ++face)
1549 if (GroupIDs.find(texID) == GroupIDs.end())
1550 GroupIDs[texID] = face;
1554 numSubsets_ = int(GroupIDs.size());
1555 subsets_.resize(numSubsets_);
1557 if (numSubsets_ > 1)
1558 faceSortMap_.resize(numFaces_, -1);
1562 std::map<int, unsigned int>::const_iterator it = GroupIDs.begin();
1563 unsigned int numSortedFaces = 0;
1565 for (
unsigned int i = 0; it != GroupIDs.end(); ++i, ++it)
1568 subsets_[i].id = it->first;
1571 subsetIDMap_[it->first] = i;
1574 subsets_[i].numFaces = 0;
1575 subsets_[i].startFace = numSortedFaces;
1578 subsets_[i].startIndex = 0;
1579 subsets_[i].numTris = 0;
1581 if (numSubsets_ == 1)
1583 subsets_[i].numFaces = numFaces_;
1589 for (
int k = it->second; k < numFaces_; ++k)
1593 if (texID == subsets_[i].
id)
1595 subsets_[i].numFaces++;
1597 faceSortMap_[numSortedFaces++] = k;
1606 void MeshCompiler::optimize()
1611 for (
int i = 0; i < numSubsets_; ++i)
1613 Subset* pSubset = &subsets_[i];
1615 const int vcacheSize = 24;
1616 GPUCacheOptimizerTipsify copt(vcacheSize, pSubset->numTris,
numDrawVerts_, 4, &triIndexBuffer_[0] + pSubset->startIndex);
1617 copt.WriteIndexBuffer(4, &
indices_[pSubset->startIndex]);
1621 const unsigned int StartTri = pSubset->startIndex/3;
1622 for (
unsigned int k = 0; k < pSubset->numTris; ++k)
1624 const unsigned int SrcTri = copt.GetTriangleMap()[k];
1625 triOptMap_[k + StartTri] = SrcTri + StartTri;
1632 unsigned int* vertexOptMap =
new unsigned int[
numDrawVerts_];
1638 for (
int i = 0; i < numTris_ * 3; ++i)
1644 for (
int i = 0; i < numFaces_; ++i)
1648 for (
int k = 0; k < fsize; ++k)
1650 int oldVertex = getInputIndexSplit(i, k);
1652 int newVertex = vertexOptMap[oldVertex];
1654 setInputIndexSplit(i, k, newVertex);
1658 delete [] vertexOptMap;
1663 void MeshCompiler::build(
bool _weldVertices,
bool _optimizeVCache,
bool _needPerFaceAttribute,
bool _keepIsolatedVertices)
1666 const bool dbg_MemProfiling =
false;
1691 if (dbg_MemProfiling)
1692 std::cout <<
"computing adjacency.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1696 if (dbg_MemProfiling)
1697 std::cout <<
"vertex welding.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1702 adjacencyVert_.clear();
1705 if (dbg_MemProfiling)
1706 std::cout <<
"vertex splitting.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1710 if (dbg_MemProfiling)
1711 std::cout <<
"splitting done.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1715 delete splitter_; splitter_ = 0;
1718 std::vector< int > emptyVec;
1719 vertexWeldMapFace_.swap(emptyVec);
1721 std::vector< int > emptyVec;
1722 vertexWeldMapCorner_.swap(emptyVec);
1736 if (dbg_MemProfiling)
1737 std::cout <<
"sorting by mat.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1767 if (dbg_MemProfiling)
1768 std::cout <<
"triangulate.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1773 if (_needPerFaceAttribute)
1775 if (dbg_MemProfiling)
1776 std::cout <<
"force unshared vertex.., memusage = " << (
getMemoryUsage() / (1024 * 1024)) << std::endl;
1782 if (provokingVertex_ < 0)
1783 provokingVertex_ = 2;
1785 provokingVertex_ = provokingVertex_ % 3;
1788 forceUnsharedFaceVertex();
1791 resolveTriangulation();
1808 if (_optimizeVCache)
1810 if (dbg_MemProfiling)
1811 std::cout <<
"optimizing.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1815 else if (!triIndexBuffer_.empty())
1818 if (dbg_MemProfiling)
1819 std::cout <<
"creating maps.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1823 std::vector< int > emptyVec;
1824 triIndexBuffer_.swap(emptyVec);
1827 createVertexMap(_keepIsolatedVertices);
1832 std::vector< int > emptyVec;
1835 std::vector< int > emptyVec;
1838 std::vector< int > emptyVec;
1839 faceSortMap_.swap(emptyVec);
1842 if (dbg_MemProfiling)
1843 std::cout <<
"finished.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1864 std::cerr <<
"setAttrib failed: please allocate internal input buffer before using setAttrib" << std::endl;
1868 assert(inbuf->
count > _v);
1875 assert (_attrIdx >= 0);
1878 return input_[_attrIdx].
count;
1882 int MeshCompiler::mapTriToInputFace(
const int _tri )
const
1885 assert(_tri < numTris_);
1888 assert(sortFaceID >= 0);
1889 assert(sortFaceID < numFaces_);
1891 int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1892 assert(faceID >= 0);
1893 assert(faceID < numFaces_);
1900 if (faceGroupIDs_.empty())
1903 return (
int)faceGroupIDs_[_faceID];
1908 return subsetIDMap_[_groupID];
1913 return &subsets_[_i];
1918 std::stringstream str;
1926 const void* data =
static_cast<const char*
>(v) + (
size_t)el->
pointer_;
1928 switch ( el->
type_ )
1932 const double* d0 =
static_cast<const double*
>(data);
1935 str << d0[k] <<
", ";
1941 const float* f0 =
static_cast<const float*
>(data);
1944 str << f0[k] <<
", ";
1948 case GL_UNSIGNED_INT:
1950 const int* i0 =
static_cast<const int*
>(data);
1953 str << i0[k] <<
", ";
1957 case GL_UNSIGNED_SHORT:
1959 const short* i0 =
static_cast<const short*
>(data);
1962 str << i0[k] <<
", ";
1966 case GL_UNSIGNED_BYTE:
1968 const char* i0 =
static_cast<const char*
>(data);
1971 str << ((int)i0[k]) <<
", ";
1974 default: std::cerr <<
"MeshCompiler: vertexToString() unknown type: " << el->
type_ << std::endl;
1987 int numTotalErrors = 0;
1992 file.open(_filename);
1994 if (file || !_filename)
2003 file <<
"checking draw_tri <-> face mapping ..\n";
2007 int numTrisOfFace = 0;
2010 for (
int k = 0; k < numTrisOfFace; ++k)
2017 if (face != dbg_face)
2020 file <<
"error: face " << face <<
" -> (numTris: " << numTrisOfFace <<
", tri " << tri <<
" -> face " << dbg_face <<
")\n";
2027 file << numErrors <<
" errors found\n\n";
2028 numTotalErrors += numErrors;
2034 file <<
"checking (face, corner) -> vbo by comparing vertex data ..\n";
2043 for (
int k = 0; k < fsize; ++k)
2045 char* v0 = vtxCmpData;
2061 if (!verifyCmp.equalVertex(v0, v1, &decl_))
2067 file <<
"error: (face " << face <<
", corner " << k <<
") -> vertex " << vertex <<
": " << vertexData0.c_str() <<
" != "<< vertexData1.c_str() <<
"\n";
2075 file << numErrors <<
" errors found\n\n";
2076 numTotalErrors += numErrors;
2084 file <<
"checking vbo -> (face, corner) by comparing vertex data ..\n";
2089 int face = 0, corner = 0;
2092 char* v0 = vtxCmpData;
2116 if (!vertexCompare_->equalVertex(v0, v1, &decl_))
2122 file <<
"error: vertex " << vertex <<
" -> (face " << face <<
", corner " << corner <<
"): " << vertexData0.c_str() <<
" != " << vertexData1.c_str() <<
"\n";
2128 file << numErrors <<
" errors found\n\n";
2129 numTotalErrors += numErrors;
2133 delete [] vtxCmpData;
2139 if (provokingVertex_ >= 0)
2142 file <<
"checking unshared per face vertices ..\n";
2145 std::vector< std::map<int, int> > VertexRefs;
2148 for (
int face = 0; face < numFaces_; ++face)
2153 for (
int k = 0; k < nTris; ++k)
2157 int faceVertex =
getIndex(tri * 3 + provokingVertex_);
2159 VertexRefs[faceVertex][face] = 1;
2168 if (VertexRefs[i].size() > 1)
2172 file <<
"error : vertex " << i <<
" is referenced by " << VertexRefs[i].size() <<
" faces: ";
2174 for (std::map<int, int>::iterator it = VertexRefs[i].begin(); it != VertexRefs[i].end(); ++it)
2175 file << it->first <<
", ";
2184 file << numErrors <<
" errors found\n\n";
2185 numTotalErrors += numErrors;
2194 file <<
"checking face group sorting ..\n";
2200 for (
int k = 0; k < (int)sub->numTris; ++k)
2207 if (grID != sub->id)
2210 file <<
"error: face " << faceID <<
" with group-id " << grID <<
" was mapped to subset-group " << sub->id <<
"\n";
2219 file << numErrors <<
" errors found\n\n";
2220 numTotalErrors += numErrors;
2229 file <<
"checking triangulation ..\n";
2231 for (
int i = 0; i < numFaces_; ++i)
2235 std::vector<int> facePositions(faceSize, -1);
2237 for (
int k = 0; k < faceSize; ++k)
2238 facePositions[k] = getInputIndex(i, k, inputIDPos_);
2240 int numFaceTris = 0;
2243 for (
int t = 0; t < numFaceTris; ++t)
2247 int triPosOccurrence[3] = {-1, -1, -1};
2249 for (
int k = 0; k < 3; ++k)
2251 int vertexID =
getIndex(triID * 3 + k);
2253 int originalFace = -1, originalCorner = -1;
2257 for (
int m = 0; m < faceSize; ++m)
2259 if (posID == facePositions[m])
2261 triPosOccurrence[k] = m;
2266 if (triPosOccurrence[k] < 0)
2269 file <<
"error: vertex at triangulated face " << i <<
" at triangle " << t <<
" at corner " << k <<
"is not even part of the original face!\n";
2276 int numInversions = 0;
2278 for (
int k = 0; k < 3; ++k)
2280 int p1 = triPosOccurrence[k];
2281 int p2 = triPosOccurrence[(k + 1) % 3];
2287 if (numInversions > 1)
2290 file <<
"error: triangulation of face " << i <<
" at triangle " << t <<
" has flipped winding order!\n";
2298 file << numErrors <<
" errors found\n\n";
2299 numTotalErrors += numErrors;
2305 return numTotalErrors == 0;
2313 file.open(_filename);
2317 for (
int i = 0; i < numAttributes_; ++i)
2321 file <<
"attribute[" << i <<
"]: internalbuf " << ((
const void*)inp->
internalBuf) <<
", data " << ((
const void*)inp->
data) <<
", count " << inp->
count <<
", stride " << inp->
stride <<
", attrSize " << inp->
attrSize <<
"\n";
2325 file <<
"faces " << numFaces_ <<
"\nindices " << numIndices_ <<
"\n";
2327 if (!vertexWeldMapFace_.empty())
2329 for (
int i = 0; i < numFaces_; ++i)
2333 int face = vertexWeldMapFace_[getInputFaceOffset(i) + k];
2334 int corner = vertexWeldMapCorner_[getInputFaceOffset(i) + k];
2335 file <<
"vertexWeldMap_[" << i <<
", "<<k<<
"] = ["<<face<<
", "<<corner<<
"]\n";
2340 for (
size_t i = 0; i < faceBufSplit_.size(); ++i)
2341 file <<
"faceBufSplit_["<<i<<
"] = "<<faceBufSplit_[i]<<
"\n";
2345 for (
size_t i = 0; i < faceGroupIDs_.size(); ++i)
2346 file <<
"faceGroupIDs_["<<i<<
"] = "<<faceGroupIDs_[i]<<
"\n";
2350 for (
size_t i = 0; i < faceSortMap_.size(); ++i)
2351 file <<
"faceSortMap_["<<i<<
"] = "<<faceSortMap_[i]<<
"\n";
2355 for (
size_t i = 0; i < triIndexBuffer_.size()/3; ++i)
2356 file <<
"tri["<<i<<
"] = "<<triIndexBuffer_[i*3+1]<<
" "<<triIndexBuffer_[i*3+1]<<
" "<<triIndexBuffer_[i*3+2]<<
"\n";
2360 for (
size_t i = 0; i < subsets_.size(); ++i)
2362 const Subset* sub = &subsets_[i];
2363 file <<
"subset["<<i<<
"]: id "<<sub->id<<
", startIndex "<<sub->startIndex<<
", numTris "<<sub->numTris<<
", numFaces "<<sub->numFaces<<
", startFace "<<sub->startFace<<
"\n";
2368 for (std::map<int, int>::const_iterator it = subsetIDMap_.begin();
2369 it != subsetIDMap_.end(); ++it)
2370 file <<
"subsetIDMap["<<it->first<<
"] = "<<it->second<<
"\n";
2374 for (
int i = 0; i < numFaces_; ++i)
2386 file <<
"mapToOriginalVertexID["<<i<<
"] = ["<<f<<
", "<<c<<
"]\n";
2389 file <<
"\n\nadjacencyVert\n";
2390 adjacencyVert_.dbgdump(file);
2397 for (
int i = 0; i < numFaces_; ++i)
2405 file <<
"data["<<i<<
", "<<k<<
"] = ("<<vtx[0]<<
" "<<vtx[1]<<
" "<<vtx[2]<<
") ("<<vtx[3]<<
" "<<vtx[4]<<
") ("<<vtx[5]<<
" "<<vtx[6]<<
" "<<vtx[7]<<
")\n";
2414 void MeshCompiler::AdjacencyList::dbgdump(std::ofstream& file)
const
2418 for (
int i = 0; i < num; ++i)
2420 for (
int k = 0; k < getCount(i); ++k)
2421 file <<
"adj["<<i<<
"]["<<k<<
"] = "<<getAdj(i,k)<<
"\n";
2429 if (count == 0 || !data)
2431 memset(_dst, 0, attrSize);
2438 if (_idx < 0 || _idx >= count)
2440 memset(_dst, 0, attrSize);
2444 const void* dataAdr =
static_cast<const char*
>(data) + (
size_t)(_idx * stride);
2446 if (fmt == 0 || elementSize == -1 || fmt == _desc->
type_)
2447 memcpy(_dst, dataAdr, attrSize);
2451 int data_i[4] = {0,0,0,0};
2452 double data_d[4] = {0.0, 0.0, 0.0, 0.0};
2455 for (
int i = 0; i < elementSize; ++i)
2459 case GL_FLOAT: data_d[i] = (
static_cast<const float*
>(dataAdr))[i];
break;
2460 case GL_DOUBLE: data_d[i] = (
static_cast<const double*
>(dataAdr))[i];
break;
2462 case GL_UNSIGNED_INT:
2463 case GL_INT: data_i[i] = (
static_cast<const int*
>(dataAdr))[i];
break;
2465 case GL_UNSIGNED_SHORT:
2466 case GL_SHORT: data_i[i] = (
static_cast<const short*
>(dataAdr))[i];
break;
2468 case GL_UNSIGNED_BYTE:
2469 case GL_BYTE: data_i[i] = (
static_cast<const short*
>(dataAdr))[i];
break;
2471 default: std::cerr <<
"MeshCompiler: unknown data format - " << fmt << std::endl;
break;
2477 memset(_dst, 0, attrSize);
2480 if (fmt == GL_FLOAT || fmt == GL_DOUBLE)
2482 for (
int i = 0; i < (int)_desc->
numElements_ && i < (
int)elementSize; ++i)
2484 switch (_desc->
type_)
2486 case GL_FLOAT: ((
float*)_dst)[i] = (float)data_d[i];
break;
2487 case GL_DOUBLE: ((
double*)_dst)[i] = (double)data_d[i];
break;
2489 case GL_UNSIGNED_INT:
2490 case GL_INT: ((
int*)_dst)[i] = (int)data_d[i];
break;
2492 case GL_UNSIGNED_BYTE:
2493 case GL_BYTE: ((
char*)_dst)[i] = (char)data_d[i];
break;
2495 case GL_UNSIGNED_SHORT:
2496 case GL_SHORT: ((
short*)_dst)[i] = (short)data_d[i];
break;
2504 for (
int i = 0; i < (int)_desc->
numElements_ && i < (
int)elementSize; ++i)
2506 switch (_desc->
type_)
2508 case GL_FLOAT: ((
float*)_dst)[i] = (float)data_i[i];
break;
2509 case GL_DOUBLE: ((
double*)_dst)[i] = (double)data_i[i];
break;
2511 case GL_UNSIGNED_INT:
2512 case GL_INT: ((
int*)_dst)[i] = (int)data_i[i];
break;
2514 case GL_UNSIGNED_BYTE:
2515 case GL_BYTE: ((
char*)_dst)[i] = (char)data_i[i];
break;
2517 case GL_UNSIGNED_SHORT:
2518 case GL_SHORT: ((
short*)_dst)[i] = (short)data_i[i];
break;
2535 file.open(_filename);
2545 if (inputIDPos_ >= 0)
2548 file <<
"v "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2551 if (inputIDNorm_ >= 0)
2554 file <<
"vn "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2557 if (inputIDTexC_ >= 0)
2560 file <<
"vt "<<pos[0]<<
" "<<pos[1]<<
"\n";
2565 for (
int i = 0; i < numTris_; ++i)
2567 if (!inputIDTexC_ && !inputIDNorm_)
2570 else if (!inputIDTexC_)
2571 file <<
"f "<<indices_[i*3]+1<<
"/"<<indices_[i*3]+1<<
" "<<indices_[i*3+1]+1<<
"/"<<indices_[i*3+1]+1<<
" "<<indices_[i*3+2]+1<<
"/"<<indices_[i*3+2]+1<<
"\n";
2574 file <<
"f "<<indices_[i*3]+1<<
"/"<<indices_[i*3]+1<<
"/"<<indices_[i*3]+1<<
" "<<indices_[i*3+1]+1<<
"/"<<indices_[i*3+1]+1<<
"/"<<indices_[i*3+1]+1<<
" "<<indices_[i*3+2]+1<<
"/"<<indices_[i*3+2]+1<<
"/"<<indices_[i*3+2]+1<<
"\n";
2587 const int nVerts = (inputIDPos_ >= 0) ? input_[inputIDPos_].count : 0;
2593 file.open(_filename);
2599 for (
int i = 0; i < nVerts; ++i)
2605 file <<
"v "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2608 if (inputIDTexC_ >= 0)
2614 for (
int i = 0; i < vei->
count; ++i)
2617 file <<
"vt "<<pos[0]<<
" "<<pos[1]<<
"\n";
2622 if (inputIDNorm_ >= 0)
2628 for (
int i = 0; i < vei->
count; ++i)
2631 file <<
"vn "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2638 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2640 std::string strLine =
"f ";
2645 for (
int k = 0; k < size; ++k)
2647 if (inputIDNorm_>=0 && inputIDTexC_>=0)
2651 else if (inputIDNorm_ >= 0)
2653 else if (inputIDTexC_ >= 0)
2661 file << strLine.c_str() <<
"\n";
2674 const int nVerts = (inputIDPos_ >= 0) ? input_[inputIDPos_].count : 0;
2675 const int nNormals = (inputIDNorm_ >= 0) ? input_[inputIDNorm_].count : 0;
2676 const int nTexC = (inputIDTexC_ >= 0) ? input_[inputIDTexC_].count : 0;
2678 if (!_seperateFiles)
2714 file = fopen(_filename,
"wb");
2718 const int nFaces = faceInput_->getNumFaces();
2719 fwrite(&nFaces, 4, 1, file);
2721 fwrite(&nVerts, 4, 1, file);
2722 fwrite(&nNormals, 4, 1, file);
2723 fwrite(&nTexC, 4, 1, file);
2725 int faceBufSize = 0;
2727 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2730 fwrite(&faceBufSize, 4, 1, file);
2734 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2737 fwrite(&fsize, 4, 1, file);
2740 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2742 for (
int k = 0; k < faceInput_->
getFaceSize(i); ++k)
2745 fwrite(&idx, 4, 1, file);
2749 if (inputIDTexC_ >= 0)
2751 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2753 for (
int k = 0; k < faceInput_->
getFaceSize(i); ++k)
2756 fwrite(&idx, 4, 1, file);
2761 if (inputIDNorm_ >= 0)
2763 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2765 for (
int k = 0; k < faceInput_->
getFaceSize(i); ++k)
2768 fwrite(&idx, 4, 1, file);
2776 for (
int i = 0; i < nVerts; ++i)
2782 fwrite(pos, 4, 3, file);
2785 if (inputIDTexC_ >= 0)
2791 for (
int i = 0; i < vei->
count; ++i)
2794 fwrite(pos, 4, 2, file);
2799 if (inputIDNorm_ >= 0)
2805 for (
int i = 0; i < vei->
count; ++i)
2808 fwrite(pos, 4, 3, file);
2815 fwrite(&adjacencyVert_.num, 4, 1, file);
2816 fwrite(&adjacencyVert_.bufSize, 4, 1, file);
2818 fwrite(adjacencyVert_.start, 4, adjacencyVert_.num, file);
2819 fwrite(adjacencyVert_.count, 1, adjacencyVert_.num, file);
2820 fwrite(adjacencyVert_.buf, 4, adjacencyVert_.bufSize, file);
2829 FILE* file = fopen(
"../mesh_fsize.bin",
"wb");
2831 for (
int i = 0; i < numFaces_; ++i)
2833 unsigned char fsize = (
unsigned char)faceInput_->
getFaceSize(i);
2834 fwrite(&fsize, 1, 1, file);
2839 file = fopen(
"../mesh_fdata_pos.bin",
"wb");
2841 for (
int i = 0; i < numFaces_; ++i)
2843 for (
int k = 0; k < faceInput_->
getFaceSize(i); ++k)
2846 fwrite(&idx, 4, 1, file);
2852 if (inputIDTexC_ >= 0)
2854 file = fopen(
"../mesh_fdata_texc.bin",
"wb");
2856 for (
int i = 0; i < numFaces_; ++i)
2858 for (
int k = 0; k < faceInput_->
getFaceSize(i); ++k)
2861 fwrite(&idx, 4, 1, file);
2868 if (inputIDNorm_ >= 0)
2870 file = fopen(
"../mesh_fdata_norm.bin",
"wb");
2872 for (
int i = 0; i < numFaces_; ++i)
2874 for (
int k = 0; k < faceInput_->
getFaceSize(i); ++k)
2877 fwrite(&idx, 4, 1, file);
2886 file = fopen(
"../mesh_vdata_pos.bin",
"wb");
2887 for (
int i = 0; i < nVerts; ++i)
2893 fwrite(pos, 4, 3, file);
2897 if (inputIDTexC_ >= 0)
2899 file = fopen(
"../mesh_vdata_texc.bin",
"wb");
2905 for (
int i = 0; i < vei->
count; ++i)
2908 fwrite(pos, 4, 2, file);
2915 if (inputIDNorm_ >= 0)
2917 file = fopen(
"../mesh_vdata_norm.bin",
"wb");
2923 for (
int i = 0; i < vei->
count; ++i)
2926 fwrite(pos, 4, 3, file);
2943 int tmp[] = {_v0, _v1, _v2};
2954 int tmp[] = {_v0, _v1, _v2};
2966 int tmp[] = {_v0, _v1, _v2};
2972 int faceID, cornerID;
2978 for (
int i = 0; i < numAttributes_; ++i)
2982 int idx = getInputIndex(faceID, cornerID, i);
2991 for (
int i = 0; i < numAttributes_; ++i)
3002 assert(_i < numTris_ * 3);
3006 void MeshCompiler::createVertexMap(
bool _keepIsolatedVerts)
3013 if (_keepIsolatedVerts)
3021 for (
int i = 0; i < numFaces_; ++i)
3024 for (
int k = 0; k < fsize; ++k)
3027 int vertexID = getInputIndexSplit(i, k);
3029 vertexMapCorner_[vertexID] = k;
3033 if (_keepIsolatedVerts)
3050 vertexMapCorner_[i] < 0)
3051 std::cerr <<
"mesh-assembler: vertexMap error at index: " << i << std::endl;
3054 std::cerr <<
"mesh-assembler: vertexMap error at index: " << i << std::endl;
3061 void MeshCompiler::createFaceMap()
3068 for (
int i = 0; i < numTris_; ++i)
3077 if (!faceSortMap_.empty())
3078 faceID = faceSortMap_[faceID];
3090 faceToTriMapOffset_.clear();
3091 if (!constantFaceSize_)
3093 faceToTriMapOffset_.resize(numTris_, -1);
3096 for (
int i = 0; i < numFaces_; ++i)
3098 faceToTriMapOffset_[i] = offset;
3102 offset += fsize - 2;
3110 for (
int i = 0; i < numTris_; ++i)
3116 int offset = constantFaceSize_ ? (faceID * (maxFaceSize_ - 2)) : faceToTriMapOffset_[faceID];
3121 while (
faceToTriMap_[offset + triNo] != -1 && triNo + offset < numTris_)
3138 file = fopen(_filename,
"wt");
3142 fprintf(file,
"vertex-adjacency: \n");
3143 for (
int i = 0; i < input_[inputIDPos_].
count; ++i)
3146 int count = getAdjVertexFaceCount(i);
3148 std::vector<int> sortedList(count);
3149 for (
int k = 0; k < count; ++k)
3150 sortedList[k] = getAdjVertexFace(i, k);
3152 std::sort(sortedList.begin(), sortedList.end());
3154 for (
int k = 0; k < count; ++k)
3155 fprintf(file,
"adj[%d][%d] = %d\n", i, k, sortedList[k]);
3165 if ((
int)faceGroupIDs_.size() <= std::max(numFaces_,_i))
3166 faceGroupIDs_.resize(std::max(numFaces_,_i+1), -1);
3168 faceGroupIDs_[_i] = _groupID;
3176 int batchSize = _range;
3179 if ((_range < 0) || (_offset + batchSize > numDrawVerts_))
3180 batchSize = numDrawVerts_ - _offset;
3182 char* bdst = (
char*)_dst;
3184 for (
int i = 0; i < batchSize; ++i)
3196 : e0(std::min(a,b)), e1(std::max(a,b)) {}
3200 return e0 == k.e0 && e1 == k.e1;
3216 #ifdef ACG_MC_USE_STL_HASH
3218 struct MeshCompiler_EdgeTriMapKey_Hash
3222 return ((std::hash<int>()(k.e0) << 1) ^ std::hash<int>()(k.e1)) >> 1;
3226 uint qHash(
const MeshCompiler_EdgeTriMapKey& k)
3228 return ((::qHash(k.e0) << 1) ^ ::qHash(k.e1)) >> 1;
3230 #endif // ACG_MC_USE_STL_HASH
3235 int* idst = (
int*)_dst;
3237 for (
int i = 0; i < numTris_; ++i)
3244 idst[i*6+1] = _borderIndex;
3245 idst[i*6+3] = _borderIndex;
3246 idst[i*6+5] = _borderIndex;
3250 QHash<MeshCompiler_EdgeTriMapKey, std::pair<int, int> > EdgeAdjMap;
3252 for (
int i = 0; i < numTris_; ++i)
3257 for (
int k = 0; k < 3; ++k)
3259 int faceId, cornerId;
3264 for (
int e = 0; e < 3; ++e)
3268 QHash< MeshCompiler_EdgeTriMapKey, std::pair<int, int> >::iterator itKey;
3270 itKey = EdgeAdjMap.find(edge);
3272 if (itKey == EdgeAdjMap.end())
3273 EdgeAdjMap[edge] = std::pair<int, int>(i, -1);
3275 itKey.value().second = i;
3281 for (QHash<
MeshCompiler_EdgeTriMapKey, std::pair<int, int> >::iterator it = EdgeAdjMap.begin(); it != EdgeAdjMap.end(); ++it)
3284 int Tris[2] = {it.value().first, it.value().second};
3289 for (
int k = 0; k < 3; ++k)
3291 int faceId, cornerId;
3302 int TriEdges[2] = {-1,-1};
3303 int TriOppositeVerts[2] = {-1,-1};
3305 for (
int e = 0; e < 3; ++e)
3309 if (edge0 == it.key())
3312 TriOppositeVerts[1] = (e+2)%3;
3318 for (
int e = 0; e < 3; ++e)
3322 if (edge1 == it.key())
3325 TriOppositeVerts[0] = (e+2)%3;
3332 for (
int i = 0; i < 2; ++i)
3336 int e = TriEdges[i];
3339 int ov = _borderIndex;
3341 if (TriOppositeVerts[i] >= 0 && Tris[(i+1)%2] >= 0)
3342 ov =
getIndex(Tris[(i+1)%2]*3 + TriOppositeVerts[i]);
3344 idst[Tris[i] * 6 + e*2 + 1] = ov;
3426 const int numVerts = input_[inputIDPos_].
count;
3429 outputVertexTriAdj.init(numVerts);
3432 for (
int i = 0; i < numTris_; ++i)
3434 int faceID, cornerID;
3436 for (
int k = 0; k < 3; ++k)
3441 outputVertexTriAdj.count[posID]++;
3448 for (
int i = 0; i < numVerts; ++i)
3450 outputVertexTriAdj.start[i] = nCounter;
3452 nCounter += outputVertexTriAdj.count[i];
3454 outputVertexTriAdj.count[i] = 0;
3458 outputVertexTriAdj.buf =
new int[nCounter];
3459 outputVertexTriAdj.bufSize = nCounter;
3462 for (
int i = 0; i < numTris_; ++i)
3464 int faceID, cornerID;
3466 for (
int k = 0; k < 3; ++k)
3471 int adjIdx = outputVertexTriAdj.start[posID] + outputVertexTriAdj.count[posID]++;
3473 outputVertexTriAdj.buf[ adjIdx ] = i;
3480 int* idst = (
int*)_dst;
3482 for (
int i = 0; i < numTris_; ++i)
3489 idst[i*6+1] = _borderIndex;
3490 idst[i*6+3] = _borderIndex;
3491 idst[i*6+5] = _borderIndex;
3495 #pragma omp parallel for
3497 for (
int vertexID = 0; vertexID < numVerts; ++vertexID)
3499 const int numAdjTris = outputVertexTriAdj.getCount(vertexID);
3502 for (
int adjID0 = 0; adjID0 < numAdjTris; ++adjID0)
3504 const int triID0 = outputVertexTriAdj.getAdj(vertexID, adjID0);
3507 for (
int k = 0; k < 3; ++k)
3509 int faceid, cornerid;
3513 for (
int adjID1 = adjID0+1; adjID1 < numAdjTris; ++adjID1)
3515 const int triID1 = outputVertexTriAdj.getAdj(vertexID, adjID1);
3518 for (
int k = 0; k < 3; ++k)
3520 int faceid, cornerid;
3525 for (
int e0 = 0; e0 < 3; ++e0)
3529 for (
int e1 = 0; e1 < 3; ++e1)
3537 int oppVertex0 =
getIndex( triID1*3 + ((e1+2)%3) );
3538 int oppVertex1 =
getIndex( triID0*3 + ((e0+2)%3) );
3540 idst[triID0*6 + e0*2 +1] = oppVertex0;
3541 idst[triID1*6 + e1*2 + 1] = oppVertex1;
3558 int* idst = (
int*)_dst;
3560 for (
int i = 0; i < numTris_; ++i)
3567 idst[i*6+1] = _borderIndex;
3568 idst[i*6+3] = _borderIndex;
3569 idst[i*6+5] = _borderIndex;
3574 #pragma omp parallel for
3576 for (
int triID0 = 0; triID0 < numTris_; ++triID0)
3579 for (
int k = 0; k < 3; ++k)
3581 int faceid, cornerid;
3585 for (
int triID1 = triID0 + 1; triID1 < numTris_; ++triID1)
3588 for (
int k = 0; k < 3; ++k)
3590 int faceid, cornerid;
3595 for (
int e0 = 0; e0 < 3; ++e0)
3599 for (
int e1 = 0; e1 < 3; ++e1)
3607 int oppVertex0 =
getIndex( triID1*3 + ((e1+2)%3) );
3608 int oppVertex1 =
getIndex( triID0*3 + ((e0+2)%3) );
3610 idst[triID0*6 + e0*2 +1] = oppVertex0;
3611 idst[triID1*6 + e1*2 + 1] = oppVertex1;
3653 int positionID = -1;
3659 _cornerID = vertexMapCorner_[_i];
3661 positionID = getInputIndex(_faceID, _cornerID, inputIDPos_);
3677 return getInputIndexSplit(_faceID, _cornerID);
3683 assert(_k < fsize - 2);
3686 *_numTrisOut = fsize - 2;
3688 int offset = constantFaceSize_ ? (_faceID * (maxFaceSize_ - 2)) : faceToTriMapOffset_[_faceID];
3721 size_t usage = faceStart_.size() * 4;
3722 usage += faceSize_.size() * 1;
3723 usage += faceData_.size() * 4;
3724 usage += faceGroupIDs_.size() * 2;
3725 usage += faceBufSplit_.size() * 4;
3726 usage += faceSortMap_.size() * 4;
3728 usage += triIndexBuffer_.size() * 4;
3730 usage += subsetIDMap_.size() *
sizeof(
Subset);
3732 usage += vertexWeldMapFace_.size() * 5;
3734 usage += adjacencyVert_.bufSize * 4;
3735 usage += adjacencyVert_.num * 4;
3736 usage += adjacencyVert_.num * 1;
3740 usage += splitter_->
splits.size() * 4;
3746 usage += faceToTriMapOffset_.size() * 4;
3755 const int byteToMB = 1024 * 1024;
3757 std::cout <<
"faceStart_: " <<
sizeof(std::pair<int, unsigned char>) << std::endl;
3759 std::cout <<
"faceStart_: " << faceStart_.size() * 4 / byteToMB << std::endl;
3760 std::cout <<
"faceSize_: " << faceSize_.size() * 1 / byteToMB << std::endl;
3761 std::cout <<
"faceData_: " << faceData_.size() * 4 / byteToMB << std::endl;
3762 std::cout <<
"faceGroupIDs_: " << faceGroupIDs_.size() * 2 / byteToMB << std::endl;
3763 std::cout <<
"faceBufSplit_: " << faceBufSplit_.size() * 4 / byteToMB << std::endl;
3765 std::cout <<
"faceSortMap_: " << faceSortMap_.size() * 4 / byteToMB << std::endl;
3767 std::cout <<
"triIndexBuffer_: " << triIndexBuffer_.size() * 4 / byteToMB << std::endl;
3769 std::cout <<
"vertexWeldMap_: " << vertexWeldMapFace_.size() * 5 / byteToMB << std::endl;
3771 std::cout <<
"adjacencyVert_: buf = " << adjacencyVert_.bufSize * 4 / byteToMB <<
3772 ", offset = " << adjacencyVert_.num * 4 / byteToMB <<
3773 ", count = " << adjacencyVert_.num * 1 / byteToMB << std::endl;
3776 std::cout <<
"splitter_: " << splitter_->
splits.size() * 4 / byteToMB << std::endl;
3778 std::cout <<
"triToSortFaceMap_: " <<
triToSortFaceMap_.size() * 4 / byteToMB << std::endl;
3779 std::cout <<
"triOptMap_: " <<
triOptMap_.size() * 4 / byteToMB << std::endl;
3780 std::cout <<
"vertexMap_: " <<
vertexMapFace_.size() * 5 / byteToMB << std::endl;
3781 std::cout <<
"faceToTriMapOffset_: " << faceToTriMapOffset_.size() * 4 / byteToMB << std::endl;
3782 std::cout <<
"faceToTriMap_: " <<
faceToTriMap_.size() * 4 / byteToMB << std::endl;
3783 std::cout <<
"triToFaceMap_: " <<
triToFaceMap_.size() * 4 / byteToMB << std::endl;
3786 std::cout <<
"indices_: " << 3 * numTris_ * 4 / byteToMB << std::endl;
3799 return "Error: no face input data present\n";
3801 std::stringstream strm;
3805 for (
int a = 0; a < numAttributes_; ++a)
3807 if (input_[a].count <= 0)
3808 strm <<
"Warning: input buffer is not initialized: buffer id " << a <<
"\n";
3811 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
3814 strm <<
"Error: face size too small: face " << i <<
", size " << faceInput_->
getFaceSize(i) <<
" must be at least 3\n";
3816 std::map<int, int> facePositions;
3818 for (
int k = 0; k < faceInput_->
getFaceSize(i); ++k)
3822 for (
int a = 0; a < numAttributes_; ++a)
3824 if (input_[a].count > 0)
3827 if (faceV[a] >= input_[a].count)
3828 strm <<
"Error: input index (face/corner/attribute: " << i <<
"/" << k <<
"/" << a <<
") invalid: " << faceV[a] <<
" >= buffer size (" << input_[a].
count <<
")\n";
3830 strm <<
"Error: input index (face/corner/attribute: " << i <<
"/" << k <<
"/" << a <<
") invalid: " << faceV[a] <<
"\n";
3835 facePositions[faceV[0]] = k;
3839 if ((
int)facePositions.size() != faceInput_->
getFaceSize(i))
3840 strm <<
"Warning: degenerate face " << i <<
"\n";
3844 strm <<
"Warning: empty face " << i <<
"\n";
3853 numFaces_ = faceInput_->getNumFaces();
3857 for (
int i = numFaces_-1; i >= 0 && !faceInput_->
getFaceSize(i); --i)
3864 assert(input_[i].attrSize <= 0 || input_[i].attrSize == attrSize);
3870 int minFaceSize = 99999999;
3871 for (
int i = 0; i < numFaces_; ++i)
3875 maxFaceSize_ = std::max((
int)maxFaceSize_, fsize);
3876 minFaceSize = std::min(minFaceSize, fsize);
3881 if (minFaceSize < 3)
3882 std::cout <<
"error: input contains faces with less than 3 vertices! MeshCompiler only works for pure surface meshes!" << std::endl;
3884 assert(minFaceSize >= 3);
3886 if (minFaceSize < (
int)maxFaceSize_)
3891 faceStart_.resize(numFaces_, -1);
3892 faceSize_.resize(numFaces_, 0);
3894 for (
int i = 0; i < numFaces_; ++i)
3896 faceSize_[i] = (
unsigned char)faceInput_->
getFaceSize(i);
3897 faceStart_[i] = curOffset;
3898 curOffset += faceSize_[i];
3901 if (numIndices_ <= 0)
3902 numIndices_ = curOffset;
3906 constantFaceSize_ =
true;
3907 numIndices_ = maxFaceSize_ * numFaces_;
3914 faceSortMap_.clear();
3917 faceToTriMapOffset_.clear();
3921 vertexMapCorner_.clear();
3923 faceBufSplit_.clear();
3925 isolatedVertices_.clear();
3928 if (!provokingVertexSetByUser_)
3929 provokingVertex_ = -1;
3933 for (
int i = 0; i < numFaces_; ++i)
3938 int v1 = getInputIndex(i, k, inputIDPos_);
3948 faceInput_ = _faceInput;
3958 for (
int i = 0; i < _numTris; ++i)
3960 int tri[3] = {-1, -1, -1};
3962 for (
int k = 0; k < 3; ++k)
3964 int offs = i * 3 + k;
3968 case 1: tri[k] = ((
char*)_indices)[offs];
break;
3969 case 2: tri[k] = ((
short*)_indices)[offs];
break;
3970 case 4: tri[k] = ((
int*)_indices)[offs];
break;
3971 case 8: tri[k] = (int)((
long long*)_indices)[offs];
break;
3987 provokingVertex_ = _v;
3988 provokingVertexSetByUser_ =
true;
3991 int MeshCompiler::getAdjVertexFaceCount(
int _vertexID )
const
3993 return adjacencyVert_.num ? adjacencyVert_.getCount(_vertexID) : faceInput_->
getVertexAdjCount(_vertexID);
3996 int MeshCompiler::getAdjVertexFace(
int _vertexID,
int _k )
const
3998 return adjacencyVert_.num ? adjacencyVert_.getAdj(_vertexID, _k) : faceInput_->
getVertexAdjFace(_vertexID, _k);
4003 return maxFaceSize_ == 3;
4011 if (maxFaceSize_ <= 3)
return true;
4019 std::vector<int> FaceVerts(fsize);
4021 for (
int i = 0; i < fsize; ++i)
4029 case 0: edgeStart = 0; edgeEnd = 1;
break;
4030 case 1: edgeStart = 1; edgeEnd = 2;
break;
4031 case 2: edgeStart = 2; edgeEnd = 0;
break;
4036 edgeStart =
getIndex(_triID * 3 + edgeStart);
4037 edgeEnd =
getIndex(_triID * 3 + edgeEnd);
4040 for (
int e = 0; e < fsize; ++e)
4042 if (FaceVerts[e] == edgeStart && FaceVerts[(e+1)%fsize] == edgeEnd)
4044 if (FaceVerts[e] == edgeEnd && FaceVerts[(e+1)%fsize] == edgeStart)
4051 void MeshCompilerDefaultFaceInput::dbgWriteToObjFile(FILE* _file,
int _posAttrID,
int _normalAttrID,
int _texcAttrID)
4053 for (
int i = 0; i < numFaces_; ++i)
4055 std::string strLine =
"f ";
4057 int offset = faceOffset_[i];
4058 int size = faceSize_[i];
4061 for (
int k = 0; k < size; ++k)
4063 if (_normalAttrID>=0 && _texcAttrID>=0)
4064 sprintf(tmp,
"%d/%d/%d ", faceData_[_posAttrID][offset+k]+1,
4065 faceData_[_texcAttrID][offset+k]+1,
4066 faceData_[_normalAttrID][offset+k]+1);
4067 else if (_normalAttrID >= 0)
4068 sprintf(tmp,
"%d//%d ", faceData_[_posAttrID][offset + k]+1, faceData_[_normalAttrID][offset+k]+1);
4069 else if (_texcAttrID >= 0)
4070 sprintf(tmp,
"%d/%d ", faceData_[_posAttrID][offset + k]+1, faceData_[_texcAttrID][offset+k]+1);
4072 sprintf(tmp,
"%d ", faceData_[_posAttrID][offset + k]+1);
4077 fprintf(_file,
"%s\n", strLine.c_str());
4083 int offset = faceOffset_[_faceID];
4084 int fsize = faceSize_[_faceID];
4086 for (
int i = 0; i < fsize; ++i)
4087 _out[i] = faceData_[_attrID][offset+i];
4095 const int pos = faceOffset_[_faceID] + _faceCorner;
4099 if (faceData_[_attrID].empty() || pos >=
int(faceData_[_attrID].size()))
4102 return faceData_[_attrID][pos];
4105 void MeshCompilerDefaultFaceInput::setFaceData(
int _faceID,
int _size,
int* _data,
int _attrID )
4108 if (numFaces_ <= _faceID)
4109 numFaces_ = _faceID + 1;
4112 if (faceData_[_attrID].capacity() == 0)
4113 faceData_[_attrID].reserve(numIndices_);
4115 if ((
int)faceOffset_.size() <= _faceID)
4116 faceOffset_.resize(_faceID+1, -1);
4118 if ((
int)faceSize_.size() <= _faceID)
4119 faceSize_.resize(_faceID+1, -1);
4121 faceSize_[_faceID] = _size;
4123 if (faceOffset_[_faceID] < 0)
4126 faceOffset_[_faceID] = faceData_[_attrID].size();
4127 for (
int i = 0; i < _size; ++i)
4128 faceData_[_attrID].push_back(_data[i]);
4132 int offs = faceOffset_[_faceID];
4134 if ((
int)faceData_[_attrID].size() == offs)
4136 for (
int i = 0; i < _size; ++i)
4137 faceData_[_attrID].push_back(_data[i]);
4142 if ((
int)faceData_[_attrID].size() < offs + _size + 1)
4143 faceData_[_attrID].resize(offs + _size + 1, -1);
4146 for (
int i = 0; i < _size; ++i)
4147 faceData_[_attrID][offs + i] = _data[i];
4157 assert(_faceID >= 0);
4158 assert(_faceCorner >= 0);
4159 assert(_faceCorner < fsize);
4163 int* tmpPtr = getFaceAttr(_faceID, _attrID);
4166 retVal = tmpPtr[_faceCorner];
4169 tmpPtr =
new int[fsize];
4170 if (getFaceAttr(_faceID, _attrID, tmpPtr))
4171 retVal = tmpPtr[_faceCorner];
4179 bool MeshCompilerVertexCompare::equalVertex(
const void* v0,
const void* v1,
const VertexDeclaration* _decl )
4188 for (
int i = 0; i < nElements; ++i)
4193 const void* el_0 =
static_cast<const char*
>(v0) + (
size_t)el->
pointer_;
4194 const void* el_1 =
static_cast<const char*
>(v1) + (
size_t)el->
pointer_;
4197 switch ( el->
type_ )
4201 const double* d0 =
static_cast<const double*
>(el_0);
4202 const double* d1 =
static_cast<const double*
>(el_1);
4207 diff += fabs(d0[k] - d1[k]);
4217 const float* f0 =
static_cast<const float*
>(el_0);
4218 const float* f1 =
static_cast<const float*
>(el_1);
4229 diff += fabsf(f0[k] - f1[k]);
4237 case GL_UNSIGNED_INT:
4239 const int* i0 =
static_cast<const int*
>(el_0);
4240 const int* i1 =
static_cast<const int*
>(el_1);
4250 case GL_UNSIGNED_SHORT:
4252 const short* i0 =
static_cast<const short*
>(el_0);
4253 const short* i1 =
static_cast<const short*
>(el_1);
4263 case GL_UNSIGNED_BYTE:
4265 const char* i0 =
static_cast<const char*
>(el_0);
4266 const char* i1 =
static_cast<const char*
>(el_1);
4275 default: std::cerr <<
"MeshCompiler: equalVertex() comparision not implemented for type: " << el->
type_ << std::endl;
void getIndexAdjBuffer(void *_dst, const int _borderIndex=-1)
Get index buffer with adjacency information ready for rendering.
int attrSize
size in bytes of one attribute
void build(bool _weldVertices=false, bool _optimizeVCache=true, bool _needPerFaceAttribute=false, bool _keepIsolatedVertices=false)
Build vertex + index buffer.
int getNumVertices() const
std::vector< int > faceToTriMap_
input face index -> output tri index
int getFaceGroup(int _faceID) const
Get Face Group of the given face.
Namespace providing different geometric functions concerning angles.
void setNormals(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
int getNumSubsets() const
Get the number of subsets.
void dbgdumpObj(const char *_filename) const
dump mesh in wavefront obj format
void setAttrib(int _attrIdx, int _v, const void *_data)
bool isTriangleMesh() const
void setTexCoords(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
int stride
offset in bytes from one element to the next
int numIsolatedVerts_
isolated vertices
void setFaceNormals(int _i, int _v0, int _v1, int _v2)
Set normal ids per triangle.
int findGroupSubset(int _groupID)
get subset ID of a group
void setIndexBufferInterleaved(int _numTris, int _indexSize, const void *_indices)
Set index buffer for a triangle mesh.
void setFaceAttrib(int _i, int _v0, int _v1, int _v2, int _attrID)
Set attribute ids per triangle.
void getInputFaceVertexData(const int _face, const int _corner, void *_out) const
void dbgdumpAdjList(const char *_filename) const
dump adjacency list to text file
std::vector< int > vertexMapFace_
vertex index in vbo -> input (face id, corner id) pair , also inverse of faceBufSplit_ ...
int getSingleFaceAttr(const int _faceID, const int _faceCorner, const int _attrID) const
bool isIsolated(const int vertexPosID)
check if vertex is isolated with a complete splitting list
const VertexElement * getElement(unsigned int i) const
std::string checkInputData() const
check for errors in input data
void setFaceInput(MeshCompilerFaceInput *_faceInput)
void setFaceVerts(int _i, int _v0, int _v1, int _v2)
Set vertex ids per triangle.
static void OptimizeVertices(unsigned int NumTris, unsigned int NumVerts, unsigned int IndexSize, const void *pIndices, unsigned int *pVertMap)
Reorders vertex buffer to minimize memory address jumps.
void setFaceGroup(int _i, short _groupID)
Specify face groups.
char * internalBuf
mem alloc if attribute buffer managed by this class
void dbgdumpInputObj(const char *_filename) const
dump input mesh to wavefront obj format
Description of one vertex element.
void getInputFaceVertex_Welded(const int _face, const int _corner, int *_out) const
void getVertexBuffer(void *_dst, const int _offset=0, const int _range=-1)
Get vertex buffer ready for rendering.
unsigned int getVertexStride(unsigned int i=0) const
void setAttribVec(int _attrIdx, int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
const int * mapToOriginalFaceIDPtr() const
int numDrawVerts_
vertices in vbo
static unsigned int getElementSize(const VertexElement *_pElement)
std::vector< int > splits
size_t getMemoryUsage(bool _printConsole=true) const
virtual int getVertexAdjFace(const int _vertexID, const int _k) const
void getIndexAdjBuffer_MT(void *_dst, const int _borderIndex=-1)
Multi-threaded version of getIndexAdjBuffer.
unsigned int getNumElements() const
std::vector< int > indices_
index buffer
virtual int getFaceSize(const int _faceID) const =0
void getInputFaceVertex(const int _face, const int _corner, int *_out) const
void setVertices(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
int count
elements in buffer
std::string vertexToString(const void *v) const
interpret vertex data according declaration and write to string
int mapToOriginalVertexID(const int _i, int &_faceID, int &_cornerID) const
void getElementData(int _idx, void *_dst, const VertexElement *_desc) const
read a vertex element
int split(int *vertex)
returns a unique index for a vertex-attribute combination
const Subset * getSubset(int _i) const
get a specific subset
bool dbgVerify(const char *_filename) const
test correctness of input <-> output id mappings, unshared per face vertex.. logs errors in file ...
virtual int getNumIndices() const =0
int mapToOriginalFaceID(const int _triID) const
Class to define the vertex input layout.
int numVerts
number of vertex combinations currently in use
bool isFaceEdge(const int _triID, const int _edge) const
unsigned int type_
GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ...
std::vector< int > triToSortFaceMap_
maps from triangle ID to sorted face ID
int mapToDrawTriID(const int _faceID, const int _k=0, int *_numTrisOut=0) const
unsigned int numElements_
how many elements of type_
int mapToDrawVertexID(const int _faceID, const int _cornerID) const
std::vector< int > triToFaceMap_
output tri index -> input face index
std::vector< int > triOptMap_
maps from optimized tri ID to unoptimized tri ID
int getFaceSize(const int _i) const
Get size of input face.
void dbgdumpInputBin(const char *_filename, bool _seperateFiles=false) const
dump input mesh to binary file format
VERTEX_USAGE usage_
position, normal, shader input ..
const char * shaderInputName_
set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically...
void prepareData()
build() preparation
void setProvokingVertex(int _v)
void setFaceTexCoords(int _i, int _v0, int _v1, int _v2)
Set texcoord ids per triangle.
const void * pointer_
Offset in bytes to the first occurrence of this element in vertex buffer; Or address to vertex data i...
virtual int getSingleFaceAttr(const int _faceID, const int _faceCorner, const int _attrID) const
void setNumFaces(const int _numFaces, const int _numIndices)
Set number of faces and indices if known by user.
virtual int getVertexAdjCount(const int _vertexID) const
void getIndexAdjBuffer_BruteForce(void *_dst, const int _borderIndex=-1)
Slow brute-force version of getIndexAdjBuffer.
int getNumInputAttributes(int _attrIdx) const
bool getFaceAttr(const int _faceID, const int _attrID, int *_out) const
int getIndex(int _i) const
void getVertex(int _id, void *_out) const
void dbgdump(const char *_filename) const
dump mesh info to text file