///////////////////////////////////////////////////////////////////////////////// // // 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 "RivContourMapProjectionPartMgr.h" #include "RiaColorTools.h" #include "RiaFontCache.h" #include "ContourMap/RigContourMapGrid.h" #include "ContourMap/RigContourMapProjection.h" #include "ContourMap/RigContourPolygonsTools.h" #include "RivMeshLinesSourceInfo.h" #include "RivPartPriority.h" #include "RivScalarMapperUtils.h" #include "cafCategoryMapper.h" #include "cafEffectGenerator.h" #include "cafFixedAtlasFont.h" #include "cvfCamera.h" #include "cvfColor3.h" #include "cvfDrawableText.h" #include "cvfModelBasicList.h" #include "cvfPart.h" #include "cvfPrimitiveSetIndexedUInt.h" #include "cvfRay.h" #include "cvfRenderStateBlending.h" #include "cvfRenderStateTextureBindings.h" #include "cvfSampler.h" #include "cvfScalarMapper.h" #include "cvfShaderProgram.h" #include "cvfShaderProgramGenerator.h" #include "cvfShaderSourceProvider.h" #include "cvfTexture.h" #include "cvfTextureImage.h" #include "cvfViewport.h" #include "cvfqtUtils.h" #include #include #include //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RivContourMapProjectionPartMgr::RivContourMapProjectionPartMgr( caf::PdmObject* pdmObject ) { m_pdmObject = pdmObject; m_labelEffect = new cvf::Effect; cvf::ShaderProgramGenerator gen( "Texturing", cvf::ShaderSourceProvider::instance() ); gen.addVertexCode( cvf::ShaderSourceRepository::vs_Standard ); gen.addFragmentCode( cvf::ShaderSourceRepository::src_Texture ); gen.addFragmentCode( cvf::ShaderSourceRepository::fs_Unlit ); m_textureShaderProg = gen.generate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivContourMapProjectionPartMgr::appendProjectionToModel( cvf::ModelBasicList* model, const caf::DisplayCoordTransform* displayCoordTransform, const std::vector& vertices, const RigContourMapGrid& contourMapGrid, const cvf::Color3f& backgroundColor, cvf::ScalarMapper* scalarMapper ) const { cvf::ref mapPart = createProjectionMapPart( displayCoordTransform, vertices, contourMapGrid, backgroundColor, scalarMapper ); if ( mapPart.notNull() ) { model->addPart( mapPart.p() ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivContourMapProjectionPartMgr::appendPickPointVisToModel( cvf::ModelBasicList* model, const caf::DisplayCoordTransform* displayCoordTransform, const cvf::Vec2d& pickPoint, const RigContourMapGrid& contourMapGrid ) const { cvf::ref drawable = createPickPointVisDrawable( displayCoordTransform, pickPoint, contourMapGrid ); if ( drawable.notNull() && drawable->boundingBox().isValid() ) { caf::MeshEffectGenerator meshEffectGen( cvf::Color3::MAGENTA ); meshEffectGen.setLineWidth( 1.0f ); caf::MeshEffectGenerator::createAndConfigurePolygonOffsetRenderState( caf::PO_2 ); cvf::ref effect = meshEffectGen.generateCachedEffect(); cvf::ref part = new cvf::Part; part->setName( "RivContourMapProjectionPartMgr::appendPickPointVisToModel" ); part->setDrawable( drawable.p() ); part->setEffect( effect.p() ); part->setSourceInfo( new RivMeshLinesSourceInfo( m_pdmObject.p() ) ); model->addPart( part.p() ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivContourMapProjectionPartMgr::appendProjectionAsTexturedQuad( cvf::ModelBasicList* model, const caf::DisplayCoordTransform* displayCoordTransform, cvf::ScalarMapper* scalarMapper, const RigContourMapProjection& contourMapProjection, const RigContourMapGrid& contourMapGrid ) { auto expandedBB = contourMapGrid.expandedBoundingBox(); cvf::Vec3dArray domainCoords; domainCoords.reserve( 4 ); domainCoords.add( expandedBB.min() ); domainCoords.add( cvf::Vec3d( expandedBB.max().x(), expandedBB.min().y(), expandedBB.min().z() ) ); domainCoords.add( expandedBB.max() ); domainCoords.add( cvf::Vec3d( expandedBB.min().x(), expandedBB.max().y(), expandedBB.min().z() ) ); double zValueForContourMap = contourMapGrid.origin3d().z(); zValueForContourMap += 0.3 * zValueForContourMap; cvf::Vec3dArray displayCoords; displayCoords.reserve( 4 ); for ( int i = 0; i < 4; i++ ) { auto displayCoord = displayCoordTransform->transformToDisplayCoord( domainCoords[i] ); displayCoord.z() = zValueForContourMap; displayCoords.add( displayCoord ); } // Texture image and part can be cached for better performance auto textureImage = RivContourMapProjectionPartMgr::createTexture( &contourMapProjection, scalarMapper ); bool transparent = true; auto part = createSingleTexturedQuadPart( displayCoords, textureImage, transparent ); part->setSourceInfo( new RivObjectSourceInfo( m_pdmObject.p() ) ); part->setPriority( RivPartPriority::BaseLevel ); model->addPart( part.p() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RivContourMapProjectionPartMgr::createTextureCoords( const std::vector& values, cvf::ScalarMapper* scalarMapper ) const { cvf::ref textureCoords = new cvf::Vec2fArray( values.size() ); #pragma omp parallel for for ( int i = 0; i < (int)values.size(); ++i ) { if ( values[i] != std::numeric_limits::infinity() ) { cvf::Vec2f textureCoord = scalarMapper->mapToTextureCoord( values[i] ); textureCoord.y() = 0.0; ( *textureCoords )[i] = textureCoord; } else { ( *textureCoords )[i] = cvf::Vec2f( 0.0, 1.0 ); } } return textureCoords; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RivContourMapProjectionPartMgr::appendContourLinesToModel( const cvf::Camera* camera, cvf::ModelBasicList* model, const caf::DisplayCoordTransform* displayCoordTransform, const std::vector& contourLinePolygons, const RigContourMapGrid& contourMapGrid, cvf::ScalarMapper* mapper, bool showContourLines, bool showContourLabels, RiaNumberFormat::NumberFormatType numberFormat, int precision ) { if ( showContourLines ) { std::vector> labelBBoxes; std::vector> labelDrawables; if ( showContourLabels ) { labelDrawables = createContourLabels( camera, displayCoordTransform, &labelBBoxes, contourLinePolygons, contourMapGrid, mapper, numberFormat, precision ); } std::vector>> contourDrawablesForAllLevels = createContourPolygons( displayCoordTransform, labelBBoxes, contourLinePolygons, mapper, contourMapGrid ); std::vector tickValues; mapper->majorTickValues( &tickValues ); for ( size_t i = 0; i < contourDrawablesForAllLevels.size(); ++i ) { std::vector> contourDrawables = contourDrawablesForAllLevels[i]; cvf::Color3f backgroundColor( mapper->mapToColor( tickValues[i] ) ); cvf::Color3f lineColor = RiaColorTools::contrastColor( backgroundColor ); for ( cvf::ref contourDrawable : contourDrawables ) { if ( contourDrawable.notNull() && contourDrawable->boundingBox().isValid() ) { caf::MeshEffectGenerator meshEffectGen( lineColor ); meshEffectGen.setLineWidth( 1.0f ); caf::MeshEffectGenerator::createAndConfigurePolygonOffsetRenderState( caf::PO_1 ); cvf::ref effect = meshEffectGen.generateCachedEffect(); cvf::ref part = new cvf::Part; part->setName( "RivContourMapProjectionPartMgr::contourDrawable_mesh" ); part->setDrawable( contourDrawable.p() ); part->setEffect( effect.p() ); part->setPriority( RivPartPriority::MeshLines ); part->setSourceInfo( new RivMeshLinesSourceInfo( m_pdmObject.p() ) ); model->addPart( part.p() ); } } } if ( showContourLabels ) { for ( auto labelDrawableRef : labelDrawables ) { cvf::ref part = new cvf::Part; part->setName( "RivContourMapProjectionPartMgr::labelDrawableRef" ); part->setDrawable( labelDrawableRef.p() ); part->setEffect( m_labelEffect.p() ); part->setPriority( RivPartPriority::Text ); part->setSourceInfo( new RivMeshLinesSourceInfo( m_pdmObject.p() ) ); model->addPart( part.p() ); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RivContourMapProjectionPartMgr::createTextLabel( const cvf::Color3f& textColor, const cvf::Color3f& backgroundColor ) { auto font = RiaFontCache::getFont( RiaFontCache::FontSize::FONT_SIZE_10 ); cvf::ref labelDrawable = new cvf::DrawableText(); labelDrawable->setFont( font.p() ); labelDrawable->setCheckPosVisible( false ); labelDrawable->setUseDepthBuffer( true ); labelDrawable->setDrawBorder( false ); labelDrawable->setDrawBackground( false ); labelDrawable->setBackgroundColor( backgroundColor ); labelDrawable->setVerticalAlignment( cvf::TextDrawer::CENTER ); labelDrawable->setTextColor( textColor ); labelDrawable->setBorderColor( textColor ); return labelDrawable; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RivContourMapProjectionPartMgr::createProjectionMapPart( const caf::DisplayCoordTransform* displayCoordTransform, const std::vector& vertices, const RigContourMapGrid& contourMapGrid, const cvf::Color3f& backgroundColor, cvf::ScalarMapper* scalarMapper ) const { if ( vertices.size() < 3u ) { return cvf::ref(); } cvf::ref vertexArray = new cvf::Vec3fArray( vertices.size() ); cvf::ref faceList = new cvf::UIntArray( vertices.size() ); std::vector values( vertices.size() ); for ( uint i = 0; i < vertices.size(); ++i ) { cvf::Vec3d globalVertex = cvf::Vec3d( vertices[i].x(), vertices[i].y(), vertices[i].z() ) + contourMapGrid.origin3d(); cvf::Vec3f displayVertexPos( displayCoordTransform->transformToDisplayCoord( globalVertex ) ); ( *vertexArray )[i] = displayVertexPos; ( *faceList )[i] = i; values[i] = vertices[i].w(); } cvf::ref indexUInt = new cvf::PrimitiveSetIndexedUInt( cvf::PrimitiveType::PT_TRIANGLES, faceList.p() ); cvf::ref geo = new cvf::DrawableGeo; geo->addPrimitiveSet( indexUInt.p() ); geo->setVertexArray( vertexArray.p() ); cvf::ref part = new cvf::Part; part->setName( "RivContourMapProjectionPartMgr::createProjectionMapPart" ); part->setDrawable( geo.p() ); cvf::ref textureCoords = createTextureCoords( values, scalarMapper ); RivScalarMapperUtils::applyTextureResultsToPart( part.p(), textureCoords.p(), scalarMapper, 1.0f, caf::FC_NONE, true, backgroundColor ); part->setSourceInfo( new RivObjectSourceInfo( m_pdmObject.p() ) ); part->setPriority( RivPartPriority::BaseLevel ); return part; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector>> RivContourMapProjectionPartMgr::createContourPolygons( const caf::DisplayCoordTransform* displayCoordTransform, const std::vector>& labelBBoxes, const std::vector& contourLinePolygons, cvf::ScalarMapper* scalarMapper, const RigContourMapGrid& contourMapGrid ) const { std::vector tickValues; scalarMapper->majorTickValues( &tickValues ); std::vector>> contourDrawablesForAllLevels; contourDrawablesForAllLevels.resize( tickValues.size() ); for ( size_t i = 1; i < contourLinePolygons.size(); ++i ) { std::vector> contourDrawables; for ( size_t j = 0; j < contourLinePolygons[i].size(); ++j ) { if ( contourLinePolygons[i][j].vertices.empty() ) continue; // cvf::String::number does not allow precision on 'g' formats, so use Qt. QString qLabelText = QString::number( contourLinePolygons[i][j].value, 'g', 2 ); cvf::String labelText = cvfqt::Utils::toString( qLabelText ); size_t nVertices = contourLinePolygons[i][j].vertices.size(); std::vector displayLines; displayLines.reserve( nVertices * 2 ); for ( size_t v = 0; v < nVertices; ++v ) { cvf::Vec3d globalVertex1 = contourLinePolygons[i][j].vertices[v] + contourMapGrid.origin3d(); cvf::Vec3d displayVertex1 = displayCoordTransform->transformToDisplayCoord( globalVertex1 ); cvf::Vec3d globalVertex2; if ( v < nVertices - 1 ) globalVertex2 = contourLinePolygons[i][j].vertices[v + 1] + contourMapGrid.origin3d(); else globalVertex2 = contourLinePolygons[i][j].vertices[0] + contourMapGrid.origin3d(); cvf::Vec3d displayVertex2 = displayCoordTransform->transformToDisplayCoord( globalVertex2 ); cvf::BoundingBox lineBBox; lineBBox.add( displayVertex1 ); lineBBox.add( displayVertex2 ); bool addOriginalSegment = true; if ( !labelBBoxes.empty() ) { for ( const cvf::BoundingBox& existingBBox : labelBBoxes[i] ) { if ( lineBBox.intersects( existingBBox ) ) { if ( existingBBox.contains( displayVertex1 ) && existingBBox.contains( displayVertex2 ) ) { addOriginalSegment = false; } else { cvf::Vec3d dir = displayVertex2 - displayVertex1; cvf::Ray ray; ray.setOrigin( displayVertex1 ); ray.setDirection( dir.getNormalized() ); ray.setMaximumDistance( dir.length() ); if ( !existingBBox.contains( displayVertex1 ) ) { cvf::Vec3d intersection; bool hit = ray.boxIntersect( existingBBox, &intersection ); if ( hit ) { displayLines.push_back( cvf::Vec3f( displayVertex1 ) ); displayLines.push_back( cvf::Vec3f( intersection ) ); addOriginalSegment = false; } } if ( !existingBBox.contains( displayVertex2 ) ) { ray.setOrigin( displayVertex2 ); ray.setDirection( -ray.direction() ); cvf::Vec3d intersection; bool hit = ray.boxIntersect( existingBBox, &intersection ); if ( hit ) { displayLines.push_back( cvf::Vec3f( intersection ) ); displayLines.push_back( cvf::Vec3f( displayVertex2 ) ); addOriginalSegment = false; } } } } } } if ( addOriginalSegment ) { displayLines.push_back( cvf::Vec3f( displayVertex1 ) ); displayLines.push_back( cvf::Vec3f( displayVertex2 ) ); } } cvf::ref vertexArray = new cvf::Vec3fArray( displayLines ); std::vector indices; indices.reserve( vertexArray->size() ); for ( cvf::uint k = 0; k < vertexArray->size(); ++k ) { indices.push_back( k ); } cvf::ref indexedUInt = new cvf::PrimitiveSetIndexedUInt( cvf::PrimitiveType::PT_LINES ); cvf::ref indexArray = new cvf::UIntArray( indices ); indexedUInt->setIndices( indexArray.p() ); cvf::ref geo = new cvf::DrawableGeo; geo->addPrimitiveSet( indexedUInt.p() ); geo->setVertexArray( vertexArray.p() ); contourDrawables.push_back( geo ); } if ( !contourDrawables.empty() ) { contourDrawablesForAllLevels[i] = contourDrawables; } } return contourDrawablesForAllLevels; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector> RivContourMapProjectionPartMgr::createContourLabels( const cvf::Camera* camera, const caf::DisplayCoordTransform* displayCoordTransform, std::vector>* labelBBoxes, const std::vector& contourLinePolygons, const RigContourMapGrid& contourMapGrid, const cvf::ScalarMapper* scalarMapper, RiaNumberFormat::NumberFormatType numberFormat, int precision ) const { CVF_ASSERT( camera && displayCoordTransform && labelBBoxes ); std::vector> labelDrawables; labelBBoxes->clear(); labelBBoxes->resize( contourLinePolygons.size() ); if ( !camera->viewport() || camera->viewport()->width() == 0 ) return labelDrawables; if ( scalarMapper == nullptr ) return labelDrawables; if ( dynamic_cast( scalarMapper ) != nullptr ) return labelDrawables; std::vector tickValues; scalarMapper->majorTickValues( &tickValues ); const RigContourPolygonsTools::ContourPolygons* previousLevel = nullptr; for ( int64_t i = (int64_t)contourLinePolygons.size() - 1; i > 0; --i ) { cvf::Color3f backgroundColor( scalarMapper->mapToColor( tickValues[i] ) ); cvf::Color3f textColor = RiaColorTools::contrastColor( backgroundColor ); cvf::ref label = createTextLabel( textColor, backgroundColor ); for ( size_t j = 0; j < contourLinePolygons[i].size(); ++j ) { if ( contourLinePolygons[i][j].vertices.empty() ) continue; QString qLabelText = RiaNumberFormat::valueToText( contourLinePolygons[i][j].value, numberFormat, precision ); cvf::String labelText = cvfqt::Utils::toString( qLabelText ); size_t nVertices = contourLinePolygons[i][j].vertices.size(); size_t nLabels = nVertices; double distanceSinceLastLabel = std::numeric_limits::infinity(); for ( size_t l = 0; l < nLabels; ++l ) { size_t nVertex = ( nVertices * l ) / nLabels; size_t nextVertex = ( nVertex + 1 ) % nVertices; const cvf::Vec3d& localVertex1 = contourLinePolygons[i][j].vertices[nVertex]; const cvf::Vec3d& localVertex2 = contourLinePolygons[i][j].vertices[nextVertex]; cvf::Vec3d lineCenter = ( localVertex1 + localVertex2 ) * 0.5; double tolerance = 1.0e-2 * contourMapGrid.sampleSpacing(); if ( previousLevel && lineOverlapsWithPreviousContourLevel( lineCenter, *previousLevel, tolerance ) ) { continue; } cvf::Vec3d globalVertex1 = localVertex1 + contourMapGrid.origin3d(); cvf::Vec3d globalVertex2 = localVertex2 + contourMapGrid.origin3d(); cvf::Vec3d globalVertex = 0.5 * ( globalVertex1 + globalVertex2 ); cvf::Vec3d segment = globalVertex2 - globalVertex1; cvf::Vec3d displayVertex = displayCoordTransform->transformToDisplayCoord( globalVertex ); cvf::Vec3d windowVertex; camera->project( displayVertex, &windowVertex ); CVF_ASSERT( !windowVertex.isUndefined() ); displayVertex.z() += 10.0f; cvf::BoundingBox windowBBox = label->textBoundingBox( labelText, cvf::Vec3f::ZERO, cvf::Vec3f( segment.getNormalized() ) ); cvf::Vec3d displayBBoxMin, displayBBoxMax; camera->unproject( windowBBox.min() + windowVertex, &displayBBoxMin ); camera->unproject( windowBBox.max() + windowVertex, &displayBBoxMax ); CVF_ASSERT( !displayBBoxMin.isUndefined() ); CVF_ASSERT( !displayBBoxMax.isUndefined() ); cvf::BoundingBox displayBBox( displayBBoxMin - cvf::Vec3d::Z_AXIS * 20.0, displayBBoxMax + cvf::Vec3d::Z_AXIS * 20.0 ); cvf::Vec3d currentExtent = displayBBoxMax - displayBBoxMin; bool overlaps = false; if ( distanceSinceLastLabel < currentExtent.length() * 10.0 ) { overlaps = true; } if ( !overlaps ) { for ( auto boxVector : *labelBBoxes ) { for ( const cvf::BoundingBox& existingBBox : boxVector ) { // Assert on invalid bounding box seen on Linux if ( !displayBBox.isValid() || !existingBBox.isValid() ) continue; double dist = ( displayBBox.center() - existingBBox.center() ).length(); if ( dist < segment.length() || existingBBox.intersects( displayBBox ) ) { overlaps = true; break; } } } } if ( !overlaps ) { cvf::Vec3f displayVertexV( displayVertex ); CVF_ASSERT( !displayVertex.isUndefined() ); label->addText( labelText, displayVertexV, cvf::Vec3f( segment.getNormalized() ) ); labelBBoxes->at( i ).push_back( displayBBox ); distanceSinceLastLabel = 0.0; } else { distanceSinceLastLabel += segment.length(); } } } if ( label->numberOfTexts() != 0u ) { labelDrawables.push_back( label ); } previousLevel = &contourLinePolygons[i]; } return labelDrawables; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RivContourMapProjectionPartMgr::createPickPointVisDrawable( const caf::DisplayCoordTransform* displayCoordTransform, const cvf::Vec2d& pickPoint, const RigContourMapGrid& contourMapGrid ) const { std::vector pickPointPolygon = RigContourPolygonsTools::generatePickPointPolygon( pickPoint, contourMapGrid ); if ( pickPointPolygon.empty() ) { return nullptr; } cvf::ref vertexArray = new cvf::Vec3fArray( pickPointPolygon.size() ); for ( size_t i = 0; i < pickPointPolygon.size(); ++i ) { cvf::Vec3d globalPoint = pickPointPolygon[i] + contourMapGrid.origin3d(); cvf::Vec3f displayPoint( displayCoordTransform->transformToDisplayCoord( globalPoint ) ); ( *vertexArray )[i] = displayPoint; } cvf::ref geo = nullptr; if ( vertexArray->size() > 0u ) { std::vector indices; indices.reserve( vertexArray->size() ); for ( cvf::uint j = 0; j < vertexArray->size(); ++j ) { indices.push_back( j ); } cvf::ref indexedUInt = new cvf::PrimitiveSetIndexedUInt( cvf::PrimitiveType::PT_LINES ); cvf::ref indexArray = new cvf::UIntArray( indices ); indexedUInt->setIndices( indexArray.p() ); geo = new cvf::DrawableGeo; geo->addPrimitiveSet( indexedUInt.p() ); geo->setVertexArray( vertexArray.p() ); } return geo; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RivContourMapProjectionPartMgr::lineOverlapsWithPreviousContourLevel( const cvf::Vec3d& lineCenter, const RigContourPolygonsTools::ContourPolygons& previousLevel, double tolerance ) { return RigContourPolygonsTools::lineOverlapsWithContourPolygons( lineCenter, previousLevel, tolerance ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RivContourMapProjectionPartMgr::createXYPlaneQuadGeoWithTexCoords( const cvf::Vec3dArray& cornerPoints ) { cvf::ref vertices = new cvf::Vec3fArray; vertices->reserve( 4 ); for ( const auto& v : cornerPoints ) { vertices->add( cvf::Vec3f( v ) ); } cvf::ref texCoords = new cvf::Vec2fArray; texCoords->reserve( 4 ); texCoords->add( cvf::Vec2f( 0, 0 ) ); texCoords->add( cvf::Vec2f( 1, 0 ) ); texCoords->add( cvf::Vec2f( 1, 1 ) ); texCoords->add( cvf::Vec2f( 0, 1 ) ); cvf::ref geo = new cvf::DrawableGeo; geo->setVertexArray( vertices.p() ); geo->setTextureCoordArray( texCoords.p() ); cvf::ref indices = new cvf::UIntArray; indices->reserve( 6 ); for ( uint i : { 0, 1, 2, 0, 2, 3 } ) { indices->add( i ); } cvf::ref primSet = new cvf::PrimitiveSetIndexedUInt( cvf::PT_TRIANGLES ); primSet->setIndices( indices.p() ); geo->addPrimitiveSet( primSet.p() ); geo->computeNormals(); return geo; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::ref RivContourMapProjectionPartMgr::createSingleTexturedQuadPart( const cvf::Vec3dArray& cornerPoints, cvf::ref image, bool transparent ) { cvf::ref part = new cvf::Part; cvf::ref geo = createXYPlaneQuadGeoWithTexCoords( cornerPoints ); geo->computeNormals(); cvf::ref eff = new cvf::Effect; bool surfaceEffect = false; if ( surfaceEffect ) { caf::SurfaceEffectGenerator geometryEffgen( cvf::Color3f::YELLOW, caf::PO_1 ); eff = geometryEffgen.generateCachedEffect(); } else { cvf::ref texture = new cvf::Texture( image.p() ); cvf::ref sampler = new cvf::Sampler; sampler->setMinFilter( cvf::Sampler::LINEAR ); sampler->setMagFilter( cvf::Sampler::NEAREST ); sampler->setWrapModeS( cvf::Sampler::CLAMP_TO_EDGE ); sampler->setWrapModeT( cvf::Sampler::CLAMP_TO_EDGE ); cvf::ref textureBindings = new cvf::RenderStateTextureBindings; textureBindings->addBinding( texture.p(), sampler.p(), "u_texture2D" ); eff->setRenderState( textureBindings.p() ); eff->setShaderProgram( m_textureShaderProg.p() ); if ( transparent ) { part->setPriority( RivPartPriority::PartType::TransparentSeismic ); cvf::ref blending = new cvf::RenderStateBlending; blending->configureTransparencyBlending(); eff->setRenderState( blending.p() ); } } part->setDrawable( geo.p() ); part->updateBoundingBox(); part->setEffect( eff.p() ); return part; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QImage RivContourMapProjectionPartMgr::createImage( const RigContourMapProjection* contourMapProjection, cvf::ScalarMapper* scalarMapper ) { if ( !contourMapProjection || !scalarMapper ) return {}; auto vertexSizeIJ = contourMapProjection->numberOfVerticesIJ(); int width = static_cast( vertexSizeIJ.x() ); int height = static_cast( vertexSizeIJ.y() ); QImage image( width, height, QImage::Format_ARGB32 ); auto filteredValues = contourMapProjection->aggregatedVertexResultsFiltered(); for ( int y = 0; y < height; ++y ) { for ( int x = 0; x < width; ++x ) { auto index = contourMapProjection->vertexIndex( x, y ); double valueAtVertex = filteredValues[index]; auto color = scalarMapper->mapToColor( valueAtVertex ); const int transparency = 255; image.setPixel( x, height - y - 1, qRgba( color.r(), color.g(), color.b(), transparency ) ); } } return image; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::TextureImage* RivContourMapProjectionPartMgr::createTexture( const RigContourMapProjection* contourMapProjection, cvf::ScalarMapper* scalarMapper ) { if ( !contourMapProjection || !scalarMapper ) return {}; auto vertexSizeIJ = contourMapProjection->numberOfVerticesIJ(); int width = static_cast( vertexSizeIJ.x() ); int height = static_cast( vertexSizeIJ.y() ); cvf::TextureImage* textureImage = new cvf::TextureImage(); textureImage->allocate( width, height ); auto dataValues = contourMapProjection->aggregatedVertexResultsFiltered(); for ( int y = 0; y < height; ++y ) { for ( int x = 0; x < width; ++x ) { size_t index = contourMapProjection->vertexIndex( x, y ); double valueAtVertex = dataValues[index]; auto color = scalarMapper->mapToColor( valueAtVertex ); int transparency = 0; if ( valueAtVertex != std::numeric_limits::infinity() ) { transparency = 255; } textureImage->setPixel( x, y, cvf::Color4ub( color, transparency ) ); } } return textureImage; }