Главная » Статьи » Учебник: практика

Hellow World!
Итак мы напишем нашу самую первую программу на Панде с использованием питона - типичный Hellow world.

Программа, которую мы напишем будет загружать небольшую сцену и анимированную модель панды.

Для начала создадим текстовой файл с расширением .py . Если вы хотите использовать кириллические символы в тексте и комментариях, то необходимо чтобы файл был в кодировке utf-8. Напишем следующие строчки в нашем файле:

Код

from direct.showbase.ShowBase import ShowBase

class MyApp(ShowBase):
   
  def __init__(self):
  ShowBase.__init__(self)

app = MyApp()
app.run()


Импортирование ShowBase загружает большинство необходимых модулей панды и подготавливает окно к выводу изображения. Run - подпрограмма, содержащая главный цикл Panda3D. В ней отрисовывается кадр и выполняются фоновые задачи, после чего цикл повторяется. Эта подпрограмма должна быть вызвана единожды в конце вашего скрипта. В этом примере сцена не содержит данных для отрисовки, поэтому мы увидим пустое серое окно.

Для запуска програмы наберите в командной строке:

python filename.py

Большинство специализированных редакторов позволяют запускать скрипт прямо из окна редактирования. Если всё было сделано правильно, мы должны увидеть серое окно с заголовком Panda. Пока мы ничего не можем в нём сделать, однако это недолго изменить.

Теперь загрузим небольшую демонстрационную сцену, для этого изменим код следующим образом:

Код

from direct.showbase.ShowBase import ShowBase
   
class MyApp(ShowBase):
   
  def __init__(self):
  ShowBase.__init__(self)
   
  # Загрузка модели.
  self.scene = self.loader.loadModel("models/environment")
  # Прицепляем модель к узлу рендера.
  self.scene.reparentTo(self.render)
  # Устанавливаем масштаб и позицию для модели.
  self.scene.setScale(0.25, 0.25, 0.25)
  self.scene.setPos(-8, 42, 0)
   
   
app = MyApp()
app.run()


Команда loader.loadModel() загружает указанный файл. Расширение файла указывать не обязательно. Поиск файла модели будет производиться сначала по указанному пути, а если ничего не найдено, то в model path, прописанном в конфигурационном файле (как в данном случае). Возвращаемое значение 'NodePath', указатель на модель. Обратите внимание, в имени файла используются прямые слеши даже под Windows.

Panda3D содержит структуру данных, называемую scene graph. Scene graph это дерево, содержащее все модели, которые необходимо выводить на экран. Корень этого дерева - объект, называемый render. Объекты не помещённые в граф сцены не будут выведены на экран.

Для перемещения нашей модели в граф сцены мы используем метод reparentTo. Этим методом мы устанавливаем родителя нашего объекта, тем самым помещая его в граф сцены, что делает его видимым.

В завершение мы изменяем позицию и масштаб модели.
Попробуйте запустить программу.
По умолчанию Панда запускает задачу, которая позволяет управлять камерой с помощью мыши:
Левая кнопка: перемещение вправо-влево
Правая кнопка: назад-вперёд
Средняя: вращение вокруг центра сцены
Правая и средняя: вращение по оси взгляда
Попробуйте - вам станет ясно, что это не самый удобный способ управления камерой.
Взамен, мы напишем задачу (task) которая напрямую будет контролировать камеру. Задача (task) - это подпрограмма, вызываемая каждый цикл прорисовки, либо через заданный промежуток времени. Изменим наш код:

Код

from math import pi, sin, cos
   
from direct.showbase.ShowBase import ShowBase
from direct.task import Task
   
class MyApp(ShowBase):
  def __init__(self):
  ShowBase.__init__(self)
   
  # Загрузка моделиl.
  self.scene = self.loader.loadModel("models/environment")
  # Прицепляем модель к узлу рендера.
  self.scene.reparentTo(self.render)
  # Устанавливаем масштаб и позицию для модели.
  self.scene.setScale(0.25, 0.25, 0.25)
  self.scene.setPos(-8, 42, 0)
   
  # Добавляем в менеджер задач, запуск функции.
  self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
   
  # Функция которая обрабатывает управление камерой.
  def spinCameraTask(self, task):
  angleDegrees = task.time * 6.0
  angleRadians = angleDegrees * (pi / 180.0)
  self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
  self.camera.setHpr(angleDegrees, 0, 0)
  return Task.cont
   
app = MyApp()
app.run()


Функция taskMgr.add указывает менеджеру задач панды, что нужно каждый цикл вызывать подпрограмму SpinCameraTask . Это подпрограмма, которую мы написали для управления камерой. До тех пор, пока подпрограмма SpinCameraTask возвращает константу Task.cont, менеджер задач будет продолжать выполнять её каждый кадр.

Наша подпрограмма вычисляет необходимую позицию камеры, основанную на прошедшем времени.Камера поворачивается на 6 градусов в секунду . Первые две строчки вычисляют желаемую ориентацию камеры - первая в градусах, вторая в радианах. SetPos устанавливает новую позицию камеры. SetHpr - ориентацию камеры. Замечание: SetPos и SetHpr- методы, наследованные от nodePath - подробнее об этом в главе про Граф сцены.

Теперь загрузим анимированного персонажа — допишем код:

Код

from math import pi, sin, cos
   
from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.actor.Actor import Actor
   
class MyApp(ShowBase):
  def __init__(self):
  ShowBase.__init__(self)
   
  # Загрузка модели.
  self.scene = self.loader.loadModel("models/environment")
  # Прицепляем модель к узлу рендера.
  self.scene.reparentTo(self.render)
  # Устанавливаем масштаб и позицию для модели.
  self.scene.setScale(0.25, 0.25, 0.25)
  self.scene.setPos(-8, 42, 0)
   
  # Добавляем в менеджер задач, запуск функции.
  self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
   
  # Загрузка модели актера и анимации ходьбы.
  self.pandaActor = Actor("models/panda-model",
  {"walk": "models/panda-walk4"})
  self.pandaActor.setScale(0.005, 0.005, 0.005)
  self.pandaActor.reparentTo(self.render)
  # Loop its animation.
  self.pandaActor.loop("walk")
   
  # Функция которая обрабатывает управление камерой.
  def spinCameraTask(self, task):
  angleDegrees = task.time * 6.0
  angleRadians = angleDegrees * (pi / 180.0)
  self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
  self.camera.setHpr(angleDegrees, 0, 0)
  return Task.cont
   
app = MyApp()
app.run()


Класс Actor предназначен для анимированных моделей. Мы используем loadModel для статических моделей, и Actor только если они анимированы. Два аргумента конструктора класса Actor — первый - имя файла, содержащего модель, второй — словарь, содержащий записи о файлах анимации.

Команда loop("walk") запускает анимацию на циклическое воспроизведение. В результате модель панды топчется на месте.

Следующим шагом мы заставим панду перемещаться назад-вперёд:

Код

from math import pi, sin, cos
   
from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import Sequence
from panda3d.core import Point3
   
class MyApp(ShowBase):
  def __init__(self):
  ShowBase.__init__(self)
   
  # Отключаем управление камерой которое было создано ShowBase.
  self.disableMouse()
   
  # Загрузка модели.
  self.scene = self.loader.loadModel("models/environment")
  # Прицепляем модель к узлу рендера.
  self.scene.reparentTo(self.render)
  # Устанавливаем масштаб и позицию для модели.
  self.scene.setScale(0.25, 0.25, 0.25)
  self.scene.setPos(-8, 42, 0)
   
  # Добавляем в менеджер задач, запуск функции.
  self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
   
  # Загрузка модели актера и анимации ходьбы.
  self.pandaActor = Actor("models/panda-model",
  {"walk": "models/panda-walk4"})
  self.pandaActor.setScale(0.005, 0.005, 0.005)
  self.pandaActor.reparentTo(self.render)
  # Зацикливаем анимацию.
  self.pandaActor.loop("walk")
   
  # Создаем интервал для изменения позиции за 13 секунд.
  # Так же создаем интервал для изменение ориентации за 3 секунды.
  # Для имитации ходьбы, вперед и назад, а так же разворот на 180 градусов.  
  pandaPosInterval1 = self.pandaActor.posInterval(13,
  Point3(0, -10, 0),
  startPos=Point3(0, 10, 0))
  pandaPosInterval2 = self.pandaActor.posInterval(13,
  Point3(0, 10, 0),
  startPos=Point3(0, -10, 0))
  pandaHprInterval1 = self.pandaActor.hprInterval(3,
  Point3(180, 0, 0),
  startHpr=Point3(0, 0, 0))
  pandaHprInterval2 = self.pandaActor.hprInterval(3,
  Point3(0, 0, 0),
  startHpr=Point3(180, 0, 0))
   
  # Создадим секвенцию для поочередного выполнения интервалов.
  self.pandaPace = Sequence(pandaPosInterval1,
  pandaHprInterval1,
  pandaPosInterval2,
  pandaHprInterval2,
  name="pandaPace")
  self.pandaPace.loop()
   
  # Функция которая обрабатывает управление камерой.
  def spinCameraTask(self, task):
  angleDegrees = task.time * 6.0
  angleRadians = angleDegrees * (pi / 180.0)
  self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
  self.camera.setHpr(angleDegrees, 0, 0)
  return Task.cont
   
app = MyApp()
app.run()


Интервалы (interval) — это фоновые задачи (tasks) которые меняют параметры от одного значения к другому в течение заданного времени. Например, рассмотрим pandaPosInterval1. Когда интервал запущен он постепенно меняет позицию панды от (0,10,0) до (0,-10,0) за период в 13 секунд. Аналогично pandaHprInterval1 меняет ориентацию — поворачивает панду на 180 градусов в течение 3 секунд.

Последовательность (Sequences) — задача, которая запускает интервалы один за другим. PandaPace — последовательность, которая перемещает панду по прямой, затем разворачивает на 180 градусов и перемещает обратно, и снова поворачивает. PandaPace.loop() стартует последовательность в режиме цикла.

В результате наша панда должна перемещаться между деревьями туда-сюда.

Источник: https://www.panda3d.org/manual/?title=A_Panda3D_Hello_World_Tutorial
Категория: Учебник: практика | Добавил: ninth (28.01.2009)
Просмотров: 14156 | Комментарии: 5 | Рейтинг: 4.4/9
Всего комментариев: 5
1 Nikolay  
0
То что надо для таких как я ! wacko

2 AlexFenix  
0
Крутой сайт! Как раз вот питоном увлёкся, очень гибкий язык. Теперь вот захотелось создать чё-нить 3d-шное. Спасибо за статью! biggrin

3 AHIMEwHIK  
0
  • У меня в 40-й строке синтаксическую ошибку. Программа показывает ошибку в "=" в отрезке "name = "pandaPace"". В чем может быть причина?

  • 4 ninth  
    1
    Я ошибку воспроизвести не могу - после копирования кода и вставки в редактор всё работает. Желательно привести полный текст ошибки.

    5 Mafia  
    0
    Интересно . Только плохо что всё через коддинг. Была бы студия , было бы полегче))

    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]
    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0