From d80a3d651e9589033b385f34dab20265ec7efd8d Mon Sep 17 00:00:00 2001 From: Mario Luzeiro Date: Sun, 15 Mar 2015 16:51:56 +0100 Subject: [PATCH] 3d-viewer: fixes and enhancements. --- 3d-viewer/3d_canvas.h | 4 +- 3d-viewer/3d_draw.cpp | 247 +++++----------- 3d-viewer/3d_draw_basic_functions.cpp | 8 +- 3d-viewer/3d_draw_helper_functions.cpp | 4 +- 3d-viewer/3d_material.cpp | 2 - 3d-viewer/3d_mesh_model.cpp | 10 + 3d-viewer/CImage.cpp | 395 +++++++++++++++++++++++++ 3d-viewer/CImage.h | 94 ++++++ 3d-viewer/CMakeLists.txt | 1 + 3d-viewer/info3d_visu.h | 7 +- 10 files changed, 587 insertions(+), 185 deletions(-) create mode 100644 3d-viewer/CImage.cpp create mode 100644 3d-viewer/CImage.h diff --git a/3d-viewer/3d_canvas.h b/3d-viewer/3d_canvas.h index 2e1cf8a1e3..4dc568dfe1 100644 --- a/3d-viewer/3d_canvas.h +++ b/3d-viewer/3d_canvas.h @@ -196,13 +196,13 @@ private: * Helper function SetGLEpoxyColor * Initialize the color to draw the epoxy body board in realistic mode. */ - void setGLEpoxyColor( double aTransparency = 1.0 ); + void setGLEpoxyColor( float aTransparency = 1.0 ); /** * Helper function SetGLSolderMaskColor * Initialize the color to draw the solder mask layers in realistic mode. */ - void setGLSolderMaskColor( double aTransparency = 1.0 ); + void setGLSolderMaskColor( float aTransparency = 1.0 ); /** * Function BuildBoard3DView diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index ff833a6b3d..02be64b2bd 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -53,6 +53,10 @@ #include #include <3d_draw_basic_functions.h> +#include + + + /* returns the Z orientation parameter 1.0 or -1.0 for aLayer * Z orientation is 1.0 for all layers but "back" layers: * B_Cu , B_Adhes, B_Paste ), B_SilkS @@ -61,99 +65,14 @@ static GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer ); -/* Based on the tutorial http://www.ulrichmierendorff.com/software/opengl_blur.html - * It will blur a openGL texture - */ -static void blur_tex( GLuint aTex, int aPasses, GLuint aTexture_size ) -{ - int i, x, y; - - glFlush(); - glFinish(); - - glPushAttrib( GL_ALL_ATTRIB_BITS ); - - glDisable( GL_LIGHTING ); - - glDisable( GL_CULL_FACE ); - glDisable( GL_DEPTH_TEST ); - glDisable( GL_ALPHA_TEST ); - glDisable( GL_COLOR_MATERIAL ); - - glReadBuffer( GL_BACK_LEFT ); - glPixelStorei( GL_PACK_ALIGNMENT, 1 ); - glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); - - - glViewport( 0, 0, aTexture_size, aTexture_size ); - - glClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - glMatrixMode( GL_PROJECTION ); - glPushMatrix(); - glLoadIdentity(); - - glOrtho( 0.0f, aTexture_size, aTexture_size, 0.0f, -1.0f, 1.0f ); - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, aTex ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - - while (aPasses > 0) - { - i = 0; - for (x = 0; x < 2; x++) - { - for (y = 0; y < 2; y++, i++) - { - glColor4f (1.0f,1.0f,1.0f,1.0 / (i + 1.0)); - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2f( 0 + (x - 0.5)/aTexture_size, 1 + (y-0.5)/aTexture_size ); - glVertex2f( 0, 0 ); - glTexCoord2f( 0 + (x - 0.5)/aTexture_size, 0 + (y-0.5)/aTexture_size ); - glVertex2f( 0, aTexture_size ); - glTexCoord2f( 1 + (x - 0.5)/aTexture_size, 1 + (y-0.5)/aTexture_size ); - glVertex2f( aTexture_size, 0 ); - glTexCoord2f( 1 + (x - 0.5)/aTexture_size, 0 + (y-0.5)/aTexture_size ); - glVertex2f( aTexture_size, aTexture_size ); - glEnd (); - } - } - glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, aTexture_size, aTexture_size, 0 ); - aPasses--; - } - - glFlush(); - glFinish(); - glDisable( GL_BLEND ); - - glMatrixMode( GL_PROJECTION ); - glPopMatrix(); - - glPopAttrib(); - - glEnable(GL_DEPTH_TEST); -} - - void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, GLuint aTexture_size, bool aDraw_body, int aBlurPasses ) { - - float *depthbufferFloat = (float*) malloc( aTexture_size * aTexture_size * sizeof(float) ); unsigned char *depthbufferRGBA = (unsigned char*) malloc( aTexture_size * aTexture_size * 4 ); glDisable( GL_TEXTURE_2D ); - glViewport( 0, 0, aTexture_size, aTexture_size ); + glViewport( 0, 0, aTexture_size, aTexture_size); glClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); @@ -163,79 +82,70 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, -GetPrm3DVisu().m_BoardPos.y * GetPrm3DVisu().m_BiuTo3Dunits, 0.0F ); - if( aDraw_body ) - { - if( m_glLists[GL_ID_BODY] ) - { + if( aDraw_body && m_glLists[GL_ID_BODY] ) glCallList( m_glLists[GL_ID_BODY] ); - } - } - // Call model list - glCallList( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] ); - - if( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ) - { - glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ); - } - - glPixelStorei( GL_PACK_ALIGNMENT, 4 ); - glReadBuffer( GL_BACK_LEFT ); + if( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] ) + glCallList( m_glLists[GL_ID_3DSHAPES_SOLID_FRONT] ); glFinish(); + float *depthbufferFloat = (float*) malloc( aTexture_size * aTexture_size * sizeof(float) ); + for( unsigned int i = 0; i < (aTexture_size * aTexture_size); i++ ) + depthbufferFloat[i] = 1.0f; + + glPixelStorei( GL_PACK_ALIGNMENT, 4 ); + glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); + glReadBuffer( GL_BACK_LEFT ); glReadPixels( 0, 0, aTexture_size, aTexture_size, GL_DEPTH_COMPONENT, GL_FLOAT, depthbufferFloat ); - glFinish(); - - for( unsigned int i = 0; i< (aTexture_size * aTexture_size); i++ ) - { - unsigned char v = depthbufferFloat[i] * 255; - depthbufferRGBA[i * 4 + 0] = v; - depthbufferRGBA[i * 4 + 1] = v; - depthbufferRGBA[i * 4 + 2] = v; - depthbufferRGBA[i * 4 + 3] = 255; - } - - glFinish(); - glEnable( GL_TEXTURE_2D ); glGenTextures( 1, aDst_gl_texture ); glBindTexture( GL_TEXTURE_2D, *aDst_gl_texture ); - glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + CIMAGE imgDepthBuffer( aTexture_size, aTexture_size ); + CIMAGE imgDepthBufferAux( aTexture_size, aTexture_size ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + imgDepthBuffer.setPixelsFromNormalizedFloat( depthbufferFloat ); + + free( depthbufferFloat ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aTexture_size, aTexture_size, 0, - GL_RGBA, GL_UNSIGNED_BYTE, depthbufferRGBA ); + wxString filename; + //filename.Printf( "imgDepthBuffer_%04d", *aDst_gl_texture ); + //imgDepthBuffer.saveAsPNG( filename ); - glFlush(); - glFinish(); - - CheckGLError( __FILE__, __LINE__ ); - - blur_tex( *aDst_gl_texture, aBlurPasses, aTexture_size ); - - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, *aDst_gl_texture ); - - glGetTexImage( GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, depthbufferRGBA ); - - for(unsigned int i = 0; i< (aTexture_size * aTexture_size); i++) + while (aBlurPasses > 0) + { + aBlurPasses--; + imgDepthBufferAux.efxFilter( &imgDepthBuffer, 1.0, FILTER_BLUR); + imgDepthBuffer.efxFilter( &imgDepthBufferAux, 1.0, FILTER_BLUR); + } + //filename.Printf( "imgDepthBuffer_blur_%04d", *aDst_gl_texture ); + //imgDepthBuffer.saveAsPNG( filename ); + + imgDepthBuffer.copyFull( &imgDepthBuffer, &imgDepthBuffer, COPY_MUL ); + //imgDepthBuffer.copyFull( &imgDepthBuffer, &imgDepthBuffer, COPY_MUL ); + //filename.Printf( "imgDepthBuffer_mul_%04d", *aDst_gl_texture ); + //imgDepthBuffer.saveAsPNG( filename ); + + //imgDepthBufferAux.efxFilter( &imgDepthBuffer, 1.0, FILTER_BLUR); + //imgDepthBuffer.efxFilter( &imgDepthBufferAux, 1.0, FILTER_BLUR); + //filename.Printf( "imgDepthBuffer_mulblur_%04d", *aDst_gl_texture ); + //imgDepthBuffer.saveAsPNG( filename ); + + imgDepthBuffer.invert(); + //filename.Printf( "imgDepthBuffer_invert_%04d", *aDst_gl_texture ); + //imgDepthBuffer.saveAsPNG( filename ); + + for(unsigned int i = 0; i < (aTexture_size * aTexture_size); i++) { - float v = (float)depthbufferRGBA[i * 4] / 255.0f; - v = v * v; depthbufferRGBA[i * 4 + 0] = 0; depthbufferRGBA[i * 4 + 1] = 0; depthbufferRGBA[i * 4 + 2] = 0; - depthbufferRGBA[i * 4 + 3] = 255 - (unsigned char)(v * 255); + depthbufferRGBA[i * 4 + 3] = imgDepthBuffer.m_pixels[i]; } glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); @@ -246,7 +156,6 @@ void EDA_3D_CANVAS::Create_and_Render_Shadow_Buffer( GLuint *aDst_gl_texture, glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aTexture_size, aTexture_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, depthbufferRGBA ); free( depthbufferRGBA ); - free( depthbufferFloat ); } #define SHADOW_BOARD_SCALE 1.5f @@ -281,7 +190,7 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures() glTranslatef( 0, 0, 0.03 ); glRotatef( 180, 0.0, 1.0, 0.0 ); - Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_front, 512, false, 5 ); + Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_front, 512, false, 1 ); // Render BACK shadow @@ -290,7 +199,7 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures() glTranslatef( 0, 0, 0.03 ); ///glRotatef( 0.0, 0.0, 1.0, 0.0 ); - Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_back, 512, false, 5 ); + Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_back, 512, false, 1 ); // Render ALL BOARD shadow glMatrixMode( GL_PROJECTION ); @@ -306,7 +215,7 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures() glTranslatef( 0, 0, -0.4f ); glRotatef( 180.0, 0.0, 1.0, 0.0 ); - Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_board, 512, true, 20 ); + Create_and_Render_Shadow_Buffer( &m_text_fake_shadow_board, 512, true, 5 ); } @@ -451,16 +360,6 @@ void EDA_3D_CANVAS::Redraw() if( isEnabled( FL_SHOW_BOARD_BODY ) ) { - if( !isEnabled( FL_RENDER_TEXTURES ) || - isEnabled( FL_SOLDERMASK ) || !isRealisticMode() ) - { - glDisable( GL_TEXTURE_2D ); - } - else - { - glEnable( GL_TEXTURE_2D ); - } - glDisable( GL_LIGHTING ); if( m_glLists[GL_ID_BODY] ) @@ -481,24 +380,22 @@ void EDA_3D_CANVAS::Redraw() glMateriali ( GL_FRONT_AND_BACK, GL_SHININESS, shininess_value ); glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.x ); - if( isRealisticMode() && isEnabled( FL_RENDER_TEXTURES ) ) - { - glEnable( GL_TEXTURE_2D ); - } - else - { - glDisable( GL_TEXTURE_2D ); - } - if( m_glLists[GL_ID_BOARD] ) { glCallList( m_glLists[GL_ID_BOARD] ); } + if( isRealisticMode() && isEnabled( FL_RENDER_TEXTURES ) ) + glEnable( GL_TEXTURE_2D ); + else + glDisable( GL_TEXTURE_2D ); + SetOpenGlDefaultMaterial(); if( m_glLists[GL_ID_TECH_LAYERS] ) { + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glCallList( m_glLists[GL_ID_TECH_LAYERS] ); } @@ -565,20 +462,15 @@ void EDA_3D_CANVAS::Redraw() if( isEnabled( FL_GRID ) && m_glLists[GL_ID_GRID] ) glCallList( m_glLists[GL_ID_GRID] ); - // This list must be drawn last, because it contains the - // transparent gl objects, which should be drawn after all - // non transparent objects - if( isEnabled( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ) - glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ); - - glDisable( GL_BLEND ); - // Draw Board Shadow if( isEnabled( FL_MODULE ) && isRealisticMode() && isEnabled( FL_RENDER_SHADOWS ) ) { if( m_glLists[GL_ID_SHADOW_BOARD] ) { + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glColor4f( 1.0, 1.0, 1.0, 1.0 ); glEnable( GL_CULL_FACE ); glDisable( GL_COLOR_MATERIAL ); glEnable( GL_TEXTURE_2D ); @@ -588,6 +480,17 @@ void EDA_3D_CANVAS::Redraw() } } + // This list must be drawn last, because it contains the + // transparent gl objects, which should be drawn after all + // non transparent objects + if( isEnabled( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ) + { + glDisable( GL_TEXTURE_2D ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] ); + } + SwapBuffers(); } @@ -1153,7 +1056,11 @@ void EDA_3D_CANVAS::BuildTechLayers3DView() currLayerPolyset += polyset; } - int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer ); + int thickness = 0; + + if( layer != B_Mask && layer != F_Mask ) + thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer ); + int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer ); if( layer == Edge_Cuts ) diff --git a/3d-viewer/3d_draw_basic_functions.cpp b/3d-viewer/3d_draw_basic_functions.cpp index e0a7b51b1a..142cc00d17 100644 --- a/3d-viewer/3d_draw_basic_functions.cpp +++ b/3d-viewer/3d_draw_basic_functions.cpp @@ -129,10 +129,10 @@ void SetGLColor( EDA_COLOR_T color, double alpha ) { const StructColors &colordata = g_ColorRefs[ColorGetBase( color )]; - double red = colordata.m_Red / 255.0; - double blue = colordata.m_Blue / 255.0; - double green = colordata.m_Green / 255.0; - glColor4f( red, green, blue, alpha ); + float red = colordata.m_Red / 255.0; + float blue = colordata.m_Blue / 255.0; + float green = colordata.m_Green / 255.0; + glColor4f( red, green, blue, (float)alpha ); } diff --git a/3d-viewer/3d_draw_helper_functions.cpp b/3d-viewer/3d_draw_helper_functions.cpp index f74e700996..7c76995f50 100644 --- a/3d-viewer/3d_draw_helper_functions.cpp +++ b/3d-viewer/3d_draw_helper_functions.cpp @@ -113,7 +113,7 @@ void EDA_3D_CANVAS::setGLCopperColor() // Helper function: initialize the color to draw the epoxy // body board in realistic mode. -void EDA_3D_CANVAS::setGLEpoxyColor( double aTransparency ) +void EDA_3D_CANVAS::setGLEpoxyColor( float aTransparency ) { // Generates an epoxy color, near board color SetGLColor( GetPrm3DVisu().m_BoardBodyColor, aTransparency ); @@ -126,7 +126,7 @@ void EDA_3D_CANVAS::setGLEpoxyColor( double aTransparency ) // Helper function: initialize the color to draw the // solder mask layers in realistic mode. -void EDA_3D_CANVAS::setGLSolderMaskColor( double aTransparency ) +void EDA_3D_CANVAS::setGLSolderMaskColor( float aTransparency ) { // Generates a solder mask color SetGLColor( GetPrm3DVisu().m_SolderMaskColor, aTransparency ); diff --git a/3d-viewer/3d_material.cpp b/3d-viewer/3d_material.cpp index ed54b49c7a..bff1b5c26e 100644 --- a/3d-viewer/3d_material.cpp +++ b/3d-viewer/3d_material.cpp @@ -73,8 +73,6 @@ void SetOpenGlDefaultMaterial() bool S3D_MATERIAL::SetOpenGLMaterial( unsigned int aMaterialIndex, bool aUseMaterial ) { - S3D_MASTER * s3dParent = (S3D_MASTER *) GetParent(); - if( aUseMaterial ) { float transparency_value = 0.0f; diff --git a/3d-viewer/3d_mesh_model.cpp b/3d-viewer/3d_mesh_model.cpp index 94ab420c8e..985b2914d0 100644 --- a/3d-viewer/3d_mesh_model.cpp +++ b/3d-viewer/3d_mesh_model.cpp @@ -113,6 +113,11 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects, if( !isTransparent && aIsRenderingJustTransparentObjects ) return; + + if( useMaterial ) + if( m_Materials->m_Transparency.size() > 0 ) + if( m_Materials->m_Transparency[0] >= 1.0f ) + return; } glPushMatrix(); @@ -146,6 +151,11 @@ void S3D_MESH::openGL_Render( bool aIsRenderingJustNonTransparentObjects, if( !isTransparent && aIsRenderingJustTransparentObjects ) continue; + + if( useMaterial ) + if( m_Materials->m_Transparency.size() > idx ) + if( m_Materials->m_Transparency[idx] >= 1.0f ) + return; } else { diff --git a/3d-viewer/CImage.cpp b/3d-viewer/CImage.cpp new file mode 100644 index 0000000000..2e0cd7de8f --- /dev/null +++ b/3d-viewer/CImage.cpp @@ -0,0 +1,395 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "CImage.h" + +#define CLAMP(n, min, max) {if (n < min) n=min; else if (n > max) n = max;} + + +CIMAGE::CIMAGE( unsigned int xsize, unsigned int ysize ) +{ + m_pixels = (unsigned char*)malloc( xsize * ysize ); + m_width = xsize; + m_height = ysize; + m_wxh = xsize * ysize; + m_wraping = (E_WRAP)WRAP_CLAMP; +} + + +CIMAGE::~CIMAGE() +{ + free( m_pixels ); +} + + +bool CIMAGE::wrapCoords( int *xo, int *yo ) +{ + int x = *xo; + int y = *yo; + + switch(m_wraping) + { + case WRAP_CLAMP: + x = (x < 0 )?0:x; + x = (x >= (int)(m_width - 1))?(m_width - 1):x; + y = (y < 0)?0:y; + y = (y >= (int)(m_height - 1))?(m_height - 1):y; + break; + case WRAP_WRAP: + x = (x < 0)?((m_width - 1)+x):x; + x = (x >= (int)(m_width - 1))?(x - m_width):x; + y = (y < 0)?((m_height - 1)+y):y; + y = (y >= (int)(m_height - 1))?(y - m_height):y; + break; + default: + break; + } + + if( (x < 0) || (x >= (int)m_width) || (y < 0) || (y >= (int)m_height)) + return false; + + *xo = x; + *yo = y; + + return true; +} + + +void CIMAGE::setpixel( int x, int y, unsigned char value ) +{ + if( wrapCoords( &x, &y ) ) + m_pixels[x + y * m_width] = value; +} + + +unsigned char CIMAGE::getpixel(int x, int y) +{ + if( wrapCoords( &x, &y ) ) + return m_pixels[x + y * m_width]; + else + return 0; +} + + +void CIMAGE::invert() +{ + for( unsigned int it = 0;it < m_wxh; it++ ) + m_pixels[it] = 255 - m_pixels[it]; +} + + +void CIMAGE::copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOperation ) +{ + int aV, bV; + + if( aOperation == COPY_RAW ) + { + if ( aImgA == NULL ) + return; + } + else + { + if ( (aImgA == NULL) || (aImgB == NULL) ) + return; + } + + switch(aOperation) + { + case COPY_RAW: + for( unsigned int it = 0;it < m_wxh; it++ ) + m_pixels[it] = aImgA->m_pixels[it]; + break; + + case COPY_ADD: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + aV = (aV + bV); + aV = (aV > 255)?255:aV; + + m_pixels[it] = aV; + } + break; + + case COPY_SUB: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + aV = (aV - bV); + aV = (aV < 0)?0:aV; + + m_pixels[it] = aV; + } + break; + + case COPY_DIF: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = abs(aV - bV); + } + break; + + case COPY_MUL: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = (unsigned char)((((float)aV / 255.0f) * ((float)bV / 255.0f)) * 255); + } + break; + + case COPY_AND: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + m_pixels[it] = aImgA->m_pixels[it] & aImgB->m_pixels[it]; + } + break; + + case COPY_OR: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + m_pixels[it] = aImgA->m_pixels[it] | aImgB->m_pixels[it]; + } + break; + + case COPY_XOR: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + m_pixels[it] = aImgA->m_pixels[it] ^ aImgB->m_pixels[it]; + } + break; + + case COPY_BLEND50: + break; + + case COPY_MIN: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = (aV < bV)?aV:bV; + } + break; + + case COPY_MAX: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = (aV > bV)?aV:bV; + } + break; + } +} + + +S_FILTER FILTERS[9] = { + // Hi Pass + { + { { 0, -1, -1, -1, 0}, + {-1, 2, -4, 2, -1}, + {-1, -4, 13, -4, -1}, + {-1, 2, -4, 2, -1}, + { 0, -1, -1, -1, 0} + }, + 7, + 255 + }, + + // Blur + { + { { 3, 5, 7, 5, 3}, + { 4, 9, 12, 9, 5}, + { 7, 12, 20, 12, 7}, + { 4, 9, 12, 9, 5}, + { 3, 5, 7, 5, 3} + }, + 180, + 0 + }, + + + // KS 01 + { + { { 0, 2, 4, 2, 0}, + { 2, -2, 1, -2, 2}, + { 4, 1, -8, 1, 4}, + { 2, -2, 1, -2, 2}, + { 0, 2, 4, 2, 0} + }, + 20, + 0 + }, + + // Cartoon + { + { {-1, -1, -1, -1, 0}, + {-1, 0, 0, 0, 0}, + {-1, 0, 4, 0, 0}, + { 0, 0, 0, 1, 0}, + { 0, 0, 0, 0, 4} + }, + 3, + 0 + }, + + // Emboss + { + { {-1, -1, -1, -1, 0}, + {-1, -1, -1, 0, 1}, + {-1, -1, 0, 1, 1}, + {-1, 0, 1, 1, 1}, + { 0, 1, 1, 1, 1} + }, + 1, + 128 + }, + + // Sharpen + { + { {-1, -1, -1, -1, -1}, + {-1, 2, 2, 2, -1}, + {-1, 2, 8, 2, -1}, + {-1, 2, 2, 2, -1}, + {-1, -1, -1, -1, -1} + }, + 8, + 0 + }, + + // Melt + { + { { 4, 2, 6, 8, 1}, + { 1, 2, 5, 4, 2}, + { 0, -1, 1, -1, 0}, + { 0, 0, -2, 0, 0}, + { 0, 0, 0, 0, 0} + }, + 32, + 0 + }, + + // Sobel Gx + { + { { 0, 0, 0, 0, 0}, + { 0, -1, 0, 1, 0}, + { 0, -2, 0, 2, 0}, + { 0, -1, 0, 1, 0}, + { 0, 0, 0, 0, 0} + }, + 1, + 0 + }, + + // Sobel Gy + { + { { 1, 2, 4, 2, 1}, + {-1, -1, 0, 1, 1}, + {-2, -2, 0, 2, 2}, + {-1, -1, 0, 1, 1}, + {-1, -2, -4, -2, -1}, + }, + 1, + 0 + } +};// Filters + + +void CIMAGE::efxFilter( CIMAGE *aInImg, float aGain, E_FILTER aFilterType ) +{ + S_FILTER filter = FILTERS[aFilterType]; + + aInImg->m_wraping = WRAP_CLAMP; + m_wraping = WRAP_CLAMP; + + for( int iy = 0; iy < (int)m_height; iy++) + { + for( int ix = 0; ix < (int)m_width; ix++ ) + { + int v = filter.offset; + + for( int sy = 0; sy < 5; sy++ ) + { + for( int sx = 0; sx < 5; sx++ ) + { + int factor = filter.kernel[sx][sy]; + unsigned char pixelv = aInImg->getpixel( ix + sx - 2, iy + sy - 2 ); + v += pixelv * factor; + } + } + + v /= filter.div; + + CLAMP(v, 0, 255); + + m_pixels[ix + iy * m_width] = v; + } + } +} + + +void CIMAGE::setPixelsFromNormalizedFloat( const float * aNormalizedFloatArray ) +{ + for( unsigned int i = 0; i < m_wxh; i++ ) + { + int v = aNormalizedFloatArray[i] * 255; + CLAMP(v, 0, 255); + m_pixels[i] = v; + } +} + + +void CIMAGE::saveAsPNG( wxString aFileName ) +{ + unsigned char* pixelbuffer = (unsigned char*) malloc( m_wxh * 3 ); + //unsigned char* alphabuffer = (unsigned char*) malloc( m_width * aHeight ); + + wxImage image( m_width, m_height ); + + for( unsigned int i = 0; i < m_wxh; i++) + { + unsigned char v = m_pixels[i]; + pixelbuffer[i * 3 + 0] = v; + pixelbuffer[i * 3 + 1] = v; + pixelbuffer[i * 3 + 2] = v; + //alphabuffer[i * 1 + 0] = aRGBABufferImage[i * 4 + 3]; + } + + image.SetData( pixelbuffer ); + //image.SetAlpha( alphabuffer ); + image = image.Mirror( false ); + image.SaveFile( aFileName + ".png", wxBITMAP_TYPE_PNG ); + image.Destroy(); +} + diff --git a/3d-viewer/CImage.h b/3d-viewer/CImage.h new file mode 100644 index 0000000000..75f28cafa5 --- /dev/null +++ b/3d-viewer/CImage.h @@ -0,0 +1,94 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef CImage_h +#define CImage_h + +#include + +enum E_IMAGE_OP { + COPY_RAW, + COPY_ADD, + COPY_SUB, + COPY_DIF, + COPY_MUL, + COPY_AND, + COPY_OR, + COPY_XOR, + COPY_BLEND50, + COPY_MIN, + COPY_MAX +}; + +enum E_WRAP { + WRAP_ZERO, ///< Coords that wraps are not evaluated + WRAP_CLAMP, + WRAP_WRAP ///< Coords are wrapped arround +}; + +enum E_FILTER { + FILTER_HIPASS, + FILTER_BLUR +}; + +typedef struct { + signed char kernel[5][5]; + unsigned char div; + unsigned char offset; +}S_FILTER; + + +class CIMAGE +{ + +public: + + CIMAGE( unsigned int xsize, unsigned int ysize ); + + ~CIMAGE(); + + void setpixel( int x, int y, unsigned char value ); + unsigned char getpixel( int x, int y ); + + void copyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOperation ); + + void invert(); + + void efxFilter( CIMAGE *aInImg, float aGain, E_FILTER aFilterType ); + + void saveAsPNG( wxString aFileName ); + + void setPixelsFromNormalizedFloat( const float * aNormalizedFloatArray ); +private: + bool wrapCoords( int *xo, int *yo ); + +public: + unsigned char* m_pixels; + unsigned int m_width; + unsigned int m_height; + unsigned int m_wxh; + E_WRAP m_wraping; +}; + +#endif diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt index f226aff2c1..2259b61f46 100644 --- a/3d-viewer/CMakeLists.txt +++ b/3d-viewer/CMakeLists.txt @@ -30,6 +30,7 @@ set(3D-VIEWER_SRCS vrml_v1_modelparser.cpp vrml_v2_modelparser.cpp x3dmodelparser.cpp + CImage.cpp ) add_library(3d-viewer STATIC ${3D-VIEWER_SRCS}) diff --git a/3d-viewer/info3d_visu.h b/3d-viewer/info3d_visu.h index 8a5067363b..c36e52f07c 100644 --- a/3d-viewer/info3d_visu.h +++ b/3d-viewer/info3d_visu.h @@ -183,9 +183,7 @@ public: INFO3D_VISU(); */ int GetNonCopperLayerThicknessBIU() const { - bool use_thickness = GetFlag( FL_USE_COPPER_THICKNESS ) -// || GetFlag( FL_USE_REALISTIC_MODE ) - ; + bool use_thickness = GetFlag( FL_USE_COPPER_THICKNESS ); return use_thickness ? KiROUND( m_nonCopperLayerThickness / m_BiuTo3Dunits ) : 0; @@ -202,8 +200,7 @@ public: INFO3D_VISU(); { return IsCopperLayer( aLayerId ) ? GetCopperThicknessBIU() : - GetNonCopperLayerThicknessBIU() - ; + GetNonCopperLayerThicknessBIU(); } bool IsRealisticMode() { return GetFlag( FL_USE_REALISTIC_MODE ); }