Optimizing voxel mesh data

Started by
5 comments, last by SpikeViper 7 years, 11 months ago

Currently, I handle the mesh data in my game with the following code:

Block class:


using UnityEngine;
using System.Collections;
using System.Collections.Generic;


[System.Serializable()]

public class Block
{
    public BlockType type;

    public Block(BlockType type1)
    {
        type = type1;
    }

    public enum Direction { north, east, south, west, up, down };

    [System.SerializableAttribute()]
    public struct Tile { public int x; public int y;}

    const float tileSize = 0.0625f;


    public virtual MeshData Blockdata
     (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)
    {

        meshData.useRenderDataForCol = true;

        if (type != BlockTypes.typeEmpty)
        {

            if (!planetchunk.GetBlock(x, y + 1, z).IsSolid)
            {
                meshData = FaceDataUp(planetchunk, x, y, z, meshData);
            }

            if (!planetchunk.GetBlock(x, y - 1, z).IsSolid)
            {
                meshData = FaceDataDown(planetchunk, x, y, z, meshData);
            }

            if (!planetchunk.GetBlock(x, y, z + 1).IsSolid)
            {
                meshData = FaceDataNorth(planetchunk, x, y, z, meshData);
            }

            if (!planetchunk.GetBlock(x, y, z - 1).IsSolid)
            {
                meshData = FaceDataSouth(planetchunk, x, y, z, meshData);
            }

            if (!planetchunk.GetBlock(x + 1, y, z).IsSolid)
            {
                meshData = FaceDataEast(planetchunk, x, y, z, meshData);
            }

            if (!planetchunk.GetBlock(x - 1, y, z).IsSolid)
            {
                meshData = FaceDataWest(planetchunk, x, y, z, meshData);
            }



            if (type.light == true)
            {

                if (planetchunk.GetBlock(x - 1, y, z).IsSolid == false || planetchunk.GetBlock(x + 1, y, z).IsSolid == false || planetchunk.GetBlock(x, y, z - 1).IsSolid == false ||
                    planetchunk.GetBlock(x, y, z + 1).IsSolid == false || planetchunk.GetBlock(x, y - 1, z).IsSolid == false || planetchunk.GetBlock(x, y + 1, z).IsSolid == false)
                {
                    meshData.AddLight(x, y, z, type.LR, type.LG, type.LB, type.LA, type.LightRange, type.LightIntensity);
                }

            }

            return meshData;

        }

        return meshData;
    }

    protected virtual MeshData FaceDataUp
        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)
    {
        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z - 0.5f));

        meshData.AddQuadTriangles();
        meshData.uv.AddRange(FaceUVs(Direction.up));
        return meshData;
    }

    protected virtual MeshData FaceDataDown
        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)
    {
        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z + 0.5f));

        meshData.AddQuadTriangles();
        meshData.uv.AddRange(FaceUVs(Direction.down));
        return meshData;
    }

    protected virtual MeshData FaceDataNorth
        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)
    {
        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z + 0.5f));

        meshData.AddQuadTriangles();
        meshData.uv.AddRange(FaceUVs(Direction.north));
        return meshData;
    }

    protected virtual MeshData FaceDataEast
        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)
    {
        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z + 0.5f));

        meshData.AddQuadTriangles();
        meshData.uv.AddRange(FaceUVs(Direction.east));
        return meshData;
    }

    protected virtual MeshData FaceDataSouth
        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)
    {
        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z - 0.5f));

        meshData.AddQuadTriangles();
        meshData.uv.AddRange(FaceUVs(Direction.south));
        return meshData;
    }

    protected virtual MeshData FaceDataWest
        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)
    {
        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z + 0.5f));
        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z - 0.5f));
        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z - 0.5f));
            

        meshData.AddQuadTriangles();
        meshData.uv.AddRange(FaceUVs(Direction.west));
        return meshData;
    }


    public virtual Vector2[] FaceUVs(Direction direction)
    {
        Vector2[] UVs = new Vector2[4];
        Tile tilePos = type.tile;

        UVs[0] = new Vector2(tileSize * tilePos.x + tileSize,
            tileSize * tilePos.y);
        UVs[1] = new Vector2(tileSize * tilePos.x + tileSize,
            tileSize * tilePos.y + tileSize);
        UVs[2] = new Vector2(tileSize * tilePos.x,
            tileSize * tilePos.y + tileSize);
        UVs[3] = new Vector2(tileSize * tilePos.x,
            tileSize * tilePos.y);

        return UVs;
    }

?}

MeshData:


using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MeshData
{
    public List<Vector3> vertices = new List<Vector3>();
    public List<int> triangles = new List<int>();
    public List<Vector2> uv = new List<Vector2>();
    public List<Vector3> colVertices = new List<Vector3>();
    public List<int> colTriangles = new List<int>();
    public Color32[,,] lightcolors = new Color32[localVars.chunklength, localVars.chunklength, localVars.chunklength];
    public float[,,] lightintensity = new float[localVars.chunklength, localVars.chunklength, localVars.chunklength];
    public float[,,] lightrange = new float[localVars.chunklength, localVars.chunklength, localVars.chunklength];
    public List<Vector3> lightpositions = new List<Vector3>(localVars.chunklength * localVars.chunklength * localVars.chunklength);

    public bool useRenderDataForCol;

    public void AddQuadTriangles()
    {
        triangles.Add(vertices.Count - 4);
        triangles.Add(vertices.Count - 3);
        triangles.Add(vertices.Count - 2);

        triangles.Add(vertices.Count - 4);
        triangles.Add(vertices.Count - 2);
        triangles.Add(vertices.Count - 1);

        if (useRenderDataForCol)
        {
            colTriangles.Add(colVertices.Count - 4);
            colTriangles.Add(colVertices.Count - 3);
            colTriangles.Add(colVertices.Count - 2);
            colTriangles.Add(colVertices.Count - 4);
            colTriangles.Add(colVertices.Count - 2);
            colTriangles.Add(colVertices.Count - 1);
        }
    }

    public void AddVertex(Vector3 vertex)
    {
        vertices.Add(vertex);

        if (useRenderDataForCol)
        {
            colVertices.Add(vertex);
        }

    }

    public void AddTriangle(int tri)
    {
        triangles.Add(tri);

        if (useRenderDataForCol)
        {
            colTriangles.Add(tri - (vertices.Count - colVertices.Count));
        }
    }

    public void AddLight (int x, int y, int z, byte R, byte G, byte B, byte A, float range, float intensity)
    {
        lightcolors[x, y, z] = new Color32(R, G, B, A);
        lightintensity[x, y, z] = intensity;
        lightrange[x, y, z] = range;
        lightpositions.Add(new Vector3(x, y, z));
    }

    public void Clear()
    {
        vertices.Clear();
        triangles.Clear();
        uv.Clear();
        colVertices.Clear();
        colTriangles.Clear();
        lightcolors = new Color32[16, 16, 16];
        lightintensity = new float[16, 16, 16];
        lightrange = new float[16, 16, 16];
        lightpositions.Clear();
    }
}

And Rendering:


    // Sends the calculated mesh information
    // to the mesh and collision components
    void RenderMesh()
    {

        filter.mesh.Clear();
        filter.mesh.vertices = meshData.vertices.ToArray();
        filter.mesh.triangles = meshData.triangles.ToArray();
        filter.mesh.uv = meshData.uv.ToArray();

        filter.mesh.RecalculateNormals();

        meshnew.Clear();

        

        meshnew.vertices = meshData.colVertices.ToArray();
        meshnew.triangles = meshData.colTriangles.ToArray();
        
        foreach (Vector3 position in meshData.lightpositions)
        {

            int x = (int)position.x;
            int y = (int)position.y;
            int z = (int)position.z;

            if (lights[x, y, z] == null)
            {
                

                Color32 color = meshData.lightcolors[x, y, z]; //Optimize lights later
                float intensity = meshData.lightintensity[x, y, z];
                float range = meshData.lightrange[x, y, z];

                GameObject light = new GameObject("Light " + x + " " + y + " " + z);
                Light lightComp = light.AddComponent<Light>();
                lightComp.color = color;
                lightComp.intensity = intensity;
                lightComp.range = range;
                light.transform.parent = this.transform;
                light.transform.localPosition = new Vector3(x, y, z);

                lights[x, y, z] = light;

            }

        }

        meshnew.RecalculateNormals();
        coll.sharedMesh = meshnew;

    }

Problem: MeshData uses lists, and when the mesh is updated... yep, so are the lists. Clearing the lists create quite a bit of garbage. I wanted to know if there's a way I should be doing this that would be less garbage-prone. Thanks.

I'm making an open source voxel space game called V0xel_Sp4ce! Help me out with the repository here: https://github.com/SpikeViper/V0xel_Sp4ce

Advertisement

For list see if you can set the Capacity property of the list when you clear. Not sure how it works if a list clears down to a small size or keeps the last capacity.

Another option should be to change to arrays and track the index yourself when you add things. Clearing it will then create no garbage as you only set indexes to zero. Then you might be able to use the array directly and put it into the unity mesh.

A link that with some information on unity's garbage handling. http://www.gamasutra.com/blogs/RobertZubek/20150504/242572/C_memory_and_performance_tips_for_Unity.php

@spinningcubes | Blog: Spinningcubes.com | Gamedev notes: GameDev Pensieve | Spinningcubes on Youtube

For list see if you can set the Capacity property of the list when you clear. Not sure how it works if a list clears down to a small size or keeps the last capacity.

Another option should be to change to arrays and track the index yourself when you add things. Clearing it will then create no garbage as you only set indexes to zero. Then you might be able to use the array directly and put it into the unity mesh.

A link that with some information on unity's garbage handling. http://www.gamasutra.com/blogs/RobertZubek/20150504/242572/C_memory_and_performance_tips_for_Unity.php

I set up the capacities, but I'm having trouble with arrays since I have no way to know how big the arrays will be since the game is procedural.

I'm making an open source voxel space game called V0xel_Sp4ce! Help me out with the repository here: https://github.com/SpikeViper/V0xel_Sp4ce

Here's my profiler if you're wondering where the GC is called:

image.png

The GC is called under MeshData..ctor, except my MeshData class has no contructor

I'm making an open source voxel space game called V0xel_Sp4ce! Help me out with the repository here: https://github.com/SpikeViper/V0xel_Sp4ce

Hi SpikeViper!

Some facts and hints about your situation:
First and foremost garbage is generated when you are "letting go" references to objects when you are not using them anymore.
Every class will have an auto-generated default constructor even if you don't write one, which does absolutely nothing except for setting the default values (or the values preset by you) for the fields of the object.
GC.Collect will kick in from time to time no matter what you do, and it may start to run "anywhere", but of course this depends on the garbage collector implementation. That is it's "nature" :), it has to check the execution stack and the objects on the heap from time to time whether there is garbage to be freed, but this can be significantly reduced (the number of times it kicks in and the time it takes to check) with careful program design.

Now on to your concrete problems:

The List<T> class does not "compact" it's inner array automatically when calling Clear/Remove/RemoveAt/RemoveAll etc...
There is a method called TrimExecess to do that explicitly, more on this here:
https://msdn.microsoft.com/en-us/library/dwb5h52a%28v=vs.110%29.aspx
and here:
https://msdn.microsoft.com/en-us/library/ms132207%28v=vs.110%29.aspx#
So the capacity of a list only grows under default use cases, but indeed when you clear a List<T>, the held references are let go, so this can generate garbage if not designed carefully.

!!! Altough in your case it is important to note that the Unity Vector2 and Vector3 types are structs (value types), and they are allocated in place and not as a new object on the heap, so they DO NOT GENERATE GARBAGE when they are let go !!!


    public void Clear()
    {
        vertices.Clear();
        triangles.Clear();
        uv.Clear();
        colVertices.Clear();
        colTriangles.Clear();
        lightcolors = new Color32[16, 16, 16];
        lightintensity = new float[16, 16, 16];
        lightrange = new float[16, 16, 16];
        lightpositions.Clear();
    }

In your clear method though you are throwing away a couple of objects. "lightcolors", "lightintensity", "lightrange" are re-created on each call and since they seem to be fixed size (16*16*16, so there is no need for a new one or a modified one) this is extremely wasteful, especially if you call this clear method often. Instead set all the values on a clear call to their default values.


    void RenderMesh()
    {

        filter.mesh.Clear();
        filter.mesh.vertices = meshData.vertices.ToArray();
        filter.mesh.triangles = meshData.triangles.ToArray();
        filter.mesh.uv = meshData.uv.ToArray();

        filter.mesh.RecalculateNormals();

        meshnew.Clear();

        

        meshnew.vertices = meshData.colVertices.ToArray();
        meshnew.triangles = meshData.colTriangles.ToArray();

When you call ToArray on a List<T>, a new array is actually allocated and all the elements of the old list are copied to the new array. So in this case you are "re-creating" the array of mesh vertices and triangles etc. on every RenderMesh() call. I guess this is not really what you want if optimization and less garbage is the goal! To solve this problem, I think you should really consider using arrays, or look for a list implementation which exposes it's inner array. The list class is actually nothing more than an encapsulated array which "grows" when you add an element to it, so it is resized to be able to hold more elements. The capacity field in the list class is the actual length of the inner array. More on this, and how to do a resizable array:
https://msdn.microsoft.com/en-us/library/bb348051%28v=vs.110%29.aspx
http://www.dotnetperls.com/array-resize
http://stackoverflow.com/questions/4972951/listt-to-t-without-copying/4973190#4973190

Another topic, that may be useful is "object pooling", but this is not something which can be applied to your current problem with your mesh data, but it still good-to-know. There is a ridiculous number of articles written on garbage collection and object pooling on the net, some useful ones:
https://blogs.msdn.microsoft.com/shawnhar/2007/07/02/twin-paths-to-garbage-collector-nirvana/
http://swampthingtom.blogspot.hu/2007/06/generic-pool-collection-class.html
http://codecube.net/2010/01/xna-resource-pool/

Br. :wink:

Blog | Overburdened | KREEP | Memorynth | @blindmessiah777 Magic Item Tech+30% Enhanced GameDev

Thanks! I've (partially) fixed it. Here's the changes:


        meshData.vertices.TrimExcess();
        meshData.triangles.TrimExcess();
        meshData.uv.TrimExcess();

        verts = meshData.vertices._items;
        tris = meshData.triangles._items;

        filter.mesh.vertices = verts;
        filter.mesh.triangles = tris;
        filter.mesh.uv = meshData.uv._items;

        filter.mesh.RecalculateNormals();

        meshnew.vertices = verts;
        meshnew.triangles = tris;

I made my own "Resizeable Array" which has its array visible. I'm still getting a GC called on the meshData constructor, though. Any way to further reduce the trash?

SHOOT. Trimming them also copies the array.

I'm making an open source voxel space game called V0xel_Sp4ce! Help me out with the repository here: https://github.com/SpikeViper/V0xel_Sp4ce

I've hit a roadblock. Yes, I managed to switch to arrays from the start by doing "preprocessing" to find the size to make my arrays before actually adding to them. But, by not using lists, multiple vertices with the same value can be put into the mesh... resulting in (2x - 4x) the vertices needed. This is bad, because I can make sure that something hasn't been added already by adding more logic, but that throws off my triangle and uv counts. I think it's come to a time for me to re-think how I make the meshes for my chunks, and how I store that data in blocks. For those wondering, here's my current code. Any suggestions, ideas, or anything vaguely related would be very helpful. Thanks.

BLOCK:
using UnityEngine;using System.Collections;using System.Collections.Generic;[System.Serializable()]public class Block{    public BlockType type;    public Vector2[] UVs = new Vector2[4];    public Tile tilePos;    public bool blockupsolid;    public bool blockdownsolid;    public bool blockeastsolid;    public bool blockwestsolid;    public bool blocknorthsolid;    public bool blocksouthsolid;    public Block(BlockType type1)    {        type = type1;    }    public enum Direction { north, east, south, west, up, down };    [System.SerializableAttribute()]    public struct Tile { public int x; public int y;}    const float tileSize = 0.0625f;    public MeshData Blockdata     (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)    {        if (this.type != BlockTypes.typeEmpty)        {            meshData.useRenderDataForCol = true;            if (!blockupsolid)            {                meshData = FaceDataUp(planetchunk, x, y, z, meshData);            }            if (!blockdownsolid)            {                meshData = FaceDataDown(planetchunk, x, y, z, meshData);            }            if (!blocknorthsolid)            {                meshData = FaceDataNorth(planetchunk, x, y, z, meshData);            }            if (!blocksouthsolid)            {                meshData = FaceDataSouth(planetchunk, x, y, z, meshData);            }            if (!blockeastsolid)            {                meshData = FaceDataEast(planetchunk, x, y, z, meshData);            }            if (!blockwestsolid)            {                meshData = FaceDataWest(planetchunk, x, y, z, meshData);            }            if (type.light == true)            {                meshData.Light(type.light);                if (planetchunk.GetBlock(x - 1, y, z).IsSolid == false || planetchunk.GetBlock(x + 1, y, z).IsSolid == false || planetchunk.GetBlock(x, y, z - 1).IsSolid == false ||                    planetchunk.GetBlock(x, y, z + 1).IsSolid == false || planetchunk.GetBlock(x, y - 1, z).IsSolid == false || planetchunk.GetBlock(x, y + 1, z).IsSolid == false)                {                    meshData.AddLight(x, y, z, type.LR, type.LG, type.LB, type.LA, type.LightRange, type.LightIntensity);                }            }            return meshData;        }        return meshData;    }    protected MeshData FaceDataUp        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)    {        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z - 0.5f));        meshData.AddQuadTriangles();        meshData.AddUVRange(FaceUVs(Direction.up));        return meshData;    }    protected MeshData FaceDataDown        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)    {        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z + 0.5f));        meshData.AddQuadTriangles();        meshData.AddUVRange(FaceUVs(Direction.down));        return meshData;    }    protected MeshData FaceDataNorth        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)    {        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z + 0.5f));        meshData.AddQuadTriangles();        meshData.AddUVRange(FaceUVs(Direction.north));        return meshData;    }    protected MeshData FaceDataEast        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)    {        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z + 0.5f));        meshData.AddQuadTriangles();        meshData.AddUVRange(FaceUVs(Direction.east));        return meshData;    }    protected MeshData FaceDataSouth        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)    {        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y + 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x + 0.5f, y - 0.5f, z - 0.5f));        meshData.AddQuadTriangles();        meshData.AddUVRange(FaceUVs(Direction.south));        return meshData;    }    protected MeshData FaceDataWest        (PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)    {        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z + 0.5f));        meshData.AddVertex(new Vector3(x - 0.5f, y + 0.5f, z - 0.5f));        meshData.AddVertex(new Vector3(x - 0.5f, y - 0.5f, z - 0.5f));                    meshData.AddQuadTriangles();        meshData.AddUVRange(FaceUVs(Direction.west));        return meshData;    }    public Vector2[] FaceUVs(Direction direction)    {        tilePos = type.tile;        UVs[0] = new Vector2(tileSize * tilePos.x + tileSize,            tileSize * tilePos.y);        UVs[1] = new Vector2(tileSize * tilePos.x + tileSize,            tileSize * tilePos.y + tileSize);        UVs[2] = new Vector2(tileSize * tilePos.x,            tileSize * tilePos.y + tileSize);        UVs[3] = new Vector2(tileSize * tilePos.x,            tileSize * tilePos.y);        return UVs;    }    public void PreProcess(PlanetChunk planetchunk, int x, int y, int z, MeshData meshData)    {             blockupsolid = false;             blockdownsolid = false;              blocknorthsolid = false;             blocksouthsolid = false;             blockeastsolid = false;             blockwestsolid = false;        if (this.type != BlockTypes.typeEmpty)        {            if (planetchunk.GetBlock(x, y + 1, z).IsSolid)            {                blockupsolid = true;                meshData.AddFaceCount();            }            if (planetchunk.GetBlock(x, y - 1, z).IsSolid)            {                blockdownsolid = true;                meshData.AddFaceCount();            }            if (planetchunk.GetBlock(x, y, z + 1).IsSolid)            {                blocknorthsolid = true;                meshData.AddFaceCount();            }            if (planetchunk.GetBlock(x, y, z - 1).IsSolid)            {                blocksouthsolid = true;                meshData.AddFaceCount();            }            if (planetchunk.GetBlock(x + 1, y, z).IsSolid)            {                blockeastsolid = true;                meshData.AddFaceCount();            }            if (planetchunk.GetBlock(x - 1, y, z).IsSolid)            {                blockwestsolid = true;                meshData.AddFaceCount();            }        }    }}
MESHDATA:
using UnityEngine;using System.Collections;using System.Collections.Generic;public class MeshData{    public Vector3[] vertices;    public int[] triangles;    public Vector2[] uv;    public Color32[,,] lightcolors;    public float[,,] lightintensity;    public float[,,] lightrange;    public ResizeableArray<Vector3> lightpositions;    public int vertcount = 0;    public int tricount = 0;    public int uvcount = 0;    public int verts = 0;    public int tris = 0;    public int uvs = 0;    public bool light;    public bool useRenderDataForCol;        public void Light(bool val)    {        if (val == true)        {            lightpositions = new ResizeableArray<Vector3>(localVars.chunklength * localVars.chunklength * localVars.chunklength); //Fix this later            lightcolors = new Color32[localVars.chunklength, localVars.chunklength, localVars.chunklength];            lightintensity = new float[localVars.chunklength, localVars.chunklength, localVars.chunklength];            lightrange = new float[localVars.chunklength, localVars.chunklength, localVars.chunklength];            light = true;        }    }    public void AddFaceCount()    {        vertcount = vertcount + 4;        uvcount = uvcount + 4;        tricount = tricount + 6;    }    public void Rebuild()    {        vertices = new Vector3[vertcount];        triangles = new int[tricount];        uv = new Vector2[uvcount];    }    public void AddQuadTriangles()    {        triangles[tris++] = verts - 4;        triangles[tris++] = verts - 3;        triangles[tris++] = verts - 2;        triangles[tris++] = verts - 4;        triangles[tris++] = verts - 2;        triangles[tris++] = verts - 1;        //triangles.Add(vertices.Count - 4);        //triangles.Add(vertices.Count - 3);        //triangles.Add(vertices.Count - 2);        //triangles.Add(vertices.Count - 4);        //triangles.Add(vertices.Count - 2);        //triangles.Add(vertices.Count - 1);        //if (useRenderDataForCol)        //{        //    colTriangles.Add(colVertices.Count - 4);        //    colTriangles.Add(colVertices.Count - 3);        //    colTriangles.Add(colVertices.Count - 2);        //    colTriangles.Add(colVertices.Count - 4);        //    colTriangles.Add(colVertices.Count - 2);        //    colTriangles.Add(colVertices.Count - 1);        //}    }    public void AddVertex(Vector3 vertex)    {                vertices[verts++] = vertex;        //if (useRenderDataForCol)        //{        //    colVertices.Add(vertex);        //}    }    public void AddTriangle(int tri)    {        triangles[tris++] = tri;    }    public void AddLight (int x, int y, int z, byte R, byte G, byte B, byte A, float range, float intensity)    {        lightcolors[x, y, z] = new Color32(R, G, B, A);        lightintensity[x, y, z] = intensity;        lightrange[x, y, z] = range;        lightpositions.Add(new Vector3(x, y, z));    }    public void Clear()    {        if (light == true)        {            lightpositions.Clear();            light = false;        }    }    public void AddUVRange(Vector2[] vect2s)    {        uv[uvs++] = vect2s[0];        uv[uvs++] = vect2s[1];        uv[uvs++] = vect2s[2];        uv[uvs++] = vect2s[3];    }}
RENDERING:
// Sends the calculated mesh information    // to the mesh and collision components    void RenderMesh()    {        mesh.vertices = meshData.vertices;        mesh.triangles = meshData.triangles;        mesh.uv = meshData.uv;        colmesh.vertices = meshData.vertices;        colmesh.triangles = meshData.triangles;        colmesh.uv = meshData.uv;        if (meshData.light == true)        {            for (int i = 0; i < meshData.lightpositions.Count; i++)            {                Vector3 position = meshData.lightpositions[i];                int x = (int)position.x;                int y = (int)position.y;                int z = (int)position.z;                if (lights[x, y, z] == null)                {                    Color32 color = meshData.lightcolors[x, y, z];                    float intensity = meshData.lightintensity[x, y, z];                    float range = meshData.lightrange[x, y, z];                    GameObject light = new GameObject("Light " + x + " " + y + " " + z);                    Light lightComp = light.AddComponent<Light>();                    lightComp.color = color;                    lightComp.intensity = intensity;                    lightComp.range = range;                    light.transform.parent = this.transform;                    light.transform.localPosition = new Vector3(x, y, z);                    lights[x, y, z] = light;                }            }        }        filter.sharedMesh = mesh;        coll.sharedMesh = colmesh;        filter.sharedMesh.RecalculateNormals();        firstrender = false;    }

I'm making an open source voxel space game called V0xel_Sp4ce! Help me out with the repository here: https://github.com/SpikeViper/V0xel_Sp4ce

This topic is closed to new replies.

Advertisement