Пример #1
0
    private void GenerateSurface()
    {
        surfaceTool.Begin(Mesh.PrimitiveType.Triangles);

        for (int x = 0; x < SIZE.x; x++)
        {
            for (int y = 0; y < SIZE.y; y++)
            {
                for (int z = 0; z < SIZE.z; z++)
                {
                    byte blockType = blocks[x, y, z];
                    if (blockType == 0)
                    {
                        continue;
                    }

                    Block block = Game.GetBlock(blockType);

                    IntVector3 localIndex = new IntVector3(x, y, z);

                    //Index in world space
                    IntVector3 index = localIndex + new IntVector3(chunkCoords.x * SIZE.x, 0, chunkCoords.y * SIZE.z);

                    //Position in chunk
                    Vector3 localBlockPosition = localIndex * Block.SIZE;

                    if (terrain.GetBlock(index.x + 1, index.y, index.z) == AIR_ID)
                    {
                        block.AddPosXFace(ref surfaceTool, localBlockPosition, blockType);
                    }
                    if (terrain.GetBlock(index.x - 1, index.y, index.z) == AIR_ID)
                    {
                        block.AddNegXFace(ref surfaceTool, localBlockPosition, blockType);
                    }
                    if (terrain.GetBlock(index.x, index.y + 1, index.z) == AIR_ID)
                    {
                        block.AddPosYFace(ref surfaceTool, localBlockPosition, blockType);
                    }
                    if (index.y != 0 && terrain.GetBlock(index.x, index.y - 1, index.z) == AIR_ID) //Don't draw bottom face
                    {
                        block.AddNegYFace(ref surfaceTool, localBlockPosition, blockType);
                    }
                    if (terrain.GetBlock(index.x, index.y, index.z + 1) == AIR_ID)
                    {
                        block.AddPosZFace(ref surfaceTool, localBlockPosition, blockType);
                    }
                    if (terrain.GetBlock(index.x, index.y, index.z - 1) == AIR_ID)
                    {
                        block.AddNegZFace(ref surfaceTool, localBlockPosition, blockType);
                    }
                }
            }
        }

        surfaceTool.GenerateNormals();

        surfaceTool.SetMaterial(material);

        surfaceTool.Index();
    }
Пример #2
0
    public Mesh CreateMesh()
    {
        SurfaceTool.Begin(Mesh.PrimitiveType.Triangles);
        SurfaceTool.SetMaterial(DefaultMaterial);

        foreach (var voxel in Voxels.Keys)
        {
            CreateVoxel(Voxels[voxel], voxel);
        }

        SurfaceTool.Index();
        return(SurfaceTool.Commit());
    }
Пример #3
0
        public void BuildVoxelMesh()
        {
            Builder.Begin(Mesh.PrimitiveType.Triangles);
            // GD.Print("Builder has begun!");
            Builder.SetMaterial(voxelMaterial);

            foreach (VoxelPos pos in Voxels.Keys)
            {
                var voxel = GetVoxel(pos, false);

                if (voxel.HasFront())
                {
                    BuildFace(pos.ToVector3(), Vector3.Right, Vector3.Up, UVFromName(voxel.frontTexture), Vector3.Forward);
                }
                if (voxel.HasBack())
                {
                    BuildFace(pos.Backwards().ToVector3(), Vector3.Up, Vector3.Right, UVFromName(voxel.backTexture), Vector3.Back);
                }
                if (voxel.HasLeft())
                {
                    BuildFace(pos.ToVector3(), Vector3.Up, Vector3.Back, UVFromName(voxel.leftTexture), Vector3.Left);
                }
                if (voxel.HasRight())
                {
                    BuildFace(pos.Right().ToVector3(), Vector3.Back, Vector3.Up, UVFromName(voxel.rightTexture), Vector3.Right);
                }
                if (voxel.HasTop())
                {
                    BuildFace(pos.Up().ToVector3(), Vector3.Right, Vector3.Back, UVFromName(voxel.topTexture), Vector3.Up);
                }
                if (voxel.HasBottom())
                {
                    BuildFace(pos.ToVector3(), Vector3.Back, Vector3.Right, UVFromName(voxel.bottomTexture), Vector3.Down);
                }
            }

            Builder.Index();
            var voxelMesh = GetNode <MeshInstance>("VoxelMesh");

            voxelMesh.Mesh = Builder.Commit();
            Builder.Clear();

            /*
             * foreach (KeyValuePair<VoxelPos, Voxel> pair in Voxels)
             * {
             *  GD.Print($"{pair.Key}: {pair.Value}");
             * }
             */
        }
        //Creates a surface tool for mesh creation
        public static SurfaceTool CreateSurfaceTool(SpatialMaterial material = null)
        {
            var surfTool = new SurfaceTool();

            surfTool.Begin(Mesh.PrimitiveType.Triangles);
            if (material == null)
            {
                material = new SpatialMaterial();
                //material.SetEmission(new Color(1.0f, 0.0f, 0.0f));
                //material.SetEmissionEnergy(0.5f);
                material.SetAlbedo(new Color(0.5f, 0.0f, 0.0f));
                //material.SetMetallic(0.5f);
                material.SetCullMode(SpatialMaterial.CullMode.Back);
            }
            surfTool.SetMaterial(material);
            return(surfTool);
        }
Пример #5
0
    public void generateMeshAndColors(float[,] dataTerrain)
    {
        //init tool
        SurfaceTool st = new SurfaceTool();

        st.Begin(Mesh.PrimitiveType.Triangles);
        st.SetMaterial(mat);

        //get HeightsQuats and create triangles
        int maxI      = dataTerrain.GetLength(0);
        int maxJ      = dataTerrain.GetLength(1);
        int quadCount = 0;

        //1º rows, 2º columns
        for (int i = 0; i < maxI - 1; i++)
        {
            for (int j = 0; j < maxJ - 1; j++)
            {
                Quat q = new Quat();//heights to Quat

                q.x = dataTerrain[i, j];       q.y = dataTerrain[i, j + 1];

                q.z = dataTerrain[i + 1, j];     q.w = dataTerrain[i + 1, j + 1];

                //to mesh
                Vector3 offset = new Vector3(j, 0, i);
                createQuad(st, offset, q);

                /*//debug algoritm
                 * GD.Print(string.Format("•quad{0}:({1},{2}): points: \n{3} {4} {5}   {6} {7} {8}\n{9} {10} {11}   {12} {13} {14}",
                 * quadCount,i,j,
                 * offset.x, q.x, offset.z - 1,       offset.x + 1, q.y, offset.z-1,
                 * offset.x, q.z, offset.z,         offset.x + 1, q.w, offset.z));
                 */
                quadCount++;
            }
        }

        //finally
        st.GenerateNormals();
        st.Commit(tmpMesh);
        this.SetMesh(tmpMesh);
    }
Пример #6
0
    // Generates sphere with radius 1
    public void GenerateSphere(int iterations)
    {
        float radius = 10f;

        System.Diagnostics.Debug.WriteLine("Generating sphere!");
        Stopwatch totalTimer = new Stopwatch();

        totalTimer.Start();

        SurfaceTool surfaceTool = new SurfaceTool();

        this.planetMesh = new ArrayMesh();

        material.VertexColorUseAsAlbedo = true;
        surfaceTool.SetMaterial(material);
        surfaceTool.Begin(PrimitiveType.Triangles);

        // GENERATE SPHERE:
        Stopwatch planetGeneratorTimer = new Stopwatch();

        planetGeneratorTimer.Start();

        // 9 gives ~30s generate time, which is acceptable
        this.currentStatus = "Generating base topology (this step can take long!)";
        PlanetTopologyData[] planetData = pg.GenerateBaseTopology(iterations, radius);

        planetGeneratorTimer.Stop();
        TimeSpan ts = planetGeneratorTimer.Elapsed;

        System.Diagnostics.Debug.WriteLine("Sphere generated. Number of faces: " + (planetData[0].faces.Count * 20) + "; time needed: " + ts.Minutes + "m " + ts.Seconds + "." + ts.Milliseconds);

        // todo: create biomes

        // Add perlino
        Stopwatch perlinTimer = new Stopwatch();

        perlinTimer.Start();

        this.currentStatus = "Adding perlin noise ...";

        Parallel.For(0, planetData.Length, new ParallelOptions {
            MaxDegreeOfParallelism = System.Environment.ProcessorCount
        }, i => {
            PlanetTopologyData data = planetData[i];
            data.vertices           = pg.AddPerlinDisplacement(data.vertices, radius, 16, 0.42f);

            // float maxDispalcement = 0;
            // float maxNegDisplacement = 0;
            // foreach (PlanetVertex pv in data.vertices) {
            //   if (pv.h > maxDispalcement) {
            //     maxDispalcement = pv.h;
            //   }
            //   if (pv.h < maxNegDisplacement) {
            //     maxNegDisplacement = pv.h;
            //   }
            // }
            // Debug.WriteLine("Max displacement for this face (from-to) " + maxNegDisplacement +" -> " + maxDispalcement);
        });

        perlinTimer.Stop();
        ts = perlinTimer.Elapsed;
        System.Diagnostics.Debug.WriteLine("Perlin applied. Time needed: " + ts.Minutes + "m " + ts.Seconds + "." + ts.Milliseconds);

        Stopwatch surfaceToolTimer = new Stopwatch();

        surfaceToolTimer.Start();

        this.currentStatus = "Building planet mesh ...";

        // // Possible future for multithreading ahead. Might happen some day.
        //
        // SurfaceTool[] surfaceTool = new SurfaceTool[planetData.Length];
        // this.planetMeshes = new ArrayMesh[planetData.Length];

        // material.VertexColorUseAsAlbedo = true;

        // Parallel.For(0, planetData.Length, new ParallelOptions {MaxDegreeOfParallelism = System.Environment.ProcessorCount}, i => {
        //   surfaceTool[i] = new SurfaceTool();
        //   this.planetMeshes[i] = new ArrayMesh();

        //   surfaceTool[i].SetMaterial(material);
        //   surfaceTool[i].Begin(PrimitiveType.Triangles);

        //   for (int j = 0; j < planetData[i].faces.Count; j++) {
        //     planetData[i].faces[j].AddToSurfaceTool(surfaceTool[i]);
        //   }

        //   surfaceTool[i].GenerateNormals();
        //   surfaceTool[i].Commit(this.planetMeshes[i]);
        // });

        int faceCount;

        for (int i = 0; i < planetData.Length; i++)
        {
            faceCount = planetData[i].faces.Count;
            for (int j = 0; j < faceCount; j++)
            {
                planetData[i].faces[j].AddToSurfaceTool(surfaceTool);
            }
        }

        // foreach (PlanetTopologyData data in planetData) {
        //   foreach (PlanetCell c in data.faces) {
        //     c.AddToSurfaceTool(surfaceTool);
        //   }
        // }

        surfaceTool.GenerateNormals();
        surfaceTool.Commit(this.planetMesh);

        surfaceToolTimer.Stop();
        ts = surfaceToolTimer.Elapsed;
        System.Diagnostics.Debug.WriteLine("SurfaceTool generated our mesh. Time needed: " + ts.Minutes + "m " + ts.Seconds + "." + ts.Milliseconds);
        totalTimer.Stop();
        ts = totalTimer.Elapsed;
        System.Diagnostics.Debug.WriteLine("————————————————— total time needed: " + ts.Minutes + "m " + ts.Seconds + "." + ts.Milliseconds + "—————————————————");

        this.Mesh          = planetMesh;
        this.currentStatus = "";
    }
Пример #7
0
    public MeshInstance CreateChunkMesh(Chunk chunk)
    {
        MeshInstance instance    = new MeshInstance();
        SurfaceTool  surfacetool = new SurfaceTool();

        surfacetool.Begin(Mesh.PrimitiveType.Points);
        surfacetool.SetMaterial(chunkMaterial);
        int count = 0;

        for (int i = 0; i < Constants.CHUNK_SIZE3D / chunk.Materials; i++)
        {
            Run         run         = chunk.Voxels[i];
            int         objectID    = run.value;
            TerraObject terraObject = registry.SelectByID((int)objectID);
            var         x           = i % CHUNK_SIZE;
            var         y           = (i / CHUNK_SIZE) % CHUNK_SIZE;
            var         z           = i / (CHUNK_SIZE * CHUNK_SIZE);
            if (chunk.Voxels[i].value != 0)
            {
                int face = 0b000000;
                //Left
                if (x == 0 || chunk.Voxels[i - 1].value != objectID)
                {
                    face = 0b000001;
                }

                //Right
                else if (x == 63 || chunk.Voxels[i + 1].value != objectID)
                {
                    face = 0b000010;
                }
                //Top
                else if (y == 63 || chunk.Voxels[i + 64].value != objectID)
                {
                    face = 0b000100;
                }
                //Bottom
                else if (y == 0 || chunk.Voxels[i - 64].value != objectID)
                {
                    face = 0b001000;
                }
                //Back
                else if (z == 63 || chunk.Voxels[i + 4096].value != objectID)
                {
                    face = 0b010000;
                }
                //Front
                else if (z == 0 || chunk.Voxels[i - 4096].value != objectID)
                {
                    face = 0b100000;
                }

                if (face != 0b000000)
                {
                    int     counter   = 0;
                    Vector3 normalAvg = Vector3.Zero;
                    for (int j = 0; j < 6; j++)
                    {
                        int bitFlagN = (face >> j) & 1;
                        if (bitFlagN == 1)
                        {
                            normalAvg = normalAvg + Normals[j];
                            counter  += 1;
                        }
                    }

                    count += 1;
                    surfacetool.AddColor(new Color(1f, 1f, 1f, 1f));
                    Vector3 voxPosition = new Vector3((x) * VOX_SIZE, (y) * VOX_SIZE, (z) * VOX_SIZE);
                    voxPosition.x = voxPosition.x + (chunk.x * CHUNK_SIZE * VOX_SIZE);
                    voxPosition.y = voxPosition.y + (chunk.y * CHUNK_SIZE * VOX_SIZE);
                    voxPosition.z = voxPosition.z + (chunk.z * CHUNK_SIZE * VOX_SIZE);
                    if (counter > 0)
                    {
                        normalAvg = normalAvg / counter;
                        surfacetool.AddNormal(normalAvg);
                    }

                    surfacetool.AddVertex(voxPosition);
                }
            }
        }

        surfacetool.Index();
        instance.Mesh = surfacetool.Commit();
        surfacetool.Clear();
        instance.MaterialOverride = chunkMaterial.Duplicate() as ShaderMaterial;

        // Console.WriteLine("Mesh AABB Pos: {0} , Size: {1}, End: {2}",bb.Position,bb.Size,bb.End);
        return(instance);
    }
Пример #8
0
    private void Render(Chunk pChunk)
    {
        // If chunk is already loaded.
        if (LoadedChunks.ContainsKey(pChunk.Offset))
        {
            return;
        }

        SurfaceTool = new SurfaceTool();
        SurfaceTool.Begin(Mesh.PrimitiveType.Triangles);

        // Adding material
        Material mat = VoxMaterial.Duplicate() as Material;

        SurfaceTool.SetMaterial(mat);

        // Creating the mesh. Voxel by voxel
        for (int y = 0; y < Chunk.ChunkSize.y; y++)
        {
            for (int x = 0; x < Chunk.ChunkSize.x; x++)
            {
                for (int z = 0; z < Chunk.ChunkSize.z; z++)
                {
                    if (!pChunk.Voxels[x, y, z].Active)
                    {
                        continue;
                    }

                    CreateVoxel(SurfaceTool, x, y, z, pChunk);
                }
            }
        }

        // Reduces vertex size
        SurfaceTool.Index();

        // Creating instance
        MeshInstance chunk = new MeshInstance
        {
            Mesh        = SurfaceTool.Commit(),
            Name        = pChunk.Offset.ToString(),
            Translation = new Vector3(pChunk.Offset.x * Chunk.ChunkSize.x, 0, pChunk.Offset.y * Chunk.ChunkSize.z)
        };

        // Creating collisions
        //chunk.CreateTrimeshCollision();


        // Tagging the chunk
        chunk.AddToGroup("Chunk");

        // Chunk is now loaded. Adding to the scene.
        LoadedChunks.TryAdd(pChunk.Offset, pChunk);
        this.CallDeferred("add_child", chunk);

        if (pChunk.VoxelSprite.Count < 64)
        {
            // Adding voxelsprite
            foreach (VoxelSprite voxSprite in pChunk.VoxelSprite)
            {
                var meshInstance = new MeshInstance();
                meshInstance.SetDeferred("mesh", voxSprite.Mesh);

                // Adding next frame to avoid locking problems.
                chunk.CallDeferred("add_child", meshInstance);

                // Moving next frame because not in tree yet
                meshInstance.SetDeferred("translation", voxSprite.Position);

                // Applying wind shader.
                meshInstance.SetDeferred("material_override", GrassMaterial);

                // Scaling down because its a decoration
                meshInstance.Scale = meshInstance.Scale /= 8;
            }
        }



        // Fade in animation.
        //var t2 = new Tween();
        //chunk.AddChild(t2);
        //t2.InterpolateProperty(mat, "albedo_color", new Color(1, 1, 1, 0f), new Color(1, 1, 1, 1f), 1f, Tween.TransitionType.Linear, Tween.EaseType.InOut);
        //t2.Start();

        SurfaceTool.Clear();
    }
Пример #9
0
    public void CreateMesh(Tile tile, PackedScene sphereMeshScene, PackedScene greenSphereMeshScene, int numberOfTiles, float radius)
    {
        var surfTool = new SurfaceTool();
        var mesh     = new ArrayMesh();
        var material = new SpatialMaterial();

        material.SetEmission(new Color(1.0f, 0.0f, 0.0f));
        material.SetAlbedo(new Color(1.0f, 0.0f, 0.0f));
        surfTool.SetMaterial(material);
        surfTool.Begin(Mesh.PrimitiveType.LineLoop);
        decimal tileCenterX   = 0;
        decimal tileCenterY   = 0;
        decimal tileCenterZ   = 0;
        decimal polygonRadius = 0;

        List <Point> points            = tile.boundary;
        var          lastPoint         = points[points.Count - 1];
        Vector3      lastPointVector   = new Vector3((float)lastPoint.x, (float)lastPoint.y, (float)lastPoint.z);
        decimal      polygonSideLength = 0;

        foreach (Point point in points)
        {
            surfTool.AddUv(new Vector2(0, 0));
            surfTool.AddVertex(new Vector3((float)point.x, (float)point.y, (float)point.z));

            tileCenterX += point.x / points.Count;
            tileCenterY += point.y / points.Count;
            tileCenterZ += point.z / points.Count;
            Vector3 currentVector = new Vector3((float)point.x, (float)point.y, (float)point.z);
            polygonSideLength += (decimal)currentVector.DistanceTo(lastPointVector);
            lastPointVector    = currentVector;
        }
        polygonSideLength = polygonSideLength / points.Count;

        var tileCenterPoint = new Vector3((float)tileCenterX, (float)tileCenterY, (float)tileCenterZ);
        var firstPoint      = new Vector3((float)points[0].x, (float)points[0].y, (float)points[0].z);

        foreach (Point point in points)
        {
            var vector = new Vector3((float)point.x, (float)point.y, (float)point.z);
            polygonRadius += (decimal)vector.DistanceTo(tileCenterPoint);
        }
        polygonRadius = polygonRadius / points.Count;

        var polygonRotation = firstPoint.AngleTo(tileCenterPoint);


        var sphereCenterPoint = new Vector3(0f, 0f, 0f);

        var          sphereScale = radius / numberOfTiles;
        MeshInstance sphere      = (MeshInstance)sphereMeshScene.Instance();

        sphere.SetTranslation(tileCenterPoint);
        sphere.SetScale(new Vector3(sphereScale, sphereScale, sphereScale));
        this.AddChild(sphere);

        MeshInstance sphere2 = (MeshInstance)greenSphereMeshScene.Instance();

        sphere2.SetTranslation(firstPoint);
        sphere2.SetScale(new Vector3(sphereScale, sphereScale, sphereScale));
        this.AddChild(sphere2);

        MeshInstance sphere3 = (MeshInstance)greenSphereMeshScene.Instance();

        sphere3.SetTranslation((firstPoint - tileCenterPoint) / 2 + tileCenterPoint);
        sphere3.SetScale(new Vector3(sphereScale, sphereScale, sphereScale));
        this.AddChild(sphere3);

        surfTool.GenerateNormals();
        surfTool.Index();
        surfTool.Commit(mesh);
        var meshInstance = new MeshInstance();

        meshInstance.SetMesh(mesh);
        this.AddChild(meshInstance);
    }