0

I'm trying to build some micro "3d engine" as to understand the basics of this field. Everything works quite fine except for rotations. I use the standard rotation matrices to do this, yet all 3 of the possible rotations not only rotate the points, they also scale them down. This behaviour is not intended or wished for. Following is the relevant part of the code (I think):

class Point:
def __init__(self, x, y, z, ui):
    self.x = mpf(x)
    self.y = mpf(y)
    self.z = mpf(z)
    self.ui = ui

def subtractVectorFromPoint(self, vector):
    self.x -= vector.x
    self.y -= vector.y
    self.z -= vector.z
    return self

def subtractPointFromPoint(self, point):
    TempVector = Vector(0, 0, 0)
    TempVector.x = self.x - point.x
    TempVector.y = self.y - point.y
    TempVector.z = self.z - point.z
    return TempVector

def setPointToPoint(self, point):
    self.x = point.x
    self.y = point.y
    self.z = point.z
    return self


class Vector:
def __init__(self, x, y ,z):
    self.x = mpf(x)
    self.y = mpf(y)
    self.z = mpf(z)

def rotateXY(self, degrees):
    radians = mpf(math.radians(degrees))

    self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
    self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
    return self


#rotate xy plane by 15 degrees on pressing r
if event.key == pygame.K_r:
    origin = Vector(0, 0, 0)
    UI.draw_background()
    for point in pointList:
        tempVector = point.subtractPointFromPoint(origin)
        point.setPointToPoint(origin)
        point.addVectorToPoint(tempVector.rotateXY(15))
        point.drawPoint()

That should be all you need I think. Any pointers to where I went wrong are welcome. I know the classes miss an indent in the example here, I suck at the layout on this website :)

p.s. I tried using the "mpf()" function to increase the precision but this had 0 result.

Daquicker
  • 515
  • 2
  • 7
  • 17
  • Can you define "scale down"? If you test the magnitude of each of your rotated vectors, they come out to be the same. – user2085282 Sep 16 '14 at 17:08
  • I use pygame to give me a visual representation and the points not only rotate around (0,0,0), they also get closer to it with every rotation. Given enough rotations, every point ends up on (0,0,0), which obviously is not desired. – Daquicker Sep 16 '14 at 17:10
  • And as a side comment, incase you are unaware, if your classes have a `__add__` function, you don't need to have `addXtoY` functions, and can just use the `+=` operator – user2085282 Sep 16 '14 at 17:13
  • I think I found the solution, I'm using the already adjusted self.x to compute self.y, I'll look in to it now. – Daquicker Sep 16 '14 at 17:16

1 Answers1

0

The problem is in this part:

def rotateXY(self, degrees):
    radians = mpf(math.radians(degrees))

    self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
    self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
    return self

self.y is being calculated using a self.x that is already adjusted, resulting in given problem.

A fix for this is using a temp variable like this:

def rotateXY(self, degrees):
    radians = mpf(math.radians(degrees))

    tempX = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
    self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
    self.x = tempX
    return self
Daquicker
  • 515
  • 2
  • 7
  • 17