프로그래밍 방식으로 구를 어떻게 생성합니까?


25

구면 정점, 인덱스 및 텍스처 좌표를 만드는 방법을 설명해 주시겠습니까? 그렇게하는 방법에 대한 문서가 놀라 울 정도로 부족하며 학습에 관심이있는 것입니다.

나는 명백하고, 인터넷 검색을 시도하고, gamedev.net을 살펴 보는 등을 시도했다.


6
나는 이것을 끝내기 위해 투표하거나 투표하지 않을 것이지만, google.com/search?q=how+to+generate+a+sphere+vertices 의 단일 결과 가 유용 하지 않다고 실제로 말하고 있습니까? 이 경우 문제가 무엇인지 더 자세히 설명해야합니다.


icosphere를 검색하십시오. 쓸모없는 얼굴을 만들어내는 멍청한 "극성 구체"보다 훨씬 똑똑합니다.
Notabene

3
주목할만한 것은, 몇 가지 간단한 목적을 위해 완벽하게 훌륭한 "구체"는 카메라를 향한 원형 텍스처를 갖는 쿼드입니다.
aaaaaaaaaaaa

게임에서 스카이 돔을 위해 구현 한 방법 은 다음과 같습니다 .
danijar

답변:


36

두 가지 일반적인 접근 방식이 있습니다.

여기에 이미지 설명을 입력하십시오

가장 왼쪽은 uv-sphere, 가장 오른쪽은 icosphere입니다.

GLUT는 uv 방식을 사용하는 경향이 있습니다 : freeglut sourcecode 의 함수 glutSolidSphere()를 보십시오 .

다음은 icosphere 생성에 대한 훌륭한 기사입니다. http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html

uv-sphere는 지구처럼 보입니다. 많은 목적을 위해 그것은 완벽하게 괜찮지 만 일부 사용 사례의 경우, 예를 들어 구를 변형하려는 경우 정점의 밀도가 극 주위에서 더 크다는 단점이 있습니다. 여기서 icosphere가 더 좋고 정점이 분배됩니다.

http://kiwi.atmos.colostate.edu/BUGS/geodesic/text.html 또한 얼굴을 영역으로 구성하는 방법을 설명합니다.

http://vterrain.org/Textures/spherical.html 에서는 텍스처를 선택하는 방법에 대한 훌륭한 설명을 제공합니다.


2
일반적인 아이디어는 좋지만 Schläfli {3,5} 폴리 토프를 세분화하는 것이 유일한 방법은 아닙니다. 일반적으로 UV 매핑을 위해 Schläfli {4, *} 제품군 (구의 경우 {4,3})을 사용하는 것이 좋습니다.
Martin Sojka

세분화 된 정 이십 면체 구체는 재귀 적으로면을 세분화해야하기 때문에 생성하는 데 약간 더 비쌉니다.
bobobobo

9

두 가지 방법이 있습니다.

  1. 구형 좌표로 세타와 파이를 걷고면과 트라이를 생성합니다.

  2. 정 이십 면체를 만들고 원하는 테셀레이션에 도달 할 때까지면을 재귀 적으로 세분화합니다.

구면 좌표계를 사용한 구

첫 번째 방법으로, theta와 phi를 걷기 위해 이중 중첩을 사용합니다. 세타와 파이를 걸 으면 삼각형을 회전하여 구를 만듭니다.

여기에 이미지 설명을 입력하십시오

이를 수행하는 코드는 다음과 같습니다.

for( int t = 0 ; t < stacks ; t++ ) // stacks are ELEVATION so they count theta
{
  real theta1 = ( (real)(t)/stacks )*PI ;
  real theta2 = ( (real)(t+1)/stacks )*PI ;

  for( int p = 0 ; p < slices ; p++ ) // slices are ORANGE SLICES so the count azimuth
  {
    real phi1 = ( (real)(p)/slices )*2*PI ; // azimuth goes around 0 .. 2*PI
    real phi2 = ( (real)(p+1)/slices )*2*PI ;

    //phi2   phi1
    // |      |
    // 2------1 -- theta1
    // |\ _   |
    // |    \ |
    // 3------4 -- theta2
    //

    //vertex1 = vertex on a sphere of radius r at spherical coords theta1, phi1
    //vertex2 = vertex on a sphere of radius r at spherical coords theta1, phi2
    //vertex3 = vertex on a sphere of radius r at spherical coords theta2, phi2
    //vertex4 = vertex on a sphere of radius r at spherical coords theta2, phi1

    // facing out
    if( t == 0 ) // top cap
      mesh->addTri( vertex1, vertex3, vertex4 ) ; //t1p1, t2p2, t2p1
    else if( t + 1 == stacks ) //end cap
      mesh->addTri( vertex3, vertex1, vertex2 ) ; //t2p2, t1p1, t1p2
    else
    {
      // body, facing OUT:
      mesh->addTri( vertex1, vertex2, vertex4 ) ;
      mesh->addTri( vertex2, vertex3, vertex4 ) ;
    }
  }
}

위의 점에서 상단 캡과 하단 캡을 쿼드가 아닌 트라이 만 사용하여 감는 것이 중요합니다.

정 이십 면체

정 이십 면체를 사용하려면 정 이십 면체의 점을 생성 한 다음 삼각형을 감습니다. 원점에 앉아 정 이십 면체정점 은 다음과 같습니다.

(0, ±1, ±φ)
1, ±φ, 0)
(±φ, 0, ±1)
where φ = (1 + 5) / 2 

당신은 그 정점에서 정 이십 면체와 바람 얼굴의 다이어그램을보아야합니다. 이미 여기에 코드가 있습니다 .


theta = pi / 4에서 theta = 3pi * 4와 같이 하프 바디를 얻는 방법에 대한 아이디어가 있습니까? 이 이미지와 같이 : i.stack.imgur.com/Jjx2c.jpg이 문제를 해결하기 위해 며칠을 보냈습니다.
Tina J

3

점이 국부적으로 균일 할 필요는 없지만 전역 적으로 균일해야하고 설정된 패턴을 따라야 할 필요가없는 경우, 다트 던지기 알고리즘의 변형을 사용하여 반지름이 r 인 구에 n 개의 점 을 분포시킬 수 있습니다. 평균 dist 포인트 차이. 이 값은 대략 다음과 같습니다.

  1. 특정 양의 정점을 원한다면 :
    • n = (원하는 정점 수)
    • dist = 2 × r × √ ( π / n )
  2. 꼭짓점 사이에 특정 평균 거리를 유지하려는 경우 :
    • n = 4 × π × ( r / 거리 ) 2
    • 거리 = (원하는 평균 거리)

가장 간단한 경우 (0, 1)에서 두 개의 균일하게 분포 된 변수 uv 를 선택하고 공식 θ = 2 × π × uϕ = arc 에 따라 두 개의 균일하게 분포 된 변수 uv 를 골라 무작위로 점을 균일하게 선택할 수 있습니다. cos (2 × v -1); 그런 다음 이미 선택한 점에 너무 가까이있는 점을 닫습니다. 약간 더 복잡하고 성능이 우수한 알고리즘 은 Cline, Jeschke, White, Razdan 및 Wonka의 " Dart Throwing on Surfaces "를 참조하십시오 .

처음 네 점을 선택한 후에 (그중 세 개가 퇴화 하지 않는다고 가정합니다 . 즉, 그들은 같은 큰 원에 있지 않지만 그럴 가능성은 거의 없습니다), 그 사이에 네 개의면을 만들 수 있습니다. 새로운 점에서는 그에 속하는면을 세 개의 하위면으로 분할 할 수 있습니다.

텍스처링을 위해 점을 큐브 맵에 매핑 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.