示例#1
0
        private void Awake()
        {
            UnityEngine.Bounds mapBoundsWorldSpace = this.Map.GetComponent <UnityEngine.MeshRenderer>().bounds;

            WorldBounds = new WorldBounds
            {
                //The world scale must be an integer value, or you will encounter floating point errors with the grid system
                XZGridSize = gridSize,
                //LEFT BOTTOM CORNER
                XZGridWorldSpaceMin = new int2
                                      (
                    //Only works with symmetrical shapes and assumes its centered at 0/0/0
                    (int)math.floor(-mapBoundsWorldSpace.extents.x),
                    (int)math.floor(-mapBoundsWorldSpace.extents.z)
                                      ),
                //TOP RIGHT CORNER
                XZGridWorldSpaceMax = new int2
                                      (
                    //Only works with symmetrical shapes
                    //Only works with symmetrical shapes and assumes its centered at 0/0/0
                    (int)math.floor(mapBoundsWorldSpace.extents.x),
                    (int)math.floor(mapBoundsWorldSpace.extents.z)
                                      ),
                WorldSpaceCellSize = gridCellSize
            };
        }
示例#2
0
    // get world bound coordinates


    WorldBounds getWorldBounds()
    {
        GameObject[] outerwalls = GameObject.FindGameObjectsWithTag("outerWall");

        WorldBounds wb = new WorldBounds();

        List <GameObject> horizontalWalls = new List <GameObject>();
        List <GameObject> verticalWalls   = new List <GameObject>();

        foreach (GameObject outerWall in outerwalls)
        {
            if (outerWall.transform.rotation.y == 0)
            {
                horizontalWalls.Add(outerWall);
            }
            else
            {
                verticalWalls.Add(outerWall);
            }
        }

        float zmax = Single.MinValue, zmin = Single.MaxValue;


        foreach (GameObject horwall in horizontalWalls)
        {
            if (horwall.transform.position.z > zmax)
            {
                zmax = horwall.transform.position.z;
            }

            if (horwall.transform.position.z < zmin)
            {
                zmin = horwall.transform.position.z;
            }
        }

        float xmax = Single.MinValue, xmin = Single.MaxValue;

        foreach (GameObject verWall in verticalWalls)
        {
            if (verWall.transform.position.x > xmax)
            {
                xmax = verWall.transform.position.x;
            }

            if (verWall.transform.position.x < xmin)
            {
                xmin = verWall.transform.position.x;
            }
        }

        wb.topleft     = new Vector3(xmin, verticalWalls[0].transform.position.y, zmax);
        wb.topright    = new Vector3(xmax, verticalWalls[0].transform.position.y, zmax);
        wb.bottomleft  = new Vector3(xmin, verticalWalls[0].transform.position.y, zmin);
        wb.bottomright = new Vector3(xmax, verticalWalls[0].transform.position.y, zmin);

        return(wb);
    }
示例#3
0
 public static int2 WorldSpaceToCell(this WorldBounds worldBounds, float3 worldSpace)
 {
     return(new int2
            (
                WorldSpaceToCell(worldSpace.x, worldBounds.XZGridWorldSpaceMin.x, 0, worldBounds.XZGridSize.x, worldBounds),
                WorldSpaceToCell(worldSpace.z, worldBounds.XZGridWorldSpaceMin.y, 0, worldBounds.XZGridSize.y, worldBounds)
            ));
 }
示例#4
0
 public static float3 CellToWorldSpace(this WorldBounds worldBounds, int2 cell, float overrideY = 0f)
 {
     //Pathfinding grid is on x, z components (2d) but cell is x and y
     return(new float3
            (
                CellToWorldSpace(cell.x, worldBounds.XZGridWorldSpaceMin.x, worldBounds),
                overrideY,
                CellToWorldSpace(cell.y, worldBounds.XZGridWorldSpaceMin.y, worldBounds)
            ));
 }
        //Calculate the whole pathfinding grid in a fixed interval to save performance.
        protected override void OnUpdate()
        {
            this.currentTime += Time.DeltaTime;

            if (this.currentTime >= UpdateInterval)
            {
                Entity      worldBoundsEntity = this.GetEntityQuery(this.EntityManager.GetWorldBoundsIdentifier()).GetSingletonEntity();
                WorldBounds worldBounds       = this.EntityManager.GetComponentData <WorldBounds>(worldBoundsEntity);

                CollisionWorld collisionWorldForJob = this.physicsWorld.PhysicsWorld.CollisionWorld;

                //SystemBase Dependency for the Physics system -> This system must wait for the phyiscs world to complete in order to create a new parallel jobs
                this.Dependency = JobHandle.CombineDependencies(Dependency, this.physicsWorld.FinalJobHandle);

                //Can not take the collider, because the raycast does not allow to query a object gridbased -> it detects hit only once, even if multiple boxcasts are present
                //So we take the world render bounds and the AABB of the world render bounds
                NativeArray <WorldRenderBounds> worldRenderBoundsOfObstacles = this.GetEntityQuery(this.EntityManager.GetRenderableTypes()
                                                                                                   .Concat(new ComponentType[] { this.EntityManager.GetObstacleIdentifier() }).ToArray())
                                                                               .ToComponentDataArray <WorldRenderBounds>(Allocator.TempJob);

                this.Dependency = JobHandle.CombineDependencies(this.Dependency,
                                                                this.Entities
                                                                .ForEach((Entity entity, ref PathNode pathNode) =>
                {
                    //Get AABB from cubic shape of each path node
                    float3 bottomLeft = worldBounds.CellToWorldSpace(new int2(pathNode.X, pathNode.Y));
                    float3 topRight   = worldBounds.CellToWorldSpace(new int2(pathNode.X + 1, pathNode.Y + 1));
                    float3 center     = (bottomLeft + topRight) / 2;

                    AABB pathNodeAABB = new AABB
                    {
                        Center  = center,
                        Extents = worldBounds.WorldSpaceCellSize
                    };

                    //Check if there is any worldRenderBoundsObstacle that intersects the AABB of pathNode
                    for (int i = 0; i < worldRenderBoundsOfObstacles.Length; ++i)
                    {
                        //Unfortunately have to cast to bounds to get the intersects method, the ecs struct only has a contains which is not the same
                        if (worldRenderBoundsOfObstacles[i].Value.ToBounds().Intersects(pathNodeAABB.ToBounds()))
                        {
                            pathNode.IsTraversable = false;
                            break;
                        }
                    }
                })
                                                                .WithDeallocateOnJobCompletion(worldRenderBoundsOfObstacles)
                                                                .ScheduleParallel(this.Dependency));

                this.Dependency.Complete();
                this.currentTime = 0f;
            }
        }
        public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
        {
            WorldBounds worldBounds = WorldBoundsStaticAccessor.WorldBounds;

            UnityEngine.Mesh      altarMesh      = altarGameObject.GetComponent <UnityEngine.MeshFilter>().mesh;
            UnityEngine.Material  altarMaterial  = altarGameObject.GetComponent <UnityEngine.MeshRenderer>().material;
            UnityEngine.Transform altarTransform = altarGameObject.GetComponent <UnityEngine.Transform>();

            using (NativeArray <Entity> altar = dstManager.CreateEntity(dstManager.CreateAltarArchetype(), 1, Allocator.Temp))
            {
                dstManager.SetComponentData(altar[0], new Translation
                {
                    Value = new float3
                            (
                        UnityEngine.Random.Range(worldBounds.XZGridWorldSpaceMin.x, worldBounds.XZGridWorldSpaceMax.x),
                        0f,
                        UnityEngine.Random.Range(worldBounds.XZGridWorldSpaceMin.y, worldBounds.XZGridWorldSpaceMax.y)
                            )
                });

                dstManager.SetComponentData(altar[0], new NonUniformScale
                {
                    Value = altarMesh.bounds.size
                });

                dstManager.SetComponentData(altar[0], new Rotation
                {
                    Value = altarTransform.rotation
                });

                dstManager.SetComponentData(altar[0], new PhysicsCollider
                {
                    Value = BoxCollider.Create
                            (
                        CollisionGeomeotrySingleton.Instance.CreateOrGetBoxGeometry(this.colliderScale),
                        CollisionFilterSingleton.Instance.CollidesWithPlayerFilter
                            )
                });

                dstManager.SetSharedComponentData <RenderMesh>(altar[0], new RenderMesh
                {
                    mesh     = altarMesh,
                    material = altarMaterial
                });
            }

            DestroyImmediate(this.altarGameObject);
        }
示例#7
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="xBlocks">Number of x blocks to represent the world</param>
        /// <param name="yBlocks">Number of y blocks to represent the world</param>
        /// <param name="bounds">World boundries</param>
        public WorldGrid(int xBlocks, int yBlocks, WorldBounds bounds)
        {
            _numXBlocks = xBlocks;
            _numYBlocks = yBlocks;
            _xBlockWidth = (float)bounds.XBound / (float)xBlocks;
            _yBlockHeight = (float)bounds.YBound / (float)yBlocks;

            _buckets = new GridBucket[_numXBlocks, _numYBlocks];

            // Initiliase the buckets
            for (int x = 0; x < _numXBlocks; x++)
            {
                for (int y = 0; y < _numYBlocks; y++)
                {
                    GridBucket bucket = new GridBucket();
                    _buckets[x, y] = bucket;
                }
            }
        }
示例#8
0
    //generate walls
    void generatewalls()
    {
        GameObject[] walls      = GameObject.FindGameObjectsWithTag("wall");
        GameObject[] outerwalls = GameObject.FindGameObjectsWithTag("outerWall");

        GameObject[] totalWalls = new GameObject[walls.Length + outerwalls.Length];

        walls.CopyTo(totalWalls, 0);
        outerwalls.CopyTo(totalWalls, walls.Length);

        WorldBounds wb = getWorldBounds();

        //placing two walls
        bool success = false;

        float xcord = wb.topleft.x + (wb.topright.x - wb.topleft.x) * UnityEngine.Random.Range(0.1f, 1.0f);
        float zcord = wb.bottomleft.z + (wb.topleft.z - wb.bottomleft.z) * UnityEngine.Random.Range(0.1f, 1.0f);

        float xcord1 = wb.topleft.x + (wb.topright.x - wb.topleft.x) * UnityEngine.Random.Range(0.1f, 1.0f);
        float zcord1 = wb.bottomleft.z + (wb.topleft.z - wb.bottomleft.z) * UnityEngine.Random.Range(0.1f, 1.0f);

        success = false;

        //try placing wall with random coordinates until valid wall placed
        while (!success)
        {
            success = placeWall(xcord, zcord, xcord1, zcord);
        }
        success = false;
        xcord   = wb.topleft.x + (wb.topright.x - wb.topleft.x) * UnityEngine.Random.Range(0.1f, 1.0f);
        zcord   = wb.bottomleft.z + (wb.topleft.z - wb.bottomleft.z) * UnityEngine.Random.Range(0.1f, 1.0f);

        xcord1 = wb.topleft.x + (wb.topright.x - wb.topleft.x) * UnityEngine.Random.Range(0.1f, 1.0f);
        zcord1 = wb.bottomleft.z + (wb.topleft.z - wb.bottomleft.z) * UnityEngine.Random.Range(0.1f, 1.0f);

        //try placing wall with random coordinates until valid wall placed
        while (!success)
        {
            success = placeWall(xcord, zcord, xcord, zcord1);
        }
    }
示例#9
0
        public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
        {
            UnityEngine.MeshRenderer meshRenderer = this.Map.GetComponent <UnityEngine.MeshRenderer>();

            dstManager.AddComponentData(entity, new PhysicsCollider
            {
                Value = BoxCollider.Create
                        (
                    CollisionGeomeotrySingleton.Instance.CreateOrGetBoxGeometry(meshRenderer.bounds.size),
                    CollisionFilterSingleton.Instance.BelongsToNonTraversableFilter
                        )
            });

            Entity worldBoundsEntity = dstManager.CreateEntity(dstManager.CreateWorldBoundsArchetype());

            WorldBounds worldBounds = WorldBoundsStaticAccessor.WorldBounds;

            dstManager.SetComponentData(worldBoundsEntity, worldBounds);

            using (NativeArray <Entity> pathNodes = dstManager.CreateEntity(dstManager.CreatePathnodeArchetype(), worldBounds.XZGridSize.x * worldBounds.XZGridSize.y, Allocator.Temp))
            {
                for (int x = 0; x < worldBounds.XZGridSize.x; ++x)
                {
                    for (int y = 0; y < worldBounds.XZGridSize.y; ++y)
                    {
                        int index = AStarUtility.CalculateIndex(x, y, worldBounds.XZGridSize.x);

                        dstManager.SetComponentData(pathNodes[index], new PathNode
                        {
                            X                 = x,
                            Y                 = y,
                            Index             = index,
                            GCost             = int.MaxValue,
                            HCost             = int.MaxValue,
                            IsTraversable     = true, //Phyisics check in MonsterPathfindingGridSystem.cs but not in FindPath Method of AStar.cs saves performance!
                            PreviousNodeIndex = -1
                        });
                    }
                }
            }
        }
示例#10
0
        public bool[,] CreateImportanceMap(Vector3 lightDirection, int photonCount, WorldBounds bounds, out int importanceMapIntersectCount)
        {
            bool[,] hiresMap;

            importanceMapIntersectCount = 0;
            float width     = bounds.X.Difference;
            float height    = bounds.Y.Difference;
            float countRoot = (float)Math.Sqrt(photonCount);
            int   countX    = (int)Math.Ceiling((countRoot * height) / width);
            int   countY    = (int)Math.Ceiling((countRoot * width) / height);
            float distanceX = width / (float)countX;
            float distanceY = height / (float)countY;

            hiresMap = new bool[countX, countY];

            //lightDirection *= -1; // back to original;
            float xPos, yPos;

            yPos = bounds.Y.Lower;
            for (int y = 0; y < countY; y++)
            {
                xPos = bounds.X.Lower;
                for (int x = 0; x < countX; x++)
                {
                    RadiosityIntersection intersect = m_bsp[0].RadiosityIntersect(new Vector3(xPos, yPos, bounds.Z.Upper), lightDirection);
                    // DeMorgan's Theorem FTW!
                    hiresMap[x, y] = !(intersect.NoIntersection || intersect.WrongSide);
                    if (hiresMap[x, y])
                    {
                        importanceMapIntersectCount++;
                    }
                    xPos += distanceX;
                    IncrementProgress();
                }
                yPos += distanceY;
            }
            //importanceMap = hiresMap;
            return(hiresMap);
        }
示例#11
0
    //generate pillars

    void generatePillars()
    {
        WorldBounds wb = getWorldBounds();

        for (int i = 0; i < noOfPillars; i++)
        {
            float xcord = wb.topleft.x + (wb.topright.x - wb.topleft.x) * UnityEngine.Random.Range(0.1f, 1.0f);
            float zcord = wb.bottomleft.z + (wb.topleft.z - wb.bottomleft.z) * UnityEngine.Random.Range(0.1f, 1.0f);
            float ycord = wb.bottomleft.y;

            float PillarWidth = UnityEngine.Random.Range(0.5f, PillarMaxWidth);

            //randomly generating pillar coordinates and placing pillar. The loop continues until successfully pillar placed
            while (!placePillars(xcord, zcord, PillarWidth))
            {
                xcord = wb.topleft.x + (wb.topright.x - wb.topleft.x) * UnityEngine.Random.Range(0.1f, 1.0f);
                zcord = wb.bottomleft.z + (wb.topleft.z - wb.bottomleft.z) * UnityEngine.Random.Range(0.1f, 1.0f);
                ycord = wb.bottomleft.y;

                PillarWidth = UnityEngine.Random.Range(0.5f, PillarMaxWidth);
            }
        }
    }
示例#12
0
        /// <summary>
        /// Begins calculating a light mapping solution.
        /// </summary>
        /// <exception cref="System.ApplicationException">
        /// Thrown when no BSP is in the current scene graph.
        /// </exception>
        public void Begin()
        {
            //      MdxRender.RenderDebug = false;

            SetOperation("Loading scenario...");
            _scenario = Prometheus.Instance.ProjectManager.ScenarioTag as ScenarioBase;

            if (_scenario == null)
            {
                throw new RadiosityException("The current project has no scenario tag or the scenario tag is invalid.");
            }

            if (_scenario.BspList.Count <= 0)
            {
                throw new RadiosityException("The current project's scenario tag does not contain a bsp tag or the bsp tag is invalid.");
            }

            SetOperation("Retrieving lighting information...");
            m_bsp = _scenario.BspList;
            WorldBounds bounds = m_bsp[0].WorldBounds;

            foreach (IBsp bsp in m_bsp)
            {
                bounds &= bsp.WorldBounds;
            }

            // We need to find the six planes of world bounds.
            m_worldBounds = bounds.CalculatePlanes();

            // Try and obtain any lighting information.
            if (Prometheus.Instance.ProjectManager.ScenarioTag != null)
            {
                this.m_lights = _scenario.WorldLighting;
                this.m_models = _scenario.StaticModels;

                if (m_models == null)
                {
                    m_models = new List <IModel>();
                }
            }
            else
            {
                ICamera camera = MdxRender.Camera;
                List <RadiosityLight> lights = new List <RadiosityLight>();
                this.m_lights = new List <ILight>();
                m_lights.Add(new RadiosityLight(camera.Position, new RealColor(1f, 1f, 1.0f), 20f));
            }

            // Get each lightmap from the currently loaded BSP.
            for (int i = 0; i < m_bsp.Count; i++)
            {
                // Add the DirectX texture to the high dynamic range texture collection.
                foreach (BaseTexture _texture in m_bsp[i].Lightmaps)
                {
                    TextureMap _lightmap = new TextureMap(_texture);
                    m_textures.AddTexture(_lightmap);
                }
            }

            // TODO: Figure out the number of photons each light gets. For now, set them all to use the same amount.
            float totalPower = 0f;
            float maxPower   = 0f;

            foreach (ILight light in m_lights)
            {
                totalPower += light.Power;
                maxPower    = Math.Max(light.Power, maxPower);
            }

            int directionalPhotons = 0;

            foreach (ILight light in m_lights)
            {
                int photonCount = (int)((float)m_maxPhotons * light.Power / totalPower);//(int)Math.Round((light.Power / totalPower) * (float)m_maxPhotons);
                light.PhotonCount = photonCount;
                light.Color.Multiply(light.Power);

                if (light is DirectionalLight)
                {
                    directionalPhotons += photonCount;
                }
            }
            bool[,] importance;
            int count;

            ChangeStage(RadiosityStage.CreatingImportanceMap, directionalPhotons);
            SetOperation("Optimizing Pass...");
            for (int l = 0; l < m_lights.Count; l++)
            {
                if (m_lights[l] is DirectionalLight)
                {
                    DirectionalLight light = m_lights[l] as DirectionalLight;
                    if (light.PhotonCount > 0)
                    {
                        importance = CreateImportanceMap(light.Direction, light.PhotonCount, bounds, out count);
                    }
                    else
                    {
                        importance = null; count = 0;
                    }
                    RadiosityHelper.ImportanceMap         = importance;
                    RadiosityHelper.ImportanceMapOnPixels = count;
                }
            }

            //currentOperation = "Saving any unsaved data...";
            //this.SaveAll();
            photonMap = new PhotonMap(m_maxBounces * m_maxPhotons);
            SetOperation("Perform radiosity...");
            // Process collisions.
            this.ProcessCollisions();

            ChangeStage(RadiosityStage.Done, 100);

            Interfaces.Output.Write(Interfaces.OutputTypes.Information, m_photonsLost + " photon(s) lost during radiosity.");
            if (OnComplete != null)
            {
                OnComplete();
            }
        }
示例#13
0
        private void CreateLightmaps()
        {
            // Stage 2: Render onto lightmaps
            //   * Step 1: Initialize
            //   * Step 2: Iterate through textures
            //     * Iterate through materials
            //       * Compute a pixel rectangle for the current material
            //       * Iterate through the pixels in the material
            //         * Convert the UV pixel coordinates to a 3D point
            //         * Gather n photons that are on that surface

            int   screenWidth  = MdxRender.Device.Viewport.Width;
            int   screenHeight = MdxRender.Device.Viewport.Height;
            float dist2        = RadiosityHelper.GatherDistance * RadiosityHelper.GatherDistance;

            if (m_bsp == null)
            {
                _scenario = Prometheus.Instance.ProjectManager.ScenarioTag as ScenarioBase;

                if (_scenario == null)
                {
                    throw new RadiosityException("The current project has no scenario tag or the scenario tag is invalid.");
                }

                if (_scenario.BspList.Count <= 0)
                {
                    throw new RadiosityException("The current project's scenario tag does not contain a bsp tag or the bsp tag is invalid.");
                }

                SetOperation("Retrieving lighting information...");
                m_bsp = _scenario.BspList;
                WorldBounds bounds = m_bsp[0].WorldBounds;
                foreach (IBsp bsp in m_bsp)
                {
                    bounds &= bsp.WorldBounds;
                }

                // We need to find the six planes of world bounds.
                m_worldBounds = bounds.CalculatePlanes();

                for (int i = 0; i < m_bsp.Count; i++)
                {
                    // Add the DirectX texture to the high dynamic range texture collection.
                    foreach (BaseTexture _texture in m_bsp[i].Lightmaps)
                    {
                        TextureMap _lightmap = new TextureMap(_texture);
                        m_textures.AddTexture(_lightmap);
                    }
                }
            }

            Vector3 badPoint = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            string  path     = (Prometheus.Instance.ProjectManager.ProjectFolder as DiskFileLibrary).RootPath + "LightMaps\\";

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            //float dist2 = RadiosityHelper.GatherDistance * RadiosityHelper.GatherDistance;
            if ((photonMap != null) && (photonMap.store.Length > 0))
            {
                int totalPixels = 0;

                foreach (TextureMap texMap in m_textures)
                {
                    totalPixels += (int)Math.Ceiling(texMap.Width * texMap.Height * RadiosityHelper.LightmapScale * RadiosityHelper.LightmapScale);
                }

                ChangeStage(RadiosityStage.TextureGeneration, totalPixels);

                int   texIndex = 0;
                float hemisphereSizeDivisor = 1f / ((float)Math.PI * dist2);
                float maxIntensity          = float.MinValue;
                foreach (TextureMap texMap in m_textures)
                {
                    CreateLightmap(dist2, badPoint, path, texIndex, hemisphereSizeDivisor, texMap, ref maxIntensity);
                    texIndex++;
                }
            }
            UpdateViewportLightmaps();
        }
示例#14
0
 void Awake()
 {
     Instance = this;
 }
示例#15
0
 private static int WorldSpaceToCell(float worldSpaceCoordinate, int offset, int min, int max, WorldBounds worldBounds)
 {
     //Have to clamp the value, otherwise flooring will make certain values fall below 0 or above grid size because the mesh is too big etc.
     return((int)(math.clamp(math.floor((worldSpaceCoordinate - offset) / worldBounds.WorldSpaceCellSize), min, max)));
 }
示例#16
0
 private static float CellToWorldSpace(int coordinate, int offset, WorldBounds worldBounds)
 {
     return(worldBounds.WorldSpaceCellSize * coordinate + offset);
 }