Skip to content

Instantly share code, notes, and snippets.

@fieldOfView
Last active November 4, 2017 16:43
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fieldOfView/4031189 to your computer and use it in GitHub Desktop.
Save fieldOfView/4031189 to your computer and use it in GitHub Desktop.
Equirectangular remapper Pixel Bender filter
/**
* Equirectangular remapper
* Last update: 7 November 2012
*
* Changelog:
* 1.0 - Initial release
* 2.0 - Rewrite with polar<->carthesian instead of euler<->matrix math
*
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*
* Credits and references
* ======================
*
* Inspired by LittlePlanets by subblue:
* http://www.subblue.com/blog/2010/6/17/little_planets
*
* A good selection of cosc-licensed equirectangular panorama source images can be found here:
* http://www.flickr.com/photos/sbprzd/sets/72057594100163739/
* http://www.flickr.com/photos/heiwa4126/sets/72157601609820530/
* http://www.flickr.com/search/?q=equirectangular&z=e&l=deriv&ss=2&ct=5&mt=all&adv=1
*
*
* Contact
* =======
*
* This plugin is free to use for personal or commercial projects.
* I'd love to hear how you are using it so email me at aldo@fieldofview.com
*
*/
#define TWOPI 6.283185307179586
#define PI 3.141592653589793
<languageVersion : 1.0;>
kernel EquirectangularRemap2
< namespace : "com.fieldofview";
vendor : "Aldo Hoeben - www.fieldofview.com";
version : 1;
displayname: "Equirectangular Remapper";
description : "Rotates an equirectangular panorama image.";
>
{
parameter float2 size
<
minValue: float2(8, 4);
maxValue: float2(4096, 4096);
defaultValue: float2(2000, 1000);
stepInterval: float2(1, 1);
displayName: "Input image size";
componentName: "Width|Height";
aeDisplayName: "Input image size";
>;
parameter float2 outputSize
<
minValue: float2(8, 4);
maxValue: float2(4096, 4096);
defaultValue: float2(800, 400);
stepInterval: float2(1, 1);
displayName: "Output image size";
componentName: "Width|Height";
aeDisplayName: "Output image size";
>;
parameter float longitude
<
minValue: -180.0;
maxValue: 180.0;
defaultValue: 0.0;
stepInterval: 0.5;
displayName: "Longitude offset";
aeDisplayName: "Longitude offset";
aeUIControl:"aeAngle";
>;
parameter float latitude
<
minValue: -90.0;
maxValue: 90.0;
defaultValue: 0.0;
stepInterval: 0.5;
displayName: "Latitude offset";
aeDisplayName: "Latitude offset";
aeUIControl:"aeAngle";
>;
parameter float rotate
<
minValue: -180.0;
maxValue: 180.0;
defaultValue: 0.0;
stepInterval: 0.5;
displayName: "Rotate";
aeDisplayName: "Rotate";
aeUIControl:"aeAngle";
>;
input image4 src;
output pixel4 dst;
#if !AIF_FLASH_TARGET
region needed(region outputRegion, imageRef inputRef)
{
return region(float4(0, 0, size.x, size.y));
}
region changed(region outputRegion, imageRef inputRef)
{
return region(float4(0, 0, outputSize.x, outputSize.y));
}
#endif
//
// utility functions
//
float wrap(float angle)
{
return (angle<0.)?angle+TWOPI:angle;
}
//
// polar <-> spherical conversion
//
float3 polarToSpherical(float2 polar)
{
return float3(
sin(polar.y)*cos(polar.x),
sin(polar.y)*sin(polar.x),
cos(polar.y)
);
}
float2 sphericalToPolar(float3 spherical)
{
return float2(wrap(
(spherical.x>0.)?
atan(spherical.y / spherical.x):
PI+atan(spherical.y / spherical.x)
),
acos(spherical.z)
);
}
//
// rotation of a 2d point around the origin
//
float2 rotate2d(float2 point, float angle)
{
return float2(
point.x*cos(angle) - point.y*sin(angle),
point.x*sin(angle) + point.y*cos(angle)
);
}
// note: euler vectors are expressed in radians,
// axes: bank/roll around x-axis, attitude/pitch around y-axis, heading/yaw around z-axis
// http://en.wikipedia.org/wiki/Spherical_coordinate_system
// order: bank/roll, attitude/pitch, heading/yaw
// to match PTGUI
void evaluatePixel()
{
float2 polar = float2(TWOPI,PI) * outCoord() / outputSize;
float3 spherical = polarToSpherical( polar );
spherical.yx = rotate2d( spherical.yx, PI*longitude/180. );
spherical.xz = rotate2d( spherical.xz, PI*latitude/180. );
spherical.zy = rotate2d( spherical.zy, PI*rotate/180. );
polar = size * sphericalToPolar( spherical ) / float2(TWOPI,PI);
dst = sampleNearest(src, polar);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment