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(
bool _forceRecompute)
162 const int numVerts = input_[inputIDPos_].count;
171 if (_forceRecompute || (faceInput_->getVertexAdjCount(0) < 0 && adjacencyVert_.bufSize <= 0))
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);
288 assert(_attrIdx < (
int)decl_.getNumElements());
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)
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);
411 for (
int i = 0; i < numVerts; ++i)
415 weldList.list.clear();
418 int numAdjFaces = getAdjVertexFaceCount(i);
419 for (
int k = 0; k < numAdjFaces; ++k)
421 const int adjFace = getAdjVertexFace(i, k);
425 int adjCornerId = -1;
426 for (
int m = 0; m < adjFaceSize; ++m)
428 const int adjVertex = getInputIndex(adjFace, m, inputIDPos_);
447 const int weldMapOffset = getInputFaceOffset(adjFace) + adjCornerId;
449 if (vertexWeldMapFace_[weldMapOffset] >= 0)
452 weldList.add(adjFace, adjCornerId);
460 for (
size_t e = 0; e < weldList.list.size(); ++e)
463 const int weldMapOffset = getInputFaceOffset(it->faceId) + it->cornerId;
465 if (vertexWeldMapFace_[weldMapOffset] >= 0)
469 vertexWeldMapFace_[weldMapOffset] = it->refFaceId;
470 vertexWeldMapCorner_[weldMapOffset] = it->refCornerId;
534 if (adjacencyVert_.bufSize <= 0)
539 computeAdjacency(
true);
543 vertexWeldMapFace_.clear();
544 vertexWeldMapCorner_.clear();
552 std::cerr <<
"MeshCompiler - faulty internal adjacency list" << std::endl;
561 delete [] vtxCompBuf;
564 void MeshCompiler::fixWeldMap()
566 for (
int i = 0; i < numFaces_; ++i)
569 for (
int k = 0; k < fsize; ++k)
571 const int weldMapOffset = getInputFaceOffset(i) + k;
575 if (vertexWeldMapFace_[weldMapOffset] < 0)
577 vertexWeldMapFace_[weldMapOffset] = i;
578 vertexWeldMapCorner_[weldMapOffset] = k;
584 void MeshCompiler::findIsolatedVertices()
586 const int nVerts = input_[inputIDPos_].count;
592 for (
int i = 0; i < nVerts; ++i)
594 if (splitter_->isIsolated(i))
598 isolatedVertices_.clear();
600 for (
int i = 0; i < nVerts; ++i)
602 if (splitter_->isIsolated(i))
603 isolatedVertices_.push_back(i);
607 void MeshCompiler::splitVertices()
639 const int numPositions = input_[inputIDPos_].count;
642 int estimatedSplitCount = 0;
643 int numDifferentInputCounts = 0;
648 for (
int i = 0; i < numAttributes_; ++i)
650 if (i != inputIDPos_)
652 if (input_[i].count > numPositions)
654 const int diff = input_[i].count - numPositions;
658 estimatedSplitCount = std::max(diff, estimatedSplitCount);
659 ++numDifferentInputCounts;
665 if (numDifferentInputCounts > 1)
668 estimatedSplitCount = int(
float(estimatedSplitCount) * 1.2f);
671 assert(estimatedSplitCount >= 0);
676 int maxSplitCount = 0;
680 if (numIndices_ > numPositions)
681 maxSplitCount = numIndices_ - numPositions;
688 if (constantFaceSize_)
689 sumFaceSize = numFaces_ * maxFaceSize_;
692 for (
int i = 0; i < numFaces_; ++i)
696 if (sumFaceSize > numPositions)
697 maxSplitCount = sumFaceSize - numPositions;
700 estimatedSplitCount = std::min(estimatedSplitCount, maxSplitCount);
708 numPositions + estimatedSplitCount,
711 faceBufSplit_.resize(numIndices_, -1);
716 for (
int i = 0; i < numFaces_; ++i)
719 for (
int k = 0; k < fsize; ++k)
730 const int idx = splitter_->split(vertex);
733 setInputIndexSplit(i, k, idx);
745 findIsolatedVertices();
751 std::vector<int> IsoFix(splitter_->numVerts, 0);
754 for (
int i = 0; i < splitter_->numVerts; ++i)
756 if (splitter_->isIsolated(i))
759 IsoFix[i] = fixIndex;
769 for (
int i = 0; i < numFaces_; ++i)
772 for (
int k = 0; k < fsize; ++k)
775 int idx = getInputIndexSplit(i, k);
782 setInputIndexSplit(i, k, idx);
789 bool MeshCompiler_forceUnsharedFaceVertex_InnerValenceSorter(
const std::pair<int, int>& a,
const std::pair<int, int>& b )
791 return a.second > b.second;
794 void MeshCompiler::forceUnsharedFaceVertex()
804 std::vector<int> sharedVertices;
805 sharedVertices.resize(maxFaceSize_);
808 std::vector<int> tmpFaceVerts;
809 tmpFaceVerts.resize(maxFaceSize_);
839 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
842 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
849 std::vector< std::pair<int, int> > vertexPriorities(faceSize);
853 const int faceTris = faceSize - 2;
855 std::vector<RingTriangle> remainingTris(faceTris);
856 for (
int i = 0; i < faceTris; ++i)
857 remainingTris[i] =
RingTriangle(i, &remainingTris[(i + faceTris - 1) % faceTris], &remainingTris[(i + 1) % faceTris]);
861 int numTrisCovered = 0;
863 while (numTrisCovered < faceTris)
866 for (
int k = 0; k < faceSize; ++k)
867 vertexPriorities[k] = std::pair<int, int>(k, 0);
870 int numRemainingTris = faceTris - numTrisCovered;
871 for (
int t = 0; t < numRemainingTris; ++t)
873 for (
int k = 0; k < 3; ++k)
875 int cornerID = -1 - triIndexBuffer_[(triCounter + currentTri->id) * 3 + k];
876 ++vertexPriorities[cornerID].second;
878 currentTri = currentTri->next;
880 assert(currentTri == startTri);
883 std::sort(vertexPriorities.begin(), vertexPriorities.end(), MeshCompiler_forceUnsharedFaceVertex_InnerValenceSorter);
887 int goodVertexID = -1;
888 int bestValence = -1;
889 for (
int k = 0; k < faceSize && vertexPriorities[k].second; ++k)
891 int cornerID = vertexPriorities[k].first;
892 int vertexID = getInputIndexSplit(faceID, cornerID);
894 int valence = vertexPriorities[k].second;
896 if (vertexID >= numInitialVerts || (VertexUsed[vertexID] == faceID))
900 goodCorner = cornerID;
901 goodVertexID = vertexID;
902 bestValence = valence;
905 else if (VertexUsed[vertexID] < 0 && bestValence < valence)
907 goodCorner = cornerID;
908 goodVertexID = vertexID;
909 bestValence = valence;
920 goodCorner = vertexPriorities[0].first;
924 setInputIndexSplit(faceID, goodCorner, goodVertexID);
929 VertexUsed[goodVertexID] = faceID;
933 for (
int t = 0; t < numRemainingTris; ++t)
936 for (
int k = 0; k < 3; ++k)
938 int cornerID = -1 - triIndexBuffer_[(triCounter + currentTri->id) * 3 + k];
940 if (cornerID == goodCorner)
943 int rotCount = 3 - k;
948 triIndexBuffer_[(triCounter + currentTri->id) * 3],
949 triIndexBuffer_[(triCounter + currentTri->id) * 3 + 1],
950 triIndexBuffer_[(triCounter + currentTri->id) * 3 + 2],
954 for (
int i = 0; i < 3; ++i)
955 triIndexBuffer_[(triCounter + currentTri->id) * 3 + (i + rotCount) % 3] = tmpTriVerts[i];
961 currentTri->prev->next = currentTri->next;
962 currentTri->next->prev = currentTri->prev;
967 currentTri = currentTri->next;
973 triCounter += faceSize - 2;
977 numInitialVerts = VertexUsed.size();
980 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
982 int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
988 memset(&sharedVertices[0], 0,
sizeof(
int) * maxFaceSize_);
992 for (
int v0 = 0; v0 < numCorners && numShared < numCorners; ++v0)
994 if (sharedVertices[v0])
997 const int vertexID0 = getInputIndexSplit(faceID, v0);
1001 if (vertexID0 < numInitialVerts && (VertexUsed[vertexID0] >= 0 && VertexUsed[vertexID0] != faceID))
1003 sharedVertices[v0] =
true;
1010 if (numShared == numCorners)
1019 else if (sharedVertices[0])
1023 for (
int i = 0; i < numCorners; ++i)
1024 x += sharedVertices[i];
1025 assert(x < numCorners);
1031 for (
int i = 0; i < numCorners; ++i)
1032 tmpFaceVerts[i] = getInputIndexSplit(faceID, i);
1037 for (; rotCount < numCorners; ++rotCount)
1039 if (!sharedVertices[rotCount % numCorners])
1041 if (tmpFaceVerts[rotCount] < numInitialVerts)
1042 VertexUsed[tmpFaceVerts[rotCount]] = faceID;
1047 assert(rotCount < numCorners);
1050 rotCount = numCorners - rotCount;
1052 for (
int i = 0; i < numCorners; ++i)
1056 triIndexBuffer_[triCounter * 3 + i] = tmpFaceVerts[(i + numCorners - rotCount) % numCorners];
1062 const int idx = getInputIndexSplit(faceID, 0);
1063 if (idx < numInitialVerts)
1064 VertexUsed[idx] = faceID;
1068 triCounter += numCorners - 2;
1076 for (
unsigned int k = 0; k < decl_.getNumElements(); ++k)
1077 _out[k] = getInputIndex(_face, _corner, k);
1086 if (!vertexWeldMapFace_.empty())
1088 const int offset = getInputFaceOffset(i);
1090 face = vertexWeldMapFace_[offset + j];
1091 corner = vertexWeldMapCorner_[offset + j];
1094 for (
unsigned int k = 0; k < decl_.getNumElements(); ++k)
1095 _out[k] = getInputIndex(face, corner, k);
1100 for (
int i = 0; i < numAttributes_; ++i)
1104 const int idx = getInputIndex(_faceId, _corner, i);
1106 input_[i].getElementData(idx, (
char*)_out + (
size_t)el->
pointer_, el);
1117 deleteFaceInputeData_ =
false;
1125 curFaceInputPos_ = 0;
1131 constantFaceSize_ =
false;
1133 provokingVertex_ = -1;
1134 provokingVertexSetByUser_ =
false;
1137 numAttributes_ = decl_.getNumElements();
1138 inputIDNorm_ = inputIDPos_ = inputIDTexC_ = -1;
1140 for (
int i = 0; i < (int)decl_.getNumElements(); ++i)
1154 vertexCompare_ = &defaultVertexCompare;
1158 MeshCompiler::~MeshCompiler()
1160 if (deleteFaceInputeData_)
1167 int MeshCompiler::getInputIndexOffset(
const int _face,
const int _corner )
const 1170 assert(_face < numFaces_);
1173 const int baseIdx = int(faceStart_.empty() ? maxFaceSize_ * _face : faceStart_[_face]);
1174 return baseIdx + _corner;
1178 void MeshCompiler::setInputIndexSplit(
const int _face,
const int _corner,
const int _val )
1180 const int offset = getInputIndexOffset(_face, _corner);
1186 faceBufSplit_[offset] = _val;
1189 int MeshCompiler::getInputIndexSplit(
const int _face,
const int _corner )
const 1191 const int offset = getInputIndexOffset(_face, _corner);
1193 return faceBufSplit_[offset];
1199 MeshCompilerDefaultFaceInput::MeshCompilerDefaultFaceInput(
int _numFaces,
int _numIndices)
1200 : numFaces_(_numFaces), numIndices_(_numIndices)
1202 faceOffset_.resize(numFaces_, -1);
1203 faceSize_.resize(numFaces_, 0);
1204 faceData_[0].reserve(_numIndices);
1215 numFaces_ = _numFaces;
1217 faceInput_ = internalInput;
1218 deleteFaceInputeData_ =
true;
1225 if (!_v || _attrID < 0)
return;
1233 input->setFaceData(_i, _numEdges, _v, _attrID);
1239 int tmp[3] = {_v0, _v1, _v2};
1245 MeshCompiler::VertexSplitter::VertexSplitter(
int _numAttribs,
1248 float _estBufferIncrease)
1249 : numAttribs(_numAttribs), numVerts(_numVerts), numBaseVerts(_numVerts)
1251 if (_numWorstCase <= 0)
1252 _numWorstCase = int(
float(_numVerts) * (_estBufferIncrease + 1.0f));
1254 const int maxCount = (_numAttribs + 1) * (_numWorstCase + 1);
1257 splits.resize(maxCount, -1);
1265 MeshCompiler::VertexSplitter::~VertexSplitter()
1272 int pos = vertex[0];
1273 int next = getNext(pos);
1280 setAttribs(pos, vertex);
1289 int bSearchSplit = 1;
1292 while (pos >= 0 && bSearchSplit)
1295 if (!memcmp(vertex, getAttribs(pos), numAttribs *
sizeof(
int)))
1302 next = getNext(pos);
1304 if (next < 0)
break;
1305 if (next == pos)
break;
1313 int newID = numVerts++;
1315 setNext(pos, newID);
1316 setAttribs(newID, vertex);
1328 int MeshCompiler::VertexSplitter::getNext(
const int id)
1332 const int entryIdx =
id * (1 + numAttribs);
1335 if (entryIdx >= (
int)splits.size())
1337 splits.resize(entryIdx + numAttribs * 100, -1);
1341 return splits[entryIdx];
1344 void MeshCompiler::VertexSplitter::setNext(
const int id,
const int next)
1348 const int entryIdx =
id * (1 + numAttribs);
1351 if (entryIdx >= (
int)splits.size())
1353 splits.resize(entryIdx + numAttribs * 100, -1);
1357 splits[entryIdx] = next;
1360 int* MeshCompiler::VertexSplitter::getAttribs(
const int id)
1364 const int entryIdx =
id * (1 + numAttribs) + 1;
1367 if (entryIdx + numAttribs >= (
int)splits.size())
1369 splits.resize(entryIdx + numAttribs * 100, -1);
1373 return &splits[0] + entryIdx;
1376 void MeshCompiler::VertexSplitter::setAttribs(
const int id,
int* attr )
1378 memcpy(getAttribs(
id), attr, numAttribs *
sizeof(
int));
1383 return (vertexPosID < numBaseVerts) && (getNext(vertexPosID) < 0);
1388 MeshCompiler::VertexElementInput::VertexElementInput()
1389 : internalBuf(0), data(0),
1390 count(0), stride(0), attrSize(0),
1391 fmt(0), elementSize(-1)
1395 MeshCompiler::VertexElementInput::~VertexElementInput()
1397 delete [] internalBuf;
1407 void MeshCompiler::triangulate()
1413 for (
int i = 0; i < numFaces_; ++i)
1418 triIndexBuffer_.resize(numTris * 3);
1430 int indexCounter = 0;
1432 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
1435 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1444 for (
int k = 0; k < 3; ++k)
1445 triIndexBuffer_[indexCounter++] = -1 - k;
1450 std::vector<Vec3f> poly(faceSize);
1451 for (
int k = 0; k < faceSize; ++k)
1454 posElement.
type_ = GL_FLOAT;
1460 posElement.
vbo_ = 0;
1461 int posID = getInputIndexSplit(faceID, k);
1462 input_[inputIDPos_].getElementData(posID, &poly[k], &posElement);
1471 for (
int k = 0; k < 3; ++k)
1472 triIndexBuffer_[indexCounter++] = -1 - k;
1474 for (
int k = 3; k < faceSize; ++k)
1479 triIndexBuffer_[indexCounter++] = -1;
1480 triIndexBuffer_[indexCounter++] = -1 - (k - 1);
1481 triIndexBuffer_[indexCounter++] = -1 - k;
1492 for (
int k = 0; k < 3; ++k)
1494 int cornerID = tris.
index(i * 3 + k);
1496 triIndexBuffer_[indexCounter++] = -1 - cornerID;
1506 for (
int i = 0; i < numSubsets_; ++i)
1508 subsets_[i].startIndex = 0xffffffff;
1509 subsets_[i].numTris = 0;
1514 for (
int i = 0; i < numTris; ++i)
1516 const int faceID = mapTriToInputFace(i);
1526 for (
int i = 0; i < numSubsets_; ++i)
1529 subsets_[i].startIndex = subsets_[i-1].startIndex + subsets_[i-1].numTris * 3;
1531 subsets_[i].startIndex = 0;
1537 void MeshCompiler::resolveTriangulation()
1541 if (provokingVertex_ >= 0)
1543 for (
int i = 0; i < numTris_; ++i)
1545 for (
int k = 0; k < 3 - provokingVertex_; ++k)
1547 const int tmp = triIndexBuffer_[i*3];
1548 triIndexBuffer_[i*3] = triIndexBuffer_[i*3 + 1];
1549 triIndexBuffer_[i*3 + 1] = triIndexBuffer_[i*3 + 2];
1550 triIndexBuffer_[i*3 + 2] = tmp;
1556 for (
int drawTriID = 0; drawTriID < numTris_; ++drawTriID)
1558 if (triIndexBuffer_[drawTriID * 3] < 0)
1565 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1567 for (
int k = 0; k < 3; ++k)
1569 int negCornerID = triIndexBuffer_[drawTriID * 3 + k];
1570 int cornerID = -1 - negCornerID;
1571 triIndexBuffer_[drawTriID * 3 + k] = getInputIndexSplit(faceID, cornerID);
1577 void MeshCompiler::sortFacesByGroup()
1584 std::map<int, unsigned int> GroupIDs;
1587 for (
int face = 0; face < numFaces_; ++face)
1591 if (GroupIDs.find(texID) == GroupIDs.end())
1592 GroupIDs[texID] = face;
1596 numSubsets_ = int(GroupIDs.size());
1597 subsets_.resize(numSubsets_);
1599 if (numSubsets_ > 1)
1600 faceSortMap_.resize(numFaces_, -1);
1604 std::map<int, unsigned int>::const_iterator it = GroupIDs.begin();
1605 unsigned int numSortedFaces = 0;
1607 for (
unsigned int i = 0; it != GroupIDs.end(); ++i, ++it)
1610 subsets_[i].id = it->first;
1613 subsetIDMap_[it->first] = i;
1616 subsets_[i].numFaces = 0;
1617 subsets_[i].startFace = numSortedFaces;
1620 subsets_[i].startIndex = 0;
1621 subsets_[i].numTris = 0;
1623 if (numSubsets_ == 1)
1625 subsets_[i].numFaces = numFaces_;
1631 for (
int k = it->second; k < numFaces_; ++k)
1635 if (texID == subsets_[i].
id)
1637 subsets_[i].numFaces++;
1639 faceSortMap_[numSortedFaces++] = k;
1648 void MeshCompiler::optimize()
1653 for (
int i = 0; i < numSubsets_; ++i)
1655 Subset* pSubset = &subsets_[i];
1657 const int vcacheSize = 24;
1663 const unsigned int StartTri = pSubset->startIndex/3;
1664 for (
unsigned int k = 0; k < pSubset->numTris; ++k)
1667 triOptMap_[k + StartTri] = SrcTri + StartTri;
1674 unsigned int* vertexOptMap =
new unsigned int[
numDrawVerts_];
1680 for (
int i = 0; i < numTris_ * 3; ++i)
1686 for (
int i = 0; i < numFaces_; ++i)
1690 for (
int k = 0; k < fsize; ++k)
1692 int oldVertex = getInputIndexSplit(i, k);
1694 int newVertex = vertexOptMap[oldVertex];
1696 setInputIndexSplit(i, k, newVertex);
1700 delete [] vertexOptMap;
1705 void MeshCompiler::build(
bool _weldVertices,
bool _optimizeVCache,
bool _needPerFaceAttribute,
bool _keepIsolatedVertices)
1708 const bool dbg_MemProfiling =
false;
1733 if (dbg_MemProfiling)
1734 std::cout <<
"computing adjacency.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1738 if (dbg_MemProfiling)
1739 std::cout <<
"vertex welding.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1744 adjacencyVert_.clear();
1747 if (dbg_MemProfiling)
1748 std::cout <<
"vertex splitting.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1752 if (dbg_MemProfiling)
1753 std::cout <<
"splitting done.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1757 delete splitter_; splitter_ = 0;
1760 std::vector< int > emptyVec;
1761 vertexWeldMapFace_.swap(emptyVec);
1763 std::vector< int > emptyVec;
1764 vertexWeldMapCorner_.swap(emptyVec);
1778 if (dbg_MemProfiling)
1779 std::cout <<
"sorting by mat.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1809 if (dbg_MemProfiling)
1810 std::cout <<
"triangulate.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1815 if (_needPerFaceAttribute)
1817 if (dbg_MemProfiling)
1818 std::cout <<
"force unshared vertex.., memusage = " << (
getMemoryUsage() / (1024 * 1024)) << std::endl;
1824 if (provokingVertex_ < 0)
1825 provokingVertex_ = 2;
1827 provokingVertex_ = provokingVertex_ % 3;
1830 forceUnsharedFaceVertex();
1833 resolveTriangulation();
1850 if (_optimizeVCache)
1852 if (dbg_MemProfiling)
1853 std::cout <<
"optimizing.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1857 else if (!triIndexBuffer_.empty())
1860 if (dbg_MemProfiling)
1861 std::cout <<
"creating maps.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1865 std::vector< int > emptyVec;
1866 triIndexBuffer_.swap(emptyVec);
1869 createVertexMap(_keepIsolatedVertices);
1874 std::vector< int > emptyVec;
1877 std::vector< int > emptyVec;
1880 std::vector< int > emptyVec;
1881 faceSortMap_.swap(emptyVec);
1884 if (dbg_MemProfiling)
1885 std::cout <<
"finished.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1906 std::cerr <<
"setAttrib failed: please allocate internal input buffer before using setAttrib" << std::endl;
1910 assert(inbuf->
count > _v);
1917 assert (_attrIdx >= 0);
1918 assert(_attrIdx <
int(decl_.getNumElements()));
1920 return input_[_attrIdx].count;
1924 int MeshCompiler::mapTriToInputFace(
const int _tri )
const 1927 assert(_tri < numTris_);
1930 assert(sortFaceID >= 0);
1931 assert(sortFaceID < numFaces_);
1933 int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1934 assert(faceID >= 0);
1935 assert(faceID < numFaces_);
1942 if (faceGroupIDs_.empty())
1945 return (
int)faceGroupIDs_[_faceID];
1950 return subsetIDMap_[_groupID];
1955 return &subsets_[_i];
1960 std::stringstream str;
1962 for (
int i = 0; i < (int)decl_.getNumElements(); ++i)
1968 const void* data =
static_cast<const char*
>(v) + (
size_t)el->
pointer_;
1970 switch ( el->
type_ )
1974 const double* d0 =
static_cast<const double*
>(data);
1977 str << d0[k] <<
", ";
1983 const float* f0 =
static_cast<const float*
>(data);
1986 str << f0[k] <<
", ";
1990 case GL_UNSIGNED_INT:
1992 const int* i0 =
static_cast<const int*
>(data);
1995 str << i0[k] <<
", ";
1999 case GL_UNSIGNED_SHORT:
2001 const short* i0 =
static_cast<const short*
>(data);
2004 str << i0[k] <<
", ";
2008 case GL_UNSIGNED_BYTE:
2010 const char* i0 =
static_cast<const char*
>(data);
2013 str << ((int)i0[k]) <<
", ";
2016 default: std::cerr <<
"MeshCompiler: vertexToString() unknown type: " << el->
type_ << std::endl;
2029 int numTotalErrors = 0;
2034 file.open(_filename);
2036 if (file || !_filename)
2045 file <<
"checking draw_tri <-> face mapping ..\n";
2049 int numTrisOfFace = 0;
2052 for (
int k = 0; k < numTrisOfFace; ++k)
2059 if (face != dbg_face)
2062 file <<
"error: face " << face <<
" -> (numTris: " << numTrisOfFace <<
", tri " << tri <<
" -> face " << dbg_face <<
")\n";
2069 file << numErrors <<
" errors found\n\n";
2070 numTotalErrors += numErrors;
2076 file <<
"checking (face, corner) -> vbo by comparing vertex data ..\n";
2079 char* vtxCmpData =
new char[decl_.getVertexStride() * 2];
2085 for (
int k = 0; k < fsize; ++k)
2087 char* v0 = vtxCmpData;
2088 char* v1 = vtxCmpData + decl_.getVertexStride();
2090 memset(v0, 0, decl_.getVertexStride());
2091 memset(v1, 0, decl_.getVertexStride());
2103 if (!verifyCmp.equalVertex(v0, v1, &decl_))
2109 file <<
"error: (face " << face <<
", corner " << k <<
") -> vertex " << vertex <<
": " << vertexData0.c_str() <<
" != "<< vertexData1.c_str() <<
"\n";
2117 file << numErrors <<
" errors found\n\n";
2118 numTotalErrors += numErrors;
2126 file <<
"checking vbo -> (face, corner) by comparing vertex data ..\n";
2131 int face = 0, corner = 0;
2134 char* v0 = vtxCmpData;
2135 char* v1 = vtxCmpData + decl_.getVertexStride();
2137 memset(v0, 0, decl_.getVertexStride());
2138 memset(v1, 0, decl_.getVertexStride());
2151 for (
unsigned int i = 0; i < decl_.getNumElements(); ++i)
2154 input_[i].getElementData(posID, (
char*)v1 + (
size_t)el->
pointer_, el);
2158 if (!vertexCompare_->equalVertex(v0, v1, &decl_))
2164 file <<
"error: vertex " << vertex <<
" -> (face " << face <<
", corner " << corner <<
"): " << vertexData0.c_str() <<
" != " << vertexData1.c_str() <<
"\n";
2170 file << numErrors <<
" errors found\n\n";
2171 numTotalErrors += numErrors;
2175 delete [] vtxCmpData;
2181 if (provokingVertex_ >= 0)
2184 file <<
"checking unshared per face vertices ..\n";
2187 std::vector< std::map<int, int> > VertexRefs;
2190 for (
int face = 0; face < numFaces_; ++face)
2195 for (
int k = 0; k < nTris; ++k)
2199 int faceVertex =
getIndex(tri * 3 + provokingVertex_);
2201 VertexRefs[faceVertex][face] = 1;
2210 if (VertexRefs[i].size() > 1)
2214 file <<
"error : vertex " << i <<
" is referenced by " << VertexRefs[i].size() <<
" faces: ";
2216 for (std::map<int, int>::iterator it = VertexRefs[i].begin(); it != VertexRefs[i].end(); ++it)
2217 file << it->first <<
", ";
2226 file << numErrors <<
" errors found\n\n";
2227 numTotalErrors += numErrors;
2236 file <<
"checking face group sorting ..\n";
2242 for (
int k = 0; k < (int)sub->numTris; ++k)
2249 if (grID != sub->id)
2252 file <<
"error: face " << faceID <<
" with group-id " << grID <<
" was mapped to subset-group " << sub->id <<
"\n";
2261 file << numErrors <<
" errors found\n\n";
2262 numTotalErrors += numErrors;
2271 file <<
"checking triangulation ..\n";
2273 for (
int i = 0; i < numFaces_; ++i)
2277 std::vector<int> facePositions(faceSize, -1);
2279 for (
int k = 0; k < faceSize; ++k)
2280 facePositions[k] = getInputIndex(i, k, inputIDPos_);
2282 int numFaceTris = 0;
2285 for (
int t = 0; t < numFaceTris; ++t)
2289 int triPosOccurrence[3] = {-1, -1, -1};
2291 for (
int k = 0; k < 3; ++k)
2293 int vertexID =
getIndex(triID * 3 + k);
2295 int originalFace = -1, originalCorner = -1;
2299 for (
int m = 0; m < faceSize; ++m)
2301 if (posID == facePositions[m])
2303 triPosOccurrence[k] = m;
2308 if (triPosOccurrence[k] < 0)
2311 file <<
"error: vertex at triangulated face " << i <<
" at triangle " << t <<
" at corner " << k <<
"is not even part of the original face!\n";
2318 int numInversions = 0;
2320 for (
int k = 0; k < 3; ++k)
2322 int p1 = triPosOccurrence[k];
2323 int p2 = triPosOccurrence[(k + 1) % 3];
2329 if (numInversions > 1)
2332 file <<
"error: triangulation of face " << i <<
" at triangle " << t <<
" has flipped winding order!\n";
2340 file << numErrors <<
" errors found\n\n";
2341 numTotalErrors += numErrors;
2347 return numTotalErrors == 0;
2355 file.open(_filename);
2359 for (
int i = 0; i < numAttributes_; ++i)
2363 file <<
"attribute[" << i <<
"]: internalbuf " << ((
const void*)inp->
internalBuf) <<
", data " << ((
const void*)inp->
data) <<
", count " << inp->
count <<
", stride " << inp->
stride <<
", attrSize " << inp->
attrSize <<
"\n";
2367 file <<
"faces " << numFaces_ <<
"\nindices " << numIndices_ <<
"\n";
2369 if (!vertexWeldMapFace_.empty())
2371 for (
int i = 0; i < numFaces_; ++i)
2375 int face = vertexWeldMapFace_[getInputFaceOffset(i) + k];
2376 int corner = vertexWeldMapCorner_[getInputFaceOffset(i) + k];
2377 file <<
"vertexWeldMap_[" << i <<
", "<<k<<
"] = ["<<face<<
", "<<corner<<
"]\n";
2382 for (
size_t i = 0; i < faceBufSplit_.size(); ++i)
2383 file <<
"faceBufSplit_["<<i<<
"] = "<<faceBufSplit_[i]<<
"\n";
2387 for (
size_t i = 0; i < faceGroupIDs_.size(); ++i)
2388 file <<
"faceGroupIDs_["<<i<<
"] = "<<faceGroupIDs_[i]<<
"\n";
2392 for (
size_t i = 0; i < faceSortMap_.size(); ++i)
2393 file <<
"faceSortMap_["<<i<<
"] = "<<faceSortMap_[i]<<
"\n";
2397 for (
size_t i = 0; i < triIndexBuffer_.size()/3; ++i)
2398 file <<
"tri["<<i<<
"] = "<<triIndexBuffer_[i*3+1]<<
" "<<triIndexBuffer_[i*3+1]<<
" "<<triIndexBuffer_[i*3+2]<<
"\n";
2402 for (
size_t i = 0; i < subsets_.size(); ++i)
2404 const Subset* sub = &subsets_[i];
2405 file <<
"subset["<<i<<
"]: id "<<sub->id<<
", startIndex "<<sub->startIndex<<
", numTris "<<sub->numTris<<
", numFaces "<<sub->numFaces<<
", startFace "<<sub->startFace<<
"\n";
2410 for (std::map<int, int>::const_iterator it = subsetIDMap_.begin();
2411 it != subsetIDMap_.end(); ++it)
2412 file <<
"subsetIDMap["<<it->first<<
"] = "<<it->second<<
"\n";
2416 for (
int i = 0; i < numFaces_; ++i)
2428 file <<
"mapToOriginalVertexID["<<i<<
"] = ["<<f<<
", "<<c<<
"]\n";
2431 file <<
"\n\nadjacencyVert\n";
2432 adjacencyVert_.dbgdump(file);
2439 for (
int i = 0; i < numFaces_; ++i)
2447 file <<
"data["<<i<<
", "<<k<<
"] = ("<<vtx[0]<<
" "<<vtx[1]<<
" "<<vtx[2]<<
") ("<<vtx[3]<<
" "<<vtx[4]<<
") ("<<vtx[5]<<
" "<<vtx[6]<<
" "<<vtx[7]<<
")\n";
2456 void MeshCompiler::AdjacencyList::dbgdump(std::ofstream& file)
const 2460 for (
int i = 0; i < num; ++i)
2462 for (
int k = 0; k < getCount(i); ++k)
2463 file <<
"adj["<<i<<
"]["<<k<<
"] = "<<getAdj(i,k)<<
"\n";
2471 if (count == 0 || !data)
2473 memset(_dst, 0, attrSize);
2480 if (_idx < 0 || _idx >= count)
2482 memset(_dst, 0, attrSize);
2486 const void* dataAdr =
static_cast<const char*
>(data) + (
size_t)(_idx * stride);
2488 if (fmt == 0 || elementSize == -1 || fmt == _desc->
type_)
2489 memcpy(_dst, dataAdr, attrSize);
2493 int data_i[4] = {0,0,0,0};
2494 double data_d[4] = {0.0, 0.0, 0.0, 0.0};
2497 for (
int i = 0; i < elementSize; ++i)
2501 case GL_FLOAT: data_d[i] = (
static_cast<const float*
>(dataAdr))[i];
break;
2502 case GL_DOUBLE: data_d[i] = (
static_cast<const double*
>(dataAdr))[i];
break;
2504 case GL_UNSIGNED_INT:
2505 case GL_INT: data_i[i] = (
static_cast<const int*
>(dataAdr))[i];
break;
2507 case GL_UNSIGNED_SHORT:
2508 case GL_SHORT: data_i[i] = (
static_cast<const short*
>(dataAdr))[i];
break;
2510 case GL_UNSIGNED_BYTE:
2511 case GL_BYTE: data_i[i] = (
static_cast<const short*
>(dataAdr))[i];
break;
2513 default: std::cerr <<
"MeshCompiler: unknown data format - " << fmt << std::endl;
break;
2519 memset(_dst, 0, attrSize);
2522 if (fmt == GL_FLOAT || fmt == GL_DOUBLE)
2524 for (
int i = 0; i < (int)_desc->
numElements_ && i < (
int)elementSize; ++i)
2526 switch (_desc->
type_)
2528 case GL_FLOAT: ((
float*)_dst)[i] = (float)data_d[i];
break;
2529 case GL_DOUBLE: ((
double*)_dst)[i] = (double)data_d[i];
break;
2531 case GL_UNSIGNED_INT:
2532 case GL_INT: ((
int*)_dst)[i] = (int)data_d[i];
break;
2534 case GL_UNSIGNED_BYTE:
2535 case GL_BYTE: ((
char*)_dst)[i] = (char)data_d[i];
break;
2537 case GL_UNSIGNED_SHORT:
2538 case GL_SHORT: ((
short*)_dst)[i] = (short)data_d[i];
break;
2546 for (
int i = 0; i < (int)_desc->
numElements_ && i < (
int)elementSize; ++i)
2548 switch (_desc->
type_)
2550 case GL_FLOAT: ((
float*)_dst)[i] = (float)data_i[i];
break;
2551 case GL_DOUBLE: ((
double*)_dst)[i] = (double)data_i[i];
break;
2553 case GL_UNSIGNED_INT:
2554 case GL_INT: ((
int*)_dst)[i] = (int)data_i[i];
break;
2556 case GL_UNSIGNED_BYTE:
2557 case GL_BYTE: ((
char*)_dst)[i] = (char)data_i[i];
break;
2559 case GL_UNSIGNED_SHORT:
2560 case GL_SHORT: ((
short*)_dst)[i] = (short)data_i[i];
break;
2577 file.open(_filename);
2587 if (inputIDPos_ >= 0)
2589 float* pos = vertex + (size_t)decl_.getElement(inputIDPos_)->pointer_ / 4;
2590 file <<
"v "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2593 if (inputIDNorm_ >= 0)
2595 float* pos = vertex + (size_t)decl_.getElement(inputIDNorm_)->pointer_ / 4;
2596 file <<
"vn "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2599 if (inputIDTexC_ >= 0)
2601 float* pos = vertex + (size_t)decl_.getElement(inputIDTexC_)->pointer_ / 4;
2602 file <<
"vt "<<pos[0]<<
" "<<pos[1]<<
"\n";
2607 for (
int i = 0; i < numTris_; ++i)
2609 if (!inputIDTexC_ && !inputIDNorm_)
2612 else if (!inputIDTexC_)
2613 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";
2616 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";
2629 const int nVerts = (inputIDPos_ >= 0) ? input_[inputIDPos_].count : 0;
2635 file.open(_filename);
2641 for (
int i = 0; i < nVerts; ++i)
2645 input_[inputIDPos_].getElementData(i, pos, el);
2647 file <<
"v "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2650 if (inputIDTexC_ >= 0)
2656 for (
int i = 0; i < vei->
count; ++i)
2659 file <<
"vt "<<pos[0]<<
" "<<pos[1]<<
"\n";
2664 if (inputIDNorm_ >= 0)
2670 for (
int i = 0; i < vei->
count; ++i)
2673 file <<
"vn "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2680 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2682 std::string strLine =
"f ";
2684 int size = faceInput_->getFaceSize(i);
2687 for (
int k = 0; k < size; ++k)
2689 if (inputIDNorm_>=0 && inputIDTexC_>=0)
2690 sprintf(tmp,
"%d/%d/%d ", faceInput_->getSingleFaceAttr(i, k, inputIDPos_) + 1,
2691 faceInput_->getSingleFaceAttr(i, k, inputIDTexC_) + 1,
2692 faceInput_->getSingleFaceAttr(i, k, inputIDNorm_) + 1);
2693 else if (inputIDNorm_ >= 0)
2694 sprintf(tmp,
"%d//%d ", faceInput_->getSingleFaceAttr(i, k, inputIDPos_) + 1, faceInput_->getSingleFaceAttr(i, k, inputIDNorm_) + 1);
2695 else if (inputIDTexC_ >= 0)
2696 sprintf(tmp,
"%d/%d ", faceInput_->getSingleFaceAttr(i, k, inputIDPos_) + 1, faceInput_->getSingleFaceAttr(i, k, inputIDTexC_) + 1);
2698 sprintf(tmp,
"%d ", faceInput_->getSingleFaceAttr(i, k, inputIDPos_) + 1);
2703 file << strLine.c_str() <<
"\n";
2716 const int nVerts = (inputIDPos_ >= 0) ? input_[inputIDPos_].count : 0;
2717 const int nNormals = (inputIDNorm_ >= 0) ? input_[inputIDNorm_].count : 0;
2718 const int nTexC = (inputIDTexC_ >= 0) ? input_[inputIDTexC_].count : 0;
2720 if (!_seperateFiles)
2756 file = fopen(_filename,
"wb");
2760 const int nFaces = faceInput_->getNumFaces();
2761 fwrite(&nFaces, 4, 1, file);
2763 fwrite(&nVerts, 4, 1, file);
2764 fwrite(&nNormals, 4, 1, file);
2765 fwrite(&nTexC, 4, 1, file);
2767 int faceBufSize = 0;
2769 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2770 faceBufSize += faceInput_->getFaceSize(i);
2772 fwrite(&faceBufSize, 4, 1, file);
2776 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2778 int fsize = faceInput_->getFaceSize(i);
2779 fwrite(&fsize, 4, 1, file);
2782 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2784 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2786 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDPos_);
2787 fwrite(&idx, 4, 1, file);
2791 if (inputIDTexC_ >= 0)
2793 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2795 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2797 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDTexC_);
2798 fwrite(&idx, 4, 1, file);
2803 if (inputIDNorm_ >= 0)
2805 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2807 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2809 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDNorm_);
2810 fwrite(&idx, 4, 1, file);
2818 for (
int i = 0; i < nVerts; ++i)
2822 input_[inputIDPos_].getElementData(i, pos, el);
2824 fwrite(pos, 4, 3, file);
2827 if (inputIDTexC_ >= 0)
2833 for (
int i = 0; i < vei->
count; ++i)
2836 fwrite(pos, 4, 2, file);
2841 if (inputIDNorm_ >= 0)
2847 for (
int i = 0; i < vei->
count; ++i)
2850 fwrite(pos, 4, 3, file);
2857 fwrite(&adjacencyVert_.num, 4, 1, file);
2858 fwrite(&adjacencyVert_.bufSize, 4, 1, file);
2860 fwrite(adjacencyVert_.start, 4, adjacencyVert_.num, file);
2861 fwrite(adjacencyVert_.count, 1, adjacencyVert_.num, file);
2862 fwrite(adjacencyVert_.buf, 4, adjacencyVert_.bufSize, file);
2871 FILE* file = fopen(
"../mesh_fsize.bin",
"wb");
2873 for (
int i = 0; i < numFaces_; ++i)
2875 unsigned char fsize = (
unsigned char)faceInput_->getFaceSize(i);
2876 fwrite(&fsize, 1, 1, file);
2881 file = fopen(
"../mesh_fdata_pos.bin",
"wb");
2883 for (
int i = 0; i < numFaces_; ++i)
2885 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2887 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDPos_);
2888 fwrite(&idx, 4, 1, file);
2894 if (inputIDTexC_ >= 0)
2896 file = fopen(
"../mesh_fdata_texc.bin",
"wb");
2898 for (
int i = 0; i < numFaces_; ++i)
2900 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2902 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDTexC_);
2903 fwrite(&idx, 4, 1, file);
2910 if (inputIDNorm_ >= 0)
2912 file = fopen(
"../mesh_fdata_norm.bin",
"wb");
2914 for (
int i = 0; i < numFaces_; ++i)
2916 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2918 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDNorm_);
2919 fwrite(&idx, 4, 1, file);
2928 file = fopen(
"../mesh_vdata_pos.bin",
"wb");
2929 for (
int i = 0; i < nVerts; ++i)
2933 input_[inputIDPos_].getElementData(i, pos, el);
2935 fwrite(pos, 4, 3, file);
2939 if (inputIDTexC_ >= 0)
2941 file = fopen(
"../mesh_vdata_texc.bin",
"wb");
2947 for (
int i = 0; i < vei->
count; ++i)
2950 fwrite(pos, 4, 2, file);
2957 if (inputIDNorm_ >= 0)
2959 file = fopen(
"../mesh_vdata_norm.bin",
"wb");
2965 for (
int i = 0; i < vei->
count; ++i)
2968 fwrite(pos, 4, 3, file);
2985 int tmp[] = {_v0, _v1, _v2};
2996 int tmp[] = {_v0, _v1, _v2};
3008 int tmp[] = {_v0, _v1, _v2};
3014 int faceID, cornerID;
3020 for (
int i = 0; i < numAttributes_; ++i)
3024 int idx = getInputIndex(faceID, cornerID, i);
3026 input_[i].getElementData(idx, (
char*)_out + (
size_t)el->
pointer_, el);
3033 for (
int i = 0; i < numAttributes_; ++i)
3036 input_[i].getElementData(posID, (
char*)_out + (
size_t)el->
pointer_, el);
3044 assert(_i < numTris_ * 3);
3048 void MeshCompiler::createVertexMap(
bool _keepIsolatedVerts)
3055 if (_keepIsolatedVerts)
3063 for (
int i = 0; i < numFaces_; ++i)
3066 for (
int k = 0; k < fsize; ++k)
3069 int vertexID = getInputIndexSplit(i, k);
3071 vertexMapCorner_[vertexID] = k;
3075 if (_keepIsolatedVerts)
3092 vertexMapCorner_[i] < 0)
3093 std::cerr <<
"mesh-assembler: vertexMap error at index: " << i << std::endl;
3096 std::cerr <<
"mesh-assembler: vertexMap error at index: " << i << std::endl;
3103 void MeshCompiler::createFaceMap()
3110 for (
int i = 0; i < numTris_; ++i)
3119 if (!faceSortMap_.empty())
3120 faceID = faceSortMap_[faceID];
3132 faceToTriMapOffset_.clear();
3133 if (!constantFaceSize_)
3135 faceToTriMapOffset_.resize(numTris_, -1);
3138 for (
int i = 0; i < numFaces_; ++i)
3140 faceToTriMapOffset_[i] = offset;
3144 offset += fsize - 2;
3152 for (
int i = 0; i < numTris_; ++i)
3158 int offset = constantFaceSize_ ? (faceID * (maxFaceSize_ - 2)) : faceToTriMapOffset_[faceID];
3163 while (
faceToTriMap_[offset + triNo] != -1 && triNo + offset < numTris_)
3180 file = fopen(_filename,
"wt");
3184 fprintf(file,
"vertex-adjacency: \n");
3185 for (
int i = 0; i < input_[inputIDPos_].count; ++i)
3188 int count = getAdjVertexFaceCount(i);
3190 std::vector<int> sortedList(count);
3191 for (
int k = 0; k < count; ++k)
3192 sortedList[k] = getAdjVertexFace(i, k);
3194 std::sort(sortedList.begin(), sortedList.end());
3196 for (
int k = 0; k < count; ++k)
3197 fprintf(file,
"adj[%d][%d] = %d\n", i, k, sortedList[k]);
3207 if ((
int)faceGroupIDs_.size() <= std::max(numFaces_,_i))
3208 faceGroupIDs_.resize(std::max(numFaces_,_i+1), -1);
3210 faceGroupIDs_[_i] = _groupID;
3218 int batchSize = _range;
3224 char* bdst = (
char*)_dst;
3226 for (
int i = 0; i < batchSize; ++i)
3228 getVertex(i + _offset, bdst + decl_.getVertexStride() * i);
3238 : e0(std::min(a,b)), e1(std::max(a,b)) {}
3242 return e0 == k.e0 && e1 == k.e1;
3258 #ifdef ACG_MC_USE_STL_HASH 3260 struct MeshCompiler_EdgeTriMapKey_Hash
3264 return ((std::hash<int>()(k.e0) << 1) ^ std::hash<int>()(k.e1)) >> 1;
3270 return ((::qHash(k.e0) << 1) ^ ::qHash(k.e1)) >> 1;
3272 #endif // ACG_MC_USE_STL_HASH 3277 int* idst = (
int*)_dst;
3279 for (
int i = 0; i < numTris_; ++i)
3286 idst[i*6+1] = _borderIndex;
3287 idst[i*6+3] = _borderIndex;
3288 idst[i*6+5] = _borderIndex;
3292 QHash<MeshCompiler_EdgeTriMapKey, std::pair<int, int> > EdgeAdjMap;
3294 for (
int i = 0; i < numTris_; ++i)
3299 for (
int k = 0; k < 3; ++k)
3301 int faceId, cornerId;
3306 for (
int e = 0; e < 3; ++e)
3310 QHash< MeshCompiler_EdgeTriMapKey, std::pair<int, int> >::iterator itKey;
3312 itKey = EdgeAdjMap.find(edge);
3314 if (itKey == EdgeAdjMap.end())
3315 EdgeAdjMap[edge] = std::pair<int, int>(i, -1);
3317 itKey.value().second = i;
3323 for (QHash<
MeshCompiler_EdgeTriMapKey, std::pair<int, int> >::iterator it = EdgeAdjMap.begin(); it != EdgeAdjMap.end(); ++it)
3326 int Tris[2] = {it.value().first, it.value().second};
3331 for (
int k = 0; k < 3; ++k)
3333 int faceId, cornerId;
3344 int TriEdges[2] = {-1,-1};
3345 int TriOppositeVerts[2] = {-1,-1};
3347 for (
int e = 0; e < 3; ++e)
3351 if (edge0 == it.key())
3354 TriOppositeVerts[1] = (e+2)%3;
3360 for (
int e = 0; e < 3; ++e)
3364 if (edge1 == it.key())
3367 TriOppositeVerts[0] = (e+2)%3;
3374 for (
int i = 0; i < 2; ++i)
3378 int e = TriEdges[i];
3381 int ov = _borderIndex;
3383 if (TriOppositeVerts[i] >= 0 && Tris[(i+1)%2] >= 0)
3384 ov =
getIndex(Tris[(i+1)%2]*3 + TriOppositeVerts[i]);
3386 idst[Tris[i] * 6 + e*2 + 1] = ov;
3468 const int numVerts = input_[inputIDPos_].count;
3471 outputVertexTriAdj.init(numVerts);
3474 for (
int i = 0; i < numTris_; ++i)
3476 int faceID, cornerID;
3478 for (
int k = 0; k < 3; ++k)
3483 outputVertexTriAdj.count[posID]++;
3490 for (
int i = 0; i < numVerts; ++i)
3492 outputVertexTriAdj.start[i] = nCounter;
3494 nCounter += outputVertexTriAdj.count[i];
3496 outputVertexTriAdj.count[i] = 0;
3500 outputVertexTriAdj.buf =
new int[nCounter];
3501 outputVertexTriAdj.bufSize = nCounter;
3504 for (
int i = 0; i < numTris_; ++i)
3506 int faceID, cornerID;
3508 for (
int k = 0; k < 3; ++k)
3513 int adjIdx = outputVertexTriAdj.start[posID] + outputVertexTriAdj.count[posID]++;
3515 outputVertexTriAdj.buf[ adjIdx ] = i;
3522 int* idst = (
int*)_dst;
3524 for (
int i = 0; i < numTris_; ++i)
3531 idst[i*6+1] = _borderIndex;
3532 idst[i*6+3] = _borderIndex;
3533 idst[i*6+5] = _borderIndex;
3537 #pragma omp parallel for 3539 for (
int vertexID = 0; vertexID < numVerts; ++vertexID)
3541 const int numAdjTris = outputVertexTriAdj.getCount(vertexID);
3544 for (
int adjID0 = 0; adjID0 < numAdjTris; ++adjID0)
3546 const int triID0 = outputVertexTriAdj.getAdj(vertexID, adjID0);
3549 for (
int k = 0; k < 3; ++k)
3551 int faceid, cornerid;
3555 for (
int adjID1 = adjID0+1; adjID1 < numAdjTris; ++adjID1)
3557 const int triID1 = outputVertexTriAdj.getAdj(vertexID, adjID1);
3560 for (
int k = 0; k < 3; ++k)
3562 int faceid, cornerid;
3567 for (
int e0 = 0; e0 < 3; ++e0)
3571 for (
int e1 = 0; e1 < 3; ++e1)
3579 int oppVertex0 =
getIndex( triID1*3 + ((e1+2)%3) );
3580 int oppVertex1 =
getIndex( triID0*3 + ((e0+2)%3) );
3582 idst[triID0*6 + e0*2 +1] = oppVertex0;
3583 idst[triID1*6 + e1*2 + 1] = oppVertex1;
3600 int* idst = (
int*)_dst;
3602 for (
int i = 0; i < numTris_; ++i)
3609 idst[i*6+1] = _borderIndex;
3610 idst[i*6+3] = _borderIndex;
3611 idst[i*6+5] = _borderIndex;
3616 #pragma omp parallel for 3618 for (
int triID0 = 0; triID0 < numTris_; ++triID0)
3621 for (
int k = 0; k < 3; ++k)
3623 int faceid, cornerid;
3627 for (
int triID1 = triID0 + 1; triID1 < numTris_; ++triID1)
3630 for (
int k = 0; k < 3; ++k)
3632 int faceid, cornerid;
3637 for (
int e0 = 0; e0 < 3; ++e0)
3641 for (
int e1 = 0; e1 < 3; ++e1)
3649 int oppVertex0 =
getIndex( triID1*3 + ((e1+2)%3) );
3650 int oppVertex1 =
getIndex( triID0*3 + ((e0+2)%3) );
3652 idst[triID0*6 + e0*2 +1] = oppVertex0;
3653 idst[triID1*6 + e1*2 + 1] = oppVertex1;
3695 int positionID = -1;
3701 _cornerID = vertexMapCorner_[_i];
3703 positionID = getInputIndex(_faceID, _cornerID, inputIDPos_);
3719 return getInputIndexSplit(_faceID, _cornerID);
3725 assert(_k < fsize - 2);
3728 *_numTrisOut = fsize - 2;
3730 int offset = constantFaceSize_ ? (_faceID * (maxFaceSize_ - 2)) : faceToTriMapOffset_[_faceID];
3763 size_t usage = faceStart_.size() * 4;
3764 usage += faceSize_.size() * 1;
3765 usage += faceData_.size() * 4;
3766 usage += faceGroupIDs_.size() * 2;
3767 usage += faceBufSplit_.size() * 4;
3768 usage += faceSortMap_.size() * 4;
3770 usage += triIndexBuffer_.size() * 4;
3772 usage += subsetIDMap_.size() *
sizeof(
Subset);
3774 usage += vertexWeldMapFace_.size() * 5;
3776 usage += adjacencyVert_.bufSize * 4;
3777 usage += adjacencyVert_.num * 4;
3778 usage += adjacencyVert_.num * 1;
3782 usage += splitter_->splits.size() * 4;
3788 usage += faceToTriMapOffset_.size() * 4;
3797 const int byteToMB = 1024 * 1024;
3799 std::cout <<
"faceStart_: " <<
sizeof(std::pair<int, unsigned char>) << std::endl;
3801 std::cout <<
"faceStart_: " << faceStart_.size() * 4 / byteToMB << std::endl;
3802 std::cout <<
"faceSize_: " << faceSize_.size() * 1 / byteToMB << std::endl;
3803 std::cout <<
"faceData_: " << faceData_.size() * 4 / byteToMB << std::endl;
3804 std::cout <<
"faceGroupIDs_: " << faceGroupIDs_.size() * 2 / byteToMB << std::endl;
3805 std::cout <<
"faceBufSplit_: " << faceBufSplit_.size() * 4 / byteToMB << std::endl;
3807 std::cout <<
"faceSortMap_: " << faceSortMap_.size() * 4 / byteToMB << std::endl;
3809 std::cout <<
"triIndexBuffer_: " << triIndexBuffer_.size() * 4 / byteToMB << std::endl;
3811 std::cout <<
"vertexWeldMap_: " << vertexWeldMapFace_.size() * 5 / byteToMB << std::endl;
3813 std::cout <<
"adjacencyVert_: buf = " << adjacencyVert_.bufSize * 4 / byteToMB <<
3814 ", offset = " << adjacencyVert_.num * 4 / byteToMB <<
3815 ", count = " << adjacencyVert_.num * 1 / byteToMB << std::endl;
3818 std::cout <<
"splitter_: " << splitter_->splits.size() * 4 / byteToMB << std::endl;
3820 std::cout <<
"triToSortFaceMap_: " <<
triToSortFaceMap_.size() * 4 / byteToMB << std::endl;
3821 std::cout <<
"triOptMap_: " <<
triOptMap_.size() * 4 / byteToMB << std::endl;
3822 std::cout <<
"vertexMap_: " <<
vertexMapFace_.size() * 5 / byteToMB << std::endl;
3823 std::cout <<
"faceToTriMapOffset_: " << faceToTriMapOffset_.size() * 4 / byteToMB << std::endl;
3824 std::cout <<
"faceToTriMap_: " <<
faceToTriMap_.size() * 4 / byteToMB << std::endl;
3825 std::cout <<
"triToFaceMap_: " <<
triToFaceMap_.size() * 4 / byteToMB << std::endl;
3828 std::cout <<
"indices_: " << 3 * numTris_ * 4 / byteToMB << std::endl;
3841 return "Error: no face input data present\n";
3843 std::stringstream strm;
3847 for (
int a = 0; a < numAttributes_; ++a)
3849 if (input_[a].count <= 0)
3850 strm <<
"Warning: input buffer is not initialized: buffer id " << a <<
"\n";
3853 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
3855 if (faceInput_->getFaceSize(i) < 3)
3856 strm <<
"Error: face size too small: face " << i <<
", size " << faceInput_->getFaceSize(i) <<
" must be at least 3\n";
3858 std::map<int, int> facePositions;
3860 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
3864 for (
int a = 0; a < numAttributes_; ++a)
3866 if (input_[a].count > 0)
3869 if (faceV[a] >= input_[a].count)
3870 strm <<
"Error: input index (face/corner/attribute: " << i <<
"/" << k <<
"/" << a <<
") invalid: " << faceV[a] <<
" >= buffer size (" << input_[a].count <<
")\n";
3872 strm <<
"Error: input index (face/corner/attribute: " << i <<
"/" << k <<
"/" << a <<
") invalid: " << faceV[a] <<
"\n";
3877 facePositions[faceV[0]] = k;
3881 if ((
int)facePositions.size() != faceInput_->getFaceSize(i))
3882 strm <<
"Warning: degenerate face " << i <<
"\n";
3885 if (!faceInput_->getFaceSize(i))
3886 strm <<
"Warning: empty face " << i <<
"\n";
3895 numFaces_ = faceInput_->getNumFaces();
3896 numIndices_ = faceInput_->getNumIndices();
3899 for (
int i = numFaces_-1; i >= 0 && !faceInput_->getFaceSize(i); --i)
3903 for (
unsigned int i = 0; i < decl_.getNumElements(); ++i)
3906 assert(input_[i].attrSize <= 0 || input_[i].attrSize == attrSize);
3907 input_[i].attrSize = attrSize;
3912 int minFaceSize = 99999999;
3913 for (
int i = 0; i < numFaces_; ++i)
3915 const int fsize = faceInput_->getFaceSize(i);
3917 maxFaceSize_ = std::max((
int)maxFaceSize_, fsize);
3918 minFaceSize = std::min(minFaceSize, fsize);
3923 if (minFaceSize < 3)
3924 std::cout <<
"error: input contains faces with less than 3 vertices! MeshCompiler only works for pure surface meshes!" << std::endl;
3926 assert(minFaceSize >= 3);
3928 if (minFaceSize < (
int)maxFaceSize_)
3933 faceStart_.resize(numFaces_, -1);
3934 faceSize_.resize(numFaces_, 0);
3936 for (
int i = 0; i < numFaces_; ++i)
3938 faceSize_[i] = faceInput_->getFaceSize(i);
3939 faceStart_[i] = curOffset;
3940 curOffset += faceSize_[i];
3943 if (numIndices_ <= 0)
3944 numIndices_ = curOffset;
3948 constantFaceSize_ =
true;
3949 numIndices_ = maxFaceSize_ * numFaces_;
3956 faceSortMap_.clear();
3959 faceToTriMapOffset_.clear();
3963 vertexMapCorner_.clear();
3965 faceBufSplit_.clear();
3967 isolatedVertices_.clear();
3970 if (!provokingVertexSetByUser_)
3971 provokingVertex_ = -1;
3975 for (
int i = 0; i < numFaces_; ++i)
3979 int v0 = faceInput_->getSingleFaceAttr(i, k, inputIDPos_);
3980 int v1 = getInputIndex(i, k, inputIDPos_);
3990 faceInput_ = _faceInput;
4000 for (
int i = 0; i < _numTris; ++i)
4002 int tri[3] = {-1, -1, -1};
4004 for (
int k = 0; k < 3; ++k)
4006 int offs = i * 3 + k;
4010 case 1: tri[k] = ((
char*)_indices)[offs];
break;
4011 case 2: tri[k] = ((
short*)_indices)[offs];
break;
4012 case 4: tri[k] = ((
int*)_indices)[offs];
break;
4013 case 8: tri[k] = (int)((
long long*)_indices)[offs];
break;
4029 provokingVertex_ = _v;
4030 provokingVertexSetByUser_ =
true;
4033 int MeshCompiler::getAdjVertexFaceCount(
int _vertexID )
const 4035 return adjacencyVert_.num ? adjacencyVert_.getCount(_vertexID) : faceInput_->getVertexAdjCount(_vertexID);
4038 int MeshCompiler::getAdjVertexFace(
int _vertexID,
int _k )
const 4040 return adjacencyVert_.num ? adjacencyVert_.getAdj(_vertexID, _k) : faceInput_->getVertexAdjFace(_vertexID, _k);
4045 return maxFaceSize_ == 3;
4053 if (maxFaceSize_ <= 3)
return true;
4061 std::vector<int> FaceVerts(fsize);
4063 for (
int i = 0; i < fsize; ++i)
4071 case 0: edgeStart = 0; edgeEnd = 1;
break;
4072 case 1: edgeStart = 1; edgeEnd = 2;
break;
4073 case 2: edgeStart = 2; edgeEnd = 0;
break;
4078 edgeStart =
getIndex(_triID * 3 + edgeStart);
4079 edgeEnd =
getIndex(_triID * 3 + edgeEnd);
4082 for (
int e = 0; e < fsize; ++e)
4084 if (FaceVerts[e] == edgeStart && FaceVerts[(e+1)%fsize] == edgeEnd)
4086 if (FaceVerts[e] == edgeEnd && FaceVerts[(e+1)%fsize] == edgeStart)
4093 void MeshCompilerDefaultFaceInput::dbgWriteToObjFile(FILE* _file,
int _posAttrID,
int _normalAttrID,
int _texcAttrID)
4095 for (
int i = 0; i < numFaces_; ++i)
4097 std::string strLine =
"f ";
4099 int offset = faceOffset_[i];
4100 int size = faceSize_[i];
4103 for (
int k = 0; k < size; ++k)
4105 if (_normalAttrID>=0 && _texcAttrID>=0)
4106 sprintf(tmp,
"%d/%d/%d ", faceData_[_posAttrID][offset+k]+1,
4107 faceData_[_texcAttrID][offset+k]+1,
4108 faceData_[_normalAttrID][offset+k]+1);
4109 else if (_normalAttrID >= 0)
4110 sprintf(tmp,
"%d//%d ", faceData_[_posAttrID][offset + k]+1, faceData_[_normalAttrID][offset+k]+1);
4111 else if (_texcAttrID >= 0)
4112 sprintf(tmp,
"%d/%d ", faceData_[_posAttrID][offset + k]+1, faceData_[_texcAttrID][offset+k]+1);
4114 sprintf(tmp,
"%d ", faceData_[_posAttrID][offset + k]+1);
4119 fprintf(_file,
"%s\n", strLine.c_str());
4125 int offset = faceOffset_[_faceID];
4126 int fsize = faceSize_[_faceID];
4128 for (
int i = 0; i < fsize; ++i)
4129 _out[i] = faceData_[_attrID][offset+i];
4137 const int pos = faceOffset_[_faceID] + _faceCorner;
4141 if (faceData_[_attrID].empty() || pos >=
int(faceData_[_attrID].size()))
4144 return faceData_[_attrID][pos];
4147 void MeshCompilerDefaultFaceInput::setFaceData(
int _faceID,
int _size,
int* _data,
int _attrID )
4150 if (numFaces_ <= _faceID)
4151 numFaces_ = _faceID + 1;
4154 if (faceData_[_attrID].capacity() == 0)
4155 faceData_[_attrID].reserve(numIndices_);
4157 if ((
int)faceOffset_.size() <= _faceID)
4158 faceOffset_.resize(_faceID+1, -1);
4160 if ((
int)faceSize_.size() <= _faceID)
4161 faceSize_.resize(_faceID+1, -1);
4163 faceSize_[_faceID] = _size;
4165 if (faceOffset_[_faceID] < 0)
4168 faceOffset_[_faceID] = faceData_[_attrID].size();
4169 for (
int i = 0; i < _size; ++i)
4170 faceData_[_attrID].push_back(_data[i]);
4174 int offs = faceOffset_[_faceID];
4176 if ((
int)faceData_[_attrID].size() == offs)
4178 for (
int i = 0; i < _size; ++i)
4179 faceData_[_attrID].push_back(_data[i]);
4184 if ((
int)faceData_[_attrID].size() < offs + _size + 1)
4185 faceData_[_attrID].resize(offs + _size + 1, -1);
4188 for (
int i = 0; i < _size; ++i)
4189 faceData_[_attrID][offs + i] = _data[i];
4199 assert(_faceID >= 0);
4200 assert(_faceCorner >= 0);
4201 assert(_faceCorner < fsize);
4205 int* tmpPtr = getFaceAttr(_faceID, _attrID);
4208 retVal = tmpPtr[_faceCorner];
4211 tmpPtr =
new int[fsize];
4212 if (getFaceAttr(_faceID, _attrID, tmpPtr))
4213 retVal = tmpPtr[_faceCorner];
4221 bool MeshCompilerVertexCompare::equalVertex(
const void* v0,
const void* v1,
const VertexDeclaration* _decl )
4230 for (
int i = 0; i < nElements; ++i)
4235 const void* el_0 =
static_cast<const char*
>(v0) + (
size_t)el->
pointer_;
4236 const void* el_1 =
static_cast<const char*
>(v1) + (
size_t)el->
pointer_;
4239 switch ( el->
type_ )
4243 const double* d0 =
static_cast<const double*
>(el_0);
4244 const double* d1 =
static_cast<const double*
>(el_1);
4249 diff += fabs(d0[k] - d1[k]);
4259 const float* f0 =
static_cast<const float*
>(el_0);
4260 const float* f1 =
static_cast<const float*
>(el_1);
4271 diff += fabsf(f0[k] - f1[k]);
4279 case GL_UNSIGNED_INT:
4281 const int* i0 =
static_cast<const int*
>(el_0);
4282 const int* i1 =
static_cast<const int*
>(el_1);
4292 case GL_UNSIGNED_SHORT:
4294 const short* i0 =
static_cast<const short*
>(el_0);
4295 const short* i1 =
static_cast<const short*
>(el_1);
4305 case GL_UNSIGNED_BYTE:
4307 const char* i0 =
static_cast<const char*
>(el_0);
4308 const char* i1 =
static_cast<const char*
>(el_1);
4317 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 getNumVertices() const
void getInputFaceVertex(const int _face, const int _corner, int *_out) const
void setFaceNormals(int _i, int _v0, int _v1, int _v2)
Set normal ids per triangle.
int mapToOriginalFaceID(const int _triID) const
unsigned int type_
GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ...
void build(bool _weldVertices=false, bool _optimizeVCache=true, bool _needPerFaceAttribute=false, bool _keepIsolatedVertices=false)
Build vertex + index buffer.
std::vector< int > vertexMapFace_
vertex index in vbo -> input (face id, corner id) pair , also inverse of faceBufSplit_ ...
int getNumSubsets() const
Get the number of subsets.
unsigned int getNumElements() const
bool dbgVerify(const char *_filename) const
test correctness of input <-> output id mappings, unshared per face vertex.. logs errors in file ...
bool getFaceAttr(const int _faceID, const int _attrID, int *_out) const
Description of one vertex element.
unsigned int vbo_
Explicit vbo source of this element, set to 0 if the buffer bound at the time of activating the decla...
int getNumInputAttributes(int _attrIdx) const
int getSingleFaceAttr(const int _faceID, const int _faceCorner, const int _attrID) const
void setProvokingVertex(int _v)
int count
elements in buffer
void setFaceAttrib(int _i, int _v0, int _v1, int _v2, int _attrID)
Set attribute ids per triangle.
int numTriangles() const
Get number of triangles.
const void * pointer_
Offset in bytes to the first occurrence of this element in vertex buffer; Or address to vertex data i...
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.
bool isIsolated(const int vertexPosID)
check if vertex is isolated with a complete splitting list
Class to define the vertex input layout.
std::vector< int > triToSortFaceMap_
maps from triangle ID to sorted face ID
virtual int getSingleFaceAttr(const int _faceID, const int _faceCorner, const int _attrID) const
const unsigned int * GetTriangleMap() const
Retrieves the map from dst triangle to src triangle. how to remap: for each triangle t in DstTriBuffe...
std::vector< int > triToFaceMap_
output tri index -> input face index
std::vector< int > indices_
index buffer
unsigned int numElements_
how many elements of type_
int index(int _i) const
Get local vertex index.
const int * mapToOriginalFaceIDPtr() const
VERTEX_USAGE usage_
position, normal, shader input ..
void setFaceTexCoords(int _i, int _v0, int _v1, int _v2)
Set texcoord ids per triangle.
void getInputFaceVertex_Welded(const int _face, const int _corner, int *_out) const
void dbgdumpInputObj(const char *_filename) const
dump input mesh to wavefront obj format
int getIndex(int _i) const
std::vector< int > triOptMap_
maps from optimized tri ID to unoptimized tri ID
unsigned int divisor_
For instanced rendering: Step rate describing how many instances are drawn before advancing to the ne...
void getVertexBuffer(void *_dst, const int _offset=0, const int _range=-1)
Get vertex buffer ready for rendering.
void dbgdumpInputBin(const char *_filename, bool _seperateFiles=false) const
dump input mesh to binary file format
void setFaceInput(MeshCompilerFaceInput *_faceInput)
std::string checkInputData() const
check for errors in input data
std::string vertexToString(const void *v) const
interpret vertex data according declaration and write to string
char * internalBuf
mem alloc if attribute buffer managed by this class
void setNumFaces(const int _numFaces, const int _numIndices)
Set number of faces and indices if known by user.
void setVertices(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
void setAttrib(int _attrIdx, int _v, const void *_data)
void getIndexAdjBuffer_MT(void *_dst, const int _borderIndex=-1)
Multi-threaded version of getIndexAdjBuffer.
int stride
offset in bytes from one element to the next
void getVertex(int _id, void *_out) const
const char * shaderInputName_
set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically...
bool isTriangleMesh() const
void setNormals(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
int split(int *vertex)
returns a unique index for a vertex-attribute combination
int mapToOriginalVertexID(const int _i, int &_faceID, int &_cornerID) const
Namespace providing different geometric functions concerning angles.
void dbgdumpObj(const char *_filename) const
dump mesh in wavefront obj format
int numDrawVerts_
vertices in vbo
bool isFaceEdge(const int _triID, const int _edge) const
const Subset * getSubset(int _i) const
get a specific subset
void WriteIndexBuffer(unsigned int DstIndexSize, void *pDst)
Applies the remapping on the initial pIndices constructor's param and stores the result in the given ...
int numIsolatedVerts_
isolated vertices
void setIndexBufferInterleaved(int _numTris, int _indexSize, const void *_indices)
Set index buffer for a triangle mesh.
void setFaceVerts(int _i, int _v0, int _v1, int _v2)
Set vertex ids per triangle.
void dbgdump(const char *_filename) const
dump mesh info to text file
void dbgdumpAdjList(const char *_filename) const
dump adjacency list to text file
static unsigned int getElementSize(const VertexElement *_pElement)
void setAttribVec(int _attrIdx, int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
bool convex() const
Is the polygon convex?
int attrSize
size in bytes of one attribute
int mapToDrawVertexID(const int _faceID, const int _cornerID) const
int mapToDrawTriID(const int _faceID, const int _k=0, int *_numTrisOut=0) const
const VertexElement * getElement(unsigned int i) const
void prepareData()
build() preparation
int findGroupSubset(int _groupID)
get subset ID of a group
void getElementData(int _idx, void *_dst, const VertexElement *_desc) const
read a vertex element
int getFaceSize(const int _i) const
Get size of input face.
void getInputFaceVertexData(const int _face, const int _corner, void *_out) const
int getFaceGroup(int _faceID) const
Get Face Group of the given face.
size_t getMemoryUsage(bool _printConsole=true) const
void getIndexAdjBuffer_BruteForce(void *_dst, const int _borderIndex=-1)
Slow brute-force version of getIndexAdjBuffer.
std::vector< int > faceToTriMap_
input face index -> output tri index
void setFaceGroup(int _i, short _groupID)
Specify face groups.
void setTexCoords(int _num, const void *_data, int _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)