On IRC, a question was asked on how to determine the collision point of a ray and a plane. As I’m not familiar with the blender functions and whatnot, I decided to just write it in pure python. The main shows most of it’s functionality. Notice that you don’t actually need a fourth point, although you can use one if you wish. Generally however, it would be better to make the vectors such that they share a common point. This precludes the chances of the two vectors being parallel, which would stuff things up.
# -*- coding: utf-8 -*-
"""
Created on Tue Jan 10 10:40:24 2012
@author: Jak_o_Shadows
"""
def vector(p1, p2):
"""Calculates the vector of the line joining p1 and p2
Returns a 3 part list, x, y, z components of the vector
"""
a = p1[0] - p2[0]
b = p1[1] - p2[1]
c = p1[2] - p2[2]
return [a, b, c]
def crossProduct(v1, v2):
"""Calculates the cross product of two 3d vectors.
Returns a list with 3 parts, x, y, z components of
the normal vector to the given vectors
"""
a = v1[1]*v2[2] - v1[2]*v2[1]
b = v1[2]*v2[0] - v1[0]*v2[2]
c = v1[0]*v2[1] - v1[1]*v2[0]
return [a, b, c]
def calcPlane(n, p):
"""Calculates the equation of a plane, given the normal
vector of the plane and any point that lies on the plane.
Returns a 4 part list correspoding to the equation:
Ax +By +Cy = D
return [A, B, C, D]
"""
a = n[0]
b = n[1]
c = n[2]
d = a*p[0] + b*p[1] + c*p[2]
return [a, b, c, d]
def parametricLine(v, p):
"""Calculates the parametric equation of the line from
the vector v and the point p that is on the line
returns a list of tuples correspoding to
x = a + At would be [(a, A), etc, etc]. t is simply a
variable
"""
x = [p[0], v[0]]
y = [p[1], v[1]]
z = [p[2], v[2]]
return [x, y, z]
def isectPlaneLine(pl, li):
"""
Calculates whether a given line intersects withs with a given plane.
pl is the plane, as belwo, li is the line, as below.
li = [[a, b], [c, d], [e, f]]
pl = [A, B, C, D]
if they intersect, returns True, t Where t can be substituted back into
the line, thus giving the point of intersection.
if they do not intersect, returns False, 0.
"""
D = pl[3]
Aa = pl[0]*li[0][0]
Bc = pl[1]*li[1][0]
Ce = pl[2]*li[2][0]
Ab = pl[0]*li[0][1]
Bd = pl[1]*li[1][1]
Cf = pl[2]*li[2][1]
numerator = D - Bc - Ce - Aa
denominator = Ab + Bd + Cf
if denominator == 0:
return False, 0
else:
t = numerator/float(denominator)
return True, t
if __name__ == "__main__":
p1 = [1, -1, 1]
p2 = [1, 1, 1]
p3 = [1, 1, -1]
p4 = [1, -1, -1]
v1 = vector(p1, p2)
v2 = vector(p1, p3)
normal = crossProduct(v1, v2)
plane = calcPlane(normal, p1)
lp = [3, 0, 0]
vp = [-1, 0, 0]
line = parametricLine(vp, lp)
print isectPlaneLine(plane, line)
I am woefully ignorant of gameblender coding, however I was informed that it is possible to do this sort of stuff.
[LIST=7]- Get all the points of the plane that you wish to check for intersections, via arcane gameblender functions.
- Get the starting point and direction vector of the ray
- Create two vectors out of any 3 of the points that you got earlier. Ensure that you do not end up with vectors that are parallel (therefore, simply ensure that the two vectors intersect, via using the same point in both of them)
- Calculate the normal vector of the plane by using the crossProduct function, feeding it the arguments of the two vectors you previously created
- Calculate the equation of the plane using one of the points found in step 1, as well as the normal vector you just created.
- Using the direction vector and starting point of the ray you found earlier, create a data structure representing the parametric equation of the ray, using the function parametricLine.
- Check for intersections of the plane and the line via isectPlaneLine(plane, line). This will return a tuple containing first the collision status, and secondly the parameter t
[/LIST]
If you wish to find the point of intersection:
status, t = isectPlaneLine(plane, line)
if status:
x = line[0][0] + t*line[0][1]
y = line[1][0] + t*line[1][1]
z = line[2][0] + t*line[2][1]
Note that i’m not too sure how this works with anything other than squares. If anyone asks, i’ll also make a function for calculating the angle at which the ray would hit the plane.