Пример #1
0
        private static List <ScanResultLOD> GetCenterPointList(
            Transform transform,
            GameObjectShape shape)
        {
            // Single ScanResultLOD for lowest LOD.
            var result = ScanResultLOD.CreateList(1);

            Matrix4x4 matrix  = transform.worldToLocalMatrix;
            bool      flatten = shape.Flatten;

            foreach (Volume vol in s_Volumes)
            {
                Vector3 localPoint = matrix.MultiplyPoint3x4(vol.Bounds.center);
                if (flatten)
                {
                    localPoint.y = 0;
                }
                result[0].LocalPoints.Add(localPoint);
            }

            return(result);
        }
Пример #2
0
        private static List <ScanResultLOD> GetLODPointLists(
            PhysicsScene scene,
            Transform transform,
            GameObjectShape shape)
        {
            SplitVolumesIntoCells(shape.ScanLOD);

            int  mask    = 1 << transform.gameObject.layer;
            bool flatten = shape.Flatten;

            var result = ScanResultLOD.CreateList(flatten ? 1 : s_GlobalMaxLOD + 1);

            foreach (Volume vol in s_Volumes)
            {
                ToggleActiveColliders(vol);

                bool       isConcave       = vol.IsConcave;
                Vector3    cellSize        = vol.CellSize;
                Vector3Int gridSize        = vol.GridSize;
                Vector3    offset          = vol.Bounds.min + cellSize * 0.5f;
                Vector3    boundsCenter    = vol.Bounds.center;
                float      boundsMagnitude = vol.Bounds.size.magnitude;
                int        nx = gridSize.x - 1;
                int        ny = gridSize.y - 1;
                int        nz = gridSize.z - 1;


                // Find cells occupied by colliders.

                Clear(gridSize);

                for (int x = 0; x <= nx; x++)
                {
                    for (int y = 0; y <= ny; y++)
                    {
                        for (int z = 0; z <= nz; z++)
                        {
                            Vector3 worldPoint = Vector3.Scale(
                                new Vector3(x, y, z), cellSize) + offset;

                            bool isInside = isConcave
                                ? IsInsideCollider(
                                scene, mask, worldPoint, vol.Bounds)
                                : IsInsideCollider(
                                scene, mask, worldPoint, vol.Colliders);

                            s_HollowGrid[x, y, z] = isInside;
                            s_FilledGrid[x, y, z] = isInside;
                        }
                    }
                }


                // Reduce cell count, hollow out filled grid.

                for (int x = 1; x < nx; x++)
                {
                    for (int y = 1; y < ny; y++)
                    {
                        for (int z = 1; z < nz; z++)
                        {
                            if (s_FilledGrid[x, y, z])
                            {
                                s_HollowGrid[x, y, z] &=
                                    !(s_FilledGrid[x - 1, y, z]
                                      & s_FilledGrid[x + 1, y, z]
                                      & s_FilledGrid[x, y - 1, z]
                                      & s_FilledGrid[x, y + 1, z]
                                      & s_FilledGrid[x, y, z - 1]
                                      & s_FilledGrid[x, y, z + 1]);
                            }
                        }
                    }
                }


                // Downsample cells for generating LODs
                // and store points in corresponding groups.

                int   level = flatten ? 0 : vol.MaxLOD;
                float yFlat = transform.position.y;

                for (int x = 0; x <= nx; x++)
                {
                    for (int y = 0; y <= ny; y++)
                    {
                        for (int z = 0; z <= nz; z++)
                        {
                            if (s_HollowGrid[x, y, z])
                            {
                                Cell    cell       = new Cell(level, x, y, z);
                                Vector3 worldPoint = cell.Scale(cellSize) + offset;

                                if (flatten)
                                {
                                    cell.y       = 0;
                                    worldPoint.y = yFlat;
                                }

                                // Highest LOD.
                                AddPoint(cell, worldPoint);

                                for (int i = level; i > 0; i--)
                                {
                                    cell = cell.Downsample();
                                    AddPoint(cell, worldPoint);
                                }
                            }
                        }
                    }
                }


                // Write centroids to result.

                Matrix4x4 matrix     = transform.worldToLocalMatrix;
                float     projection = shape.Projection;
                bool      project    = projection > 0;

                foreach (var kvp in s_PointGroupsByCell)
                {
                    // KeyValuePair, Key: Cell, Value: PointGroup.
                    int     i          = kvp.Key.level;
                    Vector3 worldPoint = kvp.Value.Centroid;

                    if (project && i > 0)
                    {
                        // Project outward from volume bounds center,
                        // unless lowest LOD or flattened points -> i == 0.
                        // NOTE Doesn't work well with compound or concave colliders.
                        Vector3 normal = (worldPoint - boundsCenter).normalized;
                        if (scene.Raycast(boundsCenter + normal * boundsMagnitude,
                                          -normal, out RaycastHit hit, boundsMagnitude, mask))
                        {
                            worldPoint = Vector3.Lerp(worldPoint, hit.point, projection);
                        }
                    }
                    // World -> local.
                    result[i].LocalPoints.Add(matrix.MultiplyPoint3x4(worldPoint));
                }
            }

            ToggleActiveColliders();

            return(result);
        }