Введение в Физику мягких форм (Перевод) Часть 8

Для нашей демонстрационной версии мы хотим иметь силу, которая выводит из равновесия гибкое тело, в то время как целевой объект остается постоянным. Мы сделаем это, используя генератор Силы тяжести. Мы сначала установим ускорение в нулевой вектор, и изменим это, ориентируясь на то, как пользователь будет использовать мышь, чтобы взаимодействовать со сценой. Логически говоря, мы должны фактически создать другой класс под названием Push, но реализация будет точно такая же как генератор Силы тяжести, таким образом, мы не будем касаться этой проблемы.

(снаружи InitGoalSoftBodyScene() в Game1.cs)
        Gravity push;
(внутри InitGoalSoftBodyScene() в Game1.cs)
            //create a force generator that we will use to push the cylinder later

            push = new
Gravity(Vector3.Zero);

            goalSoftBodySim.AddGlobalForceGenerator(push);

Как обычно, мы создаем интегратор и назначаем его моделированию. 

(внутри InitGoalSoftBodyScene() в Game1.cs)
            //create an integrator and assign it to the sim

            float drag = 0.05f;

            Integrator integrator = new
VerletNoVelocityIntegrator(this, drag);

            goalSoftBodySim.Integrator = integrator;

Затем, мы должны попросить, чтобы и целевой объект и объект мягкого тела загрузили свое содержимое.

(метод класса в Game1.cs, дополнительный код жирный шрифтом)
        protected
override
void LoadContent()

        {

            spriteBatch = new
SpriteBatch(GraphicsDevice);

            cylinder.LoadContent();

            goalCylinder.LoadContent();

        }

В существующем методе Update мы должны опросить для ввода, и также попросить, чтобы модель целевого гибкого тела обновила себя.

(метод класса в Game1.cs, дополнительный код жирный шрифтом)
        protected
override
void Update(GameTime gameTime)

        {

            //poll for input

            HandleInput(gameTime);
            //update the simulation

            goalSoftBodySim.Update(gameTime);
            base.Update(gameTime);

        }

Мы хотим, чтобы пользователь использовал мышь, чтобы взаимодействовать с мягким телом. Пользователь зажмет левую кнопку мыши и двинет курсор. Как только он отпустит, сила будет применена к мягкому объекту тела, устанавливая ускорение генератора Силы тяжести, и эта величина будет основана на том, как далеко пользователь перетащил курсор на экране.

(метод класса in Game1.cs)
        Vector2 startPos, endPos;

        private
void HandleInput(GameTime gameTime)

        {

            if (inputComponent.IsMouseJustDown(MouseButtonType.Left))

            {

                //mouse is just down, so store the starting position

                startPos = inputComponent.MousePosition;

            }

            else
if (inputComponent.IsMouseJustUp(MouseButtonType.Left))

            {

                //mouse has just been released, so find the ending position

                endPos = inputComponent.MousePosition;
                //use distance mouse moved as the push acceleration

                push.AccelerationX = (endPos.X — startPos.X) * 3;

                push.AccelerationY = -(endPos.Y — startPos.Y) * 3;
                return;

            }
            //set the push acceleration to zero

            push.Acceleration = Vector3.Zero;

        }

Наконец, мы рисуем цилиндр. Режим culling mode не установлен так, что мы можем видеть обе стороны цилиндра.

(метод класса в Game1.cs, дополнительный код жирный шрифтом)
        protected
override
void Draw(GameTime gameTime)

        {

            GraphicsDevice.Clear(Color.CornflowerBlue);

            GraphicsDevice.RenderState.CullMode = CullMode.None;

            base.Draw(gameTime);

            cylinder.Draw(gameTime);

        }

У Вас должно теперь быть моделирование мягкого тела на цилиндре, где пользователь может влиять, нажимая на левую кнопку мышки и перетаскивая через экран курсор. Это могло бы сработать хорошо для шеи или руки полного персонажа, где жир покачивается как мягкое тело.

Видео 10: моделирование целевого мягкого тела

http://www.youtube.com/watch?v=TZJDTVReTx8&feature=player_embedded

Давайте попытаемся сделать эту демонстрационную версию немного более презентабельной. Мы создадим объект, который является цилиндрическим и имеет движение похожее на пружину: слинки. Это может быть сделано, с использованием простой карты текстуры с альфой(simple texture map with alpha). В методе InitGoalSoftBodyScene, измените текстуру цилиндра на «слинки». Эта текстура есть в папке Content.

(внутри InitGoalSoftBodyScene() в Game1.cs, изменения кода показаны жирным шрифтом)
            //load in the cylinder

            cylinder = new
TexturedCylinder(this, length, radius, lengthSegments, radialSegments, «slinky«);

            cylinder.Initialize();

Вот оно! У Вас теперь есть модель псевдо-слинки, которая основана на целевом мягком теле, точно так же как на Видео 9, что Вы видели в начале главы.

В этой главе мы обсудили идею, стоящую за целевым мягким телом и создали класс, чтобы обработать присоединения нитей. Мы применили целевое моделирование мягкого тела на цилиндр, заставив его быть похожим на подобие дряблой шеи или на руку полного персонажа. Затем мы предприняли шаги далее, чтобы создать поддельную модель слинки, просто изменяя текстуру на цилиндре. Это было сделано, чтобы показать, как простые уловки могут использоваться, чтобы подражать поведению, которое могло бы быть дорогостоящим, чтобы быть обработанным в режиме реального времени.

В следующей главе мы увидим, как мы можем создать другое псевдо моделирование, которое похоже на моделирование твердого тела с обработкой столкновения!

Загрузите исходные файлы для окончания этой главы

Глава 4 – Подделка Твердых тел: Моделирование Цепи

Загрузите исходные файлы для начала этой главы

Чтобы иллюстрировать полноценность моделирований мягких тел, мы будем использовать 1D симулятор мягкого тела, чтобы создать псевдо моделирование твердого тела в этой главе. Оно будет включать последовательность узлов, упорядоченных вертикально, и эти узлы будут связаны нитями. Модель сегмента цепи будет использоваться как каждый из узлов, таким образом, создавая внешне вид длинной цепочки. Как только расстояния между узлами будут ограничены ограничениями длины, будет похоже, что цепочка подвергается проверке на пересечение, чтобы поддержать те расстояния.

К концу этой главы Вы будете в состоянии создать моделирование цепи как это:

Видео 11: моделирование цепи при использовании 1D симулятор мягкого тела

http://www.youtube.com/watch?v=XNyO0XXhh_o&feature=player_embedded

4.1 Класс Моделирования Цепи

Мы начнем, сначала создавая класс ChainSim. В папке Simulations создайте новый файл класса по имени ChainSim.cs.

(ChainSim.cs)
using System;

using Microsoft.Xna.Framework;

using SkeelSoftBodyPhysicsTutorial.Main;

using SkeelSoftBodyPhysicsTutorial.SoftBody.Constraints;

using SkeelSoftBodyPhysicsTutorial.SoftBody.SimObjects;
namespace SkeelSoftBodyPhysicsTutorial.SoftBody.Simulations

{

    public
class
ChainSim : Simulation

    {

        public ChainSim(Game game, GameModel[] ropeSegmentModels, float totalMass, float stiffness, float damping)

            : base(game)

        {

            //create sim data

            float sphereMass = totalMass / ropeSegmentModels.Length;

            SimModel[] simObjs = new
SimModel[ropeSegmentModels.Length];

            for (int i = 0; i < ropeSegmentModels.Length; i++)

            {

                simObjs[i] = new
SimModel(ropeSegmentModels[i], sphereMass, SimObjectType.ACTIVE);

                this.AddSimObject(simObjs[i]);

            }
            //attach springs between the sim objects

            for (int i = 1; i < ropeSegmentModels.Length; i++)

            {

                this.AddSpring(stiffness, damping, simObjs[i — 1], simObjs[i]);

                this.Constraints.Add(new
LengthConstraint((simObjs[i — 1].Model.Translate — simObjs[i].Model.Translate).Length(), simObjs[i — 1], simObjs[i]));

            }

        }

    }

}

Мы сначала создаем активный SimModel для каждого из цепных сегментов и затем прикрепляем нити с ограничениями между объектами SimModel. Это довольно похоже на то, как мы создавали наши классы Simulation до сих пор.

Затем, мы должны переопределить метод Update.

(метод класса в ChainSim.cs)

Vector3 currToChildVector;

float angle;

Vector3 rotAxis;

public override void Update(GameTime gameTime)

{

//call base to perform simulation

base.Update(gameTime);

//orient rope segments so that they point to immediate child

for (int i = 0; i < simObjects.Count — 1; i++)

{

//get vector that points to child

currToChildVector = simObjects[i + 1].CurrPosition — simObjects[i].CurrPosition;

if (currToChildVector != Vector3.Zero)

{

//normalize

currToChildVector.Normalize();

//find out angle to rotate

angle = (float)Math.Acos(Vector3.Dot(Vector3.UnitY, -currToChildVector));

angle = MathHelper.ToDegrees(angle);

//find out axis to rotate about

rotAxis = Vector3.Cross(Vector3.UnitY, -currToChildVector);

if (rotAxis != Vector3.Zero) rotAxis.Normalize();

//need to just rotate model about the zaxis for our case

((SimModel)simObjects[i]).Model.RotateZ = rotAxis.Z * angle;

}

}

//make the orientation of the last segment follow the parent segment

((SimModel)simObjects[simObjects.Count — 1]).Model.RotateZ = ((SimModel)simObjects[simObjects.Count — 2]).Model.RotateZ;

}

Как обычно, мы должны сначала попросить, чтобы базовый класс обновил себя, что повлечет за собой выполнение целого моделирование и предоставит нам новые положения. Затем мы будем вращать сегменты цепи так, чтобы они указывали на непосредственного ребенка. Чтобы сделать это, мы должны узнать угол вращения и ось вращения. Угол может быть найден, если узнать скалярное произведение Оси Y и вектора от ребенка к текущему сегменту. Ось вращения, с другой стороны, может быть найдена, если взять соответствующее векторное произведение. Эта ось даст нам направление вращения (по часовой стрелке или против часовой стрелки) когда нам дан угол. Для нашей программы мы будем ограничивать взаимодействие плоскостью XY, таким образом, мы должны будем только вращать сегменты цепи вдоль Оси Z, чтобы дать правдоподобное моделирование твердого тела. У последнего сегмента цепи нет никакого ребенка, на которого надо указывать, таким образом, мы только позволим ее направлению следовать за родителем.

4.2 Создание Моделирования Цепи

Мы теперь готовы создать наше моделирование цепи в Game1.cs. Как обычно, мы создаем метод, чтобы инициализировать сцену.

(метод класса в Game1.cs, дополнения к коду жирным шрифтом)
        protected
override
void Initialize()

        {

            InitChainScene();

            base.Initialize();

        }
        private
void InitChainScene()

        {

        }

Мы тогда определяем атрибуты цепи и загружаем модели, которые представят каждый цепной сегмент. Модель, которую мы будем загружать это chainSegment.fbx, которая есть в папке Content. Пока загружаем каждый сегмент, мы масштабируем и позиционируем его. Мы также поворачиваем четные сегменты на 90 градусов в Оси Y, чтобы сформировать взаимосвязанную цепочку.

(внутри InitChainScene() в Game1.cs)
            //chain attributes

            int numSegments = 30;

            float separation = 0.65f;
            //load in segments

            GameModel[] segments = new
GameModel[numSegments];

            for (int i = 0; i < numSegments; i++)

            {

                segments[i] = modelComponent.LoadGameModel(«chainSegment»);
                //reduce the size of each segment

                segments[i].Scale = 0.3f * Vector3.One;
                //position each segment downwards incrementally to form the chain

                segments[i].TranslateY = -i * separation;
                //rotate the even segments by 90 degrees in Y axis

                segments[i].RotateY = (i % 2) * 90.0f;

            }

Затем, мы создаем моделирование цепи.

(снаружи InitChainScene() in Game1.cs)
        ChainSim chainSim;
(внутри InitChainScene() in Game1.cs)
            //create a chain sim

            float totalMass = 1.0f;

            float stiffness = 0.3f;

            float damping = 0.01f;

            chainSim = new
ChainSim(this, segments, totalMass, stiffness, damping);

Мы затем добавляем Силу тяжести как глобальный источник силы.

(внутри InitChainScene() in Game1.cs)
            //add in a global force generator: gravity

            Gravity gravity = new
Gravity(new
Vector3(0, -9.81f * 5, 0));

            chainSim.AddGlobalForceGenerator(gravity);

Чтобы управлять цепочкой, мы должны прикрепить начало цепочки. Мы, таким образом, должны будем создать PointConstraint для головного цепного сегмента.

(внутри InitChainScene() in Game1.cs)
        PointConstraint chainHeadPoint;
(снаружи InitChainScene() in Game1.cs)
            //constrain the head point so that we can control it

            chainHeadPoint = new
PointConstraint(Vector3.Zero, chainSim.SimObjects[0]);

            chainSim.Constraints.Add(chainHeadPoint);

Затем мы создаем интегратор для системы моделирования как обычно.

(внутри InitChainScene() in Game1.cs)
            //create a integrator and assign it to the sim

            float drag = 0.005f;

            Integrator integrator = new
VerletNoVelocityIntegrator(this, drag);

            chainSim.Integrator = integrator;

Это — все, что мы должны сделать, чтобы инициализировать сцену.

Затем, мы должны попросить, чтобы цепное моделирование обновило себя.

(метод класса в Game1.cs, дополнения к коду жирным шрифтом)
        protected
override
void Update(GameTime gameTime)

        {

            //update the simulation

            chainSim.Update(gameTime);
            base.Update(gameTime);

        }

Если Вы скомпилируете и выполните моделирование теперь, то у Вас будет моделирование цепи! Различные сегменты поворачиваются соответствующе и с ограничениями длины, это моделирование мягкого тела действительно ведет себя как моделирование твердого тела, но только меньше затрат на производительность чем от моделирования реального твердого тела. Это — действительно так, потому что проверка на пересечение вогнутых объектов может быть в вычислительном отношении очень дорогой.

Как обычно, мы добавим кое-что в методе, чтобы управлять пользовательским вводом так, чтобы пользователь мог взаимодействовать со сценой.

(метод класса в Game1.cs, дополнения к коду жирным шрифтом)
        protected
override
void Update(GameTime gameTime)

        {

            //poll for input

            HandleInput(gameTime);
            //update the simulation

            chainSim.Update(gameTime);
            base.Update(gameTime);

        }
        private
void HandleInput(GameTime gameTime)

        {

            if (inputComponent.IsMouseHeldDown(MouseButtonType.Left))

            {

                chainHeadPoint.PointX += -inputComponent.MouseMoved.X / 40;

                chainHeadPoint.PointY += inputComponent.MouseMoved.Y / 40;

            }

        }

У Вас должно теперь быть интерактивное моделирование цепи, которое похоже на Видео 11 в начале главы.

В этой главе мы видели, как простое моделирование цепи может быть подменено при использовании простой 1D системы мягкого тела. Каждый узел системы мягкого тела представлен моделью сегмента цепи, которая вращается, чтобы всегда указать на непосредственную дочернюю вершину. Ограничения длины, добавленные к нитям, поддерживают расстояния между сегментами, заставляя все это выглядеть, будто проверка на пересечение выполняется. Такое моделирование быстро и устойчиво и является действительно хорошей заменой для более дорогого решения для твердого тела.

Загрузите исходные файлы для окончания этой главы

Заключение

Мы достигли конца этой очень длинной обучающей программы. Если Вы следовали полностью до этого пункта и заставили все работать, похлопайте себя по плечу! Вы заслуживаете этого!

Цель этой обучающей программы состояла в том, чтобы ввести главные понятия, необходимые для создания моделирования мягких тел в играх, и дать объектно-ориентированную реализацию этих понятий. Мы сначала начали с реализации простейшей системы упругих нитей и встроили много различных классов, чтобы заставить ее работать, включая объекты моделирования, генераторы силы, интеграторы и моделирования. Мы затем осуществили ограничения, чтобы заставить моделирование ткани прилично работать. Несколько различных типов нитей использовались, чтобы соединить вершины геометрии ткани вместе, для достижения реалистичного поведения. Другой тип мягкого тела был впоследствии представлен, где у каждой вершины тела есть целевая позиция, чтобы к ней двигаться. При использовании альфа-текстуры на цилиндре мы создаем слинки основанную на этом виде моделирования целевого мягкого тела. Последнее, но не по значению, мы показали альтернативное использование моделирования мягкого тела, демонстрируя, как оно может быть использовано, чтобы дать визуально благовидное моделирование твердого тела. Мы создали моделирование цепи, основанное на 1D симулятор гибкого тела. Моделирование быстрое, устойчивое и служит хорошей заменой для моделирований твердого тела.

Я надеюсь, что Вы узнали достаточно из этой обучающей программы, чтобы читать и осуществлять более продвинутые методы и алгоритмы. Есть много других методов создания мягких тел, доступных в литературе, некоторые из которых игнорируют массу тела (например, метод конечных элементов), в то время как другие пытаются сохранить массу тела, вводя вычисления жидкости в них (например, Герметичное Гибкое Тело(Pressurized Soft Body)), это только пара из них для примера. Вам проще читать об этих других методиках, как только Вы освоили основы.

Несколько расширений возможны с существующей системой, которая у нас есть. Вы могли, например, начать создавать проверку на пересечение для системы и даже создать пространственное разделение. Вы могли также начать реализовывать другие виды числовых интеграторов, силы (например ветер), и другие виды ограничений. Вы могли даже использовать GPU, чтобы выполнить некоторые из вычислений, необходимых для моделирований мягких тел! Эти темы вынужденно были упущены из этой обучающей программы из-за явной длины этой обучающей программы.

Мягкие тела точно будут интересным эффектом, применяемым в играх в ближайшем будущем, так начните с осуществления Ваших собственных систем моделирования мягких тел и пошлите мне ссылку на Вашу игру, когда Вы закончите! Наслаждайтесь и развлекайтесь!

Реклама
Запись опубликована в рубрике Uncategorized. Добавьте в закладки постоянную ссылку.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s