Exemple #1
0
        /// <summary>
        /// will set the color if our vertex color is black (IE: not already set), and no adjacent verticies are using that color
        /// if color already set to the same color, will also return true
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public bool TrySetAvailableColor(Color c, bool force = false)
        {
            if (force == true)
            {
                mdt.SetVertexColor(vertIdx, c);
                return(true);
            }
            var currentColor = mdt.GetVertexColor(vertIdx);

            if (currentColor == c)
            {
                return(true);
            }
            //
            if (currentColor != Colors.Transparent)
            {
                return(false);
            }
            foreach (var adjIdx in adjacentVerticies)
            {
                var adjColor = mdt.GetVertexColor(adjIdx);
                if (adjColor == c)
                {
                    return(false);
                }
            }
            mdt.SetVertexColor(vertIdx, c);
            return(true);
        }
Exemple #2
0
    /// <summary>
    /// 4th attempt:  set color by most linked, not by color
    /// </summary>
    /// <param name="mdt"></param>
    public static void _SetVertexColorToBarycentric(MeshDataTool mdt)
    {
        //store info about our verticies into an array
        var vertStorage = new VertexInfo[mdt.GetVertexCount()];

        for (var vertIdx = 0; vertIdx < vertStorage.Length; vertIdx++)
        {
            vertStorage[vertIdx] = new VertexInfo(vertIdx, mdt, vertStorage);
            //set vert color to alphaBlack
            mdt.SetVertexColor(vertIdx, Colors.Transparent);
        }

        //sort verticies by degree (number of edges).   defaults to highest first
        var sortedVerts = new List <VertexInfo>(vertStorage);

        sortedVerts.Sort();

        //color channels used for verticies.  3 is ideal, but aprox 10% of verts wont be colored.
        var colorChoices = new Color[] {
            //encode 5 channels as 20% red each.
            new Color(0.2f, 0, 0, 0),
            new Color(0.4f, 0, 0, 0),
            new Color(0.6f, 0, 0, 0),
            new Color(0.8f, 0, 0, 0),
            new Color(1f, 0, 0, 0)
        };


        //////////////  various algorithm choices.   best is _WELSH_POWELL_ADJUSTED
        //_GREEDY_FACE(sortedVerts, colorChoices, mdt);
        //_GREEDY_BASIC(sortedVerts, colorChoices, mdt);
        //_CYBERREALITY(sortedVerts, colorChoices, mdt);
        //_CYBERREALITY_EDIT(sortedVerts, colorChoices, mdt);
        _WELSH_POWELL_ADJUSTED(sortedVerts, colorChoices, mdt);
    }
Exemple #3
0
    /// <summary>
    /// 3rd attempt:  after researching a bit I realized this is a "graph coloring" problem: https://en.wikipedia.org/wiki/Graph_coloring
    /// nice overview of some here: https://github.com/Ajaypal91/Graph_Coloring_Algorithms_Implementation
    /// here we implement welsh-powell algorithm:  https://www.youtube.com/watch?v=CQIW2mLfG04
    /// </summary>
    /// <param name="mdt"></param>
    private static void _SetVertexColorToBarycentric_WP(MeshDataTool mdt)
    {
        //store info about our verticies into an array
        var vertStorage = new VertexInfo[mdt.GetVertexCount()];

        for (var vertIdx = 0; vertIdx < vertStorage.Length; vertIdx++)
        {
            vertStorage[vertIdx] = new VertexInfo(vertIdx, mdt, vertStorage);
            //set vert color to black
            mdt.SetVertexColor(vertIdx, Colors.Transparent);
        }

        //sort verticies by degree (number of edges).   defaults to highest first
        var sortedVerts = new List <VertexInfo>(vertStorage);

        sortedVerts.Sort();
        //verts.CopyTo(sortedVerts,0);
        //Array.Sort(sortedVerts);

        var colorChoices = new Color[] { Colors.Red, Colors.Green, Colors.Blue };

        foreach (var color in colorChoices)
        {
            //enumerate in reverse so we inspect our verticies with highest degree first (most edges)
            //and also lets us remove from the list directly
            for (int i = sortedVerts.Count - 1; i >= 0; i--)
            {
                var vertInfo = sortedVerts[i];
                if (vertInfo.TrySetAvailableColor(color))
                {
                    sortedVerts.RemoveAt(i);
                }
            }
        }

        //any remaining verts are uncolored!  bad.
        GD.Print($"Done building mesh.  Verticies uncolored count={sortedVerts.Count} / {mdt.GetVertexCount()}");

        //for any remaining verticies color alpha
        var alphaBlack = new Color(0, 0, 0, 0);

        for (int i = sortedVerts.Count - 1; i >= 0; i--)
        {
            var vertInfo = sortedVerts[i];
            mdt.SetVertexColor(vertInfo.vertIdx, alphaBlack);
        }
    }
Exemple #4
0
    /// <summary>
    /// cyberality's technique.  needs some optimization for use with big meshes.
    /// </summary>
    /// <param name="sortedVerts"></param>
    /// <param name="colorChoices"></param>
    /// <param name="mdt"></param>
    private static void _CYBERREALITY(List <VertexInfo> sortedVerts, Color[] colorChoices, MeshDataTool mdt)
    {
        var done       = new Dictionary <int, bool>();  //vertidx/isDone
        var bary       = new Dictionary <int, Color>(); //vertidx/color
        var rand       = new Random(0);
        var rand_color = new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble());
        var nors       = new Dictionary <int, (Vector3 normal, Color color)>();  //normalIdx/normal

        for (var j = 0; j < mdt.GetFaceCount(); j++)
        {
            var fid    = mdt.GetFaceVertex(j, 0);
            var nor    = mdt.GetVertexNormal(fid);
            var coords = new List <Color>()
            {
                Colors.Red, Colors.Green, Colors.Blue
            };
            foreach (var n in nors.Keys)
            {
                var dot = nor.Dot(nors[n].normal);
                if (dot == 1)
                {
                    rand_color = nors[n].color;
                }
                else
                {
                    rand_color = new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble());
                }
            }
            nors[fid] = (normal : nor, color : rand_color);
            for (var k = 0; k < 3; k++)
            {
                var vid = mdt.GetFaceVertex(j, k);
                if (bary.ContainsKey(vid))
                {
                    coords.Remove(bary[vid]);
                }
            }
            for (var i = 0; i < 3; i++)
            {
                var vid = mdt.GetFaceVertex(j, i);
                if (!done.ContainsKey(vid) || done[vid] != true)
                {
                    done[vid] = true;
                    var removal = Colors.Black;

                    var vert_0 = mdt.GetFaceVertex(j, 0);
                    var vert_1 = mdt.GetFaceVertex(j, 1);
                    var vert_2 = mdt.GetFaceVertex(j, 2);
                    var edge_a = mdt.GetVertex(vert_2).DirectionTo(mdt.GetVertex(vert_0));
                    var edge_b = mdt.GetVertex(vert_0).DirectionTo(mdt.GetVertex(vert_1));
                    var edge_c = mdt.GetVertex(vert_1).DirectionTo(mdt.GetVertex(vert_2));

                    if ((edge_a > edge_b) && (edge_a > edge_c))
                    {
                        removal.g = 1;
                    }
                    else if ((edge_b > edge_c) && (edge_b > edge_a))
                    {
                        removal.r = 1;
                    }
                    else
                    {
                        removal.b = 1;
                    }

                    if (coords.Count > 0)
                    {
                        var next = coords[0]; coords.RemoveAt(0);
                        bary[vid] = next + removal;
                    }
                    else
                    {
                        var coords2 = new List <Color>()
                        {
                            Colors.Red, Colors.Green, Colors.Blue
                        };

                        for (var m = 0; m < 3; m++)
                        {
                            if (m == i)
                            {
                                continue;
                            }
                            var vid2 = mdt.GetFaceVertex(j, m);
                            if (bary.ContainsKey(vid2))
                            {
                                coords2.Remove(bary[vid2]);
                            }
                            bary[vid] = coords2[0] + removal;                             //BUG?  coords was  checked to not have any....  maybe means coords2
                            coords2.RemoveAt(0);
                        }
                    }
                    mdt.SetVertexColor(vid, bary[vid]);
                }
            }
        }
    }
Exemple #5
0
    /// <summary>
    /// my edited version of Cyberality's technique.
    /// faster performance, about as good coverage as "greedy" algo.
    /// </summary>
    /// <param name="sortedVerts"></param>
    /// <param name="_colorChoices"></param>
    /// <param name="mdt"></param>
    private static void _CYBERREALITY_EDIT(List <VertexInfo> sortedVerts, Color[] _colorChoices, MeshDataTool mdt)
    {
        var done              = new Dictionary <int, bool>();  //vertidx/isDone
        var vertColorStorage  = new Dictionary <int, Color>(); //vertidx/color
        var rand              = new Random(0);
        var rand_color        = new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble());
        var faceVert0MetaInfo = new Dictionary <int, (Vector3 normal, Color color)>();        //normalIdx/normal

        for (var faceIdx = 0; faceIdx < mdt.GetFaceCount(); faceIdx++)
        {
            var faceVert0Idx  = mdt.GetFaceVertex(faceIdx, 0);
            var faceVert0Norm = mdt.GetVertexNormal(faceVert0Idx);
            var colorChoices  = new List <Color>()
            {
                Colors.Red, Colors.Green, Colors.Blue
            };
            //////JASON CLEANUP:  this code block isn't actually used in the algo...
            ////foreach (var n in faceVert0MetaInfo.Keys)
            ////{
            ////	var dot = faceVert0Norm.Dot(faceVert0MetaInfo[n].normal);
            ////	if (dot == 1)
            ////	{
            ////		rand_color = faceVert0MetaInfo[n].color;
            ////	}
            ////	else
            ////	{
            ////		rand_color = new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble());
            ////	}
            ////}
            ////faceVert0MetaInfo[faceVert0Idx] = (normal: faceVert0Norm, color: rand_color);


            //loop through all verts for the face, and remove colors from our colorChoices if a vert is already using it
            for (var faceVertId = 0; faceVertId < 3; faceVertId++)
            {
                var vertIdx = mdt.GetFaceVertex(faceIdx, faceVertId);
                if (vertColorStorage.ContainsKey(vertIdx))
                {
                    colorChoices.Remove(vertColorStorage[vertIdx]);
                }
            }


            for (var faceVertId = 0; faceVertId < 3; faceVertId++)
            {
                var vertIdx = mdt.GetFaceVertex(faceIdx, faceVertId);
                if (!done.ContainsKey(vertIdx) || done[vertIdx] != true)
                {
                    done[vertIdx] = true;
                    var removal = Colors.Black;

                    var vert_0 = mdt.GetFaceVertex(faceIdx, 0);
                    var vert_1 = mdt.GetFaceVertex(faceIdx, 1);
                    var vert_2 = mdt.GetFaceVertex(faceIdx, 2);
                    var edge_a = mdt.GetVertex(vert_2).DirectionTo(mdt.GetVertex(vert_0));
                    var edge_b = mdt.GetVertex(vert_0).DirectionTo(mdt.GetVertex(vert_1));
                    var edge_c = mdt.GetVertex(vert_1).DirectionTo(mdt.GetVertex(vert_2));

                    if ((edge_a > edge_b) && (edge_a > edge_c))
                    {
                        removal.g = 1;
                    }
                    else if ((edge_b > edge_c) && (edge_b > edge_a))
                    {
                        removal.r = 1;
                    }
                    else
                    {
                        removal.b = 1;
                    }

                    if (colorChoices.Count > 0)
                    {
                        var next = colorChoices[0]; colorChoices.RemoveAt(0);
                        vertColorStorage[vertIdx] = next + removal;
                    }
                    //JASON CLEANUP:  this else will never trigger, as there are only 3 verticies
                    else
                    {
                        GD.Print("in else!");
                        var coords2 = new List <Color>()
                        {
                            Colors.Red, Colors.Green, Colors.Blue
                        };

                        for (var m = 0; m < 3; m++)
                        {
                            if (m == faceVertId)
                            {
                                continue;
                            }
                            var vid2 = mdt.GetFaceVertex(faceIdx, m);
                            if (vertColorStorage.ContainsKey(vid2))
                            {
                                coords2.Remove(vertColorStorage[vid2]);
                            }
                            vertColorStorage[vertIdx] = coords2[0] + removal;                             //BUG?  coords was  checked to not have any....  maybe means coords2
                            coords2.RemoveAt(0);
                        }
                    }
                    mdt.SetVertexColor(vertIdx, vertColorStorage[vertIdx]);
                }
            }
        }
    }
Exemple #6
0
    /// <summary>
    ///
    /// </summary>
    /// <param name="sortedVerts"></param>
    /// <param name="colorChoices"></param>
    /// <param name="mdt"></param>
    private static void _WELSH_POWELL_ADJUSTED(List <VertexInfo> sortedVerts, Color[] colorChoices, MeshDataTool mdt)
    {
        for (var h = 0; h < colorChoices.Length; h++)
        {
            var color = colorChoices[h];


            //enumerate in reverse so we inspect our verticies with highest degree first (most edges)
            //and also lets us remove from the list directly
            for (int i = sortedVerts.Count - 1; i >= 0; i--)
            {
                //if we remove too many, reset our index.   this means we might invoke this loop on an element more than once.
                //but that's ok as it doesn't have negative consiquences.
                if (i >= sortedVerts.Count)
                {
                    i = sortedVerts.Count - 1;
                }


                var vertInfo = sortedVerts[i];
                if (vertInfo.TrySetAvailableColor(color))
                {
                    sortedVerts.RemoveAt(i);

                    //preemptively try to set adjacent and adjadj with related colors
                    foreach (var adj0Vert in vertInfo.GetAdjacentVertInfo())
                    {
                        //JASON OPTIMIZATION: reduces non-colored by aprox 8% on sibnek 100k vert mesh.
                        foreach (var adj1Vert in adj0Vert.GetAdjacentVertInfo())
                        {
                            if (adj1Vert.adjacentVerticies.Length > vertInfo.adjacentVerticies.Length * 0.75)
                            {
                                adj1Vert.TrySetAvailableColor(color);
                            }
                        }
                    }
                }
            }
        }
        //any remaining verts are uncolored!  bad.
        GD.Print($"Done building mesh.  Verticies uncolored count={sortedVerts.Count} / {mdt.GetVertexCount()}");

        //loop through all faces, finding the vertex for the longest edge,
        //and encode that into green channel = 0.1;
        //may be used by the shader to remove interrior edges
        var faceCount = mdt.GetFaceCount();

        for (var faceIdx = 0; faceIdx < faceCount; faceIdx++)
        {
            var vertIdx0 = mdt.GetFaceVertex(faceIdx, 0);
            var vertIdx1 = mdt.GetFaceVertex(faceIdx, 1);
            var vertIdx2 = mdt.GetFaceVertex(faceIdx, 2);
            var vert0    = mdt.GetVertex(vertIdx0);
            var vert1    = mdt.GetVertex(vertIdx1);
            var vert2    = mdt.GetVertex(vertIdx2);

            var edgeLen1 = vert0.DistanceTo(vert1);
            var edgeLen2 = vert0.DistanceTo(vert2);
            var edgeLen3 = vert1.DistanceTo(vert2);

            int longestEdgeVertIdx = -1;
            if (edgeLen1 > edgeLen2 && edgeLen1 > edgeLen3)
            {
                longestEdgeVertIdx = vertIdx2;
            }
            if (edgeLen2 > edgeLen1 && edgeLen2 > edgeLen3)
            {
                longestEdgeVertIdx = vertIdx1;
            }
            if (edgeLen3 > edgeLen1 && edgeLen3 > edgeLen2)
            {
                longestEdgeVertIdx = vertIdx0;
            }
            if (longestEdgeVertIdx != -1)
            {
                var curCol = mdt.GetVertexColor(longestEdgeVertIdx);
                //encode that this vertext has longest edge (used in shader code)
                curCol.g += 0.1f;
                mdt.SetVertexColor(longestEdgeVertIdx, curCol);
            }
        }



        ////for any remaining verticies color alpha
        //var alphaBlack = new Color(0, 0, 0, 0);
        //for (int i = sortedVerts.Count - 1; i >= 0; i--)
        //{
        //	var vertInfo = sortedVerts[i];
        //	mdt.SetVertexColor(vertInfo.vertIdx, alphaBlack);
        //	//vertInfo.TrySetAvailableColor(Colors.White, true);
        //}
    }
Exemple #7
0
    public override void _Ready()
    {
        var mesh = new PlaneMesh();

        mesh.Size           = new Vector2(size, size);
        mesh.SubdivideDepth = 3;
        mesh.SubdivideWidth = (int)position.x == 0 ? (int)size : 3;

        var surface_tool = new SurfaceTool();

        surface_tool.CreateFrom(mesh, 0);
        var mesh_tool = new MeshDataTool();

        mesh_tool.CreateFromSurface(surface_tool.Commit(), 0);

        var biome = GetBiome(/*hydro_noise.GetNoise2dv(position / size), */ heat_noise.GetNoise2d(position.x / size / 10.0f, position.y));

        for (int i = 0; i < mesh_tool.GetVertexCount(); ++i)
        {
            var vertex            = mesh_tool.GetVertex(i);
            var vertex_global_pos = position + new Vector2(vertex.x, vertex.z);

            var height_noise_val = height_noise.GetNoise2dv(vertex_global_pos);
            vertex.y = height_noise_val * 20;
            var color_factor = (height_noise_val + 1) / 2.0f;

            var hydro_val = (int)Math.Round(hydro_noise.GetNoise2dv(vertex_global_pos));

            if ((int)vertex.x == 0 && (int)position.x == 0)
            {
                mesh_tool.SetVertexColor(i, new Color(color_factor, color_factor / 2, 0.0f));
            }
            else if (hydro_val == -1)
            {
                mesh_tool.SetVertexColor(i, biome.dry_color * color_factor);
            }
            else if (hydro_val == 1)
            {
                mesh_tool.SetVertexColor(i, biome.humid_color * color_factor);
            }
            else
            {
                mesh_tool.SetVertexColor(i, biome.ground_color * color_factor);
            }
            mesh_tool.SetVertex(i, vertex);
        }

        /*if (base_tree_mesh == null && ResourceLoader.Exists("res://assets/tree.obj"))
         * {
         *      base_tree_mesh = ResourceLoader.Load<Mesh>("res://assets/tree.obj");
         * }
         * if (base_tree_material == null && ResourceLoader.Exists("res://assets/tree.tres"))
         * {
         *      Console.WriteLine("OK");
         *      base_tree_material = ResourceLoader.Load<SpatialMaterial>("res://assets/tree.tres");
         * }
         *
         * MultiMesh trees = new MultiMesh();
         * trees.Mesh = base_tree_mesh;
         * trees.TransformFormat = MultiMesh.TransformFormatEnum.Transform3d;
         *
         * if ((int)position.x == 0)
         * {
         *      var points1 = Utility.UniformPoissonDiskSampler.SampleRectangle(-new Vector2(size, size) / 2, new Vector2(-5, size / 2.0f), biome.tree_spacing);
         *      var points2 = Utility.UniformPoissonDiskSampler.SampleRectangle(new Vector2(5, 0), new Vector2(size, size) / 2, biome.tree_spacing);
         *      trees.InstanceCount = points1.Count + points2.Count;
         *
         *      int i = 0;
         *      foreach (var p in points1)
         *      {
         *              trees.SetInstanceTransform(i, Transform.Identity.Scaled(new Vector3(1, biome.tree_size, 1)).Translated(new Vector3(p.x, height_noise.GetNoise2dv(position + p) * 20, p.y)));
         ++i;
         *      }
         *
         *      foreach (var p in points2)
         *      {
         *              trees.SetInstanceTransform(i, Transform.Identity.Scaled(new Vector3(1, biome.tree_size, 1)).Translated(new Vector3(p.x, height_noise.GetNoise2dv(position + p) * 20, p.y)));
         ++i;
         *      }
         * }
         * else
         * {
         *      var points = Utility.UniformPoissonDiskSampler.SampleRectangle(-new Vector2(size, size) / 2, new Vector2(size, size) / 2, biome.tree_spacing);
         *      trees.InstanceCount = points.Count;
         *      int i = 0;
         *      foreach (var p in points)
         *      {
         *              trees.SetInstanceTransform(i, Transform.Identity.Scaled(new Vector3(1, biome.tree_size, 1)).Translated(new Vector3(p.x, height_noise.GetNoise2dv(position + p) * 20, p.y)));
         ++i;
         *      }
         * }
         *
         * MultiMeshInstance child = new MultiMeshInstance();
         * child.Multimesh = trees;
         * child.MaterialOverride = base_tree_material;
         * AddChild(child);*/

        var array = new ArrayMesh();

        mesh_tool.CommitToSurface(array);
        Mesh = array;

        if (base_shader == null && ResourceLoader.Exists("res://assets/chunk_shader.tres"))
        {
            base_shader = ResourceLoader.Load <ShaderMaterial>("res://assets/chunk_shader.tres");
        }
        var shader = base_shader;

        MaterialOverride = shader;
    }