#include "RivFemPartGeometryGenerator.h" #include "cvfBase.h" #include "RigFemPart.h" //#include "RigFemPartScalarDataAccess.h" #include "cvfDebugTimer.h" #include "cvfGeometryBuilderDrawableGeo.h" #include "cvfPrimitiveSetIndexedUInt.h" #include "cvfScalarMapper.h" #include "cvfArray.h" #include "cvfOutlineEdgeExtractor.h" #include using namespace cvf; //================================================================================================== /// /// //================================================================================================== //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RivFemPartGeometryGenerator::RivFemPartGeometryGenerator(const RigFemPart* part) : m_part(part) { CVF_ASSERT(part); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RivFemPartGeometryGenerator::~RivFemPartGeometryGenerator() { } //-------------------------------------------------------------------------------------------------- /// Generate surface drawable geo from the specified region /// //-------------------------------------------------------------------------------------------------- ref RivFemPartGeometryGenerator::generateSurface() { computeArrays(); CVF_ASSERT(m_quadVertices.notNull()); if (m_quadVertices->size() == 0) return NULL; ref geo = new DrawableGeo; geo->setFromQuadVertexArray(m_quadVertices.p()); return geo; } //-------------------------------------------------------------------------------------------------- /// Generates simplified mesh as line drawing /// Must call generateSurface first //-------------------------------------------------------------------------------------------------- ref RivFemPartGeometryGenerator::createMeshDrawable() { if (!(m_quadVertices.notNull() && m_quadVertices->size() != 0)) return NULL; ref geo = new DrawableGeo; geo->setVertexArray(m_quadVertices.p()); ref indices = lineIndicesFromQuadVertexArray(m_quadVertices.p()); ref prim = new PrimitiveSetIndexedUInt(PT_LINES); prim->setIndices(indices.p()); geo->addPrimitiveSet(prim.p()); return geo; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- ref RivFemPartGeometryGenerator::createOutlineMeshDrawable(double creaseAngle) { if (!(m_quadVertices.notNull() && m_quadVertices->size() != 0)) return NULL; cvf::OutlineEdgeExtractor ee(creaseAngle, *m_quadVertices); ref indices = lineIndicesFromQuadVertexArray(m_quadVertices.p()); ee.addPrimitives(4, *indices); ref lineIndices = ee.lineIndices(); if (lineIndices->size() == 0) { return NULL; } ref prim = new PrimitiveSetIndexedUInt(PT_LINES); prim->setIndices(lineIndices.p()); ref geo = new DrawableGeo; geo->setVertexArray(m_quadVertices.p()); geo->addPrimitiveSet(prim.p()); return geo; } //-------------------------------------------------------------------------------------------------- /// /// /// /// //-------------------------------------------------------------------------------------------------- ref RivFemPartGeometryGenerator::lineIndicesFromQuadVertexArray(const Vec3fArray* vertexArray) { CVF_ASSERT(vertexArray); size_t numVertices = vertexArray->size(); int numQuads = static_cast(numVertices/4); CVF_ASSERT(numVertices%4 == 0); ref indices = new UIntArray; indices->resize(numQuads*8); #pragma omp parallel for for (int i = 0; i < numQuads; i++) { int idx = 8*i; indices->set(idx + 0, i*4 + 0); indices->set(idx + 1, i*4 + 1); indices->set(idx + 2, i*4 + 1); indices->set(idx + 3, i*4 + 2); indices->set(idx + 4, i*4 + 2); indices->set(idx + 5, i*4 + 3); indices->set(idx + 6, i*4 + 3); indices->set(idx + 7, i*4 + 0); } return indices; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivFemPartGeometryGenerator::computeArrays() { std::vector vertices; cvf::Vec3d offset = Vec3d::ZERO; //m_part->displayModelOffset(); const std::vector& nodeCoordinates = m_part->nodes().coordinates; //#pragma omp parallel for schedule(dynamic) for (int elmIdx = 0; elmIdx < static_cast(m_part->elementCount()); elmIdx++) { if (m_elmVisibility.isNull() || (*m_elmVisibility)[elmIdx]) { RigElementType eType = m_part->elementType(elmIdx); int faceCount = RigFemTypes::elmentFaceCount(eType); int elmQuadCount = 0; const int* elmNodeIndices = m_part->connectivities(elmIdx); for (int lfIdx = 0; lfIdx < faceCount; ++lfIdx) { int faceNodeCount = 0; const int* localElmNodeIndicesForFace = RigFemTypes::localElmNodeIndicesForFace(eType, lfIdx, &faceNodeCount); if (faceNodeCount == 4) { #if 0 ++elmQuadCount; int quad[4]; quad[0] = elmNodeIndices[elmLocalFaceIndices[0]]; quad[1] = elmNodeIndices[elmLocalFaceIndices[1]]; quad[2] = elmNodeIndices[elmLocalFaceIndices[2]]; quad[3] = elmNodeIndices[elmLocalFaceIndices[3]]; #endif // Needs to get rid of opposite faces vertices.push_back(nodeCoordinates[ elmNodeIndices[localElmNodeIndicesForFace[0]] ]); vertices.push_back(nodeCoordinates[ elmNodeIndices[localElmNodeIndicesForFace[1]] ]); vertices.push_back(nodeCoordinates[ elmNodeIndices[localElmNodeIndicesForFace[2]] ]); vertices.push_back(nodeCoordinates[ elmNodeIndices[localElmNodeIndicesForFace[3]] ]); m_quadVerticesToNodeIdx.push_back(elmNodeIndices[localElmNodeIndicesForFace[0]]); m_quadVerticesToNodeIdx.push_back(elmNodeIndices[localElmNodeIndicesForFace[1]]); m_quadVerticesToNodeIdx.push_back(elmNodeIndices[localElmNodeIndicesForFace[2]]); m_quadVerticesToNodeIdx.push_back(elmNodeIndices[localElmNodeIndicesForFace[3]]); m_quadVerticesToGlobalElmNodeIdx.push_back(m_part->elementNodeResultIdx(elmIdx, localElmNodeIndicesForFace[0])); m_quadVerticesToGlobalElmNodeIdx.push_back(m_part->elementNodeResultIdx(elmIdx, localElmNodeIndicesForFace[1])); m_quadVerticesToGlobalElmNodeIdx.push_back(m_part->elementNodeResultIdx(elmIdx, localElmNodeIndicesForFace[2])); m_quadVerticesToGlobalElmNodeIdx.push_back(m_part->elementNodeResultIdx(elmIdx, localElmNodeIndicesForFace[3])); } else { // Handle triangles and 6 node and 8 node faces } } } } m_quadVertices = new cvf::Vec3fArray; m_quadVertices->assign(vertices); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivFemPartGeometryGenerator::setElementVisibility(const cvf::UByteArray* cellVisibility) { m_elmVisibility = cellVisibility; }