45 #include "MeshCompiler.hh" 53 #ifdef ACG_MC_USE_STL_HASH 54 #include <unordered_map> 57 #endif // ACG_MC_USE_STL_HASH 59 #include <ACG/Geometry/GPUCacheOptimizer.hh> 60 #include <ACG/Geometry/Triangulator.hh> 106 MeshCompilerVertexCompare MeshCompiler::defaultVertexCompare;
108 void MeshCompiler::AdjacencyList::init(
int n )
116 count =
new unsigned char[n];
121 memset(start, -1, n *
sizeof(
int));
124 memset(count, 0, n *
sizeof(
unsigned char));
127 int MeshCompiler::AdjacencyList::getAdj(
const int i,
const int k )
const 129 assert(k < count[i]);
138 int MeshCompiler::AdjacencyList::getCount(
const int i )
const 143 void MeshCompiler::AdjacencyList::clear()
146 delete [] start; start = 0;
147 delete [] buf; buf = 0;
148 delete [] count; count = 0;
154 void MeshCompiler::computeAdjacency(
bool _forceRecompute)
156 const int numVerts = input_[inputIDPos_].count;
165 if (_forceRecompute || (faceInput_->getVertexAdjCount(0) < 0 && adjacencyVert_.bufSize <= 0))
167 adjacencyVert_.init(numVerts);
170 for (
int i = 0; i < numFaces_; ++i)
174 for (
int k = 0; k < nCorners; ++k)
177 int vertex = getInputIndex(i, k, inputIDPos_);
179 adjacencyVert_.count[vertex]++;
187 for (
int i = 0; i < numVerts; ++i)
189 adjacencyVert_.start[i] = nCounter;
191 nCounter += adjacencyVert_.count[i];
193 adjacencyVert_.count[i] = 0;
197 adjacencyVert_.buf =
new int[nCounter];
198 adjacencyVert_.bufSize = nCounter;
201 for (
int i = 0; i < numFaces_; ++i)
205 for (
int k = 0; k < nCorners; ++k)
208 int vertex = getInputIndex(i, k, inputIDPos_);
209 int adjIdx = adjacencyVert_.start[vertex] + adjacencyVert_.count[vertex]++;
211 adjacencyVert_.buf[ adjIdx ] = i;
255 setAttribVec(inputIDPos_, _num, _data, _stride, _internalCopy, _fmt, _elementSize);
258 void MeshCompiler::setNormals(
size_t _num,
const void* _data,
size_t _stride,
bool _internalCopy , GLuint _fmt,
int _elementSize )
260 setAttribVec(inputIDNorm_, _num, _data, _stride, _internalCopy, _fmt, _elementSize);
265 setAttribVec(inputIDTexC_, _num, _data, _stride, _internalCopy, _fmt, _elementSize);
269 void MeshCompiler::setAttribVec(
int _attrIdx,
size_t _num,
const void* _data,
size_t _stride,
bool _internalCopy , GLuint _fmt,
int _elementSize)
282 assert(_attrIdx < (
int)decl_.getNumElements());
295 delete [] inbuf->internalBuf;
296 inbuf->internalBuf =
new char[size * _num];
297 inbuf->data = inbuf->internalBuf;
299 inbuf->stride = size;
304 for (
size_t i = 0; i < _num; ++i)
306 memcpy(inbuf->internalBuf + (
size_t)(size * i),
307 (
const char*)_data + (
size_t)(_stride * i),
315 inbuf->data = (
const char*)_data;
316 inbuf->stride = _stride ? _stride : size;
318 delete [] inbuf->internalBuf;
319 inbuf->internalBuf = 0;
324 inbuf->elementSize = _elementSize;
327 void MeshCompiler::WeldList::add(
const int _face,
const int _corner)
329 const int stride = meshComp->getVertexDeclaration()->getVertexStride();
332 char* vtx0 = workBuf + stride * list.size();
333 char* vtx1 = workBuf;
336 meshComp->getInputFaceVertexData(_face, _corner, vtx0);
338 bool matched =
false;
341 for (
size_t i = 0; i < list.size() && !matched; ++i)
347 if (cmpFunc->equalVertex(vtx0, vtx1, meshComp->getVertexDeclaration()))
353 e.faceId = _face; e.cornerId = _corner;
354 e.refFaceId = it->refFaceId; e.refCornerId = it->refCornerId;
368 e.faceId = _face; e.cornerId = _corner;
369 e.refFaceId = _face; e.refCornerId = _corner;
376 void MeshCompiler::weldVertices()
378 const int numVerts = input_[inputIDPos_].count;
381 vertexWeldMapFace_.resize(numIndices_, -1);
382 vertexWeldMapCorner_.resize(numIndices_, -1);
386 for (
int i = 0; i < numVerts; ++i)
388 const int n = getAdjVertexFaceCount(i);
389 maxAdjCount = std::max(n, maxAdjCount);
394 char* vtxCompBuf =
new char[decl_.getVertexStride() * (maxAdjCount + 1)];
397 weldList.meshComp =
this;
398 weldList.cmpFunc = vertexCompare_;
399 weldList.workBuf = vtxCompBuf;
401 weldList.list.reserve(maxAdjCount);
405 for (
int i = 0; i < numVerts; ++i)
409 weldList.list.clear();
412 int numAdjFaces = getAdjVertexFaceCount(i);
413 for (
int k = 0; k < numAdjFaces; ++k)
415 const int adjFace = getAdjVertexFace(i, k);
419 int adjCornerId = -1;
420 for (
int m = 0; m < adjFaceSize; ++m)
422 const int adjVertex = getInputIndex(adjFace, m, inputIDPos_);
441 const int weldMapOffset = getInputFaceOffset(adjFace) + adjCornerId;
443 if (vertexWeldMapFace_[weldMapOffset] >= 0)
446 weldList.add(adjFace, adjCornerId);
454 for (
size_t e = 0; e < weldList.list.size(); ++e)
457 const int weldMapOffset = getInputFaceOffset(it->faceId) + it->cornerId;
459 if (vertexWeldMapFace_[weldMapOffset] >= 0)
463 vertexWeldMapFace_[weldMapOffset] = it->refFaceId;
464 vertexWeldMapCorner_[weldMapOffset] = it->refCornerId;
528 if (adjacencyVert_.bufSize <= 0)
533 computeAdjacency(
true);
537 vertexWeldMapFace_.clear();
538 vertexWeldMapCorner_.clear();
546 std::cerr <<
"MeshCompiler - faulty internal adjacency list" << std::endl;
555 delete [] vtxCompBuf;
558 void MeshCompiler::fixWeldMap()
560 for (
int i = 0; i < numFaces_; ++i)
563 for (
int k = 0; k < fsize; ++k)
565 const int weldMapOffset = getInputFaceOffset(i) + k;
569 if (vertexWeldMapFace_[weldMapOffset] < 0)
571 vertexWeldMapFace_[weldMapOffset] = i;
572 vertexWeldMapCorner_[weldMapOffset] = k;
578 void MeshCompiler::findIsolatedVertices()
580 const int nVerts = input_[inputIDPos_].count;
586 for (
int i = 0; i < nVerts; ++i)
588 if (splitter_->isIsolated(i))
592 isolatedVertices_.clear();
594 for (
int i = 0; i < nVerts; ++i)
596 if (splitter_->isIsolated(i))
597 isolatedVertices_.push_back(i);
601 void MeshCompiler::splitVertices()
633 const int numPositions = input_[inputIDPos_].count;
636 int estimatedSplitCount = 0;
637 int numDifferentInputCounts = 0;
642 for (
int i = 0; i < numAttributes_; ++i)
644 if (i != inputIDPos_)
646 if (input_[i].count > numPositions)
648 const int diff = input_[i].count - numPositions;
652 estimatedSplitCount = std::max(diff, estimatedSplitCount);
653 ++numDifferentInputCounts;
659 if (numDifferentInputCounts > 1)
662 estimatedSplitCount = int(
float(estimatedSplitCount) * 1.2f);
665 assert(estimatedSplitCount >= 0);
670 int maxSplitCount = 0;
674 if (numIndices_ > numPositions)
675 maxSplitCount = numIndices_ - numPositions;
682 if (constantFaceSize_)
683 sumFaceSize = numFaces_ * maxFaceSize_;
686 for (
int i = 0; i < numFaces_; ++i)
690 if (sumFaceSize > numPositions)
691 maxSplitCount = sumFaceSize - numPositions;
694 estimatedSplitCount = std::min(estimatedSplitCount, maxSplitCount);
702 numPositions + estimatedSplitCount,
705 faceBufSplit_.resize(numIndices_, -1);
710 for (
int i = 0; i < numFaces_; ++i)
713 for (
int k = 0; k < fsize; ++k)
724 const int idx = splitter_->split(vertex);
727 setInputIndexSplit(i, k, idx);
739 findIsolatedVertices();
745 std::vector<int> IsoFix(splitter_->numVerts, 0);
748 for (
int i = 0; i < splitter_->numVerts; ++i)
750 if (splitter_->isIsolated(i))
753 IsoFix[i] = fixIndex;
763 for (
int i = 0; i < numFaces_; ++i)
766 for (
int k = 0; k < fsize; ++k)
769 int idx = getInputIndexSplit(i, k);
776 setInputIndexSplit(i, k, idx);
783 bool MeshCompiler_forceUnsharedFaceVertex_InnerValenceSorter(
const std::pair<int, int>& a,
const std::pair<int, int>& b )
785 return a.second > b.second;
788 void MeshCompiler::forceUnsharedFaceVertex()
798 std::vector<int> sharedVertices;
799 sharedVertices.resize(maxFaceSize_);
802 std::vector<int> tmpFaceVerts;
803 tmpFaceVerts.resize(maxFaceSize_);
833 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
836 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
843 std::vector< std::pair<int, int> > vertexPriorities(faceSize);
847 const int faceTris = faceSize - 2;
849 std::vector<RingTriangle> remainingTris(faceTris);
850 for (
int i = 0; i < faceTris; ++i)
851 remainingTris[i] =
RingTriangle(i, &remainingTris[(i + faceTris - 1) % faceTris], &remainingTris[(i + 1) % faceTris]);
855 int numTrisCovered = 0;
857 while (numTrisCovered < faceTris)
860 for (
int k = 0; k < faceSize; ++k)
861 vertexPriorities[k] = std::pair<int, int>(k, 0);
864 int numRemainingTris = faceTris - numTrisCovered;
865 for (
int t = 0; t < numRemainingTris; ++t)
867 for (
int k = 0; k < 3; ++k)
869 int cornerID = -1 - triIndexBuffer_[(triCounter + currentTri->id) * 3 + k];
870 ++vertexPriorities[cornerID].second;
872 currentTri = currentTri->next;
874 assert(currentTri == startTri);
877 std::sort(vertexPriorities.begin(), vertexPriorities.end(), MeshCompiler_forceUnsharedFaceVertex_InnerValenceSorter);
881 int goodVertexID = -1;
882 int bestValence = -1;
883 for (
int k = 0; k < faceSize && vertexPriorities[k].second; ++k)
885 int cornerID = vertexPriorities[k].first;
886 int vertexID = getInputIndexSplit(faceID, cornerID);
888 int valence = vertexPriorities[k].second;
890 if (vertexID >= numInitialVerts || (VertexUsed[vertexID] == faceID))
894 goodCorner = cornerID;
895 goodVertexID = vertexID;
896 bestValence = valence;
899 else if (VertexUsed[vertexID] < 0 && bestValence < valence)
901 goodCorner = cornerID;
902 goodVertexID = vertexID;
903 bestValence = valence;
914 goodCorner = vertexPriorities[0].first;
918 setInputIndexSplit(faceID, goodCorner, goodVertexID);
923 VertexUsed[goodVertexID] = faceID;
927 for (
int t = 0; t < numRemainingTris; ++t)
930 for (
int k = 0; k < 3; ++k)
932 int cornerID = -1 - triIndexBuffer_[(triCounter + currentTri->id) * 3 + k];
934 if (cornerID == goodCorner)
937 int rotCount = 3 - k;
942 triIndexBuffer_[(triCounter + currentTri->id) * 3],
943 triIndexBuffer_[(triCounter + currentTri->id) * 3 + 1],
944 triIndexBuffer_[(triCounter + currentTri->id) * 3 + 2],
948 for (
int i = 0; i < 3; ++i)
949 triIndexBuffer_[(triCounter + currentTri->id) * 3 + (i + rotCount) % 3] = tmpTriVerts[i];
955 currentTri->prev->next = currentTri->next;
956 currentTri->next->prev = currentTri->prev;
961 currentTri = currentTri->next;
967 triCounter += faceSize - 2;
971 numInitialVerts = VertexUsed.size();
974 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
976 int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
982 memset(&sharedVertices[0], 0,
sizeof(
int) * maxFaceSize_);
986 for (
int v0 = 0; v0 < numCorners && numShared < numCorners; ++v0)
988 if (sharedVertices[v0])
991 const int vertexID0 = getInputIndexSplit(faceID, v0);
995 if (vertexID0 < numInitialVerts && (VertexUsed[vertexID0] >= 0 && VertexUsed[vertexID0] != faceID))
997 sharedVertices[v0] =
true;
1004 if (numShared == numCorners)
1013 else if (sharedVertices[0])
1017 for (
int i = 0; i < numCorners; ++i)
1018 x += sharedVertices[i];
1019 assert(x < numCorners);
1025 for (
int i = 0; i < numCorners; ++i)
1026 tmpFaceVerts[i] = getInputIndexSplit(faceID, i);
1031 for (; rotCount < numCorners; ++rotCount)
1033 if (!sharedVertices[rotCount % numCorners])
1035 if (tmpFaceVerts[rotCount] < numInitialVerts)
1036 VertexUsed[tmpFaceVerts[rotCount]] = faceID;
1041 assert(rotCount < numCorners);
1044 rotCount = numCorners - rotCount;
1046 for (
int i = 0; i < numCorners; ++i)
1050 triIndexBuffer_[triCounter * 3 + i] = tmpFaceVerts[(i + numCorners - rotCount) % numCorners];
1056 const int idx = getInputIndexSplit(faceID, 0);
1057 if (idx < numInitialVerts)
1058 VertexUsed[idx] = faceID;
1062 triCounter += numCorners - 2;
1070 for (
unsigned int k = 0; k < decl_.getNumElements(); ++k)
1071 _out[k] = getInputIndex(_face, _corner, k);
1080 if (!vertexWeldMapFace_.empty())
1082 const int offset = getInputFaceOffset(i);
1084 face = vertexWeldMapFace_[offset + j];
1085 corner = vertexWeldMapCorner_[offset + j];
1088 for (
unsigned int k = 0; k < decl_.getNumElements(); ++k)
1089 _out[k] = getInputIndex(face, corner, k);
1094 for (
int i = 0; i < numAttributes_; ++i)
1098 const int idx = getInputIndex(_faceId, _corner, i);
1100 input_[i].getElementData(idx, (
char*)_out + (
size_t)el->
pointer_, el);
1111 deleteFaceInputeData_ =
false;
1119 curFaceInputPos_ = 0;
1125 constantFaceSize_ =
false;
1127 provokingVertex_ = -1;
1128 provokingVertexSetByUser_ =
false;
1131 numAttributes_ = decl_.getNumElements();
1132 inputIDNorm_ = inputIDPos_ = inputIDTexC_ = -1;
1134 for (
int i = 0; i < (int)decl_.getNumElements(); ++i)
1148 vertexCompare_ = &defaultVertexCompare;
1152 MeshCompiler::~MeshCompiler()
1154 if (deleteFaceInputeData_)
1161 int MeshCompiler::getInputIndexOffset(
const int _face,
const int _corner )
const 1164 assert(_face < numFaces_);
1167 const int baseIdx = int(faceStart_.empty() ? maxFaceSize_ * _face : faceStart_[_face]);
1168 return baseIdx + _corner;
1172 void MeshCompiler::setInputIndexSplit(
const int _face,
const int _corner,
const int _val )
1174 const int offset = getInputIndexOffset(_face, _corner);
1180 faceBufSplit_[offset] = _val;
1183 int MeshCompiler::getInputIndexSplit(
const int _face,
const int _corner )
const 1185 const int offset = getInputIndexOffset(_face, _corner);
1187 return faceBufSplit_[offset];
1193 MeshCompilerDefaultFaceInput::MeshCompilerDefaultFaceInput(
int _numFaces,
int _numIndices)
1194 : numFaces_(_numFaces), numIndices_(_numIndices)
1196 faceOffset_.resize(numFaces_, -1);
1197 faceSize_.resize(numFaces_, 0);
1198 faceData_[0].reserve(_numIndices);
1209 numFaces_ = _numFaces;
1211 faceInput_ = internalInput;
1212 deleteFaceInputeData_ =
true;
1219 if (!_v || _attrID < 0)
return;
1227 input->setFaceData(_i, _numEdges, _v, _attrID);
1233 int tmp[3] = {_v0, _v1, _v2};
1239 MeshCompiler::VertexSplitter::VertexSplitter(
int _numAttribs,
1242 float _estBufferIncrease)
1243 : numAttribs(_numAttribs), numVerts(_numVerts), numBaseVerts(_numVerts)
1245 if (_numWorstCase <= 0)
1246 _numWorstCase = int(
float(_numVerts) * (_estBufferIncrease + 1.0f));
1248 const int maxCount = (_numAttribs + 1) * (_numWorstCase + 1);
1251 splits.resize(maxCount, -1);
1259 MeshCompiler::VertexSplitter::~VertexSplitter()
1266 int pos = vertex[0];
1267 int next = getNext(pos);
1274 setAttribs(pos, vertex);
1283 int bSearchSplit = 1;
1286 while (pos >= 0 && bSearchSplit)
1289 if (!memcmp(vertex, getAttribs(pos), numAttribs *
sizeof(
int)))
1296 next = getNext(pos);
1298 if (next < 0)
break;
1299 if (next == pos)
break;
1307 int newID = numVerts++;
1309 setNext(pos, newID);
1310 setAttribs(newID, vertex);
1322 int MeshCompiler::VertexSplitter::getNext(
const int id)
1326 const int entryIdx =
id * (1 + numAttribs);
1329 if (entryIdx >= (
int)splits.size())
1331 splits.resize(entryIdx + numAttribs * 100, -1);
1335 return splits[entryIdx];
1338 void MeshCompiler::VertexSplitter::setNext(
const int id,
const int next)
1342 const int entryIdx =
id * (1 + numAttribs);
1345 if (entryIdx >= (
int)splits.size())
1347 splits.resize(entryIdx + numAttribs * 100, -1);
1351 splits[entryIdx] = next;
1354 int* MeshCompiler::VertexSplitter::getAttribs(
const int id)
1358 const int entryIdx =
id * (1 + numAttribs) + 1;
1361 if (entryIdx + numAttribs >= (
int)splits.size())
1363 splits.resize(entryIdx + numAttribs * 100, -1);
1367 return &splits[0] + entryIdx;
1370 void MeshCompiler::VertexSplitter::setAttribs(
const int id,
int* attr )
1372 memcpy(getAttribs(
id), attr, numAttribs *
sizeof(
int));
1377 return (vertexPosID < numBaseVerts) && (getNext(vertexPosID) < 0);
1382 MeshCompiler::VertexElementInput::VertexElementInput()
1383 : internalBuf(0), data(0),
1384 count(0), stride(0), attrSize(0),
1385 fmt(0), elementSize(-1)
1389 MeshCompiler::VertexElementInput::~VertexElementInput()
1391 delete [] internalBuf;
1401 void MeshCompiler::triangulate()
1407 for (
int i = 0; i < numFaces_; ++i)
1412 triIndexBuffer_.resize(numTris * 3);
1424 int indexCounter = 0;
1426 for (
int sortFaceID = 0; sortFaceID < numFaces_; ++sortFaceID)
1429 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1438 for (
int k = 0; k < 3; ++k)
1439 triIndexBuffer_[indexCounter++] = -1 - k;
1444 std::vector<Vec3f> poly(faceSize);
1445 for (
int k = 0; k < faceSize; ++k)
1448 posElement.
type_ = GL_FLOAT;
1454 posElement.
vbo_ = 0;
1455 int posID = getInputIndexSplit(faceID, k);
1456 input_[inputIDPos_].getElementData(posID, &poly[k], &posElement);
1465 for (
int k = 0; k < 3; ++k)
1466 triIndexBuffer_[indexCounter++] = -1 - k;
1468 for (
int k = 3; k < faceSize; ++k)
1473 triIndexBuffer_[indexCounter++] = -1;
1474 triIndexBuffer_[indexCounter++] = -1 - (k - 1);
1475 triIndexBuffer_[indexCounter++] = -1 - k;
1486 for (
int k = 0; k < 3; ++k)
1488 int cornerID = tris.
index(i * 3 + k);
1490 triIndexBuffer_[indexCounter++] = -1 - cornerID;
1500 for (
int i = 0; i < numSubsets_; ++i)
1502 subsets_[i].startIndex = 0xffffffff;
1503 subsets_[i].numTris = 0;
1508 for (
int i = 0; i < numTris; ++i)
1510 const int faceID = mapTriToInputFace(i);
1520 for (
int i = 0; i < numSubsets_; ++i)
1523 subsets_[i].startIndex = subsets_[i-1].startIndex + subsets_[i-1].numTris * 3;
1525 subsets_[i].startIndex = 0;
1531 void MeshCompiler::resolveTriangulation()
1535 if (provokingVertex_ >= 0)
1537 for (
int i = 0; i < numTris_; ++i)
1539 for (
int k = 0; k < 3 - provokingVertex_; ++k)
1541 const int tmp = triIndexBuffer_[i*3];
1542 triIndexBuffer_[i*3] = triIndexBuffer_[i*3 + 1];
1543 triIndexBuffer_[i*3 + 1] = triIndexBuffer_[i*3 + 2];
1544 triIndexBuffer_[i*3 + 2] = tmp;
1550 for (
int drawTriID = 0; drawTriID < numTris_; ++drawTriID)
1552 if (triIndexBuffer_[drawTriID * 3] < 0)
1559 const int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1561 for (
int k = 0; k < 3; ++k)
1563 int negCornerID = triIndexBuffer_[drawTriID * 3 + k];
1564 int cornerID = -1 - negCornerID;
1565 triIndexBuffer_[drawTriID * 3 + k] = getInputIndexSplit(faceID, cornerID);
1571 void MeshCompiler::sortFacesByGroup()
1578 std::map<int, unsigned int> GroupIDs;
1581 for (
int face = 0; face < numFaces_; ++face)
1585 if (GroupIDs.find(texID) == GroupIDs.end())
1586 GroupIDs[texID] = face;
1590 numSubsets_ = int(GroupIDs.size());
1591 subsets_.resize(numSubsets_);
1593 if (numSubsets_ > 1)
1594 faceSortMap_.resize(numFaces_, -1);
1598 std::map<int, unsigned int>::const_iterator it = GroupIDs.begin();
1599 unsigned int numSortedFaces = 0;
1601 for (
unsigned int i = 0; it != GroupIDs.end(); ++i, ++it)
1604 subsets_[i].id = it->first;
1607 subsetIDMap_[it->first] = i;
1610 subsets_[i].numFaces = 0;
1611 subsets_[i].startFace = numSortedFaces;
1614 subsets_[i].startIndex = 0;
1615 subsets_[i].numTris = 0;
1617 if (numSubsets_ == 1)
1619 subsets_[i].numFaces = numFaces_;
1625 for (
int k = it->second; k < numFaces_; ++k)
1629 if (texID == subsets_[i].
id)
1631 subsets_[i].numFaces++;
1633 faceSortMap_[numSortedFaces++] = k;
1642 void MeshCompiler::optimize()
1647 for (
int i = 0; i < numSubsets_; ++i)
1649 Subset* pSubset = &subsets_[i];
1651 const int vcacheSize = 24;
1657 const unsigned int StartTri = pSubset->startIndex/3;
1658 for (
unsigned int k = 0; k < pSubset->numTris; ++k)
1661 triOptMap_[k + StartTri] = SrcTri + StartTri;
1668 unsigned int* vertexOptMap =
new unsigned int[
numDrawVerts_];
1674 for (
int i = 0; i < numTris_ * 3; ++i)
1680 for (
int i = 0; i < numFaces_; ++i)
1684 for (
int k = 0; k < fsize; ++k)
1686 int oldVertex = getInputIndexSplit(i, k);
1688 int newVertex = vertexOptMap[oldVertex];
1690 setInputIndexSplit(i, k, newVertex);
1694 delete [] vertexOptMap;
1699 void MeshCompiler::build(
bool _weldVertices,
bool _optimizeVCache,
bool _needPerFaceAttribute,
bool _keepIsolatedVertices)
1702 const bool dbg_MemProfiling =
false;
1727 if (dbg_MemProfiling)
1728 std::cout <<
"computing adjacency.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1732 if (dbg_MemProfiling)
1733 std::cout <<
"vertex welding.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1738 adjacencyVert_.clear();
1741 if (dbg_MemProfiling)
1742 std::cout <<
"vertex splitting.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1746 if (dbg_MemProfiling)
1747 std::cout <<
"splitting done.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1751 delete splitter_; splitter_ = 0;
1754 std::vector< int > emptyVec;
1755 vertexWeldMapFace_.swap(emptyVec);
1757 std::vector< int > emptyVec;
1758 vertexWeldMapCorner_.swap(emptyVec);
1772 if (dbg_MemProfiling)
1773 std::cout <<
"sorting by mat.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1803 if (dbg_MemProfiling)
1804 std::cout <<
"triangulate.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1809 if (_needPerFaceAttribute)
1811 if (dbg_MemProfiling)
1812 std::cout <<
"force unshared vertex.., memusage = " << (
getMemoryUsage() / (1024 * 1024)) << std::endl;
1818 if (provokingVertex_ < 0)
1819 provokingVertex_ = 2;
1821 provokingVertex_ = provokingVertex_ % 3;
1824 forceUnsharedFaceVertex();
1827 resolveTriangulation();
1844 if (_optimizeVCache)
1846 if (dbg_MemProfiling)
1847 std::cout <<
"optimizing.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1851 else if (!triIndexBuffer_.empty())
1854 if (dbg_MemProfiling)
1855 std::cout <<
"creating maps.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1859 std::vector< int > emptyVec;
1860 triIndexBuffer_.swap(emptyVec);
1863 createVertexMap(_keepIsolatedVertices);
1868 std::vector< int > emptyVec;
1871 std::vector< int > emptyVec;
1874 std::vector< int > emptyVec;
1875 faceSortMap_.swap(emptyVec);
1878 if (dbg_MemProfiling)
1879 std::cout <<
"finished.., memusage = " << (
getMemoryUsage() /(1024 * 1024)) << std::endl;
1900 std::cerr <<
"setAttrib failed: please allocate internal input buffer before using setAttrib" << std::endl;
1904 assert(inbuf->
count > _v);
1911 assert (_attrIdx >= 0);
1912 assert(_attrIdx <
int(decl_.getNumElements()));
1914 return input_[_attrIdx].count;
1918 int MeshCompiler::mapTriToInputFace(
const int _tri )
const 1921 assert(_tri < numTris_);
1924 assert(sortFaceID >= 0);
1925 assert(sortFaceID < numFaces_);
1927 int faceID = faceSortMap_.empty() ? sortFaceID : faceSortMap_[sortFaceID];
1928 assert(faceID >= 0);
1929 assert(faceID < numFaces_);
1936 if (faceGroupIDs_.empty())
1939 return (
int)faceGroupIDs_[_faceID];
1944 return subsetIDMap_[_groupID];
1949 return &subsets_[_i];
1954 std::stringstream str;
1956 for (
int i = 0; i < (int)decl_.getNumElements(); ++i)
1962 const void* data =
static_cast<const char*
>(v) + (
size_t)el->
pointer_;
1964 switch ( el->
type_ )
1968 const double* d0 =
static_cast<const double*
>(data);
1971 str << d0[k] <<
", ";
1977 const float* f0 =
static_cast<const float*
>(data);
1980 str << f0[k] <<
", ";
1984 case GL_UNSIGNED_INT:
1986 const int* i0 =
static_cast<const int*
>(data);
1989 str << i0[k] <<
", ";
1993 case GL_UNSIGNED_SHORT:
1995 const short* i0 =
static_cast<const short*
>(data);
1998 str << i0[k] <<
", ";
2002 case GL_UNSIGNED_BYTE:
2004 const char* i0 =
static_cast<const char*
>(data);
2007 str << ((int)i0[k]) <<
", ";
2010 default: std::cerr <<
"MeshCompiler: vertexToString() unknown type: " << el->
type_ << std::endl;
2023 int numTotalErrors = 0;
2028 file.open(_filename);
2030 if (file || !_filename)
2039 file <<
"checking draw_tri <-> face mapping ..\n";
2043 int numTrisOfFace = 0;
2046 for (
int k = 0; k < numTrisOfFace; ++k)
2053 if (face != dbg_face)
2056 file <<
"error: face " << face <<
" -> (numTris: " << numTrisOfFace <<
", tri " << tri <<
" -> face " << dbg_face <<
")\n";
2063 file << numErrors <<
" errors found\n\n";
2064 numTotalErrors += numErrors;
2070 file <<
"checking (face, corner) -> vbo by comparing vertex data ..\n";
2073 char* vtxCmpData =
new char[decl_.getVertexStride() * 2];
2079 for (
int k = 0; k < fsize; ++k)
2081 char* v0 = vtxCmpData;
2082 char* v1 = vtxCmpData + decl_.getVertexStride();
2084 memset(v0, 0, decl_.getVertexStride());
2085 memset(v1, 0, decl_.getVertexStride());
2097 if (!verifyCmp.equalVertex(v0, v1, &decl_))
2103 file <<
"error: (face " << face <<
", corner " << k <<
") -> vertex " << vertex <<
": " << vertexData0.c_str() <<
" != "<< vertexData1.c_str() <<
"\n";
2111 file << numErrors <<
" errors found\n\n";
2112 numTotalErrors += numErrors;
2120 file <<
"checking vbo -> (face, corner) by comparing vertex data ..\n";
2125 int face = 0, corner = 0;
2128 char* v0 = vtxCmpData;
2129 char* v1 = vtxCmpData + decl_.getVertexStride();
2131 memset(v0, 0, decl_.getVertexStride());
2132 memset(v1, 0, decl_.getVertexStride());
2145 for (
unsigned int i = 0; i < decl_.getNumElements(); ++i)
2148 input_[i].getElementData(posID, (
char*)v1 + (
size_t)el->
pointer_, el);
2152 if (!vertexCompare_->equalVertex(v0, v1, &decl_))
2158 file <<
"error: vertex " << vertex <<
" -> (face " << face <<
", corner " << corner <<
"): " << vertexData0.c_str() <<
" != " << vertexData1.c_str() <<
"\n";
2164 file << numErrors <<
" errors found\n\n";
2165 numTotalErrors += numErrors;
2169 delete [] vtxCmpData;
2175 if (provokingVertex_ >= 0)
2178 file <<
"checking unshared per face vertices ..\n";
2181 std::vector< std::map<int, int> > VertexRefs;
2184 for (
int face = 0; face < numFaces_; ++face)
2189 for (
int k = 0; k < nTris; ++k)
2193 int faceVertex =
getIndex(tri * 3 + provokingVertex_);
2195 VertexRefs[faceVertex][face] = 1;
2204 if (VertexRefs[i].size() > 1)
2208 file <<
"error : vertex " << i <<
" is referenced by " << VertexRefs[i].size() <<
" faces: ";
2210 for (std::map<int, int>::iterator it = VertexRefs[i].begin(); it != VertexRefs[i].end(); ++it)
2211 file << it->first <<
", ";
2220 file << numErrors <<
" errors found\n\n";
2221 numTotalErrors += numErrors;
2230 file <<
"checking face group sorting ..\n";
2236 for (
int k = 0; k < (int)sub->numTris; ++k)
2243 if (grID != sub->id)
2246 file <<
"error: face " << faceID <<
" with group-id " << grID <<
" was mapped to subset-group " << sub->id <<
"\n";
2255 file << numErrors <<
" errors found\n\n";
2256 numTotalErrors += numErrors;
2265 file <<
"checking triangulation ..\n";
2267 for (
int i = 0; i < numFaces_; ++i)
2271 std::vector<int> facePositions(faceSize, -1);
2273 for (
int k = 0; k < faceSize; ++k)
2274 facePositions[k] = getInputIndex(i, k, inputIDPos_);
2276 int numFaceTris = 0;
2279 for (
int t = 0; t < numFaceTris; ++t)
2283 int triPosOccurrence[3] = {-1, -1, -1};
2285 for (
int k = 0; k < 3; ++k)
2287 int vertexID =
getIndex(triID * 3 + k);
2289 int originalFace = -1, originalCorner = -1;
2293 for (
int m = 0; m < faceSize; ++m)
2295 if (posID == facePositions[m])
2297 triPosOccurrence[k] = m;
2302 if (triPosOccurrence[k] < 0)
2305 file <<
"error: vertex at triangulated face " << i <<
" at triangle " << t <<
" at corner " << k <<
"is not even part of the original face!\n";
2312 int numInversions = 0;
2314 for (
int k = 0; k < 3; ++k)
2316 int p1 = triPosOccurrence[k];
2317 int p2 = triPosOccurrence[(k + 1) % 3];
2323 if (numInversions > 1)
2326 file <<
"error: triangulation of face " << i <<
" at triangle " << t <<
" has flipped winding order!\n";
2334 file << numErrors <<
" errors found\n\n";
2335 numTotalErrors += numErrors;
2341 return numTotalErrors == 0;
2349 file.open(_filename);
2353 for (
int i = 0; i < numAttributes_; ++i)
2357 file <<
"attribute[" << i <<
"]: internalbuf " << ((
const void*)inp->
internalBuf) <<
", data " << ((
const void*)inp->
data) <<
", count " << inp->
count <<
", stride " << inp->
stride <<
", attrSize " << inp->
attrSize <<
"\n";
2361 file <<
"faces " << numFaces_ <<
"\nindices " << numIndices_ <<
"\n";
2363 if (!vertexWeldMapFace_.empty())
2365 for (
int i = 0; i < numFaces_; ++i)
2369 int face = vertexWeldMapFace_[getInputFaceOffset(i) + k];
2370 int corner = vertexWeldMapCorner_[getInputFaceOffset(i) + k];
2371 file <<
"vertexWeldMap_[" << i <<
", "<<k<<
"] = ["<<face<<
", "<<corner<<
"]\n";
2376 for (
size_t i = 0; i < faceBufSplit_.size(); ++i)
2377 file <<
"faceBufSplit_["<<i<<
"] = "<<faceBufSplit_[i]<<
"\n";
2381 for (
size_t i = 0; i < faceGroupIDs_.size(); ++i)
2382 file <<
"faceGroupIDs_["<<i<<
"] = "<<faceGroupIDs_[i]<<
"\n";
2386 for (
size_t i = 0; i < faceSortMap_.size(); ++i)
2387 file <<
"faceSortMap_["<<i<<
"] = "<<faceSortMap_[i]<<
"\n";
2391 for (
size_t i = 0; i < triIndexBuffer_.size()/3; ++i)
2392 file <<
"tri["<<i<<
"] = "<<triIndexBuffer_[i*3+1]<<
" "<<triIndexBuffer_[i*3+1]<<
" "<<triIndexBuffer_[i*3+2]<<
"\n";
2396 for (
size_t i = 0; i < subsets_.size(); ++i)
2398 const Subset* sub = &subsets_[i];
2399 file <<
"subset["<<i<<
"]: id "<<sub->id<<
", startIndex "<<sub->startIndex<<
", numTris "<<sub->numTris<<
", numFaces "<<sub->numFaces<<
", startFace "<<sub->startFace<<
"\n";
2404 for (std::map<int, int>::const_iterator it = subsetIDMap_.begin();
2405 it != subsetIDMap_.end(); ++it)
2406 file <<
"subsetIDMap["<<it->first<<
"] = "<<it->second<<
"\n";
2410 for (
int i = 0; i < numFaces_; ++i)
2422 file <<
"mapToOriginalVertexID["<<i<<
"] = ["<<f<<
", "<<c<<
"]\n";
2425 file <<
"\n\nadjacencyVert\n";
2426 adjacencyVert_.dbgdump(file);
2433 for (
int i = 0; i < numFaces_; ++i)
2441 file <<
"data["<<i<<
", "<<k<<
"] = ("<<vtx[0]<<
" "<<vtx[1]<<
" "<<vtx[2]<<
") ("<<vtx[3]<<
" "<<vtx[4]<<
") ("<<vtx[5]<<
" "<<vtx[6]<<
" "<<vtx[7]<<
")\n";
2450 void MeshCompiler::AdjacencyList::dbgdump(std::ofstream& file)
const 2454 for (
int i = 0; i < num; ++i)
2456 for (
int k = 0; k < getCount(i); ++k)
2457 file <<
"adj["<<i<<
"]["<<k<<
"] = "<<getAdj(i,k)<<
"\n";
2465 if (count == 0 || !data)
2467 memset(_dst, 0, attrSize);
2474 if (_idx < 0 || _idx >= count)
2476 memset(_dst, 0, attrSize);
2480 const void* dataAdr =
static_cast<const char*
>(data) + (
size_t)(_idx * stride);
2482 if (fmt == 0 || elementSize == -1 || fmt == _desc->
type_)
2483 memcpy(_dst, dataAdr, attrSize);
2487 int data_i[4] = {0,0,0,0};
2488 double data_d[4] = {0.0, 0.0, 0.0, 0.0};
2491 for (
int i = 0; i < elementSize; ++i)
2495 case GL_FLOAT: data_d[i] = (
static_cast<const float*
>(dataAdr))[i];
break;
2496 case GL_DOUBLE: data_d[i] = (
static_cast<const double*
>(dataAdr))[i];
break;
2498 case GL_UNSIGNED_INT:
2499 case GL_INT: data_i[i] = (
static_cast<const int*
>(dataAdr))[i];
break;
2501 case GL_UNSIGNED_SHORT:
2502 case GL_SHORT: data_i[i] = (
static_cast<const short*
>(dataAdr))[i];
break;
2504 case GL_UNSIGNED_BYTE:
2505 case GL_BYTE: data_i[i] = (
static_cast<const short*
>(dataAdr))[i];
break;
2507 default: std::cerr <<
"MeshCompiler: unknown data format - " << fmt << std::endl;
break;
2513 memset(_dst, 0, attrSize);
2516 if (fmt == GL_FLOAT || fmt == GL_DOUBLE)
2518 for (
int i = 0; i < (int)_desc->
numElements_ && i < (
int)elementSize; ++i)
2520 switch (_desc->
type_)
2522 case GL_FLOAT: ((
float*)_dst)[i] = (float)data_d[i];
break;
2523 case GL_DOUBLE: ((
double*)_dst)[i] = (double)data_d[i];
break;
2525 case GL_UNSIGNED_INT:
2526 case GL_INT: ((
int*)_dst)[i] = (int)data_d[i];
break;
2528 case GL_UNSIGNED_BYTE:
2529 case GL_BYTE: ((
char*)_dst)[i] = (char)data_d[i];
break;
2531 case GL_UNSIGNED_SHORT:
2532 case GL_SHORT: ((
short*)_dst)[i] = (short)data_d[i];
break;
2540 for (
int i = 0; i < (int)_desc->
numElements_ && i < (
int)elementSize; ++i)
2542 switch (_desc->
type_)
2544 case GL_FLOAT: ((
float*)_dst)[i] = (float)data_i[i];
break;
2545 case GL_DOUBLE: ((
double*)_dst)[i] = (double)data_i[i];
break;
2547 case GL_UNSIGNED_INT:
2548 case GL_INT: ((
int*)_dst)[i] = (int)data_i[i];
break;
2550 case GL_UNSIGNED_BYTE:
2551 case GL_BYTE: ((
char*)_dst)[i] = (char)data_i[i];
break;
2553 case GL_UNSIGNED_SHORT:
2554 case GL_SHORT: ((
short*)_dst)[i] = (short)data_i[i];
break;
2571 file.open(_filename);
2581 if (inputIDPos_ >= 0)
2583 float* pos = vertex + (size_t)decl_.getElement(inputIDPos_)->pointer_ / 4;
2584 file <<
"v "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2587 if (inputIDNorm_ >= 0)
2589 float* pos = vertex + (size_t)decl_.getElement(inputIDNorm_)->pointer_ / 4;
2590 file <<
"vn "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2593 if (inputIDTexC_ >= 0)
2595 float* pos = vertex + (size_t)decl_.getElement(inputIDTexC_)->pointer_ / 4;
2596 file <<
"vt "<<pos[0]<<
" "<<pos[1]<<
"\n";
2601 for (
int i = 0; i < numTris_; ++i)
2603 if (!inputIDTexC_ && !inputIDNorm_)
2606 else if (!inputIDTexC_)
2607 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";
2610 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";
2623 const int nVerts = (inputIDPos_ >= 0) ? input_[inputIDPos_].count : 0;
2629 file.open(_filename);
2635 for (
int i = 0; i < nVerts; ++i)
2639 input_[inputIDPos_].getElementData(i, pos, el);
2641 file <<
"v "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2644 if (inputIDTexC_ >= 0)
2650 for (
int i = 0; i < vei->
count; ++i)
2653 file <<
"vt "<<pos[0]<<
" "<<pos[1]<<
"\n";
2658 if (inputIDNorm_ >= 0)
2664 for (
int i = 0; i < vei->
count; ++i)
2667 file <<
"vn "<<pos[0]<<
" "<<pos[1]<<
" "<<pos[2]<<
"\n";
2674 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2676 std::string strLine =
"f ";
2678 int size = faceInput_->getFaceSize(i);
2681 for (
int k = 0; k < size; ++k)
2683 if (inputIDNorm_>=0 && inputIDTexC_>=0)
2684 sprintf(tmp,
"%d/%d/%d ", faceInput_->getSingleFaceAttr(i, k, inputIDPos_) + 1,
2685 faceInput_->getSingleFaceAttr(i, k, inputIDTexC_) + 1,
2686 faceInput_->getSingleFaceAttr(i, k, inputIDNorm_) + 1);
2687 else if (inputIDNorm_ >= 0)
2688 sprintf(tmp,
"%d//%d ", faceInput_->getSingleFaceAttr(i, k, inputIDPos_) + 1, faceInput_->getSingleFaceAttr(i, k, inputIDNorm_) + 1);
2689 else if (inputIDTexC_ >= 0)
2690 sprintf(tmp,
"%d/%d ", faceInput_->getSingleFaceAttr(i, k, inputIDPos_) + 1, faceInput_->getSingleFaceAttr(i, k, inputIDTexC_) + 1);
2692 sprintf(tmp,
"%d ", faceInput_->getSingleFaceAttr(i, k, inputIDPos_) + 1);
2697 file << strLine.c_str() <<
"\n";
2710 const int nVerts = (inputIDPos_ >= 0) ? input_[inputIDPos_].count : 0;
2711 const int nNormals = (inputIDNorm_ >= 0) ? input_[inputIDNorm_].count : 0;
2712 const int nTexC = (inputIDTexC_ >= 0) ? input_[inputIDTexC_].count : 0;
2714 if (!_seperateFiles)
2750 file = fopen(_filename,
"wb");
2754 const int nFaces = faceInput_->getNumFaces();
2755 fwrite(&nFaces, 4, 1, file);
2757 fwrite(&nVerts, 4, 1, file);
2758 fwrite(&nNormals, 4, 1, file);
2759 fwrite(&nTexC, 4, 1, file);
2761 int faceBufSize = 0;
2763 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2764 faceBufSize += faceInput_->getFaceSize(i);
2766 fwrite(&faceBufSize, 4, 1, file);
2770 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2772 int fsize = faceInput_->getFaceSize(i);
2773 fwrite(&fsize, 4, 1, file);
2776 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2778 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2780 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDPos_);
2781 fwrite(&idx, 4, 1, file);
2785 if (inputIDTexC_ >= 0)
2787 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2789 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2791 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDTexC_);
2792 fwrite(&idx, 4, 1, file);
2797 if (inputIDNorm_ >= 0)
2799 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
2801 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2803 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDNorm_);
2804 fwrite(&idx, 4, 1, file);
2812 for (
int i = 0; i < nVerts; ++i)
2816 input_[inputIDPos_].getElementData(i, pos, el);
2818 fwrite(pos, 4, 3, file);
2821 if (inputIDTexC_ >= 0)
2827 for (
int i = 0; i < vei->
count; ++i)
2830 fwrite(pos, 4, 2, file);
2835 if (inputIDNorm_ >= 0)
2841 for (
int i = 0; i < vei->
count; ++i)
2844 fwrite(pos, 4, 3, file);
2851 fwrite(&adjacencyVert_.num, 4, 1, file);
2852 fwrite(&adjacencyVert_.bufSize, 4, 1, file);
2854 fwrite(adjacencyVert_.start, 4, adjacencyVert_.num, file);
2855 fwrite(adjacencyVert_.count, 1, adjacencyVert_.num, file);
2856 fwrite(adjacencyVert_.buf, 4, adjacencyVert_.bufSize, file);
2865 FILE* file = fopen(
"../mesh_fsize.bin",
"wb");
2867 for (
int i = 0; i < numFaces_; ++i)
2869 unsigned char fsize = (
unsigned char)faceInput_->getFaceSize(i);
2870 fwrite(&fsize, 1, 1, file);
2875 file = fopen(
"../mesh_fdata_pos.bin",
"wb");
2877 for (
int i = 0; i < numFaces_; ++i)
2879 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2881 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDPos_);
2882 fwrite(&idx, 4, 1, file);
2888 if (inputIDTexC_ >= 0)
2890 file = fopen(
"../mesh_fdata_texc.bin",
"wb");
2892 for (
int i = 0; i < numFaces_; ++i)
2894 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2896 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDTexC_);
2897 fwrite(&idx, 4, 1, file);
2904 if (inputIDNorm_ >= 0)
2906 file = fopen(
"../mesh_fdata_norm.bin",
"wb");
2908 for (
int i = 0; i < numFaces_; ++i)
2910 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
2912 int idx = faceInput_->getSingleFaceAttr(i, k, inputIDNorm_);
2913 fwrite(&idx, 4, 1, file);
2922 file = fopen(
"../mesh_vdata_pos.bin",
"wb");
2923 for (
int i = 0; i < nVerts; ++i)
2927 input_[inputIDPos_].getElementData(i, pos, el);
2929 fwrite(pos, 4, 3, file);
2933 if (inputIDTexC_ >= 0)
2935 file = fopen(
"../mesh_vdata_texc.bin",
"wb");
2941 for (
int i = 0; i < vei->
count; ++i)
2944 fwrite(pos, 4, 2, file);
2951 if (inputIDNorm_ >= 0)
2953 file = fopen(
"../mesh_vdata_norm.bin",
"wb");
2959 for (
int i = 0; i < vei->
count; ++i)
2962 fwrite(pos, 4, 3, file);
2979 int tmp[] = {_v0, _v1, _v2};
2990 int tmp[] = {_v0, _v1, _v2};
3002 int tmp[] = {_v0, _v1, _v2};
3008 int faceID, cornerID;
3014 for (
int i = 0; i < numAttributes_; ++i)
3018 int idx = getInputIndex(faceID, cornerID, i);
3020 input_[i].getElementData(idx, (
char*)_out + (
size_t)el->
pointer_, el);
3027 for (
int i = 0; i < numAttributes_; ++i)
3030 input_[i].getElementData(posID, (
char*)_out + (
size_t)el->
pointer_, el);
3038 assert(_i < numTris_ * 3);
3042 void MeshCompiler::createVertexMap(
bool _keepIsolatedVerts)
3049 if (_keepIsolatedVerts)
3057 for (
int i = 0; i < numFaces_; ++i)
3060 for (
int k = 0; k < fsize; ++k)
3063 int vertexID = getInputIndexSplit(i, k);
3065 vertexMapCorner_[vertexID] = k;
3069 if (_keepIsolatedVerts)
3086 vertexMapCorner_[i] < 0)
3087 std::cerr <<
"mesh-assembler: vertexMap error at index: " << i << std::endl;
3090 std::cerr <<
"mesh-assembler: vertexMap error at index: " << i << std::endl;
3097 void MeshCompiler::createFaceMap()
3104 for (
int i = 0; i < numTris_; ++i)
3113 if (!faceSortMap_.empty())
3114 faceID = faceSortMap_[faceID];
3126 faceToTriMapOffset_.clear();
3127 if (!constantFaceSize_)
3129 faceToTriMapOffset_.resize(numTris_, -1);
3132 for (
int i = 0; i < numFaces_; ++i)
3134 faceToTriMapOffset_[i] = offset;
3138 offset += fsize - 2;
3146 for (
int i = 0; i < numTris_; ++i)
3152 int offset = constantFaceSize_ ? (faceID * (maxFaceSize_ - 2)) : faceToTriMapOffset_[faceID];
3157 while (
faceToTriMap_[offset + triNo] != -1 && triNo + offset < numTris_)
3174 file = fopen(_filename,
"wt");
3178 fprintf(file,
"vertex-adjacency: \n");
3179 for (
int i = 0; i < input_[inputIDPos_].count; ++i)
3182 int count = getAdjVertexFaceCount(i);
3184 std::vector<int> sortedList(count);
3185 for (
int k = 0; k < count; ++k)
3186 sortedList[k] = getAdjVertexFace(i, k);
3188 std::sort(sortedList.begin(), sortedList.end());
3190 for (
int k = 0; k < count; ++k)
3191 fprintf(file,
"adj[%d][%d] = %d\n", i, k, sortedList[k]);
3201 if ((
int)faceGroupIDs_.size() <= std::max(numFaces_,_i))
3202 faceGroupIDs_.resize(std::max(numFaces_,_i+1), -1);
3204 faceGroupIDs_[_i] = _groupID;
3212 int batchSize = _range;
3215 if ((_range < 0) || ( static_cast<size_t>(_offset + batchSize) >
numDrawVerts_) )
3218 char* bdst = (
char*)_dst;
3220 for (
int i = 0; i < batchSize; ++i)
3222 getVertex(i + _offset, bdst + decl_.getVertexStride() * i);
3232 : e0(std::min(a,b)), e1(std::max(a,b)) {}
3236 return e0 == k.e0 && e1 == k.e1;
3252 #ifdef ACG_MC_USE_STL_HASH 3254 struct MeshCompiler_EdgeTriMapKey_Hash
3258 return ((std::hash<int>()(k.e0) << 1) ^ std::hash<int>()(k.e1)) >> 1;
3264 return ((::qHash(k.e0) << 1) ^ ::qHash(k.e1)) >> 1;
3266 #endif // ACG_MC_USE_STL_HASH 3271 int* idst = (
int*)_dst;
3273 for (
int i = 0; i < numTris_; ++i)
3280 idst[i*6+1] = _borderIndex;
3281 idst[i*6+3] = _borderIndex;
3282 idst[i*6+5] = _borderIndex;
3286 QHash<MeshCompiler_EdgeTriMapKey, std::pair<int, int> > EdgeAdjMap;
3288 for (
int i = 0; i < numTris_; ++i)
3293 for (
int k = 0; k < 3; ++k)
3295 int faceId, cornerId;
3300 for (
int e = 0; e < 3; ++e)
3304 QHash< MeshCompiler_EdgeTriMapKey, std::pair<int, int> >::iterator itKey;
3306 itKey = EdgeAdjMap.find(edge);
3308 if (itKey == EdgeAdjMap.end())
3309 EdgeAdjMap[edge] = std::pair<int, int>(i, -1);
3311 itKey.value().second = i;
3317 for (QHash<
MeshCompiler_EdgeTriMapKey, std::pair<int, int> >::iterator it = EdgeAdjMap.begin(); it != EdgeAdjMap.end(); ++it)
3320 int Tris[2] = {it.value().first, it.value().second};
3325 for (
int k = 0; k < 3; ++k)
3327 int faceId, cornerId;
3338 int TriEdges[2] = {-1,-1};
3339 int TriOppositeVerts[2] = {-1,-1};
3341 for (
int e = 0; e < 3; ++e)
3345 if (edge0 == it.key())
3348 TriOppositeVerts[1] = (e+2)%3;
3354 for (
int e = 0; e < 3; ++e)
3358 if (edge1 == it.key())
3361 TriOppositeVerts[0] = (e+2)%3;
3368 for (
int i = 0; i < 2; ++i)
3372 int e = TriEdges[i];
3375 int ov = _borderIndex;
3377 if (TriOppositeVerts[i] >= 0 && Tris[(i+1)%2] >= 0)
3378 ov =
getIndex(Tris[(i+1)%2]*3 + TriOppositeVerts[i]);
3380 idst[Tris[i] * 6 + e*2 + 1] = ov;
3462 const int numVerts = input_[inputIDPos_].count;
3465 outputVertexTriAdj.init(numVerts);
3468 for (
int i = 0; i < numTris_; ++i)
3470 int faceID, cornerID;
3472 for (
int k = 0; k < 3; ++k)
3477 outputVertexTriAdj.count[posID]++;
3484 for (
int i = 0; i < numVerts; ++i)
3486 outputVertexTriAdj.start[i] = nCounter;
3488 nCounter += outputVertexTriAdj.count[i];
3490 outputVertexTriAdj.count[i] = 0;
3494 outputVertexTriAdj.buf =
new int[nCounter];
3495 outputVertexTriAdj.bufSize = nCounter;
3498 for (
int i = 0; i < numTris_; ++i)
3500 int faceID, cornerID;
3502 for (
int k = 0; k < 3; ++k)
3507 int adjIdx = outputVertexTriAdj.start[posID] + outputVertexTriAdj.count[posID]++;
3509 outputVertexTriAdj.buf[ adjIdx ] = i;
3516 int* idst = (
int*)_dst;
3518 for (
int i = 0; i < numTris_; ++i)
3525 idst[i*6+1] = _borderIndex;
3526 idst[i*6+3] = _borderIndex;
3527 idst[i*6+5] = _borderIndex;
3531 #pragma omp parallel for 3533 for (
int vertexID = 0; vertexID < numVerts; ++vertexID)
3535 const int numAdjTris = outputVertexTriAdj.getCount(vertexID);
3538 for (
int adjID0 = 0; adjID0 < numAdjTris; ++adjID0)
3540 const int triID0 = outputVertexTriAdj.getAdj(vertexID, adjID0);
3543 for (
int k = 0; k < 3; ++k)
3545 int faceid, cornerid;
3549 for (
int adjID1 = adjID0+1; adjID1 < numAdjTris; ++adjID1)
3551 const int triID1 = outputVertexTriAdj.getAdj(vertexID, adjID1);
3554 for (
int k = 0; k < 3; ++k)
3556 int faceid, cornerid;
3561 for (
int e0 = 0; e0 < 3; ++e0)
3565 for (
int e1 = 0; e1 < 3; ++e1)
3573 int oppVertex0 =
getIndex( triID1*3 + ((e1+2)%3) );
3574 int oppVertex1 =
getIndex( triID0*3 + ((e0+2)%3) );
3576 idst[triID0*6 + e0*2 +1] = oppVertex0;
3577 idst[triID1*6 + e1*2 + 1] = oppVertex1;
3594 int* idst = (
int*)_dst;
3596 for (
int i = 0; i < numTris_; ++i)
3603 idst[i*6+1] = _borderIndex;
3604 idst[i*6+3] = _borderIndex;
3605 idst[i*6+5] = _borderIndex;
3610 #pragma omp parallel for 3612 for (
int triID0 = 0; triID0 < numTris_; ++triID0)
3615 for (
int k = 0; k < 3; ++k)
3617 int faceid, cornerid;
3621 for (
int triID1 = triID0 + 1; triID1 < numTris_; ++triID1)
3624 for (
int k = 0; k < 3; ++k)
3626 int faceid, cornerid;
3631 for (
int e0 = 0; e0 < 3; ++e0)
3635 for (
int e1 = 0; e1 < 3; ++e1)
3643 int oppVertex0 =
getIndex( triID1*3 + ((e1+2)%3) );
3644 int oppVertex1 =
getIndex( triID0*3 + ((e0+2)%3) );
3646 idst[triID0*6 + e0*2 +1] = oppVertex0;
3647 idst[triID1*6 + e1*2 + 1] = oppVertex1;
3689 int positionID = -1;
3695 _cornerID = vertexMapCorner_[_i];
3697 positionID = getInputIndex(_faceID, _cornerID, inputIDPos_);
3713 return getInputIndexSplit(_faceID, _cornerID);
3719 assert(_k < fsize - 2);
3722 *_numTrisOut = fsize - 2;
3724 int offset = constantFaceSize_ ? (_faceID * (maxFaceSize_ - 2)) : faceToTriMapOffset_[_faceID];
3757 size_t usage = faceStart_.size() * 4;
3758 usage += faceSize_.size() * 1;
3759 usage += faceData_.size() * 4;
3760 usage += faceGroupIDs_.size() * 2;
3761 usage += faceBufSplit_.size() * 4;
3762 usage += faceSortMap_.size() * 4;
3764 usage += triIndexBuffer_.size() * 4;
3766 usage += subsetIDMap_.size() *
sizeof(
Subset);
3768 usage += vertexWeldMapFace_.size() * 5;
3770 usage += adjacencyVert_.bufSize * 4;
3771 usage += adjacencyVert_.num * 4;
3772 usage += adjacencyVert_.num * 1;
3776 usage += splitter_->splits.size() * 4;
3782 usage += faceToTriMapOffset_.size() * 4;
3791 const int byteToMB = 1024 * 1024;
3793 std::cout <<
"faceStart_: " <<
sizeof(std::pair<int, unsigned char>) << std::endl;
3795 std::cout <<
"faceStart_: " << faceStart_.size() * 4 / byteToMB << std::endl;
3796 std::cout <<
"faceSize_: " << faceSize_.size() * 1 / byteToMB << std::endl;
3797 std::cout <<
"faceData_: " << faceData_.size() * 4 / byteToMB << std::endl;
3798 std::cout <<
"faceGroupIDs_: " << faceGroupIDs_.size() * 2 / byteToMB << std::endl;
3799 std::cout <<
"faceBufSplit_: " << faceBufSplit_.size() * 4 / byteToMB << std::endl;
3801 std::cout <<
"faceSortMap_: " << faceSortMap_.size() * 4 / byteToMB << std::endl;
3803 std::cout <<
"triIndexBuffer_: " << triIndexBuffer_.size() * 4 / byteToMB << std::endl;
3805 std::cout <<
"vertexWeldMap_: " << vertexWeldMapFace_.size() * 5 / byteToMB << std::endl;
3807 std::cout <<
"adjacencyVert_: buf = " << adjacencyVert_.bufSize * 4 / byteToMB <<
3808 ", offset = " << adjacencyVert_.num * 4 / byteToMB <<
3809 ", count = " << adjacencyVert_.num * 1 / byteToMB << std::endl;
3812 std::cout <<
"splitter_: " << splitter_->splits.size() * 4 / byteToMB << std::endl;
3814 std::cout <<
"triToSortFaceMap_: " <<
triToSortFaceMap_.size() * 4 / byteToMB << std::endl;
3815 std::cout <<
"triOptMap_: " <<
triOptMap_.size() * 4 / byteToMB << std::endl;
3816 std::cout <<
"vertexMap_: " <<
vertexMapFace_.size() * 5 / byteToMB << std::endl;
3817 std::cout <<
"faceToTriMapOffset_: " << faceToTriMapOffset_.size() * 4 / byteToMB << std::endl;
3818 std::cout <<
"faceToTriMap_: " <<
faceToTriMap_.size() * 4 / byteToMB << std::endl;
3819 std::cout <<
"triToFaceMap_: " <<
triToFaceMap_.size() * 4 / byteToMB << std::endl;
3822 std::cout <<
"indices_: " << 3 * numTris_ * 4 / byteToMB << std::endl;
3835 return "Error: no face input data present\n";
3837 std::stringstream strm;
3841 for (
int a = 0; a < numAttributes_; ++a)
3843 if (input_[a].count <= 0)
3844 strm <<
"Warning: input buffer is not initialized: buffer id " << a <<
"\n";
3847 for (
int i = 0; i < faceInput_->getNumFaces(); ++i)
3849 if (faceInput_->getFaceSize(i) < 3)
3850 strm <<
"Error: face size too small: face " << i <<
", size " << faceInput_->getFaceSize(i) <<
" must be at least 3\n";
3852 std::map<int, int> facePositions;
3854 for (
int k = 0; k < faceInput_->getFaceSize(i); ++k)
3858 for (
int a = 0; a < numAttributes_; ++a)
3860 if (input_[a].count > 0)
3863 if (faceV[a] >= input_[a].count)
3864 strm <<
"Error: input index (face/corner/attribute: " << i <<
"/" << k <<
"/" << a <<
") invalid: " << faceV[a] <<
" >= buffer size (" << input_[a].count <<
")\n";
3866 strm <<
"Error: input index (face/corner/attribute: " << i <<
"/" << k <<
"/" << a <<
") invalid: " << faceV[a] <<
"\n";
3871 facePositions[faceV[0]] = k;
3875 if ((
int)facePositions.size() != faceInput_->getFaceSize(i))
3876 strm <<
"Warning: degenerate face " << i <<
"\n";
3879 if (!faceInput_->getFaceSize(i))
3880 strm <<
"Warning: empty face " << i <<
"\n";
3889 numFaces_ = faceInput_->getNumFaces();
3890 numIndices_ = faceInput_->getNumIndices();
3893 for (
int i = numFaces_-1; i >= 0 && !faceInput_->getFaceSize(i); --i)
3897 for (
unsigned int i = 0; i < decl_.getNumElements(); ++i)
3900 assert(input_[i].attrSize <= 0 || input_[i].attrSize == attrSize);
3901 input_[i].attrSize = attrSize;
3906 int minFaceSize = 99999999;
3907 for (
int i = 0; i < numFaces_; ++i)
3909 const int fsize = faceInput_->getFaceSize(i);
3911 maxFaceSize_ = std::max((
int)maxFaceSize_, fsize);
3912 minFaceSize = std::min(minFaceSize, fsize);
3917 if (minFaceSize < 3)
3918 std::cout <<
"error: input contains faces with less than 3 vertices! MeshCompiler only works for pure surface meshes!" << std::endl;
3920 assert(minFaceSize >= 3);
3922 if (minFaceSize < (
int)maxFaceSize_)
3927 faceStart_.resize(numFaces_, -1);
3928 faceSize_.resize(numFaces_, 0);
3930 for (
int i = 0; i < numFaces_; ++i)
3932 faceSize_[i] = faceInput_->getFaceSize(i);
3933 faceStart_[i] = curOffset;
3934 curOffset += faceSize_[i];
3937 if (numIndices_ <= 0)
3938 numIndices_ = curOffset;
3942 constantFaceSize_ =
true;
3943 numIndices_ = maxFaceSize_ * numFaces_;
3950 faceSortMap_.clear();
3953 faceToTriMapOffset_.clear();
3957 vertexMapCorner_.clear();
3959 faceBufSplit_.clear();
3961 isolatedVertices_.clear();
3964 if (!provokingVertexSetByUser_)
3965 provokingVertex_ = -1;
3969 for (
int i = 0; i < numFaces_; ++i)
3973 int v0 = faceInput_->getSingleFaceAttr(i, k, inputIDPos_);
3974 int v1 = getInputIndex(i, k, inputIDPos_);
3984 faceInput_ = _faceInput;
3994 for (
int i = 0; i < _numTris; ++i)
3996 int tri[3] = {-1, -1, -1};
3998 for (
int k = 0; k < 3; ++k)
4000 int offs = i * 3 + k;
4004 case 1: tri[k] = ((
char*)_indices)[offs];
break;
4005 case 2: tri[k] = ((
short*)_indices)[offs];
break;
4006 case 4: tri[k] = ((
int*)_indices)[offs];
break;
4007 case 8: tri[k] = (int)((
long long*)_indices)[offs];
break;
4023 provokingVertex_ = _v;
4024 provokingVertexSetByUser_ =
true;
4027 int MeshCompiler::getAdjVertexFaceCount(
int _vertexID )
const 4029 return adjacencyVert_.num ? adjacencyVert_.getCount(_vertexID) : faceInput_->getVertexAdjCount(_vertexID);
4032 int MeshCompiler::getAdjVertexFace(
int _vertexID,
int _k )
const 4034 return adjacencyVert_.num ? adjacencyVert_.getAdj(_vertexID, _k) : faceInput_->getVertexAdjFace(_vertexID, _k);
4039 return maxFaceSize_ == 3;
4047 if (maxFaceSize_ <= 3)
return true;
4055 std::vector<int> FaceVerts(fsize);
4057 for (
int i = 0; i < fsize; ++i)
4065 case 0: edgeStart = 0; edgeEnd = 1;
break;
4066 case 1: edgeStart = 1; edgeEnd = 2;
break;
4067 case 2: edgeStart = 2; edgeEnd = 0;
break;
4072 edgeStart =
getIndex(_triID * 3 + edgeStart);
4073 edgeEnd =
getIndex(_triID * 3 + edgeEnd);
4076 for (
int e = 0; e < fsize; ++e)
4078 if (FaceVerts[e] == edgeStart && FaceVerts[(e+1)%fsize] == edgeEnd)
4080 if (FaceVerts[e] == edgeEnd && FaceVerts[(e+1)%fsize] == edgeStart)
4087 void MeshCompilerDefaultFaceInput::dbgWriteToObjFile(FILE* _file,
int _posAttrID,
int _normalAttrID,
int _texcAttrID)
4089 for (
int i = 0; i < numFaces_; ++i)
4091 std::string strLine =
"f ";
4093 int offset = faceOffset_[i];
4094 int size = faceSize_[i];
4097 for (
int k = 0; k < size; ++k)
4099 if (_normalAttrID>=0 && _texcAttrID>=0)
4100 sprintf(tmp,
"%d/%d/%d ", faceData_[_posAttrID][offset+k]+1,
4101 faceData_[_texcAttrID][offset+k]+1,
4102 faceData_[_normalAttrID][offset+k]+1);
4103 else if (_normalAttrID >= 0)
4104 sprintf(tmp,
"%d//%d ", faceData_[_posAttrID][offset + k]+1, faceData_[_normalAttrID][offset+k]+1);
4105 else if (_texcAttrID >= 0)
4106 sprintf(tmp,
"%d/%d ", faceData_[_posAttrID][offset + k]+1, faceData_[_texcAttrID][offset+k]+1);
4108 sprintf(tmp,
"%d ", faceData_[_posAttrID][offset + k]+1);
4113 fprintf(_file,
"%s\n", strLine.c_str());
4119 int offset = faceOffset_[_faceID];
4120 int fsize = faceSize_[_faceID];
4122 for (
int i = 0; i < fsize; ++i)
4123 _out[i] = faceData_[_attrID][offset+i];
4131 const int pos = faceOffset_[_faceID] + _faceCorner;
4135 if (faceData_[_attrID].empty() || pos >=
int(faceData_[_attrID].size()))
4138 return faceData_[_attrID][pos];
4141 void MeshCompilerDefaultFaceInput::setFaceData(
int _faceID,
int _size,
int* _data,
int _attrID )
4144 if (numFaces_ <= _faceID)
4145 numFaces_ = _faceID + 1;
4148 if (faceData_[_attrID].capacity() == 0)
4149 faceData_[_attrID].reserve(numIndices_);
4151 if ((
int)faceOffset_.size() <= _faceID)
4152 faceOffset_.resize(_faceID+1, -1);
4154 if ((
int)faceSize_.size() <= _faceID)
4155 faceSize_.resize(_faceID+1, -1);
4157 faceSize_[_faceID] = _size;
4159 if (faceOffset_[_faceID] < 0)
4162 faceOffset_[_faceID] = faceData_[_attrID].size();
4163 for (
int i = 0; i < _size; ++i)
4164 faceData_[_attrID].push_back(_data[i]);
4168 int offs = faceOffset_[_faceID];
4170 if ((
int)faceData_[_attrID].size() == offs)
4172 for (
int i = 0; i < _size; ++i)
4173 faceData_[_attrID].push_back(_data[i]);
4178 if ((
int)faceData_[_attrID].size() < offs + _size + 1)
4179 faceData_[_attrID].resize(offs + _size + 1, -1);
4182 for (
int i = 0; i < _size; ++i)
4183 faceData_[_attrID][offs + i] = _data[i];
4193 assert(_faceID >= 0);
4194 assert(_faceCorner >= 0);
4195 assert(_faceCorner < fsize);
4199 int* tmpPtr = getFaceAttr(_faceID, _attrID);
4202 retVal = tmpPtr[_faceCorner];
4205 tmpPtr =
new int[fsize];
4206 if (getFaceAttr(_faceID, _attrID, tmpPtr))
4207 retVal = tmpPtr[_faceCorner];
4215 bool MeshCompilerVertexCompare::equalVertex(
const void* v0,
const void* v1,
const VertexDeclaration* _decl )
4224 for (
int i = 0; i < nElements; ++i)
4229 const void* el_0 =
static_cast<const char*
>(v0) + (
size_t)el->
pointer_;
4230 const void* el_1 =
static_cast<const char*
>(v1) + (
size_t)el->
pointer_;
4233 switch ( el->
type_ )
4237 const double* d0 =
static_cast<const double*
>(el_0);
4238 const double* d1 =
static_cast<const double*
>(el_1);
4243 diff += fabs(d0[k] - d1[k]);
4253 const float* f0 =
static_cast<const float*
>(el_0);
4254 const float* f1 =
static_cast<const float*
>(el_1);
4265 diff += fabsf(f0[k] - f1[k]);
4273 case GL_UNSIGNED_INT:
4275 const int* i0 =
static_cast<const int*
>(el_0);
4276 const int* i1 =
static_cast<const int*
>(el_1);
4286 case GL_UNSIGNED_SHORT:
4288 const short* i0 =
static_cast<const short*
>(el_0);
4289 const short* i1 =
static_cast<const short*
>(el_1);
4299 case GL_UNSIGNED_BYTE:
4301 const char* i0 =
static_cast<const char*
>(el_0);
4302 const char* i1 =
static_cast<const char*
>(el_1);
4311 default: std::cerr <<
"MeshCompiler: equalVertex() comparision not implemented for type: " << el->
type_ << std::endl;
size_t numDrawVerts_
vertices in vbo
void prepareData()
build() preparation
void dbgdump(const char *_filename) const
dump mesh info to text file
void setIndexBufferInterleaved(int _numTris, int _indexSize, const void *_indices)
Set index buffer for a triangle mesh.
const char * shaderInputName_
set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically...
void getVertexBuffer(void *_dst, const int _offset=0, const int _range=-1)
Get vertex buffer ready for rendering.
int mapToOriginalFaceID(const int _triID) const
unsigned int numElements_
how many elements of type_
std::vector< int > indices_
index buffer
void setProvokingVertex(int _v)
void setTexCoords(size_t _num, const void *_data, size_t _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
const void * pointer_
Offset in bytes to the first occurrence of this element in vertex buffer; Or address to vertex data i...
unsigned int getNumElements() const
Namespace providing different geometric functions concerning angles.
void setFaceAttrib(int _i, int _v0, int _v1, int _v2, int _attrID)
Set attribute ids per triangle.
void setNumFaces(const int _numFaces, const int _numIndices)
Set number of faces and indices if known by user.
void setVertices(size_t _num, const void *_data, size_t _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
size_t getMemoryUsage(bool _printConsole=true) const
void setFaceInput(MeshCompilerFaceInput *_faceInput)
std::string checkInputData() const
check for errors in input data
Class to define the vertex input layout.
int getNumVertices() const
void dbgdumpObj(const char *_filename) const
dump mesh in wavefront obj format
int getNumInputAttributes(int _attrIdx) const
bool dbgVerify(const char *_filename) const
test correctness of input <-> output id mappings, unshared per face vertex.. logs errors in file ...
int split(int *vertex)
returns a unique index for a vertex-attribute combination
size_t numIsolatedVerts_
isolated vertices
int findGroupSubset(int _groupID)
get subset ID of a group
void setFaceNormals(int _i, int _v0, int _v1, int _v2)
Set normal ids per triangle.
int index(int _i) const
Get local vertex index.
VERTEX_USAGE usage_
position, normal, shader input ..
void setNormals(size_t _num, const void *_data, size_t _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
void setFaceGroup(int _i, short _groupID)
Specify face groups.
void build(bool _weldVertices=false, bool _optimizeVCache=true, bool _needPerFaceAttribute=false, bool _keepIsolatedVertices=false)
Build vertex + index buffer.
void getIndexAdjBuffer_MT(void *_dst, const int _borderIndex=-1)
Multi-threaded version of getIndexAdjBuffer.
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.
const Subset * getSubset(int _i) const
get a specific subset
int mapToDrawTriID(const int _faceID, const int _k=0, int *_numTrisOut=0) const
bool isTriangleMesh() const
Description of one vertex element.
int mapToDrawVertexID(const int _faceID, const int _cornerID) const
void getVertex(int _id, void *_out) const
bool isIsolated(const int vertexPosID)
check if vertex is isolated with a complete splitting list
bool convex() const
Is the polygon convex?
void setAttrib(int _attrIdx, int _v, const void *_data)
void WriteIndexBuffer(unsigned int DstIndexSize, void *pDst)
Applies the remapping on the initial pIndices constructor's param and stores the result in the given ...
void getInputFaceVertex_Welded(const int _face, const int _corner, int *_out) const
int getFaceGroup(int _faceID) const
Get Face Group of the given face.
std::vector< int > triToFaceMap_
output tri index -> input face index
std::vector< int > triToSortFaceMap_
maps from triangle ID to sorted face ID
void getIndexAdjBuffer_BruteForce(void *_dst, const int _borderIndex=-1)
Slow brute-force version of getIndexAdjBuffer.
void setFaceTexCoords(int _i, int _v0, int _v1, int _v2)
Set texcoord ids per triangle.
int getFaceSize(const int _i) const
Get size of input face.
const unsigned int * GetTriangleMap() const
Retrieves the map from dst triangle to src triangle. how to remap: for each triangle t in DstTriBuffe...
void dbgdumpInputBin(const char *_filename, bool _seperateFiles=false) const
dump input mesh to binary file format
const VertexElement * getElement(unsigned int i) const
std::string vertexToString(const void *v) const
interpret vertex data according declaration and write to string
unsigned int vbo_
Explicit vbo source of this element, set to 0 if the buffer bound at the time of activating the decla...
static size_t getElementSize(const VertexElement *_pElement)
unsigned int type_
GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ...
void dbgdumpAdjList(const char *_filename) const
dump adjacency list to text file
void setAttribVec(int _attrIdx, size_t _num, const void *_data, size_t _stride=0, bool _internalCopy=false, GLuint _fmt=0, int _elementSize=-1)
size_t numTriangles() const
Get number of triangles.
bool isFaceEdge(const int _triID, const int _edge) const
int getNumSubsets() const
Get the number of subsets.
void getInputFaceVertexData(const int _face, const int _corner, void *_out) const
std::vector< int > vertexMapFace_
vertex index in vbo -> input (face id, corner id) pair , also inverse of faceBufSplit_ ...
unsigned int divisor_
For instanced rendering: Step rate describing how many instances are drawn before advancing to the ne...
const int * mapToOriginalFaceIDPtr() const
int mapToOriginalVertexID(const size_t _i, int &_faceID, int &_cornerID) const
void getInputFaceVertex(const int _face, const int _corner, int *_out) const
void dbgdumpInputObj(const char *_filename) const
dump input mesh to wavefront obj format
std::vector< int > faceToTriMap_
input face index -> output tri index
std::vector< int > triOptMap_
maps from optimized tri ID to unoptimized tri ID
int getIndex(int _i) const
void getIndexAdjBuffer(void *_dst, const int _borderIndex=-1)
Get index buffer with adjacency information ready for rendering.
void setFaceVerts(int _i, int _v0, int _v1, int _v2)
Set vertex ids per triangle.