Author Topic: Panorama exporter with Google Cardboard  (Read 12382 times)

2015-11-26, 22:33:24
Reply #15

arqrenderz

  • Active Users
  • **
  • Posts: 736
  • arqrenderz.com
    • View Profile
    • arqrenderz
+1 for a stereo camera rig for corona!!!!

2015-11-27, 14:36:04
Reply #16

peterguthrie

  • Active Users
  • **
  • Posts: 241
    • View Profile
    • Peter Guthrie Visualisation
+1 here too!

and thanks for the interesting links rambambulli

2015-11-29, 20:58:02
Reply #17

rambambulli

  • Active Users
  • **
  • Posts: 160
    • View Profile
I don't know how complicated it is to write the Corona Sperical Stereo Rig but I can imagine that there are more urgent issues for the Corona team to work on first :D

So in the meantime I will try to create one. For who is interested, here is my research on this topic. Feel free to comment. I'm new to this so it only can get better.

My first tests are based on the EleVR blog mentioned above and the http://paulbourke.net/stereographics/stereopanoramic/ site.
The Domemaster camera (explained in the EleVr blog part 2) is not working with Corona or I don't understand how to use it. It uses lens shaders I as far as I know they aren't available for Corona.

So I started from scratch using this workflow:
- create a rig made from 2 cameras revolving around a center point. Both cameras a bit (30mm) off to the left and the right to mimic the eyes positions.
I added my simple max file. The rig has as many frames as the renderwidth of the image/strip width. So a image of 2400p pixels has 2400 frames if the strip is 1 pixel wide. 1200 pixels if the strip is 2 pixels wide. etc.
See the rig example image.

- I use the corona spherical lens and slice it in very narrow parts. So if my image is 2400x1200. I render strips of 1x1200 pixels.
(Maybe it is better to render a FOV 180 degrees camera but I get a really strange results.)

- I use a focus point to which both cameras of the rig look. The rig setup is almost similar and easy for parallel.
The third "Off Axis" is a bit more complicated. To produce a correct camera you should use a horizontal tilt shift lens. You can use the Vray camera. Calculate the horizontal tilt and render them. But if I add the coronacameramod to create a spherical image it neutrilizes the tilt shift of the Vray camera. Not solved yet.

- To make it work you should render X thin images and combine them into one big image for each eye/camera. To do this I wrote a few simple lines of maxscript code.
 
Code: [Select]

-- change so the output width of a image divided by the stripwidth makes a whole number
stripwidth = 1
 
-- the left eye image
PanLeft = bitmap renderwidth renderheight
-- the right eye image
PanRight = bitmap renderwidth renderheight
 
--set a region to render a crop
viewport.setRegionRect 1 (Box2 (renderwidth/2) 0 stripwidth renderheight)
 
parts = renderwidth/stripwidth
-- for testing parts = 100  or whatever you like

- for the left eye
 
for t = 0 to parts do (
display panLeft
--make sure the left eye camera is cold cameraL. Or change the name here
viewport.setCamera $cameraL
strip = render rendertype:#crop vfb:false frame:t 
    pastebitmap strip panLeft [0,0] [(t*stripwidth),0]
)
 
-- and for the right eye
 
for t = 0 to parts do (
display panRight
--make sure the left eye camera is cold cameraL. Or change the name here
viewport.setCamera $cameraR
strip = render rendertype:#crop vfb:false frame:t c  pastebitmap strip panRight [0,0] [(t*stripwidth),0]



So far so good. To show you what happend I made a good old red-cyan overlay image. If you have some old school glasses you can check them. It works. (sorry for the extreme dull test image btw)

To remove horizontal lines in low pass renders correct turn off "Lock sampling pattern" in the Corona Render menu. If you leave this option on Corona will render each strip the same way. This results in fine horizontal lines on your images.
 
At the end there is a anti aliasing problem. All strips are stitched together without aliasing. So you get jagged edges. Not solved yet.

So as a conclusion. It works. It is a bit slow. The "off axis" method doesn't work yet. Anti aliasing is a must and doens't work yet.
I will create a script that makes the rig and starts te rendering automaticaly and update the earlier posted javascript so it can be used with 2 images.


« Last Edit: 2015-11-29, 21:13:43 by rambambulli »

2015-12-13, 11:14:55
Reply #18

peterguthrie

  • Active Users
  • **
  • Posts: 241
    • View Profile
    • Peter Guthrie Visualisation
thanks for your work rambambulli

can anyone from the corona team help with the bits that dont work?

2015-12-14, 13:35:37
Reply #19

maru

  • Corona Team
  • Active Users
  • ****
  • Posts: 9978
  • Marcin
    • View Profile
I am trying to get some results with the script. The idea seems to be good. Here is the updated version, I think the code got messed due to copypasting:

Code: [Select]
-- change so the output width of a image divided by the stripwidth makes a whole number
stripwidth = 1
 
-- the left eye image
PanLeft = bitmap renderwidth renderheight
-- the right eye image
PanRight = bitmap renderwidth renderheight
 
--set a region to render a crop
viewport.setRegionRect 1 (Box2 (renderwidth/2) 0 stripwidth renderheight)
 
parts = renderwidth/stripwidth
-- for testing parts = 100  or whatever you like

-- for the left eye
 
for t = 0 to parts do (
display panLeft
--make sure the left eye camera is cold cameraL. Or change the name here
viewport.setCamera $cameraL
strip = render rendertype:#crop vfb:false frame:t 
    pastebitmap strip panLeft [0,0] [(t*stripwidth),0]
)
 
-- and for the right eye
 
for t = 0 to parts do (
display panRight
--make sure the left eye camera is cold cameraL. Or change the name here
viewport.setCamera $cameraR
strip = render rendertype:#crop vfb:false frame:t 
pastebitmap strip panRight [0,0] [(t*stripwidth),0]



2015-12-14, 17:17:43
Reply #20

rambambulli

  • Active Users
  • **
  • Posts: 160
    • View Profile
Oops. Sloppy me. Sorry guys. Thanks Maru.

BTW more errors. At the CameraR comment it should say --make sure the Right eye camera is called cameraR.
A lot of late night testing/copying/pasting :D

2015-12-16, 11:48:51
Reply #21

maru

  • Corona Team
  • Active Users
  • ****
  • Posts: 9978
  • Marcin
    • View Profile
Ok, this officially works. I was able to use it with krpano on my phone + google cardboard. I will be soon back with a full guide. Also, there is a chance that *soon* there will be a built in-option in Corona. ;)

2015-12-16, 13:16:24
Reply #22

arqrenderz

  • Active Users
  • **
  • Posts: 736
  • arqrenderz.com
    • View Profile
    • arqrenderz
So exited to start use it!! :) alredy made some panos for cardboard, I just have to close one eye to see them :P

2015-12-16, 13:44:45
Reply #23

peterguthrie

  • Active Users
  • **
  • Posts: 241
    • View Profile
    • Peter Guthrie Visualisation
Ok, this officially works. I was able to use it with krpano on my phone + google cardboard. I will be soon back with a full guide. Also, there is a chance that *soon* there will be a built in-option in Corona. ;)

great stuff maru, and an official method would be awesome too

2015-12-16, 17:14:47
Reply #24

maru

  • Corona Team
  • Active Users
  • ****
  • Posts: 9978
  • Marcin
    • View Profile
I have just finished upgrading the script as it looked like it's having problems in some scenarios. I have completely 0 scripting knowledge, so it took me a while, but the satisfaction was worth it. :)
I should finish the guide today or tomorrow (the unofficial one).

2015-12-16, 17:17:56
Reply #25

rambambulli

  • Active Users
  • **
  • Posts: 160
    • View Profile
Of course all this is really for the time being and we patiently wait for the official version.

Until then for who is interested I copy/pasted a web based viewer for webgl-gyro-phones. It can view different images for the left and the right eye.
@Maru, I hope it is error free this time :D
I checked it on a iphone 5 with safari and chrome. Both browsers work fine.

Code: [Select]
<!DOCTYPE html>
<html lang="en">
<head>
<title>Stereo Viewer Corona-Cardboard</title>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, initial-scale=1">
<style TYPE="text/css">
body {
margin: 0px;
background-color: #000000;
overflow: hidden;
}


</style>
</head>
<body>

<div id="container"></div>

<script src="js/three.min.js"></script>
<script src="js/DeviceOrientationControls.js"></script>
<script src="js/StereoEffect.js"></script>

<script>
(function() {
  "use strict";

  window.addEventListener('load', function() {

var container
var camera1, scene1, renderer1, controls1, geometry1, mesh1;
var camera2, scene2, renderer2, controls2, geomerty2, mesh2;


var animate = function(){

window.requestAnimationFrame( animate );

controls1.update();
controls2.update();
renderer1.render(scene1, camera1);
renderer2.render(scene2, camera2);

};

container = document.getElementById( 'container' );

camera1 = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.001, 700);
camera1.aspect = (window.innerWidth/2) / window.innerHeight;
camera1.updateProjectionMatrix();

camera2 = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.001, 700);
camera2.aspect = (window.innerWidth/2) / window.innerHeight;
camera2.updateProjectionMatrix();

controls1 = new THREE.DeviceOrientationControls( camera1 );

controls2 = new THREE.DeviceOrientationControls( camera2 );

scene1 = new THREE.Scene();

scene2 = new THREE.Scene();

var geometry1 = new THREE.SphereGeometry( 500, 32, 32 );
geometry1.scale( - 1, 1, 1 );

var geometry2 = new THREE.SphereGeometry( 500, 32, 32 );
geometry2.scale( - 1, 1, 1 );

var material1 = new THREE.MeshBasicMaterial( {
map: THREE.ImageUtils.loadTexture( 'img/YOUR_LEFT_IMAGE.jpg' )
} );

var material2 = new THREE.MeshBasicMaterial( {
map: THREE.ImageUtils.loadTexture( 'img/YOUR_RIGHT_IMAGE.jpg' )
} );

var mesh1 = new THREE.Mesh( geometry1, material1 );
scene1.add( mesh1 );

var mesh2 = new THREE.Mesh( geometry2, material2 );
scene2.add( mesh2 );


renderer1 = new THREE.WebGLRenderer();
renderer1.setPixelRatio( window.devicePixelRatio);
renderer1.setClearColor( 0xffffff );
renderer1.setSize(window.innerWidth/2, window.innerHeight);
renderer1.domElement.style.top = 0;
container.appendChild(renderer1.domElement);

renderer2 = new THREE.WebGLRenderer();
renderer2.setPixelRatio( window.devicePixelRatio);
renderer2.setSize(window.innerWidth/2, window.innerHeight);
renderer2.domElement.style.top = 0;
container.appendChild(renderer2.domElement);


window.addEventListener('resize', function() {

camera1.aspect = (window.innerWidth/2) / window.innerHeight;
camera1.updateProjectionMatrix();

camera2.aspect = (window.innerWidth/2) / window.innerHeight;
camera2.updateProjectionMatrix();

renderer1.setSize((window.innerWidth/2), window.innerHeight );
renderer2.setSize((window.innerWidth/2), window.innerHeight );

}, false);

animate();

  }, false);

})();
</script>

</body>
</html>

2015-12-17, 13:24:03
Reply #26

maru

  • Corona Team
  • Active Users
  • ****
  • Posts: 9978
  • Marcin
    • View Profile
Here is my guide:
https://corona-renderer.com/forum/index.php/topic,10592.msg67619.html#msg67619
If someone has time to test it, it would be appreciated. Let me know if I made some mistake in it, or if something doesn't work. This is the "unofficial" way. VR support should be soon in Corona.