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; } } }
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) }); }
// 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; } }