[c++] gluSphere ()를 사용하지 않고 OpenGL에서 구 그리기?

OpenGL에서 사용하지 않고도 구를 그릴 수있는 방법을 설명하는 튜토리얼이 gluSphere()있습니까?

OpenGL 용 3D 튜토리얼의 대부분은 큐브에 있습니다. 나는 검색했지만 구를 그리는 대부분의 솔루션은 gluSphere(). 이 사이트에 구를 그리는 코드가있는 사이트도 있지만 구를 그리는 이면의 수학을 설명하지 않습니다. 해당 링크의 쿼드 대신 다각형으로 구를 그리는 방법에 대한 다른 버전도 있습니다. 그러나 다시 코드로 구체가 어떻게 그려 지는지 이해하지 못합니다. 필요한 경우 구를 수정할 수 있도록 시각화 할 수 있기를 원합니다.



답변

이를 수행 할 수있는 한 가지 방법은 삼각형면이있는 플라토닉 솔리드 ( 예 : 팔면체 )로 시작하는 것 입니다. 그런 다음 각 삼각형을 재귀 적으로 더 작은 삼각형으로 나눕니다.

재귀 적으로 그려진 삼각형

충분한 양의 점이 있으면 벡터가 모두 솔리드 중심에서 일정한 거리에 있도록 벡터를 정규화합니다. 이렇게하면 점의 수를 늘릴수록 부드러움이 증가하면서 측면이 구와 유사한 모양으로 돌출됩니다.

여기서 정규화는 다른 점에 대한 각도는 같지만 그 사이의 거리는 다르도록 점을 이동하는 것을 의미합니다. 다음은 2 차원 예입니다.

여기에 이미지 설명 입력

A와 B는 6 단위 떨어져 있습니다. 그러나 우리가 A에서 12 단위 떨어진 라인 AB에서 한 지점을 찾고 싶다고 가정 해 보겠습니다.

여기에 이미지 설명 입력

C는 거리가 12 인 A에 대해 B의 정규화 된 형태라고 말할 수 있습니다. 다음과 같은 코드로 C를 얻을 수 있습니다.

#returns a point collinear to A and B, a given distance away from A. 
function normalize(a, b, length):
    #get the distance between a and b along the x and y axes
    dx = b.x - a.x
    dy = b.y - a.y
    #right now, sqrt(dx^2 + dy^2) = distance(a,b).
    #we want to modify them so that sqrt(dx^2 + dy^2) = the given length.
    dx = dx * length / distance(a,b)
    dy = dy * length / distance(a,b)
    point c =  new point
    c.x = a.x + dx
    c.y = a.y + dy
    return c

이 정규화 과정을 같은 점 A와 같은 거리 R에 대해 많은 점에 대해 수행하면 정규화 된 점은 모두 중심 A와 반경 R을 가진 원호에 놓일 것입니다.

불룩한 선 세그먼트

여기에서 검은 색 점은 선에서 시작하여 호로 “부풀어집니다”.

이 과정은 3 차원으로 확장 될 수 있으며,이 경우 원이 아닌 구를 얻게됩니다. 정규화 함수에 dz 구성 요소를 추가하기 만하면됩니다.

정규화 된 다각형

레벨 1 부풀어 오르는 팔면체
레벨 3 부풀어 오르는 팔면체

Epcot 에서 구를 보면이 기술이 작동하는 것을 볼 수 있습니다. 더 둥글게 보이게하기 위해 얼굴이 튀어 나온 십이 면체입니다.


답변

위도와 경도를 사용하여 구를 생성하는 인기있는 방법을 추가로 설명하겠습니다 (또 다른 방법 인 icospheres 는이 글을 쓰는 당시 가장 인기있는 답변에서 이미 설명되었습니다.)

구는 다음 매개 변수 방정식으로 표현할 수 있습니다.

F ( u , v ) = [cos (u) * sin (v) * r, cos (v) * r, sin (u) * sin (v) * r]

어디:

  • r 은 반경입니다.
  • u 는 0에서 2π까지의 경도입니다. 과
  • v 는 0에서 π까지의 위도입니다.

구를 생성하려면 고정 된 간격으로 파라 메트릭 함수를 평가해야합니다.

예를 들어, 16 개의 경도 라인을 생성하려면 u 축을 따라 π / 8 (2π / 16) 간격 으로 17 개의 그리드 라인이 있어야 합니다 (17 번째 라인이 둘러싸 임).

다음 의사 코드는 일정한 간격으로 파라 메트릭 함수를 평가하여 삼각형 메시를 생성합니다 (이는 구뿐만 아니라 모든 파라 메트릭 표면 함수에서 작동 함 ).

아래 의사 코드에서 UResolution 은 U 축 (여기서는 경도 선)을 따르는 격자 점의 수 이고 VResolution 은 V 축 (여기서는 위도 선)을 따르는 격자 점의 수입니다.

var startU=0
var startV=0
var endU=PI*2
var endV=PI
var stepU=(endU-startU)/UResolution // step size between U-points on the grid
var stepV=(endV-startV)/VResolution // step size between V-points on the grid
for(var i=0;i<UResolution;i++){ // U-points
 for(var j=0;j<VResolution;j++){ // V-points
 var u=i*stepU+startU
 var v=j*stepV+startV
 var un=(i+1==UResolution) ? EndU : (i+1)*stepU+startU
 var vn=(j+1==VResolution) ? EndV : (j+1)*stepV+startV
 // Find the four points of the grid
 // square by evaluating the parametric
 // surface function
 var p0=F(u, v)
 var p1=F(u, vn)
 var p2=F(un, v)
 var p3=F(un, vn)
 // NOTE: For spheres, the normal is just the normalized
 // version of each vertex point; this generally won't be the case for
 // other parametric surfaces.
 // Output the first triangle of this grid square
 triangle(p0, p2, p1)
 // Output the other triangle of this grid square
 triangle(p3, p1, p2)
 }
}


답변

샘플의 코드는 빠르게 설명됩니다. 함수를 살펴 봐야합니다 void drawSphere(double r, int lats, int longs).

void drawSphere(double r, int lats, int longs) {
    int i, j;
    for(i = 0; i <= lats; i++) {
        double lat0 = M_PI * (-0.5 + (double) (i - 1) / lats);
        double z0  = sin(lat0);
        double zr0 =  cos(lat0);

        double lat1 = M_PI * (-0.5 + (double) i / lats);
        double z1 = sin(lat1);
        double zr1 = cos(lat1);

        glBegin(GL_QUAD_STRIP);
        for(j = 0; j <= longs; j++) {
            double lng = 2 * M_PI * (double) (j - 1) / longs;
            double x = cos(lng);
            double y = sin(lng);

            glNormal3f(x * zr0, y * zr0, z0);
            glVertex3f(r * x * zr0, r * y * zr0, r * z0);
            glNormal3f(x * zr1, y * zr1, z1);
            glVertex3f(r * x * zr1, r * y * zr1, r * z1);
        }
        glEnd();
    }
}

매개 변수 lat는 구에 포함 할 수평선 수와 수직선 수를 정의합니다 lon. r구의 반경입니다.

이제 lat/에 대한 이중 반복이 있으며 lon간단한 삼각법을 사용하여 정점 좌표가 계산됩니다.

계산 된 정점이 이제를 사용하여 GPU glVertex...()GL_QUAD_STRIP전송됩니다. 즉, 이전에 전송 된 두 정점과 함께 쿼드를 형성하는 각 정점 두 개를 전송합니다.

이제 이해해야 할 것은 삼각 함수가 작동하는 방식 뿐이지 만 쉽게 알아낼 수있을 것 같습니다.


답변

OpenGL red book : http://www.glprogramming.com/red/chapter02.html#name8
다각형 세분화로 문제를 해결합니다.


답변

여우처럼 교활하고 싶다면 GLU의 코드를 반 인치로 줄일 수 있습니다. MesaGL 소스 코드 (http://cgit.freedesktop.org/mesa/mesa/)를 확인하세요.


답변

‘삼각형 스트립’을 사용하여 “극성”구를 그리는 방법의 예는 쌍의 드로잉 포인트로 구성됩니다.

const float PI = 3.141592f;
GLfloat x, y, z, alpha, beta; // Storage for coordinates and angles        
GLfloat radius = 60.0f;
int gradation = 20;

for (alpha = 0.0; alpha < GL_PI; alpha += PI/gradation)
{
    glBegin(GL_TRIANGLE_STRIP);
    for (beta = 0.0; beta < 2.01*GL_PI; beta += PI/gradation)
    {
        x = radius*cos(beta)*sin(alpha);
        y = radius*sin(beta)*sin(alpha);
        z = radius*cos(alpha);
        glVertex3f(x, y, z);
        x = radius*cos(beta)*sin(alpha + PI/gradation);
        y = radius*sin(beta)*sin(alpha + PI/gradation);
        z = radius*cos(alpha + PI/gradation);
        glVertex3f(x, y, z);
    }
    glEnd();
}

입력 된 첫 번째 점 (glVertex3f)은 다음과 같은 매개 변수 방정식이고 두 번째 점은 알파 각도의 단일 단계 (다음 평행선에서)만큼 이동합니다.


답변

받아 들여진 대답으로 문제가 해결되지만 끝에는 약간의 오해가 있습니다. 정 십이 면체 는 모든면이 동일한 면적을 갖는 정다면체입니다. 그것은 Epcot의 경우 인 것 같습니다 (그런데, 이것은 십이 면체 가 아닙니다 ). @Kevin이 제안한 솔루션은 이러한 특성을 제공하지 않기 때문에 이러한 특성을 추가 할 수 있다고 생각했습니다.

모든 정점이 같은 구에 있고 모든면이 비슷한 면적 / 표면을 갖는 N면 다면체를 생성하는 좋은 방법 은 이십 면체로 시작하고 삼각형면을 반복적으로 세분화하고 정규화하는 것입니다 (수용된 답변에서 제 안됨). ). 예를 들어 12 면체는 실제로 잘린 20 면체 입니다.

정 이십 면체 는 20 개의면 (12 개의 꼭지점)을 가지며 3 개의 금색 직사각형으로 쉽게 구성 할 수 있습니다. 이것은 팔면체가 아닌 시작점으로하는 문제 일뿐입니다. 여기 에서 예를 찾을 수 있습니다 .

나는 이것이 약간 주제에서 벗어난 것을 알고 있지만 누군가이 특정 사례를 찾고 여기에 오면 도움이 될 것이라고 생각합니다.