///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2018- Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RivWellConnectionFactorGeometryGenerator.h" #include "cafEffectGenerator.h" #include "cvfArray.h" #include "cvfDrawableGeo.h" #include "cvfGeometryTools.h" #include "cvfPart.h" #include "cvfPrimitiveSetIndexedUInt.h" #include "cvfScalarMapper.h" #include // Needed for HUGE_VAL on Linux //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RivWellConnectionFactorGeometryGenerator::RivWellConnectionFactorGeometryGenerator( std::vector& completionVizData, float radius ) : m_completionVizData( completionVizData ) , m_radius( radius ) , m_trianglesPerConnection( 0 ) { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RivWellConnectionFactorGeometryGenerator::~RivWellConnectionFactorGeometryGenerator() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RivWellConnectionFactorGeometryGenerator::createSurfacePart( const cvf::ScalarMapper* scalarMapper, bool disableLighting ) { if ( !scalarMapper ) return nullptr; cvf::ref drawable = createSurfaceGeometry(); if ( drawable.notNull() ) { cvf::ref part = new cvf::Part; part->setName( "RivWellConnectionFactorGeometryGenerator" ); part->setDrawable( drawable.p() ); // Compute texture coords cvf::ref textureCoords = new cvf::Vec2fArray(); { textureCoords->reserve( drawable->vertexArray()->size() ); size_t verticesPerItem = drawable->vertexArray()->size() / m_completionVizData.size(); textureCoords->setAll( cvf::Vec2f( 0.5f, 1.0f ) ); for ( const auto& item : m_completionVizData ) { cvf::Vec2f textureCoord = cvf::Vec2f( 0.5f, 1.0f ); if ( item.m_connectionFactor != HUGE_VAL ) { textureCoord = scalarMapper->mapToTextureCoord( item.m_connectionFactor ); } for ( size_t i = 0; i < verticesPerItem; i++ ) { textureCoords->add( textureCoord ); } } } drawable->setTextureCoordArray( textureCoords.p() ); caf::ScalarMapperEffectGenerator effGen( scalarMapper, caf::PO_1 ); effGen.disableLighting( disableLighting ); cvf::ref eff = effGen.generateCachedEffect(); part->setEffect( eff.p() ); return part; } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RivWellConnectionFactorGeometryGenerator::createSurfaceGeometry() { std::vector verticesForOneObject; std::vector indicesForOneObject; RivWellConnectionFactorGeometryGenerator::createSimplifiedStarGeometry( &verticesForOneObject, &indicesForOneObject, m_radius, m_radius * 0.3f ); m_trianglesPerConnection = indicesForOneObject.size() / 3; cvf::ref vertices = new cvf::Vec3fArray; cvf::ref indices = new cvf::UIntArray; auto indexCount = m_completionVizData.size() * indicesForOneObject.size(); auto vertexCount = m_completionVizData.size() * verticesForOneObject.size(); indices->reserve( indexCount ); vertices->reserve( vertexCount ); for ( const auto& item : m_completionVizData ) { auto rotMatrix = cvf::Mat4f( cvf::GeometryTools::rotationMatrixBetweenVectors( cvf::Vec3d::Y_AXIS, item.m_direction ) ); cvf::uint indexOffset = static_cast( vertices->size() ); for ( const auto& v : verticesForOneObject ) { auto rotatedPoint = v.getTransformedPoint( rotMatrix ); vertices->add( cvf::Vec3f( item.m_anchor ) + rotatedPoint ); } for ( const auto& i : indicesForOneObject ) { indices->add( i + indexOffset ); } } cvf::ref drawable = new cvf::DrawableGeo(); drawable->setVertexArray( vertices.p() ); drawable->addPrimitiveSet( new cvf::PrimitiveSetIndexedUInt( cvf::PT_TRIANGLES, indices.p() ) ); drawable->computeNormals(); return drawable; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- double RivWellConnectionFactorGeometryGenerator::connectionFactor( cvf::uint triangleIndex ) const { size_t connectionIndex = mapFromTriangleToConnectionIndex( triangleIndex ); return m_completionVizData[connectionIndex].m_connectionFactor; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RivWellConnectionFactorGeometryGenerator::globalCellIndexFromTriangleIndex( cvf::uint triangleIndex ) const { size_t connectionIndex = mapFromTriangleToConnectionIndex( triangleIndex ); return m_completionVizData[connectionIndex].m_globalCellIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RivWellConnectionFactorGeometryGenerator::mapFromTriangleToConnectionIndex( cvf::uint triangleIndex ) const { if ( m_trianglesPerConnection == 0 ) return 0; size_t connectionIndex = triangleIndex / m_trianglesPerConnection; return connectionIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivWellConnectionFactorGeometryGenerator::createStarGeometry( std::vector* vertices, std::vector* indices, float radius, float thickness ) { auto p0 = cvf::Vec3f::Z_AXIS * radius; auto p2 = cvf::Vec3f::X_AXIS * -radius; auto p4 = -p0; auto p6 = -p2; float innerFactor = 5.0f; auto p1 = ( p0 + p2 ) / innerFactor; auto p3 = ( p2 + p4 ) / innerFactor; auto p5 = -p1; auto p7 = -p3; auto p8 = cvf::Vec3f::Y_AXIS * thickness; auto p9 = -p8; vertices->push_back( p0 ); vertices->push_back( p1 ); vertices->push_back( p2 ); vertices->push_back( p3 ); vertices->push_back( p4 ); vertices->push_back( p5 ); vertices->push_back( p6 ); vertices->push_back( p7 ); vertices->push_back( p8 ); vertices->push_back( p9 ); // Top indices->push_back( 0 ); indices->push_back( 1 ); indices->push_back( 8 ); indices->push_back( 0 ); indices->push_back( 8 ); indices->push_back( 7 ); indices->push_back( 0 ); indices->push_back( 9 ); indices->push_back( 1 ); indices->push_back( 0 ); indices->push_back( 7 ); indices->push_back( 9 ); // Left indices->push_back( 2 ); indices->push_back( 3 ); indices->push_back( 8 ); indices->push_back( 2 ); indices->push_back( 8 ); indices->push_back( 1 ); indices->push_back( 2 ); indices->push_back( 9 ); indices->push_back( 3 ); indices->push_back( 2 ); indices->push_back( 1 ); indices->push_back( 9 ); // Bottom indices->push_back( 4 ); indices->push_back( 5 ); indices->push_back( 8 ); indices->push_back( 4 ); indices->push_back( 8 ); indices->push_back( 3 ); indices->push_back( 4 ); indices->push_back( 9 ); indices->push_back( 5 ); indices->push_back( 4 ); indices->push_back( 3 ); indices->push_back( 9 ); // Right indices->push_back( 6 ); indices->push_back( 7 ); indices->push_back( 8 ); indices->push_back( 6 ); indices->push_back( 8 ); indices->push_back( 5 ); indices->push_back( 6 ); indices->push_back( 9 ); indices->push_back( 7 ); indices->push_back( 6 ); indices->push_back( 5 ); indices->push_back( 9 ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivWellConnectionFactorGeometryGenerator::createSimplifiedStarGeometry( std::vector* vertices, std::vector* indices, float radius, float thickness ) { // Suggested improvement // As the nodes are duplicated, it will be possible create only vertices and then use // DrawableGeo::setFromTriangleVertexArray auto p0 = cvf::Vec3f::Y_AXIS * thickness; auto p1 = -p0; auto p2 = cvf::Vec3f::Z_AXIS * radius; auto p3 = p0; auto p4 = p1; auto p5 = cvf::Vec3f::X_AXIS * radius; auto p6 = p0; auto p7 = p1; auto p8 = -p2; auto p9 = p0; auto p10 = p1; auto p11 = -p5; vertices->push_back( p0 ); vertices->push_back( p1 ); vertices->push_back( p2 ); vertices->push_back( p3 ); vertices->push_back( p4 ); vertices->push_back( p5 ); vertices->push_back( p6 ); vertices->push_back( p7 ); vertices->push_back( p8 ); vertices->push_back( p9 ); vertices->push_back( p10 ); vertices->push_back( p11 ); indices->push_back( 0 ); indices->push_back( 1 ); indices->push_back( 2 ); indices->push_back( 3 ); indices->push_back( 4 ); indices->push_back( 5 ); indices->push_back( 6 ); indices->push_back( 7 ); indices->push_back( 8 ); indices->push_back( 9 ); indices->push_back( 10 ); indices->push_back( 11 ); }