Пример #1
0
        public void CalculateMesh()
        {
                                #if WDEBUG
            if (!ThreadWorker.multithreading)
            {
                Profiler.BeginSample("Calculate Mesh");
            }
                                #endif

            //reading data
            if (meshWorker.stop)
            {
                return;
            }
            int margin = voxeland.meshMargin;

            //top and bottom points
            int topPoint; int bottomPoint;
            voxeland.data.GetTopBottomPoints(rect.Expanded(margin), out topPoint, out bottomPoint, ignoreEmptyColumns: true);

            //empty mesh check
            if (topPoint == 0)
            {
                hiWrapper    = null; loWrapper = null; grassWrapper = null;
                indexToCoord = null;
                return;                         //exit to apply without stopping
            }

            //creating and filling matrix
            Matrix3 <byte> matrix = new Matrix3 <byte>(rect.offset.x - margin, bottomPoint - 1, rect.offset.z - margin, rect.size.x + margin * 2, topPoint - bottomPoint + 2, rect.size.z + margin * 2);
            voxeland.data.FillMatrix(matrix);

            //calculating verts
            if (meshWorker.stop)
            {
                return;
            }
            ChunkMesh.Face[] faces; Vector3[] verts;
            ChunkMesh.CalculateFaces(out faces, out verts, matrix, margin: margin);

            if (faces == null || verts == null || faces.Length == 0)
            {
                hiWrapper = null; loWrapper = null; return;
            }

            ChunkMesh.RelaxMesh(faces, verts, iterations: voxeland.relaxIterations, strength: voxeland.relaxStrength);

            hiWrapper = ChunkMesh.CalculateMesh(faces, verts, hipoly: true);
            loWrapper = ChunkMesh.CalculateMesh(faces, verts, hipoly: false);

            //normals
            if (meshWorker.stop)
            {
                return;
            }
            hiWrapper.normals = ChunkMesh.CalculateNormals(faces, verts, smoothIterations: voxeland.normalsSmooth);
            loWrapper.normals = hiWrapper.normals.Truncated(loWrapper.verts.Length);

            //types
            if (meshWorker.stop)
            {
                return;
            }

            int maxChannelsCount;
            switch (voxeland.channelEncoding)
            {
            case Voxeland.ChannelEncoding.MegaSplat: maxChannelsCount = 256; break;

            case Voxeland.ChannelEncoding.RTP: maxChannelsCount = 4; break;

            default: maxChannelsCount = 24; break;
            }
            maxChannelsCount = Mathf.Min(maxChannelsCount, voxeland.landTypes.array.Length);


            if (voxeland.channelEncoding == Voxeland.ChannelEncoding.Voxeland)
            {
                float[] chWeights = new float[verts.Length];
                hiWrapper.tangents = new Vector4[verts.Length];
                for (int ch = 0; ch < maxChannelsCount; ch++)
                {
                    if (!ChunkMesh.IsChannelUsed(faces, ch))
                    {
                        continue;
                    }
                    ChunkMesh.FillChWeights(faces, verts, ch, ref chWeights);
                    ChunkMesh.EncodeChWeights(chWeights, ch, ref hiWrapper.tangents);
                }
                loWrapper.tangents = hiWrapper.tangents.Truncated(loWrapper.verts.Length);
            }

            else if (voxeland.channelEncoding == Voxeland.ChannelEncoding.MegaSplat)
            {
                float[] chWeights = new float[verts.Length];
                hiWrapper.colors = new Color[verts.Length];
                Vector4[] uvs2 = new Vector4[verts.Length];

                byte[]  topTypes  = new byte[verts.Length];
                byte[]  secTypes  = new byte[verts.Length];
                float[] topBlends = new float[verts.Length];                         //blend value of the top type
                float[] secBlends = new float[verts.Length];

                ChunkMesh.EncodeMegaSplatFilters(faces, ref hiWrapper.colors);
                for (int ch = 0; ch < maxChannelsCount; ch++)
                {
                    if (!ChunkMesh.IsChannelUsed(faces, ch))
                    {
                        continue;
                    }
                    ChunkMesh.FillChWeights(faces, verts, ch, ref chWeights);
                    ChunkMesh.FillMegaSplatChTopTypes(chWeights, ch, topTypes, secTypes, topBlends, secBlends);
                }

                ChunkMesh.EncodeMegaSplatChWeights(topTypes, secTypes, topBlends, secBlends, ref hiWrapper.colors, ref uvs2);

                hiWrapper.uvs4    = new List <Vector4> [4];
                hiWrapper.uvs4[3] = new List <Vector4>();                        //3rd channel
                hiWrapper.uvs4[3].AddRange(uvs2);

                hiWrapper.uv = new Vector2[hiWrapper.verts.Length];
                for (int i = 0; i < hiWrapper.verts.Length; i++)
                {
                    hiWrapper.uv[i] = new Vector2(-hiWrapper.verts[i].x, hiWrapper.verts[i].z);
                }

                hiWrapper.tangents = new Vector4[hiWrapper.verts.Length];
                for (int i = 0; i < hiWrapper.verts.Length; i++)
                {
                    hiWrapper.tangents[i] = new Vector4(0, 1, 0, 1);
                }
            }

            else if (voxeland.channelEncoding == Voxeland.ChannelEncoding.RTP)
            {
                float[] chWeights = new float[verts.Length];
                hiWrapper.colors = new Color[verts.Length];

                for (int ch = 0; ch < maxChannelsCount; ch++)
                {
                    if (!ChunkMesh.IsChannelUsed(faces, ch))
                    {
                        continue;
                    }
                    ChunkMesh.FillChWeights(faces, verts, ch, ref chWeights);
                    ChunkMesh.EncodeColorChWeights(chWeights, ch, ref hiWrapper.colors);
                }
                loWrapper.colors = hiWrapper.colors.Truncated(loWrapper.verts.Length);
            }

            //index to coordinate array
            if (meshWorker.stop)
            {
                return;
            }
            indexToCoord = ChunkMesh.CalculateIndexToCoord(faces);

            //calculating grass
            if (meshWorker.stop)
            {
                return;
            }
            Matrix2 <byte> grassMatrix = new Matrix2 <byte>(rect);
            voxeland.data.FillGrass(grassMatrix);

            Matrix2 <ushort> topLevels = new Matrix2 <ushort>(rect);
            voxeland.data.FillHeightmap(topLevels);

            //offset lo border verts to prevent seams
            ChunkMesh.OffsetBorderVerts(loWrapper.verts, loWrapper.normals, rect.size.x, -0.15f);

            if (meshWorker.stop)
            {
                return;
            }
            grassWrapper = ChunkMesh.CalculateGrassMesh(grassMatrix, topLevels, loWrapper.verts, loWrapper.normals, loWrapper.tris, indexToCoord, voxeland.grassTypes);

                                #if WDEBUG
            if (!ThreadWorker.multithreading)
            {
                Profiler.EndSample();
            }
                                #endif
        }