Beispiel #1
0
        public float ComputeArcLength(int index, int subdivs)
        {
            float3 p0, p1, p2, p3;

            GetSplineSectionInternal(index, out p0, out p1, out p2, out p3);

            return(CatmullRom.ComputeArcLength(p0, p1, p2, p3, subdivs));
        }
        protected override void OnUpdate()
        {
            Entities.ForEach((Path path) =>
            {
                var entity = GetPrimaryEntity(path);

                int numPathNodes = path.GetNumNodes();
                PathMap.Add(path.GetInstanceID(), RIndex);

                RoadSettings roadSettings = path.gameObject.GetComponentInParent <RoadSettings>();

                uint spawnPool = 0;
                if (roadSettings != null)
                {
                    spawnPool = roadSettings.vehicleSelection;
                }

                for (int n = 1; n < numPathNodes; n++)
                {
                    var rs = new RoadSection();

                    path.GetSplineSection(n - 1, out rs.p0, out rs.p1, out rs.p2, out rs.p3);
                    rs.arcLength = CatmullRom.ComputeArcLength(rs.p0, rs.p1, rs.p2, rs.p3, 1024);

                    rs.vehicleHalfLen  = Constants.VehicleLength / rs.arcLength;
                    rs.vehicleHalfLen /= 2;

                    rs.sortIndex = RIndex;
                    rs.linkNext  = RIndex + 1;
                    if (n == numPathNodes - 1)
                    {
                        rs.linkNext = -1;
                        MergeMap[math.round((path.GetReversibleRawPosition(n) + new float3(path.transform.position)) * Constants.NodePositionRounding) / Constants.NodePositionRounding] = RIndex;
                    }

                    rs.linkExtraChance = 0.0f;
                    rs.linkExtra       = -1;

                    rs.width  = path.width;
                    rs.height = path.height;

                    rs.minSpeed = path.minSpeed;
                    rs.maxSpeed = path.maxSpeed;

                    rs.occupationLimit = math.min(Constants.RoadOccupationSlotsMax, (int)math.round(rs.arcLength / Constants.VehicleLength));

                    var sectionEnt = CreateAdditionalEntity(path);

                    IdxMap[RIndex] = sectionEnt;

                    if (!path.isOnRamp)
                    {
                        RampMap[math.round((path.GetReversibleRawPosition(n - 1) + new float3(path.transform.position)) * Constants.NodePositionRounding) / Constants.NodePositionRounding] = RIndex;
                        if (n == 1)
                        {
                            int x          = 2; // Only spawn in right lane
                            float t        = rs.vehicleHalfLen;
                            float pathTime = (n - 1) + t;

                            var spawner  = new Spawner();
                            spawner.Time = math.frac(pathTime);

                            spawner.Direction = math.normalize(path.GetTangent(pathTime));

                            float3 rightPos  = (x - 1) * math.mul(spawner.Direction, Vector3.right) * ((rs.width - Constants.VehicleWidth) / 2.0f);
                            spawner.Position = path.GetWorldPosition(pathTime) + rightPos;

                            spawner.RoadIndex = RIndex;

                            spawner.minSpeed = path.minSpeed;
                            spawner.maxSpeed = path.maxSpeed;

                            var speedInverse = 1.0f / spawner.minSpeed;

                            spawner.random     = new Unity.Mathematics.Random((uint)RIndex + 1);
                            spawner.delaySpawn = (int)Constants.VehicleLength + spawner.random.NextInt((int)(speedInverse * 60.0f),
                                                                                                       (int)(speedInverse * 120.0f));

                            spawner.LaneIndex = x;
                            spawner.poolSpawn = spawnPool;

                            // Each path will only have one spawner, so use the Primary Entity
                            DstEntityManager.AddComponentData(entity, spawner);
                        }
                    }

                    RIndex++;
                    DstEntityManager.AddComponentData(sectionEnt, rs);
                }
            });

            // Loop over the paths again to start building the ramps and merges
            Entities.ForEach((Path path) =>
            {
                int numPathNodes = path.GetNumNodes();

                // Handle On Ramp roads
                if (path.isOnRamp)
                {
                    int rsRampIdx    = PathMap[path.GetInstanceID()];
                    float3 rampEntry = math.round((path.GetReversibleRawPosition(0) + new float3(path.transform.position)) * Constants.NodePositionRounding) / Constants.NodePositionRounding;
                    if (RampMap.ContainsKey(rampEntry))
                    {
                        int rsIndex = RampMap[rampEntry];
                        if (rsIndex > 0)
                        {
                            rsIndex -= 1;
                            if (IdxMap.ContainsKey(rsIndex))
                            {
                                Entity ramp    = IdxMap[rsIndex];
                                RoadSection rs = DstEntityManager.GetComponentData <RoadSection>(ramp);
                                if (rs.linkNext == rsIndex + 1)
                                {
                                    rs.linkExtra       = rsRampIdx;
                                    rs.linkExtraChance = path.percentageChanceForOnRamp / 100.0f;
                                    DstEntityManager.SetComponentData(ramp, rs);
                                }
                            }
                        }
                    }
                }

                // Handle merging roads
                {
                    int n = 0;

                    float3 pos =
                        math.round((path.GetReversibleRawPosition(n) + new float3(path.transform.position)) *
                                   Constants.NodePositionRounding) / Constants.NodePositionRounding;
                    if (MergeMap.ContainsKey(pos))
                    {
                        int mergeFromIndex = MergeMap[pos];
                        int mergeToBase    = PathMap[path.GetInstanceID()];

                        if (mergeFromIndex > 0 && mergeFromIndex != mergeToBase + n)
                        {
                            Entity merge   = IdxMap[mergeFromIndex];
                            RoadSection rs = DstEntityManager.GetComponentData <RoadSection>(merge);
                            if (rs.linkNext == -1)
                            {
                                rs.linkNext = mergeToBase + n;
                                DstEntityManager.SetComponentData(merge, rs);
                            }
                        }
                    }
                }
            });

            RIndex = 0;
            PathMap.Clear();
            RampMap.Clear();
            MergeMap.Clear();
            IdxMap.Clear();
        }