В рамках написания библиотеки 3D-игр я пытаюсь реализовать отсечение усеченного конуса, чтобы избежать рендеринга объектов, находящихся за пределами усеченного конуса перспективы камеры. Для этого мне сначала нужно рассчитать ограничивающую сферу для каждой сетки и посмотреть, не сталкивается ли она с какой-либо из шести сторон усеченной области просмотра. Вот моя в настоящее время (очень) наивная реализация вычисления ограничивающей сферы для каждой модели, как написано в model.py
в моем коде:
from pyorama.entity import Entity
from pyorama.math3d.vec3 import Vec3
from pyorama.math3d.mat4 import Mat4
from pyorama.physics.sphere import Sphere
import math
import numpy as np
import itertools as its
class Model(Entity):
def __init__(self, mesh, texture, transform=Mat4.identity()):
super(Model, self).__init__()
self.mesh = mesh
self.texture = texture
self.transform = transform
def compute_bounding_sphere(self):
vertex_data = self.mesh.vertex_buffer.get_data()
vertices = []
for i in range(0, len(vertex_data), 3):
vertex = Vec3(vertex_data[i: i+3])
vertices.append(vertex)
max_pair = None
max_dist = 0
for a, b in its.combinations(vertices, 2):
dist = Vec3.square_distance(a, b)
if dist > max_dist:
max_pair = (a, b)
max_dist = dist
radius = math.sqrt(max_dist)/2.0
center = Vec3.lerp(max_pair[0], max_pair[1], 0.5)
return Sphere(center, radius)
Я просто беру попарные точки из своей сетки и использую наибольшее расстояние, которое я нашел, как свой диаметр. Вызывая это на 100 простых тестовых моделях куба, каждый кадр будет чрезвычайно медленным, и моя частота кадров увеличится со 120 до 1 кадра в секунду! Это неудивительно, поскольку я предполагаю, что временная сложность для этого попарного кода равна O (n ^ 2).
Мой вопрос: какой алгоритм является быстрым и достаточно простым для реализации, который вычисляет (по крайней мере) приблизительную ограничивающую сферу с учетом набора трехмерных точек из сетки? Я просмотрел эту страницу Википедии и увидел там алгоритм под названием «ограничивающая сфера Риттера». Однако для этого мне нужно выбрать какую-то случайную точку x в сетке и надеяться, что это приблизительный центр, чтобы я получил достаточно плотную ограничивающую сферу. Есть ли быстрый способ выбрать хорошую отправную точку x? Мы будем благодарны за любую помощь или совет!
ОБНОВЛЕНИЕ:
Следуя ответу @Aaron3468, вот код в моей библиотеке, который вычислит ограничивающую рамку и соответствующую ограничивающую сферу:
from pyorama.entity import Entity
from pyorama.math3d.vec3 import Vec3
from pyorama.math3d.mat4 import Mat4
from pyorama.physics.sphere import Sphere
from pyorama.physics.box import Box
import math
import numpy as np
import itertools as its
class Model(Entity):
def __init__(self, mesh, texture, transform=Mat4.identity()):
super(Model, self).__init__()
self.mesh = mesh
self.texture = texture
self.transform = transform
def compute_bounding_sphere(self):
box = self.compute_bounding_box()
a, b = box.min_corner, box.max_corner
radius = Vec3.distance(a, b)/2.0
center = Vec3.lerp(a, b, 0.5)
return Sphere(center, radius)
def compute_bounding_box(self):
vertex_data = self.mesh.vertex_buffer.get_data()
max_corner = Vec3(vertex_data[0:3])
min_corner = Vec3(vertex_data[0:3])
for i in range(0, len(vertex_data), 3):
vertex = Vec3(vertex_data[i: i+3])
min_corner = Vec3.min_components(vertex, min_corner)
max_corner = Vec3.max_components(vertex, max_corner)
return Box(min_corner, max_corner)
numpy
- хорошая оптимизация, но я скептически отношусь к ее масштабированию. Возможно, будет лучше создать движок на C и использовать python в качестве языка сценариев поверх. - person Aaron3468   schedule 08.01.2017compute_bounding_volume
в свой классMesh
из моего классаModel
. Все классы, которые я написал дляpyorama.math3d
, завершаютnumpy
массивы. Весь этот код можно найти на моей странице репозитория github дляpyorama
. Я по-прежнему склонен полагать, что есть что-то, что я могу сделать для улучшения этого кода, помимо переноса нагрузки с времени выполнения на инициализацию сетки. - person CodeSurgeon   schedule 08.01.2017