ResInsight/ApplicationLibCode/ModelVisualization/RivCellEdgeGeometryUtils.cpp
Magne Sjaastad f8c5cf389f
clang-format: Set column width to 140
* Set column width to 140
* Use c++20
* Remove redundant virtual
2023-02-26 10:48:40 +01:00

357 lines
18 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA
// Copyright (C) Ceetron Solutions AS
//
// 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RivCellEdgeGeometryUtils.h"
#include "RigCaseCellResultsData.h"
#include "RigCellEdgeResultAccessor.h"
#include "RigEclipseCaseData.h"
#include "RigGridBase.h"
#include "RigResultAccessor.h"
#include "RigResultAccessorFactory.h"
#include "RimCellEdgeColors.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseView.h"
#include "RimRegularLegendConfig.h"
#include "RimSimWellInViewCollection.h"
#include "RimTernaryLegendConfig.h"
#include "RivTernaryTextureCoordsCreator.h"
#include "cvfDrawableGeo.h"
#include "cvfScalarMapper.h"
#include "cvfVertexAttribute.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivCellEdgeGeometryUtils::addCellEdgeResultsToDrawableGeo( size_t timeStepIndex,
RimEclipseCellColors* cellResultColors,
RimCellEdgeColors* cellEdgeResultColors,
const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper,
cvf::DrawableGeo* geo,
size_t gridIndex,
bool useDefaultValueForHugeVals,
float opacityLevel )
{
RigEclipseCaseData* eclipseCase = cellResultColors->reservoirView()->eclipseCase()->eclipseCaseData();
CVF_ASSERT( eclipseCase != nullptr );
// Create result access objects
cvf::ref<RigResultAccessor> cellCenterDataAccessObject =
createCellCenterResultAccessor( cellResultColors, timeStepIndex, eclipseCase, eclipseCase->grid( gridIndex ) );
cvf::ref<RigResultAccessor> cellEdgeResultAccessor =
createCellEdgeResultAccessor( cellResultColors, cellEdgeResultColors, timeStepIndex, eclipseCase, eclipseCase->grid( gridIndex ) );
size_t vertexCount = geo->vertexArray()->size();
size_t quadCount = vertexCount / 4;
cvf::ref<cvf::Vec2fArray> localCoords = new cvf::Vec2fArray;
localCoords->resize( vertexCount );
cvf::ref<cvf::IntArray> faceIndexArray = new cvf::IntArray;
faceIndexArray->resize( vertexCount );
cvf::ref<cvf::FloatArray> cellColorTextureCoordArray = new cvf::FloatArray;
cellColorTextureCoordArray->resize( vertexCount );
// Build six cell face color arrays
cvf::Collection<cvf::FloatArray> cellEdgeColorTextureCoordsArrays;
size_t idx;
for ( idx = 0; idx < 6; idx++ )
{
cvf::ref<cvf::FloatArray> colorArray = new cvf::FloatArray;
colorArray->resize( vertexCount );
cellEdgeColorTextureCoordsArrays.push_back( colorArray.p() );
}
cvf::ScalarMapper* cellResultScalarMapper = cellResultColors->legendConfig()->scalarMapper();
cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultColors->legendConfig()->scalarMapper();
double ignoredScalarValue = cellEdgeResultColors->ignoredScalarValue();
const std::vector<cvf::ubyte>* isWellPipeVisible = nullptr;
cvf::cref<cvf::UIntArray> gridCellToWellindexMap;
if ( opacityLevel < 1.0f )
{
isWellPipeVisible = &( cellResultColors->reservoirView()->wellCollection()->resultWellGeometryVisibilities( timeStepIndex ) );
gridCellToWellindexMap = eclipseCase->gridCellToResultWellIndex( gridIndex );
}
#pragma omp parallel for
for ( int quadIdx = 0; quadIdx < static_cast<int>( quadCount ); quadIdx++ )
{
localCoords->set( quadIdx * 4 + 0, cvf::Vec2f( 0, 0 ) );
localCoords->set( quadIdx * 4 + 1, cvf::Vec2f( 1, 0 ) );
localCoords->set( quadIdx * 4 + 2, cvf::Vec2f( 1, 1 ) );
localCoords->set( quadIdx * 4 + 3, cvf::Vec2f( 0, 1 ) );
faceIndexArray->set( quadIdx * 4 + 0, quadToCellFaceMapper->cellFace( quadIdx ) );
faceIndexArray->set( quadIdx * 4 + 1, quadToCellFaceMapper->cellFace( quadIdx ) );
faceIndexArray->set( quadIdx * 4 + 2, quadToCellFaceMapper->cellFace( quadIdx ) );
faceIndexArray->set( quadIdx * 4 + 3, quadToCellFaceMapper->cellFace( quadIdx ) );
size_t cellIndex = quadToCellFaceMapper->cellIndex( quadIdx );
{
cvf::StructGridInterface::FaceType cellFace = quadToCellFaceMapper->cellFace( quadIdx );
double scalarValue = cellCenterDataAccessObject->cellFaceScalar( cellIndex, cellFace );
{
float cellColorTextureCoord = 0.5f; // If no results exists, the texture will have a special color
if ( useDefaultValueForHugeVals || scalarValue != HUGE_VAL )
{
if ( scalarValue != HUGE_VAL )
{
cellColorTextureCoord = cellResultScalarMapper->mapToTextureCoord( scalarValue )[0];
}
// If we are dealing with wellcells, the default is transparent.
// we need to make cells opaque if there are no wellpipe through them.
if ( opacityLevel < 1.0f )
{
cvf::uint wellIndex = gridCellToWellindexMap->get( cellIndex );
if ( wellIndex != cvf::UNDEFINED_UINT )
{
if ( !( *isWellPipeVisible )[wellIndex] )
{
cellColorTextureCoord += 2.0f; // The shader must interpret values in the range 2-3 as
// "opaque"
}
}
}
}
else
{
cellColorTextureCoord = -1.0f; // Undefined texture coord. Shader handles this.
}
cellColorTextureCoordArray->set( quadIdx * 4 + 0, cellColorTextureCoord );
cellColorTextureCoordArray->set( quadIdx * 4 + 1, cellColorTextureCoord );
cellColorTextureCoordArray->set( quadIdx * 4 + 2, cellColorTextureCoord );
cellColorTextureCoordArray->set( quadIdx * 4 + 3, cellColorTextureCoord );
}
}
for ( size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++ )
{
float edgeColor = -1.0f; // Undefined texture coord. Shader handles this.
double scalarValue =
cellEdgeResultAccessor->cellFaceScalar( cellIndex, static_cast<cvf::StructGridInterface::FaceType>( cubeFaceIdx ) );
if ( !hideScalarValue( scalarValue, ignoredScalarValue, 1e-2 ) )
{
edgeColor = edgeResultScalarMapper->mapToTextureCoord( scalarValue )[0];
}
cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at( cubeFaceIdx );
colArr->set( quadIdx * 4 + 0, edgeColor );
colArr->set( quadIdx * 4 + 1, edgeColor );
colArr->set( quadIdx * 4 + 2, edgeColor );
colArr->set( quadIdx * 4 + 3, edgeColor );
}
}
geo->setVertexAttribute( new cvf::Vec2fVertexAttribute( "a_localCoord", localCoords.p() ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorCell", cellColorTextureCoordArray.p() ) );
cvf::ref<cvf::IntVertexAttributeDirect> faceIntAttribute = new cvf::IntVertexAttributeDirect( "a_face", faceIndexArray.p() );
geo->setVertexAttribute( faceIntAttribute.p() );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorPosI", cellEdgeColorTextureCoordsArrays.at( 0 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorNegI", cellEdgeColorTextureCoordsArrays.at( 1 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorPosJ", cellEdgeColorTextureCoordsArrays.at( 2 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorNegJ", cellEdgeColorTextureCoordsArrays.at( 3 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorPosK", cellEdgeColorTextureCoordsArrays.at( 4 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorNegK", cellEdgeColorTextureCoordsArrays.at( 5 ) ) );
}
bool RivCellEdgeGeometryUtils::hideScalarValue( double scalarValue, double scalarValueToHide, double tolerance )
{
return ( scalarValue == HUGE_VAL || cvf::Math::abs( scalarValue - scalarValueToHide ) <= scalarValueToHide * tolerance );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RivCellEdgeGeometryUtils::addTernaryCellEdgeResultsToDrawableGeo( size_t timeStepIndex,
RimEclipseCellColors* cellResultColors,
RimCellEdgeColors* cellEdgeResultColors,
const cvf::StructGridQuadToCellFaceMapper* quadToCellFaceMapper,
cvf::DrawableGeo* geo,
size_t gridIndex,
float opacityLevel )
{
RigEclipseCaseData* eclipseCase = cellResultColors->reservoirView()->eclipseCase()->eclipseCaseData();
CVF_ASSERT( eclipseCase != nullptr );
cvf::ref<RigResultAccessor> cellEdgeResultAccessor =
createCellEdgeResultAccessor( cellResultColors, cellEdgeResultColors, timeStepIndex, eclipseCase, eclipseCase->grid( gridIndex ) );
size_t vertexCount = geo->vertexArray()->size();
size_t quadCount = vertexCount / 4;
cvf::ref<cvf::Vec2fArray> localCoords = new cvf::Vec2fArray;
localCoords->resize( vertexCount );
cvf::ref<cvf::IntArray> faceIndexArray = new cvf::IntArray;
faceIndexArray->resize( vertexCount );
cvf::ref<cvf::Vec2fArray> vCellColorTextureCoordArray = new cvf::Vec2fArray;
vCellColorTextureCoordArray->resize( vertexCount );
// Build six cell face color arrays
cvf::Collection<cvf::FloatArray> cellEdgeColorTextureCoordsArrays;
size_t idx;
for ( idx = 0; idx < 6; idx++ )
{
cvf::ref<cvf::FloatArray> colorArray = new cvf::FloatArray;
colorArray->resize( vertexCount );
cellEdgeColorTextureCoordsArrays.push_back( colorArray.p() );
}
cvf::ScalarMapper* edgeResultScalarMapper = cellEdgeResultColors->legendConfig()->scalarMapper();
double ignoredScalarValue = cellEdgeResultColors->ignoredScalarValue();
RivTernaryTextureCoordsCreator texturer( cellResultColors,
cellResultColors->ternaryLegendConfig(),
cellResultColors->reservoirView()->wellCollection(),
timeStepIndex,
gridIndex,
quadToCellFaceMapper );
texturer.createTextureCoords( vCellColorTextureCoordArray.p() );
#pragma omp parallel for
for ( int quadIdx = 0; quadIdx < static_cast<int>( quadCount ); quadIdx++ )
{
localCoords->set( quadIdx * 4 + 0, cvf::Vec2f( 0, 0 ) );
localCoords->set( quadIdx * 4 + 1, cvf::Vec2f( 1, 0 ) );
localCoords->set( quadIdx * 4 + 2, cvf::Vec2f( 1, 1 ) );
localCoords->set( quadIdx * 4 + 3, cvf::Vec2f( 0, 1 ) );
faceIndexArray->set( quadIdx * 4 + 0, quadToCellFaceMapper->cellFace( quadIdx ) );
faceIndexArray->set( quadIdx * 4 + 1, quadToCellFaceMapper->cellFace( quadIdx ) );
faceIndexArray->set( quadIdx * 4 + 2, quadToCellFaceMapper->cellFace( quadIdx ) );
faceIndexArray->set( quadIdx * 4 + 3, quadToCellFaceMapper->cellFace( quadIdx ) );
size_t cellIndex = quadToCellFaceMapper->cellIndex( quadIdx );
for ( size_t cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++ )
{
float edgeColor = -1.0f; // Undefined texture coord. Shader handles this.
double scalarValue =
cellEdgeResultAccessor->cellFaceScalar( cellIndex, static_cast<cvf::StructGridInterface::FaceType>( cubeFaceIdx ) );
if ( !hideScalarValue( scalarValue, ignoredScalarValue, 1e-2 ) )
{
edgeColor = edgeResultScalarMapper->mapToTextureCoord( scalarValue )[0];
}
cvf::FloatArray* colArr = cellEdgeColorTextureCoordsArrays.at( cubeFaceIdx );
colArr->set( quadIdx * 4 + 0, edgeColor );
colArr->set( quadIdx * 4 + 1, edgeColor );
colArr->set( quadIdx * 4 + 2, edgeColor );
colArr->set( quadIdx * 4 + 3, edgeColor );
}
}
geo->setVertexAttribute( new cvf::Vec2fVertexAttribute( "a_localCoord", localCoords.p() ) );
geo->setVertexAttribute( new cvf::Vec2fVertexAttribute( "a_cellTextureCoord", vCellColorTextureCoordArray.p() ) );
cvf::ref<cvf::IntVertexAttributeDirect> faceIntAttribute = new cvf::IntVertexAttributeDirect( "a_face", faceIndexArray.p() );
geo->setVertexAttribute( faceIntAttribute.p() );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorPosI", cellEdgeColorTextureCoordsArrays.at( 0 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorNegI", cellEdgeColorTextureCoordsArrays.at( 1 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorPosJ", cellEdgeColorTextureCoordsArrays.at( 2 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorNegJ", cellEdgeColorTextureCoordsArrays.at( 3 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorPosK", cellEdgeColorTextureCoordsArrays.at( 4 ) ) );
geo->setVertexAttribute( new cvf::FloatVertexAttribute( "a_colorNegK", cellEdgeColorTextureCoordsArrays.at( 5 ) ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigResultAccessor> RivCellEdgeGeometryUtils::createCellEdgeResultAccessor( RimEclipseCellColors* cellResultColors,
RimCellEdgeColors* cellEdgeResultColors,
size_t timeStepIndex,
RigEclipseCaseData* eclipseCase,
const RigGridBase* grid )
{
cvf::ref<RigCellEdgeResultAccessor> cellEdgeResultAccessor = new RigCellEdgeResultAccessor();
auto resultAddresses = cellEdgeResultColors->resultAddresses();
std::vector<RimCellEdgeMetaData> metaData;
cellEdgeResultColors->cellEdgeMetaData( &metaData );
size_t cubeFaceIdx;
for ( cubeFaceIdx = 0; cubeFaceIdx < 6; cubeFaceIdx++ )
{
size_t adjustedTimeStep = timeStepIndex;
if ( metaData[cubeFaceIdx].m_isStatic )
{
adjustedTimeStep = 0;
}
RiaDefines::PorosityModelType porosityModel = cellResultColors->porosityModel();
cvf::ref<RigResultAccessor> daObj = RigResultAccessorFactory::createFromResultAddress( eclipseCase,
grid->gridIndex(),
porosityModel,
adjustedTimeStep,
resultAddresses[cubeFaceIdx] );
cellEdgeResultAccessor->setDataAccessObjectForFace( static_cast<cvf::StructGridInterface::FaceType>( cubeFaceIdx ), daObj.p() );
}
return cellEdgeResultAccessor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigResultAccessor> RivCellEdgeGeometryUtils::createCellCenterResultAccessor( RimEclipseCellColors* cellResultColors,
size_t timeStepIndex,
RigEclipseCaseData* eclipseCase,
const RigGridBase* grid )
{
cvf::ref<RigResultAccessor> resultAccessor = nullptr;
if ( cellResultColors->hasResult() )
{
resultAccessor =
RigResultAccessorFactory::createFromResultDefinition( eclipseCase, grid->gridIndex(), timeStepIndex, cellResultColors );
}
if ( resultAccessor.isNull() )
{
resultAccessor = new RigHugeValResultAccessor;
}
return resultAccessor;
}