Sample ODS video

I rendered with POV-Ray (using my approach) a sample 360 degree, omnidirectional, stereo video (top/bottom).
Can be used for stress testing VR Video players, HMD etc.

It’s a 120 frame animation, loopable. It mean one seconds at 120 FPS (for example PSVR), 1.25 seconds at 90 FPS (Oculus Rift, HTC Vive), etc.

YouTube Preview:

Real plain preview:

It took around 4 days for rendering on my i7 with eight cores.
Every frame have 7680 x 7680 pixels resolution (Stereo top/bottom), around 32 MB PNG each.
I encoded it in different FPS and resolution. As explained in my other post about ODS, x264 don’t support highest framerate at highest resolution.

ffmpeg command-line encoding:

ffmpeg\bin\ffmpeg.exe -framerate 60 -i sample%03d.png -c:v libx264 -preset veryslow -vf scale=1280:720 -x264-params crf=18 -c:a aac -strict experimental preview.mp4

Download links

Image:
Single shot image, 7680 x 7680 pixels (9370 KB)
Videos:
x264 – 30 FPS – 4K UHD
x265 – 60 FPS – 4K UHD
x265 – 90 FPS – 4K UHD
x265 – 90 FPS – 4K DCI
x265 – 90 FPS – 8K
x265 – 120 FPS – 8K

POV-Ray source code: .pov, .ini.

Omni­directional stereo (ODS) with POV-Ray

Omni­directional stereo (ODS) is a projection model for stereo 360 degree videos
It’s designed for VR viewing with a head­mounted display (HMD).
More information here.

I developed and tested for fun an approach for raytracing, open-source POV-Ray software.

How to render

Currently (2016-03-11), render ODS image require an alpha version of POV-Ray, that support user_defined camera. Download from here
Or use my POV-Ray fork. More information on this below.

With POV-Ray official (Alpha),
Use the following code for an ODS top-bottom (left eye on top, right eye on bottom):

// ODS Top/Bottom - Docs: https://www.clodo.it/blog/?p=80
#declare odsIPD = 0.065; // Interpupillary distance
#declare odsVerticalModulation = 0.2; // Use 0.0001 if you don't care about Zenith & Nadir zones.
#declare odsLocationX = 0;
#declare odsLocationY = 0;
#declare odsLocationZ = 0;
#declare odsHandedness = -1; // "-1" for left-handed or "1" for right-handed
#declare odsAngle = 0; // Rotation, clockwise, in degree. 

camera {
  user_defined
  location {
    function { odsLocationX + cos(((x+0.5+odsAngle/360)) * 2 * pi - pi)*(odsIPD/2*pow(sin(select(y, 1-2*(y+0.5), 1-2*y)*pi), odsVerticalModulation))*select(-y,-1,+1) }
    function { odsLocationY }
    function { odsLocationZ + sin(((x+0.5+odsAngle/360)) * 2 * pi - pi)*(odsIPD/2*pow(sin(select(y, 1-2*(y+0.5), 1-2*y)*pi), odsVerticalModulation))*select(-y,-1,+1) * odsHandedness }
  }
  direction {
    function { sin(((x+0.5+odsAngle/360)) * 2 * pi - pi) * cos(pi / 2 -select(y, 1-2*(y+0.5), 1-2*y) * pi) }
    function { sin(pi / 2 - select(y, 1-2*(y+0.5), 1-2*y) * pi) }
    function { -cos(((x+0.5+odsAngle/360)) * 2 * pi - pi) * cos(pi / 2 -select(y, 1-2*(y+0.5), 1-2*y) * pi) * odsHandedness }
  }
}

Use the following code for an ODS side-by-side:

// ODS Side-by-Side - Docs: https://www.clodo.it/blog/?p=80
#declare odsIPD = 0.065; // Interpupillary distance
#declare odsVerticalModulation = 0.2; // Use 0.0001 if you don't care about Zenith & Nadir zones.
#declare odsLocationX = 0;
#declare odsLocationY = 0;
#declare odsLocationZ = 0;
#declare odsHandedness = -1; // "-1" for left-handed or "1" for right-handed
#declare odsAngle = 0; // Rotation, clockwise, in degree. 

camera {
  user_defined
  location {
    function {  odsLocationX + cos(((select(x,2*(x+0.5),2*x)+odsAngle/360)) * 2 * pi - pi)*(odsIPD/2*pow(sin((1-(y+0.5))*pi), odsVerticalModulation))*select(x,-1,1) }
    function {  odsLocationY }
    function {  odsLocationZ + sin(((select(x,2*(x+0.5),2*x)+odsAngle/360)) * 2 * pi - pi)*(odsIPD/2*pow(sin((1-(y+0.5))*pi), odsVerticalModulation))*select(x,-1,1) * odsHandedness }
  }
  direction {
    function {  sin(((select(x,2*(x+0.5),2*x)+odsAngle/360)) * 2 * pi - pi) * cos(pi / 2 -(1-(y+0.5)) * pi) }
    function {  sin(pi / 2 - (1-(y+0.5)) * pi) }
    function {  -cos(((select(x,2*(x+0.5),2*x)+odsAngle/360)) * 2 * pi - pi) * cos(pi / 2 -(1-(y+0.5)) * pi) * odsHandedness }
  }
}     

Use the following code for single eye rendering:

// ODS Single Eye - Docs: https://www.clodo.it/blog/?p=80
#declare odsIPD = 0.065; // Interpupillary distance     
#declare odsVerticalModulation = 0.2; // Use 0.0001 if you don't care about Zenith & Nadir zones.
#declare odsLocationX = 0;
#declare odsLocationY = 0;
#declare odsLocationZ = 0;
#declare odsHandedness = -1; // "-1" for left-handed or "1" for right-handed
#declare odsAngle = 0; // Rotation, clockwise, in degree.              
#declare odsEye = -1; // -1 for Left eye, +1 for Right eye

camera {
  user_defined
  location {
    function {  odsLocationX + cos(((x+0.5+odsAngle/360)) * 2 * pi - pi)*(odsIPD/2*pow(sin((1-(y+0.5))*pi), odsVerticalModulation))*odsEye }
    function {  odsLocationY }
    function {  odsLocationZ + sin(((x+0.5+odsAngle/360)) * 2 * pi - pi)*(odsIPD/2*pow(sin((1-(y+0.5))*pi), odsVerticalModulation))*odsEye * odsHandedness }
  }
  direction {
    function {  sin(((x+0.5+odsAngle/360)) * 2 * pi - pi) * cos(pi / 2 -(1-(y+0.5)) * pi) }
    function {  sin(pi / 2 - (1-(y+0.5)) * pi) }
    function {  -cos(((x+0.5+odsAngle/360)) * 2 * pi - pi) * cos(pi / 2 -(1-(y+0.5)) * pi) * odsHandedness }
  }
}                               

Caveats

  • Camera Direction is actually not supported. It’s always look_at<0,0,1>. You can use the odsAngle parameter for a rotation (degree) around Y axis.
  • Zenith & Nadir Zones
    Base ODS algorithm have spiral/singularities towards the zenith and nadir points.To avoid that, i modulate the stereoscopic eye separation such that it begins at normal eye separation near the horizon, and is smoothly decreased, reaching zero by the time either the zenith or nadir points on the polar axis are visible to the user, producing a monoscopic image.

    I use this formula:

    where 0.02 it’s the odsVerticalModulation and 0.065 the default IPD. Play with this value to understand how IPD are reduced near the Zenith (x:-0.5) and Nadir (x:0.5).

    In general, it’s recommended to avoid objects at zenith & nadir points, and use a odsVerticalModulation near 0 (0.0001), to obtain a perfect IPD / 3d effect.
    If you have objects at zenith & nadir points, use a odsVerticalModulation near 1 can be a good compromise.

    Other approach:
    Domemaster3D (Shader for 3DS Max, Mata, Softimage etc) recommend a texture to reduce the effect. link

    SolidAngle/Arnold use mixed approach. link

    Another kind of modulation: link

Best practice

  • Objects should remain at least 60cm from the camera (relative to an IPD of 6.5cm).
    Use this POV-Ray code to check (it’s auto adapt based on IPD):

    sphere
    {
      <odsLocationX,odsLocationY,odsLocationZ>, 0.6*odsIPD/0.065
      pigment
      {
        color <1,0,0>
        filter 0.97
      }
      hollow
    }
    
  • Objects appearing directly above or below the camera should remain at least 3.5m from the camera (relative to an IPD of 6.5cm).
  • Antialiasing is very very very important on VR headset.

Recommended Resolutions

I recommend, at least for the current (year 2016) generation of VR headset (GearVR, Oculus Rift, HTC Vive), at least 6480 x 6480 pixels in top/bottom for static images. For videos, see below.

Resolution must have 2:1 aspect ratio (standard equirectangular), that become 4:1 for side-by-side or 1:1 for a top-bottom.

TL;DR;
It’s difficult to estimate a good resolution.
VR headset do a distortion for lenses, any every VR headset can have different lenses, different FOV, different panel resolution etc.

The GearVR for example has a 90° FOV on a 2560×1440 panel, but the center pixel covers 0.06° after distortion. This value is sometime called “pixel coverage” or “pixel density” or “pixel per display pixel” or “eye buffer scaling”. So, for the GearVR, 0.06° pixels means we need 360/0.06 = 6000 pixels to cover one monoscopic turn.

Rendering Animation/Video

This is actually problematic.

In theory, the resolution must be at least as explained above for images.

Any VR headset require a high frame-rate to avoid nausea.

  • Oculus Rift DK2 (Development Kit 2): 75 FPS
  • Oculus Rift CV1 (Customers Version 1): 90 FPS
  • HTC Vive: 90 FPS
  • Sony Playstation PSVR : 120 FPS

In general, future-generation VR headset: expected 120 FPS

But H264 don’t have any level profile compatible with this kind of resolution.
Also HEVC/H265 have the same problem.

But we also need a coded that is hardware-accelerated to obtain the high FPS requested, and generally only H264/H265 are optimized for this.

VR Players

Virtual Desktop – There isn’t any option about side-by-side vs top-bottom, it simply detect it from the aspect ratio: 4:1 for side-by-side, 1:1 for top/bottom.

MaxVR

Both player can’t reproduce H265 high resolution videos.

My POV-Ray fork on GIT-Hub

With a POV-Ray builded from my fork, you can simply use a spherical camera:

camera
{             
  spherical   
  //ipd 0.065
  ods 4 
  //ods_angle 0
  //ods_modulation 0.2
  //ods_handedness 1
  location <0,0,0>  
}             
  • ods: 0 for monoscopic image, 1 for left eye only, 2 for right eye only, 3 for side-by-side, 4 for top/bottom. 0 is default. 4 recommended.
  • Other parameters ipd, ods_angle, ods_modulation and ods_handedness are the same of the user_defined approach param described above.

Interesting Links

Kudos

Many, many thanks to:

Christoph Lipka, William F Pokorny, Jaime Vives Piqueres from POV-Ray newsgroup.
Joan from Oculus Forum.
Jakob Flierl (checkout is GIT-Hub repo about ODS).

Examples of rendering

Some example of rendering (6480 x 6480 pixels, Top-Bottom).

Mirrors – I made this

——————
Stacker Day – POV-Ray sample scene adapted for ODS

——————
Fractals 1 – POV-Ray sample scene adapted for ODS

——————
Fractals 2 – POV-Ray sample scene adapted for ODS

——————
Wineglass – POV-Ray sample scene adapted for ODS

——————
Axis – Test reference

I also rendered a sample video that can be used for stress-testing of VR video players.

QUICKRES.INI

Reference resolutions for POV-Ray quickres.ini

[ODS TB Quick Test - 512 x 512]
Width=512
Height=512
Antialias=Off

[ODS TB Test - 1024 x 1024]
Width=1024
Height=1024
Antialias=Off

[ODS TB Minimum - 3600 x 3600]
Width=3600
Height=3600
Antialias=On
Antialias_Threshold=0.3

[ODS TB High - 6480 x 6480]
Width=6480
Height=6480
Antialias=On
Antialias_Threshold=0.3

[ODS TB Ultra - 12288 x 12288]
Width=12288
Height=12288
Antialias=On
Antialias_Threshold=0.3

[ODS TB 1440p - 2560 x 1440]
Width=2560
Height=1440
Antialias=On
Antialias_Threshold=0.3

[ODS TB UHD-1 2160p - 3840 x 2160]
Width=3840
Height=2160
Antialias=On
Antialias_Threshold=0.3

[ODS TB DCI 4K - 4096 x 2160]
Width=4096
Height=2160
Antialias=On
Antialias_Threshold=0.3

[ODS TB 8K UHD - 7680 x 4320]
Width=7680
Height=4320
Antialias=On
Antialias_Threshold=0.3

[ODS LR Minimum - 7200 x 1800]
Width=7200
Height=1800
Antialias=On
Antialias_Threshold=0.3

[ODS LR High - 12960 x 3240]
Width=12960
Height=3240
Antialias=On
Antialias_Threshold=0.3

[ODS LR Ultra - 24576 x 6144]
Width=24576
Height=6144
Antialias=On
Antialias_Threshold=0.3
[ODS LR Low - 7200 x 1800]
Width=7200
Height=1800
Antialias=On
Antialias_Threshold=0.3

[ODS LR Normal - 12960 x 3240]
Width=12960
Height=3240
Antialias=On
Antialias_Threshold=0.3

[ODS LR High - 24576 x 6144]
Width=24576
Height=6144
Antialias=On
Antialias_Threshold=0.3

[ODS TB Low - 3600 x 3600]
Width=3600
Height=3600
Antialias=On
Antialias_Threshold=0.3

[ODS TB Normal - 6480 x 6480]
Width=6480
Height=6480
Antialias=On
Antialias_Threshold=0.3

[ODS TB High - 12288 x 12288]
Width=12288
Height=12288
Antialias=On
Antialias_Threshold=0.3

[ODS TB YouTube - 3840 x 2160]
Width=3840
Height=2160
Antialias=On
Antialias_Threshold=0.3

An alternative approach to so-called WebRTC leaks

Posted on Reddit here: http://redd.it/32d94q

Recently there were a lot of discussions about the WebRTC IP Leak. Almost all of them are talking about a “Security flaw” or treat it as a bug.

However, many articles about the WebRTC [leaks] talk about a solution: disable WebRTC in favorite browser.
Two questions:

  • Is it really a “Security flaw” that needs to be fixed in browsers? Look at browsers bug-reports to understand how many different opinions exist on this.
  • Why the browser can go outside the VPN tunnel? How many app/protocols can do the same things of the WebRTC leak? So, is disabling WebRTC a sufficient solution for those who use a VPN to avoid exposing their ISP IP address or traffic?

I will explain details of the issue. But first, if you are connected to a VPN service right now, try this:

ipdetection.zip (source available here )

or, under Unix try this (try also as root):

for s in `ifconfig -a | sed 's/[ \t].*//;/^\(lo\|\)$/d'`; do curl --interface $s http://www.clodo.it/projects/whatismyip/; done

Is your real ISP IP leaked?

Details

When a user connects to OpenVPN, the main interface (ethernet, wifi etc) is still available (also to talk with the VPN server itself).
And another network interface is opened (tun/tap).
This is the scope of OpenVPN: create a tunnel.

As a plus, OpenVPN can be configured to push a directive from the server to their client: “redirect-gateway”.
This tells at client-side that ALL traffic needs to be redirected inside the tunnel by default.

Almost all VPN services use a specific option of that directive: “redirect-gateway def1”.
From OpenVPN manual

def1 — Use this flag to override the default gateway by using 0.0.0.0/1 and 128.0.0.0/1 rather than 0.0.0.0/0. This has the benefit of overriding but not wiping out the original default gateway.

Now, this means that the original 0.0.0.0/0 route are still active, but there are other routes created by OpenVPN that override the original based on precedence.
But 0.0.0.0/0 is a route assigned to the standard interface, while the new 0.0.0.0/1 and 128.0.0.0/1 are assigned to the TUN interface.

In every OS, when a connection/socket is opened, the program can choose a specific network interface that needs to be used.
This is not common, because most applications don’t need that and let the OS use the default network interface.

The program above do exactly this: bind to specific network interface to query an external what is my ip address service.
When binding to the standard interface, the overriding rules of OpenVPN are simply ignored, at least under Windows.

I think browsers do the same thing in WebRTC discovery.

Can a VPN service based on OpenVPN resolve the issue server-side, transparently to their users?

Yes.
Simply don’t use the def1 option in redirect-gateway directive.
Without def1, OpenVPN client removes totally the 0.0.0.0/0 route, and re-creates it at disconnection.

But I don’t recommend this approach: with def1, if the OpenVPN process is terminated, the overriding routes are automatically deleted or unused, and traffic continues to flow over the standard interface.
Without def1, if OpenVPN process is killed/terminated, the user remains without any route for his/her traffic.

For me, a good VPN service needs to use the def1 option, for the final consideration below.

Final consideration

WebRTC IP Leak is not a fault of browsers.

It is not a fault of OpenVPN (that is designed to be a Tunneling software, not an Always hide my traffic software).

It is a fault of users, because they trust the standard OpenVPN client for things out of its scope, or trust a badly-written VPN service client software.

Users need to use a VPN service that has a software addressing this kind of issue, or need to understand how to configure a firewall or a router.

*Disclaimer: *
I’m the author of the client software of a known VPN service. Anyway I don’t cite it in this reddit.

Sphere spirals, 1958, MC Escher

Immagine inviata

Immagine inviata Immagine inviata Immagine inviata Immagine inviata Immagine inviata

Download MP4

Rendering di una isosuperficie ispirata da un’opera di Escher, Sphere Spirals.
Formule per Povray da “Almost Sphere Spirals” by Tor Olav Kristensen (2002)

‘Tor Olav Kristensen’ said

An isosurface shape inspired by M.C. Escher’s “Sphere Spirals” (“Bolspiralen”) woodcut print from 1958. The edges of the four spiraling bands on the sphere can be formed by an inverse stereographic projection of eight infinite logarithmic spirals in a complex plane tangent to a Riemann Sphere onto it’s surface. I found some useful information about this shape here.

Shot 1: Twisting rate a 1.5, 4 bande. 1920 x 1080. Rendering: 2 ore circa.
Shot 2: Twisting rate a 0.1, 1 banda. 1920 x 1080. Rendering: 20 ore circa.
Shot 3: Twisting rate a 0.5, 4 bande. 1920 x 1080. Rendering: 8 ore circa.
Shot 4: Twisting rate a 1.9, 12 bande. 1920 x 1080. Rendering: 1 ora circa.
Shot 5: Twisting rate a 1.0, 4 bande, fog. 1920 x 1080. Rendering: 8 ore circa.
Animazione: Twisting rate variabile da 1 a 3, 4 bande. 640 x 360, 30 fps, 600 fotogrammi (20 sec). Rendering: 2-3 settimane su 3 macchine circa, tempo variabile da 3 ore a mezz’ora per ogni fotogramma.

Tutti con antialiasing di default, senza radiosità.
In dettaglio, i riflessi non incidono particolarmente nei tempi di rendering. E’ l’isosuperficie che “ammazza”, in particolare con bassi valori di twisting rate.

Sorgenti (PovRay 3.6 richiesto, 3.7 consigliato): ini, pov.

Forsaken

*** Semi-finalist for VCAs 2006 – Category “Best First Video” ***

The video is a ‘reassumed/summary’ of the Evangelion’s The End film, so
all the images in the AMV are exposed in the (almost) same sequence from the film.

I started this project in november 2005, so in two month (approximately 100 hours) i study After Effects 6.5 and create this video.
It was my first experience with AMV and After Effects, but i’m a code developer and i already know concepts like ‘keyframes’,’layers’ etc, so i understand quickly how this software works.

In the first pre-release, the video had many effects on it, but before the official release i removed many of the effects to create a more ‘clean’ videos, but i don’t remove the subtitles. This was a wrong choice….

In march 2006, i re-render the video without subtitles and better quality (with some encoding tips from my friend rei.andrea), available as ‘direct link’.

Here you can download the jpeg of the mosaic used in the intro, it’s a mosaic of Rei and Eva01, made with all frames of the films ‘The End Of Evangelion’ with AndreaMosaic free software.

Anime

Evangelion – The End Of Evangelion (Renewal)

Music

Artist : Within Temptation
Intro : Deceiver of Fools (Album: Mother Earth)
AMV : Forsaken (Album: The Silent Force)
End Titles : Memories (Album: The Silent Force)

English Lyrics

Now the day has come
We are forsaken this time

We lived our lives in our paradise,
As gods we shaped the world around
No borderlines we'd stay behind,
Though balance is something fragile

While we thought we were gaining,
We would turn back the tide, it still slips away
Our time has run out, our future has died,
There's no more escape

Now the day has come,
We are forsaken,
There's no time anymore
Life will pass us by,
We are forsaken,
We're the last of our kind

The sacrifice was much too high,
Our greed just made us all go blind
We tried to hide what we fared inside
Today is the end of tomorrow

As the sea started rising,
The land that we'd conquered just washed away
Although we all have tried to turn back the tide,
It was all in vain

Now the day has come,
We are forsaken,
There's no time anymore
Life will pass us by,
We are forsaken,
Only ruins stay behind

Now the day has come
We are forsaken this time

Now the day has come,
We are forsaken,
There's no time anymore

Now the day has come
The day has come
The day has come

Italian Lyrics

E' arrivato il giorno
in cui saremo dimenticati

Abbiamo vissuto le nostre vite nel nostro paradiso
Come Dei modellammo il nostro mondo
Nessun confine da rispettare
Benchè l'equilibrio fosse fragile

Volevamo risalire la corrente
Ma mentre pensavamo di guadagnarci essa lentamente scivola via
Il nostro tempo è finito, il nostro futuro è morto
Non c'è via di salvezza

E' arrivato il giorno
In cui saremo dimenticati
Non c'è più tempo ormai
La vita è trascorsa
Ci hanno dimenticato
Siamo gli ultimi del nostro genere

Il sacrificio è stato troppo alto
Fummo accecati dalla nostra avarizia
Abbiamo cercato di nascondere ciò che temevamo
Oggi è la fine del domani

Il mare si è innalzato
La terra che avevamo conquistato è stata spazzata via
Anche se tutti abbiamo provato a girare indietro la marea
Tutto è stato vano

E' arrivato il giorno
in cui saremo dimenticati
Non c'è più tempo ormai
La vita è trascorsa
Ci hanno dimenticato
Solo rovine alle nostre spalle

E' arrivato il giorno
Siamo stati abbandonati questa volta

E' arrivato il giorno
in cui saremo dimenticati
Non c'è più tempo ormai

Ora il giorno è arrivato
Il giorno è arrivato
Il giorno è arrivato

Software

Adobe After Effects 6.5 & TrapCode”s Plugins
AndreaMosaic
VirtualDubMod
Media Player Classic
Adobe Illustrator
UltraEdit-32

Links

JPEG intro mosaic (25.7 MB, 7617×5240 pixels)
Download Direct (190 MB, 704×384, Best quality available)
One of YouTube copy