Signed-off-by: Mark Hale <mark.hale@physics.org>
Former-commit-id: bb35bc5d51
pull/1161/head
Mark Hale 2017-02-28 01:10:07 +00:00
rodzic 73865db0d8
commit 6de6649d60
5 zmienionych plików z 128 dodań i 42 usunięć

Wyświetl plik

@ -2,6 +2,7 @@
# odm_photo # odm_photo
Renders photos from ODM generated texture models. Renders photos from ODM generated texture models.
Currently can produce 360 panoramic photos and 360 3D panoramic (VR) photos. Currently can produce 360 panoramic photos and 360 3D panoramic (VR) photos.
NB: the default resolution for 360 photos is 6000x3000 (maximum supported by Facebook).
## Requirements ## Requirements
* Blender * Blender

Wyświetl plik

@ -0,0 +1,44 @@
import bpy
import materials_utils
def loadMesh(file):
bpy.utils.register_module('materials_utils')
bpy.ops.import_scene.obj(filepath=file,
axis_forward='Y', axis_up='Z')
bpy.ops.xps_tools.convert_to_cycles_all()
model = bpy.data.objects[-1]
minX = float('inf')
maxX = float('-inf')
minY = float('inf')
maxY = float('-inf')
minZ = float('inf')
maxZ = float('-inf')
for coord in model.bound_box:
x = coord[0]
y = coord[1]
z = coord[2]
minX = min(x, minX)
maxX = max(x, maxX)
minY = min(y, minY)
maxY = max(y, maxY)
minZ = min(z, minZ)
maxZ = max(z, maxZ)
model.location[2] += (maxZ - minZ)/2
surfaceShaderType = 'ShaderNodeEmission'
surfaceShaderName = 'Emission'
for m in bpy.data.materials:
nt = m.node_tree
nt.nodes.remove(nt.nodes['Color Mult'])
nt.nodes.remove(nt.nodes['Diffuse BSDF'])
nt.nodes.new(surfaceShaderType)
nt.links.new(nt.nodes['Material Output'].inputs[0],
nt.nodes[surfaceShaderName].outputs[0])
nt.links.new(nt.nodes[surfaceShaderName].inputs[0],
nt.nodes['Diffuse Texture'].outputs[0])

Wyświetl plik

@ -10,11 +10,8 @@
import sys import sys
import bpy import bpy
import materials_utils
import subprocess import subprocess
from common import loadMesh
surfaceShaderType = 'ShaderNodeEmission'
surfaceShaderName = 'Emission'
def main(): def main():
@ -24,47 +21,12 @@ def main():
projectHome = sys.argv[-1] projectHome = sys.argv[-1]
bpy.utils.register_module('materials_utils') loadMesh(projectHome +
'/odm_texturing/odm_textured_model_geo.obj')
bpy.ops.import_scene.obj(filepath=projectHome +
'/odm_texturing/odm_textured_model_geo.obj',
axis_forward='Y', axis_up='Z')
bpy.ops.xps_tools.convert_to_cycles_all()
model = bpy.data.objects[-1]
minX = float('inf')
maxX = float('-inf')
minY = float('inf')
maxY = float('-inf')
minZ = float('inf')
maxZ = float('-inf')
for coord in model.bound_box:
x = coord[0]
y = coord[1]
z = coord[2]
minX = min(x, minX)
maxX = max(x, maxX)
minY = min(y, minY)
maxY = max(y, maxY)
minZ = min(z, minZ)
maxZ = max(z, maxZ)
model.location[2] += (maxZ - minZ)/2
for m in bpy.data.materials:
nt = m.node_tree
nt.nodes.remove(nt.nodes['Color Mult'])
nt.nodes.remove(nt.nodes['Diffuse BSDF'])
nt.nodes.new(surfaceShaderType)
nt.links.new(nt.nodes['Material Output'].inputs[0],
nt.nodes[surfaceShaderName].outputs[0])
nt.links.new(nt.nodes[surfaceShaderName].inputs[0],
nt.nodes['Diffuse Texture'].outputs[0])
blendName = bpy.path.display_name_from_filepath(bpy.data.filepath) blendName = bpy.path.display_name_from_filepath(bpy.data.filepath)
fileName = projectHome + '/odm_photo/odm_' + blendName fileName = projectHome + '/odm_photo/odm_' + blendName
render = bpy.data.scenes[0].render render = bpy.data.scenes['Scene'].render
render.filepath = fileName render.filepath = fileName
bpy.ops.render.render(write_still=True) bpy.ops.render.render(write_still=True)

Wyświetl plik

@ -0,0 +1,79 @@
#!/usr/bin/env python
# Renders a video.
# To generate a 360 panoramic video:
# blender -b photo_360.blend --python odm_video.py -- <project-path> <camera-waypoints.xyz> <number-of-frames>
import sys
import bpy
import subprocess
from common import loadMesh
def main():
if len(sys.argv) < 7 or sys.argv[-4] != '--':
sys.exit('Please provide the ODM project path, camera waypoints (xyz format), and number of frames.')
projectHome = sys.argv[-3]
waypointFile = sys.argv[-2]
numFrames = int(sys.argv[-1])
loadMesh(projectHome +
'/odm_texturing/odm_textured_model_geo.obj')
waypoints = loadWaypoints(waypointFile)
numWaypoints = len(waypoints)
scene = bpy.data.scenes['Scene']
# create path thru waypoints
curve = bpy.data.curves.new(name='CameraPath', type='CURVE')
curve.dimensions = '3D'
nurbs = curve.splines.new('NURBS')
nurbs.points.add(numWaypoints-1)
weight = 1
for i in range(numWaypoints):
nurbs.points[i].co[0] = waypoints[i][0]
nurbs.points[i].co[1] = waypoints[i][1]
nurbs.points[i].co[2] = waypoints[i][2]
nurbs.points[i].co[3] = weight
nurbs.use_endpoint_u = True
path = bpy.data.objects.new(name='CameraPath', object_data=curve)
scene.objects.link(path)
camera = bpy.data.objects['Camera']
camera.location[0] = 0
camera.location[1] = 0
camera.location[2] = 0
followPath = camera.constraints.new(type='FOLLOW_PATH')
followPath.name = 'CameraFollowPath'
followPath.target = path
followPath.use_curve_follow = True
animateContext = bpy.context.copy()
animateContext['constraint'] = followPath
bpy.ops.constraint.followpath_path_animate(animateContext, constraint='CameraFollowPath')
blendName = bpy.path.display_name_from_filepath(bpy.data.filepath)
fileName = projectHome + '/odm_video/odm_' + blendName.replace('photo', 'video')
scene.frame_start = 0
scene.frame_end = numFrames - 1
render = scene.render
render.filepath = fileName
render.resolution_x = 4096
render.resolution_y = 2048
render.image_settings.file_format = 'FFMPEG'
#bpy.ops.render.render(animation=True)
def loadWaypoints(filename):
waypoints = []
with open(filename) as f:
for line in f:
xyz = line.split()
waypoints.append((float(xyz[0]), float(xyz[1]), float(xyz[2])))
return waypoints
if __name__ == '__main__':
main()

Plik binarny nie jest wyświetlany.