public void RasterizeTriangle(Vector3 A, Vector3 B, Vector3 C, float voxelSize, int startX, int endX, int startZ, int endZ, Collector3.ShapeCollector volume, sbyte pass, byte area)
        {
            int minX = Mathf.Clamp(Mathf.RoundToInt(SomeMath.Min(A.x, B.x, C.x) / voxelSize) - 1, startX, endX);
            int minZ = Mathf.Clamp(Mathf.RoundToInt(SomeMath.Min(A.z, B.z, C.z) / voxelSize) - 1, startZ, endZ);
            int maxX = Mathf.Clamp(Mathf.RoundToInt(SomeMath.Max(A.x, B.x, C.x) / voxelSize) + 1, startX, endX);
            int maxZ = Mathf.Clamp(Mathf.RoundToInt(SomeMath.Max(A.z, B.z, C.z) / voxelSize) + 1, startZ, endZ);

            if (minX == maxX || minZ == maxZ)
            {
                return; //if too small return
            }
            Vector3[] vectorsStart = new Vector3[3] {
                A, B, C
            };

            for (int x = minX; x < maxX; ++x)
            {
                int vertsInLength1 = ClipPolyToPlane(1f, 0.0f, -x * voxelSize, vectorsStart, 3, ref _polyListXTemp);

                if (vertsInLength1 >= 3)
                {
                    int vertsInLength2 = ClipPolyToPlane(-1f, 0.0f, (x + 1) * voxelSize, _polyListXTemp, vertsInLength1, ref _polyListXFinal);

                    if (vertsInLength2 >= 3)
                    {
                        for (int z = minZ; z < maxZ; ++z)
                        {
                            int vertsInLength3 = ClipPolyToPlane(0.0f, 1f, -z * voxelSize, _polyListXFinal, vertsInLength2, ref _polyListZTemp);

                            if (vertsInLength3 >= 3)
                            {
                                int vertsInLength4 = ClipPolyToPlane(0.0f, -1f, (z + 1) * voxelSize, _polyListZTemp, vertsInLength3, ref _polyListZFinal);
                                if (vertsInLength4 >= 3)
                                {
                                    float min = _polyListZFinal[0].y;
                                    float max = _polyListZFinal[0].y;

                                    for (int index = 1; index < vertsInLength4; ++index)
                                    {
                                        min = Mathf.Min(min, _polyListZFinal[index].y);
                                        max = Mathf.Max(max, _polyListZFinal[index].y);
                                    }

                                    volume.SetVoxel(
                                        Mathf.Abs(x - startX),
                                        Mathf.Abs(z - startZ),
                                        min, max, pass, area);
                                }
                            }
                        }
                    }
                }
            }
        }
        //public void AppendTerrain(CSRasterization2DResult rasterizationResult, TerrainColliderInfoMesh terrainInfo) {
        //    var voxels = rasterizationResult.voxels;
        //    for (int x = 0; x < sizeX; x++) {
        //        for (int z = 0; z < sizeZ; z++) {
        //            var curVoxel = voxels[x + (z * sizeX)];
        //            if (curVoxel.exist)
        //                SetVoxel(x, z, curVoxel.height - 20f, curVoxel.height, (sbyte)curVoxel.passability);
        //        }
        //    }
        //}

        private  DataCompact[] GetTerrainCompactData(Vector3[] vrts, int[] trs) {
            var compactData = TakeCompactData();

            float maxSlopeCos = Mathf.Cos(template.maxSlope * Mathf.PI / 180.0f);
            float voxelSize = template.voxelSize;

            Vector3 realChunkPos = template.realOffsetedPosition;
            float chunkPosX = realChunkPos.x;
            float chunkPosZ = realChunkPos.z;

            int offsetX = Mathf.RoundToInt(chunkPosX / voxelSize);
            int offsetZ = Mathf.RoundToInt(chunkPosZ / voxelSize);

            int sizeX = template.lengthX_extra;
            int sizeZ = template.lengthZ_extra;

            //actual rasterization
            for (int i = 0; i < trs.Length; i += 3) {
                Vector3 A = vrts[trs[i]];
                Vector3 B = vrts[trs[i + 1]];
                Vector3 C = vrts[trs[i + 2]];

                sbyte passability = CalculateWalk(A, B, C, maxSlopeCos) ? (sbyte)Passability.Walkable : (sbyte)Passability.Slope;//if true then walkable else slope;

                int minX = Mathf.Clamp(Mathf.FloorToInt(SomeMath.Min(A.x, B.x, C.x) / voxelSize) - offsetX, 0, sizeX);
                int maxX = Mathf.Clamp(Mathf.CeilToInt(SomeMath.Max(A.x, B.x, C.x) / voxelSize) - offsetX, 0, sizeX);
                int minZ = Mathf.Clamp(Mathf.FloorToInt(SomeMath.Min(A.z, B.z, C.z) / voxelSize) - offsetZ, 0, sizeZ);
                int maxZ = Mathf.Clamp(Mathf.CeilToInt(SomeMath.Max(A.z, B.z, C.z) / voxelSize) - offsetZ, 0, sizeZ);

                for (int x = minX; x < maxX; x++) {
                    for (int z = minZ; z < maxZ; z++) {
                        float pointX = (x * voxelSize) + chunkPosX;
                        float pointZ = (z * voxelSize) + chunkPosZ;
                        if (SomeMath.LineSide(A.x, A.z, B.x, B.z, pointX, pointZ) <= 0.001 &
                            SomeMath.LineSide(B.x, B.z, C.x, C.z, pointX, pointZ) <= 0.001 &
                            SomeMath.LineSide(C.x, C.z, A.x, A.z, pointX, pointZ) <= 0.001) {
                            float height = SomeMath.CalculateHeight(A, B, C, pointX, pointZ);

                            compactData[GetIndex(x, z)].Update(height - 20, height, passability);
                        }
                    }
                }
            }

            return compactData;
        }
Beispiel #3
0
        public CSRasterization2DResult Rasterize(Vector3[] verts, int[] tris, int sizeX, int sizeZ, float chunkPosX, float chunkPosZ, float voxelSize, float maxSlopeCos, bool debug = false)
        {
            if (tris.Length == 0)
            {
                return(null);
            }

            int dsLength       = tris.Length / 3;
            int dsTargetLength = Mathf.Max(Mathf.CeilToInt((float)dsLength / (float)cellSizeX), 1) * cellSizeX;

            DataSegment2D[] ds        = new DataSegment2D[dsTargetLength];
            int             sizeTotal = sizeX * sizeZ;

            int offsetX = Mathf.RoundToInt(chunkPosX / voxelSize);
            int offsetZ = Mathf.RoundToInt(chunkPosZ / voxelSize);

            for (int i = 0; i < tris.Length; i += 3)
            {
                Vector3 A = verts[tris[i]];
                Vector3 B = verts[tris[i + 1]];
                Vector3 C = verts[tris[i + 2]];

                //making data segments
                //data segment represent:
                //triangle index
                //expected passablity based on inclanation
                //min and max indexes in grid to check it presence
                ds[i / 3] =
                    new DataSegment2D(
                        i,
                        (CalculateWalk(A, B, C, maxSlopeCos) ? 3 : 1),                                              //if true then walkable else slope;
                        Mathf.Clamp(Mathf.FloorToInt(SomeMath.Min(A.x, B.x, C.x) / voxelSize) - offsetX, 0, sizeX), //minX
                        Mathf.Clamp(Mathf.CeilToInt(SomeMath.Max(A.x, B.x, C.x) / voxelSize) - offsetX, 0, sizeX),  //maxX
                        Mathf.Clamp(Mathf.FloorToInt(SomeMath.Min(A.z, B.z, C.z) / voxelSize) - offsetZ, 0, sizeZ), //minZ
                        Mathf.Clamp(Mathf.CeilToInt(SomeMath.Max(A.z, B.z, C.z) / voxelSize) - offsetZ, 0, sizeZ)   //maxZ
                        );
            }

            int kernel = CS.FindKernel("Rasterize");

            ComputeBuffer vertsBuffer       = new ComputeBuffer(verts.Length, sizeof(float) * 3);
            ComputeBuffer trisBuffer        = new ComputeBuffer(tris.Length, sizeof(int));
            ComputeBuffer voxelBuffer       = new ComputeBuffer(sizeTotal, Voxel2D.stride);
            ComputeBuffer dataSegmentBuffer = new ComputeBuffer(dsTargetLength, DataSegment2D.stride);

            CS.SetInt("SizeX", sizeX);
            CS.SetInt("SizeZ", sizeZ);
            CS.SetVector("ChunkPos", new Vector4(chunkPosX, 0, chunkPosZ, 0));
            CS.SetFloat("VoxelSize", voxelSize);

            CS.SetBuffer(kernel, "CurTris", trisBuffer);
            CS.SetBuffer(kernel, "CurVerts", vertsBuffer);
            CS.SetBuffer(kernel, "Result", voxelBuffer);
            CS.SetBuffer(kernel, "TargetSegments", dataSegmentBuffer);

            vertsBuffer.SetData(verts);
            trisBuffer.SetData(tris);
            Voxel2D[] voxels = new Voxel2D[sizeTotal];

            for (int i = 0; i < sizeTotal; i++)
            {
                voxels[i].passability = -1;
            }


            voxelBuffer.SetData(voxels);
            dataSegmentBuffer.SetData(ds);
            CS.Dispatch(kernel, dsTargetLength / cellSizeX, 1, 1);
            voxelBuffer.GetData(voxels);

            CSRasterization2DResult result = new CSRasterization2DResult(voxels);


            //debug
#if UNITY_EDITOR
            if (debug)
            {
                Debuger_K.AddMesh(verts, tris, new Color(1, 0, 1, 0.1f));

                //implementation of things goint on in compute shader

                foreach (var dataSet in ds)
                {
                    Vector3 A = verts[tris[dataSet.index]];
                    Vector3 B = verts[tris[dataSet.index + 1]];
                    Vector3 C = verts[tris[dataSet.index + 2]];

                    for (int x = dataSet.minX; x < dataSet.maxX; x++)
                    {
                        for (int z = dataSet.minZ; z < dataSet.maxZ; z++)
                        {
                            float pointX = (x * voxelSize) + chunkPosX;
                            float pointZ = (z * voxelSize) + chunkPosZ;


                            //if (SomeMath.LineSide(B.x, B.z, A.x, A.z, pointX, pointZ) <= 0.001 &
                            //    SomeMath.LineSide(A.x, A.z, C.x, C.z, pointX, pointZ) <= 0.001 &
                            //    SomeMath.LineSide(C.x, C.z, B.x, B.z, pointX, pointZ) <= 0.001) {

                            //    float height = SomeMath.CalculateHeight(A, B, C, pointX, pointZ);
                            //    Debuger_K.AddDot(new Vector3((x * voxelSize) + chunkPosX, height, (z * voxelSize) + chunkPosZ));

                            //    Debuger_K.AddLine(A, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.green);
                            //    Debuger_K.AddLine(B, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.green);
                            //    Debuger_K.AddLine(C, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.green);
                            //}
                            //else {
                            //    Debuger_K.AddLine(A, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.red);
                            //    Debuger_K.AddLine(B, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.red);
                            //    Debuger_K.AddLine(C, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.red);
                            //}


                            if (SomeMath.PointInTriangleSimple(A, B, C, pointX, pointZ))
                            {
                                float height = SomeMath.CalculateHeight(A, B, C, pointX, pointZ);
                                Debuger_K.AddDot(new Vector3((x * voxelSize) + chunkPosX, height, (z * voxelSize) + chunkPosZ));

                                //Debuger_K.AddLine(A, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.green);
                                //Debuger_K.AddLine(B, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.green);
                                //Debuger_K.AddLine(C, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.green);
                            }
                            else
                            {
                                //Debuger_K.AddLine(A, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.red);
                                //Debuger_K.AddLine(B, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.red);
                                //Debuger_K.AddLine(C, new Vector3((x * voxelSize) + chunkPosX, 0, (z * voxelSize) + chunkPosZ), Color.red);
                            }
                        }
                    }
                }

                //for (int x = 0; x < sizeX; x++) {
                //    for (int z = 0; z < sizeZ; z++) {
                //        var curVoxel = voxels[x + (z * sizeX)];
                //        if (curVoxel.exist) {
                //            Debuger_K.AddDot(new Vector3((x * voxelSize) + chunkPosX, curVoxel.height, (z * voxelSize) + chunkPosZ));
                //        }
                //    }
                //}
            }
#endif

            vertsBuffer.Dispose();
            trisBuffer.Dispose();
            voxelBuffer.Dispose();
            dataSegmentBuffer.Dispose();
            return(result);
        }