Добавлен , опубликован

Кривая Безье

Я не буду расписывать какую-либо статью про кривые, какие они бывают, когда кем придуманы и прочую ерунду, ибо в этом нет смысла, всё уже давно разжёвано максимально понятным образом. В самом низу находятся источники, я просто покидаю примеры для понимания. Так же, на хайве есть векторная наработка по кривым с алгоритмом Де Кастельжо:

Зачем?

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

Треугольник Паскаля

Для прямого метода нужен треугольник Паскаля:
Делается просто:
    private static hashtable PascalTriangle = InitHashtable( )
    private static integer PascalTriangleRows = 2

    static method RegistPascalTriangle takes integer i returns nothing
        local integer n
        local integer k
        
        if i > PascalTriangleRows then
            set n = PascalTriangleRows
            
            loop
                set k = 0
                
                loop
                    call SaveInteger( PascalTriangle, n, k, LoadInteger( PascalTriangle, n - 1, k - 1 ) + LoadInteger( PascalTriangle, n - 1, k ) )
                    
                    set k = k + 1
                    exitwhen k > n
                endloop
                
                set n = n + 1
                exitwhen n > i
            endloop
        
            set PascalTriangleRows = i
        endif
    endmethod
    
    static method onInit takes nothing returns nothing
        call SaveInteger( PascalTriangle, 0, 0, 1 )
        call SaveInteger( PascalTriangle, 1, 0, 1 )
        call SaveInteger( PascalTriangle, 1, 1, 1 )
    endmethod
Можно естественно воспользоваться двумерным массивом примерно 7х7, чтобы покрыть практически все нужды и не занимать хэштаблицу, единственная проблема, что массивность двумерных должна быть определена заранее в вджассе, т.е. если есть динамическая фигня и вдруг в игре поднадобилось 8х8+ размерность, то всё сломается

Построение кривой

call RegistPascalTriangle( count )

set i = 0

loop
	set r = LoadInteger( PascalTriangle, count - 1, i ) * Pow( 1.00 - time, count - 1 - i ) * Pow( time, i )
            
	set x1 = x1 + r * x[i]
	set y1 = y1 + r * y[i]
	set z1 = z1 + r * z[i]
            
	set i = i + 1
	exitwhen i >= count
endloop
count - количество опорных точек
time - фактор кривой, т.е. нормализированная величина (от 0.00 до 1.00)
x1, y1, z1 - искомая точка
x[ ], y[ ], z[ ] - опорные точки
r - полином, т.е. сама конструкция кривой

Оптимизация

Чтобы исключить факториалы и треугольники Паскаля, можно воспользоваться алгоритмом Де Кастельжо:
set k = 0

loop
	set i = 0
	
	loop
		set x[i] = ( 1.00 - time ) * x[i] + time * x[i + 1]
		set y[i] = ( 1.00 - time ) * y[i] + time * y[i + 1]
		set z[i] = ( 1.00 - time ) * z[i] + time * z[i + 1]
		
		set i = i + 1
		exitwhen i > count - k
	endloop
	
	set k = k + 1
	exitwhen k >= count - 1
endloop
В данном случае опорные точки нужно скопировать, чтобы сохранить основные
В чём преимущества первого метода по сравнению с этим алгоритмом мне не известны

Прикладываю карту с этими способами


`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
11
Мне необходимо было разобраться как динамически добавлять больше 4 опорных
Не очень проблематику понял. Можно поподробнее про подводные камни.
38
Безье - наше всё!
P.S. В wGeometry тоже есть Functions.bezier = function(p0, p1, p2, amount) и Functions.hermite = function(value1, tangent1, value2, tangent2, amount)

p.p.s 1.00 - time обычно выносят в переменную для оптимизации в языках, где нет оптимизации при компиляции
33
Надо тоже обмазаться вашим безьё, из каждого утюга о нём кричите
28
Не очень проблематику понял. Можно поподробнее про подводные камни.
тяжело было найти хоть где-либо пример полиномы для 5 опорных точек, везде только 4:
P0 * (1-t)^3 + P1 * t * (1-t)^2 + P2 * t^2 * (1-t) + P3 * t^3
у меня была попытка пихнуть сюда как-нибудь 5 опорную точку, пришлось изучать, оказывается там ещё треугольник паскаля нужен, ну и появился этот недоресурс
я с математикой не дружу, поэтому если ты и видишь в этом бесполезность, т.к. ты гений, миллиардер, плейбой, филантроп (завидую белой завистью), то для людей вроде меня может и не быть настолько бесполезным, естественно есть куча всяких наработок уже, опять же, хайв, который указан в самом начале и по сути на этом моменте страничку можно закрывать, ну и от ScorpioT1000 3д библиотека, где тоже оказывается есть безье
если вбить в поиск хгм или гугла по хгм слово безье, то можно наткнуться на мою старую статью в блоге с 3 точками, на работы в мдлвисе с анимациями и какие-то комментарии, где и удалось найти ссылку на хайв
27
Соглашусь с выше мнением. У Скорпа есть библиотека, но ей очень сложна воспользоваться из за очень непонятных параметров

Берги, давай)) сальтухи пеоны еаучатся делать красивые при разбеге
38
МрачныйВорон, а что непонятного. Есть множество точек в одномерном пространстве и есть volume (сила от 0 до 1 или больше). Для многомерного у векторов wGeometry есть метод или просто применить функцию к каждой компоненте векторов.
Гифка выше наглядно показывает силу (оно же время в его случае). Просто время в математике не значит физическое время, а скорее что угодно, равномерно наростающее

    -- Applies bezier spline interpolation
    --- @param p2 Vector3 point 2
    --- @param p3 Vector3 point 3
    --- @param amount current animation state, number between 0 and 1
    --- @return Vector3 result
    bezier = function(self, p2, p3, amount)
      return Vector3:new(
        Functions.bezier(self.x, p2.x, p3.x, amount),
        Functions.bezier(self.y, p2.y, p3.y, amount),
        Functions.bezier(self.z, p2.z, p3.z, amount)
      )
    end
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.