Beispiel #1
0
    public static GameObject BlockToGameObject(RenderBuffers buffers, IVoxelBlock block, Material material, Action <PointerEventData, GameObject> clickCallback)
    {
        GameObject go = new GameObject(String.Format("Block({0}, {1})", block.Offset.x, block.Offset.y));

        go.AddComponent <ProceduralRenderer>();
        go.AddComponent <BoxCollider>();
        go.AddComponent <BlockInfo>();
        go.AddComponent <EventTrigger>();

        ProceduralRenderer renderer = go.GetComponent <ProceduralRenderer>();

        renderer.buffers     = buffers;
        renderer.bounds.min  = new Vector3(0.0f, 0.0f, 0.0f);
        renderer.bounds.size = new Vector3(block.Width, block.Height, block.Length);
        go.GetComponent <BlockInfo>().Block    = block;
        go.transform.localPosition             = new Vector3((block.Offset.x - 0.5f) * block.Width, -block.Height / 2, (block.Offset.y - 0.5f) * block.Length);
        go.transform.localScale                = new Vector3(1.0f, 1.0f, 1.0f);
        go.GetComponent <BoxCollider>().center = new Vector3(block.Width / 2, block.Height / 2, block.Length / 2);
        go.GetComponent <BoxCollider>().size   = new Vector3(block.Width, block.Height, block.Length);

        EventTrigger trigger = go.GetComponent <EventTrigger>();

        EventTrigger.Entry entry = new EventTrigger.Entry();
        entry.eventID = EventTriggerType.PointerClick;
        entry.callback.AddListener((data) => { clickCallback((PointerEventData)data, go); });
        trigger.triggers.Add(entry);

        go.AddComponent <LineRenderer>();
        LineRenderer boundingBoxRenderer = go.GetComponent <LineRenderer>();

        Vector3[] points = getBoundingBoxPoints(block);
        boundingBoxRenderer.positionCount = points.Length;
        boundingBoxRenderer.useWorldSpace = false;
        boundingBoxRenderer.SetPositions(points);

        return(go);
    }
    public IEnumerator <object> genericTest(Tests type, string name, int cpuLimit, int pmbLimit, Func <Vector3Int, int, int, int, float> voxelGenerator)
    {
        int CPU_LIMIT = cpuLimit;
        int PMB_LIMIT = pmbLimit;

        UnityEngine.Debug.Log("Starting Test " + name);
        perfData[(int)type] = new PerfData
        {
            testName = name,
            sizes    = new TestSize[testSizes.Length],
        };

        int limitCounter = 0;

        for (int i = 0; i < testSizes.Length; i++)
        {
            Vector3Int size = (Vector3Int)testSizes[i];
            UnityEngine.Debug.Log("size: " + size);
            perfData[(int)type].sizes[i] = new TestSize
            {
                sizeName     = string.Format("({0}, {1}, {2})", size.x, size.y, size.z),
                cpuTime      = new int[ROUNDS],
                pmbTime      = new int[ROUNDS],
                cpuTriangles = 0,
                pmbTriangles = 0,
            };


            float[] voxel;

            string path = Path.Combine(performanceDataDir, string.Format("{0}{1}.dat", name, perfData[(int)type].sizes[i].sizeName));
            if (File.Exists(path))
            {
                UnityEngine.Debug.Log("loading voxelData from file:");
                Stream          voxelStream  = File.OpenRead(path);
                BinaryFormatter deserializer = new BinaryFormatter();
                voxel = (float[])deserializer.Deserialize(voxelStream);
                voxelStream.Close();
            }
            else
            {
                UnityEngine.Debug.Log("recreating voxelData:");
                voxel = new float[size.x * size.y * size.z];
                for (int x = 0; x < size.x; x++)
                {
                    for (int y = 0; y < size.y; y++)
                    {
                        for (int z = 0; z < size.z; z++)
                        {
                            voxel[z * size.x * size.y + y * size.x + x] = voxelGenerator(size, x, y, z);
                        }
                    }
                }
                Stream          SaveFileStream = File.Create(path);
                BinaryFormatter serializer     = new BinaryFormatter();
                serializer.Serialize(SaveFileStream, voxel);
                SaveFileStream.Close();
            }

            UnityEngine.Debug.Log("executing Test:");

            for (int round = 0; round < ROUNDS; round++)
            {
                Stopwatch watch = Stopwatch.StartNew();

                if (limitCounter < CPU_LIMIT)
                {
                    List <Vector3> verts   = new List <Vector3>();
                    List <int>     indices = new List <int>();
                    List <Vector3> normals = new List <Vector3>();
                    marching.Generate(voxel, size.x, size.y, size.z, verts, indices, normals);

                    watch.Stop();

                    UnityEngine.Debug.LogFormat("\tCPU took {0}ms", watch.ElapsedMilliseconds);
                    perfData[(int)type].sizes[i].cpuTime[round] = (int)watch.ElapsedMilliseconds;
                    perfData[(int)type].sizes[i].cpuTriangles   = indices.Count / 3;
                }
                else
                {
                    UnityEngine.Debug.Log("\tCPU skipped");
                    perfData[(int)type].sizes[i].cpuTime[round] = -1;
                }

                if (limitCounter < PMB_LIMIT)
                {
                    VoxelBlock <Voxel> block = InitBlock(size);
                    UnityEngine.Debug.Log(voxel.Length + " " + voxel[0] + " " + voxel[1] + " " + voxel[2] + " " + voxel[3] + " " + voxel[4] + " " + voxel[5] + " " + voxel[6] + " " + voxel[7]);
                    helper.scheduleOnMainThread(() =>
                    {
                        watch = Stopwatch.StartNew();
                        pmb.ReInit(block);
                        RenderBuffers buffers = pmb.calculate(voxel, size.x, size.y, size.z, 0.5f);

                        int[] args = new int[4];
                        buffers.argsBuffer.GetData(args);
                        watch.Stop();

                        UnityEngine.Debug.LogFormat("\tPMB took {0}ms", watch.ElapsedMilliseconds);
                        perfData[(int)type].sizes[i].pmbTime[round] = (int)watch.ElapsedMilliseconds;
                        perfData[(int)type].sizes[i].pmbTriangles   = args[0] / 3;

                        buffers.vertexBuffer.Dispose();
                        buffers.indexBuffer.Dispose();
                        buffers.normalBuffer.Dispose();
                        buffers.argsBuffer.Dispose();

                        UnityEngine.Debug.Log("PMB triags inside thread: " + perfData[(int)type].sizes[i].pmbTriangles);
                    }).wait();
                    UnityEngine.Debug.Log("PMB triags after thread: " + perfData[(int)type].sizes[i].pmbTriangles);
                }
                else
                {
                    UnityEngine.Debug.Log("\tPMB skipped");
                    perfData[(int)type].sizes[i].pmbTime[round] = -1;
                    watch.Stop();
                }

                yield return(null);
            }
            limitCounter++;
        }
    }
Beispiel #3
0
    public override bool Calculate()
    {
        bool isPMB = false;

        if (!input.connected())
        {
            return(false);
        }
        VoxelBlock <Voxel> block = input.GetValue <VoxelBlock <Voxel> >();

        if (surfaceConnection.connected())
        {
            surface = surfaceConnection.GetValue <float>();
        }

        Marching marching = null;

        switch (mode)
        {
        case VerteGenerationMode.Tetrahedron:
            marching = new MarchingTertrahedron();
            break;

        case VerteGenerationMode.Cubes:
            marching = new MarchingCubes();
            break;

        case VerteGenerationMode.Voxel:
            marching = new VoxelGeneration();
            break;

        case VerteGenerationMode.PMB:
            isPMB = true;
            break;
        }

        //The size of voxel array.
        Vector3Int count  = block.VoxelCount;
        int        width  = count.x;
        int        height = count.y;
        int        length = count.z;

        float[] voxels = new float[width * height * length];

        for (int y = 0; y < height; y++)
        {
            Voxel[,] voxelLayer = block.Layers[y].Layer;
            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    int idx = x + y * width + z * width * height;
                    voxels[idx] = voxelLayer[x, z].GetValue();
                }
            }
        }

        if (isPMB)
        {
            var pmbTask = MainThreadHelper.instance().scheduleOnMainThread(() =>
            {
                pmb.ReInit(block);
                Stopwatch pmbWatch = Stopwatch.StartNew();
                buffers            = pmb.calculate(voxels, width, height, length, surface);
                pmbWatch.Stop();
                UnityEngine.Debug.LogFormat("PMB took {0}ms\n\t{1} voxels\n\t{2} triangles", pmbWatch.ElapsedMilliseconds, voxels.Count(), buffers.indexBuffer.count / 3);
            });

            pmbTask.wait();

            if (!pmbTask.completed)
            {
                return(false);
            }

            Block = block;
            return(true);
        }

        //Surface is the value that represents the surface of mesh
        //For example the perlin noise has a range of -1 to 1 so the mid point is where we want the surface to cut through.
        //The target value does not have to be the mid point it can be any value with in the range.
        //
        //This should be accesible by an input
        marching.Surface = surface;

        List <Vector3> verts   = new List <Vector3>();
        List <int>     indices = new List <int>();
        List <Vector3> normals = new List <Vector3>();

        Stopwatch sw = Stopwatch.StartNew();

        marching.Generate(voxels, width, height, length, verts, indices, normals);

        sw.Stop();

        UnityEngine.Debug.LogFormat("Marching took {0}ms\n\t{1} vertices; {2} triangles", sw.ElapsedMilliseconds, verts.Count(), indices.Count() / 3);

        sw.Restart();
        weldVertices(verts, indices, normals);
        sw.Stop();

        UnityEngine.Debug.LogFormat("Vertex welding took {0}ms\n\t {1} vertices left", sw.ElapsedMilliseconds, verts.Count());

        var task = MainThreadHelper.instance().scheduleOnMainThread(() =>
        {
            buffers = new RenderBuffers {
                vertexBuffer = new ComputeBuffer(verts.Count, sizeof(float) * 3),
                indexBuffer  = new ComputeBuffer(indices.Count, sizeof(int)),
                normalBuffer = new ComputeBuffer(normals.Count, sizeof(float) * 3),
                argsBuffer   = new ComputeBuffer(4, sizeof(int), ComputeBufferType.IndirectArguments),
            };

            buffers.vertexBuffer.SetData(verts);
            buffers.indexBuffer.SetData(indices);
            buffers.normalBuffer.SetData(normals);
            buffers.argsBuffer.SetData(new int[] { indices.Count, 1, 0, 0 });
        });

        task.wait();

        if (!task.completed)
        {
            return(false);
        }

        Block = block;

        return(true);
    }