Skip to content
Snippets Groups Projects
Commit 84033006 authored by Ben Heasly's avatar Ben Heasly
Browse files

write and render factoid scene files

parent bb8f4a64
No related branches found
No related tags found
No related merge requests found
function [factoids, exrOutput] = rtbRenderMitsubaFactoids(sceneFile, varargin)
% Obtain ground truth "factoids" about a Mitsuba scene.
%
% [factoids, exrOutput] = rtbRenderMitsubaFactoids(sceneFile) invokes
% Mitsuba to obtain ground truth scene "factoids". Returns a struct array
% of ground truth images, with one field per ground truth factoid.
%
% The given sceneFile must specify a "multichannel" integrator with one or
% more nested "field" integrators. You can create such scenes with
% rtbWriteMitsubaFactoidScene().
%
% rtbRenderMitsubaFactoids( ... 'mitsuba', mitsuba) specify a struct of
% info about the installed Mitsuba renderer. For some factoids, this must
% be a version of Mistuba compiled for RGB rendering, not spectral
% rendering. The default is taken from getpref('Mitsuba').
%
% rtbRenderMitsubaFactoids(... 'hints', hints)
% Specify a struct of RenderToolbox options. If hints is omitted, values
% are taken from rtbDefaultHints().
%
%%% RenderToolbox4 Copyright (c) 2012-2017 The RenderToolbox Team.
%%% About Us://github.com/RenderToolbox/RenderToolbox4/wiki/About-Us
%%% RenderToolbox4 is released under the MIT License. See LICENSE file.
parser = inputParser();
parser.addRequired('sceneFile', @ischar);
parser.addParameter('mitsuba', [], @(m) isempty(m) || isstruct(m));
parser.addParameter('hints', rtbDefaultHints(), @isstruct);
parser.parse(sceneFile, varargin{:});
sceneFile = parser.Results.sceneFile;
mitsuba = parser.Results.mitsuba;
hints = rtbDefaultHints(parser.Results.hints);
if isempty(mitsuba)
% modify default mitsuba config to look for rgb
mitsuba = getpref('Mitsuba');
mitsuba.dockerImage = 'ninjaben/mitsuba-rgb';
mitsuba.kubernetesPodSelector = 'app=mitsuba-spectral';
if ismac()
mitsuba.app = '/Applications/Mitsuba-RGB.app';
else
mitsuba.executable = 'mitusba-rgb';
end
end
%% Render the factoid scene.renderer = RtbMitsubaRenderer(hints);
renderer = RtbMitsubaRenderer(hints);
renderer.mitsuba = mitsuba;
[~, ~, exrOutput] = renderer.renderToExr(sceneFile);
[sliceInfo, data] = ReadMultichannelEXR(exrOutput);
%% Group data slices by factoid name.
factoids = struct();
factoidSize = size(data);
for ii = 1:numel(sliceInfo)
% factoid channels have names like albedo.R, albedo.G, albedo.B
split = find(sliceInfo(ii).name == '.');
factoidName = sliceInfo(ii).name(1:split-1);
channelName = sliceInfo(ii).name(split+1:end);
% initialize factoid output with data array and channel names
if ~isfield(factoids, factoidName)
factoids.(factoidName).data = ...
zeros(factoidSize(1), factoidSize(2), 0);
factoids.(factoidName).channels = {};
end
% insert data and channel name into output for this factoid
slice = data(:,:,ii);
factoids.(factoidName).data(:,:,end+1) = slice;
factoids.(factoidName).channels{end+1} = channelName;
end
function factoidFile = rtbWriteMitsubaFactoidScene(originalFile, varargin)
% Convert the given scene to get factoids instead of ray tracing.
%
% factoidFile = rtbWriteMitsubaFactoidScene(originalFile) copies and
% modifies the given originalFile so that it will produce Mitsuba ground
% truth "factoids" instead of ray tracing data. Returns a new Mitsuba
% scene file based on the given originalFile.
%
% The returned sceneFile woill specify a "multichannel" integrator with one
% or more nested "field" integrators. You can pass this file to
% rtbRenderMitsubaFactoids() to obtain the factoid data.
%
% rtbWriteMitsubaFactoidScene( ... 'factoids', factoids) specify a cell
% array of ground truth factoid names to be obtained. The default includes
% all available factoids:
% - 'position' - absolute position of the object under each pixel
% - 'relPosition' - camera-relative position of the object under each pixel
% - 'distance' - distance to camera of the object under each pixel
% - 'geoNormal' - surface normal at the surface under each pixel
% - 'shNormal' - surface normal at the surface under each pixel, interpolated for shading
% - 'uv' - texture mapping UV coordinates at the surface under each pixel
% - 'albedo' - diffuse reflectance of the object under each pixel
% - 'shapeIndex' - integer identifier for the object under each pixel
% - 'primIndex' - integer identifier for the triangle or other primitive under each pixel
%
% rtbWriteMitsubaFactoidScene( ... 'factoidFormat', factoidFormat) specify
% a mitsuba pixel format to use for formatting the output, like 'rgb' or
% 'spectrum'. The default is 'rgb'.
%
% rtbWriteMitsubaFactoidScene( ... 'singleSampling', singleSampling)
% whether or not to do a simplified rendering with one sample per pixel and
% a narrow "box" reconstruction filder. This is useful for labeling
% factoids like shapeIndex, where it doesn't make sense to average across
% multiple ray samples. The default is true, do a simplified rendering.
%
%%% RenderToolbox4 Copyright (c) 2012-2017 The RenderToolbox Team.
%%% About Us://github.com/RenderToolbox/RenderToolbox4/wiki/About-Us
%%% RenderToolbox4 is released under the MIT License. See LICENSE file.
parser = inputParser();
parser.addRequired('originalFile', @ischar);
parser.addParameter('factoidFile', '', @ischar);
parser.addParameter('factoids', ...
{'position', 'relPosition', 'distance', 'geoNormal', 'shNormal', ...
'uv', 'albedo', 'shapeIndex', 'primIndex'}, ...
@iscellstr);
parser.addParameter('factoidFormat', 'rgb', @ischar);
parser.addParameter('singleSampling', true, @islogical);
parser.parse(originalFile, varargin{:});
originalFile = parser.Results.originalFile;
factoidFile = parser.Results.factoidFile;
factoids = parser.Results.factoids;
factoidFormat = parser.Results.factoidFormat;
singleSampling = parser.Results.singleSampling;
% default output like the input
if isempty(factoidFile)
[factoidPath, factoidBase] = fileparts(originalFile);
factoidFile = fullfile(factoidPath, [factoidBase '-factoids.xml']);
end
%% Read the in the scene xml document.
sceneDocument = xml2struct(originalFile);
%% Replace the integrator for multiple "fields".
% "multichannel" integrator to hold several "fields"
integrator.Attributes.id = 'integrator';
integrator.Attributes.type = 'multichannel';
sceneDocument.scene.integrator = integrator;
% nested "field" for each factoid
nFactoids = numel(factoids);
fieldIntegrators = cell(1, nFactoids);
for ff = 1:nFactoids
factoidName = factoids{ff};
fieldIntegrator = struct();
fieldIntegrator.Attributes.name = factoidName;
fieldIntegrator.Attributes.type = 'field';
fieldIntegrator.string.Attributes.name = 'field';
fieldIntegrator.string.Attributes.value = factoidName;
fieldIntegrators{ff} = fieldIntegrator;
end
sceneDocument.scene.integrator.integrator = fieldIntegrators;
%% Replace the film for exr and factoid formats.
sceneDocument.scene.sensor.film.Attributes.type = 'hdrfilm';
filmStrings = cell(1, 4);
filmStrings{1}.Attributes.name = 'componentFormat';
filmStrings{1}.Attributes.value = 'float16';
filmStrings{2}.Attributes.name = 'fileFormat';
filmStrings{2}.Attributes.value = 'openexr';
[formatCell{1:nFactoids}] = deal(factoidFormat);
formatList = sprintf('%s, ', formatCell{:});
filmStrings{3}.Attributes.name = 'pixelFormat';
filmStrings{3}.Attributes.value = formatList(1:end-2);
nameList = sprintf('%s, ', factoids{:});
filmStrings{4}.Attributes.name = 'channelNames';
filmStrings{4}.Attributes.value = nameList(1:end-2);
sceneDocument.scene.sensor.film.string = filmStrings;
%% Replace the filter and sampler for simplified rendering?
if singleSampling
sampler.Attributes.id = 'sampler';
sampler.Attributes.type = 'ldsampler';
sampler.integer.Attributes.name = 'sampleCount';
sampler.integer.Attributes.value = 1;
sceneDocument.scene.sensor.sampler = sampler;
rfilter.Attributes.id = 'rfilter';
rfilter.Attributes.type = 'box';
rfilter.float.Attributes.name = 'radius';
rfilter.float.Attributes.value= 0.5;
sceneDocument.scene.sensor.film.rfilter = rfilter;
end
%% Write back the scene document.
struct2xml(sceneDocument, factoidFile);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment