/// <summary> /// Updades all subscription info for given subscription row. /// This method is needed because 'RenderPassSubscription" is a struct and values are changed by host object. /// </summary> /// <param name="newSubscriptionInfo">The subscription information passed by host object.</param> /// <param name="layerViewSubset">The host object.</param> internal void UpdateSubscription(RenderPassSubscription newSubscriptionInfo, ViewRelatedSceneLayerSubset layerViewSubset) { // Get the subscription list // (may be null if object was removed from the layer) List <RenderPassSubscription> subscriptionList = m_viewRelatedSubscriptions[layerViewSubset.ViewIndex]; if (subscriptionList == null) { return; } // Update the corresponding subscription entry int subscriptionCount = subscriptionList.Count; int entryCount = 0; for (int loop = 0; loop < subscriptionCount; loop++) { RenderPassSubscription currentSubscriptionInfo = subscriptionList[loop]; if ((currentSubscriptionInfo.SceneObject == newSubscriptionInfo.SceneObject) && (currentSubscriptionInfo.RenderPass == newSubscriptionInfo.RenderPass) && (currentSubscriptionInfo.RenderMethod == newSubscriptionInfo.RenderMethod)) { subscriptionList[loop] = newSubscriptionInfo; entryCount++; } } if (entryCount > 1) { throw new SeeingSharpGraphicsException("Inconsistency: Too much subscriptions for SceneObject detected!"); } }
/// <summary> /// Clears all subscriptions on the given view subset. /// Only for internal use.. this method gets called when a view is deregistered. /// </summary> internal void ClearSubscriptionsWithoutUnsubscribeCall(ViewRelatedSceneLayerSubset layerViewSubset, RenderPassSubscription subscription) { // Get the subscription list // (may be null if object was removed from the layer) List <RenderPassSubscription> subscriptionList = m_viewRelatedSubscriptions[layerViewSubset.ViewIndex]; if (subscriptionList == null) { return; } // Remove the given entry from subscription list int subscriptionCount = subscriptionList.Count; int entryCount = 0; for (int loop = 0; loop < subscriptionCount; loop++) { RenderPassSubscription currentSubscriptionInfo = subscriptionList[loop]; if ((currentSubscriptionInfo.SceneObject == subscription.SceneObject) && (currentSubscriptionInfo.RenderPass == subscription.RenderPass) && (currentSubscriptionInfo.RenderMethod == subscription.RenderMethod)) { subscriptionList.RemoveAt(loop); loop--; subscriptionCount--; entryCount++; } } if (entryCount > 1) { throw new SeeingSharpGraphicsException("Inconsistency: Too much subscriptions for SceneObject detected!"); } }
/// <summary> /// Unsubscribes the given object from the given render pass. /// </summary> internal void UnsubscribeForPass(RenderPassSubscription subscription) { if (!m_isSubscribeUnsubscribeAllowed) { throw new SeeingSharpException("Subscription is not allowed currently!"); } if (subscription.IsSubscribed) { // Set unsubscribed flag m_anythingUnsubscribed = true; // Register unsubscription call var subscriptionInfo = m_objectsPerPassDict[subscription.RenderPass]; subscriptionInfo.UnsubscribeCallCount++; // Update subscription info and reinsert it on the pass collection subscription.IsSubscribed = false; subscriptionInfo.Subscriptions[subscription.SubscriptionIndex] = subscription; // Post changes to the scene object holding this info too subscription.SceneObject.UpdateSubscription(subscription, this); } }
/// <summary> /// Rendering logic for lines renderings. /// </summary> private void RenderPass( RenderPassBase renderPass, PassSubscribionProperties subscriptions, RenderState renderState, ref List <SceneObject> invalidObjects) { if (subscriptions.Subscriptions.Count > 0) { if (renderPass != null) { //Ensure loaded resources for transparency pass if (!renderPass.IsLoaded) { renderPass.LoadResource(); } //Render all subscriptions renderPass.Apply(renderState); } try { int subscriptionCount = subscriptions.Subscriptions.Count; for (int loopPass = 0; loopPass < subscriptionCount; loopPass++) { RenderPassSubscription actSubscription = subscriptions.Subscriptions[loopPass]; try { actSubscription.RenderMethod(renderState); } catch (Exception ex) { GraphicsCore.PublishInternalExceptionInfo( ex, InternalExceptionLocation.Rendering3DObject); // Mark this object as invalid if (invalidObjects == null) { invalidObjects = new List <SceneObject>(); } invalidObjects.Add(actSubscription.SceneObject); } } } finally { if (renderPass != null) { renderPass.Discard(renderState); } } } }
/// <summary> /// Subscribes the given object to the given render pass. /// </summary> internal RenderPassSubscription SubscribeForPass( RenderPassInfo passInfo, SceneObject sceneObject, Action <RenderState> renderMethod, int zOrder) { if (!m_isSubscribeUnsubscribeAllowed) { throw new SeeingSharpException("Subscription is not allowed currently!"); } var subscriptionProperties = m_objectsPerPassDict[passInfo]; // Append new subscription to subscription list List <RenderPassSubscription> subscriptions = subscriptionProperties.Subscriptions; int subscriptionsCount = subscriptions.Count; RenderPassSubscription newSubscription = new RenderPassSubscription(this, passInfo, sceneObject, renderMethod, zOrder); if (!passInfo.IsSorted) { // No sort, so put the new subscription to the end of the collection newSubscription.SubscriptionIndex = subscriptionsCount; subscriptions.Add(newSubscription); } else { // Perform BinaryInsert to the correct position int newIndex = CommonTools.BinaryInsert(subscriptions, newSubscription, SubscriptionZOrderComparer.Instance); // Increment all subscription indices after the inserted position subscriptionsCount++; RenderPassSubscription actSubscription; for (int loop = newIndex; loop < subscriptionsCount; loop++) { actSubscription = subscriptions[loop]; if (actSubscription.SubscriptionIndex != loop) { actSubscription.SubscriptionIndex = loop; subscriptions[loop] = actSubscription; actSubscription.SceneObject.UpdateSubscription(actSubscription, this); } } newSubscription = subscriptions[newIndex]; } return(newSubscription); }
/// <summary> /// Executes view update using the given update state object. /// </summary> /// <param name="updateState">The update state.</param> internal void UpdateForView(SceneRelatedUpdateState updateState) { if (m_disposed) { throw new ObjectDisposedException("ViewRelatedLayerSubset"); } // TODO: Trigger some other logic to update transparent object order // TODO: Performance improvement!!! bool anyOrderChanges = false; Camera3DBase camera = m_viewInformation.Camera; m_objectsPassTransparentRender.Subscriptions.Sort(new Comparison <RenderPassSubscription>((left, right) => { SceneSpacialObject leftSpacial = left.SceneObject as SceneSpacialObject; SceneSpacialObject rightSpacial = right.SceneObject as SceneSpacialObject; if ((leftSpacial != null) && (rightSpacial != null)) { float leftDistance = (camera.Position - leftSpacial.Position).LengthSquared(); float rightDistance = (camera.Position - rightSpacial.Position).LengthSquared(); anyOrderChanges = true; return(rightDistance.CompareTo(leftDistance)); } else if (leftSpacial != null) { anyOrderChanges = true; return(-1); } else if (rightSpacial != null) { anyOrderChanges = true; return(1); } { return(0); } })); if (anyOrderChanges) { // Synchronize ordering changes with corresponding scene object for (int loop = 0; loop < m_objectsPassTransparentRender.Subscriptions.Count; loop++) { var actSubscription = m_objectsPassTransparentRender.Subscriptions[loop]; actSubscription.SubscriptionIndex = loop; actSubscription.SceneObject.UpdateSubscription(actSubscription, this); m_objectsPassTransparentRender.Subscriptions[loop] = actSubscription; } } // Update all objects related to this view m_isSubscribeUnsubscribeAllowed = true; try { // Update subscriptions based on visibility check result if (m_changedVisibilitiesAction != null) { m_changedVisibilitiesAction(); m_changedVisibilitiesAction = null; } // Unsubscribe all invalid objects SceneObject actInvalidObject = null; while (m_invalidObjectsToDeregister.Count > 0) { actInvalidObject = m_invalidObjectsToDeregister.Dequeue(); actInvalidObject.UnsubsribeFromAllPasses(this); } // Update subsccriptions based on boject state List <SceneObject> allObjects = m_sceneLayer.ObjectsInternal; int allObjectsLength = allObjects.Count; int visibleObjectCount = m_viewInformation.Owner.VisibleObjectCountInternal; for (int loop = 0; loop < allObjectsLength; loop++) { SceneObject actSceneObject = allObjects[loop]; if (m_invalidObjects.ContainsKey(actSceneObject)) { continue; } if (actSceneObject.IsLayerViewSubsetRegistered(this.ViewIndex) && actSceneObject.IsVisible(m_viewInformation)) { actSceneObject.UpdateForView(updateState, this); visibleObjectCount++; } } m_viewInformation.Owner.VisibleObjectCountInternal = visibleObjectCount; } finally { m_isSubscribeUnsubscribeAllowed = false; } // Reorganize subscriptions if there is anything unsubscribed if (m_anythingUnsubscribed) { m_anythingUnsubscribed = false; foreach (var actPassProperties in m_objectsPerPass) { if (actPassProperties.UnsubscribeCallCount <= 0) { continue; } // Variables for consistency checking int givenUnsubscribeCount = actPassProperties.UnsubscribeCallCount; int trueUnsubscribeCount = 0; // Handle case where we have unsubscribed some // => Build new subscription list and ignore all whith 'IsSubscribed' == false List <RenderPassSubscription> newSubscriptionList = new List <RenderPassSubscription>( (actPassProperties.Subscriptions.Count - actPassProperties.UnsubscribeCallCount) + 128); for (int loop = 0; loop < actPassProperties.Subscriptions.Count; loop++) { RenderPassSubscription actSubscription = actPassProperties.Subscriptions[loop]; if (!actSubscription.IsSubscribed) { actSubscription.SceneObject.ClearSubscriptionsWithoutUnsubscribeCall(this, actSubscription); trueUnsubscribeCount++; continue; } // Add this item to new subscription list actSubscription.SubscriptionIndex = newSubscriptionList.Count; newSubscriptionList.Add(actSubscription); actSubscription.SceneObject.UpdateSubscription(actSubscription, this); } actPassProperties.Subscriptions = newSubscriptionList; actPassProperties.UnsubscribeCallCount = 0; // Check for consistency: Does unsubscribe-count match true unsubscriptions using IsSubscribed flag if (givenUnsubscribeCount != trueUnsubscribeCount) { throw new SeeingSharpException("Inconsistency: Given unsubscribe count does not mach true count of unsubscriptions!"); } } } }