Suslik, статья - СУПЕР!
Просто нет слов, насколько всё понятно, реально нужно и практически полезно...
Побольше бы таких статей!!!! 
Suslik
Прошу прощения за свою назойливость, но почему всё таки ты меня игнорируешь? Я чем-то когда-то тебя оскорбил?
Wolshebnik
блин, да что ты привязался? ты хочешь услышать от меня ответ на этот вопрос?:
> А чем тебе не нравится статья "Advanced Character Physics"?
не понравилась как автор пишет да и всё, ёлки-палки.
Suslik, respect!
Статья отличная, все понятно и ясно. Жаль что твоя статья мне попалась на глаза позже Advanced Character Physics, наверняка потратил бы меньше времени на понимание и реализацию данного метода. Было очень приятно читать, сравнение методов, плюсы и минусы, красивые скрины... это я больше всего люблю в статьях такого типа=)
Жду новых статей! Удачи!
Да, народ всегда ведется на картинки! =)
В общем, что-то меня пробило на реализацию этого метода, сейчас хочу чисто реализовать функционал, который я больше всего использую в игре. И вот первая проблема, как сделать линейный дампинг?
Пытался делать так:
void particle::Move(){ vec2f deltaPos=( curPos-prevPos)*( 1.0f-damp); prevPos=curPos; curPos+=deltaPos; }
При этом имеется какое-то левое перескакивание...
MarkoPolo
в принципе, такой демпинг должен работать. ну, более-менее. ищи ошибку.
другое дело, что есть более мощный способ делать демпинг:
Vector2 point1 = particle1->pos; Vector2 point2 = particle2->pos; Vector2 delta = (point2 - point1); float velocityNormalProjection = ( particle2->deltaPos - particle1->deltaPos) * delta.GetNorm( ); Vector2 viscosityNormalForce = delta.GetNorm( ) * ( velocityNormalProjection) * viscosity; particle1->ApplyAcceleration( viscosityNormalForce); particle2->ApplyAcceleration( -viscosityNormalForce);
как-то так. мы считаем демпинг не для всей системы, а только для связей. при этом считаем, что в связи возникает напряжение, пропорциональное скорости её "растягивания", направленное, соотвественно, в противоположенном скорости направлении. это аналог вязкого трения, только вокруг одной оси(направления связи).
Suslik
В общем, ошибка как-то сама пропала...
Вот еще вопрос. Вот это лучше:
if(( p1 - p2).SquareLength( ) < sqr( particles[i].radius + particles[j].radius))
Чем:
if(( p1 - p2).Length( ) < particles[i].radius + particles[j].radius)
Так?
MarkoPolo
> Так?
так. что за глупый вопрос?
Suslik
Мысли в слух...
Конечно немного не в тему, оптимизирую, думаю разбить карту на сетку с постоянным размером клетки, какой брать размер клетки? Такой, чтобы точка частица могла принадлежать исключительно лишь одной клетке? Или как?
MarkoPolo
> какой брать размер клетки?
из логических соображений:
в идеальном случае, когда шарики плотно упакованы, каждый шарик коллайдится только примерно с 26 своими соседями(он находится примерно в центре куба 3х3х3). следовательно, в идеальном разбиении мы переберём сразу только этих кандидатов. ну вот отсюда и делай размер бакета порядка этого куба 3х3х3, то есть около трёх диаметров шарика.
Suslik
> трёх диаметров шарика.
ок.
Я массу частицам вот так прикрутил:
curPos-=penDir*penDepth*a.mass/(mass+a.mass); a.curPos+=penDir*penDepth*mass/( mass+a.mass);
Или по другому надо?
Вообще, метод ведь нормально подходит для частиц разного размера? Или он все-таки предназначен для большого числа полностью одинаковых?
MarkoPolo
> Я массу частицам вот так прикрутил
неверно. на твоём примере нужно как-то так:
curPos -= penDir * penDepth * (1.0f / mass) / ( 1.0f / mass + 1.0f / a.mass); a.curPos += penDir * penDepth * ( 1.0f / a.mass) / ( 1.0f / mass + 1.0f / a.mass);
только вижу, у тебя коллижн сделан примерно так:
void Particle::Collide(Particle &other)
это плохо. я бы советовал сразу сделать
void Collision::Solve()
или хотя бы
static void Particle::SolveCollision(Particle *particle1, Particle *particle2)
MarkoPolo
> Вообще, метод ведь нормально подходит для частиц разного размера?
да, вполне. из радиуса частицы высчитываешь массу и выталкиваешь частицу на расстояние, обратно пропорциональное её массе.
Suslik
> неверно. на твоём примере нужно как-то так:
ммм... я из этих уравнений как раз и вывел свои...
Вот это:
curPos -= penDir * penDepth * (1.0f / mass) / ( 1.0f / mass + 1.0f / a.mass);
Как раз и переходит в это:
curPos-=penDir*penDepth*a.mass/(mass+a.mass);
Suslik
> тебя коллижн сделан примерно так:
Да, так. А чем
void Collision::Solve();
Лучше?
MarkoPolo
> ммм... я из этих уравнений как раз и вывел свои...
>
> Вот это:
> curPos -= penDir * penDepth * (1.0f / mass) / (1.0f / mass + 1.0f / a.mass);
> Как раз и переходит в это:
> curPos-=penDir*penDepth*a.mass/(mass+a.mass);
да, действительно переходит. просто обычно удобнее работать с величинами, обратными массе(1 / mass). например, чтобы задать бесконечно тяжёлое тело, ставишь ему invMass в ноль.
> Да, так. А чем
> void Collision::Solve();
> Лучше?
ну хотя бы тем, что в промежуточной структуре для коллижна можно хранить какую-то дополнительную информацию(отскоки, трения), строить коллижн-графы, и вообще подход "столкнуть частицы A и B" мне видится более логичным, чем подход "столкнуть частицу B с частицей A".
Тема в архиве.