Esempio n. 1
0
    public void Render()
    {
        GameObject ground = new GameObject("_Ground");

        ground.transform.parent = MapRenderer.mapParent.transform;

        for (int i = 0; i < meshes.Length; i++)
        {
            Mesh       mesh       = meshes[i];
            GameObject gameObject = new GameObject("Ground[" + i + "]");
            gameObject.transform.parent = ground.transform;
            var mf = gameObject.AddComponent <MeshFilter>();
            mf.mesh = mesh;
            var mr = gameObject.AddComponent <MeshRenderer>();
            mr.material             = material;
            mr.material.mainTexture = atlas;
            mr.material.SetTexture("_Tintmap", tintmap);
            mr.material.SetTexture("_Lightmap", lightmap);

            Vector3 scale = gameObject.transform.localScale;
            scale.Set(1f, -1f, 1f);
            gameObject.transform.localScale = scale;

            //smooth out mesh
            NormalSolver.RecalculateNormals(mf.mesh, 60);

            //avoid z fighting between ground and models
            gameObject.transform.Translate(0, -0.002f, 0);
            gameObject.AddComponent <MeshCollider>();
            gameObject.layer = LayerMask.NameToLayer("Ground");
        }
    }
Esempio n. 2
0
        public override MeshData GenerateMeshData()
        {
            var vertices  = new List <Vector3>();
            var triangles = new List <int>();

            float[,,] voxels = CalculateDensities();

            for (int x = 0; x < chunkSize - 1; x++)
            {
                for (int y = 0; y < chunkSize - 1; y++)
                {
                    for (int z = 0; z < chunkSize - 1; z++)
                    {
                        float[] cube = CreateCube(x, y, z, voxels);
                        MarchCube(new Vector3(x, y, z), cube, vertices, triangles);
                    }
                }
            }

            List <Vector3> normals = NormalSolver.RecalculateNormals(triangles, vertices, NormalSmoothing);

            return(new MeshData
            {
                vertices = vertices,
                triangles = triangles,
                normals = normals
            });
        }
        /// <summary>
        /// Will reset all meshes stored in the mesh dictionaries to default positons
        /// </summary>
        internal void ResetInflation()
        {
            //Resets all mesh inflations
            var keyList = new List <string>(originalVertices.Keys);

            //For every active meshRenderer key we have created
            foreach (var renderKey in keyList)
            {
                var smr = PregnancyPlusHelper.GetMeshRenderer(ChaControl, renderKey);
                //Normally triggered when user changes clothes, the old clothes render wont be found
                if (smr == null)
                {
                    if (PregnancyPlusPlugin.DebugLog.Value)
                    {
                        PregnancyPlusPlugin.Logger.LogWarning($" ResetInflation > smr was not found {renderKey}");
                    }
                    continue;
                }

                //Create an instance of sharedMesh so we don't modify the mesh shared between characters, that was a fun issue
                Mesh meshCopy = (Mesh)UnityEngine.Object.Instantiate(smr.sharedMesh);
                smr.sharedMesh = meshCopy;

                var sharedMesh = smr.sharedMesh;
                var hasValue   = originalVertices.TryGetValue(renderKey, out Vector3[] origVerts);

                //On change clothes original verts become useless, so skip this
                if (!hasValue)
                {
                    return;
                }

                //Some meshes are not readable and cant be touched...
                if (!sharedMesh.isReadable)
                {
                    PregnancyPlusPlugin.errorCodeCtrl.LogErrorCode(ChaControl.chaID, ErrorCode.PregPlus_MeshNotReadable,
                                                                   $"ResetInflation > smr '{renderKey}' is not readable, skipping");
                    continue;
                }

                if (!sharedMesh || origVerts.Equals(null) || origVerts.Length == 0)
                {
                    continue;
                }

                if (origVerts.Length != sharedMesh.vertexCount)
                {
                    PregnancyPlusPlugin.errorCodeCtrl.LogErrorCode(ChaControl.chaID, ErrorCode.PregPlus_IncorrectVertCount,
                                                                   $"ResetInflation > smr '{renderKey}' has incorrect vert count {origVerts.Length}|{sharedMesh.vertexCount}");
                    continue;
                }

                sharedMesh.vertices = origVerts;
                sharedMesh.RecalculateBounds();
                NormalSolver.RecalculateNormals(sharedMesh, 40f, alteredVerticieIndexes[renderKey]);
                //sharedMesh.RecalculateNormals(); //old way that leaves skin seams
                sharedMesh.RecalculateTangents();
            }
        }
Esempio n. 4
0
 void Update()
 {
     for (int i = 0; i < mesh.vertices.Length; i++)
     {
         UpdateVertices(i);
     }
     mesh.vertices = replaceVertices;
     NormalSolver.RecalculateNormals(mesh, 90);
 }
Esempio n. 5
0
        private void UpdateMesh()
        {
            for (int i = 0; i < agents.Count; i++)
            {
                agents[i].UpdatePoints(vertexTemp);
            }

            mesh.vertices = vertexTemp;
            NormalSolver.RecalculateNormals(mesh, 90f);
            //NormalSolver.ReComputeNormals(mesh);
            //r.sharedMesh = mesh;
        }
Esempio n. 6
0
    public void DrawMeshOnEachBranch()
    {
        foreach (var branch in SplinePlus.SPData.DictBranches)
        {
            //update branches layers
            if (!DMBranches.ContainsKey(branch.Key))
            {
                var newBranchLayer = new DMBranch();
                newBranchLayer.MeshHolder = new GameObject("Mesh Holder");

                newBranchLayer.MeshHolder.AddComponent <MeshFilter>();
                newBranchLayer.MeshHolder.AddComponent <MeshRenderer>();
                newBranchLayer.MeshHolder.transform.parent = this.gameObject.transform;
                DMBranches.Add(branch.Key, newBranchLayer);
            }

            //Draw all branches meshesB
            if (branch.Value.Vertices.Count > 0 && DMBranches[branch.Key].PrefabMeshes.Count > 0)
            {
                var dMBranch = DMBranches[branch.Key];

                var branchFinalMesh = DrawMesh(branch.Value, dMBranch);
                branchFinalMesh.RecalculateBounds();

                if (dMBranch.SmoothNormals)
                {
                    NormalSolver.RecalculateNormals(branchFinalMesh, dMBranch.SmoothNormalsAngle);
                }
                else
                {
                    branchFinalMesh.RecalculateNormals();
                }
                dMBranch.MeshHolder.GetComponent <MeshFilter>().sharedMesh = branchFinalMesh;
            }
        }


        foreach (var dMBranch in DMBranches.Reverse())
        {
            if (!SplinePlus.SPData.DictBranches.ContainsKey(dMBranch.Key))
            {
                MonoBehaviour.DestroyImmediate(dMBranch.Value.MeshHolder);
                DMBranches.Remove(dMBranch.Key);
            }
        }
        if (IsUpdateBase)
        {
            IsUpdateBase = false;
        }
    }
Esempio n. 7
0
        private void UpdateSoftbody()
        {
            for (int i = 0; i < _vCount; i++)
            {
                _softVertices[i].UpdateVertex();
                _softVertices[i].UpdateVelocity(bounciness);
                _softVertices[i].Settle(stiffness);
                _deformedVertices[i] = _softVertices[i].vertexPosition;
            }

            _originalMesh.vertices = _deformedVertices;
            _originalMesh.RecalculateBounds();
            _originalMesh.RecalculateTangents();

            //Third-party Recalculate Normals because Unity's RecalculateNormals make meshes normals to have seams
            NormalSolver.RecalculateNormals(_originalMesh, 60);
        }
Esempio n. 8
0
        /// <summary>
        /// Creates a copy of this planet in scaled space
        /// </summary>
        public void CreateScaledSpaceCopy()
        {
            if (!scaledSpaceCopy)
            {
                GameObject sphere = (GameObject)Resources.Load("scaledSpacePlanet");

                sphere = Instantiate(sphere, transform.position / scaledSpaceFactor, transform.rotation * Quaternion.Euler(0f, 90f, 0f));

                Mesh mesh;
                if (Application.isPlaying)
                {
                    mesh = sphere.GetComponent <MeshFilter>().mesh;
                }
                else
                {
                    mesh = Instantiate(sphere.GetComponent <MeshFilter>().sharedMesh);
                }


                Vector3[] vertices = mesh.vertices;
                Color32[] colors   = new Color32[vertices.Length];

                float sphereRadius = radius / scaledSpaceFactor;


                for (int i = 0; i < vertices.Length; i++)
                {
                    float height = HeightAtXYZ(Quaternion.Euler(0f, 90f, 0f) * vertices[i]);
                    vertices[i] *= (heightInv + height) / heightInv;
                    vertices[i] *= sphereRadius;
                }

                mesh.vertices = vertices;
                mesh.colors32 = colors;
                mesh.RecalculateBounds();
                NormalSolver.RecalculateNormals(mesh, 60);
                if (!Application.isPlaying)
                {
                    sphere.GetComponent <MeshFilter>().mesh = mesh;
                }
                sphere.GetComponent <Renderer>().material = scaledSpaceMaterial;
                sphere.name = transform.name + "_ScaledSpace";

                scaledSpaceCopy = sphere;
            }
        }
        /// <summary>
        /// This will create a blendshape frame for a mesh, that can be used in timeline, required there be a renderKey for inflatedVertices for this smr
        /// </summary>
        /// <param name="smr">Target mesh renderer to update (original shape)</param>
        /// <param name="renderKey">The Shared Mesh render name, used in dictionary keys to get the current verticie values</param>
        /// <returns>Returns the MeshBlendShape that is created. Can be null</returns>
        internal MeshBlendShape CreateBlendShape(SkinnedMeshRenderer smr, string renderKey)
        {
            //Make a copy of the mesh. We dont want to affect the existing for this
            var meshCopyOrig = PregnancyPlusHelper.CopyMesh(smr.sharedMesh);

            if (!meshCopyOrig.isReadable)
            {
                PregnancyPlusPlugin.errorCodeCtrl.LogErrorCode(ChaControl.chaID, ErrorCode.PregPlus_MeshNotReadable,
                                                               $"CreateBlendShape > smr '{renderKey}' is not readable, skipping");
                return(null);
            }

            //Make sure we have an existing belly shape to work with (can be null if user hasnt used sliders yet)
            var exists = originalVertices.TryGetValue(renderKey, out var val);

            if (!exists)
            {
                if (PregnancyPlusPlugin.DebugLog.Value)
                {
                    PregnancyPlusPlugin.Logger.LogInfo(
                        $"CreateBlendShape > smr '{renderKey}' does not exists, skipping");
                }
                return(null);
            }

            if (originalVertices[renderKey].Length != meshCopyOrig.vertexCount)
            {
                PregnancyPlusPlugin.errorCodeCtrl.LogErrorCode(ChaControl.chaID, ErrorCode.PregPlus_IncorrectVertCount,
                                                               $"CreateBlendShape > smr.sharedMesh '{renderKey}' has incorrect vert count {originalVertices[renderKey].Length}|{meshCopyOrig.vertexCount}");
                return(null);
            }

            //Calculate the original normals, but don't show them.  We just want it for the blendshape shape destination
            meshCopyOrig.vertices = originalVertices[renderKey];
            meshCopyOrig.RecalculateBounds();
            NormalSolver.RecalculateNormals(meshCopyOrig, 40f, bellyVerticieIndexes[renderKey]);
            meshCopyOrig.RecalculateTangents();

            // LogMeshBlendShapes(smr);

            //Create a blend shape object on the mesh
            var bsc = new BlendShapeController(meshCopyOrig, smr, $"{renderKey}_{PregnancyPlusPlugin.GUID}");

            //Return the blendshape format that can be saved to character card
            return(ConvertToMeshBlendShape(smr.name, bsc.blendShape));
        }
Esempio n. 10
0
    public void Generate(Generation world, Color grass, Color dampGrass, Color mud, PerlinNoise[] terrainNoises, PerlinNoise moistureNoise)
    {
        MeshFilter meshFilter = GetComponent <MeshFilter> ();

        Mesh mesh = meshFilter.mesh;

        Vector3[] vertices = mesh.vertices;
        Color[]   colors   = mesh.colors;

        for (int i = 0; i < vertices.Length; i++)
        {
            // World positon of the vertex
            Vector3 worldPositionVertex = transform.TransformPoint(vertices[i]);

            float finalDeform    = 0f;
            float maxWorldHeight = 0f;

            foreach (PerlinNoise noise in terrainNoises)
            {
                finalDeform    += noise.ReturnNoise(worldPositionVertex);
                maxWorldHeight += noise.strength;
            }

            float moisture = moistureNoise.ReturnNoise(worldPositionVertex);

            vertices[i] += new Vector3(0f, finalDeform, 0f);

            Color groundColor = Color.Lerp(Color.Lerp(grass, dampGrass, 1f / maxWorldHeight * vertices[i].y), mud, moisture);
            colors[i] = groundColor;
        }

        // reassignation
        mesh.vertices = vertices;
        mesh.colors   = colors;

        mesh.RecalculateBounds();
        mesh.RecalculateNormals();
        NormalSolver.RecalculateNormals(mesh, normalAngle);

        meshFilter.mesh = mesh;
        GetComponent <MeshCollider> ().sharedMesh = mesh;

        world.terrainMeshFilters.Add(meshFilter);
    }
Esempio n. 11
0
 void Update()
 {
     if (Input.GetKeyDown(KeyCode.F7))
     {
         renderers = FindObjectsOfType <SkinnedMeshRenderer>();
         foreach (SkinnedMeshRenderer render in renderers)
         {
             //Console.WriteLine("SkinnedMeshRenderer: " + render.name);
             if (render.name.ToLower().Contains("cf_o_hair"))
             {
                 NormalSolver.RecalculateNormals(render.sharedMesh, 60f);
                 TangentSolver.Solve(render.sharedMesh);
             }
         }
     }
     else if (Input.GetKeyDown(KeyCode.F8))
     {
         renderers = FindObjectsOfType <SkinnedMeshRenderer>();
         foreach (SkinnedMeshRenderer render in renderers)
         {
             //Console.WriteLine("SkinnedMeshRenderer: " + render.name);
             if (render.name.ToLower().Contains("cf_o_hair"))
             {
                 render.sharedMesh.RecalculateNormals();
                 TangentSolver.Solve(render.sharedMesh);
             }
         }
     }
     else if (Input.GetKeyDown(KeyCode.F9))
     {
         renderers = FindObjectsOfType <SkinnedMeshRenderer>();
         foreach (SkinnedMeshRenderer render in renderers)
         {
             if (render.name.ToLower().Contains("cf_o_hair"))
             {
                 TangentSolver.Solve(render.sharedMesh);
             }
         }
     }
 }
Esempio n. 12
0
    public static void BuildMesh(Transform parent, LinePoints[] curves, Material material, float lineRadius, int sphereIterations, int cylinderCapSegments, Color vertexColor)
    {
        DeleteChildObjects(parent, "Curve");
        for (int z = 0; z < curves.Length; z++)
        {
            for (int v = 0; v < curves[z].Points.Length; v++)
            {
                Mesh m = SphereScript.BuildMesh(curves[z].Points[v], lineRadius, sphereIterations, vertexColor);
                m = NormalSolver.RecalculateNormals(m, 75f);
                CreateChildObject(parent, "Curve_" + z + "_Sphere_" + v, m, material);

                if (v < curves[z].Points.Length - 1)
                {
                    Mesh m2 = CylinderScript.BuildMesh(curves[z].Points[v], curves[z].Points[v + 1], lineRadius, lineRadius, vertexColor, new Vector3(0f, 90f, 0f), cylinderCapSegments, true);
                    m2 = NormalSolver.RecalculateNormals(m2, 75f);
                    CreateChildObject(parent, "Curve_" + z + "_Cylinder_" + v, m2, material);
                }
            }

            if (curves[z].ArrowAtStart)
            {
                Vector3 p0     = curves[z].Points[0];
                Vector3 p1     = curves[z].Points[1];
                Vector3 parrow = (p0 - p1).normalized * curves[z].ArrowLength + p0;
                Mesh    m      = CylinderScript.BuildMesh(p0, parrow, curves[z].ArrowRadius, 0f, vertexColor, new Vector3(0f, 90f, 0f), cylinderCapSegments, true);
                m = NormalSolver.RecalculateNormals(m, 75f);
                CreateChildObject(parent, "Curve_" + z + "_ArrowStart", m, material);
            }

            if (curves[z].ArrowAtEnd)
            {
                Vector3 p0     = curves[z].Points[curves[z].Points.Length - 1];
                Vector3 p1     = curves[z].Points[curves[z].Points.Length - 2];
                Vector3 parrow = (p0 - p1).normalized * curves[z].ArrowLength + p0;
                Mesh    m      = CylinderScript.BuildMesh(p0, parrow, curves[z].ArrowRadius, 0f, vertexColor, new Vector3(0f, 90f, 0f), cylinderCapSegments, true);
                m = NormalSolver.RecalculateNormals(m, 75f);
                CreateChildObject(parent, "Curve_" + z + "_ArrowEnd", m, material);
            }
        }
    }
Esempio n. 13
0
    public void createGeometry(Material material, Algorithm2 algorithm)
    {
        init();

        // Generate the quads
        float quadSize = (new Vector3(startPoint.x, 0, endPoint.z) - startPoint).magnitude / (float)quads;

        for (int i = 0; i < quads; i++)
        {
            for (int j = 0; j < quads; j++)
            {
                Chunk2.createQuad((float)i * quadSize, (float)j * quadSize, quadSize, algorithm, meshData, transform);
            }
        }

        // Pass the data to the mesh
        meshRenderer.sharedMaterial = material;
        meshData.GenerateData(meshFilter.sharedMesh);

        // Recalculate bounds and normals
        meshFilter.sharedMesh.RecalculateBounds();
        NormalSolver.RecalculateNormals(meshFilter.sharedMesh, 60);
    }
Esempio n. 14
0
    public void BuildMeshes()
    {
        GameObject parent = new GameObject("_Models");

        parent.transform.parent = MapRenderer.mapParent.transform;
        Dictionary <int, AnimProperties> anims = new Dictionary <int, AnimProperties>();
        int nodeId = 0;

        foreach (RSM.CompiledModel model in models)
        {
            GameObject modelObj = new GameObject(model.rsm.name);
            modelObj.transform.parent = parent.transform;

            foreach (var nodeData in model.nodesData)
            {
                foreach (var meshesByTexture in nodeData)
                {
                    long             textureId = meshesByTexture.Key;
                    RSM.NodeMeshData meshData  = meshesByTexture.Value;
                    RSM.Node         node      = meshData.node;

                    if (meshesByTexture.Value.vertices.Count == 0)
                    {
                        continue;
                    }

                    for (int i = 0; i < meshData.vertices.Count; i += 3)
                    {
                        meshData.triangles.AddRange(new int[] {
                            i + 0, i + 1, i + 2
                        });
                    }

                    //create node unity mesh
                    Mesh mesh = new Mesh();
                    mesh.vertices  = meshData.vertices.ToArray();
                    mesh.triangles = meshData.triangles.ToArray();
                    //mesh.normals = meshData.normals.ToArray();
                    mesh.uv = meshData.uv.ToArray();

                    GameObject nodeObj = new GameObject(node.name);
                    nodeObj.transform.parent = modelObj.transform;

                    string textureFile = model.rsm.textures[textureId];

                    var mf = nodeObj.AddComponent <MeshFilter>();
                    mf.mesh = mesh;
                    var mr = nodeObj.AddComponent <MeshRenderer>();
                    if (meshData.twoSided)
                    {
                        mr.material = material2s;
                        if (textureFile.EndsWith("tga"))
                        {
                            mr.material.shader       = Resources.Load("2SidedAlpha") as Shader;
                            mr.material.renderQueue += 1;
                        }
                    }
                    else
                    {
                        mr.material = material;
                        if (textureFile.EndsWith("tga"))
                        {
                            mr.material.shader       = Resources.Load("ModelShaderAlpha") as Shader;
                            mr.material.renderQueue += 1;
                        }
                    }

                    mr.material.mainTexture = FileManager.Load("data/texture/" + textureFile) as Texture2D;

                    if (model.rsm.shadeType == RSM.SHADING.SMOOTH)
                    {
                        NormalSolver.RecalculateNormals(mf.mesh, 60);
                    }
                    else
                    {
                        mf.mesh.RecalculateNormals();
                    }

                    var matrix = node.GetPositionMatrix();
                    nodeObj.transform.position = matrix.ExtractPosition();
                    var rotation = matrix.ExtractRotation();
                    nodeObj.transform.rotation   = rotation;
                    nodeObj.transform.localScale = matrix.ExtractScale();

                    var properties = nodeObj.AddComponent <NodeProperties>();
                    properties.nodeId     = nodeId;
                    properties.mainName   = model.rsm.mainNode.name;
                    properties.parentName = node.parentName;

                    if (node.posKeyframes.Count > 0 || node.rotKeyframes.Count > 0)
                    {
                        nodeObj.AddComponent <NodeAnimation>().nodeId = nodeId;
                        anims.Add(nodeId, new AnimProperties()
                        {
                            posKeyframes = node.posKeyframes,
                            rotKeyframes = node.rotKeyframes,
                            animLen      = model.rsm.animLen,
                            baseRotation = rotation,
                            isChild      = properties.isChild
                        });
                    }

                    nodeId++;
                }
            }

            modelObj.SetActive(false);

            //instantiate model
            for (int i = 0; i < model.rsm.instances.Count; i++)
            {
                GameObject instanceObj;
                if (i == model.rsm.instances.Count - 1)
                {
                    //last instance
                    instanceObj = modelObj;
                }
                else
                {
                    instanceObj = UnityEngine.Object.Instantiate(modelObj);
                }

                instanceObj.transform.parent = parent.transform;
                instanceObj.name            += "[" + i + "]";

                RSW.ModelDescriptor descriptor = model.rsm.instances[i];

                instanceObj.transform.Rotate(Vector3.forward, -descriptor.rotation[2]);
                instanceObj.transform.Rotate(Vector3.right, -descriptor.rotation[0]);
                instanceObj.transform.Rotate(Vector3.up, descriptor.rotation[1]);

                Vector3 scale = new Vector3(descriptor.scale[0], -descriptor.scale[1], descriptor.scale[2]);
                instanceObj.transform.localScale = scale;

                //avoid z fighting between models
                float xRandom = UnityEngine.Random.Range(-0.002f, 0.002f);
                float yRandom = UnityEngine.Random.Range(-0.002f, 0.002f);
                float zRandom = UnityEngine.Random.Range(-0.002f, 0.002f);

                Vector3 position = new Vector3(descriptor.position[0] + xRandom, descriptor.position[1] + yRandom, descriptor.position[2] + zRandom);
                position.x += MapRenderer.width;
                position.y *= -1;
                position.z += MapRenderer.height;
                instanceObj.transform.position = position;

                //setup hierarchy
                var propertiesComponents = instanceObj.GetComponentsInChildren <NodeProperties>();
                foreach (var properties in propertiesComponents)
                {
                    if (properties.isChild)
                    {
                        var nodeParent = instanceObj.transform.FindRecursive(properties.parentName);
                        properties.transform.parent = nodeParent;
                    }
                }

                //setup animations
                var animComponents = instanceObj.GetComponentsInChildren <NodeAnimation>();
                foreach (var animComponent in animComponents)
                {
                    var properties = anims[animComponent.nodeId];
                    animComponent.Initialize(properties);
                }

                instanceObj.SetActive(true);
            }
        }

        anims.Clear();
    }
Esempio n. 15
0
    /// <summary>
    /// Extend mesh along normal
    /// </summary>
    void Deform()
    {
        var mesh = meshFilter.sharedMesh;

        var vs     = new Vector3[baseVertices.Length];
        var colors = new Color[baseVertices.Length];
        //var vs = mesh.vertices;

        var offsetX = speed * time + seedX;
        var offsetY = speed * time + seedY;
        var offsetZ = speed * time + seedZ;

        // compute min and max height
        float min = 100, max = -100;

        for (var i = 0; i < vs.Length; ++i)
        {
            var u   = baseVertices [i];
            var inX = u.x;
            var inY = u.y;
            var inZ = u.z;

            float h = noise.SampleNoise(inX, inY, inZ, offsetX, offsetY, offsetZ);

            min = Mathf.Min(min, h);
            max = Mathf.Max(max, h);
        }

        // compute actual height
        for (var i = 0; i < vs.Length; ++i)
        {
            var u = baseVertices [i];
            var v = vs [i];

            var inX = u.x;
            var inY = u.y;
            var inZ = u.z;

            float h = noise.SampleNoise(inX, inY, inZ, offsetX, offsetY, offsetZ);

            // re-scale, so delta will always be between 0 and 1
            h = (h - min) / (max - min);


            int bi    = biomes.Length - 1;
            var realH = 0.0f;
            for (var b = 0; b < biomes.Length; ++b)
            {
                h     -= biomes [b].height;
                realH += biomes [b].scale;
                if (h < 0)
                {
                    bi = b;

                    //var dh = h - baseH;
                    //h = baseH; //+ biomes [bi].scale;
                    break;
                }
            }
            var biome = biomes [bi];
            colors [i] = biome.color;


            // randomly move along the normal
            var n = baseNormals [i];
            v = u + realH * n;

            vs [i] = v;
        }

        mesh.vertices = vs;
        mesh.colors   = colors;

        //mesh.RecalculateNormals ();
        NormalSolver.RecalculateNormals(mesh, 0);
        mesh.RecalculateTangents();
        mesh.RecalculateBounds();
    }
    void Start()
    {
        RaycastHit hit;

        if (Physics.Raycast(GetComponent <MeshRenderer>().bounds.center, Vector3.down, out hit, 200f))
        {
            if (hit.transform.tag == collisonTag)
            {
                if (deformMesh)
                {
                    // For each vertex, we raycast down and add an offset
                    MeshFilter meshFilter = GetComponent <MeshFilter>();
                    Mesh       mesh       = meshFilter.mesh;
                    Vector3[]  vertices   = mesh.vertices;

                    for (int i = 0; i < vertices.Length; i++)
                    {
                        // World positon of the vertex
                        Vector3 worldPositionVertex = transform.TransformPoint(vertices[i]);

                        RaycastHit vertexHit;

                        if (Physics.Raycast(worldPositionVertex, Vector3.down, out vertexHit, 300f, deformLayerMask))
                        {
                            float baseHeight = vertices[i].y;
                            vertices[i] -= new Vector3(0f, vertexHit.distance - baseHeight, 0f);
                        }
                        else
                        {
                            float baseHeight = vertices[i].y;
                            vertices[i] -= new Vector3(0f, 100f - baseHeight, 0f);
                        }
                    }
                    mesh.vertices = vertices;
                    mesh.RecalculateBounds();
                    mesh.RecalculateNormals();
                    NormalSolver.RecalculateNormals(mesh, 90f);
                    meshFilter.mesh = mesh;

                    gameObject.AddComponent <BoxCollider>();
                }
                else
                {
                    transform.position = new Vector3(transform.position.x, hit.point.y, transform.position.z);
                }

                // Misc Additonal

                if (useGroundColor)
                {
                    // we fetch color data from the terrain

                    MeshFilter filter   = hit.transform.gameObject.GetComponent <MeshFilter>();
                    Mesh       mesh     = filter.mesh;
                    Color[]    colors   = mesh.colors;
                    Vector3[]  vertices = mesh.vertices;

                    Color finalGrassColor = Color.white;
                    float closestDistance = 1000f;


                    for (int i = 0; i < vertices.Length; i++)
                    {
                        Vector3 worldPositionVertex = transform.TransformPoint(vertices[i]);
                        float   distancce           = Vector3.Distance(transform.position, worldPositionVertex);

                        if (distancce < closestDistance)
                        {
                            closestDistance = distancce;
                            finalGrassColor = colors[i];
                        }
                    }

                    // now we color our actual mesh

                    filter = gameObject.GetComponent <MeshFilter>();
                    mesh   = filter.mesh;
                    colors = mesh.colors;

                    for (int i = 0; i < colors.Length; i++)
                    {
                        colors[i] = new Color(finalGrassColor.r, finalGrassColor.g, finalGrassColor.b, colors[i].a);
                    }

                    mesh.colors = colors;
                    filter.mesh = mesh;
                }

                if (orientToSurfaceNormal)
                {
                    Vector3 lookAt = Vector3.Cross(-hit.normal, transform.right);
                    lookAt             = lookAt.y < 0 ? -lookAt : lookAt;
                    transform.rotation = Quaternion.LookRotation(hit.point + lookAt, hit.normal);
                }

                if (randomYRotation)
                {
                    transform.Rotate(new Vector3(0f, Random.value * 360, 0f), Space.Self);
                }
            }
            else
            {
                Destroy(this.gameObject);
            }
        }
    }
Esempio n. 17
0
    public void End()
    {
        foreach (var prim in primitives)
        {
            prim.End();
        }

        var idx_base        = 0;
        var vertices        = new List <Vector3> ();
        var triangles       = new List <int> ();
        var submeshes_count = 0;
        var colors          = new List <Color32> ();

        foreach (var prim in primitives)
        {
            vertices.AddRange(prim.vertices);
            triangles.AddRange(prim.triangles.Select(e => e + idx_base).ToList());
            submeshes_count += prim.submeshes.Count;
            colors.AddRange(prim.vcolors);
            idx_base += prim.vertices.Count;
        }

        /*
         * Manager.DebugLog ("----------");
         * Manager.DebugLog ("End:" + name);
         * Manager.DebugLog ("total size of vertices = " + vertices.Count);
         * Manager.DebugLog ("total size of triangles = " + triangles.Count);
         * Manager.DebugLog ("total size of colors = " + colors.Count);
         * Manager.DebugLog ("total size of submeshes = " + submeshes_count);
         *
         * foreach (var prim in primitives) {
         *      Manager.DebugLog ("----------");
         *      Manager.DebugLog (prim.name);
         *      Manager.DebugLog ("size of vertices = " + prim.vertices.Count);
         *      Manager.DebugLog ("size of triangles = " + prim.triangles.Count);
         *      Manager.DebugLog ("size of colorss = " + prim.vcolors.Count);
         *      Manager.DebugLog ("sizeof submeshes = " + prim.submeshes.Count);
         * }
         */

        var mesh = new Mesh();

        mesh.name      = name;
        mesh.vertices  = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.colors32  = colors.ToArray();

        GetComponent <MeshFilter> ().sharedMesh = mesh;

        var i = 0;

        idx_base = 0;
        var materials = new Material[submeshes_count];

        mesh.subMeshCount = submeshes_count;
        foreach (var prim in primitives)
        {
            foreach (var subm in prim.submeshes)
            {
                if (subm.pen.shaderType == Pen.ShaderType.SingleSided)
                {
                    materials [i] = material_singleSided;
                }
                else if (subm.pen.shaderType == Pen.ShaderType.DoubleSided)
                {
                    materials [i] = material_doubleSided;
                }
                else if (subm.pen.shaderType == Pen.ShaderType.VertexColors)
                {
                    materials [i] = material_vertexColors;
                }

                mesh.SetTriangles(subm.triangles.Select(e => e + idx_base).ToList(), i);
                ++i;
            }

            idx_base += prim.vertices.Count;
        }

        GetComponent <Renderer> ().materials = materials;

        i = 0;
        foreach (var prim in primitives)
        {
            foreach (var subm in prim.submeshes)
            {
                GetComponent <Renderer> ().materials [i].SetColor("_FColor", subm.pen.frontColor);
                GetComponent <Renderer> ().materials [i].SetColor("_BColor", subm.pen.backColor);
                ++i;
            }
        }

        //mesh.RecalculateNormals();
        NormalSolver.RecalculateNormals(mesh, 60f);        // see http://schemingdeveloper.com/2017/03/26/better-method-recalculate-normals-unity-part-2/
        mesh.RecalculateBounds();

        rendering   = false;
        initialized = false;
    }
Esempio n. 18
0
    public void generateMesh()
    {
        this.meshCached = true;

        if (this.gameObject.GetComponent <MeshFilter>() == null)
        {
            this.gameObject.AddComponent <MeshFilter>();
        }

        MeshRenderer render = this.gameObject.GetComponent <MeshRenderer>();

        if (render == null)
        {
            render          = this.gameObject.AddComponent <MeshRenderer>();
            render.material = new Material(Shader.Find("Clayxel/ClayxelMeshShader"));
        }

        render.sharedMaterial.SetFloat("_Glossiness", this.materialSmoothness);
        render.sharedMaterial.SetFloat("_Metallic", this.materialMetallic);
        render.sharedMaterial.SetColor("_Emission", this.materialEmission);

        ComputeBuffer meshIndicesBuffer = new ComputeBuffer(this.chunkMaxOutPoints * 6, sizeof(float) * 3, ComputeBufferType.Counter);

        Clayxel.claycoreCompute.SetBuffer((int)Kernels.genMesh, "meshOutIndices", meshIndicesBuffer);

        ComputeBuffer meshVertsBuffer = new ComputeBuffer(this.chunkMaxOutPoints, sizeof(float) * 3, ComputeBufferType.Counter);

        Clayxel.claycoreCompute.SetBuffer((int)Kernels.genMesh, "meshOutPoints", meshVertsBuffer);

        ComputeBuffer meshColorsBuffer = new ComputeBuffer(this.chunkMaxOutPoints, sizeof(float) * 4);

        Clayxel.claycoreCompute.SetBuffer((int)Kernels.genMesh, "meshOutColors", meshColorsBuffer);

        List <Vector3> totalVertices = new List <Vector3>();
        List <int>     totalIndices  = new List <int>();
        List <Color>   totalColors   = new List <Color>();

        int totalNumVerts = 0;

        this.mesh             = new Mesh();
        this.mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

        this.switchComputeData();

        this.updateSolids();

        Clayxel.claycoreCompute.SetInt("numSolids", this.clayObjects.Count);
        Clayxel.claycoreCompute.SetFloat("chunkSize", (float)this.chunkSize);

        Clayxel.claycoreCompute.SetFloat("surfaceBoundaryThreshold", 4.0f);         // compute more cells than needed to make sure we don't leave holes in the final mesh

        for (int chunkIt = 0; chunkIt < this.numChunks; ++chunkIt)
        {
            ClayxelChunk chunk = this.chunks[chunkIt];

            meshIndicesBuffer.SetCounterValue(0);
            meshVertsBuffer.SetCounterValue(0);

            this.computeChunkPoints(chunk);

            // dirty hack, calling this a second time will make sure we don't skip cells and there's no holes in the mesh
            this.computeChunkPoints(chunk);

            Clayxel.claycoreCompute.SetInt("outMeshIndexOffset", totalNumVerts);
            Clayxel.claycoreCompute.Dispatch((int)Kernels.genMesh, 16, 16, 16);

            Clayxel.claycoreCompute.Dispatch((int)Kernels.clearChunkData, this.numThreadsCompute6, this.numThreadsCompute6, this.numThreadsCompute6);

            int numVerts = this.getBufferCount(meshVertsBuffer);
            int numQuads = this.getBufferCount(meshIndicesBuffer) * 3;

            totalNumVerts += numVerts;

            Vector3[] vertices = new Vector3[numVerts];
            meshVertsBuffer.GetData(vertices);

            int[] indices = new int[numQuads];
            meshIndicesBuffer.GetData(indices);

            Color[] colors = new Color[numVerts];
            meshColorsBuffer.GetData(colors);

            totalVertices.AddRange(vertices);
            totalIndices.AddRange(indices);
            totalColors.AddRange(colors);
        }

        mesh.vertices  = totalVertices.ToArray();
        mesh.colors    = totalColors.ToArray();
        mesh.triangles = totalIndices.ToArray();

        this.mesh.Optimize();
        // this.mesh.RecalculateNormals();
        NormalSolver.RecalculateNormals(this.mesh, 120.0f);
        this.gameObject.GetComponent <MeshFilter>().mesh = this.mesh;

        meshIndicesBuffer.Release();
        meshVertsBuffer.Release();
        meshColorsBuffer.Release();

        this.releaseBuffers();
        this.needsInit = false;
    }
 public void RecacluateNormals(float angle = 60)
 {
     NormalSolver.RecalculateNormals(m_meshFilter.sharedMesh, angle);
 }
        /// <summary>
        /// This will update all verticies with a lerp from originalVertices to inflatedVertices depending on the inflationSize config
        /// Only modifies belly verticies, and if none are found, no action taken.
        /// </summary>
        /// <param name="mesh">Target mesh to update</param>
        /// <param name="renderKey">The Shared Mesh render name, used in dictionary keys to get the current verticie values</param>
        /// <returns>Will return True if any verticies are changed</returns>
        internal bool ApplyInflation(SkinnedMeshRenderer smr, string renderKey)
        {
            var infSize = infConfig.inflationSize;

            //Only inflate if the value is above 0
            if (infSize.Equals(null) || infSize == 0)
            {
                return(false);
            }

            //Create an instance of sharedMesh so we don't modify the mesh shared between characters
            var meshCopy = (Mesh)UnityEngine.Object.Instantiate(smr.sharedMesh);

            smr.sharedMesh = meshCopy;

            var sharedMesh = smr.sharedMesh;

            //Some meshes are not readable and cant be touched...  Nothing I can do about this right now
            if (!sharedMesh.isReadable)
            {
                PregnancyPlusPlugin.errorCodeCtrl.LogErrorCode(ChaControl.chaID, ErrorCode.PregPlus_MeshNotReadable,
                                                               $"ApplyInflation > smr '{renderKey}' is not readable, skipping");
                return(false);
            }

            //Check key exists in dict, remove it if it does not
            var exists = originalVertices.TryGetValue(renderKey, out var val);

            if (!exists)
            {
                if (PregnancyPlusPlugin.DebugLog.Value)
                {
                    PregnancyPlusPlugin.Logger.LogInfo(
                        $"ApplyInflation > smr '{renderKey}' does not exists, skipping");
                }
                RemoveRenderKey(renderKey);
                return(false);
            }

            //Get computed mesh values
            var origVert       = originalVertices[renderKey];
            var currentVert    = currentVertices[renderKey];
            var bellyVertIndex = bellyVerticieIndexes[renderKey];

            if (bellyVertIndex.Length == 0)
            {
                return(false);
            }
            infConfigHistory.inflationSize = infSize;

            var currentVertLength = currentVert.Length;

            //Apply lerp morph for each changed verticie
            for (int i = 0; i < currentVertLength; i++)
            {
                //If not a belly index verticie then skip the morph
                if (!PregnancyPlusPlugin.DebugVerts.Value && !bellyVertIndex[i])
                {
                    continue;
                }

                //Set the lerp size of the belly based on the users slider value
                currentVert[i] = Vector3.Lerp(origVert[i], inflatedVertices[renderKey][i], (infSize / 40));
            }

            //Check that the mesh did not change behind the scenes.  It will have a different vert count if it did (possible to be the same though...)
            if (currentVert.Length != sharedMesh.vertexCount)
            {
                PregnancyPlusPlugin.errorCodeCtrl.LogErrorCode(ChaControl.chaID, ErrorCode.PregPlus_IncorrectVertCount,
                                                               $"ApplyInflation > smr.sharedMesh '{renderKey}' has incorrect vert count {currentVert.Length}|{sharedMesh.vertexCount}");
                return(false);
            }

            if (PregnancyPlusPlugin.DebugLog.Value)
            {
                PregnancyPlusPlugin.Logger.LogInfo($" mesh did ApplyInflation > {smr.name}");
            }

            sharedMesh.vertices = currentVert;
            sharedMesh.RecalculateBounds();
            NormalSolver.RecalculateNormals(sharedMesh, 40f, alteredVerticieIndexes[renderKey]);
            //sharedMesh.RecalculateNormals();  //old way that leaves skin seams at UV boundaries
            sharedMesh.RecalculateTangents();

            return(true);
        }
Esempio n. 21
0
    void UpdateVertices()
    {
        UnityEngine.Debug.Log("Update Vertices");

        Stopwatch sw = new Stopwatch();

        sw.Start();

        if (dic_VertexForce.Count == 0)
        {
            _mesh.vertices = originalVertices;
            _mesh.RecalculateNormals();
            NormalSolver.RecalculateNormals(_mesh, 30);
            return;
        }

        Vector3[,] offsets = new Vector3[Masses.Count, dic_VertexForce.Count];

        Dictionary <int, Vector3> .Enumerator it = dic_VertexForce.GetEnumerator();
        int forceIdx = 0;

        while (it.MoveNext())
        {
            int     vertexIdx = it.Current.Key;
            Vector3 force     = it.Current.Value;

            offsets[vertexIdx, forceIdx++] = force;
        }


        // 多组质点弹簧遍历
        it = dic_VertexForce.GetEnumerator();
        Queue <int>   masses = new Queue <int> ();
        HashSet <int> mark   = new HashSet <int> ();

        forceIdx = 0;
        while (it.MoveNext())
        {
            int     vidx_force = it.Current.Key;
            Vector3 force      = it.Current.Value;

            offsets[vidx_force, forceIdx] = force;

            masses.Clear();
            mark.Clear();
            masses.Enqueue(vidx_force);
            mark.Add(vidx_force);

            // 一组质点弹簧遍历
            while (masses.Count > 0)
            {
                int     vidx  = masses.Dequeue();
                Vector3 delta = offsets[vidx, forceIdx];

                // 遍历此节点所有链接点
                Dictionary <int, float>             edge = MassSprings [vidx];
                Dictionary <int, float> .Enumerator iter = edge.GetEnumerator();
                while (iter.MoveNext())
                {
                    int   idx   = iter.Current.Key;
                    float value = iter.Current.Value;

                    int key = vidx > idx ? vidx | (idx << 16) : (vidx << 16) | idx;
                    if (mark.Contains(key))
                    {
                        continue;
                    }

                    Vector3 v = delta / (1 + value / kViscosity);

                    if (v.magnitude <= kThresholdZero)
                    {
                        continue;
                    }

                    if (!dic_VertexForce.ContainsKey(idx) && offsets[idx, forceIdx].sqrMagnitude < v.sqrMagnitude)
                    {
                        offsets[idx, forceIdx] = v;

                        masses.Enqueue(idx);
                    }
                }

                iter = edge.GetEnumerator();
                while (iter.MoveNext())
                {
                    int idx = iter.Current.Key;
                    int key = vidx > idx ? vidx | (idx << 16) : (vidx << 16) | idx;
                    mark.Add(key);
                }
            }

            forceIdx++;
        }


        sw.Stop();
        //UnityEngine.Debug.LogFormat ("using {0}", sw.ElapsedMilliseconds);


        // 计算各顶点偏移量
        for (int i = 0; i < offsets.GetLength(0); i++)
        {
            Vector3 result = Vector3.zero;

            // 计算改顶点最终形变量(x,y,z)
            for (int j = 0; j < 3; j++)
            {
                float positive = 0f;
                float negative = 0f;

                for (int k = 0; k < dic_VertexForce.Count; k++)
                {
                    Vector3 offset = offsets [i, k];
                    float   v      = offset [j];
                    if (v > 0 && v > positive)
                    {
                        positive = v;
                    }
                    else if (v < 0 && v < negative)
                    {
                        negative = v;
                    }
                }

                result [j] = positive + negative;
            }

            // 最终结果保存在第一个位置
            offsets [i, 0] = result;
        }

        // 计算出最新的顶点位置
        for (int i = 0; i < Masses.Count; i++)
        {
            MassPoint mass = Masses [i];

            for (int j = 0; j < mass.vertices.Count; j++)
            {
                int vid = mass.vertices [j];
                displacedVertices [vid] = originalVertices [vid] + offsets [i, 0];
            }
        }

        _mesh.vertices = displacedVertices;
        _mesh.RecalculateNormals();
        NormalSolver.RecalculateNormals(_mesh, 30);
    }
Esempio n. 22
0
    public void UpdateChunkMesh(Chunk chunk, bool?blocking = null)
    {
        int   numVoxelsPerAxis  = numPointsPerAxis - 1;
        int   numThreadsPerAxis = Mathf.CeilToInt(numVoxelsPerAxis / (float)threadGroupSize);
        float pointSpacing      = boundsSize / (numPointsPerAxis - 1);

        bool blockGpu = blocking ?? blockingGpu;

        Vector3Int coord  = chunk.coord;
        Vector3    centre = CentreFromCoord(coord);

        Vector3 worldBounds = new Vector3(numChunks.x, numChunks.y, numChunks.z) * boundsSize;

        densityGenerator.Generate(pointsBuffer, numPointsPerAxis, boundsSize, worldBounds, centre, offset, pointSpacing);

        void SetupShader()
        {
            triangleBuffer.SetCounterValue(0);
            shader.SetBuffer(0, "points", pointsBuffer);
            shader.SetBuffer(0, "triangles", triangleBuffer);
            shader.SetInt("numPointsPerAxis", numPointsPerAxis);
            shader.SetFloat("isoLevel", isoLevel);

            shader.Dispatch(0, numThreadsPerAxis, numThreadsPerAxis, numThreadsPerAxis);
        }

        ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, 0);

        void HandleReadBack()
        {
            int[] triCountArray = { 0 };
            triCountBuffer.GetData(triCountArray);

            int numTris = triCountArray[0];

            if (numTris > maxTris || tris == null || vertices == null || meshTriangles == null)
            {
                maxTris       = numTris;
                tris          = new Triangle[numTris];
                vertices      = new Vector3[numTris * 3];
                meshTriangles = new int[numTris * 3];
            }

            // Get triangle data from shader
            triangleBuffer.GetData(tris, 0, 0, numTris);

            Mesh mesh = chunk.mesh;

            mesh.Clear();

            for (int i = 0; i < numTris; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    meshTriangles[i * 3 + j] = i * 3 + j;
                    vertices[i * 3 + j]      = tris[i][j];
                }
            }
            mesh.vertices  = vertices;
            mesh.triangles = meshTriangles;
            var scale = chunk.GetComponent <Transform>().localScale;

            mesh.SetUVs(0, UvCalculator.CalculateUVs(vertices, scale.magnitude));
            NormalSolver.RecalculateNormals(mesh, normalDegrees);

            chunk.UpdateColliders();
        }

        if (!blockGpu)
        {
            chunk.asyncOp0 = null;
            chunk.asyncOp1 = null;
            chunk.asyncOp2 = null;
            var async0 = AsyncGPUReadback.Request(pointsBuffer, delegate(AsyncGPUReadbackRequest a0)
            {
                SetupShader();
                var async1 = AsyncGPUReadback.Request(triangleBuffer, delegate(AsyncGPUReadbackRequest a1)
                {
                    // Get number of triangles in the triangle buffer
                    ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, 0);
                    var async2 = AsyncGPUReadback.Request(triCountBuffer, delegate(AsyncGPUReadbackRequest a2)
                    {
                        HandleReadBack();
                    });
                    chunk.asyncOp2 = async2;
                });
                chunk.asyncOp1 = async1;
            });
            chunk.asyncOp0 = async0;
        }
        else
        {
            SetupShader();
            ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, 0);
            HandleReadBack();
        }
    }
Esempio n. 23
0
    public Mesh ExtrudeMeshFromPoints(Vector2[] points2d)
    {
        if (isClockwise(points2d))
        {
            // Debug.Log("It's clockwise!");
            System.Array.Reverse(points2d);
        }

        Mesh mesh = new Mesh();

        Vector3[] vertices = new Vector3[4 * points2d.Length];

        // Vertex list
        int sideOffset = 2 * points2d.Length;

        for (int i = 0; i < points2d.Length; i++)
        {
            Vector2 point = points2d[i];
            vertices[i] = new Vector3(point.x, point.y, 0);
            vertices[points2d.Length + i] = new Vector3(point.x, point.y, extrusionDepth);
            vertices[sideOffset + i]      = new Vector3(point.x, point.y, 0);
            vertices[sideOffset + points2d.Length + i] = new Vector3(point.x, point.y, extrusionDepth);
        }

        Triangulator tr = new Triangulator(points2d);

        int[] backIndices = tr.Triangulate();
        int[] topIndices  = GetReverseTriangles(backIndices, points2d.Length);

        int[] sideIndices = new int[6 * points2d.Length];

        //		 sides
        for (int i = 0; i < points2d.Length - 1; i++)
        {
            sideIndices[6 * i + 0] = sideOffset + i;
            sideIndices[6 * i + 1] = sideOffset + i + 1;
            sideIndices[6 * i + 2] = sideOffset + points2d.Length + i;

            sideIndices[6 * i + 3] = sideOffset + points2d.Length + i;
            sideIndices[6 * i + 4] = sideOffset + i + 1;
            sideIndices[6 * i + 5] = sideOffset + points2d.Length + i + 1;
        }
        sideIndices[sideIndices.Length - 6] = sideOffset + points2d.Length - 1;
        sideIndices[sideIndices.Length - 5] = sideOffset + 0;
        sideIndices[sideIndices.Length - 4] = sideOffset + 2 * points2d.Length - 1;

        sideIndices[sideIndices.Length - 3] = sideOffset + 2 * points2d.Length - 1;
        sideIndices[sideIndices.Length - 2] = sideOffset + 0;
        sideIndices[sideIndices.Length - 1] = sideOffset + points2d.Length;

        //if (ShouldFlipPerimeter(sideIndices, points2d.Length))
        // {
        //     sideIndices = GetReverseTriangles (sideIndices, 0);
        //     //return ExtrudeMeshFromPoints(points2d);
        // }

        // put it all together
        int[] triangles = new int[topIndices.Length + backIndices.Length + sideIndices.Length];
        topIndices.CopyTo(triangles, 0);
        backIndices.CopyTo(triangles, topIndices.Length);
        sideIndices.CopyTo(triangles, topIndices.Length + backIndices.Length);

        //		// UVs (texture mapping points) - Just half-assing for now. Easy to improve later!
        //		Vector2[] uv = new Vector2[vertices.Length];
        //		for (int i = 0; i < topPtOffset; i += 2) {
        //			uv[i + 0] = new Vector2((float)i/topPtOffset, 0);
        //			uv[i + 1] = new Vector2((float)i/topPtOffset, 1);
        //		}
        //		for (int i = topPtOffset; i < bottomPtOffset; i++) {
        //			uv[i] = new Vector2(0,0);
        //		}
        //		for (int i = bottomPtOffset; i < vertices.Length; i++) {
        //			uv[i] = new Vector2(0,0);
        //		}

        mesh.vertices  = vertices;
        mesh.triangles = triangles;
        NormalSolver.RecalculateNormals(mesh, 60f);
        //		mesh.uv = uv;
        mesh.Optimize();

        return(mesh);
    }