// Requires mesh with add vertex, add face // Smoother/higher res mesh is made using subdivision void MakeSphere() { const int iSpace = 5; const int iNTheta = m_iNHoles * iSpace; const int iNPhi = 12; const int iTop = 2, iBot = 8; const double dTheta = 2.0 * M_PI / (double) (iNTheta); const double dPhi = M_PI / (double) (iNPhi - 1.0); Array aopVs; PMSubdivMesh &out_mesh = m_meshSphereWithHoles; for (int i = 0; i < iNPhi; i++) { const double dC = cos( i * dPhi - M_PI / 2.0 ); const double dS = sin( i * dPhi - M_PI / 2.0 ); if ( i == 0 || i == iNPhi - 1 ) { aopVs += &out_mesh.AddVertex( R3Pt( dC, dS, dC ) ); aopVs.last()->SetColor( UTILSColor::BLUE ); } else { for ( int j = 0; j < iNTheta; j++ ) { const double dT = j * dTheta; aopVs += &out_mesh.AddVertex( R3Pt( cos(dT) * dC, dS, sin(dT) * dC ) ); aopVs.last()->SetColor( UTILSColor::BLUE ); } } } Array aopTri(3); for ( FORINT i = 0; i < iNPhi - 1; i++ ) { for ( int j = 0; j < iNTheta; j++ ) { if ( (i == iTop || i == iBot) && j % iSpace == 0 ) continue; if ( i == 0 ) { aopTri[0] = aopVs[0]; aopTri[1] = aopVs[ 1 + (i) * iNTheta + j ]; aopTri[2] = aopVs[ 1 + (i) * iNTheta + (j+1) % iNTheta ]; out_mesh.AddFace( aopTri ); } else if ( i == iNPhi - 2 ) { aopTri[0] = aopVs.last(); aopTri[1] = aopVs[ 1 + (i-1) * iNTheta + j ]; aopTri[2] = aopVs[ 1 + (i-1) * iNTheta + (j+1) % iNTheta ]; aopTri.reverse(); out_mesh.AddFace( aopTri ); } else { aopTri[0] = aopVs[ 1 + (i-1) * iNTheta + j ]; aopTri[1] = aopVs[ 1 + (i) * iNTheta + j ]; aopTri[2] = aopVs[ 1 + (i) * iNTheta + (j+1) % iNTheta ]; out_mesh.AddFace( aopTri ); aopTri[1] = aopVs[ 1 + (i-1) * iNTheta + j ]; aopTri[0] = aopVs[ 1 + (i-1) * iNTheta + (j+1) % iNTheta ]; aopTri[2] = aopVs[ 1 + (i) * iNTheta + (j+1) % iNTheta ]; out_mesh.AddFace( aopTri ); } } } Array aopTop(4), aopBot(4), aopTube; for ( FORINT i = 0; i < m_iNHoles; i++ ) { aopTop[0] = aopVs[ 1 + (iTop - 1) * iNTheta + i * iSpace ]; aopTop[1] = aopVs[ 1 + (iTop) * iNTheta + i * iSpace ]; aopTop[2] = aopVs[ 1 + (iTop) * iNTheta + i * iSpace + 1 ]; aopTop[3] = aopVs[ 1 + (iTop - 1) * iNTheta + i * iSpace + 1 ]; aopBot[1] = aopVs[ 1 + (iBot - 1) * iNTheta + i * iSpace ]; aopBot[0] = aopVs[ 1 + (iBot) * iNTheta + i * iSpace ]; aopBot[3] = aopVs[ 1 + (iBot) * iNTheta + i * iSpace + 1 ]; aopBot[2] = aopVs[ 1 + (iBot - 1) * iNTheta + i * iSpace + 1 ]; for ( int j = 0; j < 4; j++ ) { aopTop[j]->SetColor( UTILSColor( 0.2 + j * 0.2, j * 0.25, 0.1 ) ); aopBot[j]->SetColor( UTILSColor( 0.2 + j * 0.2, j * 0.25, 0.8 ) ); } aopTube.clearcompletely(); for ( int iS = 0; iS < 4; iS++ ) { const R3Pt &pt1 = aopTop[iS]->GetLoc(); const R3Pt &pt2 = aopBot[iS]->GetLoc(); aopTube += aopTop[iS]; for ( int j = 0; j < iNPhi; j++ ) { aopTube += &out_mesh.AddVertex( Lerp( pt1, pt2, (j+1) * 1.0 / (double) (iNPhi) ) ); } aopTube += aopBot[iS]; } for ( FORINT iS = 0; iS < 4; iS++ ) { for ( int j = 0; j < iNPhi + 1; j++ ) { aopTri[0] = aopTube[iS * (iNPhi+2) + j]; aopTri[1] = aopTube[( (iS+1)%4 ) * (iNPhi+2) + j]; aopTri[2] = aopTube[( (iS+1)%4 ) * (iNPhi+2) + (j+1)]; out_mesh.AddFace( aopTri ); aopTri[0] = aopTube[( (iS+1)%4 ) * (iNPhi+2) + (j+1)]; aopTri[1] = aopTube[( (iS)%4 ) * (iNPhi+2) + (j+1)]; aopTri[2] = aopTube[( (iS)%4 ) * (iNPhi+2) + j]; out_mesh.AddFace( aopTri ); } } } Array aopCheck; out_mesh.CAllMeshVertices( aopCheck ); for ( int iV = 0; iV < aopCheck.num(); iV++ ) if ( out_mesh.IsBoundary( *aopCheck[iV] ) ) ASSERT(FALSE); out_mesh.GenerateSubdiv( 2, FALSE ); }