Browse Source

regularize projection transform and near plane correction

David Rose 22 years ago
parent
commit
9ca106399c

+ 0 - 4
panda/src/distort/projectionScreen.cxx

@@ -677,10 +677,6 @@ make_mesh_geom(Geom *geom, Lens *lens, LMatrix4f &rel_mat) {
     // dimensions so the Z coordinate remains meaningful.
     // dimensions so the Z coordinate remains meaningful.
     LPoint3f film(0.0f, 0.0f, 0.0f);
     LPoint3f film(0.0f, 0.0f, 0.0f);
     lens->project(vert * rel_mat, film);
     lens->project(vert * rel_mat, film);
-    
-    // This might be necessary to compensate for DX's weird near plane
-    // definition.  Investigate further later.
-    //film[2] = ((film[2] + 1.0f) / 2.0f);
 
 
     new_coords.push_back(film);
     new_coords.push_back(film);
   }
   }

+ 17 - 28
panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx

@@ -27,7 +27,6 @@
 #include "graphicsWindow.h"
 #include "graphicsWindow.h"
 #include "graphicsChannel.h"
 #include "graphicsChannel.h"
 #include "lens.h"
 #include "lens.h"
-#include "perspectiveLens.h"
 #include "ambientLight.h"
 #include "ambientLight.h"
 #include "directionalLight.h"
 #include "directionalLight.h"
 #include "pointLight.h"
 #include "pointLight.h"
@@ -802,40 +801,30 @@ prepare_lens() {
     return false;
     return false;
   }
   }
 
 
-  // lets get the lens perspective matrix
+  // Start with the projection matrix from the lens.
   const LMatrix4f &projection_mat = _current_lens->get_projection_mat();
   const LMatrix4f &projection_mat = _current_lens->get_projection_mat();
 
 
   // The projection matrix must always be left-handed Y-up internally,
   // The projection matrix must always be left-handed Y-up internally,
-  // even if our coordinate system of choice is otherwise.
-  LMatrix4f new_projection_mat =
-    LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
-    projection_mat;
-
-  float vfov = _current_lens->get_vfov();
-  float nearf = _current_lens->get_near();
-  float farf = _current_lens->get_far();
-
-  //dxgsg7_cat.debug() << new_projection_mat << endl;
+  // to match DirectX's convention, even if our coordinate system of
+  // choice is otherwise.
+  const LMatrix4f &convert_mat = 
+    LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system());
+
+  // DirectX also uses a Z range of 0 to 1, whereas the Panda
+  // convention is for the projection matrix to produce a Z range of
+  // -1 to 1.  We have to rescale to compensate.
+  static const LMatrix4f rescale_mat
+    (1, 0, 0, 0,
+     0, 1, 0, 0,
+     0, 0, 0.5, 0,
+     0, 0, 0.5, 1);
   
   
-  HRESULT hr;
-  if (_current_lens->get_type().get_name() == "PerspectiveLens") {
-    ((LPD3DMATRIX)new_projection_mat.get_data())->_33 = farf / (farf-nearf);
-    ((LPD3DMATRIX)new_projection_mat.get_data())->_43 = -nearf * farf / (farf - nearf);
+  LMatrix4f new_projection_mat =
+    convert_mat * projection_mat * rescale_mat;
 
 
-    hr = _pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION,
-                                   (D3DMATRIX*)new_projection_mat.get_data());
-    //dxgsg7_cat.debug() << new_projection_mat << endl;
-    //dxgsg7_cat.debug() << "using perspective projection" << endl;
-  }
-  else {
-    ((LPD3DMATRIX)new_projection_mat.get_data())->_33 = 1/(farf-nearf);
-    ((LPD3DMATRIX)new_projection_mat.get_data())->_43 = -nearf/(farf-nearf);
-    
+  HRESULT hr = 
     hr = _pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION,
     hr = _pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION,
                                    (LPD3DMATRIX)new_projection_mat.get_data());
                                    (LPD3DMATRIX)new_projection_mat.get_data());
-    //dxgsg7_cat.debug() << new_projection_mat << endl;
-    //dxgsg7_cat.debug() << "using ortho projection" << endl;
-  }
   return SUCCEEDED(hr);
   return SUCCEEDED(hr);
 }
 }
 
 

+ 20 - 56
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -28,8 +28,6 @@
 #include "graphicsEngine.h"
 #include "graphicsEngine.h"
 #include "graphicsChannel.h"
 #include "graphicsChannel.h"
 #include "lens.h"
 #include "lens.h"
-#include "perspectiveLens.h"
-#include "orthographicLens.h"
 #include "ambientLight.h"
 #include "ambientLight.h"
 #include "directionalLight.h"
 #include "directionalLight.h"
 #include "pointLight.h"
 #include "pointLight.h"
@@ -1032,64 +1030,30 @@ prepare_lens() {
     return false;
     return false;
   }
   }
 
 
-  // lets get the lens perspective matrix
+  // Start with the projection matrix from the lens.
   const LMatrix4f &projection_mat = _current_lens->get_projection_mat();
   const LMatrix4f &projection_mat = _current_lens->get_projection_mat();
-  
-  // The projection matrix must always be left-handed Y-up internally,
-  // even if our coordinate system of choice is otherwise.
-  LMatrix4f new_projection_mat =
-    LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
-    projection_mat;
-  
-  float nearf = _current_lens->get_near();
-  float farf = _current_lens->get_far();
 
 
-  //dxgsg8_cat.debug() << new_projection_mat << endl;
+  // The projection matrix must always be left-handed Y-up internally,
+  // to match DirectX's convention, even if our coordinate system of
+  // choice is otherwise.
+  const LMatrix4f &convert_mat = 
+    LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system());
+
+  // DirectX also uses a Z range of 0 to 1, whereas the Panda
+  // convention is for the projection matrix to produce a Z range of
+  // -1 to 1.  We have to rescale to compensate.
+  static const LMatrix4f rescale_mat
+    (1, 0, 0, 0,
+     0, 1, 0, 0,
+     0, 0, 0.5, 0,
+     0, 0, 0.5, 1);
   
   
-  HRESULT hr;
-  if (false && _current_lens->is_of_type(PerspectiveLens::get_class_type())) {
-    /*
-    const LMatrix4f mat_temp;
-
-    float vfov = _current_lens->get_vfov();
-    float hfov = _current_lens->get_hfov();
-    float ar = _current_lens->get_aspect_ratio();
-    float nearf = _current_lens->get_near();
-    float farf = _current_lens->get_far();
-    double vfov_radian = vfov * 0.0174532925;
-
-    dxgsg8_cat.debug() << "hfov " << hfov << " vfov " << vfov << " ar " << ar << " near " << nearf << " far " << farf << endl;
-    D3DXMatrixPerspectiveFovLH( (D3DXMATRIX*)mat_temp.get_data(), vfov_radian, ar, nearf, farf );
-
-    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
-                                   (D3DMATRIX*)mat_temp.get_data());
-    dxgsg8_cat.debug() << mat_temp << endl;
-    */
-
-    new_projection_mat(2, 2) = farf / (farf-nearf);
-    new_projection_mat(3, 2) = -nearf * farf / (farf - nearf);
-
-    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
-                                   (D3DMATRIX*)new_projection_mat.get_data());
-    //dxgsg8_cat.debug() << new_projection_mat << endl;
-    //dxgsg8_cat.debug() << "using perspective projection" << endl;
-
-  } else if (false && _current_lens->is_of_type(OrthographicLens::get_class_type())) {
-    new_projection_mat(2, 2) = 1 / (farf - nearf);
-    new_projection_mat(3, 2) = -nearf / (farf - nearf);
-    
-    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
-                                   (D3DMATRIX*)new_projection_mat.get_data());
-    //dxgsg8_cat.debug() << new_projection_mat << endl;
-    //dxgsg8_cat.debug() << "using ortho projection" << endl;
-
-  } else {
-    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
-                                   (D3DMATRIX*)new_projection_mat.get_data());
-    //dxgsg8_cat.debug() << new_projection_mat << endl;
-    //dxgsg8_cat.debug() << "using matrix projection" << endl;
-  }
+  LMatrix4f new_projection_mat =
+    convert_mat * projection_mat * rescale_mat;
 
 
+  HRESULT hr = 
+    _pD3DDevice->SetTransform(D3DTS_PROJECTION,
+                              (D3DMATRIX*)new_projection_mat.get_data());
   return SUCCEEDED(hr);
   return SUCCEEDED(hr);
 }
 }
 
 

+ 20 - 56
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -28,8 +28,6 @@
 #include "graphicsEngine.h"
 #include "graphicsEngine.h"
 #include "graphicsChannel.h"
 #include "graphicsChannel.h"
 #include "lens.h"
 #include "lens.h"
-#include "perspectiveLens.h"
-#include "orthographicLens.h"
 #include "ambientLight.h"
 #include "ambientLight.h"
 #include "directionalLight.h"
 #include "directionalLight.h"
 #include "pointLight.h"
 #include "pointLight.h"
@@ -1047,64 +1045,30 @@ prepare_lens() {
     return false;
     return false;
   }
   }
 
 
-  // lets get the lens perspective matrix
+  // Start with the projection matrix from the lens.
   const LMatrix4f &projection_mat = _current_lens->get_projection_mat();
   const LMatrix4f &projection_mat = _current_lens->get_projection_mat();
-  
-  // The projection matrix must always be left-handed Y-up internally,
-  // even if our coordinate system of choice is otherwise.
-  LMatrix4f new_projection_mat =
-    LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()) *
-    projection_mat;
-  
-  float nearf = _current_lens->get_near();
-  float farf = _current_lens->get_far();
 
 
-  //dxgsg9_cat.debug() << new_projection_mat << endl;
+  // The projection matrix must always be left-handed Y-up internally,
+  // to match DirectX's convention, even if our coordinate system of
+  // choice is otherwise.
+  const LMatrix4f &convert_mat = 
+    LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system());
+
+  // DirectX also uses a Z range of 0 to 1, whereas the Panda
+  // convention is for the projection matrix to produce a Z range of
+  // -1 to 1.  We have to rescale to compensate.
+  static const LMatrix4f rescale_mat
+    (1, 0, 0, 0,
+     0, 1, 0, 0,
+     0, 0, 0.5, 0,
+     0, 0, 0.5, 1);
   
   
-  HRESULT hr;
-  if (false && _current_lens->is_of_type(PerspectiveLens::get_class_type())) {
-    /*
-    const LMatrix4f mat_temp;
-
-    float vfov = _current_lens->get_vfov();
-    float hfov = _current_lens->get_hfov();
-    float ar = _current_lens->get_aspect_ratio();
-    float nearf = _current_lens->get_near();
-    float farf = _current_lens->get_far();
-    double vfov_radian = vfov * 0.0174532925;
-
-    dxgsg9_cat.debug() << "hfov " << hfov << " vfov " << vfov << " ar " << ar << " near " << nearf << " far " << farf << endl;
-    D3DXMatrixPerspectiveFovLH( (D3DXMATRIX*)mat_temp.get_data(), vfov_radian, ar, nearf, farf );
-
-    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
-                                   (D3DMATRIX*)mat_temp.get_data());
-    dxgsg9_cat.debug() << mat_temp << endl;
-    */
-
-    new_projection_mat(2, 2) = farf / (farf-nearf);
-    new_projection_mat(3, 2) = -nearf * farf / (farf - nearf);
-
-    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
-                                   (D3DMATRIX*)new_projection_mat.get_data());
-    //dxgsg9_cat.debug() << new_projection_mat << endl;
-    //dxgsg9_cat.debug() << "using perspective projection" << endl;
-
-  } else if (false && _current_lens->is_of_type(OrthographicLens::get_class_type())) {
-    new_projection_mat(2, 2) = 1 / (farf - nearf);
-    new_projection_mat(3, 2) = -nearf / (farf - nearf);
-    
-    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
-                                   (D3DMATRIX*)new_projection_mat.get_data());
-    //dxgsg9_cat.debug() << new_projection_mat << endl;
-    //dxgsg9_cat.debug() << "using ortho projection" << endl;
-
-  } else {
-    hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION,
-                                   (D3DMATRIX*)new_projection_mat.get_data());
-    //dxgsg9_cat.debug() << new_projection_mat << endl;
-    //dxgsg9_cat.debug() << "using matrix projection" << endl;
-  }
+  LMatrix4f new_projection_mat =
+    convert_mat * projection_mat * rescale_mat;
 
 
+  HRESULT hr = 
+    _pD3DDevice->SetTransform(D3DTS_PROJECTION,
+                              (D3DMATRIX*)new_projection_mat.get_data());
   return SUCCEEDED(hr);
   return SUCCEEDED(hr);
 }
 }