Пример #1
0
        /// <summary>
        /// Advances the world model by one frame.
        /// </summary>
        public void Update()
        {
            // Update nodes.
            lock (_nodeLock) {
                // Update the nodes and determine required tree width.
                double halfWidth = 0;
                foreach (Node node in _nodes)
                {
                    node.Update();
                    halfWidth = Math.Max(Math.Abs(node.Location.X), halfWidth);
                    halfWidth = Math.Max(Math.Abs(node.Location.Y), halfWidth);
                    halfWidth = Math.Max(Math.Abs(node.Location.Z), halfWidth);
                }

                // Build tree for node repulsion.
                Octree tree = new Octree(2.1 * halfWidth);
                foreach (Node node in _nodes)
                {
                    tree.Add(node);
                }
                if (_nodes.Count > 0)
                {
                    Parallel.ForEach(_nodes, node => {
                        // Apply repulsion between nodes.
                        tree.Accelerate(node);

                        // Apply origin attraction of nodes.
                        Vector originDisplacementUnit = -node.Location.Unit();
                        double originDistance         = node.Location.Magnitude();

                        double attractionCofficient = OriginFactor;
                        if (originDistance < OriginWeakDistance)
                        {
                            attractionCofficient *= originDistance / OriginWeakDistance;
                        }

                        node.Acceleration += originDisplacementUnit * attractionCofficient / (originDistance + OriginEpsilon);

                        // Apply edge spring forces.
                        foreach (Node other in node.Connected)
                        {
                            Vector displacement = node.Location.To(other.Location);
                            Vector direction    = displacement.Unit();
                            double distance     = displacement.Magnitude();
                            double idealLength  = EdgeLength + node.Radius + other.Radius;

                            node.Acceleration += direction * EdgeFactor * (distance - idealLength) / node.Mass;
                        }
                    });
                }

                // Update frame info.
                if (_nodes.Count > 0)
                {
                    Frames++;
                }
            }

            // Update camera.
            _cameraZ          += _cameraZVelocity * _cameraZ;
            _cameraZ           = Math.Max(1, _cameraZ);
            _cameraZVelocity  *= CameraZEasing;
            _renderer.Camera.Z = _cameraZ;
        }
        /// <summary>
        /// Advances the world model by one frame.
        /// </summary>
        public void Update()
        {
            // Update nodes.
            lock (_nodeLock) {
                // Update the nodes and determine required tree width.
                double halfWidth = 0;
                foreach (Node node in _nodes)
                {
                    node.Update();
                    halfWidth = Math.Max(Math.Abs(node.Location.X), halfWidth);
                    halfWidth = Math.Max(Math.Abs(node.Location.Y), halfWidth);
                    halfWidth = Math.Max(Math.Abs(node.Location.Z), halfWidth);
                }
                Radius = halfWidth;

                // Build tree for node repulsion.
                Octree tree = new Octree(2.1 * halfWidth);
                foreach (Node node in _nodes)
                {
                    tree.Add(node);
                }

                Threading.Parallel.ForEach(_nodes, node => {
                    // Apply repulsion between nodes.
                    tree.Accelerate(node);

                    // Apply origin attraction of nodes.
                    //Vector originDisplacementUnit = -node.Location.Unit();
                    Vector origin = (node.Group == null) ? Vector.Zero : node.Group.Origin;
                    Vector originDisplacementUnit = Unit(origin - node.Location);
                    double originDistance         = (origin - node.Location).Magnitude();

                    double attractionCofficient = OriginFactor;
                    if (originDistance < OriginWeakDistance)
                    {
                        attractionCofficient *= originDistance / OriginWeakDistance;
                    }

                    // Apply group's attraction factor
                    //attractionCofficient *= (node.Group == null) ? 1 : node.Group.Factor;
                    //node.Acceleration += originDisplacementUnit * attractionCofficient / (originDistance + OriginEpsilon);

                    Vector originAcceleration = originDisplacementUnit * attractionCofficient / (originDistance + OriginEpsilon);

                    if (node.Group != null)
                    {
                        originAcceleration.X *= node.Group.Factor.X;
                        originAcceleration.Y *= node.Group.Factor.Y;
                        originAcceleration.Z *= node.Group.Factor.Z;
                    }

                    node.Acceleration += originAcceleration;

                    // Apply edge spring forces.
                    foreach (Node other in node.Connected)
                    {
                        Vector displacement = node.Location.To(other.Location);
                        //Vector direction = displacement.Unit();
                        Vector direction = Unit(displacement);
                        double distance  = displacement.Magnitude();
                        //double idealLength = EdgeLength + node.Radius + other.Radius;

                        // Set a large mass if it's in different groups
                        double mass        = (node.Group != other.Group) ? 1000 : node.Mass;
                        double idealLength = EdgeLength + Node.GetRadius(mass) + other.Radius;

                        node.Acceleration += direction * EdgeFactor * (distance - idealLength) / mass;
                        //node.Acceleration += direction * EdgeFactor * (distance - idealLength) / node.Mass;
                    }
                });
            }
        }