259
259
if (m_set_frustum_center)
262
// compute sphere for the general case and not only symmetric frustum:
263
// the mirror code in ImageRender can use very asymmetric frustum.
264
// We will put the sphere center on the line that goes from origin to the center of the far clipping plane
265
// This is the optimal position if the frustum is symmetric or very asymmetric and probably close
266
// to optimal for the general case. The sphere center position is computed so that the distance to
267
// the near and far extreme frustum points are equal.
269
// get the transformation matrix from device coordinate to camera coordinate
270
MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix;
271
clip_camcs_matrix.invert();
273
// detect which of the corner of the far clipping plane is the farthest to the origin
274
MT_Vector4 nfar; // far point in device normalized coordinate
275
MT_Point3 farpoint; // most extreme far point in camera coordinate
276
MT_Point3 nearpoint;// most extreme near point in camera coordinate
277
MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate
278
MT_Scalar F=1.0, N; // square distance of far and near point to origin
279
MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0
280
MT_Scalar e, s; // far and near clipping distance (<0)
281
MT_Scalar c; // slope of center line = distance of far clipping center to z axis / far clipping distance
282
MT_Scalar z; // projection of sphere center on z axis (<0)
284
MT_Vector4 npoint(1., 1., 1., 1.);
288
for (int i=0; i<4; i++)
290
hpoint = clip_camcs_matrix*npoint;
291
point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]);
292
len = point.dot(point);
299
// rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane
301
npoint[0] = -npoint[1];
305
// the far center is the average of the far clipping points
307
// the extreme near point is the opposite point on the near clipping plane
308
nfar.setValue(-nfar[0], -nfar[1], -1., 1.);
309
nfar = clip_camcs_matrix*nfar;
310
nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]);
311
N = nearpoint.dot(nearpoint);
314
// projection on XY plane for distance to axis computation
315
MT_Point2 farxy(farpoint[0], farpoint[1]);
316
// f is forced positive by construction
318
// get corresponding point on the near plane
320
// this formula preserve the sign of n
321
n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length();
322
c = MT_Point2(farcenter[0], farcenter[1]).length()/e;
323
// the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case
324
z = (F-N)/(2.0*(e-s+c*(f-n)));
325
m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z);
326
m_frustum_radius = m_frustum_center.distance(farpoint);
262
329
// The most extreme points on the near and far plane. (normalized device coords)
263
330
MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.);
264
MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix;
265
clip_camcs_matrix.invert();
267
332
// Transform to hom camera local space
268
333
hnear = clip_camcs_matrix*hnear;
273
338
MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]);
275
340
// Compute center
341
// don't use camera data in case the user specifies the matrix directly
276
342
m_frustum_center = MT_Point3(0., 0.,
277
(nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(m_camdata.m_clipend - m_camdata.m_clipstart)));
343
(nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(nearpoint[2]-farpoint[2] /*m_camdata.m_clipend - m_camdata.m_clipstart*/)));
278
344
m_frustum_radius = m_frustum_center.distance(farpoint);
280
347
// Transform to world space.
281
348
m_frustum_center = GetCameraToWorld()(m_frustum_center);
282
349
m_frustum_radius /= fabs(NodeGetWorldScaling()[NodeGetWorldScaling().closestAxis()]);