Why my Triangles starts overlapping when terrainSize too high? [duplicate] - c#

This question already has an answer here:
Is there maximum number of meshes in Unity? [duplicate]
(1 answer)
Closed last year.
I have a weird problem. At the moment I am doing a selfmade Terrain generator, for now I am doing a "plane" generation only for the bottom area with flat surface. My problem is that when I set terrainSize too high the triangles starts overlapping ironically.
Here is a picture when i set terrainSize to 120:
Here is a picture when i set the terrainSize to 200:
At the size 200 looks like its overlapping twice, i found out that the max terrainSize for me is 114 at 115 it starts overlapping.
Here is my code, maybe you can find something out and help me and other on this platform:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class MeshGeneratorSecond : MonoBehaviour
{
[SerializeField] private int terrainSize;
private Mesh myMesh;
private Vector3[] vertices;
private int[] triangles;
private int verticesInVertex = 5;
private int trianglesInVertex = 4;
void Start()
{
myMesh = new Mesh();
GetComponent<MeshFilter>().mesh = myMesh;
vertices = new Vector3[terrainSize * terrainSize * 5];
triangles = new int[terrainSize * terrainSize * 12];
StartCoroutine(CreateShape());
}
IEnumerator CreateShape()
{
int vertex = 0;
int triangle = 0;
for(int x = 0; x < terrainSize; x++)
{
for(int z = 0; z < terrainSize; z++)
{
vertices[vertex] = new Vector3(x, 0, z);
vertices[vertex + 1] = new Vector3(x, 0, z + 1);
vertices[vertex + 2] = new Vector3(x + 1, 0, z + 1);
vertices[vertex + 3] = new Vector3(x + 1, 0, z);
vertices[vertex + 4] = new Vector3(x + 0.5f, 0, z + 0.5f);
//First Triangle
triangles[triangle] = vertex;
triangles[triangle + 1] = vertex + 1;
triangles[triangle + 2] = vertex + 4;
//Second Triangle
triangles[triangle + 3] = vertex + 1;
triangles[triangle + 4] = vertex + 2;
triangles[triangle + 5] = vertex + 4;
//Third Triangle
triangles[triangle + 6] = vertex + 2;
triangles[triangle + 7] = vertex + 3;
triangles[triangle + 8] = vertex + 4;
//Fourth Triangle
triangles[triangle + 9] = vertex + 3;
triangles[triangle + 10] = vertex;
triangles[triangle + 11] = vertex + 4;
vertex += verticesInVertex;
triangle += trianglesInVertex * 3;
}
UpdateMesh();
yield return new WaitForSeconds(.1f);
}
}
private void UpdateMesh()
{
myMesh.Clear();
myMesh.vertices = vertices;
myMesh.triangles = triangles;
myMesh.RecalculateNormals();
}
public void OnDrawGizmos()
{
Gizmos.color = Color.red;
for(int i = 0; i < vertices.Length; i++)
{
Gizmos.DrawSphere(vertices[i], .1f);
}
}
}

Mesh buffers are 16 bit by default. See Mesh-indexFormat:
Index buffer can either be 16 bit (supports up to 65535 vertices in a mesh), or 32 bit (supports up to 4 billion vertices). Default index format is 16 bit, since that takes less memory and bandwidth.
Note! Ehen you want to change the 16-bit buffer to 32-bit buffer, you can change with this line of code:
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

Related

Why does my procedural grid mesh not triangulate properly for grids bigger than 256x256?

I've been making procedural terrain height maps with the diamond square algorithm and the mesh with the triangulation method below:
public Map GenerateMap()
{
Mesh mapMesh = new();
vertices = new Vector3[(Resolution + 1) * (Resolution + 1)];
Vector2[] uv1 = new Vector2[vertices.Length];
Vector2[] uv2 = new Vector2[vertices.Length];
Vector2[] uv3 = new Vector2[vertices.Length];
DiamondSquare diamondSquare = new(Resolution, Roughness, Seed, HeightLevels);
float[,] heightFloatMap = diamondSquare.DoDiamondSquare();
tex = new Texture2D(Resolution, Resolution);
for (int y = 0, i = 0; y <= Resolution; y++)
{
for (int x = 0; x <= Resolution; x++, i++)
{
//float height = heightMap.GetPixel(x,y).r;
float height = heightFloatMap[x, y];
vertices[i] = new Vector3(x * CellSize.x, height * CellSize.y, y * CellSize.z);
tex.SetPixel(x, y, new Color(height, height, height, 1));
if (height == 0)
uv1[i] = new Vector2(vertices[i].x, vertices[i].z);
else if (height < 0.4)
uv2[i] = new Vector2(vertices[i].x, vertices[i].z);
else if (height < 0.4)
uv3[i] = new Vector2(vertices[i].x, vertices[i].z);
}
}
mapMesh.vertices = vertices;
mapMesh.uv = uv1;
mapMesh.uv2 = uv2;
int[] triangles = new int[Resolution * Resolution * 6];
Cell[,] cellMap = new Cell[Resolution / 4, Resolution / 4];
for (int ti = 0, vi = 0, y = 0; y < Resolution; y++, vi++)
{
for (int x = 0; x < Resolution; x++, ti += 6, vi++)
{
triangles[ti] = vi;
triangles[ti + 3] = triangles[ti + 2] = vi + 1;
triangles[ti + 4] = triangles[ti + 1] = vi + Resolution + 1;
triangles[ti + 5] = vi + Resolution + 2;
Vector3[] cellVerts = new Vector3[]
{
vertices[vi], vertices[vi + 1], vertices[vi + Resolution + 1], vertices[vi + Resolution + 2]
};
Cell cell = new(new Vector2Int(x, y), cellVerts, CalculateCellGeometry(cellVerts));
cellMap[x / 4, y / 4] = cell;
}
}
mapMesh.triangles = triangles;
mapMesh.RecalculateNormals();
mapMesh.RecalculateTangents();
mapMesh.RecalculateBounds();
Map map = new(mapMesh, cellMap, heightFloatMap, vertices);
return map;
}
}
This works fine with grid sizes 16x16, 32x32... 256x256 but breaks when I try it on 512x512 or above
256x256
Mesh is perfect
512x512
It successfully triangulates up until the rows starting y=128
On the underside of the terrain there are these bars
I've mapped out the vertices generated from 512x512 and above resolutions and they are all good so I'm 99% sure its down to the triangulation.
I'm new to procedural meshes and am stumped by this issue, any help would be greatly appreciated.
Turns out it wasn't triangulation, the vertex limit was being reached as my mesh was set to use a 16-bit index buffer.
I added this line
mapMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
and the issue is fixed. An annoying oversight on my part but that's part of the learning process!

In unity i'm trying to figure out how to generate mesh with octaves. How would I go about it?

I've made a little mesh generator in Unity by following brackeys tutorial series, but I think one was deleted or taken down because there are pieces missing. I'm trying to learn how to use octaves with perlin noise to create more interesting terrain and I cant figure it out. Here's my code if you can help me:
[RequireComponent(typeof(MeshFilter))]
public class MeshGenerator : MonoBehaviour
{
Mesh mesh;
Vector3[] vertices;
int[] triangles;
Color[] colors;
public Gradient gradient;
float minTerrainHeight;
float maxTerrainHeight;
public int xSize = 20;
public int zSize = 20;
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateShape();
UpdateMesh();
}
void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
colors = new Color[vertices.Length];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
float y = Mathf.PerlinNoise(x * 0.3f, z * 0.3f) * 3f;
if (y > maxTerrainHeight)
{
maxTerrainHeight = y;
}
if (y < minTerrainHeight)
{
minTerrainHeight = y;
}
float height = Mathf.InverseLerp(minTerrainHeight, maxTerrainHeight, vertices[i].y);
colors[i] = gradient.Evaluate(height);
vertices[i] = new Vector3(x, y, z);
i++;
}
}
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int z = 0; z < zSize; z++)
{
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
vert++;
}
}
void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.colors = colors;
mesh.RecalculateNormals();
}
}

Mesh not changing programily

So I am trying to create my own version of Sebastian Lauge's marching cubes coding adventures (https://www.youtube.com/watch?v=M3iI2l0ltbE) and I have a script that generates perlin noise into terrain on the Y-axis ant Im trying to make it so it creates perlin noise for the x, y, and z axis and compile vertices from that perlin noise into a mesh. Rightnow I'm in the process of adding the code to decides which points should be put into the mesh The problem is that I have to change the variable y in lines 49 - 56 to the variable ypn (declared on line 45) and leave the y variables out of that area alone the problem is that if i change one of those y variables (don't know which one) it will make the mesh flat and that's not what I want then it gets worse. If you try to revert the variable you changed back to y it will not change a thing. It will always make the mesh flat unless you make a new script. My code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapGen : MonoBehaviour
{
Mesh mesh;
Material material;
Vector3[] vertices;
int[] triangles;
Vector2[] uvs;
Vector3[] interest;
public int xSize = 20;
public int zSize = 20;
public int ySize = 20;
[Range(-1, 1)]
public float Surface = 0;
public float Weight = 1;
float minHeight = 0;
float maxHeight = 0;
// Start is called before the first frame update
void Start()
{
mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
CreateShape();
UpdateMesh();
}
void CreateShape()
{
vertices = new Vector3[(xSize + 1) * (zSize + 1)];
Texture2D texture = new Texture2D(xSize, zSize, TextureFormat.ARGB32, false);
for (int y = 0; y <= ySize; y++)
{
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
float ypn = (Mathf.PerlinNoise(x * .3f, z * .3f) * 2f) * Weight;
vertices[i] = new Vector3(x, ypn, z);
if (y <= minHeight)
minHeight = y;
else
{
if (y >= maxHeight)
maxHeight = y;
}
var result = Mathf.Lerp(minHeight, maxHeight, Mathf.InverseLerp(0, 1, y));
texture.SetPixel(x, z, new Color(y, x, 1));
i++;
}
}
}
texture.Apply();
GetComponent<Renderer>().material.mainTexture = texture;
triangles = new int[xSize * zSize * 6];
int vert = 0;
int tris = 0;
for (int z = 0; z < zSize; z++)
{
for (int x = 0; x < xSize; x++)
{
triangles[tris + 0] = vert + 0;
triangles[tris + 1] = vert + xSize + 1;
triangles[tris + 2] = vert + 1;
triangles[tris + 3] = vert + 1;
triangles[tris + 4] = vert + xSize + 1;
triangles[tris + 5] = vert + xSize + 2;
vert++;
tris += 6;
}
vert++;
}
uvs = new Vector2[vertices.Length];
for (int i = 0, z = 0; z <= zSize; z++)
{
for (int x = 0; x <= xSize; x++)
{
uvs[i] = new Vector2((float)x / xSize, (float)z / zSize);
i++;
}
}
}
void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
MeshCollider meshc = gameObject.AddComponent(typeof(MeshCollider)) as MeshCollider;
meshc.sharedMesh = mesh;
}
}
Note: using unity 2019.2.15
Script is attached to empty Game object with a mesh renderer and a mesh filter on default unity values

How to fix wrong procedural grid with normalized values in Unity

I have problem with normalized values when creating procedural grid in Unity. I have been following great tutorial from catlikecoding and I dumped in to weird behaving when I tried to use normalized values for my vertices. In some cases of xSize and ySize grid combinations all works, but in other combinations mesh get deformed. Let me give you couple of examples
xSize = 35; ySize = 25; // OK
xSize = 350; ySize = 250; // NOT OK
xSize = 150; ySize = 250; // OK
xSize = 350; ySize = 200; // NOT OK
xSize = 1000; ySize = 750; // NOT OK
First 2 cases I illustrated with sphere representing each 10th vertices.
35x25 case
350x250 case
I am using Unity3d 2018.3
private void Generate()
{
GetComponent<MeshFilter>().mesh = mesh = new Mesh();
mesh.name = "Procedural Grid";
vertices = new Vector3[(xSize + 1) * (ySize + 1)];
Vector2[] uv = new Vector2[vertices.Length];
float multX = 1 / (float)xSize;
float multY = 1 / (float)ySize;
for (int i = 0, y = 0; y <= ySize; y++)
{
for (int x = 0; x <= xSize; x++, i++)
{
//vertices[i] = new Vector3(x, y);
var xNormalized = x * multX;
var yNormalized = y * multY;
vertices[i] = new Vector3(xNormalized, yNormalized);
uv[i] = new Vector2(xNormalized, yNormalized);
}
}
mesh.vertices = vertices;
mesh.uv = uv;
var triangles = new int[xSize * ySize * 6];
for (int ti = 0, vi = 0, y = 0; y < ySize; y++, vi++)
{
for (int x = 0; x < xSize; x++, ti += 6, vi++)
{
triangles[ti] = vi;
triangles[ti + 3] = triangles[ti + 2] = vi + 1;
triangles[ti + 4] = triangles[ti + 1] = vi + xSize + 1;
triangles[ti + 5] = vi + xSize + 2;
}
}
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
I expect the mesh be 1x1 in every case, no matter which xSize or ySize of the grid I use. Anybody can advise how to achieve that?
So my friend explained me, that by default meshes have a 65535 vertices limit in Unity. And I have to nicely ask if I want more.
I had to add
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
after
mesh.name = "Procedural Grid";
here is more..
Suddenly all works as expected. Thank you all for support.

Why the 3D Texture based Volume Rendering has no 3D effects

I implemented an 3D Texture based Volume Rendering using OpenTK. The code is based on this project. But the result showed no 3D effects, just flat 2D image.
The pipeline is simple enough: (1) Load 3D texture; (2) draw a series of quads(rectangles) and specify the corresponding texture coordinates.
The Vertices of each quads were generated using
private void generateVertices(int n)
{
vertices = new float[n * 3 * 4];
int cur;
for (int i = 0; i < n; i++)
{
cur = 3 * 4 * i;
vertices[cur] = -.5f;
vertices[cur + 1] = -.5f;
vertices[cur + 2] = -0.5f + i / n;
vertices[cur+3] = -.5f;
vertices[cur + 4] = .5f;
vertices[cur + 5] = -0.5f + i / n;
vertices[cur+6] = .5f;
vertices[cur + 7] = .5f;
vertices[cur + 8] = -0.5f + i / n;
vertices[cur+9] = .5f;
vertices[cur + 10] = -.5f;
vertices[cur + 11] = -0.5f + i / n;
}
}
To draw 256 quads, just call generateVertices(256) and opengl routine
GLDrawElements(GL_QUADS,...)
The TexCoordinates were calculated using vertices position in vertex shader like this:
texCoord = aPosition+vec3(0.5f,0.5f,0.5f);
Any ideas are welcome.
Integer i at range [0,n-1], i/n will be 0 forever.
So you indeed specify n overlaped quads.
The solution is simple, just explicitly cast i to float (float)i/n.

Categories