chaomodus / pyeuclid

Pyeuclid 2d/3d/matrix library. Github clone so we can maintain and enhance. [Automatically exported from code.google.com/p/pyeuclid]
0 stars 0 forks source link

Matrix's are incomplete: Perspective projection isn't working. #1

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
When you have a Matrix4 and a Vector3 like this:

Matrix4([    1.00     0.00     0.00     0.00
             0.00     1.00     0.00     0.00
             0.00     0.00     1.00     0.00
             0.00     0.00     1.00     0.00])
Vector3(20.00, 30.00, 10.00)

Then using the vector on the matrix should give you the same effect as if
you divided the vector by its z component:
Vector3(2.00, 3.00, 1.00)

If you do that now with the current euclid module nothing happens.

This is the part of the __mul__ method of the Matrix3 class that should be
changed:

elif isinstance(other, Point2):
    P = Point2(0, 0)
    P.x = A.a * B.x + A.b * B.y + A.c
    P.y = A.e * B.x + A.f * B.y + A.g
    return P
elif isinstance(other, Vector2):
    V = Vector2(0, 0)
    V.x = A.a * B.x + A.b * B.y 
    V.y = A.e * B.x + A.f * B.y 
    return V

This should be changed to:

elif isinstance(other, Point2):
    P = Point2(0, 0)
    w = A.i * B.x + A.j * B.y + A.k
    P.x = (A.a * B.x + A.b * B.y) / w + A.c
    P.y = (A.e * B.x + A.f * B.y) / w + A.g
    return P
elif isinstance(other, Vector2):
    V = Vector2(0, 0)
    w = A.i * B.x + A.j * B.y + A.k
    V.x = (A.a * B.x + A.b * B.y) / w + A.c
    V.y = (A.e * B.x + A.f * B.y) / w + A.g
    return V

The same part in the Matrix4 should be changed to this:

elif isinstance(other, Point3):
    P = Point3(0, 0, 0)
    w = A.m * B.x + A.n * B.y + A.o * B.z + A.p
    P.x = (A.a * B.x + A.b * B.y + A.c * B.z) / w + A.d
    P.y = (A.e * B.x + A.f * B.y + A.g * B.z) / w + A.h
    P.z = (A.i * B.x + A.j * B.y + A.k * B.z) / w + A.l
    return P
elif isinstance(other, Vector3):
    V = Vector3(0, 0, 0)
    w = A.m * B.x + A.n * B.y + A.o * B.z + A.p
    V.x = (A.a * B.x + A.b * B.y + A.c * B.z) / w + A.d
    V.y = (A.e * B.x + A.f * B.y + A.g * B.z) / w + A.h
    V.z = (A.i * B.x + A.j * B.y + A.k * B.z) / w + A.l
    return V

After the code is switched both vectors and points should work with all
types of transformation.
I tested it myself and I can't find anything wrong with it except for a
ZeroDivisionError that dosen't get in the way if you're doing everything
right but will appear when you make a mistake for example:

Matrix4([    1.00     0.00     0.00     0.00
             0.00     1.00     0.00     0.00
             0.00     0.00     1.00     0.00
             0.00     0.00     1.00     0.00])
Vector3(20.00, 30.00, 0.00)

This will cause the error but in normal cases you will keep the matrix like
this:
Matrix4([    1.00     0.00     0.00     0.00
             0.00     1.00     0.00     0.00
             0.00     0.00     1.00     0.00
             0.00     0.00     1.00     1.00])

Also most of this stuff I just found on wikipedia:
http://en.wikipedia.org/wiki/Transformation_matrix#Perspective_projection

Original issue reported on code.google.com by 4B796...@gmail.com on 15 Sep 2006 at 10:32

GoogleCodeExporter commented 9 years ago
Partially fixed with introduction of Matrix4.transform method.

Original comment by Alex.Hol...@gmail.com on 12 Jan 2009 at 1:42