yaphyre.YaPhyRe.java Source code

Java tutorial

Introduction

Here is the source code for yaphyre.YaPhyRe.java

Source

/*
 * Copyright 2014 Michael Bieri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yaphyre;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import yaphyre.core.Camera;
import yaphyre.core.Film;
import yaphyre.core.Sampler;
import yaphyre.films.ImageFile;
import yaphyre.films.ImageFile.ImageFormat;
import yaphyre.raytracer.RayTracer;
import yaphyre.raytracer.Scene;
import yaphyre.samplers.JitteredSampler;
import yaphyre.samplers.RandomSampler;
import yaphyre.samplers.RegularSampler;
import yaphyre.samplers.SinglePointSampler;
import yaphyre.scenereaders.SceneReaders;
import yaphyre.scenereaders.yaphyre.MultiStageXMLSceneReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;

/**
 * The main class starting the application. This class parses the command line, prepares the environment and calls the
 * renderer.
 *
 * @author Michael Bieri
 * @author $LastChangedBy$
 * @version $Revision$
 */
public class YaPhyRe {

    private static final Logger LOGGER = LoggerFactory.getLogger(YaPhyRe.class);

    private static final String DEFAULT_HEIGHT = "960";

    private static final String DEFAULT_WIDTH = "1280";

    private static final String DEFAULT_OUTPUT_FILE = "color";

    private static final String DEFAULT_FILE_FORMAT = "PNG";

    private static final int DEFAULT_SAMPLE_NUMBER = 4;

    private static Options commandLineOptions = null;

    private YaPhyRe() {
    }

    public static void main(String... args) throws IOException {

        LOGGER.info("Starting renderer");

        LOGGER.info("Parsing command line");
        CommandLine commandLine;
        try {
            commandLine = YaPhyRe.parseCommandLine(args);
        } catch (ParseException e) {
            LOGGER.error(e.getMessage());
            printHelp();
            return;
        }

        if (commandLine.hasOption("help")) {
            printHelp();
            return;
        }

        LOGGER.debug("Testing scene reader");
        String sceneFileName = commandLine.getOptionValue('i');
        if (sceneFileName != null && !sceneFileName.trim().isEmpty()) {
            try {
                InputStream sceneFile = new FileInputStream(sceneFileName);
                SceneReaders sceneReader = new MultiStageXMLSceneReader();
                Scene scene = sceneReader.readScene(sceneFile);
                System.out.println("Scene: " + scene.toString());
                sceneFile.close();
            } catch (Exception e) {
                LOGGER.debug("Error debugging scene reader", e);
            }
        }

        LOGGER.debug("Setup camera");
        int imageWidth = Integer.parseInt(commandLine.getOptionValue('w', DEFAULT_WIDTH));
        int imageHeight = Integer.parseInt(commandLine.getOptionValue('h', DEFAULT_HEIGHT));
        String imageFormat = commandLine.getOptionValue('f', DEFAULT_FILE_FORMAT);

        LOGGER.debug("Read scene");
        Scene readScene = readScene(commandLine);
        for (Camera camera : readScene.getCameras()) {
            Film film = new ImageFile(imageWidth, imageHeight);
            camera.setFilm(film);
        }

        LOGGER.debug("Initialize sampler");
        Sampler sampler = parseSampler(commandLine);

        LOGGER.debug("Initializing RayTracer");
        RayTracer rayTracer = new RayTracer();
        rayTracer.setScene(readScene);
        rayTracer.setSampler(sampler);
        if (commandLine.hasOption("single")) {
            LOGGER.info("Using single threaded renderer");
            rayTracer.useSingleThreadedRenderer();
        } else {
            LOGGER.info("Using multi threaded renderer");
        }

        LOGGER.info("Render image");
        rayTracer.render();

        LOGGER.debug("Write image file(s)");
        String fileName = commandLine.getOptionValue('o', DEFAULT_OUTPUT_FILE);
        int imageIndex = 0;
        for (Camera camera : readScene.getCameras()) {
            Film film = camera.getFilm();
            File imageFile = new File(
                    MessageFormat.format("{0}_{1,number,000}.{2}", fileName, imageIndex, imageFormat));
            imageIndex++;
            film.writeImageFile(imageWidth, imageHeight, imageFile.getAbsolutePath());

            LOGGER.info("Output written to: {}", imageFile.getAbsolutePath());
        }

        LOGGER.info("Renderer finished");

    }

    private static Scene readScene(CommandLine commandLine) {
        String sceneName = commandLine.getOptionValue('s').trim().toLowerCase();
        LOGGER.info("Trying to load scene <{}>", sceneName);
        Scene result;
        if (sceneName.equals("first")) {
            result = SceneReader.createFirstLight();
        } else if (sceneName.equals("spheres")) {
            result = SceneReader.createSceneWithSpheres();
        } else if (sceneName.equals("simple")) {
            result = SceneReader.createSimpleScene();
        } else if (sceneName.equals("dof")) {
            result = SceneReader.createDOFScene();
        } else if (sceneName.equals("area")) {
            LOGGER.warn("This scene cannot be created any more.");
            result = SceneReader.createFirstLight();
        } else {
            LOGGER.warn("Scene not found! Using fallback scene (first)");
            result = SceneReader.createFirstLight();
        }
        return result;
    }

    private static Sampler parseSampler(CommandLine commandLine) {
        String[] samplerSettings = commandLine.getOptionValues('a');
        int sampleCount = DEFAULT_SAMPLE_NUMBER;
        if (samplerSettings.length == 2) {
            sampleCount = Integer.parseInt(samplerSettings[1]);
        }
        Sampler sampler;
        if (samplerSettings[0].equalsIgnoreCase("single")) {
            sampler = new SinglePointSampler();
        } else if (samplerSettings[0].equalsIgnoreCase("regular")) {
            sampler = new RegularSampler(sampleCount);
        } else if (samplerSettings[0].equalsIgnoreCase("random")) {
            sampler = new RandomSampler(sampleCount);
        } else if (samplerSettings[0].equalsIgnoreCase("jittered")) {
            sampler = new JitteredSampler(sampleCount);
        } else {
            // Fallback to make sure that a sampler is set.
            sampler = new SinglePointSampler();
        }
        LOGGER.debug("Sampler: {}", sampler.toString());
        return sampler;
    }

    private static void printHelp() {
        HelpFormatter formatter = new HelpFormatter();
        formatter.setWidth(999);
        formatter.printHelp("java YaPhyRe", commandLineOptions, true);
    }

    @SuppressWarnings("static-access")
    private static CommandLine parseCommandLine(String... args) throws ParseException {
        CommandLineParser parser = new PosixParser();
        commandLineOptions = new Options();
        commandLineOptions.addOption(OptionBuilder.withArgName("first|spheres|simple|dof|area").hasArg()
                .isRequired().withLongOpt("scene").withDescription("Scene to render").create('s'));
        commandLineOptions.addOption(OptionBuilder.withArgName("file").hasArg().withLongOpt("out")
                .withDescription("Output file name").create('o'));
        commandLineOptions.addOption(OptionBuilder.withArgName("file").hasArg().withLongOpt("in")
                .withDescription("Scene file name").create('i'));
        commandLineOptions.addOption(OptionBuilder.withArgName("format").hasArg().withLongOpt("format")
                .withDescription("Format of the output image file").create('f'));
        commandLineOptions.addOption(OptionBuilder.withArgName("pixel").hasArg().withLongOpt("width")
                .withDescription("Width of the rendered image").create('w'));
        commandLineOptions.addOption(OptionBuilder.withArgName("pixel").hasArg().withLongOpt("height")
                .withDescription("Height of the rendered image").create('h'));
        commandLineOptions.addOption(OptionBuilder.withArgName("single|regular|random|jittered [samples]")
                .hasArgs(2).withLongOpt("sampling").isRequired()
                .withDescription("Type and number of samples for anti aliasing").create('a'));
        commandLineOptions.addOption(OptionBuilder.withLongOpt("single")
                .withDescription("Perform rendering with in a single task").create());
        commandLineOptions.addOption(OptionBuilder.withLongOpt("help").withDescription("Shows this help").create());
        return parser.parse(commandLineOptions, args);
    }
}