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);
        }
Beispiel #2
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);
    }
Beispiel #3
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();
    }