Large triangular polygon with a large number of points in the mesh - unity3d

When creating the mesh, I had a problem: both in the game, and in the scene appears a large triangular polygon. The problem is that with a system size of 250 by 250 points there aren't this polygon. At a size of 400 by 400 points, it already appears.
What I did:
void Start () {
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = mf.mesh;
int size = 400;
Vector3[] vertices = new Vector3[size * size];
Vector3[] normals = new Vector3[size * size];
Vector2[] uvc = new Vector2[size * size];
int c = 0;
for (int i =0; i < size; i++)
{
for(int j =0; j < size; j++)
{
vertices[c] = new Vector3(i, j, Mathf.Sin(j+i+Mathf.PI));
normals[c] = -Vector3.forward;
float mult = 1.0f / ((float)(size));
uvc[c] = new Vector2(((float)(i))*mult, ((float)(j)) * mult);
c++;
}
};
int[] triangles = new int[(size-1)*(size-1)*6];
int counter = 0;
{
for (int i = 0; i < size - 1; i++)
{
for (int j = 0; j < size - 1; j++)
{
setTriangle(ref triangles, ref counter, i * size + j);
setTriangle(ref triangles, ref counter, (i + 1) * size + j);
setTriangle(ref triangles, ref counter, i * size + j + 1);
setTriangle(ref triangles, ref counter, (i + 1) * size + j);
setTriangle(ref triangles, ref counter, (i + 1) * size + j + 1);
setTriangle(ref triangles, ref counter, i * size + j + 1);
};
}
};
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uvc;
mesh.RecalculateNormals();
gameObject.transform.position = new Vector3(-55, -60, 90);
void setTriangle(ref int[] triangle, ref int index, int num)
{
triangle[index++] = num;
}
And what I have in results. The first picture is with 250 by 250 points. The second is with 400 by 400. The third is just bigger picture

I think you are over the max. number of vertices for the mesh when the size is 400x400.
The default max. number of vertices for a mesh is 65535. If you want to have more, then you have to set:
mesh.indexFormat = Rendering.IndexFormat.UInt32;
but this is not guaranteed to be supported in all platforms.

Related

Flat color each triangle in a mesh

Im trying to make a 'n' sided mesh with a custom color for each triangle, I can select how many sides it has, the radius, and i'm struggling with the color. I want to put a random color on each drawn triangle, now that works, but I don't want it to blend with the other colors, I want it to be a flat color.
Shoud I make a material for each triangle via code and assign it to a triangle?, maybe a shader?. I dont know too much about materials or shaders, but willing to learn, just need to know what would be the best solution and maybe how to apply it.this is an Example of what i want
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[RequireComponent(typeof(MeshFilter))]
public class CreateSectionMesh : MonoBehaviour {
//Sides of the Plane
[Range(3, 100, order = 1)]
[SerializeField]
int NumberOfSides = 3;
//Radius of the plane
[Range(10, 100, order = 1)]
[SerializeField]
int ShapeRadius = 10;
// Just setup everything from the start to test...
void Start() {
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = new Vector3[NumberOfSides + 1];
//With this I can know the angle for each triangle
float angle = 2 * Mathf.PI / NumberOfSides;
vertices[0] = new Vector3(0, 0);
Color[] colors = new Color[vertices.Length];
//Set the vertices
for (int i = 1; i <= NumberOfSides; i++) {
vertices[i] = new Vector3(Mathf.Sin(i * angle), Mathf.Cos(i * angle)) * ShapeRadius;
}
for (int i = 0; i <= NumberOfSides; i++) {
Debug.LogFormat("Vertices: {0}", vertices[i]);
}
//Setup the triangles to draw them properly
int[] triangles = new int[3 * NumberOfSides];
for (int i = 0; i < NumberOfSides; i++) {
triangles[3 * i] = 0;
triangles[3 * i + 1] = i + 1;
triangles[3 * i + 2] = i + 2 > NumberOfSides ? i + 2 - NumberOfSides : i + 2;
}
for (int i = 0; i < triangles.Length; i++) {
Debug.Log(triangles[i]);
}
//Finally the color for each triangle, but is blending with each near driangle color...
for (int i = 0; i < vertices.Length; i++) {
colors[i] = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
}
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.colors = colors;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
mesh.Optimize();
}
}
Thanks for the help

How to implement Offset on Perlin noise?

I need a little help,
I have this Perlin noise function, but I don't know how to properly create offsets.
I am using this to create infinite terrain generation and when I use this script it the noise values of individual chunks don't fit together properly. And they create holes.
Is there a way of fixing this ?
public float[,] GenerateNoise(int chunkSize, int octaves, string seed, float noiseScale, float persistence, float lacunarity, Vector2 offset)
{
if (noiseScale <= 0)
{
noiseScale = 0.0001f;
}
float halfWidth = chunkSize / 2f;
float halfHeight = chunkSize / 2f;
float[,] noiseMap = new float[chunkSize, chunkSize];
System.Random rand = new System.Random(seed.GetHashCode());
//Octaves offset
Vector2[] octavesOffset = new Vector2[octaves];
for (int i = 0; i < octaves; i++)
{
float offset_X = rand.Next(-100000, 100000) + offset.x;
float offset_Y = rand.Next(-100000, 100000) + offset.y;
octavesOffset[i] = new Vector2(offset_X / chunkSize , offset_Y / chunkSize);
}
for (int x = 0; x < chunkSize; x++)
{
for (int y = 0; y < chunkSize; y++)
{
float amplitude = 1;
float frequency = 1;
float noiseHeight = 0;
float superpositionCompensation = 0;
for (int i = 0; i < octaves; i++)
{
float sampleX = (x - halfWidth) / noiseScale * frequency + octavesOffset[i].x * frequency;
float sampleY = (y - halfHeight) / noiseScale * frequency + octavesOffset[i].y * frequency;
float noiseValue = Mathf.PerlinNoise(sampleX, sampleY);
noiseHeight += noiseValue * amplitude;
noiseHeight -= superpositionCompensation;
amplitude *= persistence;
frequency *= lacunarity;
superpositionCompensation = amplitude / 2;
}
noiseMap[x, y] = Mathf.Clamp01(noiseHeight);
}
}
return noiseMap;
}
It is quite simple actually, just add the chunk x,y coordinates to Mathf.PerlinNoise. Taking your code as an example, you can:
Pass chunkPosition as an argument to it:
public float[,] GenerateNoise(Vector2 chunkPos, int chunkSize, int octaves, string seed, float noiseScale, float persistence, float lacunarity, Vector2 offset)
Add it to Mathf.PerlinNoise invocation:
float noiseValue = Mathf.PerlinNoise(sampleX + chunkPos.x, sampleY + chunkPos.y);
Then make sure to generate each chunk with an appropriate chunkPos, where chunkPos can be its transform.position or whatever coordinates you have.
That's it.

How to draw multiple circles by using "LineRenderer"

There is a code for a drawing circle with LineRenderer.
but I want to draw multiple circles with different radius, I used "for loop" but there is one circle instead of multiple
public float ThetaScale = 0.01f;
public float radius = 3f;
private int Size;
private LineRenderer LineDrawer;
private float Theta = 0f;
void Start ()
{
LineDrawer = GetComponent<LineRenderer>();
}
void Update ()
{
Theta = 0f;
Size = (int)((1f / ThetaScale) + 1f);
LineDrawer.SetVertexCount(Size);
for (int l = 0; l < 5; l++)
{
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
LineDrawer.SetPosition(i, new Vector3(x, 0, y));
}
}
}
In every loop you always overwrite the same positions indices in the same line renderer. So you will always only have the last circle.
Note that it is also quite expensive to use SetPoisition repeatedly. As it says in the API you should rather work on an array and then use SetPoisitions to assign all positions at once.
One thing is a bit unclear though: If you use one single LineRenderer you won't get independent circles but they will always be connected at some point. Otherwise you would need 5 separated LineRenderer instances.
Option A: 5 circles but connected to each other since part of a single LineRenderer
void Start ()
{
LineDrawer = GetComponent<LineRenderer>();
LineDrawer.loop = false;
Theta = 0f;
// Use one position more to close the circle
Size = (int)((1f / ThetaScale) + 1f) + 1;
LineDrawer.positionCount = 5 * Size;
var positions = new Vector3[5 * Size];
for (int l = 0; l < 5; l++)
{
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
positions[5 * l + i] = new Vector3(x, 0, y);
}
}
LineDrawer.SetPositions(positions);
}
Option B: 5 separated circles in 5 separated LineRenderers
// Drag 5 individual LineRenderer here via the Inspector
public LineRenderer[] lines = new LineRenderer[5];
void Start ()
{
foreach(var line in lines)
{
line.loop = true;
Theta = 0f;
Size = (int)((1f / ThetaScale) + 1f);
line.positionCount = Size;
var positions = new Vector3[Size];
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
positions[5 * l + i] = new Vector3(x, 0, y);
}
line.SetPositions(positions);
}
}
You missed few details here and there. Here, this will work:
using UnityEngine;
[ExecuteAlways]
[RequireComponent( typeof(LineRenderer) )]
public class CircularBehaviour : MonoBehaviour
{
[SerializeField][Min(3)] int _numSegments = 16;
[SerializeField][Min(1)] int _numCircles = 5;
[SerializeField] float _radius = 3f;
LineRenderer _lineRenderer;
void Awake ()
{
_lineRenderer = GetComponent<LineRenderer>();
_lineRenderer.loop = false;
_lineRenderer.useWorldSpace = false;
}
void Update ()
{
const float TAU = 2f * Mathf.PI;
float theta = TAU / (float)_numSegments;
int numVertices = _numSegments + 1;
_lineRenderer.positionCount = numVertices * _numCircles;
int vert = 0;
for( int l=1 ; l<=_numCircles ; l++ )
{
float r = _radius * (float)l;
for( int i=0 ; i<numVertices ; i++ )
{
float f = theta * (float)i;
Vector3 v = new Vector3{ x=Mathf.Cos(f) , y=Mathf.Sin(f) } * r;
_lineRenderer.SetPosition( vert++ , v );
}
}
}
}
But
as #derHugo explained, this is not what you're looking for exactly as all circles will be drawn connected.

Unity Mesh UV problem on the positive and negative x-axis on perpendicular walls

I am trying to make a 3D-voxel game that uses the marching cubes algorithm to procedurally generate a game world. This is working fine so far, except that, on exactly perpendicular sides on the positive and negative x sides of a given perpendicular piece of the world/chunk mesh, it looks like the uv coordinates aren't quite right as it just displays a solid color instead of the texture. [![view of debug-chunks and the buggy sides][1]][1]
At <2.> you can see the chunk wall how it is supposed to look like and at <1.> you can see the weird bug. This ONLY occurs on exactly perpendicular x-side triangles! Those meshes in the image are debug-chunks to show the problem.
All the noise-to-terrain translation works fine and I don't get any bugs there. It's only the uvs that cause problems.
I am using the following code to populate the Mesh.vertices, Mesh.triangles and Mesh.uv:
void MakeChunkMeshData()
{
for (int x = 0; x < Variables.chunkSize.x - 1; x++)
{
for (int y = 0; y < Variables.chunkSize.y - 1; y++)
{
for (int z = 0; z < Variables.chunkSize.z - 1; z++)
{
byte[] cubeCornerSolidityValues = new byte[8]{
chunkMapSolidity[x, y, z],
chunkMapSolidity[x + 1, y, z],
chunkMapSolidity[x + 1, y + 1, z],
chunkMapSolidity[x, y + 1, z],
chunkMapSolidity[x, y, z + 1],
chunkMapSolidity[x + 1, y, z + 1],
chunkMapSolidity[x + 1, y + 1, z + 1],
chunkMapSolidity[x, y + 1, z + 1]
};
MarchOne(new Vector3Int(x, y, z), cubeCornerSolidityValues);
}
}
}
}
void DrawChunk()
{
chunkMesh.vertices = vertices.ToArray();
chunkMesh.triangles = triangles.ToArray();
chunkMesh.SetUVs(0, uvs.ToArray());
chunkMesh.RecalculateNormals();
}
void ClearMesh()
{
chunkMesh.Clear();
}
void ClearChunkMeshAndData()
{
chunkMesh.Clear();
uvs = new List<Vector2>();
vertices = new List<Vector3>();
triangles = new List<int>();
}
/// <summary>
/// cube contains bytes for each corner of the cube
/// </summary>
/// <param name="cube"></param>
/// <returns></returns>
int GetCubeConfiguration(byte[] cube)
{
int u = 0;
int result = 0;
for(int corner = 0; corner < 8; corner++)
{
if (cube[corner] < Variables.solidityThreshold)
{
u++;
result |= 1 << corner;
}
}
return result;
}
Vector2[] getUvsPerTriangle(byte[] voxelTypes)
{
int resId = voxelTypes[0];
if (voxelTypes[1] == voxelTypes[2])
resId = voxelTypes[1];
resId = 1;
Vector2 normalized = getUvCoordFromTextureIndex(resId) / Constants.TextureAtlasSizeTextures;
float textureLength = 1f/Constants.TextureAtlasSizeTextures;
Vector2[] result = new Vector2[3] {
normalized + new Vector2(1,0) * textureLength,
normalized + new Vector2(0,1) * textureLength,
normalized + new Vector2(1,1) * textureLength
};
//Debug.Log(result);
return result;
}
/// <summary>
/// returns the absolute x and y coordinates of the given texture in the atlas (example: [4, 1])
/// </summary>
/// <param name="textureIndex"></param>
/// <returns></returns>
Vector2 getUvCoordFromTextureIndex(int textureIndex)
{
int x = textureIndex % Constants.TextureAtlasSizeTextures;
int y = (textureIndex - x) / Constants.TextureAtlasSizeTextures;
return new Vector2(x, y);
}
/// <summary>
/// takes the chunk-wide mesh data and adds its results after marching one cube to it.
/// </summary>
/// <returns></returns>
void MarchOne(Vector3Int offset, byte[] cube)
{
int configuration = GetCubeConfiguration(cube);
byte[] voxelTypes = new byte[3];
int edge = 0;
for (int i = 0; i < 5; i++) //loop at max 5 times (max number of triangles in one cube config)
{
for(int v = 0; v < 3; v++) // loop 3 times through shit(count of vertices in a TRIangle, who would have thought...)
{
int cornerIndex = VoxelData.TriangleTable[configuration, edge];
if (cornerIndex == -1) // indicates the end of the list of vertices/triangles
return;
Vector3 vertex1 = lwTo.Vec3(VoxelData.EdgeTable[cornerIndex, 0]) + offset;
Vector3 vertex2 = lwTo.Vec3(VoxelData.EdgeTable[cornerIndex, 1]) + offset;
Vector3Int vertexIndex1 = lwTo.Vec3Int(VoxelData.EdgeTable[cornerIndex, 0]) + offset;
Vector3Int vertexIndex2 = lwTo.Vec3Int(VoxelData.EdgeTable[cornerIndex, 1]) + offset;
Vector3 vertexPosition;
if (Variables.badGraphics)
{
vertexPosition = (vertex1 + vertex2) / 2f;
}
else
{
// currently using this "profile"
// this code determines the position of the vertices per triangle based on the value in chunkSolidityMap[,,]
float vert1Solidity = chunkMapSolidity[vertexIndex1.x, vertexIndex1.y, vertexIndex1.z];
float vert2Solidity = chunkMapSolidity[vertexIndex2.x, vertexIndex2.y, vertexIndex2.z];
float difference = vert2Solidity - vert1Solidity;
difference = (Variables.solidityThreshold - vert1Solidity) / difference;
vertexPosition = vertex1 + ((vertex2 - vertex1) * difference);
}
vertices.Add(vertexPosition);
triangles.Add(vertices.Count - 1);
voxelTypes[v] = chunkMapVoxelTypes[vertexIndex1.x, vertexIndex1.y, vertexIndex1.z];
edge++;
}
uvs.AddRange(getUvsPerTriangle(voxelTypes));
}
}
EDIT:
when only slightly rotating the chunks, the weird problem immediately disappears. I don't know why, but at least i now have some clue what's going on here.
[1]: https://i.stack.imgur.com/kYnkl.jpg
Well, it turns out that this probably is some weird behavior from unity. When explicitly setting the mesh after the mesh population process as the meshFilters' mesh, it works just fine. Also, I had to call mesh.RecalculateTangents() to make it work.

Unity perlin noise having repeating patterns

I made a Noise class using the Perlin Noise from Unity like this:
public static float[,] GetNoise(Vector2Int initialOffset, float scale, float persistance, float lacunarity, int octaves)
{
float[,] noiseMap = new float[Chunk.width, Chunk.height];
float maxHeight = 0;
float minHeight = 0;
for (int y = 0; y < Chunk.height; y++)
{
for (int x = 0; x < Chunk.width; x++)
{
float amplitude = 1;
float frequency = 1;
float noiseHeight = 0;
for (int oc = 0; oc < octaves; oc++)
{
float coordX = (x + initialOffset.x) / scale * frequency;
float coordY = (y + initialOffset.y) / scale * frequency;
float perlin = Mathf.PerlinNoise(coordX, coordY) * 2 - 1;
noiseHeight += perlin * amplitude;
amplitude *= persistance;
frequency *= lacunarity;
}
if (noiseHeight < minHeight)
{
minHeight = noiseHeight;
}
if (noiseHeight > maxHeight)
{
maxHeight = noiseHeight;
}
noiseMap[x, y] = noiseHeight;
}
}
for (int y = 0; y < Chunk.height; y++)
{
for (int x = 0; x < Chunk.width; x++)
{
noiseMap[x, y] = Mathf.InverseLerp(minHeight, maxHeight, noiseMap[x, y]);
}
}
return noiseMap;
}
However this code is giving me repeating patterns like this:
What am I doing wrong? Or there is no way to get rid of the patterns?
I got it working, not very well, but working. The way I did was I generate the height map for every tile in the chunk, then I did some random placing of tiles, while having in account the height map. Something like this:
if (heightMap[x, y] < 0.3 && Random.value < 0.5)
// Add tile
This way I got this result:
EDIT:
Doing some more research about Perlin Noise I found out that it just doesn't like negative coords for some reason, so I did this way, hope this helps someone!
so .. fixed the negative coords like this:
//account for negatives (ex. -1 % 256 = -1, needs to loop around to 255)
if (noiseOffset.x < 0)
noiseOffset = new Vector2(noiseOffset.x + noiseRange.x, noiseOffset.y);
if (noiseOffset.y < 0)
noiseOffset = new Vector2(noiseOffset.x, noiseOffset.y + noiseRange.y);