Example #1
0
        /// <summary>
        /// Called when the <see cref="Children"/> collection was changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="eventArgs">
        /// The <see cref="CollectionChangedEventArgs{IGeometricObject}"/> instance containing the event
        /// data.
        /// </param>
        private void OnChildrenChanged(object sender, CollectionChangedEventArgs <IGeometricObject> eventArgs)
        {
            if (eventArgs.Action == CollectionChangedAction.Move)
            {
                return;
            }

            // Handle removed items.
            var oldItems         = eventArgs.OldItems;
            int numberOfOldItems = oldItems.Count;

            for (int i = 0; i < numberOfOldItems; i++)
            {
                var geometricObject = oldItems[i];

                geometricObject.PoseChanged  -= OnChildShapeChanged;
                geometricObject.ShapeChanged -= OnChildShapeChanged;
            }

            // Handle new items.
            var newItems         = eventArgs.NewItems;
            int numberOfNewItems = newItems.Count;

            for (int i = 0; i < numberOfNewItems; i++)
            {
                var geometricObject = newItems[i];

                geometricObject.PoseChanged  += OnChildShapeChanged;
                geometricObject.ShapeChanged += OnChildShapeChanged;
            }

            // Rebuild spatial partition.
            if (_partition != null)
            {
                _partition.Clear();
                int numberOfChildren = Children.Count;
                for (int i = 0; i < numberOfChildren; i++)
                {
                    _partition.Add(i);
                }
            }

            if (numberOfOldItems == 1 &&
                numberOfNewItems == 1 &&
                eventArgs.OldItemsIndex == eventArgs.NewItemsIndex)
            {
                // Exactly one item was replaced.
                // --> Set the feature index of the item in the event args.
                var shapeChangedEventArgs = ShapeChangedEventArgs.Create(eventArgs.OldItemsIndex);
                OnChanged(shapeChangedEventArgs);
                shapeChangedEventArgs.Recycle();
            }
            else
            {
                // Multiple items added or removed. The indices of multiple items have changed.
                // --> Do not set a feature index. Use the default.
                OnChanged(ShapeChangedEventArgs.Empty);
            }
        }
Example #2
0
        /// <summary>
        /// Invalidates the whole triangle mesh or a single triangle.
        /// </summary>
        /// <param name="triangleIndex">
        /// Index of the triangle. Can be -1 to invalidate the whole mesh.
        /// </param>
        /// <param name="invalidateTopology">
        /// If set to <see langword="true"/> the mesh topology is invalidated.
        /// </param>
        /// <remarks>
        /// <para>
        /// This method must be called if the position of a triangle stored in <see cref="Mesh"/> is
        /// changed. This method updates the <see cref="Partition"/> and raises the
        /// <see cref="Shape.Changed"/> event by calling <see cref="Shape.OnChanged"/>.
        /// </para>
        /// <para>
        /// If the mesh topology has changed, <paramref name="invalidateTopology"/> must be set to
        /// <see langword="true"/>. The topology has changed if triangle neighbor relationships have
        /// changed. If each triangle has the same neighbor triangles as before and only the vertices
        /// were moved, <paramref name="invalidateTopology"/> can be <see langword="false"/>.
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="triangleIndex"/> is out of range.
        /// </exception>
        public void Invalidate(int triangleIndex, bool invalidateTopology)
        {
            int numberOfTriangles = Mesh.NumberOfTriangles;

            if (triangleIndex >= numberOfTriangles)
            {
                throw new ArgumentOutOfRangeException("triangleIndex");
            }

            // Set cached AABB to "invalid".
            _aabbLocal = new Aabb(new Vector3F(float.NaN), new Vector3F(float.NaN));

            // Fill new spatial partition.
            if (_partition != null)
            {
                if (numberOfTriangles != _partition.Count)
                {
                    // Triangle count has changed. Re-initialize partition content.
                    _partition.Clear();
                    for (int i = 0; i < numberOfTriangles; i++)
                    {
                        _partition.Add(i);
                    }
                }
                else
                {
                    // Same number of triangles - invalidate the triangle.
                    if (triangleIndex >= 0)
                    {
                        _partition.Invalidate(triangleIndex);
                    }
                    else
                    {
                        _partition.Invalidate();
                    }
                }
            }

            if (invalidateTopology)
            {
                ComputeTriangleNeighbors();
            }

            if (triangleIndex < 0)
            {
                OnChanged(ShapeChangedEventArgs.Empty);
            }
            else
            {
                var eventArgs = ShapeChangedEventArgs.Create(triangleIndex);
                OnChanged(eventArgs);
                eventArgs.Recycle();
            }
        }
Example #3
0
        /// <summary>
        /// Called when a child object was changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="eventArgs">
        /// The <see cref="EventArgs"/> instance containing the event data.
        /// </param>
        private void OnChildShapeChanged(object sender, EventArgs eventArgs)
        {
            // Invalidate partition.
            var index = Children.IndexOf(sender as IGeometricObject);

            if (Partition != null)
            {
                if (index >= 0)
                {
                    Partition.Invalidate(index);
                }
                else
                {
                    Partition.Invalidate();
                }
            }

            var shapeChangedEventArgs = ShapeChangedEventArgs.Create(index);

            OnChanged(shapeChangedEventArgs);
            shapeChangedEventArgs.Recycle();
        }