public void Append (MeshWrapper addMesh, Vector3 offset, int type) { //verts for (int v=0; v<addMesh.verts.Length; v++) verts[vertCounter+v] = addMesh.verts[v] + offset; if (normals != null) for (int v=0; v<addMesh.verts.Length; v++) verts[vertCounter+v] = addMesh.normals[v]; if (tangents != null) for (int v=0; v<addMesh.verts.Length; v++) tangents[vertCounter+v] = addMesh.tangents[v]; if (uvs != null) for (int v=0; v<addMesh.verts.Length; v++) uvs[vertCounter+v] = addMesh.uvs[v]; if (uv1 != null) for (int v=0; v<addMesh.verts.Length; v++) uv1[vertCounter+v] = addMesh.uv1[v]; if (colors != null) for (int v=0; v<addMesh.verts.Length; v++) colors[vertCounter+v] = addMesh.colors[v]; //tris // for (int t=0; t<addMesh.triangles[0].Length; t++) // triangles[type][triCounters[type] + t] = addMesh.triangles[0][t] + vertCounter; for (int t=0; t<addMesh.tris.Length; t++) triangles[type][triCounters[type] + t] = addMesh.tris[t] + vertCounter; triCounters[type] += addMesh.tris.Length; //increment counters // triCounters[type] += addMesh.triangles[0].Length; vertCounter += addMesh.verts.Length; }
public void Build () { if (land.profile) Profiler.BeginSample("Build Far"); if (land.farMesh == null) { filter.sharedMesh.Clear(); return; } //round coordinates to prevent jitter int step = (int)(land.farSize / 5f); x = Mathf.RoundToInt( 1f*x/step ) * step; z = Mathf.RoundToInt( 1f*z/step ) * step; //creating wrapper MeshWrapper wrapper = new MeshWrapper(land.farMesh); wrapper.uvs = new Vector2[wrapper.verts.Length]; //do not load arrays from mesh, but create them wrapper.uv1 = new Vector2[wrapper.verts.Length]; if (land.rtpCompatible) wrapper.colors = new Color[wrapper.verts.Length]; //calculating array of types //TODO bring this fn somewhere (to VoxelTerrain) to avoid calculation 2 types per chunk int[] typeToChannel = new int[land.types.Length]; //[0,1,2,3,4,0,0,0] int counter = 0; for (int t=0; t<land.types.Length; t++) { if (land.types[t].filledTerrain) { typeToChannel[t]=counter; counter++; } else typeToChannel[t] = -1; } //gathering ref array bool[] refExist = new bool[land.types.Length]; for (int i=0; i<land.types.Length; i++) refExist[i] = land.types[i].filledTerrain; //setting mesh constant arrays if (filter.sharedMesh==null || filter.sharedMesh.vertexCount != wrapper.verts.Length) { if (filter.sharedMesh==null) filter.sharedMesh = new Mesh(); filter.sharedMesh.Clear(); filter.sharedMesh.vertices = new Vector3[wrapper.verts.Length]; //to equalize number of verts with wrapper //filter.sharedMesh.tangents = new Vector4[wrapper.verts.Length]; } #region Setting Verts for (int v=0; v<wrapper.verts.Length; v++) { //vert position float vertX = wrapper.verts[v].x * land.farSize; float vertZ = wrapper.verts[v].z * land.farSize; wrapper.verts[v] = new Vector3(vertX, land.data.GetTopPoint((int)vertX+x, (int)vertZ+z), vertZ); //there could be GetTopPoint with refExist, but this is faster //vert type int type = land.data.GetTopType((int)vertX+x, (int)vertZ+z, refExist); if (type>=typeToChannel.Length) type=0; int textureNum = typeToChannel[type]; if (!land.rtpCompatible) { switch (textureNum) { case 0: wrapper.uvs[v] = new Vector2(1,0); break; case 1: wrapper.uvs[v] = new Vector2(0,1); break; case 2: wrapper.uv1[v] = new Vector2(1,0); break; case 3: wrapper.uv1[v] = new Vector2(0,1); break; } } else { switch (textureNum) { case 0: wrapper.colors[v] = new Color(1,0,0,0); break; case 1: wrapper.colors[v] = new Color(0,1,0,0); break; case 2: wrapper.colors[v] = new Color(0,0,1,0); break; case 3: wrapper.colors[v] = new Color(0,0,0,1); break; } } } #endregion #region Calculating normals wrapper.ApplyTo(filter.sharedMesh); filter.sharedMesh.RecalculateNormals(); wrapper.normals = filter.sharedMesh.normals; #endregion #region Adjust (lower verts and disable tris) //calculating already built area int minX = 2147483000; int maxX = -2147483000; int minZ = 2147483000; int maxZ = -2147483000; for (int i=0; i<land.chunks.array.Length; i++) { Chunk chunk = land.chunks.array[i]; if (chunk == null) continue; if (chunk.stage != Chunk.Stage.complete) continue; if (chunk.faces == null || chunk.faces.Length == 0) continue; if (chunk.offsetX < minX) minX = chunk.offsetX; if (chunk.offsetZ < minZ) minZ = chunk.offsetZ; if (chunk.offsetX + land.chunkSize > maxX) maxX = chunk.offsetX + land.chunkSize; if (chunk.offsetZ + land.chunkSize > maxZ) maxZ = chunk.offsetZ + land.chunkSize; } //finding verts that are intersecting already built chunks bool[] vertInChunk = new bool[wrapper.verts.Length]; for (int i=0; i<wrapper.verts.Length; i++) { Vector3 vert = wrapper.verts[i]; vertInChunk[i] = true; if (vert.x+x < minX || vert.z+z < minZ || vert.x+x > maxX || vert.z+z > maxZ) { vertInChunk[i] = false; continue; } int vertChunkX = Mathf.FloorToInt(1f*(vert.x+x)/land.chunkSize); int vertChunkZ = Mathf.FloorToInt(1f*(vert.z+z)/land.chunkSize); if (!land.chunks.CheckInRange(vertChunkX, vertChunkZ)) { vertInChunk[i] = false; continue; } Chunk chunk = land.chunks[vertChunkX, vertChunkZ]; if (chunk == null || chunk.stage != Chunk.Stage.complete) vertInChunk[i] = false; //flooring vert a bit wrapper.verts[i] -= wrapper.normals[i]*0.5f; } //if all of the triangle verts are in chunk or at floor - disable triangle int[] tris = wrapper.triangles[0]; for (int t=0; t<tris.Length; t+=3) { if ((vertInChunk[ tris[t] ] && vertInChunk[ tris[t+1] ] && vertInChunk[ tris[t+2] ]) || (wrapper.verts[ tris[t] ].y<0.01f && wrapper.verts[ tris[t+1] ].y<0.01f && wrapper.verts[ tris[t+2]].y<0.01f) ) { tris[t]=0; tris[t+1]=0; tris[t+2]=0; } } #endregion //applying wrapper wrapper.ApplyTo(filter.sharedMesh); //resetting vertex colors if (!land.rtpCompatible) { Color[] colors = new Color[wrapper.verts.Length]; for (int v=0; v<wrapper.verts.Length; v++) colors[v] = new Color(0.5f, 0.5f, 0.5f, 1f); filter.sharedMesh.colors = colors; } #region Material GetComponent<Renderer>().sharedMaterial = land.terrainMaterial; //MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); //int defaultType = 0; // for(int i=0; i<typeToChannel.Length; i++) // if (typeToChannel[i] != 0) defaultType = i; //for(int i=0; i<4; i++) // { // string propPostfix = i==0 ? "" : (i+1).ToString(); // int type = defaultType; // for (int j=0; j<typeToChannel.Length; j++) // if (typeToChannel[j]==i) type = j; // //if (land.types[type].texture != null) materialPropertyBlock.AddTexture("_MainTex" + propPostfix, land.types[type].texture); // //if (land.types[type].bumpTexture != null)materialPropertyBlock.AddTexture("_BumpMap" + propPostfix, land.types[type].bumpTexture); // } //materialPropertyBlock.SetFloat("_Tile", 0.1f); //GetComponent<Renderer>().SetPropertyBlock(materialPropertyBlock); #endregion //moving object transform.localPosition = new Vector3(x,0,z); //shrinking bounds so that they do not exceed build dist //filter.sharedMesh.bounds = new Bounds(Vector3.zero, new Vector3(land.removeDistance, filter.sharedMesh.bounds.extents.y, land.removeDistance)); if (land.profile) Profiler.EndSample(); }
public void AppendWithFFD (MeshWrapper addMesh, int type, Vector3 cornerA, Vector3 cornerB, Vector3 cornerC, Vector3 cornerD, Vector3 normal) { //verts for (int v=0; v < addMesh.verts.Length; v++) { float xPercent = addMesh.verts[v].x + 0.5f; float zPercent = addMesh.verts[v].z + 0.5f; Vector3 vertX1 = cornerB*xPercent + cornerA*(1-xPercent); Vector3 vertX2 = cornerC*xPercent + cornerD*(1-xPercent); verts[vertCounter+v] = vertX1*zPercent + vertX2*(1-zPercent) + new Vector3(0, addMesh.verts[v].y, 0); } if (normals != null) { if (normal.sqrMagnitude > 0.01f) for (int v=0; v<addMesh.verts.Length; v++) normals[vertCounter+v] = normal; else for (int v=0; v<addMesh.verts.Length; v++) normals[vertCounter+v] = addMesh.normals[v]; } if (tangents != null) for (int v=0; v<addMesh.verts.Length; v++) tangents[vertCounter+v] = addMesh.tangents[v]; if (uvs != null) for (int v=0; v<addMesh.verts.Length; v++) uvs[vertCounter+v] = addMesh.uvs[v]; if (uv1 != null) for (int v=0; v<addMesh.verts.Length; v++) uv1[vertCounter+v] = addMesh.uv1[v]; if (colors != null) for (int v=0; v<addMesh.verts.Length; v++) colors[vertCounter+v] = addMesh.colors[v]; //tris // for (int t=0; t<addMesh.triangles[0].Length; t++) // triangles[type][triCounters[type] + t] = addMesh.triangles[0][t] + vertCounter; for (int t=0; t<addMesh.tris.Length; t++) triangles[type][triCounters[type] + t] = addMesh.tris[t] + vertCounter; triCounters[type] += addMesh.tris.Length; //increment counters // triCounters[type] += addMesh.triangles[0].Length; vertCounter += addMesh.verts.Length; }
//operators public void Append (MeshWrapper addMesh, Vector3 offset) { Append(addMesh, offset, 0); }
public void Append (MeshWrapper addMesh, float x,float y,float z, int type) //shift xyz. Type is submesh id that should be added to { //verts for (int v=0; v < addMesh.verts.Length; v++) { int vBase = v+vertNum; verts[vBase] = new Vector3(addMesh.verts[v].x+x, addMesh.verts[v].y+y, addMesh.verts[v].z+z); normals[vBase] = addMesh.normals[v]; tangents[vBase] = addMesh.tangents[v]; uvs[vBase] = addMesh.uvs[v]; uv1[vBase] = addMesh.uv1[v]; colors[vBase] = addMesh.colors[v]; } //tris for (int t=0; t<addMesh.subs[0].tris.Length; t++) subs[type].tris[t+subs[type].triNum] = addMesh.subs[0].tris[t] + vertNum; subs[type].triNum += addMesh.subs[0].tris.Length; vertNum += addMesh.verts.Length; }
public void AppendToFace (MeshWrapper addMesh, Chunk.Face face, Vector3[] terrainVerts, int type, float height=1f, float incline=0f, float random=0f, bool takeNormals=true) { //verts for (int v=0; v < addMesh.verts.Length; v++) { int vBase = v+vertNum; //random int randomNum = (int)Mathf.Repeat(face.x*20 + face.y*10 + face.z*5 + face.dir + v, 990); float xPercent = addMesh.verts[v].x + 0.5f; float zPercent = addMesh.verts[v].z + 0.5f; Vector3 vertX1 = terrainVerts[face.cornerNums.b]*xPercent + terrainVerts[face.cornerNums.a]*(1-xPercent); Vector3 vertX2 = terrainVerts[face.cornerNums.c]*xPercent + terrainVerts[face.cornerNums.d]*(1-xPercent); Vector3 vert = vertX1*zPercent + vertX2*(1-zPercent); verts[vBase] = new Vector3( vert.x + face.normal.x*incline + (VoxelTerrain.random[randomNum]-0.5f)*random, vert.y + addMesh.verts[v].y*height + (VoxelTerrain.random[randomNum+1]-0.5f)*random, vert.z + face.normal.z*incline + (VoxelTerrain.random[randomNum+2]-0.5f)*random); if (takeNormals) normals[vBase] = face.normal; else normals[vBase] = addMesh.normals[v]; tangents[vBase] = addMesh.tangents[v]; uvs[vBase] = addMesh.uvs[v]; uv1[vBase] = addMesh.uv1[v]; colors[vBase] = addMesh.colors[v]; } //tris // for (int t=0; t<addMesh.triangles[0].Length; t++) // triangles[type][triCounters[type] + t] = addMesh.triangles[0][t] + vertCounter; for (int t=0; t<addMesh.tris.Length; t++) triangles[type][triCounters[type] + t] = addMesh.tris[t] + vertCounter; triCounters[type] += addMesh.tris.Length; //increment counters // triCounters[type] += addMesh.triangles[0].Length; vertCounter += addMesh.verts.Length; }