/* Copyright (c) 2016 Chunky contributors * * This file is part of Chunky. * * Chunky is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Chunky is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with Chunky. If not, see <http://www.gnu.org/licenses/>. */ package se.llbit.chunky.renderer.projection; import org.apache.commons.math3.util.FastMath; import se.llbit.math.Constants; import se.llbit.math.Vector3; import java.util.Random; /** * A projector for Omni-Directional Stereo (ODS) images. * * <p>This projector, unlike the {@link PanoramicProjector}, can create distinct * images for the left and the right eye by slightly displacing the view ray origins based on the * viewing angle to account for the inter-pupillary distance. This allows to create panoramic * stereo images that are perfect for viewing on VR devices. * * @see <a href="https://developers.google.com/vr/jump/rendering-ods-content.pdf">Rendering Omni‐directional Stereo Content</a> */ public class OmniDirectionalStereoProjector implements Projector { /** * The inter-pupillary distance of the viewer, in meters. */ private static final double interPupillaryDistance = 0.069; private final double scale; public OmniDirectionalStereoProjector(Eye eye) { if (eye == Eye.LEFT) { scale = -interPupillaryDistance / 2; } else { scale = interPupillaryDistance / 2; } } @Override public void apply(double x, double y, Random random, Vector3 pos, Vector3 direction) { apply(x, y, pos, direction); } @Override public void apply(double x, double y, Vector3 pos, Vector3 direction) { double theta = (x + 0.5) * Math.PI - Constants.HALF_PI; double phi = Constants.HALF_PI - (y + 0.5) * Math.PI; pos.set(FastMath.cos(theta) * scale, 0, FastMath.sin(theta) * scale); direction.set(FastMath.sin(theta) * FastMath.cos(phi), -FastMath.sin(phi), FastMath.cos(theta) * FastMath.cos(phi)); } @Override public double getMinRecommendedFoV() { return 180; } @Override public double getMaxRecommendedFoV() { return 180; } @Override public double getDefaultFoV() { return 180; } public enum Eye { LEFT, RIGHT } }