From 9be103974ec433d2c725174225bd630f3a4270e2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 30 Sep 2020 10:27:26 +0200 Subject: [PATCH] feat(nuke): exctractor plugin for camera abs (presets can do fbx) --- .../plugins/nuke/publish/collect_instances.py | 1 - pype/plugins/nuke/publish/extract_camera.py | 185 ++++++++++++++++++ 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 pype/plugins/nuke/publish/extract_camera.py diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index 9085e12bd8..d2031266bd 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -60,7 +60,6 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): families.append(family) - # except disabled nodes but exclude backdrops in test if ("nukenodes" not in family) and (node["disable"].value()): continue diff --git a/pype/plugins/nuke/publish/extract_camera.py b/pype/plugins/nuke/publish/extract_camera.py new file mode 100644 index 0000000000..9a1efba1df --- /dev/null +++ b/pype/plugins/nuke/publish/extract_camera.py @@ -0,0 +1,185 @@ +import nuke +import os +import math +import pyblish.api +import pype.api +from avalon.nuke import lib as anlib +from pprint import pformat + + +class ExtractCamera(pype.api.Extractor): + """ 3D camera exctractor + """ + label = 'Exctract Camera' + order = pyblish.api.ExtractorOrder + families = ["camera"] + hosts = ["nuke"] + + # presets + write_geo_knobs = [ + ("file_type", "abc"), + ("storageFormat", "Ogawa"), + ("writeGeometries", False), + ("writePointClouds", False), + ("writeAxes", False) + ] + + def process(self, instance): + handle_start = instance.context.data["handleStart"] + handle_end = instance.context.data["handleEnd"] + first_frame = int(nuke.root()["first_frame"].getValue()) + last_frame = int(nuke.root()["last_frame"].getValue()) + step = 1 + output_range = str(nuke.FrameRange(first_frame, last_frame, step)) + + self.log.info("instance.data: `{}`".format( + pformat(instance.data))) + + rm_nodes = list() + self.log.info("Crating additional nodes") + subset = instance.data["subset"] + staging_dir = self.staging_dir(instance) + + # get extension form preset + extension = next((k[1] for k in self.write_geo_knobs + if k[0] == "file_type"), None) + if not extension: + raise RuntimeError( + "Bad config for extension in presets. " + "Talk to your supervisor or pipeline admin") + + # create file name and path + filename = subset + ".{}".format(extension) + file_path = os.path.join(staging_dir, filename).replace("\\", "/") + + with anlib.maintained_selection(): + # bake camera with axeses onto word coordinate XYZ + rm_n = bakeCameraWithAxeses( + nuke.toNode(instance.data["name"]), output_range) + rm_nodes.append(rm_n) + + # create scene node + rm_n = nuke.createNode("Scene") + rm_nodes.append(rm_n) + + # create write geo node + wg_n = nuke.createNode("WriteGeo") + wg_n["file"].setValue(file_path) + # add path to write to + for k, v in self.write_geo_knobs: + wg_n[k].setValue(v) + rm_nodes.append(wg_n) + + # write out camera + nuke.execute( + wg_n, + int(first_frame), + int(last_frame) + ) + # erase additional nodes + for n in rm_nodes: + nuke.delete(n) + + self.log.info(file_path) + + # create representation data + if "representations" not in instance.data: + instance.data["representations"] = [] + + representation = { + 'name': extension, + 'ext': extension, + 'files': filename, + "stagingDir": staging_dir, + "frameStart": first_frame, + "frameEnd": last_frame + } + instance.data["representations"].append(representation) + + instance.data.update({ + "path": file_path, + "outputDir": staging_dir, + "ext": extension, + "handleStart": handle_start, + "handleEnd": handle_end, + "frameStart": first_frame + handle_start, + "frameEnd": last_frame - handle_end, + "frameStartHandle": first_frame, + "frameEndHandle": last_frame, + }) + + self.log.info("Extracted instance '{0}' to: {1}".format( + instance.name, file_path)) + + +def bakeCameraWithAxeses(camera_node, output_range): + """ Baking all perent hiearchy of axeses into camera + with transposition onto word XYZ coordinance + """ + bakeFocal = False + bakeHaperture = False + bakeVaperture = False + + camera_matrix = camera_node['world_matrix'] + + new_cam_n = nuke.createNode("Camera2") + new_cam_n.setInput(0, None) + new_cam_n['rotate'].setAnimated() + new_cam_n['translate'].setAnimated() + + old_focal = camera_node['focal'] + if old_focal.isAnimated() and not (old_focal.animation(0).constant()): + new_cam_n['focal'].setAnimated() + bakeFocal = True + else: + new_cam_n['focal'].setValue(old_focal.value()) + + old_haperture = camera_node['haperture'] + if old_haperture.isAnimated() and not ( + old_haperture.animation(0).constant()): + new_cam_n['haperture'].setAnimated() + bakeHaperture = True + else: + new_cam_n['haperture'].setValue(old_haperture.value()) + + old_vaperture = camera_node['vaperture'] + if old_vaperture.isAnimated() and not ( + old_vaperture.animation(0).constant()): + new_cam_n['vaperture'].setAnimated() + bakeVaperture = True + else: + new_cam_n['vaperture'].setValue(old_vaperture.value()) + + new_cam_n['win_translate'].setValue(camera_node['win_translate'].value()) + new_cam_n['win_scale'].setValue(camera_node['win_scale'].value()) + + for x in nuke.FrameRange(output_range): + math_matrix = nuke.math.Matrix4() + for y in range(camera_matrix.height()): + for z in range(camera_matrix.width()): + matrix_pointer = z + (y * camera_matrix.width()) + math_matrix[matrix_pointer] = camera_matrix.getValueAt( + x, (y + (z * camera_matrix.width()))) + + rot_matrix = nuke.math.Matrix4(math_matrix) + rot_matrix.rotationOnly() + rot = rot_matrix.rotationsZXY() + + new_cam_n['rotate'].setValueAt(math.degrees(rot[0]), x, 0) + new_cam_n['rotate'].setValueAt(math.degrees(rot[1]), x, 1) + new_cam_n['rotate'].setValueAt(math.degrees(rot[2]), x, 2) + new_cam_n['translate'].setValueAt( + camera_matrix.getValueAt(x, 3), x, 0) + new_cam_n['translate'].setValueAt( + camera_matrix.getValueAt(x, 7), x, 1) + new_cam_n['translate'].setValueAt( + camera_matrix.getValueAt(x, 11), x, 2) + + if bakeFocal: + new_cam_n['focal'].setValueAt(old_focal.getValueAt(x), x) + if bakeHaperture: + new_cam_n['haperture'].setValueAt(old_haperture.getValueAt(x), x) + if bakeVaperture: + new_cam_n['vaperture'].setValueAt(old_vaperture.getValueAt(x), x) + + return new_cam_n