Медленное вращение 3D с сглаживанием в Mathematica 7 - PullRequest
8 голосов
/ 21 августа 2011

3D вращение поверхности в Mathematica 7 с отключенным сглаживанием очень быстрое и плавное.Однако включение сглаживания даже на умеренном уровне резко снижает частоту кадров, что делает вращение очень прерывистым.Это происходит в гораздо большей степени в Mathematica , чем в других 3D-приложениях.

  1. Почему сглаживание непропорционально медленнее в Mathematica ?

  2. Способ значительно улучшить ощущение трехмерной графики - отключить АА во время вращения, но включить его, как только вращение будет остановлено.Можно ли это сделать в Mathematica 7?


Был запрошен пример.Я буду использовать вариацию кода Майка.Пожалуйста, попробуйте следующее с Edit > Preferences > Appearance > Graphics, сначала установив No antialiasing, а затем Highest quality.Также попробуйте настройки между ними.Для меня любая настройка, кроме No antialiasing, не является гладкой.Я могу визуально различать три разных уровня АА, поэтому мой GPU не заставляет всех или вообще ни одного, но все они медленные.

Animate[Plot3D[{x^2 + y^2, -x^2 - y^2}, {x, -2, 2}, {y, -2, 2},
  ImageSize -> 700,
  ViewPoint -> 
   Dynamic[{Sin[theta] Cos[phi], Sin[theta] Sin[phi], Cos[theta]}]],
 {theta, 0, Pi}, {phi, 0, 2 Pi},
 RefreshRate -> 120
]

ОБНОВЛЕНИЕ и НАБЛЮДЕНИЕ

Во время игры с кодом Алексея и Майка произошло нечто странное и хорошее.У меня вдруг плавное сглаженное вращение!Я не знаю, что ускорило изменение, и я не закрыл Mathematica из-за страха, что оно исчезнет, ​​но это доказывает то, что я подозревал, что оно МОЖЕТ быть быстрым.

Подробнеестранно, у меня медленное и быстрое поведение, происходящее параллельно в том же ноутбуке.Один рисунок вращается плавно, а другой, созданный с тем же кодом, прерывистый.Я предполагаю, что какой-то вариант ячейки был изменен при запуске кода Алексея и Майка, и это имеет очень желательный эффект.Я сделаю все возможное, чтобы выяснить, что это такое.


Полезными опциями были RotationAction -> "Clip", SphericalRegion -> True, которые случайно появились в коде Алексея.Они, или их эффект (ViewAngle), «прилипают» к графике так же, как это делает ротация, поэтому я смог набрать новый код без этих опций поверх старого, запустить его и получить плавное вращение.(что объясняет то, что я видел выше).Для получения дополнительной информации см. Ответы ниже.

Хотя был найден жизнеспособный обходной путь, меня все еще интересует объяснение прерывистого вращения с включенным АА.Я не верю, что «подгонка» графики - это объяснение, а всего лишь корреляция, поскольку подгонка все еще должна происходить при выключенном АА, и, тем не менее, вращение плавное.

Ответы [ 5 ]

7 голосов
/ 22 августа 2011

После того, как г-н Wizard указал, что изменение ViewAngle улучшило производительность, я догадывался, что его вызвало.

Обычно, когда вы поворачиваете графику в Mathematica, вы заметите, что окно, содержащее графику, изменяет свой размер при повороте изображения. Зачем? Для большинства настроек по умолчанию установлено значение Automatic, поэтому они пытаются поиграть, чтобы графика хорошо вписывалась в экран. В частности, Plot3D (и многие другие функции 3D Plot) имеют именованный параметр, называемый RotationAction. Согласно документации Mathematica :

3D-графика по умолчанию изменяет размеры и перемещается, чтобы соответствовать, когда они вращаются в интерактивном режиме

Этот параметр по умолчанию равен RotationAction->"Fit", который всегда пытается убедиться, что вся трехмерная графика помещается на экране. Вместо этого вы можете принудительно обрезать графику, используя RotationAction->"Clip". Это заставляет ограничивающий прямоугольник оставаться прежним. Вместо того, чтобы изменять размер, он просто отсекает все, что уходит с экрана. Производительность улучшена значительно , поскольку Mathematica не нужно постоянно изменять форму изображения, чтобы все поместилось на экране.

Пример кода:

Plot3D[{x^2 + y^2, -(x^2 + y^2)}, {x, -2, +2}, {y, -2, +2}, 
 ImageSize -> 700, RotationAction -> "Fit"]

Plot3D[{x^2 + y^2, -(x^2 + y^2)}, {x, -2, +2}, {y, -2, +2}, 
 ImageSize -> 700, RotationAction -> "Clip"]

Некоторые дальнейшие заметки

При дальнейшем анализе RotationAction->"Clip" изначально имеет некоторые проблемы с ротацией. При первом повороте графики она вращается очень быстро. Я не знаю, почему это так, только исследование Wolfram могло бы ответить на этот вопрос. Однако после первоначального вращения он вращается с нормальной скоростью, как и любая другая графика.

Самый плавный способ совершить для меня приятное вращение был дан:

 Plot3D[..., RotationAction -> "Clip", ViewAngle -> 0.4]

Это максимально близко к объему отсечения по умолчанию, без каких-либо странных проблем с быстрым вращением или обрезкой графики.

3 голосов
/ 21 августа 2011

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

Mouseover[
 Style[
  Graphics[Circle[]],
  Antialiasing \[Rule] True
  ],
 Style[
  Graphics[Circle[]],
  Antialiasing \[Rule] False
  ]
 ]

К сожалению, я понятия не имею, как можно включать и выключать сглаживание, и я не знаю, как сделать что-то вроде Plot[f,range,Option->Mouseover[1,2]].

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

Может быть, кто-то, кто лучше понимает динамические конструкции, может решить, как использовать инфраструктуру, которая позволяет Mouseover делать свое дело для решения вашей проблемы.

3 голосов
/ 22 августа 2011

Основано на идее acl:

EventHandler[
 Plot3D[{x^2 + y^2, -x^2 - y^2}, {x, -2, 2}, {y, -2, 2}, 
  ImageSize -> 700, RotationAction -> "Clip", 
  SphericalRegion -> 
   True], {"MouseUp" :> (SetOptions[$FrontEndSession, 
     RenderingOptions -> {"HardwareAntialiasingQuality" -> 1.}]), 
  "MouseClicked" :> (SetOptions[$FrontEndSession, 
     RenderingOptions -> {"HardwareAntialiasingQuality" -> 1.}]), 
  "MouseDown" :> (SetOptions[$FrontEndSession, 
     RenderingOptions -> {"HardwareAntialiasingQuality" -> 0.}])}, 
 PassEventsDown -> True]

Вы можете увидеть, что происходит с опцией:

Dynamic["HardwareAntialiasingQuality" /. 
  Last@Last@Options[$FrontEnd, RenderingOptions], 
 UpdateInterval -> .1]

Как это работает: он отключает сглаживание для текущего сеанса FrontEnd при повороте графика и включает его при отпускании мыши. Единственная проблема состоит в том, что когда мышь отпущена и сглаживание включено, FrontEnd не визуализирует графику снова, чтобы сделать ее сглаженной. Решение состоит в том, чтобы щелкнуть график, не поворачивая его - и он становится сглаженным!

3 голосов
/ 21 августа 2011

Опираясь на ответ Алексея, я немного изменил код, чтобы он не изменил настройки внешнего интерфейса:

aa = True;
EventHandler[
 Style[
  Plot3D[{x^2 + y^2, -(x^2 + y^2)}, {x, -2, +2}, {y, -2, +2}, 
   ImageSize -> 700, RotationAction -> "Clip", 
   SphericalRegion -> True],
   Antialiasing -> Dynamic[aa, TrackedSymbols :> {aa}]],
 {"MouseUp" :> (aa = True), "MouseDown" :> (aa = False)}, 
 PassEventsDown -> True]

Он выполняет то же самое, но избегает изменения $ FrontEnd.

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

Clear[DynamicAA]; (* Perhaps I should also add the HoldFirst attribute too, not sure *)
DynamicAA[graphics_] := Module[{aa},
  aa = True;
  EventHandler[
   Style[graphics, 
    Antialiasing -> Dynamic[aa, TrackedSymbols :> {aa}]], {"MouseUp" :> (aa = True), 
    "MouseDown" :> (aa = False)}, PassEventsDown -> True]]

Использование - это то, что вы ожидаете:

DynamicAA[Plot3D[{x^2 + y^2, -x^2 -y^2}, {x, -2, +2}, {y, -2, +2}, ImageSize->700]]
2 голосов
/ 22 августа 2011

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

Волшебная опция ViewAngle. Любое числовое значение работает; Automatic нет.

Оценивая приведенный ниже код, первая графика плохо вращается, а вторая - плавно.

Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, ImageSize -> 900]

Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}, ImageSize -> 900, ViewAngle -> 0.43]

У меня проблема с методом RotationAction -> "Clip" Майка, в котором я получаю неожиданные, а иногда и экстремальные обрезки при повороте графики. Однако добавление SphericalRegion -> True восстанавливает поведение, которое я получаю с ViewAngle, и угол выбирается автоматически:

Plot3D[{x^2 + y^2, -(x^2 + y^2)}, {x, -2, +2}, {y, -2, +2}, 
 ImageSize -> 700, SphericalRegion -> True, RotationAction -> "Clip"]
...