void Convert_shape_line_polygon_to_triangles( SHAPE_POLY_SET &aPolyList, CGENERICCONTAINER2D &aDstContainer, float aBiuTo3DunitsScale , const BOARD_ITEM &aBoardItem ) { aPolyList.CacheTriangulation(); const double conver_d = (double)aBiuTo3DunitsScale; for( unsigned int j = 0; j < aPolyList.TriangulatedPolyCount(); j++ ) { auto triPoly = aPolyList.TriangulatedPolygon( j ); for( size_t i = 0; i < triPoly->GetTriangleCount(); i++ ) { VECTOR2I a; VECTOR2I b; VECTOR2I c; triPoly->GetTriangle( i, a, b, c ); aDstContainer.Add( new CTRIANGLE2D( SFVEC2F( a.x * conver_d, -a.y * conver_d ), SFVEC2F( b.x * conver_d, -b.y * conver_d ), SFVEC2F( c.x * conver_d, -c.y * conver_d ), aBoardItem ) ); } } }
CROUNDSEGMENT2D::CROUNDSEGMENT2D( const SFVEC2F &aStart, const SFVEC2F &aEnd, float aWidth, const BOARD_ITEM &aBoardItem ) : COBJECT2D( OBJ2D_ROUNDSEG, aBoardItem ), m_segment( aStart, aEnd ) { m_radius = (aWidth / 2.0f); m_radius_squared = m_radius * m_radius; m_width = aWidth; SFVEC2F leftRadiusOffset( -m_segment.m_Dir.y * m_radius, m_segment.m_Dir.x * m_radius); m_leftStart = aStart + leftRadiusOffset; m_leftEnd = aEnd + leftRadiusOffset; m_leftEnd_minus_start = m_leftEnd - m_leftStart; m_leftDir = glm::normalize( m_leftEnd_minus_start ); SFVEC2F rightRadiusOffset( -leftRadiusOffset.x, -leftRadiusOffset.y ); m_rightStart = aEnd + rightRadiusOffset; m_rightEnd = aStart + rightRadiusOffset; m_rightEnd_minus_start = m_rightEnd - m_rightStart; m_rightDir = glm::normalize( m_rightEnd_minus_start ); m_bbox.Reset(); m_bbox.Set( aStart, aEnd ); m_bbox.Set( m_bbox.Min() - SFVEC2F( m_radius, m_radius ), m_bbox.Max() + SFVEC2F( m_radius, m_radius ) ); m_bbox.ScaleNextUp(); m_centroid = m_bbox.GetCenter(); wxASSERT( m_bbox.IsInitialized() ); }
INTERSECTION_RESULT CROUNDSEGMENT2D::IsBBoxInside( const CBBOX2D &aBBox ) const { if( !m_bbox.Intersects( aBBox ) ) return INTR_MISSES; SFVEC2F v[4]; v[0] = aBBox.Min(); v[1] = aBBox.Max(); v[2] = SFVEC2F( aBBox.Min().x, aBBox.Max().y ); v[3] = SFVEC2F( aBBox.Max().x, aBBox.Min().y ); bool isInside[4]; isInside[0] = IsPointInside( v[0] ); isInside[1] = IsPointInside( v[1] ); isInside[2] = IsPointInside( v[2] ); isInside[3] = IsPointInside( v[3] ); // Check if all points are inside the circle if( isInside[0] && isInside[1] && isInside[2] && isInside[3] ) return INTR_FULL_INSIDE; // Check if any point is inside the circle if( isInside[0] || isInside[1] || isInside[2] || isInside[3] ) return INTR_INTERSECTS; return INTR_MISSES; }
void C3D_RENDER_OGL_LEGACY::generate_ring_contour( const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, unsigned int aNr_sides_per_circle, std::vector< SFVEC2F > &aInnerContourResult, std::vector< SFVEC2F > &aOuterContourResult, bool aInvertOrder ) { aInnerContourResult.clear(); aInnerContourResult.reserve( aNr_sides_per_circle + 2 ); aOuterContourResult.clear(); aOuterContourResult.reserve( aNr_sides_per_circle + 2 ); const int delta = 3600 / aNr_sides_per_circle; for( int ii = 0; ii < 3600; ii += delta ) { const SFVEC2F rotatedDir = glm::rotate( SFVEC2F( 1.0f, 0.0f ), (float)(aInvertOrder?(3600 - ii):ii) * 2.0f * glm::pi<float>() / 3600.0f ); aInnerContourResult.push_back( SFVEC2F( aCenter.x + rotatedDir.x * aInnerRadius, aCenter.y + rotatedDir.y * aInnerRadius ) ); aOuterContourResult.push_back( SFVEC2F( aCenter.x + rotatedDir.x * aOuterRadius, aCenter.y + rotatedDir.y * aOuterRadius ) ); } aInnerContourResult.push_back( aInnerContourResult[0] ); aOuterContourResult.push_back( aOuterContourResult[0] ); wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() ); }
static void polygon_Convert( const SHAPE_LINE_CHAIN &aPath, SEGMENTS &aOutSegment, float aBiuTo3DunitsScale ) { aOutSegment.resize( aPath.PointCount() ); for( int j = 0; j < aPath.PointCount(); j++ ) { const VECTOR2I &a = aPath.CPoint( j ); aOutSegment[j].m_Start = SFVEC2F( (float) a.x * aBiuTo3DunitsScale, (float)-a.y * aBiuTo3DunitsScale ); } unsigned int i; unsigned int j = aOutSegment.size () - 1; for( i = 0; i < aOutSegment.size (); j = i++ ) { // Calculate constants for each segment aOutSegment[i].m_inv_JY_minus_IY = 1.0f / ( aOutSegment[j].m_Start.y - aOutSegment[i].m_Start.y ); aOutSegment[i].m_JX_minus_IX = (aOutSegment[j].m_Start.x - aOutSegment[i].m_Start.x); } }
void Polygon_Calc_BBox_3DU( const SHAPE_POLY_SET &aPolysList, CBBOX2D &aOutBBox , float aBiuTo3DunitsScale ) { aOutBBox.Reset(); for( int idx = 0; idx < aPolysList.OutlineCount(); ++idx ) { // Each polygon in aPolysList is a polygon with holes const SHAPE_POLY_SET::POLYGON& curr_polywithholes = aPolysList.CPolygon( idx ); for( unsigned ipoly = 0; ipoly < curr_polywithholes.size(); ++ipoly ) { const SHAPE_LINE_CHAIN& path = curr_polywithholes[ipoly]; // a simple polygon for( int jj = 0; jj < path.PointCount(); jj++ ) { const VECTOR2I& a = path.CPoint( jj ); aOutBBox.Union( SFVEC2F( (float) a.x * aBiuTo3DunitsScale, (float)-a.y * aBiuTo3DunitsScale ) ); } } } aOutBBox.ScaleNextUp(); }
void CLAYER_TRIANGLES::AddToMiddleContourns( const SHAPE_LINE_CHAIN &outlinePath, float zBot, float zTop, double aBiuTo3Du, bool aInvertFaceDirection ) { std::vector< SFVEC2F >contournPoints; contournPoints.clear(); contournPoints.reserve( outlinePath.PointCount() + 2 ); const VECTOR2I &firstV = outlinePath.CPoint( 0 ); SFVEC2F lastV = SFVEC2F( firstV.x * aBiuTo3Du, -firstV.y * aBiuTo3Du ); contournPoints.push_back( lastV ); for( unsigned int i = 1; i < (unsigned int)outlinePath.PointCount(); ++i ) { const VECTOR2I & v = outlinePath.CPoint( i ); const SFVEC2F vf = SFVEC2F( v.x * aBiuTo3Du, -v.y * aBiuTo3Du ); if( vf != lastV ) // Do not add repeated points { lastV = vf; contournPoints.push_back( vf ); } } // Add first position fo the list to close the path if( lastV != contournPoints[0] ) contournPoints.push_back( contournPoints[0] ); AddToMiddleContourns( contournPoints, zBot, zTop, aInvertFaceDirection ); }
bool CROUNDSEGMENT2D::Intersects( const CBBOX2D &aBBox ) const { if( !m_bbox.Intersects( aBBox ) ) return false; if( (aBBox.Max().x > m_bbox.Max().x) && (aBBox.Max().y > m_bbox.Max().x) && (aBBox.Min().x < m_bbox.Min().x) && (aBBox.Min().y < m_bbox.Min().y) ) return true; SFVEC2F v[4]; v[0] = aBBox.Min(); v[1] = SFVEC2F( aBBox.Min().x, aBBox.Max().y ); v[2] = aBBox.Max(); v[3] = SFVEC2F( aBBox.Max().x, aBBox.Min().y ); // Test against the main rectangle segment if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[0], v[1] - v[0] ) ) return true; if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[1], v[2] - v[1] ) ) return true; if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[2], v[3] - v[2] ) ) return true; if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[3], v[0] - v[3] ) ) return true; if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[0], v[1] - v[0] ) ) return true; if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[1], v[2] - v[1] ) ) return true; if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[2], v[3] - v[2] ) ) return true; if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[3], v[0] - v[3] ) ) return true; // Test the two circles if( aBBox.Intersects( m_segment.m_Start, m_radius_squared ) ) return true; if( aBBox.Intersects( m_segment.m_End, m_radius_squared ) ) return true; return false; }
static void polygon_Convert( const ClipperLib::Path &aPath, SEGMENTS &aOutSegment, float aBiuTo3DunitsScale ) { aOutSegment.resize( aPath.size() ); for( unsigned i = 0; i < aPath.size(); i++ ) { aOutSegment[i].m_Start = SFVEC2F( (float) aPath[i].X * aBiuTo3DunitsScale, (float)-aPath[i].Y * aBiuTo3DunitsScale ); } unsigned int i; unsigned int j = aOutSegment.size () - 1; for( i = 0; i < aOutSegment.size (); j = i++ ) { // Calculate constants for each segment aOutSegment[i].m_inv_JY_minus_IY = 1.0f / ( aOutSegment[j].m_Start.y - aOutSegment[i].m_Start.y ); aOutSegment[i].m_JX_minus_IX = (aOutSegment[j].m_Start.x - aOutSegment[i].m_Start.x); } }
void C3D_RENDER_OGL_LEGACY::reload() { m_reloadRequested = false; ogl_free_all_display_lists(); COBJECT2D_STATS::Instance().ResetStats(); m_settings.InitSettings(); SFVEC3F camera_pos = m_settings.GetBoardCenter3DU(); m_settings.CameraGet().SetBoardLookAtPos( camera_pos ); // Create Board // ///////////////////////////////////////////////////////////////////////// printf("Create board...\n"); CCONTAINER2D boardContainer; Convert_shape_line_polygon_to_triangles( m_settings.GetBoardPoly(), boardContainer, m_settings.BiuTo3Dunits(), (const BOARD_ITEM &)*m_settings.GetBoard() ); const LIST_OBJECT2D listBoardObject2d = boardContainer.GetList(); if( listBoardObject2d.size() > 0 ) { /* float layer_z_top = m_settings.GetLayerBottomZpos3DU( F_Cu ); float layer_z_bot = m_settings.GetLayerBottomZpos3DU( B_Cu ); */ float layer_z_top = m_settings.GetLayerBottomZpos3DU( B_Mask ); float layer_z_bot = m_settings.GetLayerTopZpos3DU( B_Mask ); CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listBoardObject2d.size() ); for( LIST_OBJECT2D::const_iterator itemOnLayer = listBoardObject2d.begin(); itemOnLayer != listBoardObject2d.end(); itemOnLayer++ ) { const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer); wxASSERT( object2d_A->GetObjectType() == OBJ2D_TRIANGLE ); const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A; const SFVEC2F &v1 = tri->GetP1(); const SFVEC2F &v2 = tri->GetP2(); const SFVEC2F &v3 = tri->GetP3(); add_triangle_top_bot( layerTriangles, v1, v2, v3, layer_z_top, layer_z_bot ); } const SHAPE_POLY_SET boardPoly = m_settings.GetBoardPoly(); SHAPE_POLY_SET boardPolyCopy = boardPoly; boardPolyCopy.Simplify( SHAPE_POLY_SET::PM_FAST ); if( boardPolyCopy.OutlineCount() == 1 ) { const SHAPE_LINE_CHAIN& outlinePath = boardPolyCopy.COutline( 0 ); std::vector< SFVEC2F > contournPoints; contournPoints.clear(); contournPoints.reserve( outlinePath.PointCount() + 2 ); for( unsigned int i = 0; i < (unsigned int)outlinePath.PointCount(); ++i ) { const VECTOR2I& v = outlinePath.CPoint( i ); contournPoints.push_back( SFVEC2F( v.x * m_settings.BiuTo3Dunits(), -v.y * m_settings.BiuTo3Dunits() ) ); } contournPoints.push_back( contournPoints[0] ); if( contournPoints.size() > 4 ) { // Calculate normals of each segment of the contourn std::vector< SFVEC2F > contournNormals; contournNormals.clear(); contournNormals.reserve( contournPoints.size() ); for( unsigned int i = 0; i < ( contournPoints.size() - 1 ); ++i ) { const SFVEC2F &v0 = contournPoints[i + 0]; const SFVEC2F &v1 = contournPoints[i + 1]; SFVEC2F n = glm::normalize( v1 - v0 ); contournNormals.push_back( SFVEC2F( -n.y, n.x ) ); } SFVEC2F lastNormal = contournNormals[contournPoints.size() - 2]; for( unsigned int i = 0; i < ( contournPoints.size() - 1 ); ++i ) { const SFVEC2F &v0 = contournPoints[i + 0]; const SFVEC2F &v1 = contournPoints[i + 1]; layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, NextFloatUp( layer_z_top ) ), SFVEC3F( v1.x, v1.y, NextFloatUp( layer_z_top ) ), SFVEC3F( v1.x, v1.y, NextFloatDown( layer_z_bot ) ), SFVEC3F( v0.x, v0.y, NextFloatDown( layer_z_bot ) ) ); SFVEC2F n0 = contournNormals[i]; if( glm::dot( n0, lastNormal ) > 0.5f ) n0 += lastNormal; else n0 += contournNormals[i]; const SFVEC2F &nextNormal = contournNormals[ (i + 1) % (contournPoints.size() - 1) ]; SFVEC2F n1 = contournNormals[i]; if( glm::dot( n1, nextNormal ) > 0.5f ) n1 += nextNormal; else n1 += contournNormals[i]; n0 = glm::normalize( n0 ); n1 = glm::normalize( n1 ); const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 ); lastNormal = contournNormals[i]; /* const SFVEC2F n0 = glm::normalize( v0 - center ); const SFVEC2F n1 = glm::normalize( v1 - center ); const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z );*/ } } contournPoints.clear(); } m_ogl_disp_list_board = new CLAYERS_OGL_DISP_LISTS( *layerTriangles, m_ogl_circle_texture, SFVEC3F(0.65f,0.55f,0.05f) ); delete layerTriangles; } float calc_sides_min_factor = (float)( 10.0 * IU_PER_MILS * m_settings.BiuTo3Dunits() ); float calc_sides_max_factor = (float)( 1000.0 * IU_PER_MILS * m_settings.BiuTo3Dunits() ); // Add layers maps (except B_Mask and F_Mask) // ///////////////////////////////////////////////////////////////////////// printf("Add layers maps...\n"); for( MAP_CONTAINER_2D::const_iterator it = m_settings.GetMapLayers().begin(); it != m_settings.GetMapLayers().end(); it++ ) { LAYER_ID layer_id = static_cast<LAYER_ID>(it->first); if( !m_settings.Is3DLayerEnabled( layer_id ) ) continue; const CBVHCONTAINER2D *container2d = static_cast<const CBVHCONTAINER2D *>(it->second); const LIST_OBJECT2D listObject2d = container2d->GetList(); if( listObject2d.size() == 0 ) continue; //CMATERIAL *materialLayer = &m_materials.m_SilkS; SFVEC3F layerColor = SFVEC3F( 0.3f, 0.4f, 0.5f ); float layer_z_bot = m_settings.GetLayerBottomZpos3DU( layer_id ); float layer_z_top = m_settings.GetLayerTopZpos3DU( layer_id ); if( layer_z_top < layer_z_bot ) { float tmpFloat = layer_z_bot; layer_z_bot = layer_z_top; layer_z_top = tmpFloat; } layer_z_bot -= m_settings.GetNonCopperLayerThickness3DU(); layer_z_top += m_settings.GetNonCopperLayerThickness3DU(); if( m_settings.GetFlag( FL_USE_REALISTIC_MODE ) ) { switch( layer_id ) { case B_Adhes: case F_Adhes: break; case B_Paste: case F_Paste: // materialLayer = &m_materials.m_Paste; break; case B_SilkS: case F_SilkS: // materialLayer = &m_materials.m_SilkS; // layerColor = g_silkscreenColor; break; case Dwgs_User: case Cmts_User: case Eco1_User: case Eco2_User: case Edge_Cuts: case Margin: break; case B_CrtYd: case F_CrtYd: break; case B_Fab: case F_Fab: break; default: //materialLayer = &m_materials.m_Copper; //layerColor = g_copperColor; break; } } else { layerColor = m_settings.GetLayerColor( layer_id ); } // Calculate an estiation for then nr of triangles based on the nr of objects unsigned int nrTrianglesEstimation = listObject2d.size() * 8; CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( nrTrianglesEstimation ); m_triangles[layer_id] = layerTriangles; for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin(); itemOnLayer != listObject2d.end(); itemOnLayer++ ) { const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer); switch( object2d_A->GetObjectType() ) { case OBJ2D_FILLED_CIRCLE: { const CFILLEDCIRCLE2D *filledCircle = (const CFILLEDCIRCLE2D *)object2d_A; const SFVEC2F ¢er = filledCircle->GetCenter(); float radius = filledCircle->GetRadius() * 2.0f; // Double because the render triangle float radiusSquared = radius * radius; const float f = (sqrtf(2.0f) / 2.0f) * radius * 0.9;// * texture_factor; layerTriangles->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, layer_z_top ), SFVEC3F( center.x - f, center.y, layer_z_top ), SFVEC3F( center.x, center.y - f, layer_z_top ) ); layerTriangles->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, layer_z_top ), SFVEC3F( center.x + f, center.y, layer_z_top ), SFVEC3F( center.x, center.y + f, layer_z_top ) ); layerTriangles->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, layer_z_bot ), SFVEC3F( center.x + f, center.y, layer_z_bot ), SFVEC3F( center.x, center.y - f, layer_z_bot ) ); layerTriangles->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, layer_z_bot ), SFVEC3F( center.x - f, center.y, layer_z_bot ), SFVEC3F( center.x, center.y + f, layer_z_bot ) ); unsigned int nr_sides_per_circle = (unsigned int)mapf( radiusSquared, calc_sides_min_factor, calc_sides_max_factor, 24.0f, 256.0f ); wxASSERT( nr_sides_per_circle >= 24 ); // Normal radius for the circle radius = filledCircle->GetRadius(); std::vector< SFVEC2F > contournPoints; contournPoints.clear(); contournPoints.reserve( nr_sides_per_circle + 2 ); int delta = 3600 / nr_sides_per_circle; for( int ii = 0; ii < 3600; ii += delta ) { const SFVEC2F rotatedDir = glm::rotate( SFVEC2F( 0.0f, 1.0f ), (float)ii * 2.0f * 3.14f / 3600.0f ); contournPoints.push_back( SFVEC2F( center.x - rotatedDir.y * radius, center.y + rotatedDir.x * radius ) ); } contournPoints.push_back( contournPoints[0] ); if( contournPoints.size() > 1 ) { for( unsigned int i = 0; i < ( contournPoints.size() - 1 ); ++i ) { const SFVEC2F &v0 = contournPoints[i + 0]; const SFVEC2F &v1 = contournPoints[i + 1]; layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, NextFloatUp( layer_z_bot ) ), SFVEC3F( v1.x, v1.y, NextFloatUp( layer_z_bot ) ), SFVEC3F( v1.x, v1.y, NextFloatDown( layer_z_top ) ), SFVEC3F( v0.x, v0.y, NextFloatDown( layer_z_top ) ) ); const SFVEC2F n0 = glm::normalize( v0 - center ); const SFVEC2F n1 = glm::normalize( v1 - center ); const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z ); } } contournPoints.clear(); } break; case OBJ2D_DUMMYBLOCK: { } break; case OBJ2D_POLYGON4PT: { const CPOLYGON4PTS2D *poly = (const CPOLYGON4PTS2D *)object2d_A; const SFVEC2F &v0 = poly->GetV0(); const SFVEC2F &v1 = poly->GetV1(); const SFVEC2F &v2 = poly->GetV2(); const SFVEC2F &v3 = poly->GetV3(); add_triangle_top_bot( layerTriangles, v0, v2, v1, layer_z_top, layer_z_bot ); add_triangle_top_bot( layerTriangles, v2, v0, v3, layer_z_top, layer_z_bot ); const SFVEC2F &n0 = poly->GetN0(); const SFVEC2F &n1 = poly->GetN1(); const SFVEC2F &n2 = poly->GetN2(); const SFVEC2F &n3 = poly->GetN3(); const SFVEC3F n3d0 = SFVEC3F(-n0.y, n0.x, 0.0f ); const SFVEC3F n3d1 = SFVEC3F(-n1.y, n1.x, 0.0f ); const SFVEC3F n3d2 = SFVEC3F(-n2.y, n2.x, 0.0f ); const SFVEC3F n3d3 = SFVEC3F(-n3.y, n3.x, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, layer_z_bot ), SFVEC3F( v1.x, v1.y, layer_z_bot ), SFVEC3F( v1.x, v1.y, layer_z_top ), SFVEC3F( v0.x, v0.y, layer_z_top ) ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d0, n3d0, n3d0, n3d0 ); layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v2.x, v2.y, layer_z_top ), SFVEC3F( v1.x, v1.y, layer_z_top ), SFVEC3F( v1.x, v1.y, layer_z_bot ), SFVEC3F( v2.x, v2.y, layer_z_bot ) ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d1, n3d1, n3d1, n3d1 ); layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v3.x, v3.y, layer_z_top ), SFVEC3F( v2.x, v2.y, layer_z_top ), SFVEC3F( v2.x, v2.y, layer_z_bot ), SFVEC3F( v3.x, v3.y, layer_z_bot ) ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d2, n3d2, n3d2, n3d2 ); layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, layer_z_top ), SFVEC3F( v3.x, v3.y, layer_z_top ), SFVEC3F( v3.x, v3.y, layer_z_bot ), SFVEC3F( v0.x, v0.y, layer_z_bot ) ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d3, n3d3, n3d3, n3d3 ); } break; case OBJ2D_RING: { const CRING2D *ring = (const CRING2D *)object2d_A; const SFVEC2F ¢er = ring->GetCenter(); float inner = ring->GetInnerRadius(); float outer = ring->GetOuterRadius(); unsigned int nr_sides_per_circle = (unsigned int)mapf( outer, calc_sides_min_factor, calc_sides_max_factor, 24.0f, 256.0f ); wxASSERT( nr_sides_per_circle >= 24 ); std::vector< SFVEC2F > innerContour; std::vector< SFVEC2F > outerContour; innerContour.clear(); innerContour.reserve( nr_sides_per_circle + 2 ); outerContour.clear(); outerContour.reserve( nr_sides_per_circle + 2 ); int delta = 3600 / nr_sides_per_circle; for( int ii = 0; ii < 3600; ii += delta ) { const SFVEC2F rotatedDir = glm::rotate( SFVEC2F( 0.0f, 1.0f), (float) ii * 2.0f * 3.14f / 3600.0f ); innerContour.push_back( SFVEC2F( center.x - rotatedDir.y * inner, center.y + rotatedDir.x * inner ) ); outerContour.push_back( SFVEC2F( center.x - rotatedDir.y * outer, center.y + rotatedDir.x * outer ) ); } innerContour.push_back( innerContour[0] ); outerContour.push_back( outerContour[0] ); wxASSERT( innerContour.size() == outerContour.size() ); for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i ) { const SFVEC2F &vi0 = innerContour[i + 0]; const SFVEC2F &vi1 = innerContour[i + 1]; const SFVEC2F &vo0 = outerContour[i + 0]; const SFVEC2F &vo1 = outerContour[i + 1]; layerTriangles->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, layer_z_top ), SFVEC3F( vi0.x, vi0.y, layer_z_top ), SFVEC3F( vo0.x, vo0.y, layer_z_top ), SFVEC3F( vo1.x, vo1.y, layer_z_top ) ); layerTriangles->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, layer_z_bot ), SFVEC3F( vo1.x, vo1.y, layer_z_bot ), SFVEC3F( vo0.x, vo0.y, layer_z_bot ), SFVEC3F( vi0.x, vi0.y, layer_z_bot ) ); } for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i ) { const SFVEC2F &v0 = innerContour[i + 0]; const SFVEC2F &v1 = innerContour[i + 1]; layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v1.x, v1.y, NextFloatUp( layer_z_bot ) ), SFVEC3F( v0.x, v0.y, NextFloatUp( layer_z_bot ) ), SFVEC3F( v0.x, v0.y, NextFloatDown( layer_z_top ) ), SFVEC3F( v1.x, v1.y, NextFloatDown( layer_z_top ) ) ); const SFVEC2F n0 = glm::normalize( v0 - center ); const SFVEC2F n1 = glm::normalize( v1 - center ); const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z ); } for( unsigned int i = 0; i < ( outerContour.size() - 1 ); ++i ) { const SFVEC2F &v0 = outerContour[i + 0]; const SFVEC2F &v1 = outerContour[i + 1]; layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, NextFloatUp( layer_z_bot ) ), SFVEC3F( v1.x, v1.y, NextFloatUp( layer_z_bot ) ), SFVEC3F( v1.x, v1.y, NextFloatDown( layer_z_top ) ), SFVEC3F( v0.x, v0.y, NextFloatDown( layer_z_top ) ) ); const SFVEC2F n0 = glm::normalize( v0 - center ); const SFVEC2F n1 = glm::normalize( v1 - center ); const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z ); } } break; case OBJ2D_TRIANGLE: { const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A; const SFVEC2F &v1 = tri->GetP1(); const SFVEC2F &v2 = tri->GetP2(); const SFVEC2F &v3 = tri->GetP3(); add_triangle_top_bot( layerTriangles, v1, v2, v3, layer_z_top, layer_z_bot ); } break; case OBJ2D_ROUNDSEG: { const CROUNDSEGMENT2D &roundSeg = (const CROUNDSEGMENT2D &) *object2d_A; unsigned int nr_sides_per_circle = (unsigned int)mapf( roundSeg.GetWidth(), calc_sides_min_factor, calc_sides_max_factor, 24.0f, 256.0f ); wxASSERT( nr_sides_per_circle >= 24 ); SFVEC2F leftStart = roundSeg.GetLeftStar(); SFVEC2F leftEnd = roundSeg.GetLeftEnd(); SFVEC2F leftDir = roundSeg.GetLeftDir(); SFVEC2F rightStart = roundSeg.GetRightStar(); SFVEC2F rightEnd = roundSeg.GetRightEnd(); SFVEC2F rightDir = roundSeg.GetRightDir(); float radius = roundSeg.GetRadius(); SFVEC2F start = roundSeg.GetStart(); SFVEC2F end = roundSeg.GetEnd(); float texture_factor = (12.0f/(float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f; float texture_factorF= ( 4.0f/(float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f; const float radius_of_the_square = sqrtf( roundSeg.GetRadiusSquared() * 2.0f ); const float radius_triangle_factor = (radius_of_the_square - radius) / radius; const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor, rightDir.x * radius * radius_triangle_factor ); const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor, leftDir.x * radius * radius_triangle_factor ); // Top end segment triangles layerTriangles->m_layer_top_segment_ends->AddTriangle( SFVEC3F( rightEnd.x + texture_factor * factorS.x, rightEnd.y + texture_factor * factorS.y, layer_z_top ), SFVEC3F( leftStart.x + texture_factor * factorE.x, leftStart.y + texture_factor * factorE.y, layer_z_top ), SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf(2.0f), start.y - texture_factorF * leftDir.y * radius * sqrtf(2.0f), layer_z_top ) ); layerTriangles->m_layer_top_segment_ends->AddTriangle( SFVEC3F( leftEnd.x + texture_factor * factorE.x, leftEnd.y + texture_factor * factorE.y, layer_z_top ), SFVEC3F( rightStart.x + texture_factor * factorS.x, rightStart.y + texture_factor * factorS.y, layer_z_top ), SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf(2.0f), end.y - texture_factorF * rightDir.y * radius * sqrtf(2.0f), layer_z_top ) ); // Bot end segment triangles layerTriangles->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( leftStart.x + texture_factor * factorE.x, leftStart.y + texture_factor * factorE.y, layer_z_bot ), SFVEC3F( rightEnd.x + texture_factor * factorS.x, rightEnd.y + texture_factor * factorS.y, layer_z_bot ), SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf(2.0f), start.y - texture_factorF * leftDir.y * radius * sqrtf(2.0f), layer_z_bot ) ); layerTriangles->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( rightStart.x + texture_factor * factorS.x, rightStart.y + texture_factor * factorS.y, layer_z_bot ), SFVEC3F( leftEnd.x + texture_factor * factorE.x, leftEnd.y + texture_factor * factorE.y, layer_z_bot ), SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf(2.0f), end.y - texture_factorF * rightDir.y * radius * sqrtf(2.0f), layer_z_bot ) ); // Segment top and bot planes layerTriangles->m_layer_top_triangles->AddQuad( SFVEC3F( rightEnd.x, rightEnd.y, layer_z_top ), SFVEC3F( rightStart.x, rightStart.y, layer_z_top ), SFVEC3F( leftEnd.x, leftEnd.y, layer_z_top ), SFVEC3F( leftStart.x, leftStart.y, layer_z_top ) ); layerTriangles->m_layer_bot_triangles->AddQuad( SFVEC3F( rightEnd.x, rightEnd.y, layer_z_bot ), SFVEC3F( leftStart.x, leftStart.y, layer_z_bot ), SFVEC3F( leftEnd.x, leftEnd.y, layer_z_bot ), SFVEC3F( rightStart.x, rightStart.y, layer_z_bot ) ); // Middle contourns (two sides of the segment) layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( leftStart.x, leftStart.y, layer_z_top ), SFVEC3F( leftEnd.x, leftEnd.y, layer_z_top ), SFVEC3F( leftEnd.x, leftEnd.y, layer_z_bot ), SFVEC3F( leftStart.x, leftStart.y, layer_z_bot ) ); const SFVEC3F leftNormal = SFVEC3F( -leftDir.y, leftDir.x, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( leftNormal, leftNormal, leftNormal, leftNormal ); layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( rightStart.x, rightStart.y, layer_z_top ), SFVEC3F( rightEnd.x, rightEnd.y, layer_z_top ), SFVEC3F( rightEnd.x, rightEnd.y, layer_z_bot ), SFVEC3F( rightStart.x, rightStart.y, layer_z_bot ) ); const SFVEC3F rightNormal = SFVEC3F( -rightDir.y, rightDir.x, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( rightNormal, rightNormal, rightNormal, rightNormal ); // Compute the outlines of the segment, and creates a polygon // add right rounded end: std::vector< SFVEC2F > roundedEndPointsStart; std::vector< SFVEC2F > roundedEndPointsEnd; roundedEndPointsStart.clear(); roundedEndPointsStart.reserve( nr_sides_per_circle + 2 ); roundedEndPointsEnd.clear(); roundedEndPointsEnd.reserve( nr_sides_per_circle + 2 ); roundedEndPointsStart.push_back( SFVEC2F( leftStart.x, leftStart.y ) ); roundedEndPointsEnd.push_back( SFVEC2F( leftEnd.x, leftEnd.y ) ); int delta = 3600 / nr_sides_per_circle; for( int ii = delta; ii < 1800; ii += delta ) { const SFVEC2F rotatedDirL = glm::rotate( leftDir, (float) ii * 2.0f * 3.14f / 3600.0f ); const SFVEC2F rotatedDirR = glm::rotate( rightDir, (float)(1800 - ii) * 2.0f * 3.14f / 3600.0f ); roundedEndPointsStart.push_back( SFVEC2F( start.x - rotatedDirL.y * radius, start.y + rotatedDirL.x * radius ) ); roundedEndPointsEnd.push_back( SFVEC2F( end.x - rotatedDirR.y * radius, end.y + rotatedDirR.x * radius ) ); } roundedEndPointsStart.push_back( SFVEC2F( rightEnd.x, rightEnd.y ) ); roundedEndPointsEnd.push_back( SFVEC2F( rightStart.x, rightStart.y ) ); if( roundedEndPointsStart.size() > 1 ) { for( unsigned int i = 0; i < ( roundedEndPointsStart.size() - 1 ); ++i ) { const SFVEC2F &v0 = roundedEndPointsStart[i + 0]; const SFVEC2F &v1 = roundedEndPointsStart[i + 1]; layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, layer_z_bot ), SFVEC3F( v1.x, v1.y, layer_z_bot ), SFVEC3F( v1.x, v1.y, layer_z_top ), SFVEC3F( v0.x, v0.y, layer_z_top ) ); const SFVEC2F n0 = glm::normalize( v0 - start ); const SFVEC2F n1 = glm::normalize( v1 - start ); const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z ); } } roundedEndPointsStart.clear(); if( roundedEndPointsEnd.size() > 1 ) { for( unsigned int i = 0; i < ( roundedEndPointsEnd.size() - 1 ); ++i ) { const SFVEC2F &v0 = roundedEndPointsEnd[i + 0]; const SFVEC2F &v1 = roundedEndPointsEnd[i + 1]; layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, layer_z_top ), SFVEC3F( v1.x, v1.y, layer_z_top ), SFVEC3F( v1.x, v1.y, layer_z_bot ), SFVEC3F( v0.x, v0.y, layer_z_bot ) ); const SFVEC2F n0 = glm::normalize( v0 - end ); const SFVEC2F n1 = glm::normalize( v1 - end ); const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f ); layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z ); } } roundedEndPointsEnd.clear(); } break; default: { } break; } #if 0 // not yet used / implemented (can be used in future to clip the objects in the board borders COBJECT2D *object2d_C = CSGITEM_FULL; std::vector<const COBJECT2D *> *object2d_B = CSGITEM_EMPTY; if( m_settings.GetFlag( FL_RENDER_SHOW_HOLES_IN_ZONES ) ) { object2d_B = new std::vector<const COBJECT2D *>(); // Check if there are any layerhole that intersects this object // Eg: a segment is cutted by a via hole or THT hole. // ///////////////////////////////////////////////////////////// const MAP_CONTAINER_2D &layerHolesMap = m_settings.GetMapLayersHoles(); if( layerHolesMap.find(layer_id) != layerHolesMap.end() ) { MAP_CONTAINER_2D::const_iterator ii_hole = layerHolesMap.find(layer_id); const CBVHCONTAINER2D *containerLayerHoles2d = static_cast<const CBVHCONTAINER2D *>(ii_hole->second); CONST_LIST_OBJECT2D intersectionList; containerLayerHoles2d->GetListObjectsIntersects( object2d_A->GetBBox(), intersectionList ); if( !intersectionList.empty() ) { for( CONST_LIST_OBJECT2D::const_iterator holeOnLayer = intersectionList.begin(); holeOnLayer != intersectionList.end(); holeOnLayer++ ) { const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*holeOnLayer); //if( object2d_A->Intersects( hole2d->GetBBox() ) ) //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) ) object2d_B->push_back( hole2d ); } } } // Check if there are any THT that intersects this object // ///////////////////////////////////////////////////////////// if( !m_settings.GetThroughHole_Inflated().GetList().empty() ) { CONST_LIST_OBJECT2D intersectionList; m_settings.GetThroughHole_Inflated().GetListObjectsIntersects( object2d_A->GetBBox(), intersectionList ); if( !intersectionList.empty() ) { for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin(); hole != intersectionList.end(); hole++ ) { const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole); //if( object2d_A->Intersects( hole2d->GetBBox() ) ) //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) ) object2d_B->push_back( hole2d ); } } } if( object2d_B->empty() ) { delete object2d_B; object2d_B = CSGITEM_EMPTY; } } if( (object2d_B == CSGITEM_EMPTY) && (object2d_C == CSGITEM_FULL) ) { #if 0 create_3d_object_from( m_object_container, object2d_A, m_settings.GetLayerBottomZpos3DU( layer_id ), m_settings.GetLayerTopZpos3DU( layer_id ), materialLayer, layerColor ); #else CLAYERITEM *objPtr = new CLAYERITEM( object2d_A, m_settings.GetLayerBottomZpos3DU( layer_id ), m_settings.GetLayerTopZpos3DU( layer_id ) ); objPtr->SetMaterial( materialLayer ); objPtr->SetColor( layerColor ); m_object_container.Add( objPtr ); #endif } else { #if 1 CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A, object2d_B, object2d_C, object2d_A->GetBoardItem() ); m_containerWithObjectsToDelete.Add( itemCSG2d ); CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, m_settings.GetLayerBottomZpos3DU( layer_id ), m_settings.GetLayerTopZpos3DU( layer_id ) ); objPtr->SetMaterial( materialLayer ); objPtr->SetColor( layerColor ); m_object_container.Add( objPtr ); #endif } #endif } // Create display list // ///////////////////////////////////////////////////////////////////// m_ogl_disp_lists_layers[layer_id] = new CLAYERS_OGL_DISP_LISTS( *layerTriangles, m_ogl_circle_texture, layerColor ); }// for each layer on map }
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CROUNDSEGMENT2D * aSeg, CLAYER_TRIANGLES *aDstLayer, float aZtop, float aZbot ) { const SFVEC2F leftStart = aSeg->GetLeftStar(); const SFVEC2F leftEnd = aSeg->GetLeftEnd(); const SFVEC2F leftDir = aSeg->GetLeftDir(); const SFVEC2F rightStart = aSeg->GetRightStar(); const SFVEC2F rightEnd = aSeg->GetRightEnd(); const SFVEC2F rightDir = aSeg->GetRightDir(); const float radius = aSeg->GetRadius(); const SFVEC2F start = aSeg->GetStart(); const SFVEC2F end = aSeg->GetEnd(); const float texture_factor = (12.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f; const float texture_factorF= ( 6.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f; const float radius_of_the_square = sqrtf( aSeg->GetRadiusSquared() * 2.0f ); const float radius_triangle_factor = (radius_of_the_square - radius) / radius; const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor, rightDir.x * radius * radius_triangle_factor ); const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor, leftDir.x * radius * radius_triangle_factor ); // Top end segment triangles (semi-circles) aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( rightEnd.x + texture_factor * factorS.x, rightEnd.y + texture_factor * factorS.y, aZtop ), SFVEC3F( leftStart.x + texture_factor * factorE.x, leftStart.y + texture_factor * factorE.y, aZtop ), SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ), start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ), aZtop ) ); aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( leftEnd.x + texture_factor * factorE.x, leftEnd.y + texture_factor * factorE.y, aZtop ), SFVEC3F( rightStart.x + texture_factor * factorS.x, rightStart.y + texture_factor * factorS.y, aZtop ), SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ), end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ), aZtop ) ); // Bot end segment triangles (semi-circles) aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( leftStart.x + texture_factor * factorE.x, leftStart.y + texture_factor * factorE.y, aZbot ), SFVEC3F( rightEnd.x + texture_factor * factorS.x, rightEnd.y + texture_factor * factorS.y, aZbot ), SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ), start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ), aZbot ) ); aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( rightStart.x + texture_factor * factorS.x, rightStart.y + texture_factor * factorS.y, aZbot ), SFVEC3F( leftEnd.x + texture_factor * factorE.x, leftEnd.y + texture_factor * factorE.y, aZbot ), SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ), end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ), aZbot ) ); // Segment top and bot planes aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( rightEnd.x, rightEnd.y, aZtop ), SFVEC3F( rightStart.x, rightStart.y, aZtop ), SFVEC3F( leftEnd.x, leftEnd.y, aZtop ), SFVEC3F( leftStart.x, leftStart.y, aZtop ) ); aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( rightEnd.x, rightEnd.y, aZbot ), SFVEC3F( leftStart.x, leftStart.y, aZbot ), SFVEC3F( leftEnd.x, leftEnd.y, aZbot ), SFVEC3F( rightStart.x, rightStart.y, aZbot ) ); }
bool CVCYLINDER::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const { // Based on: // http://www.cs.utah.edu/~lha/Code%206620%20/Ray4/Cylinder.cpp // Ray-sphere intersection: geometric // ///////////////////////////////////////////////////////////////////////// const double OCx_Start = aRay.m_Origin.x - m_center.x; const double OCy_Start = aRay.m_Origin.y - m_center.y; const double p_dot_p = OCx_Start * OCx_Start + OCy_Start * OCy_Start; const double a = (double)aRay.m_Dir.x * (double)aRay.m_Dir.x + (double)aRay.m_Dir.y * (double)aRay.m_Dir.y; const double b = (double)aRay.m_Dir.x * (double)OCx_Start + (double)aRay.m_Dir.y * (double)OCy_Start; const double c = p_dot_p - m_radius_squared; const float delta = (float)(b * b - a * c); bool hitResult = false; if( delta > FLT_EPSILON ) { const float inv_a = 1.0 / a; const float sdelta = sqrtf( delta ); const float t = (-b - sdelta) * inv_a; const float z = aRay.m_Origin.z + t * aRay.m_Dir.z; if( (z >= m_bbox.Min().z) && (z <= m_bbox.Max().z) ) { if( t < aHitInfo.m_tHit ) { hitResult = true; aHitInfo.m_tHit = t; } } if( !hitResult ) { const float t1 = (-b + sdelta) * inv_a; const float z1 = aRay.m_Origin.z + t1 * aRay.m_Dir.z; if( (z1 > m_bbox.Min().z ) && (z1 < m_bbox.Max().z ) ) { if( t1 < aHitInfo.m_tHit ) { hitResult = true; aHitInfo.m_tHit = t1; } } } } if( hitResult ) { aHitInfo.m_HitPoint = aRay.at( aHitInfo.m_tHit ); const SFVEC2F hitPoint2D = SFVEC2F( aHitInfo.m_HitPoint.x, aHitInfo.m_HitPoint.y ); aHitInfo.m_HitNormal = SFVEC3F( -(hitPoint2D.x - m_center.x) * m_inv_radius, -(hitPoint2D.y - m_center.y) * m_inv_radius, 0.0f ); m_material->PerturbeNormal( aHitInfo.m_HitNormal, aRay, aHitInfo ); aHitInfo.pHitObject = this; } return hitResult; }
void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks( const SHAPE_POLY_SET &aMainPath, CGENERICCONTAINER2D &aDstContainer, float aBiuTo3DunitsScale, float aDivFactor, const BOARD_ITEM &aBoardItem ) { BOX2I pathBounds = aMainPath.BBox(); // Get the path wxASSERT( aMainPath.OutlineCount() == 1 ); const SHAPE_POLY_SET::POLYGON& curr_polywithholes = aMainPath.CPolygon( 0 ); wxASSERT( curr_polywithholes.size() == 1 ); const SHAPE_LINE_CHAIN& path = curr_polywithholes[0]; // a simple polygon // Convert the points to segments class CBBOX2D bbox; bbox.Reset(); // Contains the main list of segments and each segment normal interpolated SEGMENTS_WIDTH_NORMALS segments_and_normals; // Contains a closed polygon used to calc if points are inside SEGMENTS segments; segments_and_normals.resize( path.PointCount() ); segments.resize( path.PointCount() ); for( int i = 0; i < path.PointCount(); i++ ) { const VECTOR2I& a = path.CPoint( i ); const SFVEC2F point ( (float)( a.x) * aBiuTo3DunitsScale, (float)(-a.y) * aBiuTo3DunitsScale ); bbox.Union( point ); segments_and_normals[i].m_Start = point; segments[i].m_Start = point; } bbox.ScaleNextUp(); // Calc the slopes, normals and some statistics about this polygon unsigned int i; unsigned int j = segments_and_normals.size() - 1; // Temporary normal to the segment, it will later be used for interpolation std::vector< SFVEC2F > tmpSegmentNormals; tmpSegmentNormals.resize( segments_and_normals.size() ); float medOfTheSquaresSegmentLength = 0.0f; #ifdef PRINT_STATISTICS_3D_VIEWER float minLength = FLT_MAX; #endif for( i = 0; i < segments_and_normals.size(); j = i++ ) { const SFVEC2F slope = segments_and_normals[j].m_Start - segments_and_normals[i].m_Start; segments_and_normals[i].m_Precalc_slope = slope; // Calculate constants for each segment segments[i].m_inv_JY_minus_IY = 1.0f / ( segments_and_normals[j].m_Start.y - segments_and_normals[i].m_Start.y ); segments[i].m_JX_minus_IX = ( segments_and_normals[j].m_Start.x - segments_and_normals[i].m_Start.x ); // The normal orientation expect a fixed polygon orientation (!TODO: which one?) //tmpSegmentNormals[i] = glm::normalize( SFVEC2F( -slope.y, +slope.x ) ); tmpSegmentNormals[i] = glm::normalize( SFVEC2F( slope.y, -slope.x ) ); const float length = slope.x * slope.x + slope.y * slope.y; #ifdef PRINT_STATISTICS_3D_VIEWER if( length < minLength ) minLength = length; #endif medOfTheSquaresSegmentLength += length; } #ifdef PRINT_STATISTICS_3D_VIEWER float minSegmentLength = sqrt( minLength ); #endif // This calc an approximation of medium lengths, that will be used to calc // the size of the division. medOfTheSquaresSegmentLength /= segments_and_normals.size(); medOfTheSquaresSegmentLength = sqrt( medOfTheSquaresSegmentLength ); // Compute the normal interpolation // If calculate the dot between the segments, if they are above/below some // threshould it will not interpolated it (ex: if you are in a edge corner // or in a smooth transaction) j = segments_and_normals.size() - 1; for( i = 0; i < segments_and_normals.size(); j = i++ ) { const SFVEC2F normalBeforeSeg = tmpSegmentNormals[j]; const SFVEC2F normalSeg = tmpSegmentNormals[i]; const SFVEC2F normalAfterSeg = tmpSegmentNormals[ (i + 1) % segments_and_normals.size() ]; const float dotBefore = glm::dot( normalBeforeSeg, normalSeg ); const float dotAfter = glm::dot( normalAfterSeg, normalSeg ); if( dotBefore < 0.7f ) segments_and_normals[i].m_Normals.m_Start = normalSeg; else segments_and_normals[i].m_Normals.m_Start = glm::normalize( (((normalBeforeSeg * dotBefore ) + normalSeg) * 0.5f) ); if( dotAfter < 0.7f ) segments_and_normals[i].m_Normals.m_End = normalSeg; else segments_and_normals[i].m_Normals.m_End = glm::normalize( (((normalAfterSeg * dotAfter ) + normalSeg) * 0.5f) ); } if( aDivFactor == 0.0f ) aDivFactor = medOfTheSquaresSegmentLength; SFVEC2UI grid_divisions; grid_divisions.x = (unsigned int)( (bbox.GetExtent().x / aDivFactor) ); grid_divisions.y = (unsigned int)( (bbox.GetExtent().y / aDivFactor) ); grid_divisions = glm::clamp( grid_divisions , SFVEC2UI( 1, 1 ), SFVEC2UI( MAX_NR_DIVISIONS, MAX_NR_DIVISIONS ) ); // Calculate the steps advance of the grid SFVEC2F blockAdvance; blockAdvance.x = bbox.GetExtent().x / (float)grid_divisions.x; blockAdvance.y = bbox.GetExtent().y / (float)grid_divisions.y; wxASSERT( blockAdvance.x > 0.0f ); wxASSERT( blockAdvance.y > 0.0f ); const int leftToRight_inc = (pathBounds.GetRight() - pathBounds.GetLeft()) / grid_divisions.x; const int topToBottom_inc = (pathBounds.GetBottom() - pathBounds.GetTop()) / grid_divisions.y; // Statistics unsigned int stats_n_empty_blocks = 0; unsigned int stats_n_dummy_blocks = 0; unsigned int stats_n_poly_blocks = 0; unsigned int stats_sum_size_of_polygons = 0; // Step by each block of a grid trying to extract segments and create // polygon blocks int topToBottom = pathBounds.GetTop(); float blockY = bbox.Max().y; for( unsigned int iy = 0; iy < grid_divisions.y; iy++ ) { int leftToRight = pathBounds.GetLeft(); float blockX = bbox.Min().x; for( unsigned int ix = 0; ix < grid_divisions.x; ix++ ) { CBBOX2D blockBox( SFVEC2F( blockX, blockY - blockAdvance.y ), SFVEC2F( blockX + blockAdvance.x, blockY ) ); // Make the box large to it will catch (intersect) the edges blockBox.ScaleNextUp(); blockBox.ScaleNextUp(); blockBox.ScaleNextUp(); SEGMENTS_WIDTH_NORMALS extractedSegments; extractPathsFrom( segments_and_normals, blockBox, extractedSegments ); if( extractedSegments.empty() ) { SFVEC2F p1( blockBox.Min().x, blockBox.Min().y ); SFVEC2F p2( blockBox.Max().x, blockBox.Min().y ); SFVEC2F p3( blockBox.Max().x, blockBox.Max().y ); SFVEC2F p4( blockBox.Min().x, blockBox.Max().y ); if( polygon_IsPointInside( segments, p1 ) || polygon_IsPointInside( segments, p2 ) || polygon_IsPointInside( segments, p3 ) || polygon_IsPointInside( segments, p4 ) ) { // In this case, the segments are not intersecting the // polygon, so it means that if any point is inside it, // then all other are inside the polygon. // This is a full bbox inside, so add a dummy box aDstContainer.Add( new CDUMMYBLOCK2D( blockBox, aBoardItem ) ); stats_n_dummy_blocks++; } else { // Points are outside, so this block complety missed the polygon // In this case, no objects need to be added stats_n_empty_blocks++; } } else { // At this point, the borders of polygon were intersected by the // bounding box, so we must calculate a new polygon that will // close that small block. // This block will be used to calculate if points are inside // the (sub block) polygon. SHAPE_POLY_SET subBlockPoly; SHAPE_LINE_CHAIN sb = SHAPE_LINE_CHAIN( VECTOR2I( leftToRight, topToBottom ), VECTOR2I( leftToRight + leftToRight_inc, topToBottom ), VECTOR2I( leftToRight + leftToRight_inc, topToBottom + topToBottom_inc ), VECTOR2I( leftToRight, topToBottom + topToBottom_inc ) ); //sb.Append( leftToRight, topToBottom ); sb.SetClosed( true ); subBlockPoly.AddOutline( sb ); // We need here a strictly simple polygon with outlines and holes SHAPE_POLY_SET solution; solution.BooleanIntersection( aMainPath, subBlockPoly, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); OUTERS_AND_HOLES outersAndHoles; outersAndHoles.m_Holes.clear(); outersAndHoles.m_Outers.clear(); for( int idx = 0; idx < solution.OutlineCount(); idx++ ) { const SHAPE_LINE_CHAIN & outline = solution.Outline( idx ); SEGMENTS solutionSegment; polygon_Convert( outline, solutionSegment, aBiuTo3DunitsScale ); outersAndHoles.m_Outers.push_back( solutionSegment ); stats_sum_size_of_polygons += solutionSegment.size(); for( int holeIdx = 0; holeIdx < solution.HoleCount( idx ); holeIdx++ ) { const SHAPE_LINE_CHAIN & hole = solution.Hole( idx, holeIdx ); polygon_Convert( hole, solutionSegment, aBiuTo3DunitsScale ); outersAndHoles.m_Holes.push_back( solutionSegment ); stats_sum_size_of_polygons += solutionSegment.size(); } } if( !outersAndHoles.m_Outers.empty() ) { aDstContainer.Add( new CPOLYGONBLOCK2D( extractedSegments, outersAndHoles, aBoardItem ) ); stats_n_poly_blocks++; } } blockX += blockAdvance.x; leftToRight += leftToRight_inc; } blockY -= blockAdvance.y; topToBottom += topToBottom_inc; } #ifdef PRINT_STATISTICS_3D_VIEWER printf( "////////////////////////////////////////////////////////////////////////////////\n" ); printf( "Convert_path_polygon_to_polygon_blocks_and_dummy_blocks\n" ); printf( " grid_divisions (%u, %u)\n", grid_divisions.x, grid_divisions.y ); printf( " N Total Blocks %u\n", grid_divisions.x * grid_divisions.y ); printf( " N Empty Blocks %u\n", stats_n_empty_blocks ); printf( " N Dummy Blocks %u\n", stats_n_dummy_blocks ); printf( " N Polyg Blocks %u\n", stats_n_poly_blocks ); printf( " Med N Seg Poly %u\n", stats_sum_size_of_polygons / stats_n_poly_blocks ); printf( " medOfTheSquaresSegmentLength %f\n", medOfTheSquaresSegmentLength ); printf( " minSegmentLength %f\n", minSegmentLength ); printf( " aDivFactor %f\n", aDivFactor ); printf( "////////////////////////////////////////////////////////////////////////////////\n" ); #endif }
void Convert_shape_line_polygon_to_triangles( const SHAPE_POLY_SET &aPolyList, CGENERICCONTAINER2D &aDstContainer, float aBiuTo3DunitsScale , const BOARD_ITEM &aBoardItem ) { unsigned int nOutlines = aPolyList.OutlineCount(); for( unsigned int idx = 0; idx < nOutlines; ++idx ) { const SHAPE_LINE_CHAIN &outlinePath = aPolyList.COutline( idx ); wxASSERT( outlinePath.PointCount() >= 3 ); std::vector<SFVEC2I64> scaledOutline; scaledOutline.resize( outlinePath.PointCount() ); // printf("\nidx: %u\n", idx); // Apply a scale to the points for( unsigned int i = 0; i < (unsigned int)outlinePath.PointCount(); ++i ) { const VECTOR2I& a = outlinePath.CPoint( i ); #ifdef APPLY_EDGE_SHRINK scaledOutline[i] = SFVEC2I64( (glm::int64)a.x * POLY_SCALE_FACT, (glm::int64)a.y * POLY_SCALE_FACT ); #else scaledOutline[i] = SFVEC2I64( (glm::int64)a.x, (glm::int64)a.y ); #endif } #ifdef APPLY_EDGE_SHRINK // Apply a modification to the points EdgeShrink( scaledOutline ); #endif // Copy to a array of pointers std::vector<p2t::Point*> polyline; polyline.resize( outlinePath.PointCount() ); for( unsigned int i = 0; i < (unsigned int)scaledOutline.size(); ++i ) { const SFVEC2I64 &a = scaledOutline[i]; //printf("%lu %lu\n", a.x, a.y); polyline[i] = new p2t::Point( (double)a.x, (double)a.y ); } // Start creating the structured to be triangulated p2t::CDT* cdt = new p2t::CDT( polyline ); // Add holes for this outline unsigned int nHoles = aPolyList.HoleCount( idx ); std::vector< std::vector<p2t::Point*> > polylineHoles; polylineHoles.resize( nHoles ); for( unsigned int idxHole = 0; idxHole < nHoles; ++idxHole ) { const SHAPE_LINE_CHAIN &outlineHoles = aPolyList.CHole( idx, idxHole ); wxASSERT( outlineHoles.PointCount() >= 3 ); std::vector<SFVEC2I64> scaledHole; scaledHole.resize( outlineHoles.PointCount() ); // Apply a scale to the points for( unsigned int i = 0; i < (unsigned int)outlineHoles.PointCount(); ++i ) { const VECTOR2I &h = outlineHoles.CPoint( i ); #ifdef APPLY_EDGE_SHRINK scaledHole[i] = SFVEC2I64( (glm::int64)h.x * POLY_SCALE_FACT, (glm::int64)h.y * POLY_SCALE_FACT ); #else scaledHole[i] = SFVEC2I64( (glm::int64)h.x, (glm::int64)h.y ); #endif } #ifdef APPLY_EDGE_SHRINK // Apply a modification to the points EdgeShrink( scaledHole ); #endif // Resize and reserve space polylineHoles[idxHole].resize( outlineHoles.PointCount() ); for( unsigned int i = 0; i < (unsigned int)outlineHoles.PointCount(); ++i ) { const SFVEC2I64 &h = scaledHole[i]; polylineHoles[idxHole][i] = new p2t::Point( h.x, h.y ); } cdt->AddHole( polylineHoles[idxHole] ); } // Triangulate cdt->Triangulate(); // Hint: if you find any crashes on the triangulation poly2tri library, // you can use the following site to debug the points and it will mark // the errors in the polygon: // http://r3mi.github.io/poly2tri.js/ // Get and add triangles std::vector<p2t::Triangle*> triangles; triangles = cdt->GetTriangles(); #ifdef APPLY_EDGE_SHRINK const double conver_d = (double)aBiuTo3DunitsScale * POLY_SCALE_FACT_INVERSE; #else const double conver_d = (double)aBiuTo3DunitsScale; #endif for( unsigned int i = 0; i < triangles.size(); ++i ) { p2t::Triangle& t = *triangles[i]; p2t::Point& a = *t.GetPoint( 0 ); p2t::Point& b = *t.GetPoint( 1 ); p2t::Point& c = *t.GetPoint( 2 ); aDstContainer.Add( new CTRIANGLE2D( SFVEC2F( a.x * conver_d, -a.y * conver_d ), SFVEC2F( b.x * conver_d, -b.y * conver_d ), SFVEC2F( c.x * conver_d, -c.y * conver_d ), aBoardItem ) ); } // Delete created data delete cdt; // Free points FreeClear(polyline); for( unsigned int idxHole = 0; idxHole < nHoles; ++idxHole ) { FreeClear( polylineHoles[idxHole] ); } } }
GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends( const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer, bool aIsNormalUp, GLuint aTextureId ) const { wxASSERT( aTriangleContainer != NULL ); wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 ); // Top and Bot dont have normals array stored in container wxASSERT( aTriangleContainer->GetNormalsSize() == 0 ); if( (aTriangleContainer->GetVertexSize() > 0) && ((aTriangleContainer->GetVertexSize() % 3) == 0) ) { GLuint listIdx = glGenLists( 1 ); if( glIsList( listIdx ) ) { // Prepare an array of UV text coordinates SFVEC2F *uvArray = new SFVEC2F[aTriangleContainer->GetVertexSize()]; for( unsigned int i = 0; i < aTriangleContainer->GetVertexSize(); i += 3 ) { uvArray[i + 0] = SFVEC2F( 1.0f, 0.0f ); uvArray[i + 1] = SFVEC2F( 0.0f, 1.0f ); uvArray[i + 2] = SFVEC2F( 0.0f, 0.0f ); } glEnableClientState( GL_TEXTURE_COORD_ARRAY ); glDisableClientState( GL_COLOR_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() ); glTexCoordPointer( 2, GL_FLOAT, 0, uvArray ); glNewList( listIdx, GL_COMPILE ); glDisable( GL_COLOR_MATERIAL ); glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, aTextureId ); setBlendfunction(); glAlphaFunc( GL_GREATER, 0.2f ); glEnable( GL_ALPHA_TEST ); glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f ); glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() ); glDisable( GL_TEXTURE_2D ); glDisable( GL_ALPHA_TEST ); glDisable( GL_BLEND ); glEndList(); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); delete [] uvArray; return listIdx; } } return 0; }
void CLAYER_TRIANGLES::AddToMiddleContourns( const std::vector< SFVEC2F > &aContournPoints, float zBot, float zTop, bool aInvertFaceDirection ) { if( aContournPoints.size() > 4 ) { // Calculate normals of each segment of the contourn std::vector< SFVEC2F > contournNormals; contournNormals.clear(); contournNormals.resize( aContournPoints.size() - 1 ); if( aInvertFaceDirection ) { for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i ) { const SFVEC2F &v0 = aContournPoints[i + 0]; const SFVEC2F &v1 = aContournPoints[i + 1]; const SFVEC2F n = glm::normalize( v1 - v0 ); contournNormals[i] = SFVEC2F( n.y,-n.x ); } } else { for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i ) { const SFVEC2F &v0 = aContournPoints[i + 0]; const SFVEC2F &v1 = aContournPoints[i + 1]; const SFVEC2F n = glm::normalize( v1 - v0 ); contournNormals[i] = SFVEC2F( -n.y, n.x ); } } if( aInvertFaceDirection ) std::swap( zBot, zTop ); const unsigned int nContournsToProcess = ( aContournPoints.size() - 1 ); for( unsigned int i = 0; i < nContournsToProcess; ++i ) { SFVEC2F lastNormal; if( i > 0 ) lastNormal = contournNormals[i - 1]; else lastNormal = contournNormals[nContournsToProcess - 1]; SFVEC2F n0 = contournNormals[i]; // Only interpolate the normal if the angle is closer if( glm::dot( n0, lastNormal ) > 0.5f ) n0 = glm::normalize( n0 + lastNormal ); SFVEC2F nextNormal; if( i < (nContournsToProcess - 1) ) nextNormal = contournNormals[i + 1]; else nextNormal = contournNormals[0]; SFVEC2F n1 = contournNormals[i]; if( glm::dot( n1, nextNormal ) > 0.5f ) n1 = glm::normalize( n1 + nextNormal ); const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f ); const SFVEC2F &v0 = aContournPoints[i + 0]; const SFVEC2F &v1 = aContournPoints[i + 1]; #pragma omp critical { m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ), SFVEC3F( v1.x, v1.y, zTop ), SFVEC3F( v1.x, v1.y, zBot ), SFVEC3F( v0.x, v0.y, zBot ) ); m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 ); } } } }
void Polygon2d_TestModule() { // "This structure contains a sequence of IntPoint vertices defining a // single contour" ClipperLib::Path aPath; SEGMENTS aSegments; aPath.resize( 4 ); aPath[0] = ClipperLib::IntPoint( -2, -2 ); aPath[1] = ClipperLib::IntPoint( 2, -2 ); aPath[2] = ClipperLib::IntPoint( 2, 2 ); aPath[3] = ClipperLib::IntPoint( -2, 2 ); // It must be an outter polygon wxASSERT( ClipperLib::Orientation( aPath ) ); polygon_Convert( aPath, aSegments, 1.0f ); wxASSERT( aPath.size() == aSegments.size() ); wxASSERT( aSegments[0].m_Start == SFVEC2F( -2.0f, 2.0f ) ); wxASSERT( aSegments[1].m_Start == SFVEC2F( 2.0f, 2.0f ) ); wxASSERT( aSegments[2].m_Start == SFVEC2F( 2.0f, -2.0f ) ); wxASSERT( aSegments[3].m_Start == SFVEC2F( -2.0f, -2.0f ) ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 0.0f, 0.0f ) ) ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -1.9f, -1.9f ) ) ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -1.9f, 1.9f ) ) ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 1.9f, 1.9f ) ) ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 1.9f, -1.9f ) ) ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -2.1f, -2.0f ) ) == false ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( -2.1f, 2.0f ) ) == false ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 2.1f, 2.0f ) ) == false ); wxASSERT( polygon_IsPointInside( aSegments, SFVEC2F( 2.1f, -2.0f ) ) == false ); }
bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const { wxASSERT( aOutT ); wxASSERT( aNormalOut ); bool start_is_inside = IsPointInside( aSegRay.m_Start ); bool end_is_inside = IsPointInside( aSegRay.m_End ); // If segment if inside there are no hits if( start_is_inside && end_is_inside ) return false; bool hitted = false; float closerHitT = FLT_MAX; float farHitT = FLT_MAX; SFVEC2F closerHitNormal; SFVEC2F farHitNormal; float leftSegT; bool leftSegmentHit = aSegRay.IntersectSegment( m_leftStart, m_leftEnd_minus_start, &leftSegT ); if( leftSegmentHit ) { hitted = true; closerHitT = leftSegT; farHitT = leftSegT; closerHitNormal = SFVEC2F( -m_leftDir.y, m_leftDir.x ); farHitNormal = SFVEC2F( -m_leftDir.y, m_leftDir.x ); } float rightSegT; bool rightSegmentHit = aSegRay.IntersectSegment( m_rightStart, m_rightEnd_minus_start, &rightSegT ); if( rightSegmentHit ) { if( !start_is_inside ) if( (hitted == false) || (rightSegT < closerHitT) ) { closerHitT = rightSegT; closerHitNormal = SFVEC2F( -m_rightDir.y, m_rightDir.x ); } if( start_is_inside ) if( (hitted == false) || (rightSegT > farHitT) ) { farHitT = rightSegT; farHitNormal = SFVEC2F( -m_rightDir.y, m_rightDir.x ); } hitted = true; } float circleStart_T0; float circleStart_T1; SFVEC2F circleStart_N0; SFVEC2F circleStart_N1; bool startCircleHit = aSegRay.IntersectCircle( m_segment.m_Start, m_radius, &circleStart_T0, &circleStart_T1, &circleStart_N0, &circleStart_N1 ); if( startCircleHit ) { if( circleStart_T0 > 0.0f ) { if( !start_is_inside ) if( (hitted == false) || (circleStart_T0 < closerHitT) ) { closerHitT = circleStart_T0; closerHitNormal = circleStart_N0; } if( start_is_inside ) if( (hitted == false) || (circleStart_T1 > farHitT) ) { farHitT = circleStart_T1; farHitNormal = circleStart_N1; } } else { // This can only happen if the ray starts inside if( (hitted == false) || (circleStart_T1 > farHitT) ) { farHitT = circleStart_T1; farHitNormal = circleStart_N1; } } hitted = true; } float circleEnd_T0; float circleEnd_T1; SFVEC2F circleEnd_N0; SFVEC2F circleEnd_N1; bool rightCircleHit = aSegRay.IntersectCircle( m_segment.m_End, m_radius, &circleEnd_T0, &circleEnd_T1, &circleEnd_N0, &circleEnd_N1 ); if( rightCircleHit ) { if( circleEnd_T0 > 0.0f ) { if( !start_is_inside ) if( (hitted == false) || (circleEnd_T0 < closerHitT) ) { closerHitT = circleEnd_T0; closerHitNormal = circleEnd_N0; } if( start_is_inside ) if( (hitted == false) || (circleEnd_T1 > farHitT) ) { farHitT = circleEnd_T1; farHitNormal = circleEnd_N1; } } else { // This can only happen if the ray starts inside if( (hitted == false) || (circleEnd_T1 > farHitT) ) { farHitT = circleEnd_T1; farHitNormal = circleEnd_N1; } } hitted = true; } if( hitted ) { if( !start_is_inside ) { *aOutT = closerHitT; //wxASSERT( (closerHitT > 0.0f) && (closerHitT <= 1.0f) ); *aNormalOut = closerHitNormal; } else { wxASSERT( (farHitT > 0.0f) && (farHitT <= 1.0f) ); *aOutT = farHitT; *aNormalOut = farHitNormal; } } return hitted; }