Esempio n. 1
0
        protected override void OnUpdate()
        {
            Entities.ForEach(
                (LegacyRigidBody body) =>
            {
                var entity = GetPrimaryEntity(body.gameObject);

                // prefer conversions from non-legacy data if they have already been performed
                if (DstEntityManager.HasComponent <PhysicsVelocity>(entity))
                {
                    return;
                }

                DstEntityManager.PostProcessTransformComponents(
                    entity, body.transform,
                    body.isKinematic ? BodyMotionType.Kinematic : BodyMotionType.Dynamic
                    );

                if (body.gameObject.isStatic)
                {
                    return;
                }

                if (body.interpolation != RigidbodyInterpolation.None)
                {
                    DstEntityManager.AddOrSetComponent(entity, new PhysicsGraphicalSmoothing());
                    if (body.interpolation == RigidbodyInterpolation.Interpolate)
                    {
                        DstEntityManager.AddComponentData(entity, new PhysicsGraphicalInterpolationBuffer
                        {
                            PreviousTransform = Math.DecomposeRigidBodyTransform(body.transform.localToWorldMatrix)
                        });
                    }
                }

                // Build mass component
                var massProperties = MassProperties.UnitSphere;
                if (DstEntityManager.HasComponent <PhysicsCollider>(entity))
                {
                    // Build mass component
                    massProperties = DstEntityManager.GetComponentData <PhysicsCollider>(entity).MassProperties;
                }
                // n.b. no way to know if CoM was manually adjusted, so all legacy Rigidbody objects use auto CoM
                DstEntityManager.AddOrSetComponent(entity, !body.isKinematic ?
                                                   PhysicsMass.CreateDynamic(massProperties, body.mass) :
                                                   PhysicsMass.CreateKinematic(massProperties));

                DstEntityManager.AddOrSetComponent(entity, new PhysicsVelocity());

                if (!body.isKinematic)
                {
                    DstEntityManager.AddOrSetComponent(entity, new PhysicsDamping
                    {
                        Linear  = body.drag,
                        Angular = body.angularDrag
                    });
                    if (!body.useGravity)
                    {
                        DstEntityManager.AddOrSetComponent(entity, new PhysicsGravityFactor {
                            Value = 0f
                        });
                    }
                }
                else
                {
                    DstEntityManager.AddOrSetComponent(entity, new PhysicsGravityFactor {
                        Value = 0
                    });
                }
            }
                );
        }
Esempio n. 2
0
        protected override void OnUpdate()
        {
            Entities.ForEach((Canvas canvas) => {
                var parent = canvas.transform.parent;
                if (parent != null)
                {
#if UNITY_EDITOR
                    UnityEditor.EditorGUIUtility.PingObject(canvas);
#endif
                    throw new NotSupportedException($"{canvas.name} is child of {parent.name}, this is not supported!");
                }

                var entity       = GetPrimaryEntity(canvas);
                var canvasScaler = canvas.GetComponent <CanvasScaler>();

                // Build a metadata of the children which are active
                var count = 0;
                count     = RecurseCountChildren(ref count, canvas.transform);

                var metadata = new UnsafeHashMap <Entity, bool>(count + 1, Allocator.Persistent);
                RecurseAddMetadata(ref metadata, canvas.transform);

                DstEntityManager.AddComponentData(entity, new ChildrenActiveMetadata {
                    Value = metadata
                });

                // Remove unnecessary information
                DstEntityManager.RemoveComponent <Rotation>(entity);
                DstEntityManager.RemoveComponent <Translation>(entity);
                DstEntityManager.RemoveComponent <NonUniformScale>(entity);

                // Add the root mesh renderering data to the canvas as the root primary renderer
                DstEntityManager.AddBuffer <RootVertexData>(entity);
                DstEntityManager.AddBuffer <RootTriangleIndexElement>(entity);

                // Add a mesh to the canvas so treat it as a renderer.
                DstEntityManager.AddComponentData(entity, new AddMeshTag {
                });

                // Add a collection of the submesh information
                DstEntityManager.AddBuffer <SubmeshSliceElement>(entity);
                DstEntityManager.AddBuffer <SubmeshKeyElement>(entity);

                switch (canvasScaler.uiScaleMode)
                {
                case CanvasScaler.ScaleMode.ScaleWithScreenSize:
                    DstEntityManager.AddComponentData(entity, new ReferenceResolution {
                        Value = canvasScaler.referenceResolution
                    });

                    // TODO: Should figure out if I want to support shrinking and expanding only...
                    if (canvasScaler.screenMatchMode == CanvasScaler.ScreenMatchMode.MatchWidthOrHeight)
                    {
                        DstEntityManager.AddComponentData(entity, new WidthHeightRatio {
                            Value = canvasScaler.matchWidthOrHeight
                        });
                    }
                    else
                    {
                        throw new NotSupportedException($"{canvasScaler.screenMatchMode} is not supported yet.");
                    }
                    break;

                default:
                    throw new NotSupportedException($"{canvasScaler.uiScaleMode} is not supported yet.");
                }
            });
        }
Esempio n. 3
0
        protected override void OnUpdate()
        {
            Entities.ForEach((UnityEngine.Rigidbody2D rigidbody) =>
            {
                // We don't convert a Rigidbody2D if it's not Simulated.
                if (!rigidbody.simulated)
                {
                    return;
                }

                var entity = GetPrimaryEntity(rigidbody);

                var bodyType = rigidbody.bodyType;

                // There's no components to define a Static rigidbody or its properties.
                if (bodyType != UnityEngine.RigidbodyType2D.Static)
                {
                    // Velocity.
                    if (!DstEntityManager.HasComponent <PhysicsVelocity>(entity))
                    {
                        DstEntityManager.AddComponentData(entity,
                                                          new PhysicsVelocity
                        {
                            Linear  = rigidbody.velocity,
                            Angular = rigidbody.angularVelocity
                        });
                    }

                    var massProperties = MassProperties.Default;

                    // Fetch mass properties from any available collider.
                    if (DstEntityManager.HasComponent <PhysicsColliderBlob>(entity))
                    {
                        var collider   = DstEntityManager.GetComponentData <PhysicsColliderBlob>(entity).Collider;
                        massProperties = collider.IsCreated ? collider.Value.MassProperties : MassProperties.Default;
                    }

                    // Dynamic.
                    if (bodyType == UnityEngine.RigidbodyType2D.Dynamic)
                    {
                        DstEntityManager.AddOrSetComponent(entity,
                                                           PhysicsMass.CreateDynamic(massProperties, rigidbody.mass));

                        if (!DstEntityManager.HasComponent <PhysicsGravity>(entity))
                        {
                            DstEntityManager.AddComponentData(entity,
                                                              new PhysicsGravity {
                                Scale = rigidbody.gravityScale
                            });
                        }

                        if (!DstEntityManager.HasComponent <PhysicsDamping>(entity))
                        {
                            DstEntityManager.AddComponentData(entity,
                                                              new PhysicsDamping
                            {
                                Linear  = rigidbody.drag,
                                Angular = rigidbody.angularDrag
                            });
                        }
                    }
                    // Kinematic.
                    else
                    {
                        DstEntityManager.AddOrSetComponent(entity,
                                                           PhysicsMass.CreateKinematic(massProperties));
                    }
                }

                // Create any colliders associated with this rigidbody entity.
                m_ColliderConversionSystem.CreateCollider(entity);
            });
        }
        void ConvertBatchedClips()
        {
            var clipList = new List <AudioClip>();

            using (var computationContext = new BlobAssetComputationContext <AudioClipComputationData, AudioClipBlob>(BlobAssetStore, 128, Allocator.Temp))
            {
                var hashes     = new NativeList <Hash128>(Allocator.Persistent);
                var jobs       = new List <ComputeAudioClipHashesJob>();
                var jobHandles = new NativeList <JobHandle>(Allocator.Persistent);
                Entities.ForEach((AudioSourceAuthoring authoring) =>
                {
                    if (authoring.clip != null)
                    {
                        int frequency = authoring.clip.frequency;
                        var arr       = new float[authoring.clip.samples * authoring.clip.channels];
                        authoring.clip.GetData(arr, 0);
                        var job = new ComputeAudioClipHashesJob
                        {
                            samples   = new NativeArray <float>(arr, Allocator.Persistent),
                            hash      = new NativeReference <uint2>(Allocator.Persistent),
                            frequency = frequency
                        };
                        jobs.Add(job);
                        jobHandles.Add(job.Schedule());
                    }
                });
                JobHandle.CompleteAll(jobHandles);
                jobHandles.Dispose();

                int index = 0;
                Entities.ForEach((AudioSourceAuthoring authoring) =>
                {
                    if (authoring.clip != null)
                    {
                        var hash =
                            new Hash128(jobs[index].hash.Value.x, jobs[index].hash.Value.y, (uint)authoring.clip.channels, (uint)math.select(0, authoring.voices,
                                                                                                                                             authoring.looping));
                        computationContext.AssociateBlobAssetWithUnityObject(hash, authoring.gameObject);
                        if (computationContext.NeedToComputeBlobAsset(hash))
                        {
                            computationContext.AddBlobAssetToCompute(hash, new AudioClipComputationData {
                                hash = hash, index = index
                            });
                        }
                        index++;
                        clipList.Add(authoring.clip);
                        hashes.Add(hash);
                    }
                });
                foreach (var job in jobs)
                {
                    job.samples.Dispose();
                    job.hash.Dispose();
                }
                using (var computationDataArray = computationContext.GetSettings(Allocator.TempJob))
                {
                    var samples       = new NativeList <float>(Allocator.TempJob);
                    var ranges        = new NativeArray <int2>(computationDataArray.Length, Allocator.TempJob);
                    var rates         = new NativeArray <int>(computationDataArray.Length, Allocator.TempJob);
                    var channelCounts = new NativeArray <int>(computationDataArray.Length, Allocator.TempJob);
                    var offsets       = new NativeArray <int>(computationDataArray.Length, Allocator.TempJob);
                    var names         = new NativeArray <FixedString128>(computationDataArray.Length, Allocator.TempJob);
                    for (int i = 0; i < computationDataArray.Length; i++)
                    {
                        var clip           = clipList[computationDataArray[i].index];
                        var samplesManaged = new float[clip.samples * clip.channels];
                        clip.GetData(samplesManaged, 0);
                        var samplesUnmanaged = new NativeArray <float>(samplesManaged, Allocator.Temp);
                        ranges[i] = new int2(samples.Length, samplesUnmanaged.Length);
                        samples.AddRange(samplesUnmanaged);
                        rates[i]         = clip.frequency;
                        channelCounts[i] = clip.channels;
                        offsets[i]       = (int)computationDataArray[i].hash.Value.w;
                        names[i]         = clip.name;
                    }
                    new ComputeAudioClipBlobsJob
                    {
                        samples              = samples,
                        ranges               = ranges,
                        rates                = rates,
                        channelCounts        = channelCounts,
                        computationDataArray = computationDataArray,
                        offsetCounts         = offsets,
                        names                = names
                    }.ScheduleParallel(ranges.Length, 1, default).Complete();
                    foreach (var data in computationDataArray)
                    {
                        computationContext.AddComputedBlobAsset(data.hash, data.blob);
                    }
                    samples.Dispose();
                    ranges.Dispose();
                    rates.Dispose();
                    channelCounts.Dispose();
                    offsets.Dispose();
                    names.Dispose();

                    index = 0;
                    Entities.ForEach((AudioSourceAuthoring authoring) =>
                    {
                        if (authoring.clip != null)
                        {
                            var hash = hashes[index];
                            computationContext.GetBlobAsset(hash, out var blob);

                            var entity = GetPrimaryEntity(authoring);
                            if (!authoring.looping)
                            {
                                DstEntityManager.AddComponentData(entity, new AudioSourceOneShot
                                {
                                    clip            = blob,
                                    innerRange      = authoring.innerRange,
                                    outerRange      = authoring.outerRange,
                                    rangeFadeMargin = authoring.rangeFadeMargin,
                                    volume          = authoring.volume
                                });
                                if (authoring.autoDestroyOnFinish)
                                {
                                    DstEntityManager.AddComponent <AudioSourceDestroyOneShotWhenFinished>(entity);
                                }
                            }
                            else
                            {
                                DstEntityManager.AddComponentData(entity, new AudioSourceLooped
                                {
                                    m_clip          = blob,
                                    innerRange      = authoring.innerRange,
                                    outerRange      = authoring.outerRange,
                                    rangeFadeMargin = authoring.rangeFadeMargin,
                                    volume          = authoring.volume,
                                });
                            }
                            if (authoring.useCone)
                            {
                                DstEntityManager.AddComponentData(entity, new AudioSourceEmitterCone
                                {
                                    cosInnerAngle         = math.cos(math.radians(authoring.innerAngle)),
                                    cosOuterAngle         = math.cos(math.radians(authoring.outerAngle)),
                                    outerAngleAttenuation = authoring.outerAngleVolume
                                });
                            }
                            index++;
                        }
                    });
                }
                hashes.Dispose();
            }
        }
        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();
        }
        protected override void OnUpdate()
        {
            Entities.ForEach((LODGroup lodGroup) =>
            {
                if (lodGroup.lodCount > 8)
                {
                    Debug.LogWarning("LODGroup has more than 8 LOD - Not supported", lodGroup);
                    return;
                }

                var lodGroupEntity = GetPrimaryEntity(lodGroup);

                var lodGroupData = new MeshLODGroupComponent();
                //@TODO: LOD calculation should respect scale...
                var worldSpaceSize = LODGroupExtensions.GetWorldSpaceSize(lodGroup);
                lodGroupData.LocalReferencePoint = lodGroup.localReferencePoint;

                var lodDistances0 = new float4(float.PositiveInfinity);
                var lodDistances1 = new float4(float.PositiveInfinity);
                var lodGroupLODs  = lodGroup.GetLODs();
                for (int i = 0; i < lodGroup.lodCount; ++i)
                {
                    float d = worldSpaceSize / lodGroupLODs[i].screenRelativeTransitionHeight;
                    if (i < 4)
                    {
                        lodDistances0[i] = d;
                    }
                    else
                    {
                        lodDistances1[i - 4] = d;
                    }
                }

                lodGroupData.LODDistances0 = lodDistances0;
                lodGroupData.LODDistances1 = lodDistances1;

                DstEntityManager.AddComponentData(lodGroupEntity, lodGroupData);

                for (int i = 0; i < lodGroupLODs.Length; ++i)
                {
                    foreach (var renderer in lodGroupLODs[i].renderers)
                    {
                        if (renderer == null)
                        {
                            Debug.LogWarning("Missing renderer in LOD Group", lodGroup);
                            continue;
                        }

                        DeclareDependency(renderer, lodGroup);
                        DeclareDependency(lodGroup, renderer);

                        foreach (var rendererEntity in GetEntities(renderer))
                        {
                            if (DstEntityManager.HasComponent <RenderMesh>(rendererEntity))
                            {
                                var lodComponent = new MeshLODComponent {
                                    Group = lodGroupEntity, LODMask = 1 << i
                                };
                                if (!DstEntityManager.HasComponent <MeshLODComponent>(rendererEntity))
                                {
                                    DstEntityManager.AddComponentData(rendererEntity, lodComponent);
                                }
                                else
                                {
                                    var previousLODComponent = DstEntityManager.GetComponentData <MeshLODComponent>(rendererEntity);
                                    if (previousLODComponent.Group != lodComponent.Group)
                                    {
                                        Debug.LogWarning("A renderer can not be in multiple different LODGroup.", renderer);
                                        continue;
                                    }

                                    if ((previousLODComponent.LODMask & (1 << (i - 1))) == 0)
                                    {
                                        Debug.LogWarning("A renderer that is present in the same LODGroup multiple times must be in consecutive LOD levels.", renderer);
                                    }

                                    lodComponent.LODMask |= previousLODComponent.LODMask;
                                    DstEntityManager.SetComponentData(rendererEntity, lodComponent);
                                }
                            }
                        }
                    }
                }
            });
        }
Esempio n. 7
0
        protected override void OnUpdate()
        {
            Entities.ForEach((HLOD hlod) =>
            {
                var lodGroup   = hlod.GetComponent <LODGroup>();
                var hlodEntity = GetPrimaryEntity(hlod);

                // If conversion of LODGroup failed, skip HLOD conversion too
                if (!DstEntityManager.HasComponent <MeshLODGroupComponent>(hlodEntity))
                {
                    return;
                }

                DstEntityManager.AddComponent(hlodEntity, ComponentType.ReadWrite <HLODComponent>());

                var LODCount = lodGroup.lodCount;
                if (LODCount != hlod.LODParentTransforms.Length)
                {
                    Debug.LogWarning("HLOD out of sync with LODGroup", hlod);
                    return;
                }

                for (int i = 0; i != LODCount; i++)
                {
                    var childGroups = hlod.CalculateLODGroups(i);
                    var HLODMask    = 1 << i;

                    foreach (var childGroup in childGroups)
                    {
                        var childLodGroupEntities = GetEntities(childGroup);
                        if (childLodGroupEntities.Count() == 0)
                        {
                            Debug.LogWarning($"Missing child group '{childGroup.gameObject.name}' in LOD group '{hlod.gameObject.name}', this can happen because the child group is disabled.");
                            return;
                        }

                        foreach (var childLodGroupEntity in childLodGroupEntities)
                        {
                            if (DstEntityManager.HasComponent <MeshLODGroupComponent>(childLodGroupEntity))
                            {
                                var group         = DstEntityManager.GetComponentData <MeshLODGroupComponent>(childLodGroupEntity);
                                group.ParentGroup = hlodEntity;
                                group.ParentMask  = HLODMask;
                                DstEntityManager.SetComponentData(childLodGroupEntity, group);
                            }
                        }
                    }

                    var outsideRenderers = CalculateRenderersOutsideLODGroups(hlod, i);
                    foreach (var r in outsideRenderers)
                    {
                        foreach (var rendererEntity in GetEntities(r))
                        {
                            if (DstEntityManager.HasComponent <RenderMesh>(rendererEntity))
                            {
                                //@TODO: Not quite sure if this makes sense. Test that this behaviour is reasonable.
                                if (DstEntityManager.HasComponent <MeshLODComponent>(rendererEntity))
                                {
                                    continue;
                                }

                                var lodComponent = new MeshLODComponent {
                                    Group = hlodEntity, LODMask = HLODMask
                                };
                                DstEntityManager.AddComponentData(rendererEntity, lodComponent);
                            }
                        }
                    }
                }
            });
        }
        protected override void OnUpdate()
        {
            var simpleMeshContext  = new BlobAssetComputationContext <UMeshSettings, SimpleMeshData>(BlobAssetStore, 128, Allocator.Temp);
            var litMeshContext     = new BlobAssetComputationContext <UMeshSettings, LitMeshData>(BlobAssetStore, 128, Allocator.Temp);
            var blendShapeContext  = new BlobAssetComputationContext <UMeshSettings, BlendShapeData>(BlobAssetStore, 128, Allocator.Temp);
            var skinnedMeshContext = new BlobAssetComputationContext <UMeshSettings, SkinnedMeshData>(BlobAssetStore, 128, Allocator.Temp);

            JobHandle combinedJH       = new JobHandle();
            int       simpleIndex      = 0;
            int       litIndex         = 0;
            int       blendShapeIndex  = 0;
            int       skinnedMeshIndex = 0;

            // Init blobasset arrays
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                CheckForMeshLimitations(uMesh);
                var entity = GetPrimaryEntity(uMesh);
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    simpleIndex++;
                }
                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    litIndex++;
                }
                if (uMesh.blendShapeCount > 0)
                {
                    blendShapeIndex++;
                }
                if (uMesh.boneWeights.Length > 0)
                {
                    skinnedMeshIndex++;
                }
            });
            NativeArray <BlobAssetReference <SimpleMeshData> >  simpleblobs      = new NativeArray <BlobAssetReference <SimpleMeshData> >(simpleIndex, Allocator.TempJob);
            NativeArray <BlobAssetReference <LitMeshData> >     litblobs         = new NativeArray <BlobAssetReference <LitMeshData> >(litIndex, Allocator.TempJob);
            NativeArray <BlobAssetReference <BlendShapeData> >  blendshapeblobs  = new NativeArray <BlobAssetReference <BlendShapeData> >(blendShapeIndex, Allocator.TempJob);
            NativeArray <BlobAssetReference <SkinnedMeshData> > skinnedMeshBlobs = new NativeArray <BlobAssetReference <SkinnedMeshData> >(litIndex, Allocator.TempJob);

            simpleIndex      = 0;
            litIndex         = 0;
            blendShapeIndex  = 0;
            skinnedMeshIndex = 0;

            // Check which blob assets to re-compute
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                var verticesHash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                               (uint)uMesh.subMeshCount.GetHashCode(), 0);
                uint boneCount      = (uint)uMesh.bindposes.Length;
                var skinnedDataHash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                  (uint)uMesh.subMeshCount.GetHashCode(), (uint)boneCount.GetHashCode());

                var entity = GetPrimaryEntity(uMesh);

                //Schedule blob asset recomputation jobs
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    simpleMeshContext.AssociateBlobAssetWithUnityObject(verticesHash, uMesh);
                    if (simpleMeshContext.NeedToComputeBlobAsset(verticesHash))
                    {
                        var simpleMeshData = new UMeshDataCache();
                        if (boneCount > 0)
                        {
                            simpleMeshData.RetrieveSkinnedMeshData(uMesh, entity, DstEntityManager, false);
                            if (skinnedMeshContext.NeedToComputeBlobAsset(skinnedDataHash))
                            {
                                UMeshSettings uSkinnedMeshSettings = new UMeshSettings(skinnedDataHash, uMesh, skinnedMeshIndex++);
                                skinnedMeshContext.AddBlobAssetToCompute(skinnedDataHash, uSkinnedMeshSettings);
                                var skinningJob = new SkinningDataConversionJob(simpleMeshData, uSkinnedMeshSettings.blobIndex, skinnedMeshBlobs);
                                combinedJH      = JobHandle.CombineDependencies(combinedJH, skinningJob.Schedule(combinedJH));
                            }
                        }
                        else
                        {
                            simpleMeshData.RetrieveSimpleMeshData(uMesh);
                        }

                        UMeshSettings uMeshSettings = new UMeshSettings(verticesHash, uMesh, simpleIndex++);
                        simpleMeshContext.AddBlobAssetToCompute(verticesHash, uMeshSettings);
                        var job    = new SimpleMeshConversionJob(simpleMeshData, uMeshSettings.blobIndex, simpleblobs);
                        combinedJH = JobHandle.CombineDependencies(combinedJH, job.Schedule(combinedJH));
                    }
                }

                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    litMeshContext.AssociateBlobAssetWithUnityObject(verticesHash, uMesh);
                    if (litMeshContext.NeedToComputeBlobAsset(verticesHash))
                    {
                        var litMeshData = new UMeshDataCache();
                        if (boneCount > 0)
                        {
                            litMeshData.RetrieveSkinnedMeshData(uMesh, entity, DstEntityManager, true);
                            if (skinnedMeshContext.NeedToComputeBlobAsset(skinnedDataHash))
                            {
                                UMeshSettings uSkinnedMeshSettings = new UMeshSettings(skinnedDataHash, uMesh, skinnedMeshIndex++);
                                skinnedMeshContext.AddBlobAssetToCompute(skinnedDataHash, uSkinnedMeshSettings);
                                var skinningJob = new SkinningDataConversionJob(litMeshData, uSkinnedMeshSettings.blobIndex, skinnedMeshBlobs);
                                combinedJH      = JobHandle.CombineDependencies(combinedJH, skinningJob.Schedule(combinedJH));
                            }
                        }
                        else
                        {
                            litMeshData.RetrieveLitMeshData(uMesh);
                        }

                        UMeshSettings uMeshSettings = new UMeshSettings(verticesHash, uMesh, litIndex++);
                        litMeshContext.AddBlobAssetToCompute(verticesHash, uMeshSettings);
                        var job    = new LitMeshConversionJob(litMeshData, uMeshSettings.blobIndex, litblobs);
                        combinedJH = JobHandle.CombineDependencies(combinedJH, job.Schedule(combinedJH));
                    }
                }

                if (uMesh.blendShapeCount > 0)
                {
                    verticesHash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                               (uint)uMesh.subMeshCount.GetHashCode(), (uint)uMesh.blendShapeCount);
                    blendShapeContext.AssociateBlobAssetWithUnityObject(verticesHash, uMesh);
                    if (blendShapeContext.NeedToComputeBlobAsset(verticesHash))
                    {
                        var blendShapeDataCache = new UBlendShapeDataCache();
                        blendShapeDataCache.RetrieveBlendShapeData(uMesh);

                        UMeshSettings uMeshSettings = new UMeshSettings(verticesHash, uMesh, blendShapeIndex++);
                        blendShapeContext.AddBlobAssetToCompute(verticesHash, uMeshSettings);

                        var job    = new BlendShapeConversionJob(uMeshSettings, blendShapeDataCache, blendshapeblobs);
                        combinedJH = JobHandle.CombineDependencies(combinedJH, job.Schedule(combinedJH));
                    }
                }
            });

            // Re-compute the new blob assets
            combinedJH.Complete();

            // Update the BlobAssetStore
            using (var simpleMeshSettings = simpleMeshContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < simpleMeshSettings.Length; i++)
                {
                    simpleMeshContext.AddComputedBlobAsset(simpleMeshSettings[i].hash, simpleblobs[simpleMeshSettings[i].blobIndex]);
                }
            }
            using (var litMeshSettings = litMeshContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < litMeshSettings.Length; i++)
                {
                    litMeshContext.AddComputedBlobAsset(litMeshSettings[i].hash, litblobs[litMeshSettings[i].blobIndex]);
                }
            }
            using (var meshSettings = blendShapeContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < meshSettings.Length; i++)
                {
                    blendShapeContext.AddComputedBlobAsset(meshSettings[i].hash, blendshapeblobs[meshSettings[i].blobIndex]);
                }
            }
            using (var meshSettings = skinnedMeshContext.GetSettings(Allocator.TempJob))
            {
                for (int i = 0; i < meshSettings.Length; i++)
                {
                    skinnedMeshContext.AddComputedBlobAsset(meshSettings[i].hash, skinnedMeshBlobs[meshSettings[i].blobIndex]);
                }
            }

            // Use blob assets in the conversion
            Entities.ForEach((UnityEngine.Mesh uMesh) =>
            {
                var entity     = GetPrimaryEntity(uMesh);
                bool addBounds = false;
                if (DstEntityManager.HasComponent <SimpleMeshRenderData>(entity))
                {
                    Hash128 hash128 = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                  (uint)uMesh.subMeshCount.GetHashCode(), 0);
                    simpleMeshContext.GetBlobAsset(hash128, out var blob);
                    DstEntityManager.AddComponentData(entity, new SimpleMeshRenderData()
                    {
                        Mesh = blob
                    });

                    addBounds = true;
                }
                if (DstEntityManager.HasComponent <LitMeshRenderData>(entity))
                {
                    Hash128 hash128 = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                  (uint)uMesh.subMeshCount.GetHashCode(), 0);
                    litMeshContext.GetBlobAsset(hash128, out var blob);
                    DstEntityManager.AddComponentData(entity, new LitMeshRenderData()
                    {
                        Mesh = blob
                    });

                    addBounds = true;
                }
                if (addBounds)
                {
                    DstEntityManager.AddComponentData(entity, new MeshBounds
                    {
                        Bounds = new AABB
                        {
                            Center  = uMesh.bounds.center,
                            Extents = uMesh.bounds.extents
                        }
                    });
                }
                if (uMesh.blendShapeCount > 0)
                {
                    Hash128 hash128 = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                  (uint)uMesh.subMeshCount.GetHashCode(), (uint)uMesh.blendShapeCount);
                    blendShapeContext.GetBlobAsset(hash128, out var blendShapeBlob);
                    DstEntityManager.AddComponentData(entity, new MeshBlendShapeData()
                    {
                        BlendShapeDataRef = blendShapeBlob
                    });
                }

                if (uMesh.bindposes.Length > 0)
                {
                    var skinnedDataHash = new Hash128((uint)uMesh.GetHashCode(), (uint)uMesh.vertexCount.GetHashCode(),
                                                      (uint)uMesh.subMeshCount.GetHashCode(), (uint)uMesh.bindposes.Length.GetHashCode());
                    skinnedMeshContext.GetBlobAsset(skinnedDataHash, out var skinnedMeshBlob);
                    DstEntityManager.AddComponentData(entity, new SkinnedMeshRenderData()
                    {
                        SkinnedMeshDataRef = skinnedMeshBlob
                    });
                }
            });

            simpleMeshContext.Dispose();
            litMeshContext.Dispose();
            blendShapeContext.Dispose();
            simpleblobs.Dispose();
            litblobs.Dispose();
            blendshapeblobs.Dispose();
            skinnedMeshBlobs.Dispose();
        }
Esempio n. 9
0
        protected override void OnUpdate()
        {
            var sceneBounds = MinMaxAABB.Empty;

            var materials = new List <Material>(10);

            Entities.ForEach((MeshRenderer meshRenderer, MeshFilter meshFilter) =>
            {
                var entity = GetPrimaryEntity(meshRenderer);

                var dst            = new RenderMesh();
                dst.mesh           = meshFilter.sharedMesh;
                dst.castShadows    = meshRenderer.shadowCastingMode;
                dst.receiveShadows = meshRenderer.receiveShadows;
                dst.layer          = meshRenderer.gameObject.layer;


                //@TODO: Transform system should handle RenderMeshFlippedWindingTag automatically. This should not be the responsibility of the conversion system.
                float4x4 localToWorld = meshRenderer.transform.localToWorldMatrix;
                var flipWinding       = math.determinant(localToWorld) < 0.0;

                meshRenderer.GetSharedMaterials(materials);
                var materialCount = materials.Count;

                if (materialCount == 1 && AttachToPrimaryEntityForSingleMaterial)
                {
                    dst.material = materials[0];
                    dst.subMesh  = 0;

                    DstEntityManager.AddSharedComponentData(entity, dst);
                    DstEntityManager.AddComponentData(entity, new PerInstanceCullingTag());

                    if (flipWinding)
                    {
                        DstEntityManager.AddComponent(entity, ComponentType.ReadWrite <RenderMeshFlippedWindingTag>());
                    }
                }
                else
                {
                    for (var m = 0; m != materialCount; m++)
                    {
                        var meshEntity = CreateAdditionalEntity(meshRenderer);

                        dst.material = materials[m];
                        dst.subMesh  = m;

                        DstEntityManager.AddSharedComponentData(meshEntity, dst);

                        DstEntityManager.AddComponentData(meshEntity, new PerInstanceCullingTag());

                        DstEntityManager.AddComponentData(meshEntity, new LocalToWorld {
                            Value = localToWorld
                        });
                        if (!DstEntityManager.HasComponent <Static>(meshEntity))
                        {
                            DstEntityManager.AddComponentData(meshEntity, new Parent {
                                Value = entity
                            });
                            DstEntityManager.AddComponentData(meshEntity, new LocalToParent {
                                Value = float4x4.identity
                            });
                        }

                        if (flipWinding)
                        {
                            DstEntityManager.AddComponent(meshEntity, ComponentType.ReadWrite <RenderMeshFlippedWindingTag>());
                        }
                    }
                }

                sceneBounds.Encapsulate(meshRenderer.bounds.ToAABB());
            });


            using (var boundingVolume = DstEntityManager.CreateEntityQuery(typeof(SceneBoundingVolume)))
            {
                if (!boundingVolume.IsEmptyIgnoreFilter)
                {
                    var bounds = boundingVolume.GetSingleton <SceneBoundingVolume>();
                    bounds.Value.Encapsulate(sceneBounds);
                    boundingVolume.SetSingleton(bounds);
                }
            }
        }
Esempio n. 10
0
        protected override void OnUpdate()
        {
            Entities.ForEach((Light light) =>
            {
                AddHybridComponent(light);
                var entity = GetPrimaryEntity(light);
                ConfigureEditorRenderData(entity, light.gameObject, true);

#if UNITY_2020_2_OR_NEWER && UNITY_EDITOR
                // Explicitly store the LightBakingOutput using a component, so we can restore it
                // at runtime.
                var bakingOutput = light.bakingOutput;
                DstEntityManager.AddComponentData(entity, new LightBakingOutputData {
                    Value = bakingOutput
                });
#endif
            });

            Entities.ForEach((LightProbeProxyVolume group) =>
            {
                AddHybridComponent(group);
            });

            Entities.ForEach((ReflectionProbe probe) =>
            {
                AddHybridComponent(probe);
            });

            Entities.ForEach((TextMesh mesh, MeshRenderer renderer) =>
            {
                AddHybridComponent(mesh);
                AddHybridComponent(renderer);
            });

            Entities.ForEach((SpriteRenderer sprite) =>
            {
                AddHybridComponent(sprite);
            });

            Entities.ForEach((VisualEffect vfx) =>
            {
                AddHybridComponent(vfx);
            });

            Entities.ForEach((ParticleSystem ps, ParticleSystemRenderer ren) =>
            {
                AddHybridComponent(ps);
                AddHybridComponent(ren);
            });

#if SRP_7_0_0_OR_NEWER
            Entities.ForEach((Volume volume) =>
            {
                AddHybridComponent(volume);
            });

            // NOTE: Colliders are only converted when a graphics Volume is on the same GameObject to avoid problems with Unity Physics!
            Entities.ForEach((SphereCollider collider, Volume volume) =>
            {
                AddHybridComponent(collider);
            });

            Entities.ForEach((BoxCollider collider, Volume volume) =>
            {
                AddHybridComponent(collider);
            });

            Entities.ForEach((CapsuleCollider collider, Volume volume) =>
            {
                AddHybridComponent(collider);
            });

            Entities.ForEach((MeshCollider collider, Volume volume) =>
            {
                AddHybridComponent(collider);
            });
#endif

#if HDRP_7_0_0_OR_NEWER
            // HDRP specific extra data for Light
            Entities.ForEach((HDAdditionalLightData light) =>
            {
#if UNITY_2020_2_OR_NEWER && UNITY_EDITOR
                if (light.GetComponent <Light>().lightmapBakeType != LightmapBakeType.Baked)
#endif
                AddHybridComponent(light);
            });

            // HDRP specific extra data for ReflectionProbe
            Entities.ForEach((HDAdditionalReflectionData reflectionData) =>
            {
                AddHybridComponent(reflectionData);
            });

            Entities.ForEach((DecalProjector projector) =>
            {
                AddHybridComponent(projector);
            });

            Entities.ForEach((DensityVolume volume) =>
            {
                AddHybridComponent(volume);
            });

            Entities.ForEach((PlanarReflectionProbe probe) =>
            {
                AddHybridComponent(probe);
            });

//This feature requires a modified HDRP
//If ProbeVolumes are enabled, add PROBEVOLUME_CONVERSION
//to the project script defines
#if PROBEVOLUME_CONVERSION
            Entities.ForEach((ProbeVolume probe) =>
            {
                AddHybridComponent(probe);
            });
#endif
#endif

#if URP_7_0_0_OR_NEWER
            // URP specific extra data for Light
            Entities.ForEach((UniversalAdditionalLightData light) =>
            {
#if UNITY_2020_2_OR_NEWER && UNITY_EDITOR
                if (light.GetComponent <Light>().lightmapBakeType != LightmapBakeType.Baked)
#endif
                AddHybridComponent(light);
            });
#endif

#if HYBRID_ENTITIES_CAMERA_CONVERSION
            // Camera conversion is disabled by default, because Unity Editor loses track of the main camera if it's put into a subscene
            Entities.ForEach((Camera camera) =>
            {
                AddHybridComponent(camera);
            });

#if HDRP_7_0_0_OR_NEWER
            Entities.ForEach((HDAdditionalCameraData data) =>
            {
                AddHybridComponent(data);
            });
#endif

#if URP_7_0_0_OR_NEWER
            Entities.ForEach((UniversalAdditionalCameraData data) =>
            {
                AddHybridComponent(data);
            });
#endif
#endif
        }
Esempio n. 11
0
    protected override void OnUpdate()
    {
        var blobFactoryPoints = new NativeList <float3>(Allocator.TempJob);
        int curPointIndex     = 0;
        var vertices          = new List <Vector3>(4096);
        var processBlobAssets = new NativeList <Hash128>(32, Allocator.Temp);

        Profiler.BeginSample("Conv_BuildHashAndPush");

        using (var context = new BlobAssetComputationContext <MeshBBFactorySettings, MeshBBBlobAsset>(BlobAssetStore, 128, Allocator.Temp))
        {
            // First step: for all changed GameObjects we compute the hash of their blob asset then get the asset or register its computation
            Entities.ForEach((MeshToBoundingBoxsAuthoring auth) =>
            {
                // Compute the blob asset hash based on Authoring properties
                var hasMesh      = auth.Mesh != null;
                var meshHashCode = hasMesh ? auth.Mesh.GetHashCode() : 0;
                var hash         = new Hash128((uint)meshHashCode, (uint)auth.MeshScale.GetHashCode(), 0, 0);

                // Query the context to determine if we need to build the BlobAsset
                processBlobAssets.Add(hash);
                context.AssociateBlobAssetWithGameObject(hash, auth.gameObject);
                if (context.NeedToComputeBlobAsset(hash))
                {
                    Profiler.BeginSample("CopyVertices");

                    float xp = float.MinValue, yp = float.MinValue, zp = float.MinValue;
                    float xn = float.MaxValue, yn = float.MaxValue, zn = float.MaxValue;

                    // Copy the mesh vertices into the point array
                    if (hasMesh)
                    {
                        auth.Mesh.GetVertices(vertices);
                        for (int i = 0; i < vertices.Count; i++)
                        {
                            var p = vertices[i];
                            xp    = math.max(p.x, xp);
                            yp    = math.max(p.y, yp);
                            zp    = math.max(p.z, zp);
                            xn    = math.min(p.x, xn);
                            yn    = math.min(p.y, yn);
                            zn    = math.min(p.z, zn);
                            blobFactoryPoints.Add(new float3(p.x, p.y, p.z));
                        }
                    }
                    else
                    {
                        xp = yp = zp = xn = yn = zn = 0;
                    }

                    Profiler.EndSample();

                    // Record this blob asset for computation
                    var vertexCount = hasMesh ? auth.Mesh.vertexCount : 0;
                    var setting     = new MeshBBFactorySettings {
                        Hash = hash, MeshScale = auth.MeshScale, PointStartIndex = curPointIndex, PointCount = vertexCount, MinBoundingBox = new float3(xn, yn, zn), MaxBoundingBox = new float3(xp, yp, zp)
                    };
                    curPointIndex += vertexCount;

                    context.AddBlobAssetToCompute(hash, setting);
                }
            });

            Profiler.EndSample();

            Profiler.BeginSample("Conv_CreateBlobAssets");

            using (var settings = context.GetSettings(Allocator.TempJob))
            {
                // Step two, compute BlobAssets
                var job = new ComputeMeshBBAssetJob(settings, blobFactoryPoints.AsArray());
                job.Schedule(job.Settings.Length, 1).Complete();

                for (int i = 0; i < settings.Length; i++)
                {
                    context.AddComputedBlobAsset(settings[i].Hash, job.BlobAssets[i]);
                }
                job.BlobAssets.Dispose();
            }

            Profiler.EndSample();

            Profiler.BeginSample("Conv_CreateECS");

            // Third step, create the ECS component with the associated blob asset
            var index = 0;
            Entities.ForEach((MeshToBoundingBoxsAuthoring auth) =>
            {
                context.GetBlobAsset(processBlobAssets[index++], out var blob);

                // Create the ECS component for the given GameObject
                var entity = GetPrimaryEntity(auth);

                DstEntityManager.AddComponentData(entity, new MeshBBComponent(blob));
            });

            Profiler.EndSample();
            blobFactoryPoints.Dispose();
            processBlobAssets.Dispose();
        }
    }
Esempio n. 12
0
        protected override void OnUpdate()
        {
            using (var context = new BlobAssetComputationContext <int, GhostPrefabMetaData>(BlobAssetStore, 16, Allocator.Temp))
            {
                Entities.ForEach((GhostAuthoringComponent ghostAuthoring) =>
                {
                    bool isPrefab = !ghostAuthoring.gameObject.scene.IsValid() || ghostAuthoring.ForcePrefabConversion;
                    var target    = GetConversionTarget(this, isPrefab);
                    // Check if the ghost is valid before starting to process
                    if (String.IsNullOrEmpty(ghostAuthoring.prefabId))
                    {
                        throw new InvalidOperationException($"The ghost {ghostAuthoring.gameObject.name} is not a valid prefab, all ghosts must be the top-level GameObject in a prefab. Ghost instances in scenes must be instances of such prefabs and changes should be made on the prefab asset, not the prefab instance");
                    }

                    if (!isPrefab && ghostAuthoring.DefaultGhostMode == GhostAuthoringComponent.GhostMode.OwnerPredicted && target != NetcodeConversionTarget.Server)
                    {
                        throw new InvalidOperationException($"Cannot convert a owner predicted ghost {ghostAuthoring.Name} as a scene instance");
                    }

                    if (!isPrefab && DstEntityManager.World.GetExistingSystem <ClientSimulationSystemGroup>() != null)
                    {
                        throw new InvalidOperationException($"The ghost {ghostAuthoring.gameObject.name} cannot be created on the client, either put it in a sub-scene or spawn it on the server only");
                    }

                    if (ghostAuthoring.prefabId.Length != 32)
                    {
                        throw new InvalidOperationException("Invalid guid for ghost prefab type");
                    }

                    // All ghosts should have a linked entity group
                    DeclareLinkedEntityGroup(ghostAuthoring.gameObject);
                    var entity = GetPrimaryEntity(ghostAuthoring);

                    // Generate a ghost type component so the ghost can be identified by mathcing prefab asset guid
                    var ghostType   = new GhostTypeComponent();
                    ghostType.guid0 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(0, 8), 16);
                    ghostType.guid1 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(8, 8), 16);
                    ghostType.guid2 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(16, 8), 16);
                    ghostType.guid3 = Convert.ToUInt32(ghostAuthoring.prefabId.Substring(24, 8), 16);
                    DstEntityManager.AddComponentData(entity, ghostType);

                    // FIXME: maybe stripping should be individual systems running before this to make sure it can be changed in a way that always triggers a reconvert - and to avoid reflection
                    var components = DstEntityManager.GetComponentTypes(entity);
                    if (target != NetcodeConversionTarget.Client)
                    {
                        // If this ghost should be usable on a server we must add a shared ghost type to make sure different ghost types
                        // with the same archetype end up in different chunks. If conversion is client and server the client needs to remove
                        // this at runtime
                        DstEntityManager.AddSharedComponentData(entity, new SharedGhostTypeComponent {
                            SharedValue = ghostType
                        });
                    }
                    if (target != NetcodeConversionTarget.Server)
                    {
                        // Converting to client or client and server, if client and server this should be stripped from servers at runtime
                        DstEntityManager.AddComponentData(entity, new SnapshotData());
                        DstEntityManager.AddBuffer <SnapshotDataBuffer>(entity);
                    }
                    // All types have the ghost components
                    DstEntityManager.AddComponentData(entity, new GhostComponent());
                    // No need to add the predicted ghost component for interpolated only ghosts if the data is only used by the client
                    if (target != NetcodeConversionTarget.Client || ghostAuthoring.SupportedGhostModes != GhostAuthoringComponent.GhostModeMask.Interpolated)
                    {
                        DstEntityManager.AddComponentData(entity, new PredictedGhostComponent());
                    }
                    if (target == NetcodeConversionTarget.Server)
                    {
                        // If converting server-only data we can remove all components which are not used on the server
                        foreach (var comp in components)
                        {
                            var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>();
                            if (attr != null && (attr.PrefabType & GhostPrefabType.Server) == 0)
                            {
                                DstEntityManager.RemoveComponent(entity, comp);
                            }
                        }
                    }
                    else if (target == NetcodeConversionTarget.Client)
                    {
                        // If converting client-only data we can remove all components which are not used on the client
                        // If the ghost is interpolated only we can also remove all componens which are not used on interpolated clients,
                        // and if it is predicted only we can remove everything which is not used on predicted clients
                        foreach (var comp in components)
                        {
                            var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>();
                            if (attr == null)
                            {
                                continue;
                            }
                            if ((attr.PrefabType & GhostPrefabType.Client) == 0)
                            {
                                DstEntityManager.RemoveComponent(entity, comp);
                            }
                            else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated && (attr.PrefabType & GhostPrefabType.InterpolatedClient) == 0)
                            {
                                DstEntityManager.RemoveComponent(entity, comp);
                            }
                            else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Predicted && (attr.PrefabType & GhostPrefabType.PredictedClient) == 0)
                            {
                                DstEntityManager.RemoveComponent(entity, comp);
                            }
                        }
                    }
                    // Even if converting for client and server we can remove components which are only for predicted clients when
                    // the ghost is always interpolated, or components which are only for interpolated clients if the ghost is always
                    // predicted
                    else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated)
                    {
                        foreach (var comp in components)
                        {
                            var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>();
                            if (attr != null && (attr.PrefabType & (GhostPrefabType.InterpolatedClient | GhostPrefabType.Server)) == 0)
                            {
                                DstEntityManager.RemoveComponent(entity, comp);
                            }
                        }
                    }
                    else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Predicted)
                    {
                        foreach (var comp in components)
                        {
                            var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>();
                            if (attr != null && (attr.PrefabType & (GhostPrefabType.PredictedClient | GhostPrefabType.Server)) == 0)
                            {
                                DstEntityManager.RemoveComponent(entity, comp);
                            }
                        }
                    }

                    // This logic needs to match the logic creating LinkedEntityGroups, gather a list of all child entities
                    var linkedEntities  = new NativeList <Entity>(1, Allocator.Temp);
                    var selfAndChildren = ghostAuthoring.gameObject.GetComponentsInChildren <Transform>(true);
                    foreach (var transform in selfAndChildren)
                    {
                        foreach (var child in GetEntities(transform.gameObject))
                        {
                            if (DstEntityManager.Exists(child))
                            {
                                linkedEntities.Add(child);
                            }
                        }
                    }
                    // Mark all child entities as ghost children, entity 0 is the root and hsould not be marked
                    for (int i = 1; i < linkedEntities.Length; ++i)
                    {
                        DstEntityManager.AddComponentData(linkedEntities[i], default(GhostChildEntityComponent));
                    }

                    if (isPrefab)
                    {
                        var contentHash = TypeHash.FNV1A64(ghostAuthoring.Importance);
                        contentHash     = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64((int)ghostAuthoring.SupportedGhostModes));
                        contentHash     = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64((int)ghostAuthoring.DefaultGhostMode));
                        contentHash     = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64((int)ghostAuthoring.OptimizationMode));
                        contentHash     = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64(ghostAuthoring.Name.ToString()));
                        foreach (var comp in components)
                        {
                            contentHash = TypeHash.CombineFNV1A64(contentHash, TypeManager.GetTypeInfo(comp.TypeIndex).StableTypeHash);
                            var attr    = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>();
                            if (attr != null)
                            {
                                contentHash = TypeHash.CombineFNV1A64(contentHash, TypeHash.FNV1A64((int)attr.PrefabType));
                            }
                        }
                        var blobHash = new Unity.Entities.Hash128(ghostType.guid0 ^ (uint)(contentHash >> 32), ghostType.guid1 ^ (uint)(contentHash), ghostType.guid2, ghostType.guid3);
                        context.AssociateBlobAssetWithUnityObject(blobHash, ghostAuthoring.gameObject);
                        if (context.NeedToComputeBlobAsset(blobHash))
                        {
                            var builder  = new BlobBuilder(Allocator.Temp);
                            ref var root = ref builder.ConstructRoot <GhostPrefabMetaData>();

                            // Store importance, supported modes, default mode and name in the meta data blob asset
                            root.Importance     = ghostAuthoring.Importance;
                            root.SupportedModes = GhostPrefabMetaData.GhostMode.Both;
                            root.DefaultMode    = GhostPrefabMetaData.GhostMode.Interpolated;
                            if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated)
                            {
                                root.SupportedModes = GhostPrefabMetaData.GhostMode.Interpolated;
                            }
                            else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Predicted)
                            {
                                root.SupportedModes = GhostPrefabMetaData.GhostMode.Predicted;
                                root.DefaultMode    = GhostPrefabMetaData.GhostMode.Predicted;
                            }
                            else if (ghostAuthoring.DefaultGhostMode == GhostAuthoringComponent.GhostMode.OwnerPredicted)
                            {
                                if (!DstEntityManager.HasComponent <GhostOwnerComponent>(entity))
                                {
                                    throw new InvalidOperationException("OwnerPrediction mode can only be used on prefabs which have a GhostOwnerComponent");
                                }
                                root.DefaultMode = GhostPrefabMetaData.GhostMode.Both;
                            }
                            else if (ghostAuthoring.DefaultGhostMode == GhostAuthoringComponent.GhostMode.Predicted)
                            {
                                root.DefaultMode = GhostPrefabMetaData.GhostMode.Predicted;
                            }
                            root.StaticOptimization = (ghostAuthoring.OptimizationMode == GhostAuthoringComponent.GhostOptimizationMode.Static);
                            builder.AllocateString(ref root.Name, ghostAuthoring.Name);

                            var serverComponents      = new NativeList <ulong>(components.Length, Allocator.Temp);
                            var removeOnServer        = new NativeList <ulong>(components.Length, Allocator.Temp);
                            var removeOnClient        = new NativeList <ulong>(components.Length, Allocator.Temp);
                            var disableOnPredicted    = new NativeList <ulong>(components.Length, Allocator.Temp);
                            var disableOnInterpolated = new NativeList <ulong>(components.Length, Allocator.Temp);

                            // Snapshot data buffers should be removed from the server, and shared ghost type from the client
                            removeOnServer.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <SnapshotData>().TypeIndex).StableTypeHash);
                            removeOnServer.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <SnapshotDataBuffer>().TypeIndex).StableTypeHash);
                            removeOnClient.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <SharedGhostTypeComponent>().TypeIndex).StableTypeHash);

                            // If both interpolated and predicted clients are supported the interpolated client needs to disable the prediction component
                            // If the ghost is interpolated only the prediction component can be removed on clients
                            if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.All)
                            {
                                disableOnInterpolated.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <PredictedGhostComponent>().TypeIndex).StableTypeHash);
                            }
                            else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated)
                            {
                                removeOnClient.Add(TypeManager.GetTypeInfo(ComponentType.ReadWrite <PredictedGhostComponent>().TypeIndex).StableTypeHash);
                            }

                            foreach (var comp in components)
                            {
                                var hash = TypeManager.GetTypeInfo(comp.TypeIndex).StableTypeHash;
                                var attr = comp.GetManagedType().GetCustomAttribute <GhostComponentAttribute>();
                                if (attr == null)
                                {
                                    serverComponents.Add(hash);
                                    continue;
                                }
                                if ((attr.PrefabType & GhostPrefabType.Server) == 0)
                                {
                                    removeOnServer.Add(hash);
                                }
                                else
                                {
                                    serverComponents.Add(hash);
                                }

                                // If something is not used on the client, remove it. Make sure to include things that is interpolated only if ghost
                                // is predicted only and the other way around
                                if ((attr.PrefabType & GhostPrefabType.Client) == 0)
                                {
                                    removeOnClient.Add(hash);
                                }
                                else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Interpolated &&
                                         (attr.PrefabType & GhostPrefabType.InterpolatedClient) == 0)
                                {
                                    removeOnClient.Add(hash);
                                }
                                else if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.Predicted &&
                                         (attr.PrefabType & GhostPrefabType.PredictedClient) == 0)
                                {
                                    removeOnClient.Add(hash);
                                }

                                // If the prefab only supports a single mode on the client there is no need to enable / disable, if is handled by the
                                // previous loop removing components on the client instead
                                if (ghostAuthoring.SupportedGhostModes == GhostAuthoringComponent.GhostModeMask.All)
                                {
                                    // Components available on predicted but not interpolated should be disabled on interpolated clients
                                    if ((attr.PrefabType & GhostPrefabType.InterpolatedClient) == 0 && (attr.PrefabType & GhostPrefabType.PredictedClient) != 0)
                                    {
                                        disableOnInterpolated.Add(hash);
                                    }
                                    if ((attr.PrefabType & GhostPrefabType.InterpolatedClient) != 0 && (attr.PrefabType & GhostPrefabType.PredictedClient) == 0)
                                    {
                                        disableOnPredicted.Add(hash);
                                    }
                                }
                            }
                            var blobServerComponents = builder.Allocate(ref root.ServerComponentList, serverComponents.Length);
                            for (int i = 0; i < serverComponents.Length; ++i)
                            {
                                blobServerComponents[i] = serverComponents[i];
                            }

                            // A pre-spawned instance can be created in ClientServer even if the prefab is not, so anything which should
                            // be usable on the server needs to know what to remove from the server version
                            if (target != NetcodeConversionTarget.Client)
                            {
                                // Client only data never needs information about the server
                                var blobRemoveOnServer = builder.Allocate(ref root.RemoveOnServer, removeOnServer.Length);
                                for (int i = 0; i < removeOnServer.Length; ++i)
                                {
                                    blobRemoveOnServer[i] = removeOnServer[i];
                                }
                            }
                            else
                            {
                                builder.Allocate(ref root.RemoveOnServer, 0);
                            }
                            if (target != NetcodeConversionTarget.Server)
                            {
                                var blobRemoveOnClient = builder.Allocate(ref root.RemoveOnClient, removeOnClient.Length);
                                for (int i = 0; i < removeOnClient.Length; ++i)
                                {
                                    blobRemoveOnClient[i] = removeOnClient[i];
                                }
                            }
                            else
                            {
                                builder.Allocate(ref root.RemoveOnClient, 0);
                            }

                            if (target != NetcodeConversionTarget.Server)
                            {
                                // The data for interpolated / predicted diff is required unless this is server-only
                                var blobDisableOnPredicted = builder.Allocate(ref root.DisableOnPredictedClient, disableOnPredicted.Length);
                                for (int i = 0; i < disableOnPredicted.Length; ++i)
                                {
                                    blobDisableOnPredicted[i] = disableOnPredicted[i];
                                }
                                var blobDisableOnInterpolated = builder.Allocate(ref root.DisableOnInterpolatedClient, disableOnInterpolated.Length);
                                for (int i = 0; i < disableOnInterpolated.Length; ++i)
                                {
                                    blobDisableOnInterpolated[i] = disableOnInterpolated[i];
                                }
                            }
                            else
                            {
                                builder.Allocate(ref root.DisableOnPredictedClient, 0);
                                builder.Allocate(ref root.DisableOnInterpolatedClient, 0);
                            }

                            var blobAsset = builder.CreateBlobAssetReference <GhostPrefabMetaData>(Allocator.Persistent);
                            context.AddComputedBlobAsset(blobHash, blobAsset);
                        }
                        context.GetBlobAsset(blobHash, out var blob);
                        DstEntityManager.AddComponentData(entity, new GhostPrefabMetaDataComponent {
                            Value = blob
                        });
                    }
                });
Esempio n. 13
0
        protected override void OnUpdate()
        {
            var materials = new List <Material>(10);

            Entities.ForEach((SkinnedMeshRenderer meshRenderer) =>
            {
                meshRenderer.GetSharedMaterials(materials);
                var mesh           = meshRenderer.sharedMesh;
                var root           = meshRenderer.rootBone ? meshRenderer.rootBone : meshRenderer.transform;
                var hasSkinning    = mesh == null ? false : mesh.boneWeights.Length > 0 && mesh.bindposes.Length > 0;
                var hasBlendShapes = mesh == null ? false : mesh.blendShapeCount > 0;
                var deformedEntity = GetPrimaryEntity(meshRenderer);

                // Convert Renderers as normal MeshRenderers.
                MeshRendererConversion.Convert(DstEntityManager, this, k_AttachToPrimaryEntityForSingleMaterial, meshRenderer, mesh, materials, root, meshRenderer.localBounds.ToAABB());

                foreach (var rendererEntity in GetEntities(meshRenderer))
                {
                    if (DstEntityManager.HasComponent <RenderMesh>(rendererEntity))
                    {
                        // Add relevant deformation tags to converted render entities and link them to the DeformedEntity.
#if ENABLE_COMPUTE_DEFORMATIONS
                        DstEntityManager.AddComponentData(rendererEntity, new DeformedMeshIndex());
#endif
                        DstEntityManager.AddComponentData(rendererEntity, new DeformedEntity {
                            Value = deformedEntity
                        });

                        if (hasSkinning)
                        {
                            DstEntityManager.AddComponent <SkinningTag>(rendererEntity);
                        }

                        if (hasBlendShapes)
                        {
                            DstEntityManager.AddComponent <BlendShapeTag>(rendererEntity);
                        }
                    }
                }

                // Fill the blend shape weights.
                if (hasBlendShapes && !DstEntityManager.HasComponent <BlendShapeWeight>(deformedEntity))
                {
                    DstEntityManager.AddBuffer <BlendShapeWeight>(deformedEntity);
                    var weights = DstEntityManager.GetBuffer <BlendShapeWeight>(deformedEntity);
                    weights.ResizeUninitialized(meshRenderer.sharedMesh.blendShapeCount);

                    for (int i = 0; i < weights.Length; ++i)
                    {
                        weights[i] = new BlendShapeWeight {
                            Value = meshRenderer.GetBlendShapeWeight(i)
                        };
                    }
                }

                // Fill the skin matrices with bindpose skin matrices.
                if (hasSkinning && !DstEntityManager.HasComponent <SkinMatrix>(deformedEntity))
                {
                    var bones         = meshRenderer.bones;
                    var rootMatrixInv = root.localToWorldMatrix.inverse;

                    DstEntityManager.AddBuffer <SkinMatrix>(deformedEntity);
                    var skinMatrices = DstEntityManager.GetBuffer <SkinMatrix>(deformedEntity);
                    skinMatrices.ResizeUninitialized(bones.Length);

                    for (int i = 0; i < bones.Length; ++i)
                    {
                        var bindPose         = meshRenderer.sharedMesh.bindposes[i];
                        var boneMatRootSpace = math.mul(rootMatrixInv, bones[i].localToWorldMatrix);
                        var skinMatRootSpace = math.mul(boneMatRootSpace, bindPose);
                        skinMatrices[i]      = new SkinMatrix {
                            Value = new float3x4(skinMatRootSpace.c0.xyz, skinMatRootSpace.c1.xyz, skinMatRootSpace.c2.xyz, skinMatRootSpace.c3.xyz)
                        };
                    }
                }
            });
        }
        private void ConvertCompoundColliders()
        {
            Profiler.BeginSample("ConvertCompoundColliders");

            m_nativeColliders  = new NativeList <Collider>(128, Allocator.TempJob);
            m_nativeTransforms = new NativeList <RigidTransform>(128, Allocator.TempJob);
            m_compoundRanges   = new NativeList <int2>(128, Allocator.TempJob);

            //Step 1: Find all colliders and construct parallel arrays
            m_authorings.Clear();
            Entities.WithNone <DontConvertColliderTag>().ForEach((ColliderAuthoring colliderAuthoring) =>
            {
                //Do stuff
                if (colliderAuthoring.colliderType == AuthoringColliderTypes.None)
                {
                    return;
                }
                if (colliderAuthoring.generateFromChildren)
                {
                    m_unityColliders.Clear();
                    colliderAuthoring.GetComponentsInChildren(m_unityColliders);
                    try
                    {
                        CreateChildrenColliders(colliderAuthoring, m_unityColliders, m_nativeColliders, m_nativeTransforms, m_compoundRanges);
                    }
                    catch (Exception e)
                    {
                        DisposeAndThrow(e);
                    }
                }
                else
                {
                    try
                    {
                        CreateChildrenColliders(colliderAuthoring, colliderAuthoring.colliders, m_nativeColliders, m_nativeTransforms, m_compoundRanges);
                    }
                    catch (Exception e)
                    {
                        DisposeAndThrow(e);
                    }
                }
                m_authorings.Add(colliderAuthoring);
            });

            if (m_authorings.Count > 0)
            {
                using (var computationContext = new BlobAssetComputationContext <CompoundColliderComputationData, CompoundColliderBlob>(BlobAssetStore, 128, Allocator.Temp))
                {
                    //Step 2: Compute hashes
                    var hashes = new NativeArray <ColliderTransformHashPair>(m_compoundRanges.Length, Allocator.TempJob);
                    new ComputeCompoundHashesJob
                    {
                        colliders  = m_nativeColliders,
                        transforms = m_nativeTransforms,
                        ranges     = m_compoundRanges,
                        hashes     = hashes
                    }.ScheduleParallel(m_compoundRanges.Length, 1, default).Complete();

                    //Step 3: Check hashes against computationContext to see if blobs need to be built
                    for (int i = 0; i < m_authorings.Count; i++)
                    {
                        var hash = hashes.ReinterpretLoad <Hash128>(i);
                        computationContext.AssociateBlobAssetWithUnityObject(hash, m_authorings[i].gameObject);
                        if (computationContext.NeedToComputeBlobAsset(hash))
                        {
                            computationContext.AddBlobAssetToCompute(hash, new CompoundColliderComputationData
                            {
                                hash  = hash,
                                index = i
                            });
                        }
                    }

                    //Step 4: Dispatch builder job
                    using (var computationData = computationContext.GetSettings(Allocator.TempJob))
                    {
                        new ComputeCompoundBlobs
                        {
                            colliders       = m_nativeColliders,
                            transforms      = m_nativeTransforms,
                            ranges          = m_compoundRanges,
                            computationData = computationData
                        }.ScheduleParallel(computationData.Length, 1, default).Complete();

                        foreach (var data in computationData)
                        {
                            computationContext.AddComputedBlobAsset(data.hash, data.blob);
                        }
                    }

                    //Step 5: Build Collider component
                    var index = 0;
                    Entities.ForEach((ColliderAuthoring colliderAuthoring) =>
                    {
                        computationContext.GetBlobAsset(hashes.ReinterpretLoad <Hash128>(index++), out var blob);

                        var targetEntity = GetPrimaryEntity(colliderAuthoring);

                        DeclareDependency(colliderAuthoring, colliderAuthoring.transform);
                        float3 scale = colliderAuthoring.transform.lossyScale;
                        if (scale.x != scale.y || scale.x != scale.z)
                        {
                            throw new InvalidOperationException(
                                $"GameObject Conversion Error: Failed to convert {colliderAuthoring}. Only uniform scale is permitted on Compound colliders.");
                        }

                        Collider icdCompound = new CompoundCollider
                        {
                            compoundColliderBlob = blob,
                            scale = scale.x
                        };
                        DstEntityManager.AddComponentData(targetEntity, icdCompound);
                    });

                    hashes.Dispose();
                }
            }

            m_nativeColliders.Dispose();
            m_nativeTransforms.Dispose();
            m_compoundRanges.Dispose();

            Profiler.EndSample();
        }
    protected override void OnUpdate()
    {
        ForEach((LODGroup lodGroup) =>
        {
            if (lodGroup.lodCount > 8)
            {
                Debug.LogWarning("LODGroup has more than 8 LOD - Not supported", lodGroup);
                return;
            }

            var lodGroupEntity = GetPrimaryEntity(lodGroup);

            var lodGroupData = new MeshLODGroupComponent();
            //@TODO: LOD calculation should respect scale...
            var worldSpaceSize = LODGroupExtensions.GetWorldSpaceSize(lodGroup);
            lodGroupData.LocalReferencePoint = lodGroup.localReferencePoint;

            var lodDistances0 = new float4(float.PositiveInfinity);
            var lodDistances1 = new float4(float.PositiveInfinity);
            var lodGroupLODs  = lodGroup.GetLODs();
            for (int i = 0; i < lodGroup.lodCount; ++i)
            {
                float d = worldSpaceSize / lodGroupLODs[i].screenRelativeTransitionHeight;
                if (i < 4)
                {
                    lodDistances0[i] = d;
                }
                else
                {
                    lodDistances1[i - 4] = d;
                }
            }

            lodGroupData.LODDistances0 = lodDistances0;
            lodGroupData.LODDistances1 = lodDistances1;

            DstEntityManager.AddComponentData(lodGroupEntity, lodGroupData);

            for (int i = 0; i < lodGroupLODs.Length; ++i)
            {
                foreach (var renderer in lodGroupLODs[i].renderers)
                {
                    if (renderer == null)
                    {
                        Debug.LogWarning("Missing renderer in LOD Group", lodGroup);
                        continue;
                    }

                    foreach (var rendererEntity in GetEntities(renderer))
                    {
                        if (DstEntityManager.HasComponent <RenderMesh>(rendererEntity))
                        {
                            var lodComponent = new MeshLODComponent {
                                Group = lodGroupEntity, LODMask = 1 << i
                            };
                            DstEntityManager.AddComponentData(rendererEntity, lodComponent);
                        }
                    }
                }
            }
        });
    }