kopia lustrzana https://github.com/OpenDroneMap/ODM
Video script.
Signed-off-by: Mark Hale <mark.hale@physics.org>
Former-commit-id: bb35bc5d51
pull/1161/head
rodzic
73865db0d8
commit
6de6649d60
|
@ -2,6 +2,7 @@
|
|||
# odm_photo
|
||||
Renders photos from ODM generated texture models.
|
||||
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
|
||||
* Blender
|
||||
|
|
|
@ -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])
|
|
@ -10,11 +10,8 @@
|
|||
|
||||
import sys
|
||||
import bpy
|
||||
import materials_utils
|
||||
import subprocess
|
||||
|
||||
surfaceShaderType = 'ShaderNodeEmission'
|
||||
surfaceShaderName = 'Emission'
|
||||
from common import loadMesh
|
||||
|
||||
|
||||
def main():
|
||||
|
@ -24,47 +21,12 @@ def main():
|
|||
|
||||
projectHome = sys.argv[-1]
|
||||
|
||||
bpy.utils.register_module('materials_utils')
|
||||
|
||||
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])
|
||||
loadMesh(projectHome +
|
||||
'/odm_texturing/odm_textured_model_geo.obj')
|
||||
|
||||
blendName = bpy.path.display_name_from_filepath(bpy.data.filepath)
|
||||
fileName = projectHome + '/odm_photo/odm_' + blendName
|
||||
render = bpy.data.scenes[0].render
|
||||
render = bpy.data.scenes['Scene'].render
|
||||
render.filepath = fileName
|
||||
bpy.ops.render.render(write_still=True)
|
||||
|
||||
|
|
|
@ -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.
Ładowanie…
Reference in New Issue