Spaces:
Running on Zero
Running on Zero
File size: 4,491 Bytes
43ca9e0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | import os
import json
from pathlib import Path
import shutil
import subprocess
from urllib.request import urlretrieve
import numpy as np
REPO_ROOT = Path(__file__).resolve().parents[2]
BLENDER_LINK = 'https://download.blender.org/release/Blender3.0/blender-3.0.1-linux-x64.tar.xz'
BLENDER_INSTALLATION_PATH = os.environ.get('SPACEFLOW_BLENDER_ROOT', str(REPO_ROOT))
BLENDER_PATH = os.environ.get(
'SPACEFLOW_BLENDER_PATH',
f'{BLENDER_INSTALLATION_PATH}/blender-3.0.1-linux-x64/blender',
)
BLENDER_RENDER_SCRIPT = os.environ.get(
'SPACEFLOW_BLENDER_RENDER_SCRIPT',
str(REPO_ROOT / 'third_party' / 'TRELLIS' / 'dataset_toolkits' / 'blender_script' / 'render.py'),
)
def _install_blender():
if shutil.which(BLENDER_PATH):
return
if os.environ.get('SPACEFLOW_BLENDER_PATH'):
raise FileNotFoundError(
f'Blender is not executable at SPACEFLOW_BLENDER_PATH={BLENDER_PATH}. '
'Set it to an installed Blender 3.x executable.'
)
installation = Path(BLENDER_INSTALLATION_PATH)
installation.mkdir(parents=True, exist_ok=True)
archive = installation / 'blender-3.0.1-linux-x64.tar.xz'
try:
urlretrieve(BLENDER_LINK, archive)
subprocess.run(['tar', '-xf', str(archive), '-C', str(installation)], check=True)
except (OSError, subprocess.CalledProcessError) as exc:
raise RuntimeError(
'Blender installation failed. Install Blender 3.x separately and set '
'SPACEFLOW_BLENDER_PATH to its executable.'
) from exc
if not shutil.which(BLENDER_PATH):
raise FileNotFoundError(f'Blender installation did not produce an executable: {BLENDER_PATH}')
def _run_blender(args):
result = subprocess.run(args, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True)
if result.returncode:
raise RuntimeError(
f'Blender failed with exit code {result.returncode}. '
f'Executable: {BLENDER_PATH}. Error output:\n{result.stderr[-3000:]}'
)
def render_all_views(file_path, output_folder, num_views=150):
_install_blender()
# Build camera {yaw, pitch, radius, fov}
yaws = []
pitchs = []
offset = (np.random.rand(), np.random.rand())
for i in range(num_views):
y, p = sphere_hammersley_sequence(i, num_views, offset)
yaws.append(y)
pitchs.append(p)
radius = [2] * num_views
fov = [40 / 180 * np.pi] * num_views
views = [{'yaw': y, 'pitch': p, 'radius': r, 'fov': f} for y, p, r, f in zip(yaws, pitchs, radius, fov)]
args = [
BLENDER_PATH, '-b', '-P', BLENDER_RENDER_SCRIPT,
'--',
'--views', json.dumps(views),
'--object', os.path.expanduser(file_path),
'--resolution', '512',
'--output_folder', output_folder,
'--engine', 'CYCLES',
'--save_mesh',
]
if file_path.endswith('.blend'):
args.insert(1, file_path)
_run_blender(args)
if os.path.exists(os.path.join(output_folder, 'transforms.json')):
return True
def export_normalized_mesh(file_path, output_folder):
_install_blender()
args = [
BLENDER_PATH, '-b', '-P', BLENDER_RENDER_SCRIPT,
'--',
'--views', '[]',
'--object', os.path.expanduser(file_path),
'--resolution', '512',
'--output_folder', output_folder,
'--engine', 'CYCLES',
'--save_mesh',
]
if file_path.endswith('.blend'):
args.insert(1, file_path)
_run_blender(args)
if os.path.exists(os.path.join(output_folder, 'mesh.ply')):
return True
# ===============LOW DISCREPANCY SEQUENCES================
PRIMES = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]
def radical_inverse(base, n):
val = 0
inv_base = 1.0 / base
inv_base_n = inv_base
while n > 0:
digit = n % base
val += digit * inv_base_n
n //= base
inv_base_n *= inv_base
return val
def halton_sequence(dim, n):
return [radical_inverse(PRIMES[dim], n) for dim in range(dim)]
def hammersley_sequence(dim, n, num_samples):
return [n / num_samples] + halton_sequence(dim - 1, n)
def sphere_hammersley_sequence(n, num_samples, offset=(0, 0)):
u, v = hammersley_sequence(2, n, num_samples)
u += offset[0] / num_samples
v += offset[1]
u = 2 * u if u < 0.25 else 2 / 3 * u + 1 / 3
theta = np.arccos(1 - 2 * u) - np.pi / 2
phi = v * 2 * np.pi
return [phi, theta]
|