3D-Viewer: implements opacity property for 3D models

fixes #2087
This commit is contained in:
Mario Luzeiro 2020-04-25 01:08:55 +01:00 committed by Jon Evans
parent 960ce4aa67
commit 5a7f875602
6 changed files with 112 additions and 39 deletions

View File

@ -313,7 +313,7 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
m_ogl_3dmodel->BeginDrawMulti();
m_ogl_3dmodel->Draw_opaque();
m_ogl_3dmodel->Draw_transparent();
m_ogl_3dmodel->Draw_transparent( 1.0f );
m_ogl_3dmodel->EndDrawMulti();

View File

@ -361,27 +361,27 @@ void C3D_RENDER_OGL_LEGACY::set_layer_material( PCB_LAYER_ID aLayerID )
{
case B_Mask:
m_materials.m_SolderMaskBot.m_Diffuse = get_layer_color( aLayerID );
OGL_SetMaterial( m_materials.m_SolderMaskBot );
OGL_SetMaterial( m_materials.m_SolderMaskBot, 1.0f );
break;
case F_Mask:
m_materials.m_SolderMaskTop.m_Diffuse = get_layer_color( aLayerID );
OGL_SetMaterial( m_materials.m_SolderMaskTop );
OGL_SetMaterial( m_materials.m_SolderMaskTop, 1.0f );
break;
case B_Paste:
case F_Paste:
m_materials.m_Paste.m_Diffuse = get_layer_color( aLayerID );
OGL_SetMaterial( m_materials.m_Paste );
OGL_SetMaterial( m_materials.m_Paste, 1.0f );
break;
case B_SilkS:
m_materials.m_SilkSBot.m_Diffuse = get_layer_color( aLayerID );
OGL_SetMaterial( m_materials.m_SilkSBot );
OGL_SetMaterial( m_materials.m_SilkSBot, 1.0f );
break;
case F_SilkS:
m_materials.m_SilkSTop.m_Diffuse = get_layer_color( aLayerID );
OGL_SetMaterial( m_materials.m_SilkSTop );
OGL_SetMaterial( m_materials.m_SilkSTop, 1.0f );
break;
case B_Adhes:
@ -409,12 +409,12 @@ void C3D_RENDER_OGL_LEGACY::set_layer_material( PCB_LAYER_ID aLayerID )
m_materials.m_Plastic.m_Shininess = 0.078125f * 128.0f;
m_materials.m_Plastic.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
OGL_SetMaterial( m_materials.m_Plastic );
OGL_SetMaterial( m_materials.m_Plastic, 1.0f );
break;
default:
m_materials.m_Copper.m_Diffuse = get_layer_color( aLayerID );
OGL_SetMaterial( m_materials.m_Copper );
OGL_SetMaterial( m_materials.m_Copper, 1.0f );
break;
}
@ -589,6 +589,7 @@ bool C3D_RENDER_OGL_LEGACY::Redraw(
glClearStencil( 0x00 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
OGL_ResetTextureStateDefaults();
// Draw the background ( rectangle with color gradient)
// /////////////////////////////////////////////////////////////////////////
@ -659,7 +660,7 @@ bool C3D_RENDER_OGL_LEGACY::Redraw(
m_ogl_disp_list_board->ApplyScalePosition( -m_boardAdapter.GetEpoxyThickness3DU() / 2.0f,
m_boardAdapter.GetEpoxyThickness3DU() );
OGL_SetMaterial( m_materials.m_EpoxyBoard );
OGL_SetMaterial( m_materials.m_EpoxyBoard, 1.0f );
m_ogl_disp_list_board->SetItIsTransparent( false );
@ -688,7 +689,7 @@ bool C3D_RENDER_OGL_LEGACY::Redraw(
}
else
{
OGL_SetMaterial( m_materials.m_GrayMaterial );
OGL_SetMaterial( m_materials.m_GrayMaterial, 1.0f );
}
if( (!( skipRenderVias || skipRenderHoles ) ) && m_ogl_disp_list_via )
@ -860,6 +861,8 @@ bool C3D_RENDER_OGL_LEGACY::Redraw(
// Render 3D Models (Transparent)
// /////////////////////////////////////////////////////////////////////////
// !TODO: this can be optimized. If there are no transparent models (or no opacity),
// then there is no need to make this function call.
render_3D_models( false, true );
render_3D_models( true, true );
@ -1180,8 +1183,8 @@ void C3D_RENDER_OGL_LEGACY::render_3D_module( const MODULE* module,
{
if( const C_OGL_3DMODEL *modelPtr = cache_i->second )
{
if( ( (!aRenderTransparentOnly) && modelPtr->Have_opaque() ) ||
( aRenderTransparentOnly && modelPtr->Have_transparent() ) )
if( ( (!aRenderTransparentOnly) && modelPtr->Have_opaque() && (sM.m_Opacity >= 1.0 ) ) ||
( aRenderTransparentOnly && ( modelPtr->Have_transparent() || (sM.m_Opacity < 1.0 ) ) ) )
{
glPushMatrix();
@ -1196,7 +1199,7 @@ void C3D_RENDER_OGL_LEGACY::render_3D_module( const MODULE* module,
glMultMatrixf( glm::value_ptr( mtx ) );
if( aRenderTransparentOnly )
modelPtr->Draw_transparent();
modelPtr->Draw_transparent( sM.m_Opacity );
else
modelPtr->Draw_opaque();

View File

@ -391,8 +391,11 @@ void C_OGL_3DMODEL::EndDrawMulti()
}
void C_OGL_3DMODEL::Draw( bool aTransparent ) const
void C_OGL_3DMODEL::Draw( bool aTransparent, float aOpacity ) const
{
if( aOpacity <= FLT_EPSILON )
return;
glBindBuffer( GL_ARRAY_BUFFER, m_vertex_buffer );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_index_buffer );
@ -411,29 +414,61 @@ void C_OGL_3DMODEL::Draw( bool aTransparent ) const
glTexCoordPointer( 2, GL_FLOAT, sizeof( VERTEX ),
reinterpret_cast<const void*>( offsetof( VERTEX, m_tex_uv ) ) );
if( aTransparent )
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
if( aOpacity < 1.0f )
{
glEnable( GL_TEXTURE_2D );
glActiveTexture( GL_TEXTURE0 );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE );
glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE );
glTexEnvi( GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PRIMARY_COLOR );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA );
glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_CONSTANT );
const SFVEC4F param = SFVEC4F( 1.0f, 1.0f, 1.0f, aOpacity );
glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const float*)&param.x );
}
}
// BeginDrawMulti();
for( auto& mat : m_materials )
{
if( mat.IsTransparent() != aTransparent )
continue;
if( ( mat.IsTransparent() != aTransparent ) &&
( aOpacity >= 1.0f ) )
continue;
switch( m_material_mode )
{
case MATERIAL_MODE::NORMAL:
OGL_SetMaterial( mat );
break;
switch( m_material_mode )
{
case MATERIAL_MODE::NORMAL:
OGL_SetMaterial( mat, aOpacity );
break;
case MATERIAL_MODE::DIFFUSE_ONLY:
OGL_SetDiffuseOnlyMaterial( mat.m_Diffuse );
break;
case MATERIAL_MODE::DIFFUSE_ONLY:
OGL_SetDiffuseOnlyMaterial( mat.m_Diffuse, aOpacity );
break;
case MATERIAL_MODE::CAD_MODE:
OGL_SetDiffuseOnlyMaterial( MaterialDiffuseToColorCAD( mat.m_Diffuse ) );
break;
case MATERIAL_MODE::CAD_MODE:
OGL_SetDiffuseOnlyMaterial( MaterialDiffuseToColorCAD( mat.m_Diffuse ), aOpacity );
break;
default:
break;
default:
break;
}
glDrawElements( GL_TRIANGLES, mat.m_render_idx_count, m_index_buffer_type,
@ -441,6 +476,16 @@ void C_OGL_3DMODEL::Draw( bool aTransparent ) const
}
// EndDrawMulti();
if( aTransparent )
{
glDisable( GL_BLEND );
if( aOpacity < 1.0f )
{
OGL_ResetTextureStateDefaults();
}
}
}
C_OGL_3DMODEL::~C_OGL_3DMODEL()

View File

@ -53,12 +53,12 @@ public:
/**
* @brief Draw_opaque - render the model into the current context
*/
void Draw_opaque() const { Draw( false ); }
void Draw_opaque() const { Draw( false, 1.0f ); }
/**
* @brief Draw_transparent - render the model into the current context
*/
void Draw_transparent() const { Draw( true ); }
void Draw_transparent( float aOpacity ) const { Draw( true, aOpacity ); }
/**
* @brief Have_opaque - return true if have opaque meshs to render
@ -155,7 +155,7 @@ private:
VERTEX *aVtxOut, GLuint *aIdxOut,
const glm::vec4 &aColor );
void Draw( bool aTransparent ) const;
void Draw( bool aTransparent, float aOpacity ) const;
};
#endif // _C_OGL_3DMODEL_H_

View File

@ -141,11 +141,15 @@ GLuint OGL_LoadTexture( const CIMAGE &aImage )
}
void OGL_SetMaterial( const SMATERIAL & aMaterial )
void OGL_SetMaterial( const SMATERIAL & aMaterial, float aOpacity )
{
const SFVEC4F ambient = SFVEC4F( aMaterial.m_Ambient, 1.0f );
const SFVEC4F diffuse = SFVEC4F( aMaterial.m_Diffuse, 1.0f -
aMaterial.m_Transparency );
// !TODO: at this moment, diffuse color is added via
// glEnableClientState( GL_COLOR_ARRAY ) so this line may has no effect
// but can be used for optimization
const SFVEC4F diffuse = SFVEC4F( aMaterial.m_Diffuse,
( 1.0f - aMaterial.m_Transparency ) * aOpacity );
const SFVEC4F specular = SFVEC4F( aMaterial.m_Specular, 1.0f );
const SFVEC4F emissive = SFVEC4F( aMaterial.m_Emissive, 1.0f );
@ -161,10 +165,10 @@ void OGL_SetMaterial( const SMATERIAL & aMaterial )
}
void OGL_SetDiffuseOnlyMaterial( const SFVEC3F &aMaterialDiffuse )
void OGL_SetDiffuseOnlyMaterial( const SFVEC3F &aMaterialDiffuse, float aOpacity )
{
const SFVEC4F ambient = SFVEC4F( 0.2f, 0.2f, 0.2f, 1.0f );
const SFVEC4F diffuse = SFVEC4F( aMaterialDiffuse, 1.0f );
const SFVEC4F diffuse = SFVEC4F( aMaterialDiffuse, aOpacity );
const SFVEC4F specular = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f );
const SFVEC4F emissive = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f );
@ -203,3 +207,16 @@ void OGL_DrawBackground( const SFVEC3F &aTopColor, const SFVEC3F &aBotColor )
glVertex2f( 1.0, 1.0 ); // top right corner
glEnd();
}
void OGL_ResetTextureStateDefaults()
{
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, 0 );
glClientActiveTexture( GL_TEXTURE0 );
glDisable( GL_TEXTURE_2D );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
const SFVEC4F zero = SFVEC4F( 0.0f );
glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const float*)&zero.x );
}

View File

@ -38,8 +38,9 @@
/**
* @brief OGL_SetMaterial - Set OpenGL materials
* @param aMaterial: a material structure with parameters to set
* @param aOpacity: main model opacity 0.0 full transparente, 1.0 full opaque
*/
void OGL_SetMaterial( const SMATERIAL & aMaterial );
void OGL_SetMaterial( const SMATERIAL & aMaterial, float aOpacity );
/**
@ -47,7 +48,7 @@ void OGL_SetMaterial( const SMATERIAL & aMaterial );
* parameters with default values
* @param aMaterialDiffuse: the diffese color to assign to material properties
*/
void OGL_SetDiffuseOnlyMaterial( const SFVEC3F &aMaterialDiffuse );
void OGL_SetDiffuseOnlyMaterial( const SFVEC3F &aMaterialDiffuse, float aOpacity );
/**
@ -72,4 +73,11 @@ void OGL_GetScreenshot( wxImage &aDstImage );
*/
void OGL_DrawBackground( const SFVEC3F &aTopColor, const SFVEC3F &aBotColor );
/**
* @brief OGL_ResetTextureStateDefaults - resets to default state the texture settings
*/
void OGL_ResetTextureStateDefaults();
#endif // OGL_UTILS_H_