Fix 73841 : Game Engine - Camera Lens Shift

This is essential for video projection, and the alternative until now was to manually change the projection matrix via Python.
( http://www.blender.org/manual/game_engine/camera/introduction.html#camera-lens-shift
- this page will be removed as soon as I commit this)

Also this is working for perspective and orto cameras BUT if the sensor is not AUTO it will only look correct in blenderplayer (this is an unrelated bug, but just in case someone runs into it while testing this, now you know why you got the issue).

Kudos for the BlenderVR project for supporting this feature development.

Differential Revision: https://developer.blender.org/D1379
This commit is contained in:
Dalai Felinto 2015-06-29 10:45:27 -03:00
parent 3d12d4b94f
commit f12b1790a0
Notes: blender-bot 2023-02-14 11:15:40 +01:00
Referenced by issue #38451, Camera Lens Shift Game Engine
8 changed files with 83 additions and 14 deletions

View File

@ -1461,7 +1461,7 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l
static KX_Camera *gamecamera_from_bcamera(Object *ob, KX_Scene *kxscene, KX_BlenderSceneConverter *converter)
{
Camera* ca = static_cast<Camera*>(ob->data);
RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->sensor_x, ca->sensor_y, ca->sensor_fit, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, ca->YF_dofdist);
RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->sensor_x, ca->sensor_y, ca->sensor_fit, ca->shiftx, ca->shifty, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, ca->YF_dofdist);
KX_Camera *gamecamera;
gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata);

View File

@ -224,6 +224,22 @@ short KX_Camera::GetSensorFit() const
return m_camdata.m_sensor_fit;
}
/**
* Gets the horizontal shift of the sensor - for camera matching.
*/
float KX_Camera::GetShiftHorizontal() const
{
return m_camdata.m_shift_x;
}
/**
* Gets the vertical shift of the sensor - for camera matching.
*/
float KX_Camera::GetShiftVertical() const
{
return m_camdata.m_shift_y;
}
float KX_Camera::GetCameraNear() const
{
return m_camdata.m_clipstart;

View File

@ -206,6 +206,10 @@ public:
float GetSensorHeight() const;
/** Gets the mode FOV is calculating from sensor dimensions */
short GetSensorFit() const;
/** Gets the horizontal shift of the sensor - for camera matching */
float GetShiftHorizontal() const;
/** Gets the vertical shift of the sensor - for camera matching */
float GetShiftVertical() const;
/** Gets the near clip distance. */
float GetCameraNear() const;
/** Gets the far clip distance. */

View File

@ -1159,6 +1159,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
nearfrust,
farfrust,
cam->GetSensorFit(),
cam->GetShiftHorizontal(),
cam->GetShiftVertical(),
frustum
);
if (!cam->GetViewport()) {
@ -1179,6 +1181,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
cam->GetSensorWidth(),
cam->GetSensorHeight(),
cam->GetSensorFit(),
cam->GetShiftHorizontal(),
cam->GetShiftVertical(),
nearfrust,
farfrust,
frustum

View File

@ -39,6 +39,8 @@ struct RAS_CameraData
float m_sensor_x;
float m_sensor_y;
short m_sensor_fit;
float m_shift_x;
float m_shift_y;
float m_clipstart;
float m_clipend;
bool m_perspective;
@ -50,6 +52,7 @@ struct RAS_CameraData
float m_focallength;
RAS_CameraData(float lens = 35.0, float scale = 6.0, float sensor_x = 32.0, float sensor_y = 18.0, short sensor_fit = 0,
float shift_x = 0.0, float shift_y = 0.0,
float clipstart = 0.1, float clipend = 5000.0, bool perspective = true,
float focallength = 3.0, bool viewport = false, int viewportleft = 0, int viewportbottom = 0,
int viewportright = 0, int viewporttop = 0) :
@ -58,6 +61,8 @@ struct RAS_CameraData
m_sensor_x(sensor_x),
m_sensor_y(sensor_y),
m_sensor_fit(sensor_fit),
m_shift_x(shift_x),
m_shift_y(shift_y),
m_clipstart(clipstart),
m_clipend(clipend),
m_perspective(perspective),

View File

@ -41,15 +41,21 @@ ComputeDefaultFrustum(
const float lens,
const float sensor_x, const float sensor_y,
const short sensor_fit,
const float shift_x,
const float shift_y,
const float design_aspect_ratio,
RAS_FrameFrustum & frustum
) {
float size;
float halfSize;
float sizeX;
float sizeY;
float offsetX;
float offsetY;
if (sensor_fit==RAS_SENSORFIT_AUTO) {
halfSize = (sensor_x / 2.f) * camnear / lens;
size = sensor_x * camnear / lens;
halfSize = size * 0.5f;
if (design_aspect_ratio > 1.f) {
// halfsize defines the width
@ -62,20 +68,25 @@ ComputeDefaultFrustum(
}
}
else if (sensor_fit==RAS_SENSORFIT_HOR) {
halfSize = (sensor_x / 2.f) * camnear / lens;
size = sensor_x * camnear / lens;
halfSize = size * 0.5f;
sizeX = halfSize;
sizeY = halfSize/design_aspect_ratio;
}
else {
halfSize = (sensor_y / 2.f) * camnear / lens;
size = sensor_y * camnear / lens;
halfSize = size * 0.5f;
sizeX = halfSize * design_aspect_ratio;
sizeY = halfSize;
}
frustum.x2 = sizeX;
frustum.x1 = -frustum.x2;
frustum.y2 = sizeY;
frustum.y1 = -frustum.y2;
offsetX = size * shift_x;
offsetY = size * shift_y;
frustum.x2 = sizeX + offsetX;
frustum.x1 = -sizeX + offsetX;
frustum.y2 = sizeY + offsetY;
frustum.y1 = -sizeY + offsetY;
frustum.camnear = camnear;
frustum.camfar = camfar;
}
@ -88,12 +99,16 @@ ComputeDefaultOrtho(
const float scale,
const float design_aspect_ratio,
const short sensor_fit,
const float shift_x,
const float shift_y,
RAS_FrameFrustum & frustum
)
{
float halfSize = scale*0.5f;
float sizeX;
float sizeY;
float offsetX;
float offsetY;
if (sensor_fit==RAS_SENSORFIT_AUTO) {
if (design_aspect_ratio > 1.f) {
@ -114,11 +129,14 @@ ComputeDefaultOrtho(
sizeX = halfSize * design_aspect_ratio;
sizeY = halfSize;
}
frustum.x2 = sizeX;
frustum.x1 = -frustum.x2;
frustum.y2 = sizeY;
frustum.y1 = -frustum.y2;
offsetX = scale * shift_x;
offsetY = scale * shift_y;
frustum.x2 = sizeX + offsetX;
frustum.x1 = -sizeX + offsetX;
frustum.y2 = sizeY + offsetY;
frustum.y1 = -sizeY + offsetY;
frustum.camnear = camnear;
frustum.camfar = camfar;
}
@ -221,6 +239,8 @@ ComputeFrustum(
const RAS_Rect &viewport,
const float lens,
const float sensor_x, const float sensor_y, const short sensor_fit,
const float shift_x,
const float shift_y,
const float camnear,
const float camfar,
RAS_FrameFrustum &frustum
@ -249,6 +269,8 @@ ComputeFrustum(
sensor_x,
sensor_y,
sensor_fit,
shift_x,
shift_y,
design_aspect_ratio,
frustum
);
@ -315,6 +337,8 @@ RAS_FramingManager::
const float camnear,
const float camfar,
const short sensor_fit,
const float shift_x,
const float shift_y,
RAS_FrameFrustum &frustum
)
{
@ -340,6 +364,8 @@ RAS_FramingManager::
scale,
design_aspect_ratio,
sensor_fit,
shift_x,
shift_y,
frustum
);

View File

@ -236,6 +236,8 @@ public :
const float camnear,
const float camfar,
const short sensor_fit,
const float shift_x,
const float shift_y,
RAS_FrameFrustum &frustum
);
@ -247,6 +249,8 @@ public :
const RAS_Rect &viewport,
const float lens,
const float sensor_x, const float sensor_y, const short sensor_fit,
const float shift_x,
const float shift_y,
const float camnear,
const float camfar,
RAS_FrameFrustum &frustum
@ -260,6 +264,8 @@ public :
const float lens,
const float sensor_x, const float sensor_y,
const short sensor_fit,
const float shift_x,
const float shift_y,
const float design_aspect_ratio,
RAS_FrameFrustum & frustum
);
@ -272,6 +278,8 @@ public :
const float scale,
const float design_aspect_ratio,
const short sensor_fit,
const float shift_x,
const float shift_y,
RAS_FrameFrustum & frustum
);

View File

@ -240,6 +240,8 @@ void ImageRender::Render()
float lens = m_camera->GetLens();
float sensor_x = m_camera->GetSensorWidth();
float sensor_y = m_camera->GetSensorHeight();
float shift_x = m_camera->GetShiftHorizontal();
float shift_y = m_camera->GetShiftVertical();
bool orthographic = !m_camera->GetCameraData()->m_perspective;
float nearfrust = m_camera->GetCameraNear();
float farfrust = m_camera->GetCameraFar();
@ -260,6 +262,8 @@ void ImageRender::Render()
m_camera->GetScale(),
aspect_ratio,
m_camera->GetSensorFit(),
shift_x,
shift_y,
frustrum
);
@ -274,6 +278,8 @@ void ImageRender::Render()
sensor_x,
sensor_y,
RAS_SENSORFIT_AUTO,
shift_x,
shift_y,
aspect_ratio,
frustrum);