add python access to mathutils.intersect_line_plane, update view3d_utils module to...
authorCampbell Barton <ideasman42@gmail.com>
Thu, 19 May 2011 04:28:09 +0000 (04:28 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 19 May 2011 04:28:09 +0000 (04:28 +0000)
release/scripts/modules/bpy_extras/view3d_utils.py
source/blender/python/generic/mathutils_geometry.c

index 0e21eab771735a99a52b91204a1be29a574c4d4a..60436328477dddcd900b01fc8d1b0f8848737005 100644 (file)
 # <pep8 compliant>
 
 
-def _is_persp_matrix(persmat, eps=0.00001):
-    """
-    crummy way to check if its a perspective matrix
-    """
-    return not (
-            abs(persmat[0][3]) < eps and \
-            abs(persmat[1][3]) < eps and \
-            abs(persmat[2][3]) < eps and \
-            abs(persmat[3][3] - 1.0) < eps)
-
-
 def region_2d_to_vector_3d(region, rv3d, coord):
     """
     Return a direction vector from the viewport at the spesific 2d region
@@ -47,13 +36,13 @@ def region_2d_to_vector_3d(region, rv3d, coord):
     """
     from mathutils import Vector
 
-    persmat = rv3d.perspective_matrix.copy()
     viewvec = rv3d.view_matrix.inverted()[2].xyz.normalized()
 
-    if _is_persp_matrix(persmat):
+    if rv3d.is_perspective:
         dx = (2.0 * coord[0] / region.width) - 1.0
         dy = (2.0 * coord[1] / region.height) - 1.0
-        
+
+        persmat = rv3d.perspective_matrix.copy()
         perspinv_x, perspinv_y = persmat.inverted().to_3x3()[0:2]
         return ((perspinv_x * dx + perspinv_y * dy) - viewvec).normalized()
     else:
@@ -78,22 +67,28 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location):
     :return: normalized 3d vector.
     :rtype: :class:`Vector`
     """
+    from mathutils import Vector
     from mathutils.geometry import intersect_point_line
 
     persmat = rv3d.perspective_matrix.copy()
+    coord_vec = region_2d_to_vector_3d(region, rv3d, coord)
+    depth_location = Vector(depth_location)
+
+    if rv3d.is_perspective:
+        from mathutils.geometry import intersect_line_plane
 
-    if _is_persp_matrix(persmat):
         origin_start = rv3d.view_matrix.inverted()[3].to_3d()
+        origin_end = origin_start + coord_vec
+        view_vec = rv3d.view_matrix.inverted()[2]
+        return intersect_line_plane(origin_start, origin_end, depth_location, view_vec, 1)
     else:
         dx = (2.0 * coord[0] / region.width) - 1.0
         dy = (2.0 * coord[1] / region.height) - 1.0
         persinv = persmat.inverted()
         viewinv = rv3d.view_matrix.inverted()
         origin_start = (persinv[0].xyz * dx) + (persinv[1].xyz * dy) + viewinv[3].xyz
-
-    origin_end = origin_start + region_2d_to_vector_3d(region, rv3d, coord)
-    
-    return intersect_point_line(depth_location, origin_start, origin_end)[0]
+        origin_end = origin_start + coord_vec
+        return intersect_point_line(depth_location, origin_start, origin_end)[0]
 
 
 def location_3d_to_region_2d(region, rv3d, coord):
index 6031c716807b0713af402e0847f311e215b4a046..49b5eff3aa8d42257810755a972fe8daf9757ee4 100644 (file)
@@ -497,6 +497,60 @@ static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObj
 }
 
 
+static char M_Geometry_intersect_line_plane_doc[] =
+".. function:: intersect_line_plane(line_a, line_b, plane_co, plane_no, no_flip=False)\n"
+"\n"
+"   Takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None.\n"
+"\n"
+"   :arg line_a: First point of the first line\n"
+"   :type line_a: :class:`mathutils.Vector`\n"
+"   :arg line_b: Second point of the first line\n"
+"   :type line_b: :class:`mathutils.Vector`\n"
+"   :arg plane_co: A point on the plane\n"
+"   :type plane_co: :class:`mathutils.Vector`\n"
+"   :arg plane_no: The direction the plane is facing\n"
+"   :type plane_no: :class:`mathutils.Vector`\n"
+"   :arg no_flip: Always return an intersection on the directon defined bt line_a -> line_b\n"
+"   :type no_flip: :boolean\n"
+"   :return: The point of intersection or None when not found\n"
+"   :rtype: :class:`mathutils.Vector` or None\n"
+;
+static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject* args)
+{
+       VectorObject *line_a, *line_b, *plane_co, *plane_no;
+       int no_flip= 0;
+       float isect[3];
+       if(!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_line_2d",
+         &vector_Type, &line_a,
+         &vector_Type, &line_b,
+         &vector_Type, &plane_co,
+         &vector_Type, &plane_no,
+         &no_flip)
+       ) {
+               return NULL;
+       }
+
+       if(             BaseMath_ReadCallback(line_a) == -1 ||
+               BaseMath_ReadCallback(line_b) == -1 ||
+               BaseMath_ReadCallback(plane_co) == -1 ||
+               BaseMath_ReadCallback(plane_no) == -1
+       ) {
+               return NULL;
+       }
+
+       if(ELEM4(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) {
+               PyErr_SetString(PyExc_RuntimeError, "geometry.intersect_line_plane(...) can't use 2D Vectors");
+               return NULL;
+       }
+
+       if(isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec, no_flip) == 1) {
+               return newVectorObject(isect, 3, Py_NEW, NULL);
+       }
+       else {
+               Py_RETURN_NONE;
+       }
+}
+
 static char M_Geometry_intersect_point_line_doc[] =
 ".. function:: intersect_point_line(pt, line_p1, line_p2)\n"
 "\n"
@@ -860,6 +914,7 @@ static PyMethodDef M_Geometry_methods[]= {
        {"intersect_point_quad_2d", (PyCFunction) M_Geometry_intersect_point_quad_2d, METH_VARARGS, M_Geometry_intersect_point_quad_2d_doc},
        {"intersect_line_line", (PyCFunction) M_Geometry_intersect_line_line, METH_VARARGS, M_Geometry_intersect_line_line_doc},
        {"intersect_line_line_2d", (PyCFunction) M_Geometry_intersect_line_line_2d, METH_VARARGS, M_Geometry_intersect_line_line_2d_doc},
+       {"intersect_line_plane", (PyCFunction) M_Geometry_intersect_line_plane, METH_VARARGS, M_Geometry_intersect_line_plane_doc},
        {"interpolate_bezier", (PyCFunction) M_Geometry_interpolate_bezier, METH_VARARGS, M_Geometry_interpolate_bezier_doc},
        {"area_tri", (PyCFunction) M_Geometry_area_tri, METH_VARARGS, M_Geometry_area_tri_doc},
        {"normal", (PyCFunction) M_Geometry_normal, METH_VARARGS, M_Geometry_normal_doc},