Python для 3D: от базовой визуализации до продвинутых техник

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Студенты и начинающие программисты, желающие изучить Python и 3D графику
  • Профессиональные разработчики, ищущие новые инструменты для создания 3D приложений
  • Исследователи и ученые, интересующиеся визуализацией научных данных с помощью Python

    Python — язык, преодолевший путь от скриптового решения до полноценной платформы для разработки высокопроизводительной 3D графики. Создание трехмерных визуализаций, от простых моделей до интерактивных сцен и реалистичных рендеров, становится доступным каждому, кто владеет базовыми концепциями этого языка. Изящество кода Python в сочетании с мощными графическими библиотеками открывает безграничные возможности для проектов любого масштаба — от научной визуализации данных до игровых прототипов и архитектурных презентаций. 🚀

Погружение в мир 3D графики с Python требует системного подхода к обучению. Курс Обучение Python-разработке от Skypro построен именно на этих принципах. Здесь вы не просто изучите синтаксис — вы освоите промышленные методологии создания высоконагруженных приложений, включая работу с графическими API. Практические кейсы от реальных компаний и наставничество опытных разработчиков сделают ваш путь к 3D-визуализации максимально эффективным.

Python и 3D графика: обзор возможностей и применений

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

Ключевые области применения Python для 3D графики включают:

  • Научная визуализация — визуальное представление многомерных данных, молекулярных структур, физических явлений
  • Компьютерные игры — создание игровых прототипов, инструментов разработки, редакторов уровней
  • Моделирование и анимация — автоматизация рабочих процессов в 3D-редакторах, создание параметрических моделей
  • Дополненная и виртуальная реальность — прототипирование AR/VR-приложений, обработка пространственных данных
  • Архитектурная визуализация — генеративная архитектура, параметрическое моделирование зданий

Преимущества Python перед специализированными языками программирования 3D заключаются в низком пороге вхождения, обширной документации и кроссплатформенности. В отличие от C++ или GLSL, Python позволяет быстро создавать прототипы без погружения в сложности управления памятью или графическим конвейером.

Критерий Python для 3D C++ для 3D JavaScript (WebGL)
Скорость разработки Высокая Низкая Средняя
Производительность Средняя (с оптимизациями) Высокая Средняя
Кривая обучения Пологая Крутая Средняя
Экосистема Обширная Фрагментированная Растущая
Интеграция с наукой о данных Превосходная Ограниченная Ограниченная

Михаил Соколов, технический директор проекта визуализации научных данных Наша команда столкнулась с необходимостью визуализировать результаты астрофизических симуляций в трехмерном пространстве. Данные представляли собой облака частиц, взаимодействующих по сложным законам. Первоначально мы использовали специализированные решения на C++, но итеративная разработка занимала недели.

Переход на Python с VTK и NumPy радикально изменил ситуацию. Время разработки сократилось в 5-7 раз. Мы создали интерактивную визуализацию, позволяющую исследователям манипулировать параметрами симуляции в реальном времени и наблюдать результаты. Особенно полезным оказалось сочетание 3D-визуализации с аналитическими возможностями библиотек машинного обучения — мы смогли внедрить алгоритмы кластеризации для автоматического выделения интересующих структур в облаках частиц.

Производительность немного страдала по сравнению с C++, но выигрыш в скорости разработки и простоте поддержки решения с лихвой компенсировал эти недостатки.

Пошаговый план для смены профессии

Ключевые библиотеки Python для создания 3D графики

Экосистема Python предлагает богатый выбор библиотек для работы с 3D графикой, каждая из которых имеет свою область применения и особенности. Выбор правильного инструмента критичен для успеха проекта и зависит от конкретных требований и контекста использования. 🛠️

Рассмотрим наиболее значимые библиотеки Python для 3D графики:

Библиотека Уровень абстракции Оптимальное применение Сложность освоения Производительность
PyOpenGL Низкий Прямой доступ к GPU, специализированные визуализации Высокая Высокая
Panda3D Высокий Игры, интерактивные симуляции, образовательные приложения Средняя Средняя
Pyglet Средний Простые приложения, прототипы, образовательные проекты Низкая Средняя
VTK Высокий Научная визуализация, медицинские приложения Высокая Высокая
PyVista Высокий 3D анализ геометрии, упрощенная обертка для VTK Средняя Средняя
Mayavi Высокий Научная визуализация с интеграцией NumPy/SciPy Средняя Средняя
Blender Python API Высокий Автоматизация моделирования, пакетная обработка 3D Средняя Высокая
Pygame Средний 2D игры с элементами 3D, учебные проекты Низкая Низкая для 3D

PyOpenGL предоставляет Python-привязки к OpenGL API, что обеспечивает низкоуровневый доступ к функциям графической библиотеки. Это требует глубокого понимания работы графического конвейера, но даёт полный контроль над рендерингом.

Пример базового кода с использованием PyOpenGL:

Python
Скопировать код
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

vertices = (
(1, -1, -1),
(1, 1, -1),
(-1, 1, -1),
(-1, -1, -1),
(1, -1, 1),
(1, 1, 1),
(-1, -1, 1),
(-1, 1, 1)
)

edges = (
(0,1), (0,3), (0,4),
(2,1), (2,3), (2,7),
(6,3), (6,4), (6,7),
(5,1), (5,4), (5,7)
)

def draw_cube():
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(vertices[vertex])
glEnd()

def main():
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0, 0.0, -5)

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()

glRotatef(1, 3, 1, 1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
draw_cube()
pygame.display.flip()
pygame.time.wait(10)

if __name__ == "__main__":
main()

Panda3D — это игровой движок с высокоуровневым API, который скрывает многие сложности 3D-программирования. Отлично подходит для создания полноценных 3D-приложений без необходимости глубокого понимания компьютерной графики.

VTK (Visualization Toolkit) специализируется на научной визуализации и обработке 3D-данных. Идеален для медицинских приложений, CFD-визуализации и других научных областей, где требуется работа со сложными объемными данными.

Blender Python API позволяет автоматизировать задачи в популярном 3D-редакторе Blender, создавать плагины и расширения. Это мощный инструмент для пакетной обработки 3D-моделей и автоматизации рендеринга.

Базовые принципы работы с 3D объектами в Python

Эффективная работа с трехмерной графикой в Python требует понимания фундаментальных концепций, которые лежат в основе всех библиотек для 3D визуализации. Независимо от выбранного инструмента, определенные принципы остаются неизменными. 📐

Ключевые концепции 3D графики в Python включают:

  • Координатные системы — определение положения объектов в трехмерном пространстве
  • Геометрические примитивы — базовые формы, из которых строятся сложные объекты
  • Освещение и материалы — определение внешнего вида объектов при взаимодействии со светом
  • Камера и проекция — настройка точки обзора и преобразование 3D в 2D для отображения
  • Трансформации — перемещение, вращение и масштабирование объектов

Рассмотрим базовые структуры данных, используемые для представления 3D геометрии:

Python
Скопировать код
import numpy as np

# Представление вершины в 3D пространстве
vertex = np.array([1\.0, 2.0, 3.0])

# Представление треугольника через три вершины
triangle = np.array([
[0\.0, 0.0, 0.0], # вершина 1
[1\.0, 0.0, 0.0], # вершина 2
[0\.5, 1.0, 0.0] # вершина 3
])

# Нормаль к поверхности треугольника
edge1 = triangle[1] – triangle[0]
edge2 = triangle[2] – triangle[0]
normal = np.cross(edge1, edge2)
normal = normal / np.linalg.norm(normal) # нормализация вектора

print(f"Нормаль к треугольнику: {normal}")

Работа с матрицами трансформации — фундаментальный аспект 3D графики. В Python для этого часто используется библиотека NumPy:

Python
Скопировать код
import numpy as np

def create_rotation_matrix_y(angle_degrees):
"""Создает матрицу вращения вокруг оси Y"""
angle_radians = np.radians(angle_degrees)
cos_theta = np.cos(angle_radians)
sin_theta = np.sin(angle_radians)

# Создание матрицы 4x4 для вращения вокруг Y
matrix = np.array([
[cos_theta, 0, sin_theta, 0],
[0, 1, 0, 0],
[-sin_theta, 0, cos_theta, 0],
[0, 0, 0, 1]
])
return matrix

def create_translation_matrix(dx, dy, dz):
"""Создает матрицу перемещения"""
matrix = np.array([
[1, 0, 0, dx],
[0, 1, 0, dy],
[0, 0, 1, dz],
[0, 0, 0, 1]
])
return matrix

# Пример применения трансформаций
point = np.array([1, 2, 3, 1]) # Однородные координаты
rotation = create_rotation_matrix_y(45)
translation = create_translation_matrix(5, 0, 0)

# Композиция трансформаций (сначала вращение, затем перемещение)
transform = translation @ rotation
transformed_point = transform @ point

print(f"Исходная точка: {point[:3]}")
print(f"Преобразованная точка: {transformed_point[:3]}")

Освещение — ключевой аспект реалистичного рендеринга. Базовая модель освещения Фонга может быть реализована следующим образом:

Python
Скопировать код
def phong_lighting(normal, view_dir, light_dir, material_color, light_color,
ambient_coef=0.1, diffuse_coef=0.7, specular_coef=0.2, shininess=32):
"""
Рассчитывает цвет пикселя по модели освещения Фонга

normal: нормализованная нормаль к поверхности
view_dir: нормализованный вектор направления взгляда
light_dir: нормализованный вектор направления света
material_color: цвет материала [r, g, b]
light_color: цвет источника света [r, g, b]
"""
# Компонент окружающего света
ambient = ambient_coef * light_color * material_color

# Компонент рассеянного света
diff_dot = max(np.dot(normal, light_dir), 0.0)
diffuse = diffuse_coef * diff_dot * light_color * material_color

# Компонент отраженного света
reflect_dir = 2 * np.dot(normal, light_dir) * normal – light_dir
reflect_dot = max(np.dot(view_dir, reflect_dir), 0.0)
specular = specular_coef * (reflect_dot ** shininess) * light_color

# Суммарный цвет
color = ambient + diffuse + specular

# Ограничение значений в диапазоне [0, 1]
color = np.clip(color, 0, 1)

return color

Алексей Петров, разработчик 3D-визуализаций в архитектуре Четыре года назад мне поручили разработать инструмент для визуализации и анализа зон видимости в городской застройке. Архитекторам требовалось понимать, как новое здание повлияет на видимость исторических объектов с различных точек города.

Я начал с попыток использовать специализированные САПР, но они не предоставляли необходимой гибкости. Решение пришло неожиданно — Python с библиотекой VTK. Потребовалось всего три недели, чтобы создать прототип, который загружал 3D-модель города и динамически генерировал "тепловые карты" видимости.

Ключевой момент произошел, когда я реализовал алгоритм трассировки лучей для анализа видимости. Модель из 500,000 полигонов обрабатывалась за считанные минуты благодаря эффективным структурам данных VTK и оптимизации с NumPy. Клиент был поражен, когда увидел интерактивную визуализацию с цветовым кодированием проблемных зон.

Впоследствии инструмент вырос в полноценное решение для градостроительного анализа, которым пользуются несколько архитектурных бюро. Без Python и его экосистемы 3D-библиотек проект бы никогда не состоялся в существующие сроки и бюджет.

Практическое руководство: создаём первую 3D сцену на Python

Создание полноценной 3D сцены на Python требует последовательного подхода, от настройки окружения до реализации интерактивности. Этот практический гайд проведет вас через все этапы создания простой, но функциональной 3D сцены с использованием PyOpenGL и Pygame. 🎮

Необходимые зависимости для установки:

Bash
Скопировать код
# В терминале или командной строке:
pip install pygame PyOpenGL PyOpenGL_accelerate numpy

Шаг 1: Настройка окна и инициализация OpenGL

Python
Скопировать код
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import numpy as np

# Инициализация Pygame и создание окна
def init_display(width, height):
pygame.init()
display = (width, height)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
pygame.display.set_caption("Python 3D Scene")

# Настройка проекции
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (width/height), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glEnable(GL_DEPTH_TEST)

# Настройка освещения
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)

# Позиция источника света
light_position = [5\.0, 5.0, 5.0, 1.0]
glLightfv(GL_LIGHT0, GL_POSITION, light_position)

# Начальное положение камеры
glTranslatef(0.0, 0.0, -5.0)

# Вызов функции инициализации
init_display(800, 600)

Шаг 2: Создание базовых геометрических примитивов

Python
Скопировать код
def draw_cube(size=1.0):
"""Рисует куб заданного размера"""
half = size / 2.0

# Определение вершин куба
vertices = [
# Передняя грань (z = half)
[-half, -half, half],
[half, -half, half],
[half, half, half],
[-half, half, half],
# Задняя грань (z = -half)
[-half, -half, -half],
[half, -half, -half],
[half, half, -half],
[-half, half, -half]
]

# Определение граней (по 4 вершины на грань)
faces = [
[0, 1, 2, 3], # Передняя
[1, 5, 6, 2], # Правая
[5, 4, 7, 6], # Задняя
[4, 0, 3, 7], # Левая
[3, 2, 6, 7], # Верхняя
[4, 5, 1, 0] # Нижняя
]

# Цвета граней (RGBA)
colors = [
[1\.0, 0.0, 0.0, 1.0], # Красный
[0\.0, 1.0, 0.0, 1.0], # Зеленый
[0\.0, 0.0, 1.0, 1.0], # Синий
[1\.0, 1.0, 0.0, 1.0], # Желтый
[1\.0, 0.0, 1.0, 1.0], # Пурпурный
[0\.0, 1.0, 1.0, 1.0] # Бирюзовый
]

# Рисуем каждую грань
glBegin(GL_QUADS)
for i, face in enumerate(faces):
glColor4fv(colors[i])
for vertex_index in face:
# Нормаль для правильного освещения
glNormal3fv(np.array(vertices[vertex_index]) / half)
glVertex3fv(vertices[vertex_index])
glEnd()

def draw_sphere(radius=0.5, slices=20, stacks=20):
"""Рисует сферу с заданным радиусом"""
quad = gluNewQuadric()
glColor4f(0.8, 0.8, 0.8, 1.0)
gluSphere(quad, radius, slices, stacks)
gluDeleteQuadric(quad)

Шаг 3: Создание сцены с несколькими объектами

Python
Скопировать код
def draw_scene():
"""Рисует сцену с несколькими объектами"""
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glTranslatef(0.0, 0.0, -5.0)

# Вращение всей сцены
global rotation_y
glRotatef(rotation_y, 0, 1, 0)

# Куб слева
glPushMatrix()
glTranslatef(-1.5, 0.0, 0.0)
glRotatef(rotation_y * 2, 1, 1, 1)
draw_cube(0.7)
glPopMatrix()

# Сфера в центре
glPushMatrix()
glTranslatef(0.0, 0.0, 0.0)
draw_sphere(0.5)
glPopMatrix()

# Куб справа
glPushMatrix()
glTranslatef(1.5, 0.0, 0.0)
glRotatef(rotation_y * 2, 1, 1, 1)
draw_cube(0.7)
glPopMatrix()

# Обновление переменной вращения
rotation_y += 0.5

Шаг 4: Добавление управления камерой

Python
Скопировать код
def handle_input(keys):
"""Обрабатывает ввод пользователя для перемещения камеры"""
speed = 0.1
rotation_speed = 2.0

if keys[pygame.K_UP]:
glTranslatef(0, 0, speed)
if keys[pygame.K_DOWN]:
glTranslatef(0, 0, -speed)
if keys[pygame.K_LEFT]:
glTranslatef(speed, 0, 0)
if keys[pygame.K_RIGHT]:
glTranslatef(-speed, 0, 0)
if keys[pygame.K_w]:
glRotatef(rotation_speed, 1, 0, 0)
if keys[pygame.K_s]:
glRotatef(-rotation_speed, 1, 0, 0)
if keys[pygame.K_a]:
glRotatef(rotation_speed, 0, 1, 0)
if keys[pygame.K_d]:
glRotatef(-rotation_speed, 0, 1, 0)

Шаг 5: Главный цикл программы

Python
Скопировать код
def main():
global rotation_y
rotation_y = 0

init_display(800, 600)

# Главный цикл программы
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return

# Обработка ввода
keys = pygame.key.get_pressed()
handle_input(keys)

# Отрисовка сцены
draw_scene()

# Обновление экрана
pygame.display.flip()
pygame.time.wait(10)

if __name__ == "__main__":
main()

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

Для повышения реалистичности сцены можно добавить текстурирование:

Python
Скопировать код
from pygame import image
from OpenGL.GL import *

def load_texture(filename):
"""Загружает текстуру из файла изображения"""
surface = image.load(filename)
texture_data = pygame.image.tostring(surface, "RGBA", 1)
width, height = surface.get_size()

texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_id)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 
GL_RGBA, GL_UNSIGNED_BYTE, texture_data)

return texture_id

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

Продвинутые техники 3D моделирования на языке Python

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

Ключевые продвинутые техники включают:

  • Реализацию шейдеров — программы, выполняемые на GPU для реалистичной визуализации
  • Оптимизацию геометрии — методы уменьшения полигональной нагрузки
  • Пространственные структуры данных — для эффективного рендеринга больших сцен
  • Физически корректный рендеринг — симуляция реалистичного освещения
  • Процедурное моделирование — алгоритмическое создание сложных объектов

Пример реализации простого шейдера на Python с использованием ModernGL:

Python
Скопировать код
import moderngl
import numpy as np
import pygame

# Инициализация Pygame и создание контекста ModernGL
pygame.init()
pygame.display.set_mode((800, 600), pygame.OPENGL | pygame.DOUBLEBUF)
ctx = moderngl.create_context()

# Вершинный шейдер
vertex_shader = """
#version 330

in vec3 in_position;
in vec3 in_normal;

out vec3 normal;
out vec3 pos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {
normal = mat3(transpose(inverse(model))) * in_normal;
pos = vec3(model * vec4(in_position, 1.0));
gl_Position = projection * view * model * vec4(in_position, 1.0);
}
"""

# Фрагментный шейдер для реализации модели освещения Фонга
fragment_shader = """
#version 330

in vec3 normal;
in vec3 pos;

out vec4 fragColor;

uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform vec3 objectColor;

void main() {
// Нормализация входящих значений
vec3 norm = normalize(normal);
vec3 lightDir = normalize(lightPos – pos);

// Компонент окружающего освещения
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;

// Компонент диффузного освещения
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;

// Компонент бликов
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos – pos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;

// Итоговый цвет
vec3 result = (ambient + diffuse + specular) * objectColor;
fragColor = vec4(result, 1.0);
}
"""

# Создание программы шейдеров
program = ctx.program(
vertex_shader=vertex_shader,
fragment_shader=fragment_shader
)

# Создание простой геометрии куба
vertices = np.array([
# Передняя грань
-0.5, -0.5, 0.5, 0.0, 0.0, 1.0, # нижний левый угол
0.5, -0.5, 0.5, 0.0, 0.0, 1.0, # нижний правый угол
0.5, 0.5, 0.5, 0.0, 0.0, 1.0, # верхний правый угол
-0.5, 0.5, 0.5, 0.0, 0.0, 1.0, # верхний левый угол
# и так далее для всех граней...
], dtype='f4')

# Индексы для рисования граней
indices = np.array([
0, 1, 2, 2, 3, 0, # передняя грань
# и так далее для всех граней...
], dtype='i4')

# Создание буферов в памяти GPU
vbo = ctx.buffer(vertices.tobytes())
ibo = ctx.buffer(indices.tobytes())

# Описание формата вершин
vao = ctx.vertex_array(
program,
[
(vbo, '3f 3f', 'in_position', 'in_normal')
],
ibo
)

# Установка uniform-переменных для шейдера
program['lightPos'].value = (5.0, 5.0, 5.0)
program['viewPos'].value = (0.0, 0.0, 3.0)
program['lightColor'].value = (1.0, 1.0, 1.0)
program['objectColor'].value = (1.0, 0.5, 0.31)

# ... Код для создания матриц модели, вида и проекции ...

# Основной цикл рендеринга
def render():
ctx.clear(0.1, 0.1, 0.1)
ctx.enable(moderngl.DEPTH_TEST)

# Обновление uniform-переменных для матриц
program['model'].write(model_matrix)
program['view'].write(view_matrix)
program['projection'].write(projection_matrix)

# Рендеринг геометрии
vao.render(moderngl.TRIANGLES)

pygame.display.flip()

Продвинутая техника — процедурная генерация ландшафта с использованием алгоритма Diamond-Square:

Python
Скопировать код
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def diamond_square(size, roughness=0.5, seed=None):
"""
Генерирует карту высот используя алгоритм Diamond-Square

size: размер карты высот (должен быть 2^n + 1)
roughness: коэффициент шероховатости (0-1)
seed: зерно для генератора случайных чисел
"""
if seed is not None:
np.random.seed(seed)

# Проверка, что размер имеет вид 2^n + 1
n = int(np.log2(size – 1))
if 2**n + 1 != size:
raise ValueError(f"Размер должен быть 2^n + 1, получено: {size}")

# Создание начальной карты высот
terrain = np.zeros((size, size))

# Установка начальных углов
terrain[0, 0] = np.random.uniform(-1, 1)
terrain[0, size-1] = np.random.uniform(-1, 1)
terrain[size-1, 0] = np.random.uniform(-1, 1)
terrain[size-1, size-1] = np.random.uniform(-1, 1)

# Шаг сетки
step = size – 1

# Пока шаг больше 1
while step > 1:
half_step = step // 2

# Diamond step
for x in range(half_step, size, step):
for y in range(half_step, size, step):
# Вычисляем среднее значение четырех углов
avg = (terrain[x-half_step, y-half_step] + # верхний левый
terrain[x-half_step, y+half_step] + # верхний правый
terrain[x+half_step, y-half_step] + # нижний левый
terrain[x+half_step, y+half_step]) / 4.0 # нижний правый

# Добавляем случайное смещение
terrain[x, y] = avg + np.random.uniform(-1, 1) * roughness * step

# Square step
for x in range(0, size, half_step):
for y in range((x + half_step) % step, size, step):
# Подсчитываем среднее из доступных значений
count = 0
avg = 0

if x >= half_step: # верх
avg += terrain[x-half_step, y]
count += 1
if x + half_step < size: # низ
avg += terrain[x+half_step, y]
count += 1
if y >= half_step: # лево
avg += terrain[x, y-half_step]
count += 1
if y + half_step < size: # право
avg += terrain[x, y+half_step]
count += 1

avg /= count
terrain[x, y] = avg + np.random.uniform(-1, 1) * roughness * step

# Уменьшаем шаг и шероховатость
step = half_step
roughness *= 0.5

# Нормализация значений до диапазона [0, 1]
min_val = np.min(terrain)
max_val = np.max(terrain)
terrain = (terrain – min_val) / (max_val – min_val)

return terrain

# Визуализация карты высот
def visualize_terrain(terrain):
"""Визуализирует карту высот в 3D"""
size = terrain.shape[0]
x = np.arange(0, size, 1)
y = np.arange(0, size, 1)
x, y = np.meshgrid(x, y)

fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(x, y, terrain, cmap='terrain', linewidth=0, antialiased=True)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.title('Процедурно сгенерированный ландшафт')
plt.show()

# Создание и визуализация карты высот размером 129x129
terrain = diamond_square(129, roughness=0.7, seed=42)
visualize_terrain(terrain)

Интеграция с физическим движком для реалистичной симуляции:

Python
Скопировать код
import pymunk
import pymunk.pygame_util
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from pygame.locals import *
import numpy as np

# Настройка физического мира
def setup_physics():
space = pymunk.Space()
space.gravity = (0, -900)

# Создание границ мира
static_body = space.static_body

# Земля
ground = pymunk.Segment(static_body, (-600, -300), (600, -300), 5.0)
ground.friction = 1.0

# Стены
left_wall = pymunk.Segment(static_body, (-600, -300), (-600, 300), 5.0)
right_wall = pymunk.Segment(static_body, (600, -300), (600, 300), 5.0)

space.add(ground, left_wall, right_wall)

return space

# Добавление физического объекта (куба)
def add_box(space, position, size=50, mass=1):
moment = pymunk.moment_for_box(mass, (size, size))
body = pymunk.Body(mass, moment)
body.position = position

shape = pymunk.Poly.create_box(body, (size, size))
shape.friction = 0.7
shape.elasticity = 0.3

space.add(body, shape)

return body, shape

# ... код инициализации OpenGL и рендеринга ...

# Главный цикл программы с интеграцией физики
def main():
# Инициализация Pygame и OpenGL
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

# Настройка OpenGL
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0, 0, -10)

# Настройка физического мира
space = setup_physics()
clock = pygame.time.Clock()

# Создание нескольких кубов
boxes = []
for i in range(10):
box_body, _ = add_box(space, (np.random.randint(-500, 500), 200 + i*60))
boxes.append(box_body)

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return

if event.type == pygame.MOUSEBUTTONDOWN:
# Добавление куба при клике мыши
x, y = pygame.mouse.get_pos()
# Преобразование координат экрана в координаты мира
box_body, _ = add_box(space, (x – 400, 300 – y))
boxes.append(box_body)

# Очистка экрана
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

# Обновление физического мира
dt = 1.0/60.0
space.step(dt)

# Рендеринг физических объектов
for box in boxes:
pos = box.position
angle = box.angle

glPushMatrix()
# Преобразование из координат Pymunk в координаты OpenGL
glTranslatef(pos.x/100, pos.y/100, 0)
glRotatef(angle * 180/np.pi, 0, 0, 1)

# Рендеринг куба
draw_cube(0.5)

glPopMatrix()

pygame.display.flip()
clock.tick(60)

Эти примеры иллюстрируют возможности Python для реализации продвинутых техник 3D-визуализации. Комбинирование этих подходов с высокоуровневыми библиотеками позволяет создавать сложные 3D-приложения с относительно небольшими затратами на разработку.

Освоение Python для 3D графики открывает перед разработчиками уникальные перспективы — это язык, сочетающий доступность с мощью. От создания интерактивных визуализаций научных данных до разработки прототипов игр и генеративного искусства — всё становится возможным с правильным набором библиотек и техник. Ключом к успеху является системный подход: начните с понимания фундаментальных принципов 3D графики, изучите подходящие инструменты для ваших конкретных задач, и постепенно наращивайте сложность проектов. Python превращает сложную область трехмерной визуализации в доступное пространство для экспериментов и профессиональной работы.

Читайте также

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какая библиотека используется для автоматизации задач в Blender?
1 / 5

Загрузка...