public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            AreaAttribute area = attribute as AreaAttribute;

            EditorGUI.BeginProperty(position, label, property);

            if (property.propertyType != SerializedPropertyType.Integer)
            {
                EditorGUI.LabelField(position, label.text, "Use this attribute with Integer");
            }
            else
            {
                if (area.drawLabel & (label.text != string.Empty))
                {
                    position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
                }

                int value = property.intValue;

                //GUI.Label(new Rect(position.x, position.y, idWidth, position.height), value.ToString());

                Area pathFinderArea = PathFinder.GetArea(value);
                if (pathFinderArea == null)
                {
                    property.intValue = 0;
                    pathFinderArea    = PathFinder.GetArea(0);
                }

                TextAnchor curAnchor = GUI.skin.box.alignment;
                GUI.skin.box.alignment = TextAnchor.MiddleCenter;
                Color curColor = GUI.color;
                GUI.color = pathFinderArea.color;
                GUI.Box(new Rect(position.x, position.y, colorBoxWidth, position.height), value.ToString());
                GUI.color = curColor;
                GUI.skin.box.alignment = curAnchor;

                EditorGUI.BeginChangeCheck();
                value = EditorGUI.IntPopup(
                    new Rect(position.x + colorBoxWidth, position.y, position.width - colorBoxWidth, position.height),
                    value, PathFinder.settings.areaNames, PathFinder.settings.areaIDs);
                if (EditorGUI.EndChangeCheck())
                {
                    property.intValue = value;
                }
            }

            EditorGUI.EndProperty();
        }
Пример #2
0
 public Area GetArea()
 {
     return(PathFinder.GetArea(areaInt));
 }
Пример #3
0
        //not main thread
        public override void Collect(VolumeContainer container)
        {
            Area defaultArea = PathFinder.GetArea(0);

            foreach (var terrain in _terrainsInfo)
            {
                //terrain
                Volume terrainVolume;

                if (terrain.alphaMap != null)
                {
                    terrainVolume = new Volume(template.lengthX_extra, template.lengthZ_extra, terrain.possibleArea);
                }
                else
                {
                    terrainVolume = new Volume(template.lengthX_extra, template.lengthZ_extra, defaultArea);
                }

                terrainVolume.terrain = true;

                float[][] heightMap      = terrain.heightMap;
                int[][]   passabilityMap = terrain.passabilityMap;

                var areaLibrary = PathFinder.settings.areaLibrary;

                //apply terrain area info if it exist
                //SetTerrainArea(terrainVolume, terrain, defaultArea);
                if (terrain.alphaMap != null)
                {
                    int[][] areaMap = ProcessAlphaMap(terrain);

                    for (int x = 0; x < template.lengthX_extra; x++)
                    {
                        for (int z = 0; z < template.lengthZ_extra; z++)
                        {
                            terrainVolume.SetVoxel(x, z, heightMap[x][z], areaLibrary[areaMap[x][z]], passabilityMap[x][z]);

                            if (areaMap[x][z] == 1)
                            {
                                terrainVolume.SetPassability(x, z, Passability.Unwalkable);
                            }
                        }
                    }
                }
                else
                {
                    for (int x = 0; x < template.lengthX_extra; x++)
                    {
                        for (int z = 0; z < template.lengthZ_extra; z++)
                        {
                            terrainVolume.SetVoxel(x, z, heightMap[x][z], defaultArea, passabilityMap[x][z]);
                        }
                    }
                }

                terrainVolume.SetVolumeMinimum(-1000f);

                //trees
                Volume treeVolume = base.CollectTrees(terrain);

                //connecting terrain and trees to single volume
                if (treeVolume != null)
                {
                    terrainVolume.Subtract(treeVolume);
                    terrainVolume.ConnectToItself();
                    terrainVolume.Override(treeVolume);
                }

                //sent terrain to container
                container.AddVolume(terrainVolume);
                //container.AddVolume(treeVolume);
            }
        }
Пример #4
0
        private void AddColliderTerrain(Collider collider, TerrainCollectorType terrainCollectionType)
        {
            Terrain terrain = collider.GetComponent <Terrain>();

            if (terrain == null | terrain.enabled == false)
            {
                return;
            }

            if (profiler != null)
            {
                profiler.AddLogFormat("collecting terrain {0}", terrain.gameObject.name);
            }

            TerrainColliderInfoMesh info = new TerrainColliderInfoMesh(terrain);

            info.trees = CollectTreeData(terrain);

            //general stuff
            float   voxelSize      = template.voxelSize;
            Bounds  offsetedBounds = template.chunkOffsetedBounds;
            Vector3 boundsMin      = offsetedBounds.min;
            Vector3 boundsMax      = offsetedBounds.max;

            float minSize = PathFinder.settings.terrainFastMinimalSize;

            //terrain stuff
            TerrainData data     = terrain.terrainData;
            Vector3     position = terrain.transform.position;
            Vector3     scale    = data.size;

            //height map
            int resolution = 1;

            int heightMapSizeX = data.heightmapWidth;
            int heightMapSizeZ = data.heightmapHeight;

            float hScaleX = scale.x / (heightMapSizeX - 1);
            float hScaleZ = scale.z / (heightMapSizeZ - 1);

            for (int i = 0; i < 4; i++)
            {
                if (minSize > hScaleX * resolution)
                {
                    resolution = (int)Mathf.Pow(2, i);
                }
                else
                {
                    break;
                }
            }

            int hTargetMinX = Mathf.Clamp(((Mathf.RoundToInt((boundsMin.x - position.x) / hScaleX) / resolution) - 1) * resolution, 0, heightMapSizeX);
            int hTargetMinZ = Mathf.Clamp(((Mathf.RoundToInt((boundsMin.z - position.z) / hScaleZ) / resolution) - 1) * resolution, 0, heightMapSizeX);

            int hTargetMaxX = Mathf.Clamp(((Mathf.RoundToInt((boundsMax.x - position.x) / hScaleX) / resolution) + 1) * resolution + 1, 0, heightMapSizeX);
            int hTargetMaxZ = Mathf.Clamp(((Mathf.RoundToInt((boundsMax.z - position.z) / hScaleZ) / resolution) + 1) * resolution + 1, 0, heightMapSizeX);

            int hSizeX = hTargetMaxX - hTargetMinX;
            int hSizeZ = hTargetMaxZ - hTargetMinZ;

            int hTargetSizeX = hSizeX / resolution + 1;
            int hTargetSizeZ = hSizeZ / resolution + 1;

            if (resolution == 1)
            {
                hTargetSizeX = hSizeX;
                hTargetSizeZ = hSizeZ;
            }


            info.heightMap    = data.GetHeights(hTargetMinX, hTargetMinZ, hSizeX, hSizeZ);
            info.heightMatrix = Matrix4x4.TRS(
                position + new Vector3(hScaleX * hTargetMinX, 0, hScaleZ * hTargetMinZ),
                Quaternion.identity,
                new Vector3(hScaleX * resolution, scale.y, hScaleZ * resolution));

            info.hSizeX     = hTargetSizeX;
            info.hSizeZ     = hTargetSizeZ;
            info.resolution = resolution;

            //rest
            VectorInt.Vector3Int terrainStartInt = new VectorInt.Vector3Int((position / voxelSize) + template.halfVoxelOffset);
            VectorInt.Vector3Int terrainEndInt   = new VectorInt.Vector3Int((position + data.size) / voxelSize + template.halfVoxelOffset);

            int startXClamp = Mathf.Clamp(terrainStartInt.x, template.startX_extra, template.endX_extra);
            int startZClamp = Mathf.Clamp(terrainStartInt.z, template.startZ_extra, template.endZ_extra);

            int endXClamp = Mathf.Clamp(terrainEndInt.x, template.startX_extra, template.endX_extra);
            int endZClamp = Mathf.Clamp(terrainEndInt.z, template.startZ_extra, template.endZ_extra);

            int terrainStartX = terrainStartInt.x;
            int terrainStartZ = terrainStartInt.z;

            float terrainSizeX = terrainEndInt.x - terrainStartX;
            float terrainSizeZ = terrainEndInt.z - terrainStartZ;

            var navmeshSettings = terrain.gameObject.GetComponent <TerrainNavmeshSettings>();

            if (navmeshSettings != null && navmeshSettings.isActiveAndEnabled && navmeshSettings.data.Any(x => x != 0))  //0 is default so if there is settings full of deffault areas then dont need that
            {
                Vector3 size = data.size;
                info.settings    = navmeshSettings;
                info.startXClamp = startXClamp;
                info.startZClamp = startZClamp;

                info.endXClamp = endXClamp;
                info.endZClamp = endZClamp;

                info.terrainStartX = terrainStartX;
                info.terrainStartZ = terrainStartZ;

                info.terrainSizeX = terrainSizeX;
                info.terrainSizeZ = terrainSizeZ;

                //all this values needed in 2 places. here to use data.GetAlphamaps in main thread and later in not main thread
                //so we just store it in terrain collider info
                info.alphaWidth  = data.alphamapWidth;
                info.alphaHeight = data.alphamapHeight;

                //normalized start and end
                //dont needed later
                float terNormStartX = Mathf.Clamp01((template.chunkData.realX - template.properties.radius - position.x) / size.x);
                float terNormStartZ = Mathf.Clamp01((template.chunkData.realZ - template.properties.radius - position.z) / size.z);

                float terNormEndX = Mathf.Clamp01((template.chunkData.realX + PathFinder.gridSize + template.properties.radius - position.x) / size.x);
                float terNormEndZ = Mathf.Clamp01((template.chunkData.realZ + PathFinder.gridSize + template.properties.radius - position.z) / size.z);

                //alpha map position of chunk
                info.alphaStartX = Mathf.RoundToInt(terNormStartX * info.alphaWidth);
                info.alphaStartZ = Mathf.RoundToInt(terNormStartZ * info.alphaHeight);

                //alpha map size of chunk
                //size needed only now
                info.alphaSizeX = Mathf.Min(Mathf.RoundToInt((terNormEndX - terNormStartX) * info.alphaWidth) + 1, info.alphaWidth - info.alphaStartX);
                info.alphaSizeZ = Mathf.Min(Mathf.RoundToInt((terNormEndZ - terNormStartZ) * info.alphaHeight) + 1, info.alphaHeight - info.alphaStartZ);

                info.alphaMap     = data.GetAlphamaps(info.alphaStartX, info.alphaStartZ, info.alphaSizeX, info.alphaSizeZ);
                info.possibleArea = (from areaID in navmeshSettings.data select PathFinder.GetArea(areaID)).ToArray(); //else if doCollectAreaInfo == false than later it became defaul area
            }

            switch (terrainCollectionType)
            {
            case TerrainCollectorType.CPU:
                terrainsInfoForCPU.Add(info);
                break;

            case TerrainCollectorType.ComputeShader:
                CollectTerrainOnGPU(info);
                break;
            }
        }
        private void AddColliderGenericGPU(Collider collider)
        {
            Matrix4x4 matrix            = Matrix4x4.identity;
            Transform colliderTransform = collider.transform;

            Vector3[] verts  = null;
            int[]     tris   = null;
            Bounds    bounds = collider.bounds;

            if (collider is BoxCollider)
            {
                verts  = cubeVerts;
                tris   = cubeTris;
                matrix = Matrix4x4.TRS(bounds.center, colliderTransform.rotation, Vector3.Scale(colliderTransform.lossyScale, (collider as BoxCollider).size));
            }

            else if (collider is SphereCollider)
            {
                verts = sphereVerts;
                tris  = sphereTris;
                float r = bounds.extents.x / 0.5f;
                matrix = Matrix4x4.TRS(bounds.center, Quaternion.identity, new Vector3(r, r, r));
            }

            else if (collider is CapsuleCollider)
            {
                tris  = capsuleTris;
                verts = new Vector3[capsuleVerts.Length];
                CapsuleCollider capsuleCollider = collider as CapsuleCollider;

                Vector3 lossyScale = colliderTransform.lossyScale;
                float   height     = capsuleCollider.height * lossyScale.y;
                float   radius     = capsuleCollider.radius * Mathf.Max(lossyScale.x, lossyScale.z);

                float     size = Mathf.Max(1f, height / (radius * 2f)) - 2f;
                Matrix4x4 capsuleShapeMatrix = Matrix4x4.Scale(new Vector3(radius * 2f, radius * 2f, radius * 2f));

                for (int index = 0; index < verts.Length; ++index)
                {
                    if (capsuleVerts[index].y > 0.0)
                    {
                        verts[index] = capsuleShapeMatrix.MultiplyPoint(
                            new Vector3(
                                capsuleVerts[index].x,
                                Mathf.Max((float)(capsuleVerts[index].y + size * 0.5), 0.0f),
                                capsuleVerts[index].z));
                    }

                    else if (capsuleVerts[index].y < 0.0)
                    {
                        verts[index] = capsuleShapeMatrix.MultiplyPoint(
                            new Vector3(
                                capsuleVerts[index].x,
                                Mathf.Min((float)(capsuleVerts[index].y - size * 0.5), 0.0f),
                                capsuleVerts[index].z));
                    }
                }

                matrix = Matrix4x4.TRS(
                    capsuleCollider.bounds.center, //actual world position
                    colliderTransform.rotation *   //world rotation
                    Quaternion.Euler(              //plus capsule orientation
                        capsuleCollider.direction == 2 ? 90f : 0.0f,
                        0.0f,
                        capsuleCollider.direction == 0 ? 90f : 0.0f),
                    Vector3.one);
            }

            else if (collider is CharacterController)
            {
                tris  = capsuleTris;
                verts = new Vector3[capsuleVerts.Length];
                CharacterController charControler = collider as CharacterController;

                Vector3 lossyScale = colliderTransform.lossyScale;
                float   height     = charControler.height * lossyScale.y;
                float   radius     = charControler.radius * Mathf.Max(lossyScale.x, lossyScale.z);

                float     size = Mathf.Max(1f, height / (radius * 2f)) - 2f;
                Matrix4x4 capsuleShapeMatrix = Matrix4x4.Scale(new Vector3(radius * 2f, radius * 2f, radius * 2f));

                for (int index = 0; index < verts.Length; ++index)
                {
                    if (capsuleVerts[index].y > 0.0)
                    {
                        verts[index] = capsuleShapeMatrix.MultiplyPoint(new Vector3(capsuleVerts[index].x, Mathf.Max((float)(capsuleVerts[index].y + size * 0.5), 0.0f), capsuleVerts[index].z));
                    }
                    else if (capsuleVerts[index].y < 0.0)
                    {
                        verts[index] = capsuleShapeMatrix.MultiplyPoint(new Vector3(capsuleVerts[index].x, Mathf.Min((float)(capsuleVerts[index].y - size * 0.5), 0.0f), capsuleVerts[index].z));
                    }
                }

                matrix = Matrix4x4.TRS(charControler.bounds.center, colliderTransform.rotation, Vector3.one);
            }

            else if (collider is MeshCollider)
            {
                Mesh curMesh = (collider as MeshCollider).sharedMesh;
                verts  = curMesh.vertices;
                tris   = curMesh.triangles;
                matrix = colliderTransform.localToWorldMatrix;
            }

            else
            {
                Debug.LogFormat("hey i dont know wich collider type is on {0}. please tell developer to fix that.", collider.gameObject.name);
                return;
            }

            var  gameObjectArea = collider.transform.GetComponent <AreaGameObject>();
            Area area;

            if (gameObjectArea != null)
            {
                area = PathFinder.GetArea(gameObjectArea.areaInt);
            }
            else
            {
                if (PathFinder.settings.checkRootTag)
                {
                    area = PathFinderSettings.tagAssociations[collider.transform.root.tag];
                }
                else
                {
                    area = PathFinderSettings.tagAssociations[collider.transform.tag];
                }
            }

            if (verts != null & tris != null)
            {
                float   maxSlopeCos = Mathf.Cos(template.maxSlope * Mathf.PI / 180f);
                Vector3 offsetedPos = template.realOffsetedPosition;


                CSRasterization3DResult result = PathFinder.sceneInstance.Rasterize3D(
                    verts, tris, bounds, matrix,
                    template.lengthX_extra, template.lengthZ_extra,
                    offsetedPos.x, offsetedPos.z,
                    template.voxelSize,
                    maxSlopeCos,
                    false,
                    false);

                if (result != null)
                {
                    collectedComputeShaderData.Add(new ComputeShaderResultHolder(result, ColliderInfoMode.Solid, area));
                }
            }
        }
Пример #6
0
 public void SetGoalFindNearestArea(int globalDictionaryID, float maxSearchCost, bool snapToNavMesh = true, bool applyRaycast = false)
 {
     SetGoalFindNearestArea(PathFinder.GetArea(globalDictionaryID), maxSearchCost, snapToNavMesh, applyRaycast);
 }
Пример #7
0
        //not main thread
        public override void Collect(VolumeContainer container)
        {
            Area  defaultArea = PathFinder.GetArea(0);
            float maxSlopeCos = Mathf.Cos((float)((double)template.maxSlope * Math.PI / 180.0));
            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;

            foreach (var terrain in terrainsInfo)
            {
                Volume terrainVolume;
                if (terrain.alphaMap != null)
                {
                    terrainVolume = new Volume(template.lengthX_extra, template.lengthZ_extra, terrain.possibleArea);
                }
                else
                {
                    terrainVolume = new Volume(template.lengthX_extra, template.lengthZ_extra, defaultArea);
                }

                terrainVolume.terrain = true;

                Vector3[] vrts;
                int[]     trs;
                GetTerrainMesh(terrain, out vrts, out trs);

                //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]];

                    int passability = CalculateWalk(A, B, C, maxSlopeCos) ? 3 : 1;//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)
                            {
                                terrainVolume.SetVoxelLight(x, z, SomeMath.CalculateHeight(A, B, C, pointX, pointZ), passability);
                            }
                        }
                    }
                }

                //var areaLibrary = PathFinder.settings.areaLibrary;

                SetTerrainArea(terrainVolume, terrain, defaultArea); //apply terrain area info if it exist

                terrainVolume.SetVolumeMinimum(-1000f);

                //trees
                Volume treeVolume = base.CollectTrees(terrain);

                //connecting terrain and trees to single volume
                if (treeVolume != null)
                {
                    terrainVolume.Subtract(treeVolume);
                    terrainVolume.ConnectToItself();
                    terrainVolume.Override(treeVolume);
                }

                //sent terrain to container
                container.AddVolume(terrainVolume);
            }
        }