public static ChiselRenderObjects Create(string name, Transform parent, GameObjectState state, LayerUsageFlags query) { var renderContainer = ChiselObjectUtility.CreateGameObject(name, parent, state); var sharedMesh = new Mesh { name = name }; #if UNITY_EDITOR var partialMesh = new Mesh { name = name }; partialMesh.hideFlags = HideFlags.DontSave; #endif var meshFilter = renderContainer.AddComponent <MeshFilter>(); var meshRenderer = renderContainer.AddComponent <MeshRenderer>(); meshRenderer.enabled = false; var renderObjects = new ChiselRenderObjects { query = query, container = renderContainer, meshFilter = meshFilter, meshRenderer = meshRenderer, sharedMesh = sharedMesh, #if UNITY_EDITOR partialMesh = partialMesh, #endif renderMaterials = new Material[0] }; renderObjects.Initialize(); return(renderObjects); }
void UpdateSettings(ChiselModel model, GameObjectState state, bool meshIsModified) { #if UNITY_EDITOR Profiler.BeginSample("CheckIfFullMeshNeedsToBeHidden"); // If we need to render partial meshes (where some brushes are hidden) then we should show the full mesh ChiselGeneratedComponentManager.CheckIfFullMeshNeedsToBeHidden(model, this); Profiler.EndSample(); if (meshIsModified) { // Setting the sharedMesh to ensure the meshFilter knows it needs to be updated Profiler.BeginSample("OverrideMesh"); meshFilter.sharedMesh = meshFilter.sharedMesh; Profiler.EndSample(); Profiler.BeginSample("SetDirty"); UnityEditor.EditorUtility.SetDirty(meshFilter); UnityEditor.EditorUtility.SetDirty(model); Profiler.EndSample(); Profiler.BeginSample("SetHasLightmapUVs"); ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false); Profiler.EndSample(); Profiler.BeginSample("ClearLightmapData"); ChiselGeneratedComponentManager.ClearLightmapData(state, this); Profiler.EndSample(); } #endif }
const HideFlags kComponentHideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable; // Avoids MeshCollider showing wireframe internal static void UpdateContainerFlags(GameObject gameObject, GameObjectState state) { var transform = gameObject.transform; if (gameObject.layer != state.layer) { gameObject.layer = state.layer; } if (gameObject.hideFlags != kGameObjectHideFlags) { gameObject.hideFlags = kGameObjectHideFlags; } if (transform.hideFlags != kTransformHideFlags) { transform.hideFlags = kTransformHideFlags; } #if UNITY_EDITOR var prevStaticFlags = UnityEditor.GameObjectUtility.GetStaticEditorFlags(gameObject); if (prevStaticFlags != state.staticFlags) { UnityEditor.GameObjectUtility.SetStaticEditorFlags(gameObject, state.staticFlags); } #endif }
static readonly List <GeneratedMeshContents> __foundContents = new List <GeneratedMeshContents>(); // static to avoid allocations public void Update(ChiselModel model, GameObjectState state, GeneratedMeshDescription[] meshDescriptions, int startIndex, int endIndex) { bool meshIsModified = false; // Retrieve the generatedMeshes and its materials, combine them into a single Unity Mesh/Material array try { for (int i = startIndex; i < endIndex; i++) { ref var meshDescription = ref meshDescriptions[i]; var generatedMeshContents = model.Node.GetGeneratedMesh(meshDescription); if (generatedMeshContents == null) { continue; } if (generatedMeshContents.indices.Length == 0) { generatedMeshContents.Dispose(); continue; } var renderMaterial = ChiselBrushMaterialManager.GetRenderMaterialByInstanceID(meshDescription.surfaceParameter); __foundContents.Add(generatedMeshContents); __foundMaterials.Add(renderMaterial); } triangleBrushes.Clear(); if (__foundContents.Count == 0) { if (sharedMesh.vertexCount > 0) { sharedMesh.Clear(keepVertexLayout: true); } } else { sharedMesh.CopyFrom(__foundContents, triangleBrushes); #if UNITY_EDITOR ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false); #endif } if (renderMaterials != null && renderMaterials.Length == __foundMaterials.Count) { __foundMaterials.CopyTo(renderMaterials); } else { renderMaterials = __foundMaterials.ToArray(); } if (meshFilter.sharedMesh != sharedMesh) { meshFilter.sharedMesh = sharedMesh; meshIsModified = true; } meshRenderer.sharedMaterials = renderMaterials; meshRenderer.enabled = sharedMesh.vertexCount > 0; }
void UpdateSettings(ChiselModel model, GameObjectState state, bool meshIsModified) { #if UNITY_EDITOR // If we need to render partial meshes (where some brushes are hidden) then we should show the full mesh ChiselGeneratedComponentManager.CheckIfFullMeshNeedsToBeHidden(model, this); if (meshIsModified) { ChiselGeneratedComponentManager.ClearLightmapData(state, this); } #endif }
internal static void UpdateContainerFlags(Component component, GameObjectState modelState) { var gameObject = component.gameObject; UpdateContainerFlags(gameObject, modelState); if (component.hideFlags != kComponentHideFlags) { component.hideFlags = kComponentHideFlags; } }
public static void ClearLightmapData(GameObjectState state, ChiselRenderObjects renderable) { var lightmapStatic = (state.staticFlags & UnityEditor.StaticEditorFlags.ContributeGI) == UnityEditor.StaticEditorFlags.ContributeGI; if (lightmapStatic) { renderable.meshRenderer.realtimeLightmapIndex = -1; renderable.meshRenderer.lightmapIndex = -1; renderable.uvLightmapUpdateTime = Time.realtimeSinceStartup; haveUVsToUpdate = true; } }
public static ChiselModelGeneratedObjects Create(ChiselModel model) { // Make sure there's not a dangling container out there from a previous version var existingContainer = model.FindChildByName(kGeneratedContainerName); ChiselObjectUtility.SafeDestroy(existingContainer, ignoreHierarchyEvents: true); var modelState = GameObjectState.Create(model); var parent = model.transform; var container = ChiselObjectUtility.CreateGameObject(kGeneratedContainerName, parent, modelState); var containerTransform = container.transform; var colliderContainer = ChiselObjectUtility.CreateGameObject(kGeneratedMeshColliderName, containerTransform, modelState); Debug.Assert((int)LayerUsageFlags.Renderable == 1); Debug.Assert((int)LayerUsageFlags.CastShadows == 2); Debug.Assert((int)LayerUsageFlags.ReceiveShadows == 4); Debug.Assert((int)LayerUsageFlags.RenderReceiveCastShadows == (1 | 2 | 4)); var renderables = new ChiselRenderObjects[] { null,//ChiselRenderObjects Create(kGeneratedMeshRendererNames[0], containerTransform, modelState, LayerUsageFlags.None), ChiselRenderObjects.Create(kGeneratedMeshRendererNames[1], containerTransform, modelState, LayerUsageFlags.Renderable), ChiselRenderObjects.Create(kGeneratedMeshRendererNames[2], containerTransform, modelState, LayerUsageFlags.CastShadows), ChiselRenderObjects.Create(kGeneratedMeshRendererNames[3], containerTransform, modelState, LayerUsageFlags.Renderable | LayerUsageFlags.CastShadows), null, //ChiselRenderObjects.Create(kGeneratedMeshRendererNames[4], containerTransform, modelState, LayerUsageFlags.ReceiveShadows), ChiselRenderObjects.Create(kGeneratedMeshRendererNames[5], containerTransform, modelState, LayerUsageFlags.Renderable | LayerUsageFlags.ReceiveShadows), null, //ChiselRenderObjects.Create(kGeneratedMeshRendererNames[6], containerTransform, modelState, LayerUsageFlags.CastShadows | LayerUsageFlags.ReceiveShadows), ChiselRenderObjects.Create(kGeneratedMeshRendererNames[7], containerTransform, modelState, LayerUsageFlags.Renderable | LayerUsageFlags.CastShadows | LayerUsageFlags.ReceiveShadows), }; var meshRenderers = new MeshRenderer[] { renderables[1].meshRenderer, renderables[2].meshRenderer, renderables[3].meshRenderer, renderables[5].meshRenderer, renderables[7].meshRenderer }; return(new ChiselModelGeneratedObjects { generatedDataContainer = container, colliderContainer = colliderContainer, colliders = new ChiselColliderObjects[0], renderables = renderables, meshRenderers = meshRenderers }); }
public void Clear(ChiselModel model, GameObjectState state) { bool meshIsModified = false; { Profiler.BeginSample("Clear"); triangleBrushes = Array.Empty <CompactNodeID>(); if (sharedMesh.vertexCount > 0) { meshIsModified = true; sharedMesh.Clear(keepVertexLayout: true); } Profiler.EndSample(); Profiler.BeginSample("SetSharedMesh"); if (meshFilter.sharedMesh != sharedMesh) { meshFilter.sharedMesh = sharedMesh; meshIsModified = true; } Profiler.EndSample(); Profiler.BeginSample("SetMaterialsIfModified"); renderMaterials = Array.Empty <Material>(); SetMaterialsIfModified(meshRenderer, renderMaterials); Profiler.EndSample(); Profiler.BeginSample("Enable"); var expectedEnabled = sharedMesh.vertexCount > 0; if (meshRenderer.enabled != expectedEnabled) { meshRenderer.enabled = expectedEnabled; } Profiler.EndSample(); } Profiler.BeginSample("UpdateSettings"); UpdateSettings(model, state, meshIsModified); Profiler.EndSample(); }
const HideFlags kComponentHideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable; // Avoids MeshCollider showing wireframe internal static void UpdateContainerFlags(GameObject gameObject, GameObjectState state, bool debugHelperRenderer = false, bool isRenderable = false) { var transform = gameObject.transform; var desiredGameObjectFlags = debugHelperRenderer ? kEditorGameObjectHideFlags : kGameObjectHideFlags; var desiredLayer = debugHelperRenderer ? 0 : state.layer; if (gameObject.layer != desiredLayer) { gameObject.layer = desiredLayer; } if (gameObject.hideFlags != desiredGameObjectFlags) { gameObject.hideFlags = desiredGameObjectFlags; } if (transform.hideFlags != kTransformHideFlags) { transform.hideFlags = kTransformHideFlags; } #if UNITY_EDITOR StaticEditorFlags desiredStaticFlags; if (debugHelperRenderer) { desiredStaticFlags = (StaticEditorFlags)0; } else { desiredStaticFlags = UnityEditor.GameObjectUtility.GetStaticEditorFlags(gameObject); } if (!isRenderable && desiredStaticFlags != (StaticEditorFlags)0) { desiredStaticFlags |= StaticEditorFlags.OccluderStatic; } if (desiredStaticFlags != state.staticFlags) { UnityEditor.GameObjectUtility.SetStaticEditorFlags(gameObject, desiredStaticFlags); } #endif }
public static GameObject CreateGameObject(string name, Transform parent, GameObjectState state, bool debugHelperRenderer = false) { var parentScene = parent.gameObject.scene; var oldActiveScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); if (parentScene != oldActiveScene) { UnityEngine.SceneManagement.SceneManager.SetActiveScene(parentScene); } try { ChiselNodeHierarchyManager.ignoreNextChildrenChanged = true; var newGameObject = new GameObject(name); newGameObject.SetActive(false); try { UpdateContainerFlags(newGameObject, state, debugHelperRenderer: debugHelperRenderer); var transform = newGameObject.GetComponent <Transform>(); ChiselNodeHierarchyManager.ignoreNextChildrenChanged = true; transform.SetParent(parent, false); ChiselNodeHierarchyManager.ignoreNextChildrenChanged = false; ResetTransform(transform); } finally { newGameObject.SetActive(true); } ChiselNodeHierarchyManager.ignoreNextChildrenChanged = false; return(newGameObject); } finally { if (parentScene != oldActiveScene) { UnityEngine.SceneManagement.SceneManager.SetActiveScene(oldActiveScene); } } }
public static ChiselRenderObjects Create(string name, Transform parent, GameObjectState state, LayerUsageFlags query, bool debugHelperRenderer = false) { var renderContainer = ChiselObjectUtility.CreateGameObject(name, parent, state, debugHelperRenderer: debugHelperRenderer); var meshFilter = renderContainer.AddComponent <MeshFilter>(); var meshRenderer = renderContainer.AddComponent <MeshRenderer>(); meshRenderer.enabled = false; var renderObjects = new ChiselRenderObjects { invalid = false, query = query, container = renderContainer, meshFilter = meshFilter, meshRenderer = meshRenderer, renderMaterials = new Material[0], debugHelperRenderer = debugHelperRenderer }; renderObjects.EnsureMeshesAllocated(); renderObjects.Initialize(); return(renderObjects); }
public static ChiselGeneratedObjects Create(GameObject parentGameObject) { var parentTransform = parentGameObject.transform; // Make sure there's not a dangling container out there from a previous version var existingContainer = parentTransform.FindChildByName(kGeneratedContainerName); ChiselObjectUtility.SafeDestroy(existingContainer, ignoreHierarchyEvents: true); var gameObjectState = GameObjectState.Create(parentGameObject); var container = ChiselObjectUtility.CreateGameObject(kGeneratedContainerName, parentTransform, gameObjectState); var containerTransform = container.transform; var colliderContainer = ChiselObjectUtility.CreateGameObject(kGeneratedMeshColliderName, containerTransform, gameObjectState); Debug.Assert((int)LayerUsageFlags.Renderable == 1); Debug.Assert((int)LayerUsageFlags.CastShadows == 2); Debug.Assert((int)LayerUsageFlags.ReceiveShadows == 4); Debug.Assert((int)LayerUsageFlags.RenderReceiveCastShadows == (1 | 2 | 4)); var renderables = new ChiselRenderObjects[] { new ChiselRenderObjects() { invalid = true }, ChiselRenderObjects.Create(kGeneratedMeshRendererNames[1], containerTransform, gameObjectState, LayerUsageFlags.Renderable), ChiselRenderObjects.Create(kGeneratedMeshRendererNames[2], containerTransform, gameObjectState, LayerUsageFlags.CastShadows), ChiselRenderObjects.Create(kGeneratedMeshRendererNames[3], containerTransform, gameObjectState, LayerUsageFlags.Renderable | LayerUsageFlags.CastShadows), new ChiselRenderObjects() { invalid = true }, ChiselRenderObjects.Create(kGeneratedMeshRendererNames[5], containerTransform, gameObjectState, LayerUsageFlags.Renderable | LayerUsageFlags.ReceiveShadows), new ChiselRenderObjects() { invalid = true }, ChiselRenderObjects.Create(kGeneratedMeshRendererNames[7], containerTransform, gameObjectState, LayerUsageFlags.Renderable | LayerUsageFlags.CastShadows | LayerUsageFlags.ReceiveShadows), }; var meshRenderers = new MeshRenderer[] { renderables[1].meshRenderer, renderables[2].meshRenderer, renderables[3].meshRenderer, renderables[5].meshRenderer, renderables[7].meshRenderer }; renderables[1].invalid = false; renderables[2].invalid = false; renderables[3].invalid = false; renderables[5].invalid = false; renderables[7].invalid = false; var debugHelpers = new ChiselRenderObjects[kDebugHelperCount]; var debugMeshRenderers = new MeshRenderer[kDebugHelperCount]; for (int i = 0; i < kDebugHelperCount; i++) { debugHelpers[i] = ChiselRenderObjects.Create(kGeneratedDebugRendererNames[i], containerTransform, gameObjectState, AssignMeshesJob.kGeneratedDebugRendererFlags[i].Item1, debugHelperRenderer: true); debugMeshRenderers[i] = debugHelpers[0].meshRenderer; debugHelpers[i].invalid = false; } var result = new ChiselGeneratedObjects { generatedDataContainer = container, colliderContainer = colliderContainer, colliders = new ChiselColliderObjects[0], renderables = renderables, meshRenderers = meshRenderers, debugHelpers = debugHelpers, debugMeshRenderers = debugMeshRenderers }; Debug.Assert(IsValid(result)); return(result); }
// in between UpdateMeshes and FinishMeshUpdates our jobs should be force completed, so we can now upload our meshes to unity Meshes public int FinishMeshUpdates(ChiselModel model, GameObject parentGameObject, Mesh.MeshDataArray meshDataArray, ref VertexBufferContents vertexBufferContents, NativeList <ChiselMeshUpdate> colliderMeshUpdates, NativeList <ChiselMeshUpdate> debugHelperMeshes, NativeList <ChiselMeshUpdate> renderMeshes, JobHandle dependencies) { gameObjectStates.Clear(); colliderObjectUpdates.Clear(); renderMeshUpdates.Clear(); renderObjectUpdates.Clear(); colliderObjects.Clear(); foundMeshes.Clear(); GameObjectState gameObjectState; { Profiler.BeginSample("Setup"); var parentTransform = parentGameObject.transform; gameObjectState = GameObjectState.Create(parentGameObject); ChiselObjectUtility.UpdateContainerFlags(generatedDataContainer, gameObjectState); var containerTransform = generatedDataContainer.transform; var colliderTransform = colliderContainer.transform; // Make sure we're always a child of the model ChiselObjectUtility.ResetTransform(containerTransform, requiredParent: parentTransform); ChiselObjectUtility.ResetTransform(colliderTransform, requiredParent: containerTransform); ChiselObjectUtility.UpdateContainerFlags(colliderContainer, gameObjectState); for (int i = 0; i < renderables.Length; i++) { if (renderables[i] == null || renderables[i].invalid) { continue; } bool isRenderable = (renderables[i].query & LayerUsageFlags.Renderable) == LayerUsageFlags.Renderable; var renderableContainer = renderables[i].container; ChiselObjectUtility.UpdateContainerFlags(renderableContainer, gameObjectState, isRenderable: isRenderable); ChiselObjectUtility.ResetTransform(renderableContainer.transform, requiredParent: containerTransform); } for (int i = 0; i < debugHelpers.Length; i++) { if (debugHelpers[i] == null || debugHelpers[i].invalid) { continue; } var renderableContainer = debugHelpers[i].container; ChiselObjectUtility.UpdateContainerFlags(renderableContainer, gameObjectState, isRenderable: true, debugHelperRenderer: true); ChiselObjectUtility.ResetTransform(renderableContainer.transform, requiredParent: containerTransform); } gameObjectStates.Add(model, gameObjectState); Profiler.EndSample(); } Debug.Assert(LayerParameterIndex.LayerParameter1 < LayerParameterIndex.LayerParameter2); Debug.Assert((LayerParameterIndex.LayerParameter1 + 1) == LayerParameterIndex.LayerParameter2); dependencies.Complete(); Debug.Assert(!vertexBufferContents.meshDescriptions.IsCreated || vertexBufferContents.meshDescriptions.Length == 0 || vertexBufferContents.meshDescriptions[0].meshQuery.LayerParameterIndex >= LayerParameterIndex.None); Profiler.BeginSample("Init"); var colliderCount = colliderMeshUpdates.Length; if (colliderObjects.Capacity < colliderCount) { colliderObjects.Capacity = colliderCount; } for (int i = 0; i < colliderCount; i++) { colliderObjects.Add(null); } for (int i = 0; i < debugHelperMeshes.Length; i++) { renderMeshUpdates.Add(debugHelperMeshes[i]); } for (int i = 0; i < renderMeshes.Length; i++) { renderMeshUpdates.Add(renderMeshes[i]); } renderMeshUpdates.Sort(delegate(ChiselMeshUpdate x, ChiselMeshUpdate y) { return(x.contentsIndex - y.contentsIndex); }); Profiler.EndSample(); // Now do all kinds of book-keeping code that we might as well do while our jobs are running on other threads Profiler.BeginSample("new_ChiselDebugObjectUpdate"); usedDebugHelpers.Clear(); for (int i = 0; i < debugHelperMeshes.Length; i++) { var debugHelperMeshUpdate = debugHelperMeshes[i]; usedDebugHelpers.Add(debugHelperMeshUpdate.objectIndex); var instance = debugHelpers[debugHelperMeshUpdate.objectIndex]; foundMeshes.Add(instance.sharedMesh); renderObjectUpdates.Add(new ChiselRenderObjectUpdate { meshIndex = debugHelperMeshUpdate.meshIndex, materialOverride = ChiselMaterialManager.HelperMaterials[debugHelperMeshUpdate.objectIndex], instance = instance, model = model }); } Profiler.EndSample(); Profiler.BeginSample("new_ChiselRenderObjectUpdate"); usedRenderMeshes.Clear(); for (int i = 0; i < renderMeshes.Length; i++) { var renderMeshUpdate = renderMeshes[i]; usedRenderMeshes.Add(renderMeshUpdate.objectIndex); var instance = renderables[renderMeshUpdate.objectIndex]; foundMeshes.Add(instance.sharedMesh); renderObjectUpdates.Add(new ChiselRenderObjectUpdate { meshIndex = renderMeshUpdate.meshIndex, materialOverride = null, instance = instance, model = model }); } Profiler.EndSample(); Profiler.BeginSample("new_ChiselPhysicsObjectUpdate"); for (int i = 0; i < colliderMeshUpdates.Length; i++) { var colliderMeshUpdate = colliderMeshUpdates[i]; var surfaceParameter = colliderMeshUpdate.objectIndex; var colliderIndex = colliderMeshUpdate.colliderIndex; // TODO: optimize for (int j = 0; j < colliders.Length; j++) { if (colliders[j] == null) { continue; } if (colliders[j].surfaceParameter != surfaceParameter) { continue; } colliderObjects[colliderIndex] = colliders[j]; colliders[j] = null; break; } Profiler.BeginSample("Create.Colliders"); if (colliderObjects[colliderIndex] == null) { colliderObjects[colliderIndex] = ChiselColliderObjects.Create(colliderContainer, surfaceParameter); } Profiler.EndSample(); var instance = colliderObjects[colliderIndex]; foundMeshes.Add(instance.sharedMesh); colliderObjectUpdates.Add(new ChiselColliderObjectUpdate { meshIndex = colliderMeshUpdate.meshIndex }); } Profiler.EndSample(); Profiler.BeginSample("Renderers.UpdateMaterials"); ChiselRenderObjects.UpdateMaterials(renderMeshUpdates, renderObjectUpdates, ref vertexBufferContents); Profiler.EndSample(); Profiler.BeginSample("CleanUp.Colliders"); for (int j = 0; j < colliders.Length; j++) { if (colliders[j] != null) { colliders[j].Destroy(); } } Profiler.EndSample(); Profiler.BeginSample("Assign.Colliders"); if (colliders.Length != colliderCount) { colliders = new ChiselColliderObjects[colliderCount]; } for (int i = 0; i < colliderCount; i++) { colliders[i] = colliderObjects[i]; } Profiler.EndSample(); Profiler.BeginSample("Renderers.Update"); ChiselRenderObjects.UpdateSettings(renderMeshUpdates, renderObjectUpdates, gameObjectStates, ref vertexBufferContents); Profiler.EndSample(); Debug.Assert(foundMeshes.Count <= meshDataArray.Length); var realMeshDataArraySize = meshDataArray.Length; { // This is a hack to ensure foundMeshes is the same exact length as meshDataArray // (All these need to be set to empty anyway) // TODO: figure out why the maximum meshDataArray.Length does not match the maximum used meshes? int meshDataArrayOffset = foundMeshes.Count; for (int i = 0; i < renderables.Length; i++) { if (usedRenderMeshes.Contains(i)) { continue; } var instance = renderables[i]; if (instance.meshRenderer && instance.meshRenderer.enabled) { instance.meshRenderer.enabled = false; } if (foundMeshes.Count < meshDataArray.Length) { var sharedMesh = instance.sharedMesh; if (!sharedMesh || foundMeshes.Contains(sharedMesh)) { continue; } foundMeshes.Add(sharedMesh); meshDataArray[meshDataArrayOffset].SetIndexBufferParams(0, IndexFormat.UInt32); meshDataArray[meshDataArrayOffset].SetVertexBufferParams(0, VertexBufferContents.s_RenderDescriptors); meshDataArrayOffset++; } } for (int i = 0; i < debugHelpers.Length; i++) { if (usedDebugHelpers.Contains(i)) { continue; } var instance = debugHelpers[i]; if (instance.meshRenderer && instance.meshRenderer.enabled) { instance.meshRenderer.enabled = false; } if (foundMeshes.Count < meshDataArray.Length) { var sharedMesh = instance.sharedMesh; if (!sharedMesh || foundMeshes.Contains(sharedMesh)) { continue; } foundMeshes.Add(sharedMesh); meshDataArray[meshDataArrayOffset].SetIndexBufferParams(0, IndexFormat.UInt32); meshDataArray[meshDataArrayOffset].SetVertexBufferParams(0, VertexBufferContents.s_RenderDescriptors); meshDataArrayOffset++; } } } Profiler.BeginSample("UpdateMeshRenderers"); ChiselRenderObjects.UpdateProperties(model, this.meshRenderers); Profiler.EndSample(); // Updates the Unity Mesh-es that are used in our MeshRenderers and MeshColliders // MeshUpdateFlags => Bounds are never updated no matter what flag you use Profiler.BeginSample("ApplyAndDisposeWritableMeshData"); Mesh.ApplyAndDisposeWritableMeshData(meshDataArray, foundMeshes, UnityEngine.Rendering.MeshUpdateFlags.DontRecalculateBounds); Profiler.EndSample(); // TODO: user meshDataArray data to determine if colliders are visible or not, then we can move this before the Apply Profiler.BeginSample("UpdateColliders"); ChiselColliderObjects.UpdateProperties(model, this.colliders); Profiler.EndSample(); // So we need to update the bounds ourselves Profiler.BeginSample("Mesh.UpdateBounds"); ChiselRenderObjects.UpdateBounds(renderObjectUpdates); // TODO: user meshDataArray data to determine the bounds and set it directly for (int i = 0; i < colliders.Length; i++) { colliders[i].sharedMesh.RecalculateBounds(); } Profiler.EndSample(); Profiler.BeginSample("Schedule Collider bake"); ChiselColliderObjects.ScheduleColliderBake(model, this.colliders); Profiler.EndSample(); this.needVisibilityMeshUpdate = true; gameObjectStates.Clear(); renderMeshUpdates.Clear(); renderObjectUpdates.Clear(); colliderObjects.Clear(); var foundMeshCount = foundMeshes.Count; foundMeshes.Clear(); return(foundMeshCount); }
public void Update(ChiselModel model, GeneratedMeshDescription[] meshDescriptions) { var modelState = GameObjectState.Create(model); ChiselObjectUtility.UpdateContainerFlags(generatedDataContainer, modelState); var modelTransform = model.transform; var containerTransform = generatedDataContainer.transform; var colliderTransform = colliderContainer.transform; // Make sure we're always a child of the model ChiselObjectUtility.ResetTransform(containerTransform, requiredParent: modelTransform); ChiselObjectUtility.ResetTransform(colliderTransform, requiredParent: containerTransform); ChiselObjectUtility.UpdateContainerFlags(colliderContainer, modelState); for (int i = 0; i < renderables.Length; i++) { if (renderables[i] == null) { continue; } var renderableContainer = renderables[i].container; ChiselObjectUtility.UpdateContainerFlags(renderableContainer, modelState); ChiselObjectUtility.ResetTransform(renderableContainer.transform, requiredParent: containerTransform); } Debug.Assert(LayerParameterIndex.LayerParameter1 < LayerParameterIndex.LayerParameter2); Debug.Assert((LayerParameterIndex.LayerParameter1 + 1) == LayerParameterIndex.LayerParameter2); Debug.Assert(meshDescriptions[0].meshQuery.LayerParameterIndex >= LayerParameterIndex.LayerParameter1); int descriptionIndex = 0; ChiselRenderObjects.UpdateProperties(model, meshRenderers); ChiselColliderObjects.UpdateColliders(model, colliders); renderMaterials.Clear(); // Loop through all meshDescriptions with LayerParameter1, and create renderable meshes from them if (meshDescriptions[0].meshQuery.LayerParameterIndex == LayerParameterIndex.LayerParameter1) { var prevQuery = meshDescriptions[0].meshQuery; var startIndex = 0; for (; descriptionIndex < meshDescriptions.Length; descriptionIndex++) { ref var meshDescriptionIterator = ref meshDescriptions[descriptionIndex]; // Exit when layerParameterIndex is no longer LayerParameter1 if (meshDescriptionIterator.meshQuery.LayerParameterIndex != LayerParameterIndex.LayerParameter1) { break; } var currQuery = meshDescriptionIterator.meshQuery; if (prevQuery == currQuery) { continue; } prevQuery = currQuery; var renderIndex = (int)(prevQuery.LayerQueryMask & LayerUsageFlags.RenderReceiveCastShadows); // Group by all meshDescriptions with same query renderables[renderIndex].Update(model, modelState, meshDescriptions, startIndex, descriptionIndex); renderMaterials.AddRange(renderables[renderIndex].renderMaterials); startIndex = descriptionIndex; } { var renderIndex = (int)(prevQuery.LayerQueryMask & LayerUsageFlags.RenderReceiveCastShadows); // Group by all meshDescriptions with same query renderables[renderIndex].Update(model, modelState, meshDescriptions, startIndex, descriptionIndex); renderMaterials.AddRange(renderables[renderIndex].renderMaterials); } }
// in between UpdateMeshes and FinishMeshUpdates our jobs should be force completed, so we can now upload our meshes to unity Meshes public int FinishMeshUpdates(ChiselModel model, GameObject parentGameObject, List <Mesh.MeshDataArray> meshDataArrays, ref VertexBufferContents vertexBufferContents, NativeList <ChiselMeshUpdate> colliderMeshUpdates, NativeList <ChiselMeshUpdate> debugHelperMeshes, NativeList <ChiselMeshUpdate> renderMeshes, JobHandle dependencies) { gameObjectStates.Clear(); colliderObjectUpdates.Clear(); renderMeshUpdates.Clear(); renderObjectUpdates.Clear(); colliderObjects.Clear(); foundMeshes.Clear(); GameObjectState gameObjectState; { Profiler.BeginSample("Setup"); var parentTransform = parentGameObject.transform; gameObjectState = GameObjectState.Create(parentGameObject); ChiselObjectUtility.UpdateContainerFlags(generatedDataContainer, gameObjectState); var containerTransform = generatedDataContainer.transform; var colliderTransform = colliderContainer.transform; // Make sure we're always a child of the model ChiselObjectUtility.ResetTransform(containerTransform, requiredParent: parentTransform); ChiselObjectUtility.ResetTransform(colliderTransform, requiredParent: containerTransform); ChiselObjectUtility.UpdateContainerFlags(colliderContainer, gameObjectState); for (int i = 0; i < renderables.Length; i++) { if (renderables[i] == null || renderables[i].invalid) { continue; } bool isRenderable = (renderables[i].query & LayerUsageFlags.Renderable) == LayerUsageFlags.Renderable; var renderableContainer = renderables[i].container; ChiselObjectUtility.UpdateContainerFlags(renderableContainer, gameObjectState, isRenderable: isRenderable); ChiselObjectUtility.ResetTransform(renderableContainer.transform, requiredParent: containerTransform); } for (int i = 0; i < debugHelpers.Length; i++) { if (debugHelpers[i] == null || debugHelpers[i].invalid) { continue; } var renderableContainer = debugHelpers[i].container; ChiselObjectUtility.UpdateContainerFlags(renderableContainer, gameObjectState, isRenderable: true, debugHelperRenderer: true); ChiselObjectUtility.ResetTransform(renderableContainer.transform, requiredParent: containerTransform); } gameObjectStates.Add(model, gameObjectState); Profiler.EndSample(); } Debug.Assert(LayerParameterIndex.LayerParameter1 < LayerParameterIndex.LayerParameter2); Debug.Assert((LayerParameterIndex.LayerParameter1 + 1) == LayerParameterIndex.LayerParameter2); dependencies.Complete(); Debug.Assert(!vertexBufferContents.meshDescriptions.IsCreated || vertexBufferContents.meshDescriptions.Length == 0 || vertexBufferContents.meshDescriptions[0].meshQuery.LayerParameterIndex >= LayerParameterIndex.None); Profiler.BeginSample("Init"); var colliderCount = colliderMeshUpdates.Length; if (colliderObjects.Capacity < colliderCount) { colliderObjects.Capacity = colliderCount; } for (int i = 0; i < colliderCount; i++) { colliderObjects.Add(null); } for (int i = 0; i < renderMeshes.Length; i++) { renderMeshUpdates.Add(renderMeshes[i]); } for (int i = 0; i < debugHelperMeshes.Length; i++) { renderMeshUpdates.Add(debugHelperMeshes[i]); } renderMeshUpdates.Sort(delegate(ChiselMeshUpdate x, ChiselMeshUpdate y) { return(x.contentsIndex - y.contentsIndex); }); Profiler.EndSample(); // Now do all kinds of book-keeping code that we might as well do while our jobs are running on other threads Profiler.BeginSample("new ChiselRenderObjectUpdate"); for (int i = 0; i < debugHelperMeshes.Length; i++) { var debugHelperMeshUpdate = debugHelperMeshes[i]; var instance = debugHelpers[debugHelperMeshUpdate.objectIndex]; foundMeshes.Add(instance.sharedMesh); renderObjectUpdates.Add(new ChiselRenderObjectUpdate { meshIndex = debugHelperMeshUpdate.meshIndex, meshDataArray = meshDataArrays[debugHelperMeshUpdate.meshIndex], materialOverride = ChiselMaterialManager.HelperMaterials[debugHelperMeshUpdate.objectIndex], instance = instance, model = model }); } Profiler.EndSample(); Profiler.BeginSample("new ChiselRenderObjectUpdate"); for (int i = 0; i < renderMeshes.Length; i++) { var renderMeshUpdate = renderMeshes[i]; var instance = renderables[renderMeshUpdate.objectIndex]; foundMeshes.Add(instance.sharedMesh); renderObjectUpdates.Add(new ChiselRenderObjectUpdate { meshIndex = renderMeshUpdate.meshIndex, meshDataArray = meshDataArrays[renderMeshUpdate.meshIndex], materialOverride = null, instance = instance, model = model }); } Profiler.EndSample(); Profiler.BeginSample("new ChiselPhysicsObjectUpdate"); for (int i = 0; i < colliderMeshUpdates.Length; i++) { var colliderMeshUpdate = colliderMeshUpdates[i]; var surfaceParameter = colliderMeshUpdate.objectIndex; var colliderIndex = colliderMeshUpdate.contentsIndex; // TODO: optimize for (int j = 0; j < colliders.Length; j++) { if (colliders[j] == null) { continue; } if (colliders[j].surfaceParameter != surfaceParameter) { continue; } colliderObjects[colliderIndex] = colliders[j]; colliders[j] = null; break; } Profiler.BeginSample("Create.Colliders"); if (colliderObjects[colliderIndex] == null) { colliderObjects[colliderIndex] = ChiselColliderObjects.Create(colliderContainer, surfaceParameter); } Profiler.EndSample(); var instance = colliderObjects[colliderIndex]; foundMeshes.Add(instance.sharedMesh); colliderObjectUpdates.Add(new ChiselColliderObjectUpdate { meshIndex = colliderMeshUpdate.meshIndex, meshDataArray = meshDataArrays[colliderMeshUpdate.meshIndex], }); } Profiler.EndSample(); Profiler.BeginSample("Renderers.UpdateMaterials"); ChiselRenderObjects.UpdateMaterials(renderMeshUpdates, renderObjectUpdates, ref vertexBufferContents); Profiler.EndSample(); Profiler.BeginSample("CleanUp.Colliders"); for (int j = 0; j < colliders.Length; j++) { if (colliders[j] != null) { colliders[j].Destroy(); } } Profiler.EndSample(); Profiler.BeginSample("Assign.Colliders"); if (colliders.Length != colliderCount) { colliders = new ChiselColliderObjects[colliderCount]; } for (int i = 0; i < colliderCount; i++) { colliders[i] = colliderObjects[i]; } Profiler.EndSample(); Profiler.BeginSample("Renderers.Update"); ChiselRenderObjects.UpdateSettings(this.renderMeshUpdates, this.renderObjectUpdates, this.gameObjectStates, ref vertexBufferContents); Profiler.EndSample(); Profiler.BeginSample("ApplyAndDisposeWritableMeshData"); for (int i = 0; i < this.renderObjectUpdates.Count; i++) { var update = this.renderObjectUpdates[i]; var meshIndex = update.meshIndex; if (update.meshDataArray.Length > 0) { Mesh.ApplyAndDisposeWritableMeshData(update.meshDataArray, foundMeshes[meshIndex], UnityEngine.Rendering.MeshUpdateFlags.DontRecalculateBounds); } update.meshDataArray = default; this.renderObjectUpdates[i] = update; } for (int i = 0; i < this.colliderObjectUpdates.Count; i++) { var update = this.colliderObjectUpdates[i]; var meshIndex = update.meshIndex; if (update.meshDataArray.Length > 0) { Mesh.ApplyAndDisposeWritableMeshData(update.meshDataArray, foundMeshes[meshIndex], UnityEngine.Rendering.MeshUpdateFlags.DontRecalculateBounds); } update.meshDataArray = default; this.colliderObjectUpdates[i] = update; } Profiler.EndSample(); Profiler.BeginSample("UpdateProperties"); ChiselRenderObjects.UpdateProperties(model, this.meshRenderers); Profiler.EndSample(); Profiler.BeginSample("UpdateColliders"); ChiselColliderObjects.UpdateProperties(model, this.colliders); Profiler.EndSample(); this.needVisibilityMeshUpdate = true; this.gameObjectStates.Clear(); this.renderMeshUpdates.Clear(); this.renderObjectUpdates.Clear(); this.colliderObjects.Clear(); var foundMeshCount = foundMeshes.Count; foundMeshes.Clear(); return(foundMeshCount); }