Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/gameengine/Ketsji/KX_Camera.cpp')
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp75
1 files changed, 71 insertions, 4 deletions
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index 53b3e348a36..fb91c793765 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -259,10 +259,75 @@ void KX_Camera::ExtractFrustumSphere()
if (m_set_frustum_center)
return;
- // The most extreme points on the near and far plane. (normalized device coords)
- MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.);
+ // compute sphere for the general case and not only symmetric frustum:
+ // the mirror code in ImageRender can use very asymmetric frustum.
+ // We will put the sphere center on the line that goes from origin to the center of the far clipping plane
+ // This is the optimal position if the frustum is symmetric or very asymmetric and probably close
+ // to optimal for the general case. The sphere center position is computed so that the distance to
+ // the near and far extreme frustum points are equal.
+
+ // get the transformation matrix from device coordinate to camera coordinate
MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix;
clip_camcs_matrix.invert();
+
+ // detect which of the corner of the far clipping plane is the farthest to the origin
+ MT_Vector4 nfar; // far point in device normalized coordinate
+ MT_Point3 farpoint; // most extreme far point in camera coordinate
+ MT_Point3 nearpoint;// most extreme near point in camera coordinate
+ MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate
+ MT_Scalar F=1.0, N; // square distance of far and near point to origin
+ MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0
+ MT_Scalar e, s; // far and near clipping distance (<0)
+ MT_Scalar c; // slope of center line = distance of far clipping center to z axis / far clipping distance
+ MT_Scalar z; // projection of sphere center on z axis (<0)
+ // tmp value
+ MT_Vector4 npoint(1., 1., 1., 1.);
+ MT_Vector4 hpoint;
+ MT_Point3 point;
+ MT_Scalar len;
+ for (int i=0; i<4; i++)
+ {
+ hpoint = clip_camcs_matrix*npoint;
+ point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]);
+ len = point.dot(point);
+ if (len > F)
+ {
+ nfar = npoint;
+ farpoint = point;
+ F = len;
+ }
+ // rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane
+ len = npoint[0];
+ npoint[0] = -npoint[1];
+ npoint[1] = len;
+ farcenter += point;
+ }
+ // the far center is the average of the far clipping points
+ farcenter *= 0.25;
+ // the extreme near point is the opposite point on the near clipping plane
+ nfar.setValue(-nfar[0], -nfar[1], -1., 1.);
+ nfar = clip_camcs_matrix*nfar;
+ nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]);
+ N = nearpoint.dot(nearpoint);
+ e = farpoint[2];
+ s = nearpoint[2];
+ // projection on XY plane for distance to axis computation
+ MT_Point2 farxy(farpoint[0], farpoint[1]);
+ // f is forced positive by construction
+ f = farxy.length();
+ // get corresponding point on the near plane
+ farxy *= s/e;
+ // this formula preserve the sign of n
+ n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length();
+ c = MT_Point2(farcenter[0], farcenter[1]).length()/e;
+ // the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case
+ z = (F-N)/(2.0*(e-s+c*(f-n)));
+ m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z);
+ m_frustum_radius = m_frustum_center.distance(farpoint);
+
+#if 0
+ // The most extreme points on the near and far plane. (normalized device coords)
+ MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.);
// Transform to hom camera local space
hnear = clip_camcs_matrix*hnear;
@@ -273,10 +338,12 @@ void KX_Camera::ExtractFrustumSphere()
MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]);
// Compute center
+ // don't use camera data in case the user specifies the matrix directly
m_frustum_center = MT_Point3(0., 0.,
- (nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(m_camdata.m_clipend - m_camdata.m_clipstart)));
+ (nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(nearpoint[2]-farpoint[2] /*m_camdata.m_clipend - m_camdata.m_clipstart*/)));
m_frustum_radius = m_frustum_center.distance(farpoint);
-
+#endif
+
// Transform to world space.
m_frustum_center = GetCameraToWorld()(m_frustum_center);
m_frustum_radius /= fabs(NodeGetWorldScaling()[NodeGetWorldScaling().closestAxis()]);