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

Класс ClothSim берет TexturedPlane в качестве геометрии ткани, так же как атрибуты для различных типов нитей должны соединить вершины ткани. Он также создает вершины моделирования, подключает нити и добавляет ограничения длины между вершинами. Два метода в конструкторе еще не были реализованы, и сейчас мы их обсудим.

Реализация для CreateSimVertices следующая:

(метод класса в ClothSim.cs)
        private
void CreateSimVertices(TexturedPlane clothPlane, float clothMass)

        {

            int numVertices = clothPlane.NumVertices;

            float vertexMass = clothMass / numVertices;

            simVertices = new
SimVertex[numVertices];

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

            {

                simVertices[i] = new
SimVertex(vertexMass, SimObjectType.ACTIVE, i, clothPlane);

                this.AddSimObject(simVertices[i]);

            }

        }

В основном создается SimVertex для каждой вершины плоскости, и устанавливается активным, чтобы быть обработанным моделированием.

Прежде, чем мы обсудим метод ConnectSprings, мы должны поговорить о том, как нити должны быть подключены для геометрии ткани. Есть по существу три вида нитей, которые необходимы для хорошего моделирования ткани:

1. Структурные нити(Structural springs) (Рис. 3): Они размещены вдоль стороны квадрата. Это — основные нити, которые поддерживают расстояние между вершинами в горизонтальных и вертикальных направлениях.


Рисунок 3:Структурные нити на плоскости

  1. Нити сдвига(Shear springs) (Рис. 4): Они размещены вдоль диагоналей каждого квадрата. Они помогают поддерживать квадратную форму каждого четырехугольника, мешая им свернуться в плоские алмазные формы.


рисунок 4:Нити сдвига на плоскости

  1. Нити изгиба(Bend springs) (Рис. 5 и 6): Они размещены горизонтально и вертикально точно так же как структурные нити. Однако, они размещены между вершинами, которые является обособленными (через одну). Они помогают управлять тем, насколько ткань может изогнуться. Высокое значение жесткости для этих нитей создаст «более жесткий» вид (например, кожа), в то время как низкое значение жесткости создаст более мягкое поведение (например, шелк).


Рис 5: Горизонтальные нити изгиба на плоскости


Рис 6: Вертикальные нити изгиба на плоскости

Эти видео иллюстрируют, как ткань будет вести себя без некоторых из этих нитей.

Видео 7: моделирование Ткани с только структурными нитями (никаких нитей изгиба или сдвига). Ткань неспособна поддержать хорошую форму.

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

Видео 8: моделирование Ткани со структурным нитями и нитями сдвига (без нитей изгиба). Ткань держит свою форму лучше, но неспособна изогнуться реалистично и проникает через себя легко.

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

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

С этим новым знанием того, как соединить нити, мы можем начать реализовывать метод ConnectSprings:

(метод класса в ClothSim.cs)
        private
void ConnectSprings(float structStiffness, float structDamping,

                                    float shearStiffness, float shearDamping,

                                    float bendStiffness, float bendDamping)

        {

            for (int x = 0; x < clothPlane.LengthSegments; x++)

            {

                for (int y = 0; y <= clothPlane.WidthSegments; y++)

                {

                    //structural spring: horizontal (-)

                    int vertexAId = x + y * (clothPlane.LengthSegments + 1);

                    int vertexBId = (x + 1) + y * (clothPlane.LengthSegments + 1);

                    this.AddSpring(structStiffness, structDamping, simVertices[vertexAId], simVertices[vertexBId]);

                    float length = (clothPlane.GetVertexPosition(vertexAId) — clothPlane.GetVertexPosition(vertexBId)).Length();

                    this.Constraints.Add(new
LengthConstraint(length, simVertices[vertexAId], simVertices[vertexBId]));

                }

            }
            for (int x = 0; x <= clothPlane.LengthSegments; x++)

            {

                for (int y = 0; y < clothPlane.WidthSegments; y++)

                {

                    //structural spring: vertical (|)

                    int vertexAId = x + y * (clothPlane.LengthSegments + 1);

                    int vertexBId = x + (y + 1) * (clothPlane.LengthSegments + 1);

                    this.AddSpring(structStiffness, structDamping, simVertices[vertexAId], simVertices[vertexBId]);

                    float length = (clothPlane.GetVertexPosition(vertexAId) — clothPlane.GetVertexPosition(vertexBId)).Length();

                    this.Constraints.Add(new
LengthConstraint(length, simVertices[vertexAId], simVertices[vertexBId]));

                }

            }
            for (int x = 0; x < clothPlane.LengthSegments; x++)

            {

                for (int y = 0; y < clothPlane.WidthSegments; y++)

                {

                    //shear spring: diagonal (/)

                    int vertexAId = (x + 1) + y * (clothPlane.LengthSegments + 1);

                    int vertexBId = x + (y + 1) * (clothPlane.LengthSegments + 1);

                    this.AddSpring(shearStiffness, shearDamping, simVertices[vertexAId], simVertices[vertexBId]);

                    float length = (clothPlane.GetVertexPosition(vertexAId) — clothPlane.GetVertexPosition(vertexBId)).Length();

                    this.Constraints.Add(new
LengthConstraint(length, simVertices[vertexAId], simVertices[vertexBId]));

                    //shear spring: diagonal (\)

                    vertexAId = x + y * (clothPlane.LengthSegments + 1);

                    vertexBId = (x + 1) + (y + 1) * (clothPlane.LengthSegments + 1);

                    this.AddSpring(shearStiffness, shearDamping, simVertices[vertexAId], simVertices[vertexBId]);

                    length = (clothPlane.GetVertexPosition(vertexAId) — clothPlane.GetVertexPosition(vertexBId)).Length();

                    this.Constraints.Add(new
LengthConstraint(length, simVertices[vertexAId], simVertices[vertexBId]));

                }

            }
            for (int x = 0; x < clothPlane.LengthSegments — 1; x++)

            {

                for (int y = 0; y <= clothPlane.WidthSegments; y++)

                {

                    //bend spring: horizontal (—)

                    int vertexAId = x + y * (clothPlane.LengthSegments + 1);

                    int vertexBId = (x + 2) + y * (clothPlane.LengthSegments + 1);

                    this.AddSpring(bendStiffness, bendDamping, simVertices[vertexAId], simVertices[vertexBId]);

                    float length = (clothPlane.GetVertexPosition(vertexAId) — clothPlane.GetVertexPosition(vertexBId)).Length();

                    this.Constraints.Add(new
LengthConstraint(length, simVertices[vertexAId], simVertices[vertexBId]));

                }

            }
            for (int x = 0; x <= clothPlane.LengthSegments; x++)

            {

                for (int y = 0; y < clothPlane.WidthSegments — 1; y++)

                {

                    //bend spring: vertical (||)

                    int vertexAId = x + y * (clothPlane.LengthSegments + 1);

                    int vertexBId = x + (y + 2) * (clothPlane.LengthSegments + 1);

                    this.AddSpring(bendStiffness, bendDamping, simVertices[vertexAId], simVertices[vertexBId]);

                    float length = (clothPlane.GetVertexPosition(vertexAId) — clothPlane.GetVertexPosition(vertexBId)).Length();

                    this.Constraints.Add(new
LengthConstraint(length, simVertices[vertexAId], simVertices[vertexBId]));

                }

            }

        }

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

Теперь, когда мы присоединили нити, мы должны обновить геометрию ткани в методе Update:

(метод класса в ClothSim.cs)
        public
override
void Update(GameTime gameTime)

        {

            //call base.Update() to update the vertex positions

            base.Update(gameTime);
            //recalculate the vertex normals

            clothPlane.RecalculateNormals();
            //commit the vertex position and normal changes

            clothPlane.CommitChanges();

        }

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

2.5 Используя Новые Классы, Чтобы Создать Моделирование Ткани

Мы теперь готовы создать ткань в нашем главном программном файле Game1.cs.

Во-первых, мы инициализируем сцену.

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

        {

            InitClothScene();

            base.Initialize();

        }
        private
void InitClothScene()

        {

        }

Мы определяем атрибуты ткани и создаем плоскость как геометрию ткани.

(в самом верху Game1.cs)
using SkeelSoftBodyPhysicsTutorial.Primitives;
(снаружи InitClothScene()в Game1.cs)
         TexturedPlane clothPlane;
(внутри InitClothScene()в Game1.cs)
            //cloth attributes

            int length = 10;

            int width = 5;

            int lengthSegments = 20;

            int widthSegments = 15;
            //load in a plane

            clothPlane = new
TexturedPlane(this, length, width, lengthSegments, widthSegments, @»checkerboard»);

            clothPlane.Initialize();

В Solution Explorer обратите внимание, что есть папка под названием Primitives, которая содержит классы, которые Вы можете использовать, чтобы создать текстурируемые плоскости и цилиндры. Я не буду объяснять коды в этих классах, но отмечаю, что с этими классами, Вы будете в состоянии создать примитивы, а также получить/установить атрибуты вершины, такие как позиция и нормаль. Если Вы соберетесь использовать свои собственные классы примитивов или загрузить Ваши собственные модели из файлов, то Вы также должны будете иметь методы, чтобы получить/установить атрибуты вершины.

Мы затем определяем массу ткани, атрибуты различных нитей для ткани, и создаем экземпляр класса ClothSim:

(в самом верху Game1.cs)
using SkeelSoftBodyPhysicsTutorial.SoftBody.Simulations;
(снаружи InitClothScene()в Game1.cs)
        ClothSim clothSim;
(внутри InitClothScene()в Game1.cs)
            //create a cloth sim

            float clothMass = 2.0f;

            float structStiffness = 2.0f;

            float structDamping = 0.02f;

            float shearStiffness = 2.0f;

            float shearDamping = 0.02f;

            float bendStiffness = 2.0f;

            float bendDamping = 0.02f;

            clothSim = new
ClothSim(this, clothPlane, clothMass, structStiffness, structDamping, shearStiffness, shearDamping, bendStiffness, bendDamping);

            clothSim.ConstraintIterations = 10;

Затем, мы создаем глобальные источники силы. Для нашего моделирования ткани это только сила тяжести. Отметьте, что мы не будем создавать генератор силы окружающей среды, так как силы сопротивления будут моделироваться в интеграторе Verlet.

(на самом верху Game1.cs)
using SkeelSoftBodyPhysicsTutorial.SoftBody.ForceGenerators;
(внутри InitClothScene()в Game1.cs)
            //add in a global forceGenerators: gravity

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

            clothSim.AddGlobalForceGenerator(gravity);

Мы ограничим верхние левые и верхние правые углы плоскости, чтобы затем управлять ими. Это сделано при использовании PointConstraints.

(в самом верху Game1.cs)
using SkeelSoftBodyPhysicsTutorial.SoftBody.Constraints;
(снаружи InitClothScene()in Game1.cs)
        PointConstraint topLeftCorner, topRightCorner;
(внутри InitClothScene()in Game1.cs)
            //constrain the two top corners of the cloth so that we can control it

            topLeftCorner = new
PointConstraint(clothSim.SimVertices[0].CurrPosition, clothSim.SimVertices[0]);

            clothSim.Constraints.Add(topLeftCorner);

            topRightCorner = new
PointConstraint(clothSim.SimVertices[lengthSegments].CurrPosition, clothSim.SimVertices[lengthSegments]);

            clothSim.Constraints.Add(topRightCorner);

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

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

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

Логотип WordPress.com

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

Фотография Twitter

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

Фотография Facebook

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

Google+ photo

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

Connecting to %s