public void rebuild(float newSize, int newResolution, int newNodesPerMesh, float newColliderDepth, int newSortingLayer, int newSortingOrder) { Texture2D oldValues = new Texture2D(resolution + 1, resolution + 1); for (int x = 0; x < resolution; x++) { for (int y = 0; y < resolution; y++) { Destroy2DNode node = getNode(x, resolution - y); if (node != null) { oldValues.SetPixel(x, y, new Color(0, 0, 0, node.tl)); oldValues.SetPixel(x + 1, y, new Color(0, 0, 0, node.tr)); oldValues.SetPixel(x, y + 1, new Color(0, 0, 0, node.bl)); oldValues.SetPixel(x + 1, y + 1, new Color(0, 0, 0, node.br)); } else { oldValues.SetPixel(x, y, new Color(0, 0, 0, 0)); oldValues.SetPixel(x + 1, y, new Color(0, 0, 0, 0)); oldValues.SetPixel(x, y + 1, new Color(0, 0, 0, 0)); oldValues.SetPixel(x + 1, y + 1, new Color(0, 0, 0, 0)); } } } oldValues.Apply(); clean(); terrainSize = newSize; resolution = newResolution; nodesPerMesh = newNodesPerMesh; colliderDepth = newColliderDepth; sortingLayer = newSortingLayer; sortingOrder = newSortingOrder; createTerrain(oldValues); }
private void buildMesh(Material material, float colliderDepth, int sortingLayer, int sortingOrder, Destroy2D terrain) { if (GetComponent <MeshCollider>() != null) { DestroyImmediate(GetComponent <MeshCollider>()); } MeshRenderer mr = gameObject.GetComponent <MeshRenderer>(); MeshFilter mf = gameObject.GetComponent <MeshFilter>(); PolygonCollider2D polyCollider = gameObject.GetComponent <PolygonCollider2D>(); Mesh m; if (mr != null) { DestroyImmediate(mr); } if (mf != null) { if (mf.sharedMesh != null) { mf.sharedMesh.Clear(); } DestroyImmediate(mf); } if (terrain == null) { //GameObject.DestroyImmediate(gameObject); return; } if (polyCollider != null) { DestroyImmediate(polyCollider); polyCollider = null; } mr = gameObject.AddComponent <MeshRenderer>(); mf = gameObject.AddComponent <MeshFilter>(); m = new Mesh(); mf.sharedMesh = m; int vertexCount = 0; int indexCount = 0; int uvCount = 0; int uv1Count = 0; int colliderCount = 0; for (int x = 0; x < meshNodeCount; x++) { for (int y = 0; y < meshNodeCount; y++) { Destroy2DNode node = terrain.getNode(x + meshX, y + meshY); if (node != null) { if (node.isFull || node.isGeometry) { vertexCount += node.vertices.Length; indexCount += node.indexes.Length; uvCount += node.uv.Length; uv1Count += node.uv1.Length; if (node.isGeometry) { colliderCount++; if (node.hasSecondNormal) { colliderCount++; } } } } } } Vector3[] vertices = new Vector3[vertexCount]; Vector3[] normals = new Vector3[vertexCount]; Vector4[] tangents = new Vector4[vertexCount]; int[] indexes = new int[indexCount]; Vector2[] uv = new Vector2[uvCount]; Vector2[] uv1 = new Vector2[uv1Count]; vertexCount = 0; indexCount = 0; uvCount = 0; uv1Count = 0; colliderCount = 0; for (int x = 0; x < meshNodeCount; x++) { for (int y = 0; y < meshNodeCount; y++) { Destroy2DNode node = terrain.getNode(x + meshX, y + meshY); if (node != null) { if (node.isFull || node.isGeometry) { Vector3 nodePos = node.nodePosition - gameObject.transform.localPosition; for (int i = 0; i < node.vertices.Length; i++) { vertices[vertexCount + i] = node.vertices[i] + nodePos; normals[vertexCount + i] = Vector3.back; tangents[vertexCount + i] = new Vector4(1, 0, 0, -1); } for (int i = 0; i < node.indexes.Length; i++) { indexes[indexCount + i] = node.indexes[i] + vertexCount; } for (int i = 0; i < node.uv.Length; i++) { uv[uvCount + i] = node.uv[i]; } for (int i = 0; i < node.uv1.Length; i++) { uv1[uv1Count + i] = node.uv1[i]; } vertexCount += node.vertices.Length; indexCount += node.indexes.Length; uvCount += node.uv.Length; uv1Count += node.uv1.Length; if (node.isGeometry) { if (polyCollider == null) { polyCollider = gameObject.AddComponent <PolygonCollider2D>(); } node.addPolygonCollider(polyCollider); /*node.addToCollisionMesh(collVertices, collIndexes, collNormals, colliderCount, colliderDepth, nodePos); * * if (node.hasSecondNormal) { * colliderCount++; * } * * colliderCount++;*/ } } } } } m.vertices = vertices; m.triangles = indexes; m.uv = uv; m.uv1 = uv1; m.normals = normals; m.tangents = tangents; m.Optimize(); renderer.material = material; gameObject.layer = terrain.gameObject.layer; isDirty = false; }
void createTerrain(Texture2D mapTexture) { clean(); createColorMask(); nodes = new Destroy2DNode[resolution * resolution]; int meshCount = Mathf.FloorToInt(resolution / nodesPerMesh); if ((resolution % nodesPerMesh) > 0) { meshCount++; } nodeMeshes = new Destroy2DMesh[meshCount * meshCount]; Destroy2DMesh currentMesh = null; //nodeValuesTexture = new Texture2D(resolution, resolution); float nodeSize = terrainSize / resolution; float uvDelta = 1.0f / resolution; for (int x = 0; x < resolution; x++) { for (int y = 0; y < resolution; y++) { Destroy2DNode node = Destroy2DNode.createNewNode(); node.terrainSize = terrainSize; node.nodePosition = new Vector3(x * nodeSize, y * -nodeSize, 0); nodes[x + y * resolution] = node; currentMesh = nodeMeshes[Mathf.FloorToInt(x / nodesPerMesh) + Mathf.FloorToInt(y / nodesPerMesh) * meshCount]; if (currentMesh == null) { currentMesh = Destroy2DMesh.instantiate(); currentMesh.gameObject.transform.parent = gameObject.transform; currentMesh.gameObject.transform.localPosition = node.nodePosition; nodeMeshes[Mathf.FloorToInt(x / nodesPerMesh) + Mathf.FloorToInt(y / nodesPerMesh) * meshCount] = currentMesh; currentMesh.meshX = x; currentMesh.meshY = y; currentMesh.meshNodeCount = nodesPerMesh; } if (node.init(mapTexture, x * uvDelta, 1 - y * uvDelta, uvDelta, nodeSize, colorValue, material)) { } //nodeValuesTexture.SetPixel(x,-y, Color.white * (colorValue + (node.tl + node.tr + node.bl + node.br) * 0.25f)); } } //nodeValuesTexture.Apply(); foreach (Destroy2DMesh mesh in GetComponentsInChildren <Destroy2DMesh>()) { mesh.commit(material, colliderDepth, sortingLayer, sortingOrder, this); } }
public void paintColorMask(int type, Vector3 pos, float radius, float intensity) { createColorMask(); float nodeSize = terrainSize / resolution; int radiusSize = Mathf.FloorToInt(radius / nodeSize) + 1; int posX = Mathf.FloorToInt((pos.x - transform.position.x) / nodeSize); int posY = Mathf.FloorToInt(-(pos.y - transform.position.y) / nodeSize); for (int x = posX - radiusSize; x < posX + radiusSize; x++) { for (int y = posY - radiusSize; y < posY + radiusSize; y++) { if ((x >= 0) && (x < resolution) && (y >= 0) && (y < resolution)) { Destroy2DNode node = nodes[x + y * resolution]; if (node != null) { float rad = ((node.nodePosition + transform.position) - pos).magnitude; if (rad < radius) { Color currentColor = colorMasks.GetPixel(x, -y); float factor = (1 - (rad / radius)) * intensity; if (type == 0) { currentColor.r += factor; currentColor.g -= factor; currentColor.b -= factor; currentColor.a -= factor; } if (type == 1) { currentColor.r -= factor; currentColor.g += factor; currentColor.b -= factor; currentColor.a -= factor; } if (type == 2) { currentColor.r -= factor; currentColor.g -= factor; currentColor.b += factor; currentColor.a -= factor; } if (type == 3) { currentColor.r -= factor; currentColor.g -= factor; currentColor.b -= factor; currentColor.a += factor; } if (type == 4) { currentColor.r -= factor; currentColor.g -= factor; currentColor.b -= factor; currentColor.a -= factor; } currentColor.r = Mathf.Clamp01(currentColor.r); currentColor.g = Mathf.Clamp01(currentColor.g); currentColor.b = Mathf.Clamp01(currentColor.b); currentColor.a = Mathf.Clamp01(currentColor.a); colorMasks.SetPixel(x, -y, currentColor); } } } } } colorMasks.Apply(); updateMaterial(); }
private void changeTerrain(Vector3 pos, float radius, float intensity) { int meshCount = Mathf.FloorToInt(resolution / nodesPerMesh); Destroy2DMesh currentMesh = null; float nodeSize = terrainSize / resolution; int radiusSize = Mathf.FloorToInt(radius / nodeSize) + 1; int posX = Mathf.FloorToInt((pos.x - transform.position.x) / nodeSize); int posY = Mathf.FloorToInt(-(pos.y - transform.position.y) / nodeSize); float uvDelta = 1.0f / resolution; for (int x = posX - radiusSize; x < posX + radiusSize; x++) { for (int y = posY - radiusSize; y < posY + radiusSize; y++) { if ((x >= 0) && (x < resolution) && (y >= 0) && (y < resolution)) { Destroy2DNode node = nodes[x + y * resolution]; if (node == null) { node = nodes[x + y * resolution] = Destroy2DNode.createNewNode(); node.terrainSize = terrainSize; node.setValues(x * uvDelta, 1 - y * uvDelta, uvDelta, nodeSize); node.nodePosition = new Vector3(x * nodeSize, y * -nodeSize, 0); } if (node != null) { bool shouldUpdate = false; float rad_tl = ((node.nodePosition + transform.position) - pos).magnitude; float rad_tr = ((node.nodePosition + transform.position + Vector3.right * nodeSize) - pos).magnitude; float rad_bl = ((node.nodePosition + transform.position + Vector3.down * nodeSize) - pos).magnitude; float rad_br = ((node.nodePosition + transform.position + Vector3.right * nodeSize + Vector3.down * node.size) - pos).magnitude; if (rad_tl < radius) { node.tl -= intensity * (1 - (rad_tl / radius)); shouldUpdate = true; } if (rad_tr < radius) { node.tr -= intensity * (1 - (rad_tr / radius)); shouldUpdate = true; } if (rad_bl < radius) { node.bl -= intensity * (1 - (rad_bl / radius)); shouldUpdate = true; } if (rad_br < radius) { node.br -= intensity * (1 - (rad_br / radius)); shouldUpdate = true; } if (shouldUpdate) { node.tl = Mathf.Clamp01(node.tl); node.tr = Mathf.Clamp01(node.tr); node.bl = Mathf.Clamp01(node.bl); node.br = Mathf.Clamp01(node.br); currentMesh = nodeMeshes[Mathf.FloorToInt(x / nodesPerMesh) + Mathf.FloorToInt(y / nodesPerMesh) * meshCount]; currentMesh.isDirty = true; Destroy2DNode otherNode = null; Destroy2DMesh otherMesh = null; //top left if ((x > 1) && (y > 1)) { otherNode = nodes[(x - 1) + (y - 1) * resolution]; otherNode.br = node.tl; otherNode.reInit(colorValue); otherMesh = nodeMeshes[Mathf.FloorToInt((x - 1) / nodesPerMesh) + Mathf.FloorToInt((y - 1) / nodesPerMesh) * meshCount]; otherMesh.isDirty = true; } //top if (y > 1) { otherNode = nodes[(x) + (y - 1) * resolution]; otherNode.bl = node.tl; otherNode.br = node.tr; otherNode.reInit(colorValue); otherMesh = nodeMeshes[Mathf.FloorToInt((x) / nodesPerMesh) + Mathf.FloorToInt((y - 1) / nodesPerMesh) * meshCount]; otherMesh.isDirty = true; } //top right if ((x < (resolution - 2)) && (y > 1)) { otherNode = nodes[(x + 1) + (y - 1) * resolution]; otherNode.bl = node.tr; otherNode.reInit(colorValue); otherMesh = nodeMeshes[Mathf.FloorToInt((x + 1) / nodesPerMesh) + Mathf.FloorToInt((y - 1) / nodesPerMesh) * meshCount]; otherMesh.isDirty = true; } //right if (x < (resolution - 2)) { otherNode = nodes[(x + 1) + (y) * resolution]; otherNode.tl = node.tr; otherNode.bl = node.br; otherNode.reInit(colorValue); otherMesh = nodeMeshes[Mathf.FloorToInt((x + 1) / nodesPerMesh) + Mathf.FloorToInt((y) / nodesPerMesh) * meshCount]; otherMesh.isDirty = true; } //bottom right if ((x < (resolution - 2)) && (y < (resolution - 2))) { otherNode = nodes[(x + 1) + (y + 1) * resolution]; otherNode.tl = node.br; otherNode.reInit(colorValue); otherMesh = nodeMeshes[Mathf.FloorToInt((x + 1) / nodesPerMesh) + Mathf.FloorToInt((y + 1) / nodesPerMesh) * meshCount]; otherMesh.isDirty = true; } //bottom if (y < (resolution - 2)) { otherNode = nodes[(x) + (y + 1) * resolution]; otherNode.tl = node.bl; otherNode.tr = node.br; otherNode.reInit(colorValue); otherMesh = nodeMeshes[Mathf.FloorToInt((x) / nodesPerMesh) + Mathf.FloorToInt((y + 1) / nodesPerMesh) * meshCount]; otherMesh.isDirty = true; } //bottom left if ((x > 1) && (y < (resolution - 2))) { otherNode = nodes[(x - 1) + (y + 1) * resolution]; otherNode.tr = node.bl; otherNode.reInit(colorValue); otherMesh = nodeMeshes[Mathf.FloorToInt((x - 1) / nodesPerMesh) + Mathf.FloorToInt((y + 1) / nodesPerMesh) * meshCount]; otherMesh.isDirty = true; } //left if (x > 1) { otherNode = nodes[(x - 1) + (y) * resolution]; otherNode.tr = node.tl; otherNode.br = node.bl; otherNode.reInit(colorValue); otherMesh = nodeMeshes[Mathf.FloorToInt((x - 1) / nodesPerMesh) + Mathf.FloorToInt((y) / nodesPerMesh) * meshCount]; otherMesh.isDirty = true; } node.reInit(colorValue); //nodeValuesTexture.SetPixel(x,-y, Color.white * (colorValue + (node.tl + node.tr + node.bl + node.br) * 0.25f)); } } } } } //nodeValuesTexture.Apply(); }