[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [46287] trunk/blender: Fisheye Camera for Cycles
Dalai Felinto
dfelinto at gmail.com
Fri May 4 18:20:53 CEST 2012
Revision: 46287
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=46287
Author: dfelinto
Date: 2012-05-04 16:20:51 +0000 (Fri, 04 May 2012)
Log Message:
-----------
Fisheye Camera for Cycles
For sample images see:
http://www.dalaifelinto.com/?p=399 (equisolid)
http://www.dalaifelinto.com/?p=389 (equidistant)
The 'use_panorama' option is now part of a new Camera type: 'Panorama'.
Created two other panorama cameras:
- Equisolid: most of lens in the market simulate this lens - e.g. Nikon, Canon, ...)
this works as a real lens up to an extent. The final result takes the
sensor dimensions into account also.
.:. to simulate a Nikon DX2S with a 10.5mm lens do:
sensor: 23.7 x 15.7
fisheye lens: 10.5
fisheye fov: 180
render dimensions: 4288 x 2848
- Equidistant: this is not a real lens model. Although the old equidistant lens simulate
this lens. The result is always as a circular fisheye that takes the whole sensor
(in other words, it doesn't take the sensor into consideration).
This is perfect for fulldomes ;)
For the UI we have 10 to 360 as soft values and 10 to 3600 as hard values (because we can).
Reference material:
http://www.hdrlabs.com/tutorials/downloads_files/HDRI%20for%20CGI.pdf
http://www.bobatkins.com/photography/technical/field_of_view.html
Note, this is not a real simulation of the light path through the lens.
The ideal solution would be this:
https://graphics.stanford.edu/wikis/cs348b-11/Assignment3
http://www.graphics.stanford.edu/papers/camera/
Thanks Brecht for the fix, suggestions and code review.
Kudos for the dome community for keeping me stimulated on the topic since 2009 ;)
Patch partly implemented during lab time at VisGraf, IMPA - Rio de Janeiro.
Modified Paths:
--------------
trunk/blender/intern/cycles/app/cycles_xml.cpp
trunk/blender/intern/cycles/blender/addon/enums.py
trunk/blender/intern/cycles/blender/addon/properties.py
trunk/blender/intern/cycles/blender/blender_camera.cpp
trunk/blender/intern/cycles/kernel/kernel_camera.h
trunk/blender/intern/cycles/kernel/kernel_montecarlo.h
trunk/blender/intern/cycles/kernel/kernel_path.h
trunk/blender/intern/cycles/kernel/kernel_types.h
trunk/blender/intern/cycles/render/camera.cpp
trunk/blender/intern/cycles/render/camera.h
trunk/blender/release/scripts/startup/bl_ui/properties_data_camera.py
trunk/blender/source/blender/blenkernel/intern/camera.c
trunk/blender/source/blender/blenlib/intern/uvproject.c
trunk/blender/source/blender/blenloader/intern/readfile.c
trunk/blender/source/blender/collada/CameraExporter.cpp
trunk/blender/source/blender/makesdna/DNA_camera_types.h
trunk/blender/source/blender/makesrna/intern/rna_camera.c
trunk/blender/source/blender/modifiers/intern/MOD_uvproject.c
Modified: trunk/blender/intern/cycles/app/cycles_xml.cpp
===================================================================
--- trunk/blender/intern/cycles/app/cycles_xml.cpp 2012-05-04 16:17:09 UTC (rev 46286)
+++ trunk/blender/intern/cycles/app/cycles_xml.cpp 2012-05-04 16:20:51 UTC (rev 46287)
@@ -290,9 +290,23 @@
cam->type = CAMERA_ORTHOGRAPHIC;
else if(xml_equal_string(node, "type", "perspective"))
cam->type = CAMERA_PERSPECTIVE;
- else if(xml_equal_string(node, "type", "environment"))
- cam->type = CAMERA_ENVIRONMENT;
+ else if(xml_equal_string(node, "type", "panorama"))
+ cam->type = CAMERA_PANORAMA;
+ if(xml_equal_string(node, "panorama_type", "equirectangular"))
+ cam->panorama_type = PANORAMA_EQUIRECTANGULAR;
+ else if(xml_equal_string(node, "panorama_type", "fisheye_equidistant"))
+ cam->panorama_type = PANORAMA_FISHEYE_EQUIDISTANT;
+ else if(xml_equal_string(node, "panorama_type", "fisheye_equisolid"))
+ cam->panorama_type = PANORAMA_FISHEYE_EQUISOLID;
+
+ xml_read_float(&cam->fisheye_fov, node, "fisheye_fov");
+ xml_read_float(&cam->fisheye_lens, node, "fisheye_lens");
+
+ xml_read_float(&cam->sensorwidth, node, "sensorwidth");
+ xml_read_float(&cam->sensorheight, node, "sensorheight");
+
+
cam->matrix = state.tfm;
cam->need_update = true;
Modified: trunk/blender/intern/cycles/blender/addon/enums.py
===================================================================
--- trunk/blender/intern/cycles/blender/addon/enums.py 2012-05-04 16:17:09 UTC (rev 46286)
+++ trunk/blender/intern/cycles/blender/addon/enums.py 2012-05-04 16:20:51 UTC (rev 46287)
@@ -54,3 +54,9 @@
('RADIUS', "Radius", "Directly change the size of the aperture"),
('FSTOP', "F/stop", "Change the size of the aperture by f/stops"),
)
+
+panorama_types = (
+ ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"),
+ ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"),
+ ('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, take sensor dimensions into consideration"),
+ )
Modified: trunk/blender/intern/cycles/blender/addon/properties.py
===================================================================
--- trunk/blender/intern/cycles/blender/addon/properties.py 2012-05-04 16:17:09 UTC (rev 46286)
+++ trunk/blender/intern/cycles/blender/addon/properties.py 2012-05-04 16:20:51 UTC (rev 46287)
@@ -278,6 +278,25 @@
subtype='ANGLE',
default=0,
)
+ cls.panorama_type = EnumProperty(
+ name="Panorama Type",
+ description="Distortion to use for the calculation",
+ items=enums.panorama_types,
+ default='FISHEYE_EQUISOLID',
+ )
+ cls.fisheye_fov = FloatProperty(
+ name="Field of View",
+ description="Field of view for the fisheye lens",
+ min=0.1745, soft_max=2*math.pi, max=10.0*math.pi,
+ subtype='ANGLE',
+ default=math.pi,
+ )
+ cls.fisheye_lens = FloatProperty(
+ name="Fisheye Lens",
+ description="Lens focal length (mm))",
+ min=0.01, soft_max=15.0, max=100.0,
+ default=10.5,
+ )
@classmethod
def unregister(cls):
Modified: trunk/blender/intern/cycles/blender/blender_camera.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_camera.cpp 2012-05-04 16:17:09 UTC (rev 46286)
+++ trunk/blender/intern/cycles/blender/blender_camera.cpp 2012-05-04 16:20:51 UTC (rev 46287)
@@ -48,6 +48,10 @@
float2 pixelaspect;
+ PanoramaType panorama_type;
+ float fisheye_fov;
+ float fisheye_lens;
+
enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
float sensor_width;
float sensor_height;
@@ -94,9 +98,37 @@
bcam->nearclip = b_camera.clip_start();
bcam->farclip = b_camera.clip_end();
- bcam->type = (b_camera.type() == BL::Camera::type_ORTHO)? CAMERA_ORTHOGRAPHIC: CAMERA_PERSPECTIVE;
- if(bcam->type == CAMERA_PERSPECTIVE && b_camera.use_panorama())
- bcam->type = CAMERA_ENVIRONMENT;
+ switch(b_camera.type())
+ {
+ case BL::Camera::type_ORTHO:
+ bcam->type = CAMERA_ORTHOGRAPHIC;
+ break;
+ case BL::Camera::type_PANO:
+ bcam->type = CAMERA_PANORAMA;
+ break;
+ case BL::Camera::type_PERSP:
+ default:
+ bcam->type = CAMERA_PERSPECTIVE;
+ break;
+ }
+
+ switch(RNA_enum_get(&ccamera, "panorama_type"))
+ {
+ case 1:
+ bcam->panorama_type = PANORAMA_FISHEYE_EQUIDISTANT;
+ break;
+ case 2:
+ bcam->panorama_type = PANORAMA_FISHEYE_EQUISOLID;
+ break;
+ case 0:
+ default:
+ bcam->panorama_type = PANORAMA_EQUIRECTANGULAR;
+ break;
+ }
+
+ bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov");
+ bcam->fisheye_lens = RNA_float_get(&ccamera, "fisheye_lens");
+
bcam->ortho_scale = b_camera.ortho_scale();
bcam->lens = b_camera.lens();
@@ -138,7 +170,7 @@
{
Transform result;
- if(type == CAMERA_ENVIRONMENT) {
+ if(type == CAMERA_PANORAMA) {
/* make it so environment camera needs to be pointed in the direction
of the positive x-axis to match an environment texture, this way
it is looking at the center of the texture */
@@ -172,6 +204,9 @@
bool horizontal_fit;
float sensor_size;
+ cam->sensorwidth = bcam->sensor_width;
+ cam->sensorheight = bcam->sensor_height;
+
if(bcam->sensor_fit == BlenderCamera::AUTO) {
horizontal_fit = (xratio > yratio);
sensor_size = bcam->sensor_width;
@@ -203,7 +238,7 @@
aspectratio = bcam->ortho_scale/2.0f;
}
- if(bcam->type == CAMERA_ENVIRONMENT) {
+ if(bcam->type == CAMERA_PANORAMA) {
/* set viewplane */
cam->left = 0.0f;
cam->right = 1.0f;
@@ -240,6 +275,11 @@
/* type */
cam->type = bcam->type;
+ /* panorama */
+ cam->panorama_type = bcam->panorama_type;
+ cam->fisheye_fov = bcam->fisheye_fov;
+ cam->fisheye_lens = bcam->fisheye_lens;
+
/* perspective */
cam->fov = 2.0f*atan((0.5f*sensor_size)/bcam->lens/aspectratio);
cam->focaldistance = bcam->focaldistance;
Modified: trunk/blender/intern/cycles/kernel/kernel_camera.h
===================================================================
--- trunk/blender/intern/cycles/kernel/kernel_camera.h 2012-05-04 16:17:09 UTC (rev 46286)
+++ trunk/blender/intern/cycles/kernel/kernel_camera.h 2012-05-04 16:20:51 UTC (rev 46287)
@@ -132,17 +132,41 @@
#endif
}
-/* Environment Camera */
+/* Panorama Camera */
-__device void camera_sample_environment(KernelGlobals *kg, float raster_x, float raster_y, Ray *ray)
+__device float3 panorama_to_direction(KernelGlobals *kg, float u, float v, Ray *ray)
{
+ switch (kernel_data.cam.panorama_type) {
+ case PANORAMA_EQUIRECTANGULAR:
+ return equirectangular_to_direction(u, v);
+ break;
+ case PANORAMA_FISHEYE_EQUIDISTANT:
+ return fisheye_to_direction(u, v, kernel_data.cam.fisheye_fov, ray);
+ break;
+ case PANORAMA_FISHEYE_EQUISOLID:
+ default:
+ return fisheye_equisolid_to_direction(u, v, kernel_data.cam.fisheye_lens, kernel_data.cam.fisheye_fov, kernel_data.cam.sensorwidth, kernel_data.cam.sensorheight, ray);
+ break;
+ }
+}
+
+__device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, Ray *ray)
+{
Transform rastertocamera = kernel_data.cam.rastertocamera;
float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
/* create ray form raster position */
ray->P = make_float3(0.0f, 0.0f, 0.0f);
- ray->D = equirectangular_to_direction(Pcamera.x, Pcamera.y);
+#ifdef __CAMERA_CLIPPING__
+ /* clipping */
+ ray->t = kernel_data.cam.cliplength;
+#else
+ ray->t = FLT_MAX;
+#endif
+
+ ray->D = panorama_to_direction(kg, Pcamera.x, Pcamera.y, ray);
+
/* transform ray from camera to world */
Transform cameratoworld = kernel_data.cam.cameratoworld;
@@ -161,17 +185,11 @@
ray->dP.dy = make_float3(0.0f, 0.0f, 0.0f);
Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
- ray->dD.dx = normalize(transform_direction(&cameratoworld, equirectangular_to_direction(Pcamera.x, Pcamera.y))) - ray->D;
+ ray->dD.dx = normalize(transform_direction(&cameratoworld, panorama_to_direction(kg, Pcamera.x, Pcamera.y, ray))) - ray->D;
Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
- ray->dD.dy = normalize(transform_direction(&cameratoworld, equirectangular_to_direction(Pcamera.x, Pcamera.y))) - ray->D;
-#endif
+ ray->dD.dy = normalize(transform_direction(&cameratoworld, panorama_to_direction(kg, Pcamera.x, Pcamera.y, ray))) - ray->D;
-#ifdef __CAMERA_CLIPPING__
- /* clipping */
- ray->t = kernel_data.cam.cliplength;
-#else
- ray->t = FLT_MAX;
#endif
}
@@ -198,7 +216,7 @@
else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
camera_sample_orthographic(kg, raster_x, raster_y, ray);
else
- camera_sample_environment(kg, raster_x, raster_y, ray);
+ camera_sample_panorama(kg, raster_x, raster_y, ray);
}
CCL_NAMESPACE_END
Modified: trunk/blender/intern/cycles/kernel/kernel_montecarlo.h
===================================================================
--- trunk/blender/intern/cycles/kernel/kernel_montecarlo.h 2012-05-04 16:17:09 UTC (rev 46286)
+++ trunk/blender/intern/cycles/kernel/kernel_montecarlo.h 2012-05-04 16:20:51 UTC (rev 46287)
@@ -224,6 +224,57 @@
cos(theta));
}
+/* Fisheye <- Cartesian direction */
+
+__device float3 fisheye_to_direction(float u, float v, float fov, Ray *ray)
+{
+ u = (u - 0.5f) * 2.f;
+ v = (v - 0.5f) * 2.f;
+
+ float r = sqrt(u*u + v*v);
+
+ if (r > 1.0) {
+ ray->t = 0.f;
+ return make_float3(0.f,0.f,0.f);
+ }
+
+ float phi = acosf((r!=0.f)?u/r:0.f);
+ float theta = asinf(r) * (fov / M_PI_F);
+
+ if (v < 0.f) phi = -phi;
+
+ return make_float3(
+ cosf(theta),
+ -cosf(phi)*sinf(theta),
+ sinf(phi)*sinf(theta)
+ );
+}
+
+__device float3 fisheye_equisolid_to_direction(float u, float v, float lens, float fov, float width, float height, Ray *ray)
+{
+ u = (u - 0.5f) * width;
+ v = (v - 0.5f) * height;
+
+ float rmax = 2.f * lens * sinf(fov * 0.5f);
+ float r = sqrt(u*u + v*v);
+
+ if (r > rmax) {
+ ray->t = 0.f;
+ return make_float3(0.f,0.f,0.f);
+ }
+
+ float phi = acosf((r!=0.f)?u/r:0.f);
+ float theta = 2.f * asinf(r/(2.f * lens));
+
+ if (v < 0.f) phi = -phi;
+
+ return make_float3(
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list