Я пытаюсь оживить вращающийся куб. Для этого я использую Poly3DCollection и анимирую его с помощью FuncAnimation:
anim = animation.FuncAnimation(fig, visualize_rotation, fargs=[collection],
init_func=partial(init_func, ax, collection),
frames=360, interval=1000 / 30)
Но он рендерит каждый кадр очень медленно, так что я получаю всего несколько кадров в секунду. Чтобы исправить это, я попытался добавить параметр blit=True
в надежде, что это улучшит скорость рендеринга, но таким образом я не вижу куб.
Как ни странно куб виден при сохранении фигуры. Вот результат, который я получаю:
Я убедился, что visualize_rotation
возвращает список художников [collection]
, который требуется blit=True
, как указано в этот вопрос, но куб по-прежнему не виден.
Итак, как я могу использовать флаг blit
в этом случае, имея возможность видеть куб во время анимации?
Полный код:
import math
from functools import partial
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
def visualize_rotation(frame, collection):
angle = math.radians(2) * frame
points = np.array([[-1, -1, -1],
[1, -1, -1],
[1, 1, -1],
[-1, 1, -1],
[-1, -1, 1],
[1, -1, 1],
[1, 1, 1],
[-1, 1, 1]])
Z = np.zeros((8, 3))
for i in range(8):
Z[i, :] = [
math.cos(angle) * points[i, 0] - math.sin(angle) * points[i, 1],
math.sin(angle) * points[i, 0] + math.cos(angle) * points[i, 1],
points[i, 2]
]
Z = 10.0 * Z
# list of sides' polygons of figure
vertices = [[Z[0], Z[1], Z[2], Z[3]],
[Z[4], Z[5], Z[6], Z[7]],
[Z[0], Z[1], Z[5], Z[4]],
[Z[2], Z[3], Z[7], Z[6]],
[Z[1], Z[2], Z[6], Z[5]],
[Z[4], Z[7], Z[3], Z[0]]]
# plot sides
collection.set_verts(vertices)
print(frame)
return [collection]
def init_func(ax, collection):
ax.set_xlim(-15, 15)
ax.set_ylim(-15, 15)
ax.set_zlim(-15, 15)
ax.set_box_aspect(np.ptp([ax.get_xlim(), ax.get_ylim(), ax.get_zlim()], axis=1))
return [collection]
def animate_rotation():
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', proj_type='persp')
collection = Poly3DCollection([[np.zeros(3)]], facecolors='white',
linewidths=1, edgecolors='r', alpha=0.8)
ax.add_collection3d(collection)
# noinspection PyUnusedLocal
anim = animation.FuncAnimation(fig, visualize_rotation, fargs=[collection],
init_func=partial(init_func, ax, collection),
frames=360, interval=1000 / 30, blit=True)
plt.show()
Редактировать:
Я добавил вычисление кадров в секунду и построил его:
timestamps = []
def visualize_rotation(frame, collection):
...
# plot sides
collection.set_verts(vertices)
global timestamps
timestamps.append(time.time())
print(round(1 / np.mean(np.diff(timestamps[-1000:])), 1))
return [collection]
def animate_rotation():
...
plt.plot(np.diff(timestamps))
plt.ylim([0, 0.1])
plt.show()
Вот что происходит, когда окно имеет нормальный размер и скорость рисования низкая (время в секундах по сравнению с номером кадра):
И это сюжет, когда окно крошечное:
Начало графика показывает изменение размера окна. Во втором случае было пропущено только 2 кадра (примерно 50 и 150), а общая частота кадров составляет около 30 кадров в секунду, как и хотелось. Я ищу такое же поведение, когда окно нормального размера. Когда я включаю blit
, график выглядит нормально, но проблема в том, что куб не виден.
blit=True
для меня. У вас значительно медленнее или вы просите увеличить эту скорость? - person Mr. T   schedule 11.02.2021interval=1000 / 30
). Одна вещь, которую я заметил, это то, что скорость зависит от размера фигуры. Если размер окна уменьшен до крошечного, то скорость анимации правильная, а анимация приятная и плавная. Но для размера окна по умолчанию это примерно в 2 раза медленнее. Поэтому прошу увеличить скорость. - person fdermishin   schedule 11.02.2021print(frame)
отображается в текущем код также был улучшен на ощупь. - person r-beginners   schedule 12.02.2021visualize_rotation
вызывается примерно 150 раз в секунду, но большинство кадров отбрасываются. Я не уверен, как функция инициализации может повлиять на скорость, потому что она вызывается только один раз. Я обновил вопрос, добавив графики частоты кадров. - person fdermishin   schedule 12.02.2021visualize_rotation
вовсе не является узким местом, потому что в среднем занимает 1 миллисекунду на кадр, но узким местом является рендеринг внутри matplotlib - person fdermishin   schedule 12.02.2021