void PlaceOccludingObjects(
        GameObject[] objectsToPlace, Camera camera, PlacementStatics statics, NativeList <PlacedObject> placedObjects)
    {
        var textures = statics.BackgroundImages;

        if (m_OccludingObjectCache == null)
        {
            m_OccludingObjectCache = new GameObjectOneWayCache(m_ParentOccluding.transform, objectsToPlace);
        }

        m_OccludingObjectCache.ResetAllObjects();
        var occludingObjectBounds = ComputeObjectBounds(objectsToPlace);

        var materialPropertyBlock  = new MaterialPropertyBlock();
        var placedOccludingObjects = new NativeArray <PlacedObject>(placedObjects.Length, Allocator.TempJob);
        var placementRegion        = ObjectPlacementUtilities.ComputePlacementRegion(camera, k_OccludingLayerDistance);

        using (s_ComputePlacements.Auto())
        {
            var job = new ComputeOccludingObjectPlacements()
            {
                OccludingObjectBounds   = occludingObjectBounds,
                ImageCoordinates        = placementRegion,
                Transformer             = new WorldToScreenTransformer(camera),
                PlacedForegroundObjects = placedObjects,
                RandomSeed             = m_Rand.NextUInt(),
                PlacedOccludingObjects = placedOccludingObjects,
                ScalingMin             = statics.ScalingMin,
                ScalingSize            = statics.ScalingSize
            };
            job.Schedule(placedObjects.Length, 10).Complete();
        }

        using (s_SetupObjects.Auto())
        {
            foreach (var placedOccludingObject in placedOccludingObjects)
            {
                if (placedOccludingObject.PrefabIndex < 0)
                {
                    continue;
                }

                var prefab        = objectsToPlace[placedOccludingObject.PrefabIndex];
                var objectToPlace = m_OccludingObjectCache.GetOrInstantiate(prefab);
                objectToPlace.layer = m_OccludingLayer;

                var meshRenderer = objectToPlace.GetComponentInChildren <MeshRenderer>();
                meshRenderer.GetPropertyBlock(materialPropertyBlock);
                ObjectPlacementUtilities.CreateRandomizedHue(materialPropertyBlock, statics.OccludingHueMaxOffset, ref m_Rand);
                materialPropertyBlock.SetTexture("_BaseMap", textures[m_Rand.NextInt(textures.Length)]);
                meshRenderer.SetPropertyBlock(materialPropertyBlock);

                objectToPlace.transform.localPosition = placedOccludingObject.Position;
                objectToPlace.transform.localRotation = placedOccludingObject.Rotation;
                objectToPlace.transform.localScale    = Vector3.one * placedOccludingObject.Scale;
            }
        }
        placedOccludingObjects.Dispose();
        occludingObjectBounds.Dispose();
    }
Exemple #2
0
 public void IntersectRect_ReturnsCorrectValues(Rect a, Rect b, Rect expected)
 {
     // Test identities
     Assert.AreEqual(a, ObjectPlacementUtilities.IntersectRect(a, a));
     Assert.AreEqual(b, ObjectPlacementUtilities.IntersectRect(b, b));
     // Test operation
     Assert.AreEqual(expected, ObjectPlacementUtilities.IntersectRect(a, b));
     // Test for symmetry
     Assert.AreEqual(expected, ObjectPlacementUtilities.IntersectRect(b, a));
 }
Exemple #3
0
        public void ComputeAreaOfTriangle_IgnoresTranslations(float area, Vector2[] triangle)
        {
            var translation = m_Rand.NextFloat2();

            for (var i = 0; i < 3; i++)
            {
                triangle[i] = (Vector2)translation + triangle[i];
            }
            Assert.AreApproximatelyEqual(area,
                                         ObjectPlacementUtilities.ComputeAreaOfTriangle(triangle[0], triangle[1], triangle[2]));
        }
Exemple #4
0
        public void ComputeAreaOfTriangle_IgnoresZAxis(float area, Vector2[] triangle)
        {
            var triangle3d = new Vector3[3];

            for (var i = 0; i < 3; i++)
            {
                triangle3d[i] = (Vector3)triangle[i] + m_Rand.NextFloat(-10f, 10f) * Vector3.forward;
            }

            Assert.AreApproximatelyEqual(area,
                                         ObjectPlacementUtilities.ComputeAreaOfTriangle(triangle3d[0], triangle3d[1], triangle3d[2]));
        }
    static NativeArray <Bounds> ComputeObjectBounds(GameObject[] prefabs)
    {
        var objectBounds = new NativeArray <Bounds>(prefabs.Length, Allocator.TempJob);

        using (s_CollectBounds.Auto())
        {
            for (int i = 0; i < prefabs.Length; i++)
            {
                var bounds = ObjectPlacementUtilities.ComputeBounds(prefabs[i]);
                objectBounds[i] = bounds;
            }
        }

        return(objectBounds);
    }
Exemple #6
0
 public void ComputeAreaOfTriangle_IsOrderInvariant(float area, Vector2[] triangle)
 {
     Assert.AreApproximatelyEqual(area,
                                  ObjectPlacementUtilities.ComputeAreaOfTriangle(triangle[0], triangle[1], triangle[2]));
     Assert.AreApproximatelyEqual(area,
                                  ObjectPlacementUtilities.ComputeAreaOfTriangle(triangle[0], triangle[2], triangle[1]));
     Assert.AreApproximatelyEqual(area,
                                  ObjectPlacementUtilities.ComputeAreaOfTriangle(triangle[1], triangle[0], triangle[2]));
     Assert.AreApproximatelyEqual(area,
                                  ObjectPlacementUtilities.ComputeAreaOfTriangle(triangle[1], triangle[2], triangle[0]));
     Assert.AreApproximatelyEqual(area,
                                  ObjectPlacementUtilities.ComputeAreaOfTriangle(triangle[2], triangle[1], triangle[0]));
     Assert.AreApproximatelyEqual(area,
                                  ObjectPlacementUtilities.ComputeAreaOfTriangle(triangle[2], triangle[0], triangle[1]));
 }
    static NativeArray <Bounds> ComputeObjectBounds(GameObject[] prefabs)
    {
        var objectBounds = new NativeArray <Bounds>(prefabs.Length, Allocator.TempJob);

        using (s_CollectBounds.Auto())
        {
            for (int i = 0; i < prefabs.Length; i++)
            {
                var bounds = ObjectPlacementUtilities.ComputeBounds(prefabs[i]);
                //assume objects will be aligned at origin
                bounds.center   = Vector3.zero;
                objectBounds[i] = bounds;
            }
        }

        return(objectBounds);
    }
 void EnsureObjectGroupsExist(PlacementStatics statics, int objectGroupIndex)
 {
     while (m_ParentForeground.transform.childCount < statics.ForegroundPrefabs.Length * (objectGroupIndex + 1))
     {
         foreach (var foregroundPrefab in statics.ForegroundPrefabs)
         {
             var newParent = new GameObject();
             newParent.transform.parent = m_ParentForeground.transform;
             var gameObject = Object.Instantiate(foregroundPrefab, newParent.transform);
             var bounds     = ObjectPlacementUtilities.ComputeBounds(gameObject);
             gameObject.transform.localPosition -= bounds.center;
             gameObject.layer = m_ForegroundLayer;
             newParent.name   = gameObject.name;
             ObjectPlacementUtilities.SetMeshRenderersEnabledRecursive(gameObject, false);
         }
     }
 }
        public void Execute(int index)
        {
            var foregroundObjectBox = PlacedForegroundObjects[index];
            // See comment regarding Random in jobs in BackgroundGenerator.PlaceObjectsJob
            var rand = new Random(RandomSeed + (uint)index * ObjectPlacementUtilities.LargePrimeNumber);

            var prefabIndex = rand.NextInt(OccludingObjectBounds.Length);
            var bounds      = OccludingObjectBounds[prefabIndex];
            var foregroundObjectBoundingBox = ObjectPlacementUtilities.IntersectRect(
                foregroundObjectBox.BoundingBox, ImageCoordinates);

            //place over a foreground object such that overlap is between 10%-30%
            var numTries = 0;

            PlacedOccludingObjects[index] = new PlacedObject()
            {
                PrefabIndex = -1
            };
            while (numTries < 1000)
            {
                numTries++;
                var rotation = rand.NextQuaternionRotation();
                var position = new Vector3(rand.NextFloat(foregroundObjectBoundingBox.xMin, foregroundObjectBoundingBox.xMax),
                                           rand.NextFloat(foregroundObjectBoundingBox.yMin, foregroundObjectBoundingBox.yMax), 0f);
                var scale = ObjectPlacementUtilities.ComputeScaleToMatchArea(Transformer, position, rotation, bounds,
                                                                             rand.NextFloat(ScalingMin, ScalingMin + ScalingSize) * foregroundObjectBox.ProjectedArea);
                var placedObject = new PlacedObject()
                {
                    Scale       = scale,
                    Rotation    = rotation,
                    Position    = position,
                    PrefabIndex = prefabIndex
                };
                // NOTE: This computation is done with orthographic projection and will be slightly inaccurate
                //       when rendering with perspective projection
                var occludingObjectBox = GetBoundingBox(bounds, scale, position, rotation);
                var cropping           = ComputeOverlap(foregroundObjectBoundingBox, occludingObjectBox);
                if (cropping >= 0.10 && cropping <= 0.30)
                {
                    PlacedOccludingObjects[index] = placedObject;
                    return;
                }
            }
        }
        public void Execute()
        {
            bool placedSuccessfully;

            do
            {
                var curriculumState = *CurriculumStatePtr;
                var bounds          = ObjectBounds[curriculumState.PrefabIndex];
                var scale           =
                    ObjectPlacementUtilities.ComputeForegroundScaling(bounds, NativePlacementStatics.ScaleFactors[curriculumState.ScaleIndex]);
                var rotation = ObjectPlacementUtilities.ComposeForegroundRotation(curriculumState,
                                                                                  NativePlacementStatics.OutOfPlaneRotations, NativePlacementStatics.InPlaneRotations);
                var placedObject = new PlacedObject
                {
                    Scale       = scale,
                    Rotation    = rotation,
                    PrefabIndex = curriculumState.PrefabIndex,
                };
                placedSuccessfully = false;
                for (var i = 0; i < 100; i++)
                {
                    placedObject.Position = new Vector3(RandomPtr->NextFloat(ImageCoordinates.xMin, ImageCoordinates.xMax),
                                                        RandomPtr->NextFloat(ImageCoordinates.yMin, ImageCoordinates.yMax), 0f);
                    placedObject.ProjectedArea = ObjectPlacementUtilities.ComputeProjectedArea(
                        Transformer, placedObject.Position, rotation, bounds, scale);

                    placedObject.BoundingBox = GetBoundingBox(bounds, placedObject.Scale, placedObject.Position, placedObject.Rotation);
                    var cropping      = CalculateCropping(placedObject.BoundingBox, ImageCoordinates);
                    var passedOverlap = ValidateOverlap(placedObject.BoundingBox, PlaceObjects);
                    if ((cropping <= .5 && passedOverlap))
                    {
                        placedSuccessfully = true;
                        PlaceObjects.Add(placedObject);
                        *CurriculumStatePtr = NextCurriculumState(curriculumState, NativePlacementStatics);

                        break;
                    }
                }

                // If it can’t be placed within the scene due to violations of the cropping or overlap
                // constraints we stop processing the current foreground scene
                // and start with the next one.
            } while (placedSuccessfully && PlaceObjects.Length < NativePlacementStatics.MaxForegroundObjects && CurriculumStatePtr->ScaleIndex < NativePlacementStatics.ScaleFactors.Length);
        }
    void EnsureObjectGroupsExist(PlacementStatics statics, int objectGroupIndex)
    {
        while (m_ParentForeground.transform.childCount < statics.ForegroundPrefabs.Length * (objectGroupIndex + 1))
        {
            foreach (var foregroundPrefab in statics.ForegroundPrefabs)
            {
                var gameObject = Object.Instantiate(foregroundPrefab, m_ParentForeground.transform);
                gameObject.layer = m_ForegroundLayer;
                ObjectPlacementUtilities.SetMeshRenderersEnabledRecursive(gameObject, false);
                var labeling = gameObject.AddComponent <Labeling>();
                var name     = foregroundPrefab.name;
                if (s_NameRegex.IsMatch(name))
                {
                    name = name.Substring(0, name.Length - 3);
                }

                labeling.labels.Add(name);
            }
        }
    }
    int EstimateTotalFrames()
    {
        var scaleFactorRange             = m_ScaleFactorCurve.value;
        var steps                        = m_StepsField.value;
        var stepsPerJob                  = m_StepsPerJobField.value;
        var maxFramesPerJob              = m_MaxFramesField.value;
        var maxForegroundObjectsPerFrame = m_MaxForegroundObjectsPerFrame.value;

        if (steps == 0 || maxFramesPerJob == 0 || stepsPerJob == 0 || maxForegroundObjectsPerFrame == 0)
        {
            return(0);
        }

        var inPlaneRotations    = ObjectPlacementUtilities.GenerateInPlaneRotationCurriculum(Allocator.Temp);
        var outOfPlaneRotations = ObjectPlacementUtilities.GenerateOutOfPlaneRotationCurriculum(Allocator.Temp);

        var framesPerScaleFactorMaxObjects           = inPlaneRotations.Length * outOfPlaneRotations.Length * 64 / maxForegroundObjectsPerFrame;
        var scaleAccountingForBackgroundInForeground = 1 / (1 - m_BackgroundInForegroundChanceField.value);
        var framesPerScaleFactorAtOneScale           = k_EstimatedFramesPerCurriculumStepAtOneScale * scaleAccountingForBackgroundInForeground * inPlaneRotations.Length * outOfPlaneRotations.Length;

        inPlaneRotations.Dispose();
        outOfPlaneRotations.Dispose();

        var stepSize = 1f / (steps + 1);
        var time     = 0f;
        var estimate = 0;

        for (int i = 0; i < steps; i++)
        {
            var scaleFactor  = scaleFactorRange.Evaluate(time);
            var stepEstimate = (int)(framesPerScaleFactorAtOneScale * (scaleFactor * scaleFactor));
            stepEstimate = Math.Max(stepEstimate, framesPerScaleFactorMaxObjects);
            estimate    += stepEstimate;
            time        += stepSize;
        }

        var maxFrames = (m_StepsField.value / stepsPerJob) * maxFramesPerJob;

        return(math.min(maxFrames, estimate));
    }
Exemple #13
0
        public void ComputeProjectedArea_ReturnsCorrectValues(float area, PrimitiveType primitive, Quaternion rotation)
        {
            var cameraGo = new GameObject("camera");
            var camera   = cameraGo.AddComponent <Camera>();

            camera.orthographic = true;
            var cameraViewAreaMeters = camera.orthographicSize * camera.orthographicSize * camera.aspect * 4;
            var cameraViewAreaPixels = camera.pixelHeight * camera.pixelWidth;
            var pixelsToMeters       = cameraViewAreaMeters / cameraViewAreaPixels;
            var transformer          = new WorldToScreenTransformer(camera);
            var mesh          = GetMeshForPrimitive(primitive);
            var projectedArea = ObjectPlacementUtilities.ComputeProjectedArea(
                transformer, Vector3.zero, rotation, mesh.bounds) * pixelsToMeters;

            Assert.AreApproximatelyEqual(area, projectedArea);
            var scale      = 1.5f;
            var scaledArea = ObjectPlacementUtilities.ComputeProjectedArea(
                transformer, Vector3.zero, rotation, mesh.bounds, scale) * pixelsToMeters;

            Assert.AreApproximatelyEqual(area * scale * scale, scaledArea);
            GameObject.Destroy(cameraGo);
        }
Exemple #14
0
    static MeshDrawInfo PlaceBackgroundObject(NativeArray <MeshInfo> meshInfos, WorldToScreenTransformer transformer,
                                              float foregroundObjectSize, Vector3 position,
                                              ref Random rand, float scaleMin, float scaleMax, int textureCount)
    {
        var meshIndex = rand.NextInt(0, meshInfos.Length);
        var meshInfo  = meshInfos[meshIndex];

        // Rotate/resize object
        var rotation    = rand.NextQuaternionRotation();
        var scaleRandom = rand.NextFloat(scaleMin, scaleMax);
        var scale       = ObjectPlacementUtilities.ComputeScaleToMatchArea(transformer, position, rotation, meshInfo.Bounds,
                                                                           scaleRandom * foregroundObjectSize);

        return(new MeshDrawInfo()
        {
            MeshIndex = meshIndex,
            Position = position,
            Rotation = rotation,
            Scale = scale * Vector3.one,
            TextureIndex = rand.NextInt(textureCount)
        });
    }
Exemple #15
0
    // Update is called once per frame
    void Update()
    {
        var tfSource = SourceObject.transform;
        // NOTE: The bounds from the meshfilter mesh are for the un-transformed mesh,
        //       the mesh renderer's mesh already has the transforms (rotation and scale) applied
        var boundsSource = SourceObject.GetComponent <MeshFilter>().sharedMesh.bounds;

        var transformer = new WorldToScreenTransformer(m_Camera);

        m_ProjectedSize = ObjectPlacementUtilities.ComputeProjectedArea(
            transformer, tfSource.position, tfSource.rotation, tfSource.localScale, boundsSource);
        m_TextUI.text = $"Area: {m_ProjectedSize:F2} px^2";

        foreach (var target in TargetObjects)
        {
            var tfTarget     = target.transform;
            var boundsTarget = target.GetComponent <MeshFilter>().sharedMesh.bounds;
            var scalarTarget = ObjectPlacementUtilities.ComputeScaleToMatchArea(
                transformer, tfTarget.position, tfTarget.rotation, boundsTarget, m_ProjectedSize);
            target.transform.localScale = scalarTarget * Vector3.one;
        }
    }
Exemple #16
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        if (!initialized)
        {
            Initialize();
        }

        if (!initialized)
        {
            return(inputDeps);
        }

        if (m_CurriculumQuery.CalculateEntityCount() != 1)
        {
            return(inputDeps);
        }

        using (s_ResetBackgroundObjects.Auto())
        {
            objectCache.ResetAllObjects();
        }

        var entity          = m_CurriculumQuery.GetSingletonEntity();
        var curriculumState = EntityManager.GetComponentData <CurriculumState>(entity);
        var statics         = EntityManager.GetComponentObject <PlacementStatics>(entity);

        if (curriculumState.ScaleIndex >= statics.ScaleFactors.Length)
        {
            return(inputDeps);
        }

        var meshInfos = new NativeArray <MeshInfo>(statics.BackgroundPrefabs.Length, Allocator.TempJob);

        for (int i = 0; i < statics.BackgroundPrefabs.Length; i++)
        {
            // ReSharper disable once UnusedVariable
            ObjectPlacementUtilities.GetMeshAndMaterial(statics.BackgroundPrefabs[i], out var material, out var meshToDraw);
            meshInfos[i] = new MeshInfo()
            {
                Bounds = meshToDraw.bounds
            };
        }

        var foregroundObject   = statics.ForegroundPrefabs[curriculumState.PrefabIndex];
        var foregroundBounds   = ObjectPlacementUtilities.ComputeBounds(foregroundObject);
        var foregroundRotation =
            ObjectPlacementUtilities.ComposeForegroundRotation(curriculumState, statics.OutOfPlaneRotations, statics.InPlaneRotations);
        var foregroundScale = ObjectPlacementUtilities.ComputeForegroundScaling(
            foregroundBounds, statics.ScaleFactors[curriculumState.ScaleIndex]);
        var transformer = new WorldToScreenTransformer(camera);
        // NOTE: For perspective projection, size will depend on position within the viewport, but we're approximating
        //       by computing size for the center
        var foregroundSizePixels = ObjectPlacementUtilities.ComputeProjectedArea(
            transformer, m_ForegroundCenter, foregroundRotation, foregroundBounds, foregroundScale);

        var placementRegion     = ObjectPlacementUtilities.ComputePlacementRegion(camera, k_PlacementDistance);
        var areaPlacementRegion = placementRegion.width * placementRegion.height;
        var cameraSquarePixels  = camera.pixelHeight * camera.pixelWidth;
        var foregroundSizeUnits = foregroundSizePixels * areaPlacementRegion / cameraSquarePixels;
        // Lazy approximation of how many subdivisions we need to achieve the target density
        var numCellsSqrt       = math.sqrt(m_objectDensity * areaPlacementRegion / foregroundSizeUnits);
        var numCellsHorizontal = (int)math.round(numCellsSqrt * m_aspectRatio);
        var numCellsVertical   = (int)math.round(numCellsSqrt / m_aspectRatio);
        var verticalStep       = placementRegion.height / numCellsVertical;
        var horizontalStep     = placementRegion.width / numCellsHorizontal;
        var scale0             = m_Rand.NextFloat(0.9f, 1.5f);
        var scale1             = m_Rand.NextFloat(0.9f, 1.5f);
        var scaleMin           = math.min(scale0, scale1);
        var scaleMax           = math.max(scale0, scale1);
        var cameraTf           = camera.transform;
        var placementOrigin    = new Vector3(placementRegion.x, placementRegion.y,
                                             k_PlacementDistance + cameraTf.position.z);

        DatasetCapture.ReportMetric(m_ScaleRangeMetric, $@"[ {{ ""scaleMin"": {scaleMin}, ""scaleMax"": {scaleMax} }}]");

        var meshesToDraw = new NativeArray <MeshDrawInfo>(numCellsHorizontal * numCellsVertical * numFillPasses, Allocator.TempJob);

        using (s_PlaceBackgroundObjects.Auto())
        {
            // XXX: Rather than placing a large collection and then looking for gaps, we simply assume that a sufficiently
            //      dense background will not have gaps - rendering way more objects than necessary is still substantially
            //      faster than trying to read the render texture multiple times per frame
            new PlaceBackgroundObjectsJob()
            {
                PlacementOrigin    = placementOrigin,
                Transformer        = new WorldToScreenTransformer(camera),
                NumCellsHorizontal = numCellsHorizontal,
                NumCellsVertical   = numCellsVertical,
                HorizontalStep     = horizontalStep,
                VerticalStep       = verticalStep,
                ForegroundSize     = foregroundSizePixels,
                MeshInfos          = meshInfos,
                MeshDrawInfos      = meshesToDraw,
                TextureCount       = statics.BackgroundImages.Length,
                Seed     = m_Rand.NextUInt(),
                MinScale = scaleMin,
                MaxScale = scaleMax
            }.Schedule(numFillPasses, 1, inputDeps).Complete();
        }

        using (s_DrawMeshes.Auto())
        {
            var properties = new MaterialPropertyBlock();
            foreach (var meshDrawInfo in meshesToDraw)
            {
                var prefab      = statics.BackgroundPrefabs[meshDrawInfo.MeshIndex];
                var sceneObject = objectCache.GetOrInstantiate(prefab);
                ObjectPlacementUtilities.CreateRandomizedHue(properties, backgroundHueMaxOffset, ref m_Rand);
                // ReSharper disable once Unity.PreferAddressByIdToGraphicsParams
                properties.SetTexture("_BaseMap", statics.BackgroundImages[meshDrawInfo.TextureIndex]);
                sceneObject.GetComponentInChildren <MeshRenderer>().SetPropertyBlock(properties);
                sceneObject.transform.SetPositionAndRotation(meshDrawInfo.Position, meshDrawInfo.Rotation);
                sceneObject.transform.localScale = meshDrawInfo.Scale;
            }
        }

        // We have finished drawing the meshes in the camera view, but the engine itself will call Render()
        // at the end of the frame
        meshInfos.Dispose();
        meshesToDraw.Dispose();

        var numObjectsExpected = numCellsHorizontal * numCellsVertical * numFillPasses;

        if (numObjectsExpected != objectCache.NumObjectsActive)
        {
            Debug.LogWarning($"BackgroundGenerator should have placed {numObjectsExpected} but is only using " +
                             $"{objectCache.NumObjectsActive} from the cache.");
        }

        return(inputDeps);
    }
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        if (m_CameraContainer == null)
        {
            m_CameraContainer = GameObject.Find("MainCamera");
            if (m_CameraContainer == null)
            {
                return(inputDeps);
            }
            var tfCamera = m_CameraContainer.transform;
            m_ParentForeground.transform.SetPositionAndRotation(
                tfCamera.position + tfCamera.forward * k_ForegroundLayerDistance, Quaternion.identity);
            m_ParentOccluding.transform.SetPositionAndRotation(
                tfCamera.position + tfCamera.forward * k_OccludingLayerDistance, Quaternion.identity);
        }

        using (s_ClearGameObjects.Auto())
        {
            for (var i = 0; i < m_ParentForeground.transform.childCount; i++)
            {
                var gameObject = m_ParentForeground.transform.GetChild(i).gameObject;
                ObjectPlacementUtilities.SetMeshRenderersEnabledRecursive(gameObject, false);
            }
        }

        if (m_ResourceDirectoriesQuery.CalculateEntityCount() != 1)
        {
            return(inputDeps);
        }

        var singletonEntity = m_CurriculumQuery.GetSingletonEntity();
        var curriculumState = EntityManager.GetComponentData <CurriculumState>(singletonEntity);
        var statics         = EntityManager.GetComponentObject <PlacementStatics>(singletonEntity);

        if (statics.ForegroundPrefabs == null || statics.ForegroundPrefabs.Length == 0)
        {
            return(inputDeps);
        }
        if (statics.BackgroundPrefabs == null || statics.BackgroundPrefabs.Length == 0)
        {
            return(inputDeps);
        }

        if (curriculumState.ScaleIndex >= statics.ScaleFactors.Length)
        {
            return(inputDeps);
        }

        var perceptionCamera = m_CameraContainer.GetComponent <PerceptionCamera>();

        if (perceptionCamera != null)
        {
            perceptionCamera.SetPersistentSensorData("scale", statics.ScaleFactors[curriculumState.ScaleIndex]);
        }

        var camera = m_CameraContainer.GetComponent <Camera>();
        NativeList <PlacedObject> placedObjectBoundingBoxes;

        using (s_PlaceObjects.Auto())
            placedObjectBoundingBoxes = PlaceObjects(camera, statics, ref curriculumState);

        ReportObjectStats(placedObjectBoundingBoxes, m_CameraContainer);

        var occludingObjects = statics.BackgroundPrefabs;

        using (s_PlaceOccludingObjects.Auto())
            PlaceOccludingObjects(occludingObjects, camera, statics, placedObjectBoundingBoxes);
        EntityManager.SetComponentData(singletonEntity, curriculumState);

        placedObjectBoundingBoxes.Dispose();

        return(inputDeps);
    }
Exemple #18
0
    // Start is called before the first frame update
    void Start()
    {
        var outOfPlaneParent    = new GameObject("Out of plane test");
        var outOfPlaneRotations = ObjectPlacementUtilities.GenerateOutOfPlaneRotationCurriculum(Allocator.Temp);

        foreach (var rotation in outOfPlaneRotations)
        {
            var instance = Instantiate(prefab, outOfPlaneParent.transform);
            instance.transform.localRotation = rotation;
        }


        var inPlaneParent    = new GameObject("In plane test");
        var inPlaneRotations = ObjectPlacementUtilities.GenerateInPlaneRotationCurriculum(Allocator.Persistent);

        for (var index = 0; index < inPlaneRotations.Length; index++)
        {
            var rotation = inPlaneRotations[index];
            var cube     = GameObject.CreatePrimitive(PrimitiveType.Cube);
            cube.transform.localScale = new Vector3(.2f, .2f, .2f);
            cube.transform.Translate(Vector3.down * index + Vector3.right * 5);
            cube.transform.localRotation = rotation;
            cube.transform.parent        = inPlaneParent.transform;
        }

        var combinedParent = new GameObject("Combined Test Grouped By In Plane");

        combinedParent.transform.localPosition = new Vector3(0, 0, 10);

        for (var iInPlane = 0; iInPlane < inPlaneRotations.Length; iInPlane++)
        {
            var inPlaneCombinedParent = new GameObject("In Plane #" + iInPlane);
            inPlaneCombinedParent.transform.parent        = combinedParent.transform;
            inPlaneCombinedParent.transform.localPosition = Vector3.right * (iInPlane * 2);
            for (var iOutOfPlane = 0; iOutOfPlane < outOfPlaneRotations.Length; iOutOfPlane++)
            {
                var rotation = ObjectPlacementUtilities.ComposeForegroundRotation(new CurriculumState()
                {
                    InPlaneRotationIndex    = iInPlane,
                    OutOfPlaneRotationIndex = iOutOfPlane
                }, outOfPlaneRotations, inPlaneRotations);
                var instance = Instantiate(prefab, inPlaneCombinedParent.transform);
                instance.transform.localPosition = Vector3.zero;
                instance.transform.localRotation = rotation;
            }
        }
        var combinedOutOfPlane = new GameObject("Combined Test Grouped By Out of Plane");

        combinedOutOfPlane.transform.localPosition = new Vector3(0, 0, 20);

        for (var iOutOfPlane = 0; iOutOfPlane < outOfPlaneRotations.Length; iOutOfPlane++)
        {
            var outOfPlaneCombinedParent = new GameObject("Out of Plane #" + iOutOfPlane);
            outOfPlaneCombinedParent.transform.parent        = combinedOutOfPlane.transform;
            outOfPlaneCombinedParent.transform.localPosition = Vector3.right * (iOutOfPlane * 2);
            for (var iInPlane = 0; iInPlane < inPlaneRotations.Length; iInPlane++)
            {
                var rotation = ObjectPlacementUtilities.ComposeForegroundRotation(new CurriculumState()
                {
                    InPlaneRotationIndex    = iInPlane,
                    OutOfPlaneRotationIndex = iOutOfPlane
                }, outOfPlaneRotations, inPlaneRotations);
                var instance = Instantiate(prefab, outOfPlaneCombinedParent.transform);
                instance.transform.localPosition = Vector3.zero;
                instance.transform.localRotation = rotation;
            }
        }

        var combinedHeirParent = new GameObject("Combined Test Using Heirarchy");

        combinedHeirParent.transform.localPosition = new Vector3(0, 0, 40);

        for (var iInPlane = 0; iInPlane < inPlaneRotations.Length; iInPlane++)
        {
            var inPlaneCombinedParent = new GameObject("In Plane #" + iInPlane);
            inPlaneCombinedParent.transform.parent        = combinedHeirParent.transform;
            inPlaneCombinedParent.transform.localPosition = Vector3.right * (iInPlane * 2);
            inPlaneCombinedParent.transform.localRotation = inPlaneRotations[iInPlane];
            for (var iOutOfPlane = 0; iOutOfPlane < outOfPlaneRotations.Length; iOutOfPlane++)
            {
                var instance = Instantiate(prefab, inPlaneCombinedParent.transform);
                instance.transform.localPosition = Vector3.zero;
                instance.transform.localRotation = outOfPlaneRotations[iOutOfPlane];
            }
        }

        var combinedHeirInvParent = new GameObject("Combined Test Using Heirarchy");

        combinedHeirInvParent.transform.localPosition = new Vector3(0, 0, 60);

        for (var iOutOfPlane = 0; iOutOfPlane < outOfPlaneRotations.Length; iOutOfPlane++)
        {
            var outOfPlaneCombinedParent = new GameObject("Out of Plane #" + iOutOfPlane);
            outOfPlaneCombinedParent.transform.parent        = combinedHeirInvParent.transform;
            outOfPlaneCombinedParent.transform.localPosition = Vector3.right * (iOutOfPlane * 2);
            outOfPlaneCombinedParent.transform.localRotation = outOfPlaneRotations[iOutOfPlane];
            for (var iInPlane = 0; iInPlane < inPlaneRotations.Length; iInPlane++)
            {
                var instance = Instantiate(prefab, outOfPlaneCombinedParent.transform);
                instance.transform.localPosition = Vector3.zero;
                instance.transform.localRotation = inPlaneRotations[iInPlane];
            }
        }


        var combinedStackedParent = new GameObject("Combined Test All Stacked");

        combinedStackedParent.transform.localPosition = new Vector3(0, 0, 70);

        for (var iInPlane = 0; iInPlane < inPlaneRotations.Length; iInPlane++)
        {
            for (var iOutOfPlane = 0; iOutOfPlane < outOfPlaneRotations.Length; iOutOfPlane++)
            {
                var rotation = ObjectPlacementUtilities.ComposeForegroundRotation(new CurriculumState()
                {
                    InPlaneRotationIndex    = iInPlane,
                    OutOfPlaneRotationIndex = iOutOfPlane
                }, outOfPlaneRotations, inPlaneRotations);
                var instance = Instantiate(prefab, combinedStackedParent.transform, true);
                instance.name = $"InPlane: {iInPlane} OutOfPlane: {iOutOfPlane}";
                instance.transform.localRotation = rotation;
                instance.transform.localPosition = Vector3.zero;
            }
        }

        outOfPlaneRotations.Dispose();
        inPlaneRotations.Dispose();
    }
    NativeList <PlacedObject> PlaceObjects(Camera camera, PlacementStatics statics, NativeArray <Bounds> occludingObjectBounds, ref CurriculumState curriculumState)
    {
        var placedObjectBoundingBoxes = new NativeList <PlacedObject>(500, Allocator.TempJob);
        var objectBounds = ComputeObjectBounds(statics.ForegroundPrefabs);

        var localCurriculumState = curriculumState;
        var curriculumStatePtr   = (CurriculumState *)UnsafeUtility.AddressOf(ref localCurriculumState);
        var localRandom          = m_Rand;
        var randomPtr            = (Random *)UnsafeUtility.AddressOf(ref localRandom);
        var placementRegion      = ObjectPlacementUtilities.ComputePlacementRegion(camera, k_ForegroundLayerDistance);

        using (s_ComputePlacements.Auto())
        {
            var computePlacementsJob = new ComputePlacementsJob()
            {
                CurriculumStatePtr     = curriculumStatePtr,
                Transformer            = new WorldToScreenTransformer(camera),
                ImageCoordinates       = placementRegion,
                ObjectBounds           = objectBounds,
                OccludingObjectBounds  = occludingObjectBounds,
                PlaceObjects           = placedObjectBoundingBoxes,
                RandomPtr              = randomPtr,
                NativePlacementStatics = new NativePlacementStatics
                {
                    ForegroundPrefabCount = statics.ForegroundPrefabs.Length,
                    MaxForegroundObjects  = statics.MaxForegroundObjectsPerFrame,
                    InPlaneRotations      = statics.InPlaneRotations,
                    OutOfPlaneRotations   = statics.OutOfPlaneRotations,
                    ScaleFactors          = statics.ScaleFactors,
                    BackgroundObjectInForegroundChance = statics.BackgroundObjectInForegroundChance,
                }
            };
            computePlacementsJob.Run();
            curriculumState = *computePlacementsJob.CurriculumStatePtr;
            m_Rand          = *computePlacementsJob.RandomPtr;
        }

        using (s_SetupObjects.Auto())
        {
            var materialPropertyBlock = new MaterialPropertyBlock();
            int objectGroupIndex      = 0;
            foreach (var placedObject in placedObjectBoundingBoxes)
            {
                GameObject gameObject;
                if (placedObject.IsOccluding)
                {
                    gameObject = m_BackgroundInForegroundObjectCache.GetOrInstantiate(statics.BackgroundPrefabs[placedObject.PrefabIndex]);

                    var meshRenderer = gameObject.GetComponentInChildren <MeshRenderer>();
                    meshRenderer.GetPropertyBlock(materialPropertyBlock);
                    ObjectPlacementUtilities.CreateRandomizedHue(materialPropertyBlock, statics.OccludingHueMaxOffset, ref m_Rand);
                    materialPropertyBlock.SetTexture("_BaseMap", statics.BackgroundImages[m_Rand.NextInt(statics.BackgroundImages.Length)]);
                    meshRenderer.SetPropertyBlock(materialPropertyBlock);
                }
                else
                {
                    EnsureObjectGroupsExist(statics, objectGroupIndex);
                    gameObject = m_ParentForeground.transform.GetChild(placedObject.PrefabIndex + objectGroupIndex * statics.ForegroundPrefabs.Length).gameObject;
                }

                gameObject.transform.localRotation = placedObject.Rotation;
                gameObject.transform.localScale    = Vector3.one * placedObject.Scale;
                gameObject.transform.localPosition = placedObject.Position;

                ObjectPlacementUtilities.SetMeshRenderersEnabledRecursive(gameObject, true);

                if (placedObject.PrefabIndex == statics.ForegroundPrefabs.Length - 1)
                {
                    objectGroupIndex++;
                }
            }
        }

        objectBounds.Dispose();

        return(placedObjectBoundingBoxes);
    }
    NativeList <PlacedObject> PlaceObjects(Camera camera, PlacementStatics statics, ref CurriculumState curriculumState)
    {
        var placedObjectBoundingBoxes = new NativeList <PlacedObject>(500, Allocator.TempJob);
        var objectBounds = ComputeObjectBounds(statics.ForegroundPrefabs);

        var localCurriculumState = curriculumState;
        var curriculumStatePtr   = (CurriculumState *)UnsafeUtility.AddressOf(ref localCurriculumState);
        var localRandom          = m_Rand;
        var randomPtr            = (Random *)UnsafeUtility.AddressOf(ref localRandom);
        var placementRegion      = ObjectPlacementUtilities.ComputePlacementRegion(camera, k_ForegroundLayerDistance);

        using (s_ComputePlacements.Auto())
        {
            var computePlacementsJob = new ComputePlacementsJob()
            {
                CurriculumStatePtr     = curriculumStatePtr,
                Transformer            = new WorldToScreenTransformer(camera),
                ImageCoordinates       = placementRegion,
                ObjectBounds           = objectBounds,
                PlaceObjects           = placedObjectBoundingBoxes,
                RandomPtr              = randomPtr,
                NativePlacementStatics = new NativePlacementStatics
                {
                    ForegroundPrefabCount = statics.ForegroundPrefabs.Length,
                    MaxForegroundObjects  = statics.MaxForegroundObjectsPerFrame,
                    InPlaneRotations      = statics.InPlaneRotations,
                    OutOfPlaneRotations   = statics.OutOfPlaneRotations,
                    ScaleFactors          = statics.ScaleFactors
                }
            };
            computePlacementsJob.Run();
            curriculumState = *computePlacementsJob.CurriculumStatePtr;
            m_Rand          = *computePlacementsJob.RandomPtr;
        }

        using (s_SetupObjects.Auto())
        {
            int objectGroupIndex = 0;
            foreach (var placedObject in placedObjectBoundingBoxes)
            {
                EnsureObjectGroupsExist(statics, objectGroupIndex);
                var gameObject = m_ParentForeground.transform.GetChild(placedObject.PrefabIndex + objectGroupIndex * statics.ForegroundPrefabs.Length).gameObject;

                gameObject.transform.localRotation = placedObject.Rotation;

                gameObject.transform.localScale =
                    Vector3.one * placedObject.Scale;
                gameObject.transform.localPosition = placedObject.Position;

                ObjectPlacementUtilities.SetMeshRenderersEnabledRecursive(gameObject, true);

                if (placedObject.PrefabIndex == statics.ForegroundPrefabs.Length - 1)
                {
                    objectGroupIndex++;
                }
            }
        }

        objectBounds.Dispose();

        return(placedObjectBoundingBoxes);
    }
Exemple #21
0
    void Start()
    {
        m_ResourceDirectoriesEntity = World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntity(typeof(ResourceDirectories));
        World.DefaultGameObjectInjectionWorld.EntityManager.SetComponentData(m_ResourceDirectoriesEntity, new ResourceDirectories
        {
            ForegroundResourcePath = ForegroundObjectResourcesDirectory,
            BackgroundResourcePath = BackgroundObjectResourcesDirectory
        });
        var foregroundObjects = Resources.LoadAll <GameObject>(ForegroundObjectResourcesDirectory);
        var backgroundObjects = Resources.LoadAll <GameObject>(BackgroundObjectResourcesDirectory);
        var backgroundImages  = Resources.LoadAll <Texture2D>(BackgroundImageResourcesDirectory);

        if (foregroundObjects.Length == 0)
        {
            Debug.LogError($"No Prefabs of FBX files found in foreground object directory \"{ForegroundObjectResourcesDirectory}\".");
            return;
        }
        if (backgroundObjects.Length == 0)
        {
            Debug.LogError($"No Prefabs of FBX files found in background object directory \"{BackgroundObjectResourcesDirectory}\".");
            return;
        }
        //TODO: Fill in CurriculumState from app params
        if (TryGetAppParamPathFromCommandLine(out string appParamPath))
        {
            var AppParamsJson = File.ReadAllText(appParamPath);
            AppParameters = JsonUtility.FromJson <AppParams>(AppParamsJson);
        }
        else if (!String.IsNullOrEmpty(Configuration.Instance.SimulationConfig.app_param_uri))
        {
            AppParameters = Configuration.Instance.GetAppParams <AppParams>();
        }

        Debug.Log($"{nameof(ProjectInitialization)}: Starting up. MaxFrames: {AppParameters.MaxFrames}, " +
                  $"scale factors {{{string.Join(", ", AppParameters.ScaleFactors)}}}");

        m_PlacementStatics = new PlacementStatics(
            AppParameters.MaxFrames,
            AppParameters.MaxForegroundObjectsPerFrame,
            AppParameters.ScalingMin,
            AppParameters.ScalingSize,
            AppParameters.OccludingHueMaxOffset,
            foregroundObjects,
            backgroundObjects,
            backgroundImages,
            ObjectPlacementUtilities.GenerateInPlaneRotationCurriculum(Allocator.Persistent),
            ObjectPlacementUtilities.GenerateOutOfPlaneRotationCurriculum(Allocator.Persistent),
            new NativeArray <float>(AppParameters.ScaleFactors, Allocator.Persistent));
        var appParamsMetricDefinition = SimulationManager.RegisterMetricDefinition(
            "app-params", description: "The values from the app-params used in the simulation. Only triggered once per simulation.", id: k_AppParamsMetricGuid);

        SimulationManager.ReportMetric(appParamsMetricDefinition, new[] { AppParameters });
        m_CurriculumStateEntity = World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntity();
        World.DefaultGameObjectInjectionWorld.EntityManager.AddComponentData(
            m_CurriculumStateEntity, new CurriculumState());
        World.DefaultGameObjectInjectionWorld.EntityManager.AddComponentObject(
            m_CurriculumStateEntity, m_PlacementStatics);

        ValidateForegroundLabeling(foregroundObjects, PerceptionCamera);

#if !UNITY_EDITOR
        if (Debug.isDebugBuild && EnableProfileLog)
        {
            Debug.Log($"Enabling profile capture");
            m_ProfileLogPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "profileLog.raw");
            if (System.IO.File.Exists(m_ProfileLogPath))
            {
                System.IO.File.Delete(m_ProfileLogPath);
            }

            UnityEngine.Profiling.Profiler.logFile         = m_ProfileLogPath;
            UnityEngine.Profiling.Profiler.enabled         = true;
            UnityEngine.Profiling.Profiler.enableBinaryLog = true;
        }
#endif
        Manager.Instance.ShutdownNotification += CleanupState;

        //PerceptionCamera.renderedObjectInfosCalculated += OnRenderedObjectInfosCalculated;
    }