Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Yandalf · Jun 24, 2014 at 05:53 PM · terraintileperlin noisetilingchunk

Tiling problem with Perlin generated terrain chunks

I'm trying to create a procedural generator for terrain using Unity's Perlin Noise generator. I've managed to create a grid of 3x3 terrains with what seems to be a working repetition, except at the very top and right edges of each terrain they take a plunge to 0.

I've looked around for solutions to this (mostly trying to offset the noise applied by 1 pixel up and right), but nothing seems to work. Any ideas what I'm doing wrong? Thanks in advance!

 void GenerateMesh (int xOrg, int yOrg)
     {
         float[,] Heights= MultiDim.FloatArray ((int)m_MapSize.x, (int)m_MapSize.y);
         Heights=CalcNoise (xOrg,yOrg);
         TerrainData NewTerrain= new TerrainData();
 
         NewTerrain.heightmapResolution = (int)m_MapSize.x;
         NewTerrain.size = new Vector3 (m_MapSize.x, m_MaxHeight, m_MapSize.y);
         NewTerrain.baseMapResolution = (int)m_MapSize.x/2;
         NewTerrain.SetDetailResolution (1024, 16);
         NewTerrain.SetHeights(0,0,Heights);
         GameObject TerrainSquare= Terrain.CreateTerrainGameObject(NewTerrain);
         TerrainSquare.transform.position = new Vector3 ((xOrg*m_MapSize.x)-m_MapSize.x/2, 0,(yOrg*m_MapSize.y)-m_MapSize.y/2);
     }
 
     public float PerlinNoise(float x, float y)
     {
         float noise = Mathf.PerlinNoise (x/(m_MapSize.x)*m_ScaleRED,(y/(m_MapSize.y)*m_ScaleRED));
 
         return noise;
     }
 
     float[,] CalcNoise(int xOrg, int yOrg)
     {
         float y = 0.0f;
         float [,] finalheight =MultiDim.FloatArray ((int)m_MapSize.x, (int)m_MapSize.y);
         while (y < m_NoiseTexture.height) 
         {
             float x= 0.0f;
             while (x < m_NoiseTexture.width)
             {
                 float Xcoord = xOrg*m_MapSize.x+(x-1);
                 float Ycoord = yOrg*m_MapSize.y+(y-1);
                 float ColorSample = PerlinNoise(Xcoord,Ycoord);
 
                 m_PixelColor[(int)y*m_NoiseTexture.width+(int)x]= new Color(ColorSample,ColorSample,ColorSample);
                 finalheight[(int)y,(int)x]=0+(ColorSample);
 
                 x++;
             }
 
             y++;
         }
         m_NoiseTexture.SetPixels (m_PixelColor);
         m_NoiseTexture.Apply ();
 
         return finalheight;
 
     }
 
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by AlucardJay · Jun 25, 2014 at 11:56 AM

The problem is heightmaps are to the power of 2 + 1. Imagine it like this :

alt text

Each black dot is a member of the heightmap array. Each color square is a member of the NoiseTexture array.

Factoring this in, your Heights Arrays would be (int)m_MapSize.x + 1 (same for y). For the noise you would also need to loop through every member of the heightmap array. But with your texture you have to check if you havn't exceeded the texture array size. (Or also for the colours you may want to interpolate a sample that is in between the heightmap array values).

eg :

 void GenerateMesh (int xOrg, int yOrg)
 {
     float[,] Heights= MultiDim.FloatArray ((int)m_MapSize.x + 1, (int)m_MapSize.y + 1);
     Heights = CalcNoise (xOrg,yOrg);
     TerrainData NewTerrain = new TerrainData();
     
     NewTerrain.heightmapResolution = (int)m_MapSize.x;
     NewTerrain.size = new Vector3 (m_MapSize.x, m_MaxHeight, m_MapSize.y);
     NewTerrain.baseMapResolution = (int)m_MapSize.x/2;
     NewTerrain.SetDetailResolution(1024, 16);
     NewTerrain.SetHeights(0,0,Heights);
     GameObject TerrainSquare = Terrain.CreateTerrainGameObject(NewTerrain);
     TerrainSquare.transform.position = new Vector3 ((xOrg*m_MapSize.x)-m_MapSize.x/2, 0,(yOrg*m_MapSize.y)-m_MapSize.y/2);
 }
 
 
 public float PerlinNoise(float x, float y)
 {
     float noise = Mathf.PerlinNoise (x/(m_MapSize.x)*m_ScaleRED,(y/(m_MapSize.y)*m_ScaleRED));
     
     return noise;
 }
 
 
 float[,] CalcNoise(int xOrg, int yOrg)
 {
     float [,] finalheight =MultiDim.FloatArray ((int)m_MapSize.x + 1, (int)m_MapSize.y + 1);
     
     float y = 0.0f;
     while (y < m_NoiseTexture.height + 1)
     {
         float x = 0.0f;
         while (x < m_NoiseTexture.width + 1)
         {
             float Xcoord = xOrg*m_MapSize.x+(x-1);
             float Ycoord = yOrg*m_MapSize.y+(y-1);
             float ColorSample = PerlinNoise(Xcoord,Ycoord);
 
             finalheight[(int)y,(int)x]=0+(ColorSample);
 
             if ( y < m_NoiseTexture.height && x < m_NoiseTexture.width ) // check if within the texture array
                 m_PixelColor[(int)y*m_NoiseTexture.width+(int)x]= new Color(ColorSample,ColorSample,ColorSample);
             
             x++;
         }
         
         y++;
     }
 
     m_NoiseTexture.SetPixels (m_PixelColor);
     m_NoiseTexture.Apply ();
     
     return finalheight;
 }



heightmapexample.png (1.6 kB)
Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Yandalf · Jun 25, 2014 at 01:47 PM 0
Share

Oh my, thank you! This fixes it (other than a few very slight seams, but they're almost innoticeable) quite elegantly. I do have to say it seems very strange to me for the heightmaps to use odd dimensions, any idea why this is the case?

avatar image Yandalf · Jun 25, 2014 at 01:53 PM 0
Share

On another note, I just noticed that around the seams the terrain is behaving oddly. I get a lot of shapes like the one in the screenshot. Did I do something wrong in the tiling of the noisemap, or is this something else?alt text

unitescreenerror.jpg (29.8 kB)
avatar image AlucardJay · Jun 25, 2014 at 02:45 PM 0
Share

TerrainData is a highly guarded secret by Unity! All my findings are based on trial and error rather than actual knowledge, but I shall try to answer.

I can only guess that the heightmaps are 2^n+1 for using the heightmap vertices as UV coordinates for the splatmap data. Like the picture in my answer, one quad would need 4 vertices for generating the triangles and assigning UVs.

The noticeable 'seams' are probably the calculations for the normal of each vertex in the terrain. At the edges, the terrain cannot get all of the adjacent vertices (because they don't exist from the perspective of each terrain object), therefore they are calculated as flat rather than in relation to where the adjacent vertices of the next terrain piece are.

Regarding your image, this looks like mirroring of the perlin noise. All I can assume is you are assigning your terrain chunks between a negative value and a positive value. Perlin Noise doesn't continue into the negative axis, rather the results are a mirror of the positive axis, eg :

 // both of these will return the same value
 $$anonymous$$athf.PerlinNoise ( 1, 1 );
 $$anonymous$$athf.PerlinNoise ( -1, 1 ); 
 
 // both of thee will return the same value
 $$anonymous$$athf.PerlinNoise ( 2, 1 );
 $$anonymous$$athf.PerlinNoise ( -2, 1 );

 // etc etc

the only way to compensate for this would be to start your chunks at (0,0), and increment positively. Or add an offset in your PerlinNoise function with a magnitude greater than half of your world size so that all perlin noise values returned are in the values of positive perlin axis.

avatar image AlucardJay · Jun 25, 2014 at 03:07 PM 0
Share

image of perlin mirroring when you use -xOrg to +xOrg

alt text

perlinmirroring.jpg (39.4 kB)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

How can I correctly offset seeded perlin noise over multiple terrains? 1 Answer

Tile generation problem 1 Answer

[BEGINNER] Generating Terrain with Perlin noise flat and nothing happens ? 1 Answer

Only Effect One Material? 1 Answer

How would one approach tile-by-tile terrain generation with Perlin Noise? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges