void CBBOX::ApplyTransformationAA( glm::mat4 aTransformMatrix ) { if( m_initialized == false ) return; // apply the transformation matrix for each of vertices of the bounding box // and make a union with all vertices CBBOX tmpBBox = CBBOX( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_min.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_min.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_max.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_max.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_min.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_max.z, 1.0f ) ) ); tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ) ); m_min = tmpBBox.m_min; m_max = tmpBBox.m_max; }
void EDA_3D_CANVAS::calcBBox() { BOARD* pcb = GetBoard(); m_fastAABBox.Reset(); for( MODULE* module = pcb->m_Modules; module; module = module->Next() ) { CBBOX tmpFastAABBox; // Compute the transformation matrix for this module based on translation, rotation and orientation. float zpos = GetPrm3DVisu().GetModulesZcoord3DIU( module->IsFlipped() ); wxPoint pos = module->GetPosition(); glm::mat4 fullTransformMatrix; fullTransformMatrix = glm::translate( glm::mat4(), S3D_VERTEX( (float)(pos.x * GetPrm3DVisu().m_BiuTo3Dunits), (float)(-pos.y * GetPrm3DVisu().m_BiuTo3Dunits), zpos ) ); if( module->GetOrientation() ) fullTransformMatrix = glm::rotate( fullTransformMatrix, glm::radians( (float)(module->GetOrientation() / 10.0f) ), S3D_VERTEX( 0.0f, 0.0f, 1.0f ) ); if( module->IsFlipped() ) { fullTransformMatrix = glm::rotate( fullTransformMatrix, glm::radians( 180.0f ), S3D_VERTEX( 0.0f, 1.0f, 0.0f ) ); fullTransformMatrix = glm::rotate( fullTransformMatrix, glm::radians( 180.0f ), S3D_VERTEX( 0.0f, 0.0f, 1.0f ) ); } // Compute a union bounding box for all the shapes of the model S3D_MASTER* shape3D = module->Models(); for( ; shape3D; shape3D = shape3D->Next() ) { if( shape3D->Is3DType( S3D_MASTER::FILE3D_VRML ) ) tmpFastAABBox.Union( shape3D->getFastAABBox() ); } tmpFastAABBox.ApplyTransformationAA( fullTransformMatrix ); m_fastAABBox.Union( tmpFastAABBox ); } // Create a board bounding box based on board size wxSize brd_size = getBoardSize(); wxPoint brd_center_pos = getBoardCenter(); float xsize = brd_size.x; float ysize = brd_size.y; float scale = GetPrm3DVisu().m_BiuTo3Dunits; float xmin = (brd_center_pos.x - xsize / 2.0) * scale; float xmax = (brd_center_pos.x + xsize / 2.0) * scale; float ymin = (brd_center_pos.y - ysize / 2.0) * scale; float ymax = (brd_center_pos.y + ysize / 2.0) * scale; float zmin = GetPrm3DVisu().GetLayerZcoordBIU( B_Adhes ) * scale; float zmax = GetPrm3DVisu().GetLayerZcoordBIU( F_Adhes ) * scale; m_boardAABBox = CBBOX( S3D_VERTEX(xmin, ymin, zmin), S3D_VERTEX(xmax, ymax, zmax) ); // Add BB board with BB models and scale it a bit m_fastAABBox.Union( m_boardAABBox ); m_fastAABBox_Shadow = m_fastAABBox; m_fastAABBox_Shadow.Scale( SHADOW_BOUNDING_BOX_SCALE ); }
void CINFO3D_VISU::InitSettings( REPORTER *aStatusTextReporter ) { wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::InitSettings" ) ); // Calculates the board bounding box // First, use only the board outlines EDA_RECT bbbox = m_board->ComputeBoundingBox( true ); // If no outlines, use the board with items if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) ) bbbox = m_board->ComputeBoundingBox( false ); // Gives a non null size to avoid issues in zoom / scale calculations if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) ) bbbox.Inflate( Millimeter2iu( 10 ) ); m_boardSize = bbbox.GetSize(); m_boardPos = bbbox.Centre(); wxASSERT( (m_boardSize.x > 0) && (m_boardSize.y > 0) ); m_boardPos.y = -m_boardPos.y; // The y coord is inverted in 3D viewer m_copperLayersCount = m_board->GetCopperLayerCount(); // Ensure the board has 2 sides for 3D views, because it is hard to find // a *really* single side board in the true life... if( m_copperLayersCount < 2 ) m_copperLayersCount = 2; // Calculate the convertion to apply to all positions. m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y ); // Calculate factors for cicle segment approximation m_calc_seg_min_factor3DU = (float)( SEG_MIN_FACTOR_BIU * m_biuTo3Dunits ); m_calc_seg_max_factor3DU = (float)( SEG_MAX_FACTOR_BIU * m_biuTo3Dunits ); m_epoxyThickness3DU = m_board->GetDesignSettings().GetBoardThickness() * m_biuTo3Dunits; // !TODO: use value defined by user (currently use default values by ctor m_copperThickness3DU = COPPER_THICKNESS * m_biuTo3Dunits; m_nonCopperLayerThickness3DU = TECH_LAYER_THICKNESS * m_biuTo3Dunits; // Init Z position of each layer // calculate z position for each copper layer // Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31) // Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0) // all unused copper layer z position are set to 0 // ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0, // | | Top = Bottom + m_copperThickness // |__________________________________| // == == == == <- Bottom = -m_epoxyThickness / 2.0, // Top = Bottom - m_copperThickness unsigned int layer; for( layer = 0; layer < m_copperLayersCount; ++layer ) { m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f - (m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) ); if( layer < (m_copperLayersCount / 2) ) m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_copperThickness3DU; else m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_copperThickness3DU; } #define layerThicknessMargin 1.1 const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin; // Fill remaining unused copper layers and back layer zpos // with -m_epoxyThickness / 2.0 for( ; layer < MAX_CU_LAYERS; layer++ ) { m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f); m_layerZcoordTop[layer] = -(m_epoxyThickness3DU / 2.0f) - m_copperThickness3DU; } // This is the top of the copper layer thickness. const float zpos_copperTop_back = m_layerZcoordTop[B_Cu]; const float zpos_copperTop_front = m_layerZcoordTop[F_Cu]; // calculate z position for each non copper layer // Solder mask and Solder paste have the same Z position for( int layer_id = MAX_CU_LAYERS; layer_id < LAYER_ID_COUNT; ++layer_id ) { float zposTop; float zposBottom; switch( layer_id ) { case B_Adhes: zposBottom = zpos_copperTop_back - 2.0f * zpos_offset; zposTop = zposBottom - m_nonCopperLayerThickness3DU; break; case F_Adhes: zposBottom = zpos_copperTop_front + 2.0f * zpos_offset; zposTop = zposBottom + m_nonCopperLayerThickness3DU; break; case B_Mask: case B_Paste: zposBottom = zpos_copperTop_back; zposTop = zpos_copperTop_back - m_nonCopperLayerThickness3DU; break; case F_Mask: case F_Paste: zposTop = zpos_copperTop_front + m_nonCopperLayerThickness3DU; zposBottom = zpos_copperTop_front; break; case B_SilkS: zposBottom = zpos_copperTop_back - 1.0f * zpos_offset; zposTop = zposBottom - m_nonCopperLayerThickness3DU; break; case F_SilkS: zposBottom = zpos_copperTop_front + 1.0f * zpos_offset; zposTop = zposBottom + m_nonCopperLayerThickness3DU; break; // !TODO: review default: zposTop = zpos_copperTop_front + (layer_id - MAX_CU_LAYERS + 3.0f) * zpos_offset; zposBottom = zposTop - m_nonCopperLayerThickness3DU; break; } m_layerZcoordTop[layer_id] = zposTop; m_layerZcoordBottom[layer_id] = zposBottom; } m_boardCenter = SFVEC3F( m_boardPos.x * m_biuTo3Dunits, m_boardPos.y * m_biuTo3Dunits, 0.0f ); SFVEC3F boardSize = SFVEC3F( m_boardSize.x * m_biuTo3Dunits, m_boardSize.y * m_biuTo3Dunits, 0.0f ); boardSize /= 2.0f; SFVEC3F boardMin = (m_boardCenter - boardSize); SFVEC3F boardMax = (m_boardCenter + boardSize); boardMin.z = m_layerZcoordTop[B_Adhes]; boardMax.z = m_layerZcoordTop[F_Adhes]; m_boardBoudingBox = CBBOX( boardMin, boardMax ); #ifdef PRINT_STATISTICS_3D_VIEWER unsigned stats_startCreateBoardPolyTime = GetRunningMicroSecs(); #endif if( aStatusTextReporter ) aStatusTextReporter->Report( _( "Build board body" ) ); createBoardPolygon(); #ifdef PRINT_STATISTICS_3D_VIEWER unsigned stats_stopCreateBoardPolyTime = GetRunningMicroSecs(); unsigned stats_startCreateLayersTime = stats_stopCreateBoardPolyTime; #endif if( aStatusTextReporter ) aStatusTextReporter->Report( _( "Create layers" ) ); createLayers( aStatusTextReporter ); #ifdef PRINT_STATISTICS_3D_VIEWER unsigned stats_stopCreateLayersTime = GetRunningMicroSecs(); printf( "CINFO3D_VISU::InitSettings times\n" ); printf( " CreateBoardPoly: %.3f ms\n", (float)( stats_stopCreateBoardPolyTime - stats_startCreateBoardPolyTime ) / 1e3 ); printf( " CreateLayers and holes: %.3f ms\n", (float)( stats_stopCreateLayersTime - stats_startCreateLayersTime ) / 1e3 ); printf( "\n" ); #endif }