Pull to refresh

Java/Scala программа, имитирующая анимацию капель дождя

Reading time2 min
Views2.9K

Видео:

Данную заметку, наверное, следует воспринимать больше как отзыв о библиотеке org.fxyz3d, так как сама программа совсем простая.

В прошлом выпуске "Slicer: нарезка твердотельных объектов под раскрой" я упоминал интересный предмет интерьера, который весьма мне приглянулся:

Несмотря на то, что до этого я не встречался с ruby, я набросал программулину которая на выходе давала поверхность вида:

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

Вместо этого, я ловко создал новую, более лучшую программу на java/scala на 120 строк, которая мало того что рисует такую сетку двух волн, так еще сдвигает по таймеру фазы этих волн, чем имитирует анимацию (см. ролик). Используется библиотека org.fxyz3d

В это время можно крутить камеру мышкой, и перемещать ее с клавиатуры по WASD.

В общем-то, в коде все просто, но пару комментариев дам:

  • Очень удобно, что можно отнаследоваться от класса ShapeBaseSample, который является дженериком. Не очень удобно, что org.fxyz3d.samples нет внутри библиотеки (можно было просто создать еще 1 артефакт), и приходится все это хозяйство руками копировать в проект.

  • Еще более неудобно, что встроенное поведение обработки клавиатуры при наследовании почему-то ломается (возможно только в scala). На починку ушло время.

  • Координата Z задается функцией на основе координат текущей точки и координат двух центров колебаний:

def z(x:Int,y:Int):Float = {
       (Math.cos(-t+Math.sqrt(pow(ox1 - x,2)  + pow(oy1 - y,2)) / 5 * 2 * 3.14) * 5 * (Math.max(0,1-Math.sqrt(pow(ox1 - x,2) + pow(oy1 - y,2))/30))
      + Math.cos(-t+Math.sqrt(pow(ox2 - x,2)  + pow(oy2 - y,2)) / 5 * 2 * 3.14) * 4 * (Math.max(0,1-Math.sqrt(pow(ox2 - x,2) + pow(oy2 - y,2))/30))).toFloat
  }

Это косинус, параметром которого является расстояние до центра колебаний (плюс временное смещение), которое вычисляется банально по теореме Пифагора c = sqrt(a^2+b^2).

В формулу добавлен коэф. линейного затухания, который равен 1 в центре колебаний, и 0 в достаточном удалении (30).

  • В качестве коллекций хранения сетки высот и линий неспроста выбраны мапы. Дело в том, что я рассчитывал оптимизировать производительность программы путем переиспользования объектов (для чего ссылки на них должны храниться), но это оказалось напрасным. Дело в том, что замещение списка точек PolyLine3D не влияет на его отражение на экране - при создании он уже породил дочерние объекты Mesh и пересоздавать их не намерен.

  • Впрочем, это все не занимает практически никакого времени - затык в методе Scene.getChildren.addAll(...). На 30*30 точках анимация видна, а кадр 100*100 уже рисуется несколько секунд. Это неприемлемо.

Приходится признать, что библиотека org.fxyz3d не слишком-то пригодна для работы с морфингом объектов в реальном времени, что стало для меня некоторыми разочарованием.

Возможно, кто-то умеет ее правильно готовить, но пока думаю посмотреть что-то другое, если в будущем возникнет необходимость.

Tags:
Hubs:
Total votes 5: ↑2 and ↓3-1
Comments0

Articles