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