I am generating a sphere with the marching cubes algorithm, the sphere is split up into chunks and whenever I try to terraform near a chunk border, instead of a bump being added to the sphere a rift forms on the chunk border breaking up the bump into 2 parts.
Edit: I know what the problem is but I don't know how to fix it. The problem is that in the ChangePointValueFromVector3 function the points on the border aren't registering as a point from both chunks but as a point from only one chunk ie. for point (16, 18, 3) it is only changing the point's value in chunk (1, 2, 0) but it is supposed to change the point's value in both chunk (1, 2, 0) and chunk (2, 2, 0)
here is the marching cubes implementation
public class World : MonoBehaviour
{
[Header("Generation Settings")]
public int NumOfChunksPerAxis = 1;
public int NumOfPointsPerChunkPerAxis = 8;
public float terrainSurface = 0.5f;
public float sphereRadius = 3.5f;
[Header("Refrences")]
public ComputeShader marchingCubesShader;
public Material mat;
ComputeBuffer triBuffer;
ComputeBuffer pointBuffer;
ComputeBuffer debugBuffer;
Dictionary<Vector3Int, Chunk> chunks = new Dictionary<Vector3Int, Chunk>();
private Triangle[] triangles;
private Vector3[] debug;
ComputeBuffer countBuffer;
void Start()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
InitBuffers();
//Debug.Log("InitBuffers Time: " + sw.ElapsedMilliseconds + " ms");
sw = System.Diagnostics.Stopwatch.StartNew();
CreateChunks();
//Debug.Log("CreateChunks Time: " + sw.ElapsedMilliseconds + " ms");
sw = System.Diagnostics.Stopwatch.StartNew();
GenerateChunks();
ReleaseBuffers();
gameObject.GetComponent<GravityAttractor>().center = new Vector3((NumOfChunksPerAxis * NumOfPointsPerChunkPerAxis) / 2f, (NumOfChunksPerAxis * NumOfPointsPerChunkPerAxis) / 2f, (NumOfChunksPerAxis * NumOfPointsPerChunkPerAxis) / 2f);
}
public Chunk GetChunkFromVector3(Vector3 pos)
{
Vector3Int chunkPos = new Vector3Int(Mathf.FloorToInt(pos.x / NumOfPointsPerChunkPerAxis), Mathf.FloorToInt(pos.y / NumOfPointsPerChunkPerAxis), Mathf.FloorToInt(pos.z / NumOfPointsPerChunkPerAxis));
if (chunks.ContainsKey(chunkPos))
return chunks[chunkPos];
return null;
}
void GenerateChunks()
{
long populateChunkTime = 0;
long shaderTime = 0;
long getBufferTime = 0;
long createMeshTime = 0;
foreach (Vector3Int pos in chunks.Keys)
{
Chunk chunk = chunks[pos];
chunk.SetNeighbors(chunks);
var populateChunksw = System.Diagnostics.Stopwatch.StartNew();
chunk.PopulatePoints();
populateChunkTime += populateChunksw.ElapsedMilliseconds;
var shadersw = System.Diagnostics.Stopwatch.StartNew();
DispatchShader(chunk);
shaderTime += shadersw.ElapsedMilliseconds;
var getBuffersw = System.Diagnostics.Stopwatch.StartNew();
GetAppendBufferData(triBuffer, out triangles);
getBufferTime += getBuffersw.ElapsedMilliseconds;
var createMeshsw = System.Diagnostics.Stopwatch.StartNew();
chunk.CreateMesh(triangles);
createMeshTime += createMeshsw.ElapsedMilliseconds;
}
//Debug.Log("Populate Chunks Time: " + populateChunkTime + " ms");
//Debug.Log("Run Shaders Time: " + shaderTime + " ms");
//Debug.Log("Get Bufffers Time: " + getBufferTime + " ms");
//Debug.Log("Create Mesh Time: " + createMeshTime + " ms");
}
private void DispatchShader(Chunk chunk)
{
int kernelIndex = marchingCubesShader.FindKernel("EpThree");
pointBuffer.SetData(chunk.points);
triBuffer.SetCounterValue(0);
marchingCubesShader.SetBuffer(kernelIndex, "triangles", triBuffer);
marchingCubesShader.SetBuffer(kernelIndex, "points", pointBuffer);
marchingCubesShader.SetBuffer(kernelIndex, "debug", debugBuffer);
marchingCubesShader.SetInt("ChunkSize", NumOfPointsPerChunkPerAxis);
marchingCubesShader.SetInts("chunkPos", chunk.chunkPos.x, chunk.chunkPos.y, chunk.chunkPos.z);
marchingCubesShader.SetFloat("terrainSurface", terrainSurface);
marchingCubesShader.Dispatch(kernelIndex, Mathf.CeilToInt(NumOfPointsPerChunkPerAxis / 8), Mathf.CeilToInt(NumOfPointsPerChunkPerAxis / 8), Mathf.CeilToInt(NumOfPointsPerChunkPerAxis / 8));
}
public void RefreshChunk(Chunk chunk)
{
InitBuffers();
DispatchShader(chunk);
GetAppendBufferData(triBuffer, out triangles);
chunk.CreateMesh(triangles);
ReleaseBuffers();
}
void InitBuffers()
{
countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.IndirectArguments);
triBuffer = new ComputeBuffer(5 * NumOfPointsPerChunkPerAxis * NumOfPointsPerChunkPerAxis * NumOfPointsPerChunkPerAxis, sizeof(float) * 9, ComputeBufferType.Append);
pointBuffer = new ComputeBuffer((NumOfPointsPerChunkPerAxis + 1) * (NumOfPointsPerChunkPerAxis + 1) * (NumOfPointsPerChunkPerAxis + 1), sizeof(int) * 3 + sizeof(float));
debugBuffer = new ComputeBuffer(NumOfPointsPerChunkPerAxis * NumOfPointsPerChunkPerAxis * NumOfPointsPerChunkPerAxis * 15, sizeof(float) * 3, ComputeBufferType.Append);
}
void ReleaseBuffers()
{
triBuffer.Release();
pointBuffer.Release();
debugBuffer.Release();
countBuffer.Release();
}
void CreateChunks()
{
for (int x = 0; x < NumOfChunksPerAxis; x++)
{
for (int y = 0; y < NumOfChunksPerAxis; y++)
{
for (int z = 0; z < NumOfChunksPerAxis; z++)
{
Vector3Int pos = new Vector3Int(x, y, z);
GameObject holder = new GameObject("Chunk " + pos);
holder.AddComponent<MeshFilter>();
holder.AddComponent<MeshRenderer>();
holder.AddComponent<MeshCollider>();
holder.transform.tag = "Terrain";
holder.transform.parent = transform;
int size = NumOfChunksPerAxis * NumOfPointsPerChunkPerAxis;
Chunk chunk = new Chunk(this, holder, pos, mat, new Vector3(size / 2f, size / 2f, size / 2f));
chunks.Add(pos, chunk);
}
}
}
}
void GetAppendBufferData<T>(ComputeBuffer buffer, out T[] data)
{
ComputeBuffer.CopyCount(buffer, countBuffer, 0);
int[] counter = new int[1];
countBuffer.GetData(counter);
int count = counter[0];
data = new T[count];
buffer.GetData(data);
}
}
here's the shader
#pragma kernel EpThree
#include "/Tables.compute"
/*
static const int3 CornerTable[8] = {
int3(0, 0, 0), int3(1, 0, 0), int3(1, 1, 0), int3(0, 1, 0), int3(0, 0, 1), int3(1, 0, 1),
int3(1, 1, 1), int3(0, 1, 1)
};
*/
static const int Edges[24] = {
0, 1,
1, 2,
3, 2,
0, 3,
4, 5,
5, 6,
7, 6,
4, 7,
0, 4,
1, 5,
2, 6,
3, 7
};
struct Point {
int3 pos;
float value;
};
struct Triangle {
float3 v1;
float3 v2;
float3 v3;
};
AppendStructuredBuffer<Triangle> triangles;
StructuredBuffer<Point> points;
AppendStructuredBuffer<float3> debug;
int ChunkSize;
int3 chunkPos;
float terrainSurface;
float3 GetWorldSpaceOfPoint(int3 pos) {
return (chunkPos * ChunkSize) + pos;
}
Point GetVertice(int3 pos) {
return points[pos.x + (pos.y * (ChunkSize + 1)) + (pos.z * ((ChunkSize + 1) * (ChunkSize + 1)))];
}
int GetConfigIndex(float cube[8]) {
int configIndex = 0;
for (int i = 0; i < 8; i++)
{
if (cube[i] > terrainSurface) {
configIndex |= 1 << i;
}
}
return configIndex;
}
float3 GetVertex(float3 v1, float3 v2, int indice, float cube[8]) {
float3 vertPos;
float vert1Sample = cube[Edges[indice * 2]];
float vert2Sample = cube[Edges[indice * 2 + 1]];
float diffrence = vert2Sample - vert1Sample;
if (diffrence == 0) {
diffrence = 0.5;
}
else {
diffrence = (0.5 - vert1Sample) / diffrence;
}
vertPos = v1 + ((v2 - v1) * diffrence);
return vertPos;
}
[numthreads(8,8,8)]
void EpThree(int3 pos : SV_DispatchThreadID)
{
//MarchCube(pos);
int NoCubesPerChunk = ChunkSize;
if (pos.x >= NoCubesPerChunk || pos.y >= NoCubesPerChunk || pos.z >= NoCubesPerChunk) {
return;
}
float cube[8];
for (int h = 0; h < 8; h++)
{
cube[h] = GetVertice(pos + CornerTable[h]).value;
// points[(pos + CornerTable[h]).x + ((pos + CornerTable[h]).y * ChunkSize) + ((pos +
CornerTable[h]).z + (ChunkSize * ChunkSize))].value;
}
int configIndex = GetConfigIndex(cube);
int edgeIndexes[] = triangulation[configIndex];
if (configIndex == 0 || configIndex == 255) {
return;
}
for (int i = 0; i < 16; i += 3)
{
int indice1 = edgeIndexes[i];
int indice2 = edgeIndexes[i + 1];
int indice3 = edgeIndexes[i + 2];
if (indice1 == -1 || indice2 == -1 || indice3 == -1) {
break;
}
float diffrence;
float3 a1 = GetWorldSpaceOfPoint(pos + CornerTable[Edges[indice1 * 2]]);
float3 a2 = GetWorldSpaceOfPoint(pos + CornerTable[Edges[indice1 * 2 + 1]]);
float3 b1 = GetWorldSpaceOfPoint(pos + CornerTable[Edges[indice2 * 2]]);
float3 b2 = GetWorldSpaceOfPoint(pos + CornerTable[Edges[indice2 * 2 + 1]]);
float3 c1 = GetWorldSpaceOfPoint(pos + CornerTable[Edges[indice3 * 2]]);
float3 c2 = GetWorldSpaceOfPoint(pos + CornerTable[Edges[indice3 * 2 + 1]]);
//-----------------------------------------------------------------------------------------
float a1s = cube[Edges[indice1 * 2]];
float a2s = cube[Edges[indice1 * 2 + 1]];
diffrence = a2s - a1s;
if (diffrence == 0) {
diffrence = 0.5;
}
else {
diffrence = (0.5 - a1s) / diffrence;
}
float3 a = a1 + ((a2 - a1) * diffrence);
//----------------------------------------------------
float b1s = cube[Edges[indice2 * 2]];
float b2s = cube[Edges[indice2 * 2 + 1]];
diffrence = b2s - b1s;
if (diffrence == 0) {
diffrence = 0.5;
}
else {
diffrence = (0.5 - b1s) / diffrence;
}
float3 b = b1 + ((b2 - b1) * diffrence);
//---------------------------------------------------
float c1s = cube[Edges[indice3 * 2]];
float c2s = cube[Edges[indice3 * 2 + 1]];
diffrence = c2s - c1s;
if (diffrence == 0) {
diffrence = 0.5;
}
else {
diffrence = (0.5 - c1s) / diffrence;
}
float3 c = c1 + ((c2 - c1) * diffrence);
//------------------------------------------------------
Triangle tri = { a, b, c };
debug.Append(tri.v1);
debug.Append(tri.v2);
debug.Append(tri.v3);
triangles.Append(tri);
}
}
this is the chunk script
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Chunk
{
public static Vector3Int[] neighborPositions = new Vector3Int[26]
{
new Vector3Int( 1, 0, 0),
new Vector3Int( 1, 1, 0),
new Vector3Int( 1, -1, 0),
new Vector3Int( 1, 0, 1),
new Vector3Int( 1, 0, -1),
new Vector3Int( 1, 1, 1),
new Vector3Int( 1, 1, -1),
new Vector3Int( 1, -1, 1),
new Vector3Int( 1, -1, -1),
new Vector3Int(-1, 0, 0),
new Vector3Int(-1, 1, 0),
new Vector3Int(-1, -1, 0),
new Vector3Int(-1, 0, 1),
new Vector3Int(-1, 0, -1),
new Vector3Int(-1, 1, 1),
new Vector3Int(-1, 1, -1),
new Vector3Int(-1, -1, 1),
new Vector3Int(-1, -1, -1),
new Vector3Int( 0, 1, 0),
new Vector3Int( 0, 1, 1),
new Vector3Int( 0, 1, -1),
new Vector3Int( 0, -1, 0),
new Vector3Int( 0, -1, 1),
new Vector3Int( 0, -1, -1),
new Vector3Int( 0, 0, 1),
new Vector3Int( 0, 0, -1)
};
World world;
public GameObject holder;
MeshFilter meshFilter;
MeshCollider meshCollider;
public Vector3Int chunkPos;
Vector3 center;
List<Vector3> vertices = new List<Vector3>();
List<int> meshTriangles = new List<int>();
public Point[] points;
Chunk[] neighbors;
List<Chunk> refreshList = new List<Chunk>();
public Chunk(World world, GameObject holder, Vector3Int pos, Material mat, Vector3 center)
{
this.world = world;
this.holder = holder;
meshFilter = this.holder.GetComponent<MeshFilter>();
meshCollider = this.holder.GetComponent<MeshCollider>();
this.holder.GetComponent<MeshRenderer>().material = mat;
chunkPos = pos;
this.center = center;
neighbors = new Chunk[26];
}
public void SetNeighbors(Dictionary<Vector3Int, Chunk> chunks)
{
for (int i = 0; i < 26; i++)
{
chunks.TryGetValue(chunkPos + neighborPositions[i], out neighbors[i]);
}
/*
foreach(Chunk chunk in neighbors)
{
if (chunk != null)
Debug.Log(chunkPos + " : " + chunk.chunkPos);
else
Debug.Log(chunkPos + " : null");
}
*/
}
public Vector3Int GetWorldSpaceOfPoint(Vector3Int point)
{
return chunkPos * world.NumOfPointsPerChunkPerAxis + point;
}
public void PopulatePoints()
{
points = new Point[(world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)];
for (int x = 0; x < (world.NumOfPointsPerChunkPerAxis + 1); x++)
{
for (int y = 0; y < (world.NumOfPointsPerChunkPerAxis + 1); y++)
{
for (int z = 0; z < (world.NumOfPointsPerChunkPerAxis + 1); z++)
{
Vector3Int position = GetWorldSpaceOfPoint(new Vector3Int(x, y, z));
float dstToCenter = Mathf.Sqrt(
((position.x) - center.x) * ((position.x) - center.x)
+ ((position.y) - center.y) * ((position.y) - center.y)
+ ((position.z) - center.z) * ((position.z) - center.z)
);
points[x + (y * (world.NumOfPointsPerChunkPerAxis + 1)) + (z * ((world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)))] = new Point
{
pos = position,
value = dstToCenter - (world.sphereRadius + GetNoiseAtPos(position))
};
}
}
}
}
public void AddTerrain(Vector3 globalPos, int addRadius)
{
Vector3 localPos = new Vector3(globalPos.x % world.NumOfPointsPerChunkPerAxis, globalPos.y % world.NumOfPointsPerChunkPerAxis, globalPos.z % world.NumOfPointsPerChunkPerAxis);
/*
points[Mathf.RoundToInt(localPos.x) + (Mathf.RoundToInt(localPos.y) * (world.NumOfPointsPerChunkPerAxis + 1)) + (Mathf.RoundToInt(localPos.z) * ((world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)))].value += 1;
*/
for (float x = -((addRadius + 1) / 2f); x < (addRadius + 1) / 2f; x++)
{
for (float y = -((addRadius + 1) / 2f); y < (addRadius + 1) / 2f; y++)
{
for (float z = -((addRadius + 1) / 2f); z < (addRadius + 1) / 2f; z++)
{
Vector3 pointPos = (new Vector3(x, y, z) + localPos);
float distance = Vector3.Distance(pointPos, localPos);
ChangePointValueFromVector3(pointPos, distance - addRadius);
}
}
}
world.RefreshChunk(this);
foreach(Chunk chunk in refreshList)
{
if (chunk != null)
world.RefreshChunk(chunk);
}
}
public void RemoveTerrain(Vector3 globalPos, int removeRadius)
{
Vector3 localPos = new Vector3(globalPos.x % world.NumOfPointsPerChunkPerAxis, globalPos.y % world.NumOfPointsPerChunkPerAxis, globalPos.z % world.NumOfPointsPerChunkPerAxis);
/*
points[Mathf.RoundToInt(localPos.x) + (Mathf.RoundToInt(localPos.y) * (world.NumOfPointsPerChunkPerAxis + 1)) + (Mathf.RoundToInt(localPos.z) * ((world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)))].value += 1;
*/
for (float x = -((removeRadius + 1) / 2f); x < (removeRadius + 1) / 2f; x++)
{
for (float y = -((removeRadius + 1) / 2f); y < (removeRadius + 1) / 2f; y++)
{
for (float z = -((removeRadius + 1) / 2f); z < (removeRadius + 1) / 2f; z++)
{
Vector3 pointPos = (new Vector3(x, y, z) + localPos);
float distance = Vector3.Distance(pointPos, localPos);
ChangePointValueFromVector3(pointPos, (removeRadius - distance));
}
}
}
world.RefreshChunk(this);
foreach(Chunk chunk in refreshList)
{
if (chunk != null)
{
world.RefreshChunk(chunk);
Debug.Log(chunk.holder.name);
}
}
}
public Vector3 GetLocalPosFromGlobalPos(Vector3 pos)
{
return new Vector3(pos.x % (world.NumOfPointsPerChunkPerAxis ), pos.y % (world.NumOfPointsPerChunkPerAxis ), pos.z % (world.NumOfPointsPerChunkPerAxis ));
}
public void ChangePointValueFromVector3(Vector3 pos, float changeVal)
{
if (pos.x < world.NumOfPointsPerChunkPerAxis + 1 && pos.x > 0 && pos.y < world.NumOfPointsPerChunkPerAxis + 1 && pos.y > 0 && pos.z < world.NumOfPointsPerChunkPerAxis + 1 && pos.z > 0)
{
points[GetPointIdFromVector3(pos)].value += changeVal;
}
else if (pos.x == world.NumOfPointsPerChunkPerAxis + 1 || pos.x == 0 || pos.y == world.NumOfPointsPerChunkPerAxis + 1 || pos.y == 0 || pos.z == world.NumOfPointsPerChunkPerAxis + 1 || pos.z == 0)
{
points[GetPointIdFromVector3(pos)].value += changeVal;
Chunk chunk = world.GetChunkFromVector3((chunkPos * world.NumOfPointsPerChunkPerAxis) + pos);
refreshList.Add(chunk);
chunk.points[chunk.GetPointIdFromVector3(pos - (Vector3.one * world.NumOfPointsPerChunkPerAxis))].value += changeVal;
}
else
{
Chunk chunk = world.GetChunkFromVector3((chunkPos * world.NumOfPointsPerChunkPerAxis) + pos);
refreshList.Add(chunk);
chunk.points[chunk.GetPointIdFromVector3(GetLocalPosFromGlobalPos((chunkPos * world.NumOfPointsPerChunkPerAxis) + pos))].value += changeVal;
}
/*if (pos.x > world.NumOfPointsPerChunkPerAxis + 1 || pos.x < 0 || pos.y > world.NumOfPointsPerChunkPerAxis + 1 || pos.y < 0 || pos.z > world.NumOfPointsPerChunkPerAxis + 1 || pos.z < 0)
{
Chunk chunk = world.GetChunkFromVector3((chunkPos * world.NumOfPointsPerChunkPerAxis) + pos);
chunk.points[Mathf.RoundToInt((pos - (Vector3.one * world.NumOfPointsPerChunkPerAxis)).x) + Mathf.RoundToInt((pos - (Vector3.one * world.NumOfPointsPerChunkPerAxis)).y) * (world.NumOfPointsPerChunkPerAxis + 1) + (Mathf.RoundToInt((pos - (Vector3.one * world.NumOfPointsPerChunkPerAxis)).z) * ((world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)))].value += changeVal;
}
else if (pos.x < world.NumOfPointsPerChunkPerAxis + 1 && pos.x > 0 && pos.y < world.NumOfPointsPerChunkPerAxis + 1 && pos.y > 0 && pos.z < world.NumOfPointsPerChunkPerAxis + 1 && pos.z > 0)
{
points[Mathf.RoundToInt(pos.x) + (Mathf.RoundToInt(pos.y) * (world.NumOfPointsPerChunkPerAxis + 1)) + (Mathf.RoundToInt(pos.z) * ((world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)))].value += changeVal;
}
else
{
points[Mathf.RoundToInt(pos.x) + (Mathf.RoundToInt(pos.y) * (world.NumOfPointsPerChunkPerAxis + 1)) + (Mathf.RoundToInt(pos.z) * ((world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)))].value += changeVal;
Chunk chunk = world.GetChunkFromVector3((chunkPos * world.NumOfPointsPerChunkPerAxis) + pos);
chunk.points[Mathf.RoundToInt((pos - (Vector3.one * world.NumOfPointsPerChunkPerAxis)).x) + Mathf.RoundToInt((pos - (Vector3.one * world.NumOfPointsPerChunkPerAxis)).y) * (world.NumOfPointsPerChunkPerAxis + 1) + (Mathf.RoundToInt((pos - (Vector3.one * world.NumOfPointsPerChunkPerAxis)).z) * ((world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)))].value += changeVal;
}*/
}
public int GetPointIdFromVector3(Vector3 pos)
{
try
{
return Mathf.RoundToInt(pos.x) + (Mathf.RoundToInt(pos.y) * (world.NumOfPointsPerChunkPerAxis + 1)) + (Mathf.RoundToInt(pos.z) * ((world.NumOfPointsPerChunkPerAxis + 1) * (world.NumOfPointsPerChunkPerAxis + 1)));
}
catch
{
return -1;
}
}
private float GetNoiseAtPos(Vector3Int position)
{
return 0;
}
public void CreateMesh(Triangle[] triangleData)
{
meshTriangles.Clear();
vertices.Clear();
foreach (Triangle triangle in triangleData)
{
/*
vertices.Add(triangle.v1);
meshTriangles.Add(vertices.Count - 1);
vertices.Add(triangle.v2);
meshTriangles.Add(vertices.Count - 1);
vertices.Add(triangle.v3);
meshTriangles.Add(vertices.Count - 1);
*/
meshTriangles.Add(VertForIndice(triangle.v1));
meshTriangles.Add(VertForIndice(triangle.v2));
meshTriangles.Add(VertForIndice(triangle.v3));
}
Mesh mesh = new Mesh();
mesh.vertices = vertices.ToArray();
mesh.triangles = meshTriangles.ToArray();
mesh.RecalculateNormals();
meshFilter.sharedMesh = mesh;
meshCollider.sharedMesh = mesh;
}
int VertForIndice(Vector3 vert)
{
for (int i = 0; i < vertices.Count; i++)
{
if (vertices[i] == vert)
return i;
}
vertices.Add(vert);
return vertices.Count - 1;
}
}
public struct Triangle
{
public Vector3 v1, v2, v3;
}
public struct Point
{
public Vector3Int pos;
public float value;
}
I think the problem is in the AddTerrain function but I'm not sure
I also get this error whenever I edit it but I think it is related to the size limit
NullReferenceException: Object reference not set to an instance of an object Ep3.Chunk.ChangePointValueFromVector3 (UnityEngine.Vector3 pos, System.Single changeVal) (at Assets/Ep 3 Player Controler/Scripts/Chunk.cs:199) Ep3.Chunk.AddTerrain (UnityEngine.Vector3 globalPos, System.Int32 addRadius) (at Assets/Ep 3 Player Controler/Scripts/Chunk.cs:135) Ep3.FirstPersonController.Update () (at Assets/Ep 3 Player Controler/Scripts/Player Controller/FirstPersonController.cs:81)
