부드러운 복셀 지형


13

개인 프로젝트로서 저는 Castle Story 부드러운 지형과 같은 지형을 만드는 지형 생성기를 만들려고합니다.

이전에 본 적이 없다면 여기 : 여기에 이미지 설명을 입력하십시오

보시다시피, 블록과 "부드러운"블록의 조합입니다.

이 모양을 에뮬레이트하기 위해 시도한 것은 각 표면 블록에 미니 하이트 맵을 제공하는 것입니다. 이것은 일반적으로 작동하지만 다음과 같은 지형을 생성하는 몇 가지 문제가 있습니다.

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

문제는 각 블록이 1x1x1이지만 때로는 특정 위치의 높이가 음수 또는> 1이라는 것입니다.이 경우 자르고 높이를 0 또는 1로 설정합니다.

내가 의미하는 바를 더 잘 설명하기 위해 다이어그램이 있습니다. 여기에 이미지 설명을 입력하십시오

높이를 생성하기 위해 기본적으로 다음을 수행합니다.

genColumn(int x, int z)
{
    int highestBlockY = (int)noise2d(x, z);

    bool is_surface = true;

    for(int y = max_height - 1; y >= 0; y--)
    {
        Block b;

        if(is_surface)
        {
            b = Block.Grass;
            b.HasHeightMap = true;

            // generate heightmap
            for(int ix = 0; ix < 5; ix++)
            {
                for(int iz = 0; iz < 5; iz++)
                {
                    float heightHere = noise2d(x + ix / 4, z + iz / 4) - y;

                    // clip heights
                    if(heightHere > 1)
                        heightHere = 1;

                    if(heightHere < 0)
                        heightHere = 0;

                    b.HeightMap[ix][iz] = heightHere;
                }
            }

            is_surface = false;
        }
        else
        {
            b = Block.Dirt;
        }

        setBlock(x, y, z, b);
    }
}

아마도 "true"펄린 노이즈 값을 사용하여 잘못 접근하고 있습니까?

어떤 도움이라도 대단히 감사하겠습니다!

답변:


11

Castle Story는 기술적 인 제약으로 인해 다음과 같이 보입니다. 각 표면 복셀 당 높이 맵이 아닌 전체 볼륨에 각 복셀 당 높이 맵이 있었으므로 저장 비용은 O (n ^ 3의 순서로 훨씬 더 큽니다. )는 더 유리한 O (n ^ 2)와 달리 금지 될 수 있습니다. 여기서 n은 사용자의 세계를 나타내는 입방 복셀 공간의 측면 길이입니다. 지하 복셀에 대한 하이트 맵 정보는 그리드 구조에 내재되어 있으므로 하이트 맵 정보 는 표면에있는 복셀에 대해서만 명시 적으로 저장하면됩니다. 캐슬 스토리 사람들은 스토리지 비용과 메시 구성 복잡성을 절약하기 위해 정점을 그리드 틈새에 맞췄습니다.

먼저 옵션을 살펴 보겠습니다.

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

(1) 단일 복셀 컬럼에서는 최상위 복셀에 대한 미니 하이트 맵 정보 만 원하기 때문에 어려운 점이 있습니다 . 이유는 첫 번째 단락을 참조하십시오. (1)을 보면 오른쪽 열에 맨 위와 두 번째부터 두 번째에 대한 하이트 맵 정보가 있습니다 (기울기가 너무 크면 세 번째부터 위까지 적용 할 수 있음). 이건 좋지 않아

(2) 아마도 더 나은 선택 일 것입니다. 즉, 모서리 정점이 복셀 격자 간극에 스냅되도록합니다. 그렇다면 극단적 인 경사 문제를 어떻게 해결할 수 있을까요? 글쎄, 우리는 단순히 세로 열에 스냅하고 따라서 n 개의 최상위 복셀을 가로 지르는 것보다 그라디언트가 없는지 확인하는 그라디언트를 선택해야합니다. 45도 기울기는 아래에서 설명하는 이유로 자연 차단입니다. 따라서 (3) 대신에 (4)가 있습니다.

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

(4) 복셀의 코너 정점을 가장 가까운 격자 간격에 스냅하는 것이 해결책입니다. Castle Story의 스크린 샷에서 시각 효과 (대각선 앨리어싱)를 볼 수 있습니다. 복셀의 컷오프 기울기는 1 : 1 그라디언트 또는 45도 (직교로 볼 때)입니다. 솔루션에서 뒤로 작업하면서 이유를 살펴 보겠습니다.

  • 우리가 깨지지 않고 극단적 인 경사를 가질 수있는 유일한 방법은 복셀이 세로로 길어 졌을 때입니다.
  • .... 그러나 복셀의 메쉬는 실제 스무딩 된 모양에 관계없이 경계 영역을 초과 할 수 없습니다. 복셀은 정확한 형태가 아니라면 적어도 축 정렬 경계 상자를 설명하는 3D 그리드의 정의 된 공간에 앉아 있어야합니다.

이런 식으로 접근하는 또 다른 이유는 이미 발견했듯이 스냅 (분산)을 사용하지 않으면 기하학적으로 복잡한 표면 스무딩 시나리오가 다양하게 발생하는 것을 피할 수 있습니다. 이러한 게임은 일반적으로 필요하지 않습니다. 올바른 CSG 알고리즘이 제공하는 정확성의 정도, 이것이 우리가 처음에 복셀을 사용하는 전체 이유입니다. 복셀은 부동 소수점 (연속) 다각형 교차점 / CSG 알고리즘보다 볼륨으로 점진적으로 작업하기가 훨씬 쉽습니다. .


방금 이것을 구현하려고했는데 혼란에 빠졌습니다. "intertices"는 무엇을 의미합니까? 적분 그리드 좌표를 의미합니까?
제목 없음

@ThomasBradworth. "사물 사이에 개입하는 공간." 2D의 경우, 셀의 축 그리드가 있으면 (n + 1) x (n + 1) 틈새가 생깁니다. 이것은 3D로 직접 확장됩니다. 그것들은 각 셀을 묶는 "꼭지점 (vertice)"으로, 대부분 여러 셀 / 복셀간에 공유됩니다. 1D (선)로 끓이면 셀과 틈새가 모두 배열로 표시되면 셀 0은 틈새 0과 틈새 1에 의해 묶이고 셀 1은 틈새 1과 틈새 2에 의해 묶입니다. 등
엔지니어

답장을 보내 주셔서 감사합니다! 나는 정확히 그 일을 시도했지만 좋지 않은 결과를 얻었습니다. 처음에는 가장자리에서 높이 값을 반올림하려고 시도했지만 (x가 0 또는 4이거나 z가 0 또는 4 인 경우) i.imgur.com/eQW7Y.png ( pastbin.com/Lr8vyyHB ) 다음으로 중간에 점을 다듬어 보았으므로 "고정 높이 함수"를 추가했습니다. pastebin.com/AazQ07Xm 그러나 더 각도가 많지만 결과는 좋지 않습니다. i.imgur.com/q1JVP .png 잡음 기능에 문제가 있습니까?
제목 없음

@ThomasBradsworth 슬프게도, 나는 당신이 글을 쓰고 편집하는데 한 시간 이상 걸린 답을 절반 만 읽거나 이해했다고 생각합니다. 소음을 잊어 버리십시오. 또한 잡음 함수를 이해하지 못하면 지금 당장 방정식에서 제거하십시오. 문제는 개별 복셀 메시 데이터가 구성되는 방식에 있으며 노이즈가 없을 때 하이트 맵을 생성 할 수 있기 때문에 노이즈와 관련이 없습니다. 가장 간단한 테스트 사례, 즉 높이 배열을 하드 코딩하십시오. 그런 다음 결과를보고 메시 생성 알고리즘을 조정하십시오. 예상대로 될 때까지 반복하십시오. 그런 다음 소음을 다시 넣고 검토하십시오.
엔지니어

모서리의 높이 값만 저장하고 "중간"포인트의 높이 값을 저장해서는 안된다고 말씀하십니까?
제목 없음
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.