26 template<
typename VolumeType,
typename Controller>
29 ,m_sampVolume(volData)
30 ,m_meshCurrent(result)
31 ,m_regSizeInVoxels(region)
34 m_regSizeInCells = m_regSizeInVoxels;
37 m_controller = controller;
38 m_tThreshold = m_controller.getThreshold();
41 template<
typename VolumeType,
typename Controller>
44 m_meshCurrent->clear();
46 uint32_t uArrayWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1;
47 uint32_t uArrayHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1;
48 uint32_t arraySizes[2]= {uArrayWidth, uArrayHeight};
62 m_regSlicePrevious = m_regSizeInVoxels;
63 Vector3DInt32 v3dUpperCorner = m_regSlicePrevious.getUpperCorner();
64 v3dUpperCorner.
setZ(m_regSlicePrevious.getLowerCorner().getZ());
65 m_regSlicePrevious.setUpperCorner(v3dUpperCorner);
66 m_regSliceCurrent = m_regSlicePrevious;
68 uint32_t uNoOfNonEmptyCellsForSlice0 = 0;
69 uint32_t uNoOfNonEmptyCellsForSlice1 = 0;
72 computeBitmaskForSlice<false>(pPreviousBitmask, pCurrentBitmask);
73 uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
75 if(uNoOfNonEmptyCellsForSlice1 != 0)
80 generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
83 std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
84 pPreviousBitmask.swap(pCurrentBitmask);
85 m_pPreviousVertexIndicesX.
swap(m_pCurrentVertexIndicesX);
86 m_pPreviousVertexIndicesY.
swap(m_pCurrentVertexIndicesY);
87 m_pPreviousVertexIndicesZ.
swap(m_pCurrentVertexIndicesZ);
89 m_regSlicePrevious = m_regSliceCurrent;
93 for(
int32_t uSlice = 1; uSlice <= m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ(); uSlice++)
95 computeBitmaskForSlice<true>(pPreviousBitmask, pCurrentBitmask);
96 uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells;
98 if(uNoOfNonEmptyCellsForSlice1 != 0)
103 generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ);
106 if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0))
108 generateIndicesForSlice(pPreviousBitmask, m_pPreviousVertexIndicesX, m_pPreviousVertexIndicesY, m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY);
111 std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1);
112 pPreviousBitmask.swap(pCurrentBitmask);
113 m_pPreviousVertexIndicesX.
swap(m_pCurrentVertexIndicesX);
114 m_pPreviousVertexIndicesY.
swap(m_pCurrentVertexIndicesY);
115 m_pPreviousVertexIndicesZ.
swap(m_pCurrentVertexIndicesZ);
117 m_regSlicePrevious = m_regSliceCurrent;
121 m_meshCurrent->m_Region = m_regSizeInVoxels;
123 m_meshCurrent->m_vecLodRecords.clear();
126 lodRecord.
endIndex = m_meshCurrent->getNoOfIndices();
127 m_meshCurrent->m_vecLodRecords.push_back(lodRecord);
130 template<
typename VolumeType,
typename Controller>
131 template<
bool isPrevZAvail>
134 m_uNoOfOccupiedCells = 0;
136 const int32_t iMaxXVolSpace = m_regSliceCurrent.getUpperCorner().getX();
137 const int32_t iMaxYVolSpace = m_regSliceCurrent.getUpperCorner().getY();
139 int32_t iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
142 int32_t iYVolSpace = m_regSliceCurrent.getLowerCorner().getY();
143 int32_t iXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
145 uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
146 uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
148 m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
149 computeBitmaskForCell<false, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace);
152 iXVolSpace = m_regSliceCurrent.getLowerCorner().getX();
153 m_sampVolume.setPosition(iXVolSpace, m_regSliceCurrent.getLowerCorner().getY(), iZVolSpace);
154 for(iYVolSpace = m_regSliceCurrent.getLowerCorner().getY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++)
156 uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
157 uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
159 m_sampVolume.movePositiveY();
161 computeBitmaskForCell<false, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace);
165 iYVolSpace = m_regSliceCurrent.getLowerCorner().getY();
166 m_sampVolume.setPosition(m_regSliceCurrent.getLowerCorner().getX(), iYVolSpace, iZVolSpace);
167 for(iXVolSpace = m_regSliceCurrent.getLowerCorner().getX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++)
169 uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
170 uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
172 m_sampVolume.movePositiveX();
174 computeBitmaskForCell<true, false, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace);
178 for(iYVolSpace = m_regSliceCurrent.getLowerCorner().getY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++)
180 m_sampVolume.setPosition(m_regSliceCurrent.getLowerCorner().getX(), iYVolSpace, iZVolSpace);
181 for(iXVolSpace = m_regSliceCurrent.getLowerCorner().getX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++)
183 uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
184 uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
186 m_sampVolume.movePositiveX();
188 computeBitmaskForCell<true, true, isPrevZAvail>(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace);
192 return m_uNoOfOccupiedCells;
195 template<
typename VolumeType,
typename Controller>
196 template<
bool isPrevXAvail,
bool isPrevYAvail,
bool isPrevZAvail>
197 void MarchingCubesSurfaceExtractor<VolumeType, Controller>::computeBitmaskForCell(
const Array2DUint8& pPreviousBitmask,
Array2DUint8& pCurrentBitmask, uint32_t uXRegSpace, uint32_t uYRegSpace)
199 uint8_t iCubeIndex = 0;
201 typename VolumeType::VoxelType v000;
202 typename VolumeType::VoxelType v100;
203 typename VolumeType::VoxelType v010;
204 typename VolumeType::VoxelType v110;
205 typename VolumeType::VoxelType v001;
206 typename VolumeType::VoxelType v101;
207 typename VolumeType::VoxelType v011;
208 typename VolumeType::VoxelType v111;
216 v111 = m_sampVolume.peekVoxel1px1py1pz();
219 uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
220 iPreviousCubeIndexZ >>= 4;
223 uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
224 iPreviousCubeIndexY &= 192;
225 iPreviousCubeIndexY >>= 2;
228 uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
229 iPreviousCubeIndexX &= 128;
230 iPreviousCubeIndexX >>= 1;
232 iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY | iPreviousCubeIndexZ;
234 if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
238 v011 = m_sampVolume.peekVoxel0px1py1pz();
239 v111 = m_sampVolume.peekVoxel1px1py1pz();
242 uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
243 iPreviousCubeIndexZ >>= 4;
246 uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
247 iPreviousCubeIndexY &= 192;
248 iPreviousCubeIndexY >>= 2;
250 iCubeIndex = iPreviousCubeIndexY | iPreviousCubeIndexZ;
252 if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64;
253 if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
260 v101 = m_sampVolume.peekVoxel1px0py1pz();
261 v111 = m_sampVolume.peekVoxel1px1py1pz();
264 uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
265 iPreviousCubeIndexZ >>= 4;
268 uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
269 iPreviousCubeIndexX &= 160;
270 iPreviousCubeIndexX >>= 1;
272 iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexZ;
274 if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32;
275 if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
279 v001 = m_sampVolume.peekVoxel0px0py1pz();
280 v101 = m_sampVolume.peekVoxel1px0py1pz();
281 v011 = m_sampVolume.peekVoxel0px1py1pz();
282 v111 = m_sampVolume.peekVoxel1px1py1pz();
285 uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace];
286 iCubeIndex = iPreviousCubeIndexZ >> 4;
288 if (m_controller.convertToDensity(v001) < m_tThreshold) iCubeIndex |= 16;
289 if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32;
290 if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64;
291 if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
301 v110 = m_sampVolume.peekVoxel1px1py0pz();
302 v111 = m_sampVolume.peekVoxel1px1py1pz();
305 uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
306 iPreviousCubeIndexY &= 204;
307 iPreviousCubeIndexY >>= 2;
310 uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
311 iPreviousCubeIndexX &= 170;
312 iPreviousCubeIndexX >>= 1;
314 iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY;
316 if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8;
317 if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
321 v010 = m_sampVolume.peekVoxel0px1py0pz();
322 v110 = m_sampVolume.peekVoxel1px1py0pz();
324 v011 = m_sampVolume.peekVoxel0px1py1pz();
325 v111 = m_sampVolume.peekVoxel1px1py1pz();
328 uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1];
329 iPreviousCubeIndexY &= 204;
330 iPreviousCubeIndexY >>= 2;
332 iCubeIndex = iPreviousCubeIndexY;
334 if (m_controller.convertToDensity(v010) < m_tThreshold) iCubeIndex |= 4;
335 if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8;
336 if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64;
337 if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
344 v100 = m_sampVolume.peekVoxel1px0py0pz();
345 v110 = m_sampVolume.peekVoxel1px1py0pz();
347 v101 = m_sampVolume.peekVoxel1px0py1pz();
348 v111 = m_sampVolume.peekVoxel1px1py1pz();
351 uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace];
352 iPreviousCubeIndexX &= 170;
353 iPreviousCubeIndexX >>= 1;
355 iCubeIndex = iPreviousCubeIndexX;
357 if (m_controller.convertToDensity(v100) < m_tThreshold) iCubeIndex |= 2;
358 if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8;
359 if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32;
360 if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
364 v000 = m_sampVolume.getVoxel();
365 v100 = m_sampVolume.peekVoxel1px0py0pz();
366 v010 = m_sampVolume.peekVoxel0px1py0pz();
367 v110 = m_sampVolume.peekVoxel1px1py0pz();
369 v001 = m_sampVolume.peekVoxel0px0py1pz();
370 v101 = m_sampVolume.peekVoxel1px0py1pz();
371 v011 = m_sampVolume.peekVoxel0px1py1pz();
372 v111 = m_sampVolume.peekVoxel1px1py1pz();
374 if (m_controller.convertToDensity(v000) < m_tThreshold) iCubeIndex |= 1;
375 if (m_controller.convertToDensity(v100) < m_tThreshold) iCubeIndex |= 2;
376 if (m_controller.convertToDensity(v010) < m_tThreshold) iCubeIndex |= 4;
377 if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8;
378 if (m_controller.convertToDensity(v001) < m_tThreshold) iCubeIndex |= 16;
379 if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32;
380 if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64;
381 if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128;
387 pCurrentBitmask[uXRegSpace][uYRegSpace] = iCubeIndex;
391 ++m_uNoOfOccupiedCells;
395 template<
typename VolumeType,
typename Controller>
396 void MarchingCubesSurfaceExtractor<VolumeType, Controller>::generateVerticesForSlice(
const Array2DUint8& pCurrentBitmask,
401 int32_t iZVolSpace = m_regSliceCurrent.getLowerCorner().getZ();
404 for(
int32_t iYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); iYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); iYVolSpace++)
406 const uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY();
408 for(
int32_t iXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); iXVolSpace <= m_regSliceCurrent.getUpperCorner().getX(); iXVolSpace++)
411 const uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX();
414 uint8_t iCubeIndex = pCurrentBitmask[uXRegSpace][uYRegSpace];
425 m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
426 const typename VolumeType::VoxelType v000 = m_sampVolume.getVoxel();
432 m_sampVolume.movePositiveX();
433 const typename VolumeType::VoxelType v100 = m_sampVolume.getVoxel();
436 float fInterp =
static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000));
438 const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()) + fInterp, static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInCells.getLowerCorner().getZ()));
440 Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp));
446 typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
447 typename Controller::MaterialType uMaterial100 = m_controller.convertToMaterial(v100);
448 typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial100);
450 PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
451 uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
452 m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
454 m_sampVolume.moveNegativeX();
458 m_sampVolume.movePositiveY();
459 const typename VolumeType::VoxelType v010 = m_sampVolume.getVoxel();
462 float fInterp =
static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000));
464 const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()) + fInterp, static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()));
466 Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp));
472 typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
473 typename Controller::MaterialType uMaterial010 = m_controller.convertToMaterial(v010);
474 typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial010);
476 PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
477 uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
478 m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
480 m_sampVolume.moveNegativeY();
484 m_sampVolume.movePositiveZ();
485 const typename VolumeType::VoxelType v001 = m_sampVolume.getVoxel();
488 float fInterp =
static_cast<float>(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast<float>(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000));
490 const Vector3DFloat v3dPosition(static_cast<float>(iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()), static_cast<float>(iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()), static_cast<float>(iZVolSpace - m_regSizeInVoxels.getLowerCorner().getZ()) + fInterp);
492 Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp));
498 typename Controller::MaterialType uMaterial000 = m_controller.convertToMaterial(v000);
499 typename Controller::MaterialType uMaterial001 = m_controller.convertToMaterial(v001);
500 typename Controller::MaterialType uMaterial = (std::max)(uMaterial000, uMaterial001);
502 PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast<float>(uMaterial));
503 uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex);
504 m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerCorner().getX()][iYVolSpace - m_regSizeInVoxels.getLowerCorner().getY()] = uLastVertexIndex;
506 m_sampVolume.moveNegativeZ();
512 template<
typename VolumeType,
typename Controller>
513 void MarchingCubesSurfaceExtractor<VolumeType, Controller>::generateIndicesForSlice(
const Array2DUint8& pPreviousBitmask,
521 for(
int i = 0; i < 12; i++)
526 for(
int32_t iYVolSpace = m_regSlicePrevious.getLowerCorner().getY(); iYVolSpace <= m_regSizeInCells.getUpperCorner().getY(); iYVolSpace++)
528 for(
int32_t iXVolSpace = m_regSlicePrevious.getLowerCorner().getX(); iXVolSpace <= m_regSizeInCells.getUpperCorner().getX(); iXVolSpace++)
530 int32_t iZVolSpace = m_regSlicePrevious.getLowerCorner().getZ();
531 m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace);
534 const uint32_t uXRegSpace = m_sampVolume.getPosition().getX() - m_regSizeInVoxels.getLowerCorner().getX();
535 const uint32_t uYRegSpace = m_sampVolume.getPosition().getY() - m_regSizeInVoxels.getLowerCorner().getY();
538 uint8_t iCubeIndex = pPreviousBitmask[uXRegSpace][uYRegSpace];
549 indlist[0] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace];
554 indlist[1] = m_pPreviousVertexIndicesY[uXRegSpace+1][uYRegSpace];
559 indlist[2] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace+1];
564 indlist[3] = m_pPreviousVertexIndicesY[uXRegSpace][uYRegSpace];
569 indlist[4] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace];
574 indlist[5] = m_pCurrentVertexIndicesY[uXRegSpace+1][uYRegSpace];
579 indlist[6] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace+1];
584 indlist[7] = m_pCurrentVertexIndicesY[uXRegSpace][uYRegSpace];
589 indlist[8] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace];
594 indlist[9] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace];
599 indlist[10] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace+1];
604 indlist[11] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace+1];
608 for (
int i=0;
triTable[iCubeIndex][i]!=-1;i+=3)
611 int32_t ind1 = indlist[triTable[iCubeIndex][i+1]];
612 int32_t ind2 = indlist[triTable[iCubeIndex][i+2]];
614 if((ind0 != -1) && (ind1 != -1) && (ind2 != -1))
616 m_meshCurrent->addTriangle(ind0, ind1, ind2);