public void Visualize(float[,,] data) { var cube = new MarchingCube(transform.position, data, cubeSize, isoLevel); _bounds.Clear(); var meshData = cube.March((min, max) => { _bounds.Add(new Bounds((min + max) / 2f, max - min)); }); mesh = new Mesh() { indexFormat = IndexFormat.UInt32, vertices = meshData.Vertices.ToArray(), triangles = meshData.Triangles.ToArray() }; mesh.RecalculateBounds(); mesh.RecalculateNormals(); if (!meshFilter) { meshFilter = gameObject.AddComponent <MeshFilter>(); } meshFilter.sharedMesh = mesh; if (!meshRenderer) { meshRenderer = gameObject.AddComponent <MeshRenderer>(); } meshRenderer.sharedMaterial = VisualMaterial; if (!meshCollider) { meshCollider = gameObject.AddComponent <MeshCollider>(); } meshCollider.sharedMesh = mesh; }
void GenerateMap() { int resolutionCube = resolution * resolution * resolution; if (map.Length != resolutionCube) { map = new float[resolution, resolution, resolution]; } NativeList <int3> usedIndices = new NativeList <int3>(Allocator.Temp); for (int x = 0; x < resolution - 1; x++) { for (int y = 0; y < resolution - 1; y++) { for (int z = 0; z < resolution - 1; z++) { float4 pos = new float4(position.x + x * scale, position.y + y * scale, position.z + z * scale, position.w); float perlin = noise.cnoise(pos); map[x, y, z] = perlin > thresHold ? 1 : 0; usedIndices.Add(new int3(x, y, z)); } } } MarchingCube.CreateMeshData(map, usedIndices, scale, ref mesh); usedIndices.Dispose(); filter.mesh = mesh; }
static void CalculateVertexWeight(MarchingCube cube, int index, MarchingCubeChunkSetting marchingCubeSetting, NoiseSetting noiseSetting) { //Cube neigborCube; //check there is exsiting noise value at neighbor //Skip this process because we use perlin noise //if(cubeDictionary.TryGetValue(new Vector3(vertexPosition.x - someOffset?, vertexPosition.y, vertexPosition.z), out neigborCube) { // ... //} else if ... //For threading, we have to dupulicate Animation Curve AnimationCurve weightCurve = new AnimationCurve(marchingCubeSetting.weightCurve.keys); float height = cube.origin.y + cube.offset[index].y; float height01 = Mathf.Lerp(1, 0, (marchingCubeSetting.mapMaxHeight - height) / (marchingCubeSetting.mapMaxHeight - marchingCubeSetting.mapMinHeight)); float weight = MarchingCubeNoise.GenerateTerrainNoise(cube.origin + cube.offset[index], noiseSetting) * weightCurve.Evaluate(height01); if (height < marchingCubeSetting.mapMinHeight + cube.offsetDistance) { weight = 1; } else if (height > marchingCubeSetting.mapMaxHeight - cube.offsetDistance) { weight = 0; } cube.vertexSelected[index] = weight < marchingCubeSetting.ignoreVertexLevel; cube.vertexWeight[index] = weight; }
/// <summary> /// Uncompleted Bursted version /// </summary> public static void GenerateMeshBurst(NativeArray <SPHSystem.WaterParticle> waterParticles, int count, float3 minPosition, float3 maxPosition, int resolution, ref Mesh mesh) { Profiler.BeginSample("WaterMarchingCube"); int resolutionCube = resolution * resolution * resolution; var nativeMap = new NativeArray <float>(resolutionCube, Allocator.TempJob); var nativeUsedIndices = new NativeList <int3>(resolutionCube, Allocator.TempJob); float invResolution = 1f / resolution; FillMapJob fillMapJob = new FillMapJob() { map = nativeMap, usedIndices = nativeUsedIndices, resolution = resolution, invResolution = invResolution, maxPosition = maxPosition, minPosition = minPosition, waterParticles = waterParticles, }; fillMapJob.Run(); Profiler.EndSample(); MarchingCube.CreateMeshData(nativeMap, nativeUsedIndices, resolution, invResolution, ref mesh); nativeMap.Dispose(); nativeUsedIndices.Dispose(); }
public static MarchingCube getInstance() { if (instance == null) { instance = new MarchingCube(); } return(instance); }
void SetupOutline(ChunkConfig chunk, Vector2Int loc) { var terrainGen = chunk.terrainGen; using (ComputeBuffer outBuf = new ComputeBuffer(chunk.gridCount, sizeof(float))) { // Setup compute shader. int k = terrainGen.FindKernel("Main"); terrainGen.SetFloat("pi", PI); terrainGen.SetFloat("rdSeed", chunk.seed); terrainGen.SetFloats("resolution", chunk.resolution.x, chunk.resolution.y); terrainGen.SetFloat("caveShrinkY", chunk.caveShrinkY); terrainGen.SetFloat("caveEliminateY", chunk.caveEliminateY); terrainGen.SetFloats("roughness", chunk.roughness); terrainGen.SetFloats("localScale", chunk.localScale.x, chunk.localScale.y); terrainGen.SetFloats("freq", chunk.frequency.x, chunk.frequency.y); terrainGen.SetFloats("offset", chunk.OffsetBottomLeft(loc).x, chunk.OffsetBottomLeft(loc).y); terrainGen.SetFloats("amplitude", chunk.amplitude.x, chunk.amplitude.y); terrainGen.SetBuffer(k, "output", outBuf); // Draw chunk terrain. terrainGen.Dispatch(k, CeilToInt(chunk.resolution.x / 16.0f), CeilToInt(chunk.resolution.y / 16.0f), 1); // check the databuf and its size. if (dataBuf == null || dataBuf.Length != chunk.gridCount) { dataBuf = new float[chunk.gridCount]; } // get data from GPU back into main memory. outBuf.GetData(dataBuf); } // Check chunk points. // Mesh vertices should be in *local* space that relative to the bottom-left corner. if (segs == null) { segs = new List <Segment>(); } segs.Clear(); for (int x = 0; x < chunk.resolution.x; x++) { for (int y = 0; y < chunk.resolution.y; y++) { int val = RoundToInt(dataBuf[x + y * chunk.resolution.x]) ^ 0xF; MarchingCube.Get(val, new Vector2(x, y), segs); } } for (int i = 0; i < segs.Count; i++) { segs[i] = new Segment(segs[i].from * chunk.localScale, segs[i].to * chunk.localScale); } lks = segs.LinkUp().Smooth(Util.SmoothAverage).Smooth(Util.SmoothFill); }
public void Init(GameObject template, Vector3 position) { internalCubes = new MarchingCube[offsets.Length]; for (int i = 0; i < offsets.Length; i++) { var obj = Object.Instantiate(template, position + offsets[i] * cubeSize, new Quaternion()); var marchingCubeShader = obj.GetComponent <MarchingCubeShader>(); internalCubes[i] = new MarchingCube(matrixSize, marchingCubeShader); } }
public GridMarcher(OccupancyGrid occupancyGrid, ComputeShader computeShader) { this.occupancyGrid = occupancyGrid; this.marchingCube = new MarchingCube(); marchingCube.Init(); this.computeShader = computeShader; }
public static void GenerateMesh(NativeArray <SPHSystem.WaterParticle> waterParticles, int count, float3 minPosition, float3 maxPosition, int resolution, ref Mesh mesh) { Profiler.BeginSample("WaterMarchingCube"); int resolutionCube = resolution * resolution * resolution; if (usedGrid == null || usedGrid.Length != resolutionCube) { usedGrid = new bool[resolution, resolution, resolution]; map = new float[resolution, resolution, resolution]; } else { Array.Clear(usedGrid, 0, resolutionCube); Array.Clear(map, 0, resolutionCube); } float invResolution = 1f / resolution; float step = math.distance(maxPosition.x, minPosition.x) * invResolution; float invStep = 1f / step; NativeList <int3> usedIndices = new NativeList <int3>(resolution * resolution, Allocator.Temp); for (int i = 0; i < count; i++) { int3 index = GetPositionIndex(waterParticles[i].position, minPosition, maxPosition, resolution, invStep); //Only calculate marching cube for the 8 corners per cube for (int j = 0; j < MarchingCubeTables.CornerTable.Length; j++) { int3 conerIndex = index + MarchingCubeTables.CornerTable[j]; if (!usedGrid[conerIndex.x, conerIndex.y, conerIndex.z]) { usedGrid[conerIndex.x, conerIndex.y, conerIndex.z] = true; usedIndices.Add(conerIndex); } int3 conerIndex2 = index - MarchingCubeTables.CornerTable[j]; if (!usedGrid[conerIndex2.x, conerIndex2.y, conerIndex2.z]) { usedGrid[conerIndex2.x, conerIndex2.y, conerIndex2.z] = true; usedIndices.Add(conerIndex2); } } map[index.x, index.y, index.z] = 1; } Profiler.EndSample(); MarchingCube.CreateMeshData(map, usedIndices, invResolution, ref mesh); usedIndices.Dispose(); }
/// <summary> /// Get the vertices of the triangles to be drawn. /// Each triangle is drawn between 3 points, each of which are on an edge in the marching cube. /// </summary> /// <param name="cube">The marching cube for which we are calculating triangles.</param> /// <param name="edgeNumbers">The numbers of the edges to be connected. Every 3 edges is /// one triangle.</param> /// <returns>The coordinates of every triangle vertex. Every 3 is one triangle.</returns> private Vector3[] GetTriangleVertices(MarchingCube cube, int[] edgeNumbers) { List <Vector3> triangleVertices = new List <Vector3>(); // Loop through each triangle for (int i = 0; i < edgeNumbers.Length; i++) { if (edgeNumbers[i] != -1) { triangleVertices.Add(cube.GetEdgeMidpoint(edgeNumbers[i])); } } return(triangleVertices.ToArray()); }
public void InitializeVoxelCollection() { if (bIsVoxelCollectionInitialized) { for (int ColX = 0; ColX < XZMarchingCubeNums; ++ColX) { for (int ColY = 0; ColY < YMarchingCubeNums; ++ColY) { for (int ColZ = 0; ColZ < XZMarchingCubeNums; ++ColZ) { InjectionData(ref GetMarchingCube(ColX, ColY, ColZ), ColX, ColY, ColZ); GetMarchingCube(ColX, ColY, ColZ).InitializeVoxelData(); } } } return; } mVoxelData = new VoxelPoint[(XZMultiplier * XZMarchingCubeNums + 1) * (YMultiplier * YMarchingCubeNums + 1) * (XZMultiplier * XZMarchingCubeNums + 1)]; mMarchingCubeCollection = new MarchingCube[XZMarchingCubeNums * YMarchingCubeNums * XZMarchingCubeNums]; for (int ColX = 0; ColX < XZMarchingCubeNums; ++ColX) { for (int ColY = 0; ColY < YMarchingCubeNums; ++ColY) { for (int ColZ = 0; ColZ < XZMarchingCubeNums; ++ColZ) { GameObject TempObject = Instantiate(MarchingCubePrefab, transform.position + new Vector3( (ColX - XZMarchingCubeNums / 2) * VoxelResolution * XZMultiplier, (ColY - YMarchingCubeNums / 2) * VoxelResolution * YMultiplier, (ColZ - XZMarchingCubeNums / 2) * VoxelResolution * XZMultiplier), Quaternion.identity); TempObject.transform.parent = transform; MarchingCube TempComp = TempObject.GetComponent <MarchingCube>(); InjectionData(ref TempComp, ColX, ColY, ColZ); TempComp.InitializeVoxelData(); GetMarchingCube(ColX, ColY, ColZ) = TempComp; } } } bIsVoxelCollectionInitialized = true; }
/// <summary> /// Generate a 3D mesh for the densities using a marching cubes algorithm. /// </summary> /// <returns>A Mesh object</returns> public Mesh Generate() { List <Vector3> vertices = new List <Vector3>(); // Loop through the volumetric data. for (int xIndex = 0; xIndex < densities.GetLength(0) - 1; xIndex++) { for (int yIndex = 0; yIndex < densities.GetLength(1) - 1; yIndex++) { for (int zIndex = 0; zIndex < densities.GetLength(2) - 1; zIndex++) { // Create a marching cube for this position. Vector3Int cubeIndex = new Vector3Int(xIndex, yIndex, zIndex); MarchingCube cube = new MarchingCube(settings, cubeIndex, points, densities); // Determine which triangles to draw for this cube. int cubeCase = ConcatenateIntoByte(GetActiveDensityBitArray(cube.densities)); int[] connectedEdges = Tables.triangles[cubeCase]; Vector3[] cubeTriangleVertices = GetTriangleVertices(cube, connectedEdges); // Add the triangle vertices for this cube to the list of all triangle vertices for (int i = 0; i < cubeTriangleVertices.Length; i++) { vertices.Add(cubeTriangleVertices[i]); } } } } // Add all of the triangle indeces, which should simply be [0, numVertices] because we are // not reusing any vertices between triangles. List <int> triangles = new List <int>(); for (int i = 0; i < vertices.Count; i++) { triangles.Add(vertices.Count - 1 - i); } // Create the mesh itself and assign all the data. Mesh cellMesh = new Mesh(); cellMesh.vertices = vertices.ToArray(); cellMesh.triangles = triangles.ToArray(); cellMesh.RecalculateNormals(); return(cellMesh); }
void DrawMarchingCube(MarchingCube cube) { Gizmos.color = Color.white; for (int i = 0; i < 8; i++) { if (cube.vertexSelected[i]) { Gizmos.color = Color.black; Gizmos.DrawSphere(cube.origin + cube.offset[i], 0.05f); } else { Gizmos.color = Color.white; Gizmos.DrawSphere(cube.origin + cube.offset[i], 0.05f); } } }
private IEnumerator DestroyVoxel() { while (bIsTriggerPressed) { Ray RayDescriptor = new Ray(); RayDescriptor.origin = AimPoint.position; RayDescriptor.direction = AimPoint.forward; Debug.DrawRay(RayDescriptor.origin, RayDescriptor.direction * VoxelCastLength, Color.green, 10.0f); RaycastHit HitInfo; if (Physics.Raycast(RayDescriptor, out HitInfo, VoxelCastLength, -1, QueryTriggerInteraction.Ignore) == true) { BeamComp.TargetPosition = HitInfo.point; Collider[] HitColliders = Physics.OverlapSphere(HitInfo.point, VoxelEffectRadius); if (HitColliders != null) { MarchingCube HitCube = HitInfo.collider.gameObject.GetComponent <MarchingCube>(); if (HitCube == null) { yield return(new WaitForSeconds(VoxelEditDelay)); } HitCube.RemoveVoxel(HitInfo.point, VoxelEffectRadius, VoxelEditPower * VoxelEditDelay, Space.World); for (int i = 0; i < HitColliders.Length; ++i) { MarchingCube CurCube = HitColliders[i].gameObject.GetComponent <MarchingCube>(); if (CurCube == null) { continue; } CurCube.UpdateMarchingCube(); } } } else { BeamComp.TargetPosition = RayDescriptor.direction * VoxelCastLength + BeamComp.transform.position; } yield return(new WaitForSeconds(VoxelEditDelay)); } }
public static List <MarchingCube> InitVertices(Vector3 center, MarchingCubeChunkSetting marchingCubeChunksettings, NoiseSetting noiseSetting) { List <MarchingCube> cubeList = new List <MarchingCube>(); for (int x = 0; x < marchingCubeChunksettings.numberOfVerticesPerLine; x++) { for (int y = 0; y < marchingCubeChunksettings.numberOfVerticesPerLine; y++) { for (int z = 0; z < marchingCubeChunksettings.numberOfVerticesPerLine; z++) { MarchingCube cube = new MarchingCube(new Vector3(x, y, z) * marchingCubeChunksettings.distanceBetweenVertex + center, marchingCubeChunksettings.distanceBetweenVertex); cubeList.Add(cube); for (int i = 0; i < 8; i++) { CalculateVertexWeight(cube, i, marchingCubeChunksettings, noiseSetting); } } } } return(cubeList); }
public void process(Chunk chunk) { this.chunk = chunk; MarchingCube marchingCube = MarchingCube.getInstance(); float[,,] density = chunk.getDensity(); for (int x = 0; x < voxelCount; x++) { for (int y = 0; y < voxelCount; y++) { for (int z = 0; z < voxelCount; z++) { Profiler.BeginSample("Marching:March"); marchingCube.march(x, y, z, density, this); Profiler.EndSample(); } } } Profiler.BeginSample("Proccessor:GenerateMesh"); generateMesh(); Profiler.EndSample(); reset(); }
private void OnDrawGizmos() { MarchingCube cube = new MarchingCube(Vector3.zero, 1); for (int i = 0; i < 8; i++) { cube.vertexSelected[i] = selectedCubeIndex[i]; } Vector3[] vertices = cube.GetMarchingCubeVertices(); int[] triangle = new int[vertices.Length]; for (int i = 0; i < triangle.Length; i++) { triangle[i] = i; } mesh.sharedMesh = new Mesh(); mesh.sharedMesh.vertices = vertices; mesh.sharedMesh.triangles = triangle; mesh.sharedMesh.RecalculateNormals(); DrawMarchingCube(cube); }
private void OnSceneGUI() { UnityEngine.Mesh mesh = null; int cellNum = 10; MarchingCube mc = target as MarchingCube; Dictionary <int, List <Vector3> > ss = new Dictionary <int, List <Vector3> >(); if (mc.gameObject != null) { mesh = mc.gameObject.GetComponent <MeshFilter>().sharedMesh; Vector3[] verts = mesh.vertices; for (int i = 0; i < verts.Length; i++) { Vector3 worldPos = mc.gameObject.transform.TransformPoint(verts[i]); Vector3 pos = worldPos; //check bound if (pos.x < 0 || pos.y < 0 || pos.z < 0) { continue; } int hash = mc.MakeHash(pos); if (ss.ContainsKey(hash)) { ss[hash].Add(pos); } else { List <Vector3> ptlist = new List <Vector3>(); ptlist.Add(pos); ss.Add(hash, ptlist); } } } gizmoLines = new Vector3[cellNum * cellNum * cellNum]; int cnt = 0; BitMap3d bm3d = new BitMap3d(cellNum, cellNum, cellNum); for (int i = 0; i < cellNum; i++) { for (int j = 0; j < cellNum; j++) { for (int k = 0; k < cellNum; k++) { Vector3 start = new Vector3(k, j, i); int hash = mc.MakeHash(start); float dens = 0; if (ss.ContainsKey(hash)) { //verts inside cellgrid, calculate density List <Vector3> objverts = ss[hash]; //obj verts in cell //for (int ii = 0; ii < 8; ii++) { float dd = 0; foreach (var vert in objverts) { dd += Vector3.Magnitude(vert - start); } dd = dd / objverts.Count; if (dd > 0 && dd < densityThreshold) { Handles.color = new Color(dd, 0.5f, 0.0f); //Handles.DrawLine(vert, cubePts[ii]); Handles.SphereHandleCap(0, start, Quaternion.identity, 0.2f, EventType.Repaint); Handles.Label(start, start.ToString()); } } } else { dens = 0; } gizmoLines[cnt] = start; Handles.color = new Color(0.3f, 0.5f, 0.5f); Vector3 gizmoCubeCenter = start + Vector3.one * 0.5f; if (gizmoCube) { Handles.DrawWireCube(gizmoCubeCenter, Vector3.one); } cnt++; } } } }
public static MarchingCube getInstance() { if(instance==null){ instance = new MarchingCube(); } return instance; }
void Generate() { DateTime startTime = System.DateTime.Now; INoise perlin = new PerlinNoise(seed, 2f); FractalNoise fractal = new FractalNoise(perlin, 3, 1f); MarchingCube marching = new MarchingCube(); Marching.Surface = 0f; width = sizeScale; height = sizeScale; length = sizeScale; float[] voxels = new float[width * height * length]; //Fill voxels with values. Im using perlin noise but any method to create voxels will work. for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { for (int z = 0; z < length; z++) { float fx = x / (width - 1.0f); float fy = y / (height - 1.0f); float fz = z / (length - 1.0f); int idx = x + y * width + z * width * height; voxels[idx] = fractal.Sample3D(fx, fy, fz); } } } verts = new List <Vector3>(); indices = new List <int>(); if (useJobSystem) { MarchingCubeParallel marching_p = new MarchingCubeParallel(0); MarchingCubeParallel.MarchJob job; JobHandle handle = marching_p.Generate(new List <float>(voxels), width, height, length, out job); StartCoroutine(Wait4Complete(handle, job)); } else { marching.Generate(voxels, width, height, length, verts, indices); int maxVertsPerMesh = 30000; //must be divisible by 3, ie 3 verts == 1 triangle int numMeshes = verts.Count / maxVertsPerMesh + 1; for (int i = 0; i < numMeshes; i++) { List <Vector3> splitVerts = new List <Vector3>(); List <int> splitIndices = new List <int>(); for (int j = 0; j < maxVertsPerMesh; j++) { int idx = i * maxVertsPerMesh + j; if (idx < verts.Count) { splitVerts.Add(verts[idx]); splitIndices.Add(j); } } if (splitVerts.Count == 0) { continue; } Mesh mesh = new Mesh(); mesh.SetVertices(splitVerts); mesh.SetTriangles(splitIndices, 0); mesh.RecalculateBounds(); mesh.RecalculateNormals(); GameObject go = new GameObject("Mesh"); go.transform.parent = transform; go.AddComponent <MeshFilter>(); go.AddComponent <MeshRenderer>(); go.GetComponent <Renderer>().material = m_material; go.GetComponent <MeshFilter>().mesh = mesh; go.transform.localPosition = new Vector3(-width / 2, -height / 2, -length / 2); meshes.Add(go); } } double timeCost = System.DateTime.Now.Subtract(startTime).TotalMilliseconds; print("Time Cost : " + timeCost + " at size " + (8 * sizeScale)); }