x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Office Holiday

Epic Games' offices will be on holiday from June 22nd to July 7th. During this period support will be limited. Our offices will reopen on Monday, July 8th. 

How to tile heightmap chunk ?

Hi,

I'm trying to create a terrain based on a heightmap and chunks. I can currently add and remove chunks around my character and generate a heightmap based on the chunk's position in the world (to keep it simple). My problem is that I have no idea how to "join" the borders of the chunks together. Can someone enlighten me on the way forward?

here some code : // Fill out your copyright notice in the Description page of Project Settings.

 #include "WorldChunk.h"
 
 
 // Sets default values
 AWorldChunk::AWorldChunk()
 {
      // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
     PrimaryActorTick.bCanEverTick = true;
 
     RootNode = CreateDefaultSubobject<USceneComponent>("Rootnode");
     RootComponent = RootNode;
 
     MeshComponent = CreateDefaultSubobject<URuntimeMeshComponent>(TEXT("ProceduralChunkMesh"));
     MeshComponent->SetupAttachment(RootComponent);
 
 }
 
 void AWorldChunk::SetupChunk(int32 inSeed, int32 inindexX, int32 inindexY, int32 inSectionSize, int32 inChunkSize, int32 inMaxHeight)
 {
     Seed = inSeed;
     ChunkX = inindexX;
     ChunkY = inindexY;
     SectionSize = inSectionSize;
     ChunkSize = inChunkSize;
     MaxHeight = inMaxHeight; 
 }
 
 void AWorldChunk::OnConstruction(const FTransform & Transform)
 {
     int32 NumberOfPoints = (SectionSize + 1) * (SectionSize + 1);
     int32 NumberOfVertices = SectionSize * SectionSize * 4; // 4x vertices per quad/section
     int32 NumberOfTriangles = SectionSize * SectionSize * 2 * 3; // 2x3 vertex indexes per quad
     Vertices.AddUninitialized(NumberOfVertices);
     Triangles.AddUninitialized(NumberOfTriangles);
     HeightValues.Reserve(NumberOfPoints);
 
     for (int i = 0; i < NumberOfPoints; i++) {
         HeightValues.Emplace(0.0f);
     }
 
     GenerateMesh();
 }
 
 // Generate heightmap
 void AWorldChunk::GenerateHeightmap()
 {
     noiseGenerator->setNoiseSeed(Seed);
 
     for (int32 x = 0; x < SectionSize + 1; x++) {
         for (int32 y = 0; y < SectionSize + 1; y++) {
             int nX = ((ChunkX * ChunkSize) + (x * SectionSize));
             int nY = ((ChunkY * ChunkSize) + (y * SectionSize));
             HeightValues[x + (y*SectionSize)] = noiseGenerator->SimplexNoise2D(nX, nY);
         }    
     }
 }
 
 void AWorldChunk::GenerateMesh()
 {
     GenerateHeightmap();
     GenerateGrid(Vertices, Triangles, HeightValues);
     MeshComponent->ClearAllMeshSections();
     MeshComponent->CreateMeshSection(0, Vertices, Triangles, false, EUpdateFrequency::Infrequent);
 }
 
 void AWorldChunk::GenerateGrid(TArray<FRuntimeMeshVertexSimple>& InVertices, TArray<int32>& InTriangles, const TArray<float>& InHeightValues)
 {
     FVector2D NumberOfSection = FVector2D(ChunkSize / SectionSize, ChunkSize / SectionSize);
 
     int32 VertexIndex = 0;
     int32 TriangleIndex = 0;
     
     for (int32 X = 0; X < SectionSize; X++) {
         for (int32 Y = 0; Y < SectionSize; Y++) {
             
             int32 BottomLeftIndex = VertexIndex++;
             int32 BottomRightIndex = VertexIndex++;
             int32 TopRightIndex = VertexIndex++;
             int32 TopLeftIndex = VertexIndex++;
 
             int32 NoiseIndex_TopLeft = (X + 1) + (Y * (SectionSize + 1));
             int32 NoiseIndex_TopRight = (X + 1) + (Y + 1) * (SectionSize + 1);
             int32 NoiseIndex_BottomRight = X + (Y + 1) * (SectionSize + 1);
             int32 NoiseIndex_BottomLeft = X + (Y * (SectionSize + 1));
             
             FVector pTopLeft = FVector((X + 1) * NumberOfSection.X, Y * NumberOfSection.Y, InHeightValues[NoiseIndex_TopLeft]);
             FVector pTopRight = FVector((X + 1) * NumberOfSection.X, (Y + 1) * NumberOfSection.Y, InHeightValues[NoiseIndex_TopRight]);
             FVector pBottomRight = FVector(X * NumberOfSection.X, (Y + 1) * NumberOfSection.Y, InHeightValues[NoiseIndex_BottomRight]);
             FVector pBottomLeft = FVector(X * NumberOfSection.X, Y * NumberOfSection.Y, InHeightValues[NoiseIndex_BottomLeft]);
 
             InVertices[BottomLeftIndex].Position = pBottomLeft;
             InVertices[BottomRightIndex].Position = pBottomRight;
             InVertices[TopRightIndex].Position = pTopRight;
             InVertices[TopLeftIndex].Position = pTopLeft;
 
             // Note that Unreal UV origin (0,0) is top left
             InVertices[TopLeftIndex].UV0 = FVector2D((float)(X + 1) / (float)SectionSize, (float)Y / (float)SectionSize);
             InVertices[TopRightIndex].UV0 = FVector2D((float)(X + 1) / (float)SectionSize, (float)(Y + 1) / (float)SectionSize);
             InVertices[BottomRightIndex].UV0 = FVector2D((float)X / (float)SectionSize, (float)(Y + 1) / (float)SectionSize);
             InVertices[BottomLeftIndex].UV0 = FVector2D((float)X / (float)SectionSize, (float)Y / (float)SectionSize);
             
             
 
             // Now create triangles 
             InTriangles[TriangleIndex++] = BottomLeftIndex;
             InTriangles[TriangleIndex++] = TopRightIndex;
             InTriangles[TriangleIndex++] = TopLeftIndex;
 
             InTriangles[TriangleIndex++] = BottomLeftIndex;
             InTriangles[TriangleIndex++] = BottomRightIndex;
             InTriangles[TriangleIndex++] = TopRightIndex;
 
             // Normals
             FVector NormalCurrent = FVector::CrossProduct(InVertices[BottomLeftIndex].Position - InVertices[TopLeftIndex].Position, InVertices[TopLeftIndex].Position - InVertices[TopRightIndex].Position).GetSafeNormal();
 
             // Normals
             InVertices[BottomLeftIndex].Normal = InVertices[BottomRightIndex].Normal = InVertices[TopRightIndex].Normal = InVertices[TopLeftIndex].Normal = FPackedNormal(NormalCurrent);
 
             // Tangents
             FVector SurfaceTangent = pBottomLeft - pBottomRight;
             SurfaceTangent = SurfaceTangent.GetSafeNormal();
             InVertices[BottomLeftIndex].Tangent = InVertices[BottomRightIndex].Tangent = InVertices[TopRightIndex].Tangent = InVertices[TopLeftIndex].Tangent = FPackedNormal(SurfaceTangent);
             
         }
     }
 }
 
 // Called when the game starts or when spawned
 void AWorldChunk::BeginPlay()
 {
     Super::BeginPlay();
     
 }
 
 // Called every frame
 void AWorldChunk::Tick(float DeltaTime)
 {
     Super::Tick(DeltaTime);
 
 }
 
 

Current result ! Result Example

Product Version: UE 4.20
Tags:
tiledchunk.png (2.1 MB)
more ▼

asked Oct 05 '18 at 01:40 PM in C++ Programming

avatar image

BigBadWouf
10 2 4

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

0 answers: sort voted first
Be the first one to answer this question
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question