public void ChunkMemoryCopy(SimTerrain.TerrainChunk chunk) { Array.Copy(chunk.verticesAry, memoryFlag.verticeOldStart, verticesAry, memoryFlag.verticeNewStart, memoryFlag.verticeCount); Array.Copy(chunk.ColorsAry, memoryFlag.verticeOldStart, ColorsAry, memoryFlag.verticeNewStart, memoryFlag.verticeCount); Array.Copy(chunk.uvAry, memoryFlag.verticeOldStart, uvAry, memoryFlag.verticeNewStart, memoryFlag.verticeCount); Array.Copy(chunk.indicesAry, memoryFlag.indiceOldStart, indicesBuffer, memoryFlag.indiceNewStart, memoryFlag.indiceCount); }
private void BrushDown(Vector3 point, TerrainBrush brush, TerrainChunk chunk) { float radius = brush.Radius; float num = brush.Strenght; float blurRange = brush.BlurRadius; float num3 = 1.0f - Mathf.Pow(brush.BlurPower, 4.0f); num3 = 1.0f - Mathf.Pow(1.0f - num3, 1.1f); float target = brush.Targetheight; target -= 1.0f; //Height Vector2 localPoint = new Vector2(point.x - transform.position.x, point.z - transform.position.z); localPoint.x = Mathf.RoundToInt((localPoint.x / chunk.groupInfo.worldSize.x) * (chunk.groupInfo.terrainWidth - 1)); localPoint.y = Mathf.RoundToInt((localPoint.y / chunk.groupInfo.worldSize.y) * (chunk.groupInfo.terrainLength - 1)); float Minx = Mathf.Max(0, localPoint.x - (radius + blurRange)); float Maxx = Mathf.Min(chunk.groupInfo.terrainWidth - 1, localPoint.x + (radius + blurRange)); float MinY = Mathf.Max(0, localPoint.y - (radius + blurRange)); float Maxy = Mathf.Min(chunk.groupInfo.terrainLength - 1, localPoint.y + (radius + blurRange)); Vector2 CenterPoint = new Vector2(Minx, MinY); float localsqrDis = (radius + blurRange) * (radius + blurRange); for (int y = (int)MinY; y <= Maxy; ++y) { for (int x = (int)Minx; x <= Maxx; ++x) { int heightflag = chunk.groupInfo.GetHeightIndex(x, y); int heightMinFlag = chunk.groupInfo.GetMinHeightIndex(x, y); int targetFlag = Mathf.FloorToInt(brush.Targetheight - 0.001f); if (heightMinFlag < targetFlag) { if (heightflag > targetFlag) { chunk.groupInfo.SetCullFace(x, y, targetFlag); } continue; } float curValue = chunk.groupInfo.GetRealHeight(x, y); CenterPoint.x = x; CenterPoint.y = y; float sqr = Vector2.SqrMagnitude(localPoint - CenterPoint); if (sqr < localsqrDis) { float distancePower = GetDistancePower(Mathf.Sqrt(sqr), true, brush); float newvalue = Mathf.Lerp(curValue, target, num * distancePower); newvalue = Mathf.Min(curValue, newvalue); newvalue = Mathf.Max(target + 0.001f, newvalue); chunk.groupInfo.SetValue(x, y, newvalue); chunk.groupInfo.SetSurfaceValue(x, y, newvalue); chunk.groupInfo.SetCullFace(x, y, newvalue); } } } }
public bool CastGroup(Ray ray, TerrainBrush brush, List <TerrainChunk> colliedChunks, out Vector3 HitPoint) { RaycastHit info = default(RaycastHit); bool Collided = false; HitPoint = Vector3.zero; List <TerrainChunk> CopyChunks = Chunks; int nChildCount = CopyChunks.Count; int nCopyChunkCount = CopyChunks.Count; for (int idx = 0; idx < nCopyChunkCount; ++idx) { TerrainChunk Curchunk = CopyChunks[idx]; if (Curchunk.GetMeshCollider().Raycast(ray, out info, 1000)) { if (flag != null) { flag.transform.position = info.point; } Brush(info.point, Curchunk, brush); // Brush(info.point + new Vector3(0.0f,0.0f,0.2f), Curchunk, brush); // Brush(info.point + new Vector3(0.0f, 0.0f, -0.2f), Curchunk, brush); // Brush(info.point + new Vector3(-0.2f, 0.0f, 0.0f), Curchunk, brush); // Brush(info.point + new Vector3(0.2f, 0.0f, 0.0f), Curchunk, brush); //return info.point; HitPoint = info.point; Collided = true; break; } } float brushLenght = (brush.Radius + brush.BlurRadius) + 2.0f; Circle brushCircle = new Circle(new Vector2(info.point.x, info.point.z), brushLenght); colliedChunks.Clear(); if (Collided) { for (int idx = 0; idx < nCopyChunkCount; ++idx) { if (Circle.ColliderRect(brushCircle, CopyChunks[idx]._boxRect)) { colliedChunks.Add(CopyChunks[idx]); } } } int nColliderChunks = colliedChunks.Count; for (int idx = 0; idx < nColliderChunks; ++idx) { colliedChunks[idx].BuildChunk(); } return(Collided); }
private void BrushRaise(Vector3 point, TerrainBrush brush, TerrainChunk chunk) { Vector3 localPoint = point - transform.position; int BrushSize = (int)brush.Radius; float BrushOcaptiy = brush.Targetheight; float powValue = brush.Strenght; int idx = Mathf.RoundToInt((localPoint.x / chunk.groupInfo.worldSize.x) * chunk.groupInfo.terrainWidth); int idy = Mathf.RoundToInt((localPoint.z / chunk.groupInfo.worldSize.y) * chunk.groupInfo.terrainLength); int minX = Mathf.Max(0, idx - BrushSize); int maxX = Mathf.Min(chunk.groupInfo.terrainWidth, idx + BrushSize); int minY = Mathf.Max(0, idy - BrushSize); int maxY = Mathf.Min(chunk.groupInfo.terrainLength, idy + BrushSize); Vector2 center = new Vector2(idx, idy); Vector2 testPoint = new Vector2(maxX, maxY); float maxDistance = Vector2.Distance(center, testPoint); for (int y = minY; y <= maxY; ++y) { for (int x = minX; x <= maxX; ++x) { float curValue = chunk.groupInfo.GetRealHeight(x, y); testPoint.x = x; testPoint.y = y; float distance = Vector2.Distance(center, testPoint); float Distancevalue = (distance / maxDistance); float num1 = Mathf.Pow(Distancevalue, powValue); float num2 = (1.0F - num1); if (num2 > 1.0f) { num2 = 1.0f; } if (num2 < 0.0f) { num2 = 0.0f; } float newvalue = BrushOcaptiy * num2; newvalue = Mathf.Max(newvalue, curValue); chunk.groupInfo.SetValue(x, y, newvalue); chunk.groupInfo.SetSurfaceValue(x, y, newvalue); if (chunk.groupInfo.GetValue(x, y) != chunk.groupInfo.GetSurfaceValue(x, y)) { Debug.LogError("Set Value Error"); chunk.groupInfo.SetValue(x, y, newvalue); chunk.groupInfo.SetSurfaceValue(x, y, newvalue); } } } }
TerrainBox GetBox(int x, int y) { int ChunkX = Mathf.FloorToInt(x / 32.0f); int ChunkY = Mathf.FloorToInt(y / 32.0f); TerrainChunk chunk = Chunks[ChunkY * ChunkColumn + ChunkX]; int BoxX = x % 32; int BoxY = y % 32; TerrainBox[] boxs = chunk.boxs; return(boxs[BoxY * 32 + BoxX]); }
public bool Init(LayerTerrainColor color, LayerTerrainGroups.Chunk data, TerrainFile file, Material mat) { chunkData = data; filedata = file; ChunkColumn = (file.terrainWidth / data.ChunkWidth); //2 *2 or 3*3 4*4 ChunkRow = (file.terrainLength / data.ChunkLenght); ChunkCount = ChunkColumn * ChunkRow; //create Chunk Chunks.Capacity = ChunkCount; float WorldChunkSize = file.worldSize.x / ChunkColumn; for (int idy = 0; idy < ChunkRow; ++idy) { for (int idx = 0; idx < ChunkColumn; ++idx) { GameObject Chunk = new GameObject(this.gameObject.name + "Chunk[" + idy.ToString() + ":" + idx.ToString() + "]"); Chunk.transform.parent = transform; Chunk.tag = "Terrain"; Chunk.layer = 8; MeshFilter meshfilter = Chunk.AddComponent <MeshFilter>(); meshfilter.hideFlags = HideFlags.HideAndDontSave; MeshRenderer render = Chunk.AddComponent <MeshRenderer>(); render.hideFlags = HideFlags.DontSave; TerrainChunk terrainChunkItem = Chunk.AddComponent <TerrainChunk>(); terrainChunkItem.hideFlags = HideFlags.HideAndDontSave; Vector2Int index = new Vector2Int(); index.x = idx; index.y = idy; Vector3 offset = new Vector3(); offset.x = WorldChunkSize * idx; offset.z = WorldChunkSize * idy; offset.y = 0.0f; terrainChunkItem.Init(new Vector2Int(idx, idy), offset, new Vector2(WorldChunkSize, WorldChunkSize), file, color, data, mat); Chunks.Add(terrainChunkItem); } } return(true); }
public bool TouchInGround(Ray ray, out int layerIndex) { RaycastHit info; for (int idx = 0; idx < transform.childCount; ++idx) { TerrainChunk Curchunk = transform.GetChild(idx).GetComponent <TerrainChunk>(); if (Curchunk == null) { continue; } if (Curchunk.GetComponent <MeshCollider>().Raycast(ray, out info, 5000.0f)) { layerIndex = Mathf.RoundToInt(info.point.y / chunkData.LayerHeight) + 1; return(true); } } layerIndex = 0; return(false); }
public void Brush(Vector3 point, TerrainChunk chunk, TerrainBrush brush) { switch (brush.brushType) { case TerrainBrush.BrushType.BT_ADD: { BrushRaiseEx(point, brush, chunk); } break; case TerrainBrush.BrushType.BT_DOWN: { BrushDown(point, brush, chunk); } break; case TerrainBrush.BrushType.LOCK: { BrushRaiseEx(point, brush, chunk); } break; } }
public void BuildMesh(SimTerrain.TerrainChunk chunk /*, List<SimTerrain.TerrainTriangle> triangles*/) { Mesh mesh = chunk.GetMeshFilter().sharedMesh; mesh.Clear(); if (vertticeIndex > chunk.verticesAry.Length) { int newValue = Math.Min(65000, vertticeIndex + 10000); chunk.verticesAry = new Vector3[newValue]; chunk.uvAry = new Vector2[newValue]; chunk.ColorsAry = new Color32[newValue]; } if (IndicesIndex > chunk.indicesAry.Length) { chunk.indicesAry = new int[IndicesIndex + 2000 * 3]; } Array.Clear(chunk.indicesAry, 0, chunk.indicesAry.Length); Array.Copy(indicesBuffer, chunk.indicesAry, IndicesIndex); int copyCount = Math.Min(65000, vertticeIndex); Array.Copy(verticesAry, chunk.verticesAry, copyCount); Array.Copy(ColorsAry, chunk.ColorsAry, copyCount); Array.Copy(uvAry, chunk.uvAry, copyCount); mesh.vertices = chunk.verticesAry; mesh.uv = chunk.uvAry; mesh.colors32 = chunk.ColorsAry; mesh.SetIndices(chunk.indicesAry, MeshTopology.Triangles, 0); mesh.RecalculateNormals(); }
/// <summary> /// 根据高度图,重建三角面 /// </summary> public bool RebuildTriangle(TerrainChunk chunk, TerrainMeshPool pool, ref TerrainMeshPool.MemoryFlag flag, int index) { if (groupInfo != null) { int value0 = groupInfo.CopyData[chunkIndex.v0Index]; int value1 = groupInfo.CopyData[chunkIndex.v1Index]; int value2 = groupInfo.CopyData[chunkIndex.v2Index]; int valueSurface0 = groupInfo.CopySurfaceData[chunkIndex.v0Index]; int valueSurface1 = groupInfo.CopySurfaceData[chunkIndex.v1Index]; int valueSurface2 = groupInfo.CopySurfaceData[chunkIndex.v2Index]; bool hasShowSurface = false; if (value0 != valueSurface0) { hasShowSurface = true; } if (value1 != valueSurface1) { hasShowSurface = true; } if (value2 != valueSurface2) { hasShowSurface = true; } if (value0 == v0value && value1 == v1value && value2 == v2value && hasShowSurface == false) { if (pool.vertticeIndex != verticesStart) { int det = pool.vertticeIndex - verticesStart; int indexCount = indicesCount; for (int idx = 0; idx < indexCount; ++idx) { chunk.indicesAry[IndicesStart + idx] = chunk.indicesAry[IndicesStart + idx] + det; } } if (flag.flagOldPoint == false) { flag.verticeOldStart = verticesStart; flag.indiceOldStart = IndicesStart; flag.flagOldPoint = true; } flag.verticeCount += verticesCount; flag.indiceCount += indicesCount; verticesStart = pool.vertticeIndex; IndicesStart = pool.IndicesIndex; pool.IndicesIndex += indicesCount; pool.vertticeIndex += verticesCount; return(false); } else { v0value = value0; v1value = value1; v2value = value2; } float maxValue = (float)ushort.MaxValue; _v0.y = (value0 / maxValue) * groupInfo.worldSize.z; _v1.y = (value1 / maxValue) * groupInfo.worldSize.z; _v2.y = (value2 / maxValue) * groupInfo.worldSize.z; groupInfo.CalculateHeightFlag(chunkIndex.v0Index); groupInfo.CalculateHeightFlag(chunkIndex.v1Index); groupInfo.CalculateHeightFlag(chunkIndex.v2Index); /*if (hasShowSurface) * { * colorConfig.testSurface = true; * }*/ buildTriangle(pool, _v0, _v1, _v2); // buildTriangle(pool, _v0, _v1, _v2); if (hasShowSurface) { int minSurfaceValue = Mathf.Min(valueSurface0, valueSurface1, valueSurface2); _v0.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v1.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v2.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; buildTriangle(pool, _v0, _v1, _v2); } //colorConfig.testSurface = false; return(true); } return(false); }
public bool RebuildTriangleEx(TerrainChunk chunk, TerrainMeshPool pool, ref TerrainMeshPool.MemoryFlag flag) { Vector3[] verticesAry = pool.verticesAry; Vector2[] uv0Ary = pool.uvAry; Color32[] colorsAry = pool.ColorsAry; int[] indicesAry = pool.indicesBuffer; float value0 = groupInfo.GetValue(chunkIndex.v0Index); float value1 = groupInfo.GetValue(chunkIndex.v1Index); float value2 = groupInfo.GetValue(chunkIndex.v2Index); float maxValue = (float)ushort.MaxValue; _v0.y = (value0 / maxValue) * groupInfo.worldSize.z; _v1.y = (value1 / maxValue) * groupInfo.worldSize.z; _v2.y = (value2 / maxValue) * groupInfo.worldSize.z; verticesStart = pool.vertticeIndex; verticesCount = 0; IndicesStart = pool.IndicesIndex; indicesCount = 0; verticesAry[verticesStart] = (_v0); verticesAry[verticesStart + 1] = (_v1); verticesAry[verticesStart + 2] = (_v2); colorsAry[verticesStart + 0] = colorConfig.bottomColor; colorsAry[verticesStart + 1] = colorConfig.bottomColor; colorsAry[verticesStart + 2] = colorConfig.bottomColor; uv0Ary[verticesStart + 0] = (new Vector2(_v0.x / chunkConfig.uvReslution.x, _v0.z / chunkConfig.uvReslution.y)); uv0Ary[verticesStart + 1] = (new Vector2(_v1.x / chunkConfig.uvReslution.x, _v1.z / chunkConfig.uvReslution.y)); uv0Ary[verticesStart + 2] = (new Vector2(_v2.x / chunkConfig.uvReslution.x, _v2.z / chunkConfig.uvReslution.y)); indicesAry[IndicesStart + 0] = verticesStart; indicesAry[IndicesStart + 1] = verticesStart + 1; indicesAry[IndicesStart + 2] = verticesStart + 2; verticesCount = 3; indicesCount = 3; pool.vertticeIndex += 3; pool.IndicesIndex += 3; return(true); /* * clear(); * //TODO: * if (groupInfo != null) * { * * float value0 = groupInfo.GetValue(chunkIndex.v0Index); * float value1 = groupInfo.GetValue(chunkIndex.v1Index); * float value2 = groupInfo.GetValue(chunkIndex.v2Index); * float maxValue = (float)ushort.MaxValue; * _v0.y = (value0 / maxValue) * groupInfo.worldSize.z; * _v1.y = (value1 / maxValue) * groupInfo.worldSize.z; * _v2.y = (value2 / maxValue) * groupInfo.worldSize.z; * * verticesAry[0] = (_v0); * verticesAry[1] = (_v1); * verticesAry[2] = (_v2); * * colorsAry[0] = colorConfig.bottomColor; * colorsAry[1] = colorConfig.bottomColor; * colorsAry[2] = colorConfig.bottomColor; * * uv0Ary[0] = (new Vector2(_v0.x / chunkConfig.uvReslution.x, _v0.z / chunkConfig.uvReslution.y)); * uv0Ary[1] = (new Vector2(_v1.x / chunkConfig.uvReslution.x, _v1.z / chunkConfig.uvReslution.y)); * uv0Ary[2] = (new Vector2(_v2.x / chunkConfig.uvReslution.x, _v2.z / chunkConfig.uvReslution.y)); * * * indexBuffer.Add(IndexBufferIndex + 0); * indexBuffer.Add(IndexBufferIndex + 1); * indexBuffer.Add(IndexBufferIndex + 2); * * * * verticesCount = 3; * * * * return IndexBufferIndex + 3; * } * * return IndexBufferIndex; */ }
public bool RebuildTriangle(TerrainChunk chunk, TerrainMeshPool pool, ref TerrainMeshPool.MemoryFlag flag, int boxindex) { int value0 = groupInfo.CopyData[v0Index]; int value1 = groupInfo.CopyData[v1Index]; int value2 = groupInfo.CopyData[v2Index]; int value3 = groupInfo.CopyData[v3Index]; int valueSurface0 = groupInfo.CopySurfaceData[v0Index]; int valueSurface1 = groupInfo.CopySurfaceData[v1Index]; int valueSurface2 = groupInfo.CopySurfaceData[v2Index]; int valueSurface3 = groupInfo.CopySurfaceData[v3Index]; int valueCull0 = groupInfo.copyCullfaceData[v0Index]; int valueCull1 = groupInfo.copyCullfaceData[v1Index]; int valueCull2 = groupInfo.copyCullfaceData[v2Index]; int valueCull3 = groupInfo.copyCullfaceData[v3Index]; bool hasShowSurface = false; if (value0 != valueSurface0) { hasShowSurface = true; } if (value1 != valueSurface1) { hasShowSurface = true; } if (value2 != valueSurface2) { hasShowSurface = true; } if (value3 != valueSurface3) { hasShowSurface = true; } bool hasCullFace = false; if (value0 != valueCull0) { hasCullFace = true; } if (value1 != valueCull1) { hasCullFace = true; } if (value2 != valueCull2) { hasCullFace = true; } if (value3 != valueCull3) { hasCullFace = true; } if (value0 == v0value && value1 == v1value && value2 == v2value && value3 == v3value && hasShowSurface == false && hasCullFace == false) { if (pool.vertticeIndex != verticesStart) { int det = pool.vertticeIndex - verticesStart; int indexCount = indicesCount; for (int idx = 0; idx < indexCount; ++idx) { chunk.indicesAry[IndicesStart + idx] = chunk.indicesAry[IndicesStart + idx] + det; } } if (flag.flagOldPoint == false) { flag.verticeOldStart = verticesStart; flag.indiceOldStart = IndicesStart; flag.flagOldPoint = true; } flag.verticeCount += verticesCount; flag.indiceCount += indicesCount; verticesStart = pool.vertticeIndex; IndicesStart = pool.IndicesIndex; pool.IndicesIndex += indicesCount; pool.vertticeIndex += verticesCount; return(false); } else { v0value = value0; v1value = value1; v2value = value2; v3value = value3; } float maxValue = (float)ushort.MaxValue; _v0.y = (value0 / maxValue) * groupInfo.worldSize.z; _v1.y = (value1 / maxValue) * groupInfo.worldSize.z; _v2.y = (value2 / maxValue) * groupInfo.worldSize.z; _v3.y = (value3 / maxValue) * groupInfo.worldSize.z; if (hasCullFace) { valueCull0 = (int)((valueCull0 / maxValue) * groupInfo.worldSize.z); valueCull1 = (int)((valueCull1 / maxValue) * groupInfo.worldSize.z); valueCull2 = (int)((valueCull2 / maxValue) * groupInfo.worldSize.z); valueCull3 = (int)((valueCull3 / maxValue) * groupInfo.worldSize.z); } verticesStart = pool.vertticeIndex; verticesCount = 0; IndicesStart = pool.IndicesIndex; indicesCount = 0; //Debug.Log (chunk.name + v0Index + ":" + v1Index + ":" + v2Index + ":" + v3Index); /*switch (TestCode) * { * case 1: * { * colorConfig.testSurface = true; * colorConfig.Red.r = 255; * colorConfig.Red.b = 0; * colorConfig.Red.g = 0; * }break; * case 2: * { * colorConfig.testSurface = true; * colorConfig.Red.r = 0; * colorConfig.Red.b = 0; * colorConfig.Red.g = 255; * } * break; * * } * */ groupInfo.CalculateHeightFlag(v0Index); groupInfo.CalculateHeightFlag(v1Index); groupInfo.CalculateHeightFlag(v2Index); groupInfo.CalculateHeightFlag(v3Index); //colorConfig.testSurface = hasCullFace; if (Mathf.Max(_v0.y, _v2.y) > Mathf.Max(_v1.y, _v3.y)) { int CullFaca = -1; if (hasCullFace) { CullFaca = Mathf.Max(valueCull0, valueCull1, valueCull3); } buildTriangleLeft(pool, _v0, _v1, _v3, CullFaca); if (hasCullFace) { CullFaca = Mathf.Max(valueCull2, valueCull1, valueCull3); } buildTriangleLeft(pool, _v3, _v1, _v2, CullFaca); if (hasShowSurface) { int minSurfaceValue = Mathf.Min(valueSurface0, valueSurface1, valueSurface3); _v0.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v1.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v3.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; buildTriangleLeft(pool, _v0, _v1, _v3); minSurfaceValue = Mathf.Min(valueSurface2, valueSurface1, valueSurface3); _v2.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v1.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v3.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; buildTriangleLeft(pool, _v3, _v1, _v2); } } else { int CullFaca = -1; if (hasCullFace) { CullFaca = Mathf.Max(valueCull0, valueCull1, valueCull2); } buildTriangleLeft(pool, _v0, _v1, _v2, CullFaca); if (hasCullFace) { CullFaca = Mathf.Max(valueCull0, valueCull2, valueCull3); } buildTriangleLeft(pool, _v0, _v2, _v3, CullFaca); if (hasShowSurface) { int minSurfaceValue = Mathf.Min(valueSurface0, valueSurface1, valueSurface2); _v0.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v1.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v2.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; buildTriangleLeft(pool, _v0, _v1, _v2); minSurfaceValue = Mathf.Min(valueSurface0, valueSurface2, valueSurface3); _v0.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v2.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; _v3.y = (minSurfaceValue / maxValue) * groupInfo.worldSize.z; buildTriangleLeft(pool, _v0, _v1, _v2); buildTriangleLeft(pool, _v0, _v2, _v3); } } // colorConfig.testSurface = false; pool.vertticeIndex += verticesCount; pool.IndicesIndex += indicesCount; return(true); }
private void BrushRaiseEx(Vector3 point, TerrainBrush brush, TerrainChunk chunk) { #region v1.0 /* * * Vector3 localPoint = point - transform.position; * Vector2 localIdx = new Vector2(localPoint.x, localPoint.z); * * localIdx.x = Mathf.RoundToInt((localIdx.x / chunk.groupInfo.worldSize.x) * * chunk.groupInfo.terrainWidth); * localIdx.y = Mathf.RoundToInt((localIdx.y / chunk.groupInfo.worldSize.y) * * chunk.groupInfo.terrainLength); * * float radio = (float)brush.BrushRange; * float BrushOcaptiy = brush.BrushOpacity; * float cell = chunk.groupInfo.worldSize.x / (chunk.groupInfo.terrainWidth - 1); * * * float maxX = localPoint.x + (radio + 2.0f * cell); * float minX = localPoint.x - (radio + 2.0f * cell); * float maxY = localPoint.z + (radio + 2.0f * cell); * float minY = localPoint.z - (radio + 2.0f * cell); * int iMinx = Mathf.FloorToInt((minX / chunk.groupInfo.worldSize.x) * * chunk.groupInfo.terrainWidth); * * * float fMaxX = (maxX / chunk.groupInfo.worldSize.x) * chunk.groupInfo.terrainWidth; * int iMaxx = Mathf.CeilToInt(fMaxX); * int iMiny = Mathf.FloorToInt((minY / chunk.groupInfo.worldSize.y) * * chunk.groupInfo.terrainLength); * int iMaxy = Mathf.CeilToInt((maxY / chunk.groupInfo.worldSize.y) * * chunk.groupInfo.terrainLength); * * Vector2 TestPoint = new Vector2(); * for(int idy = iMiny; idy <= iMaxy; ++idy) * { * for(int idx = iMinx; idx <= iMaxx; ++idx) * { * TestPoint.x = idx; * TestPoint.y = idy; * float distance = Vector2.Distance(TestPoint, localIdx); * float weight =1.0f - (distance / radio); * if(weight < 0.0f) * { * weight = 0.0f; * } * if(weight > 1.0f) * { * weight = 1.0f; * } * weight = Mathf.Sin(weight * (Mathf.PI / 2.0f)); * float curValue = chunk.groupInfo.GetRealHeight(idx, idy); * float newValue = (curValue * (1.0f - weight)) + BrushOcaptiy * weight; * chunk.groupInfo.SetValue(idx, idy, newValue); * } * } * */ #endregion v1.0 #region v1.1 /* * Vector3 localPoint = point - transform.position; * int BrushSize = (int)brush.BrushRange; * float BrushOcaptiy = brush.Targetheight + 1.0f; * float powValue = brush.BrushPow; * * int idx = Mathf.RoundToInt((localPoint.x / chunk.groupInfo.worldSize.x) * chunk.groupInfo.terrainWidth); * int idy = Mathf.RoundToInt((localPoint.z / chunk.groupInfo.worldSize.y) * chunk.groupInfo.terrainLength); * * int minX = Mathf.Max(0, idx - BrushSize); * int maxX = Mathf.Min(chunk.groupInfo.terrainWidth, idx + BrushSize); * * int minY = Mathf.Max(0, idy - BrushSize); * int maxY = Mathf.Min(chunk.groupInfo.terrainLength, idy + BrushSize); * * Vector2 center = new Vector2(idx, idy); * Vector2 testPoint = new Vector2(maxX, maxY); * float maxDistance = Vector2.Distance(center, testPoint); * for (int y = minY; y <= maxY; ++y) * { * for (int x = minX; x <= maxX; ++x) * { * float curValue = chunk.groupInfo.GetRealHeight(x, y); * testPoint.x = x; * testPoint.y = y; * float distance = Vector2.Distance(center, testPoint); * //if (distance > brush.BrushRange) continue; * float Distancevalue = (distance / maxDistance); * float num1 = Mathf.Pow(Distancevalue, powValue); * float num2 = (1.0F - num1); * if (num2 > 1.0f) num2 = 1.0f; * if (num2 < 0.0f) num2 = 0.0f; * float newvalue = BrushOcaptiy * num2; * * if(newvalue > BrushOcaptiy - 1.0f) * { * newvalue = BrushOcaptiy - 1.0F; * } * newvalue = Mathf.Max(curValue, newvalue); * chunk.groupInfo.SetValue(x, y, newvalue); * } * } */ #endregion v1.1 float radius = brush.Radius; float num = brush.Strenght; float blurRange = brush.BlurRadius; float num3 = 1.0f - Mathf.Pow(brush.BlurPower, 4.0f); num3 = 1.0f - Mathf.Pow(1.0f - num3, 1.1f); //Height Vector2 localPoint = new Vector2(point.x - transform.position.x, point.z - transform.position.z); localPoint.x = Mathf.RoundToInt((localPoint.x / chunk.groupInfo.worldSize.x) * (chunk.groupInfo.terrainWidth - 1)); localPoint.y = Mathf.RoundToInt((localPoint.y / chunk.groupInfo.worldSize.y) * (chunk.groupInfo.terrainLength - 1)); float Minx = Mathf.Max(0, localPoint.x - (radius + blurRange)); float Maxx = Mathf.Min(chunk.groupInfo.terrainWidth - 1, localPoint.x + (radius + blurRange)); float MinY = Mathf.Max(0, localPoint.y - (radius + blurRange)); float Maxy = Mathf.Min(chunk.groupInfo.terrainLength - 1, localPoint.y + (radius + blurRange)); Vector2 CenterPoint = new Vector2(Minx, MinY); float localsqrDis = (radius + blurRange) * (radius + blurRange); for (int y = (int)MinY; y <= Maxy; ++y) { for (int x = (int)Minx; x <= Maxx; ++x) { //每个点的 高低的切面 int heightflag = chunk.groupInfo.GetHeightIndex(x, y); int heightMinFlag = chunk.groupInfo.GetMinHeightIndex(x, y); //float curValue = chunk.groupInfo.GetRealHeight(x, y); CenterPoint.x = x; CenterPoint.y = y; float sqr = Vector2.SqrMagnitude(localPoint - CenterPoint); if (sqr < localsqrDis) { float distancePower = GetDistancePower(Mathf.Sqrt(sqr), true, brush); int targetFlag = Mathf.FloorToInt(brush.Targetheight - 0.001f); // float curValue = chunk.groupInfo.GetRealHeight(x, y); //做一次 Filter 整形,不需要重复整形。用Flag标志位表示 /* if (heightflag == heightMinFlag && heightMinFlag < targetFlag) * { * if (chunk.groupInfo.GetFilterFlagValue(x, y) == false) * { * * chunk.groupInfo.SetValue(x,y, heightMinFlag); * chunk.groupInfo.SetSurfaceValue(x, y, heightMinFlag); * chunk.groupInfo.SetFilterFlagValue(x, y, true); * //curValue = heightflag; * } * } */ float curValue = chunk.groupInfo.GetSurfaceRealValue(x, y); float newvalue = Mathf.Lerp(curValue, brush.Targetheight, num * distancePower); //防止拓扑面畸变,补面 if (heightflag > targetFlag) { if (heightMinFlag <= targetFlag) { float surfacevalue = Mathf.Max(chunk.groupInfo.GetSurfaceRealValue(x, y), brush.Targetheight - 0.5f); chunk.groupInfo.SetSurfaceValue(x, y, surfacevalue); } continue; } if (heightMinFlag >= targetFlag) { continue; } chunk.groupInfo.SetCullFace(x, y, newvalue); chunk.groupInfo.SetValue(x, y, newvalue); chunk.groupInfo.SetSurfaceValue(x, y, newvalue); } } } }