Forums: » Register « |  Free Tools |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support |

New Free Tools on Dev Shed!

#1
May 15th, 2013, 10:39 PM
 imp96
Registered User

Join Date: May 2013
Posts: 3
Time spent in forums: 1 h 37 m 17 sec
Reputation Power: 0
Need help with 3D rotation

I am working on a 3D 2x2 rubix cube.
As of right now, I am able to rotate the whole cube.
The problem I have however is that I am not always able to rotate each individual side. For now I am trying to rotate the right side(the side that you see on the right of the screen). This rotation works if there has not been any rotation in the y plane.
However, as soon as I rotate the cube in the y axis, and then rotate the side, it becomes deformed. I am using a 3D rotational
matrix(http://en.wikipedia.org/wiki/Rotation_matrix).
My question is how can make it so side does not become deformed. I also whant to be able to rotate that side couple degrees at a time so that there is a smooth animation of the rotating side.
Also I will not be able to use any 3D library because I have no knowledge of any other library besides pygame.

Here is my code:
Code:
```import math
import pygame
from operator import itemgetter
import sys
import os

os.environ['SDL_VIDEODRIVER']='windib'

faces = [(0,1,3,2), (4,5,7,6), (0,2,6,4),(1,3,7,5),(2,3,7,6), (0,1,5,4),
]

factor = 100
win_width = 1000
win_height = 600

anglex = 0
angley = 0
anglez = 0

def construct_matrix(x, y, z, theta):
matrix = [
[[],[],[]],
[[],[],[]],
[[],[],[]]
]
constant = (math.sqrt(math.pow(x,2)+ math.pow(y,2)+ math.pow(z,2)))
ux = x/constant
uy = y/constant
uz = z/constant
rad_theta = theta * math.pi / 180
print bc
matrix[0][0] = (aa)
matrix[0][1] = (ab)
matrix[0][2] = (ac)
matrix[1][0] = (ba)
matrix[1][1] = (bb)
matrix[1][2] = (bc)
matrix[2][0] = (ca)
matrix[2][1] = (cb)
matrix[2][2] = (cc)
return matrix

class Cube:
def trial2(self,cords):
new_cords = cords
new_xcord = new_cords[0]*factor+win_width/2
new_ycord = new_cords[1]*factor+win_height/2
twod_cords = (new_xcord, new_ycord, new_cords[2])
return  twod_cords

def screen_vert(self,vertices):
dvertices = []
for v in vertices:
dvertices.append(self.trial2(v))
return dvertices

def avg_stat(self,vertices,position):
avg_stat = 0
for i in vertices:
avg_stat = avg_stat + i[position]
avg_stat = avg_stat / 8.0
return avg_stat

def __init__(self, vertices ,colors):

self.vertices = vertices
self.colors = colors
self.screenvert = self.screen_vert(self.vertices)
self.width = self.avg_stat(self.vertices,0)
self.height = self.avg_stat(self.vertices,1)
self.depth = self.avg_stat(self.vertices,2)

def cube_point(self,x,y,z,x_angle,y_angle,z_angle):
radx = x_angle * math.pi / 180
rady = y_angle * math.pi / 180
radz = z_angle * math.pi / 180

return(xprime,yprime,zprime)

def make_new_vert(self,anglex,angley,anglez):
current_vertices = []
for v in self.vertices:
current_vertices.append(self.cube_point(float(v[0]), float(v[1]), float(v[2]), float(anglex), float(angley), float(anglez)))
self.vertices = current_vertices
self.screenvert = self.screen_vert(self.vertices)
self.width = self.avg_stat(self.vertices,0)
self.height = self.avg_stat(self.vertices,1)
self.depth = self.avg_stat(self.vertices,2)

def make_new_vert_matrix(self,matrix):
current_vertices = []
solving = []
for v in self.vertices:
print v
a = matrix[0][0]*v[0] + matrix[0][1]*v[1] + matrix[0][2]*v[2]
b = matrix[1][0]*v[0] + matrix[1][1]*v[1] + matrix[1][2]*v[2]
c = matrix[2][0]*v[0] + matrix[2][1]*v[1] + matrix[2][2]*v[2]
current_vertices.append((a,b,c))

self.vertices = current_vertices
self.screenvert = self.screen_vert(self.vertices)
self.width = self.avg_stat(self.vertices,0)
self.height = self.avg_stat(self.vertices,1)
self.depth = self.avg_stat(self.vertices,2)

def drawing(self):
avg_depth = []
i = 0
for f in faces:
z_avg = (self.screenvert[f[0]][2] + self.screenvert[f[1]][2] + self.screenvert[f[2]][2] + self.screenvert[f[3]][2]) / 4.0
avg_depth.append([i,z_avg])
i+=1

for i in sorted(avg_depth,key=itemgetter(1),reverse=False):
index = i[0]
face = faces[index]
points = [
(self.screenvert[face[0]][0], self.screenvert[face[0]][1]), (self.screenvert[face[1]][0], self.screenvert[face[1]][1]),
(self.screenvert[face[1]][0], self.screenvert[face[1]][1]), (self.screenvert[face[2]][0], self.screenvert[face[2]][1]),
(self.screenvert[face[2]][0], self.screenvert[face[2]][1]), (self.screenvert[face[3]][0], self.screenvert[face[3]][1]),
(self.screenvert[face[3]][0], self.screenvert[face[3]][1]), (self.screenvert[face[0]][0], self.screenvert[face[0]][1]),
]
pygame.draw.polygon(screen,self.colors[index],points)

vertices0 = [(-1,1,-1),
(0,1,-1),
(-1,1,0),
(0,1,0),
(-1,0,-1),
(0,0,-1),
(-1,0,0),
(0,0,0),
]

vertices1 = [(0,1,-1),
(1,1,-1),
(0,1,0),
(1,1,0),
(0,0,-1),
(1,0,-1),
(0,0,0),
(1,0,0),
]
vertices2 = [(-1,1,0),
(0,1,0),
(-1,1,1),
(0,1,1),
(-1,0,0),
(0,0,0),
(-1,0,1),
(0,0,1),
]

vertices3 = [(0,1,0),
(1,1,0),
(0,1,1),
(1,1,1),
(0,0,0),
(1,0,0),
(0,0,1),
(1,0,1),
]

vertices4 = [(-1,0,-1),
(0,0,-1),
(-1,0,0),
(0,0,0),
(-1,-1,-1),
(0,-1,-1),
(-1,-1,0),
(0,-1,0),
]

vertices5 = [(0,0,-1),
(1,0,-1),
(0,0,0),
(1,0,0),
(0,-1,-1),
(1,-1,-1),
(0,-1,0),
(1,-1,0),
]
vertices6 = [(-1,0,0),
(0,0,0),
(-1,0,1),
(0,0,1),
(-1,-1,0),
(0,-1,0),
(-1,-1,1),
(0,-1,1),
]

vertices7 = [(0,0,0),
(1,0,0),
(0,0,1),
(1,0,1),
(0,-1,0),
(1,-1,0),
(0,-1,1),
(1,-1,1),
]

colors0 = [(255,0,0), (0,0,0), (0,0,255),(0,0,0), (0, 0, 0), (255, 255, 0)]

colors1 = [(255,80,0), (0,0,0), (0,0,0),(255,255,0), (0, 0, 0), (255, 0, 255)]

colors2 = [(255,0,80), (0,0,0), (25,0,25),(0,0,0), (255, 128, 0), (0, 0, 0)]

colors3 = [(255,89,0), (0,0,0), (0,0,0),(255,200,0), (25, 128, 0), (0, 0, 0)]
colors4 = [(0,0,0), (0,255,0), (0,0,255),(0,0,0), (0, 0, 0), (0, 255, 255)]

colors5 = [(0,0,0), (0,55,43), (0,0,0),(255,255,0), (0, 0, 0), (255, 255, 255)]
colors6 = [(0,0,0), (0,255,0), (0,0,255),(0,0,0), (255, 128, 200), (0, 0, 0)]

colors7 = [(0,0,0), (0,255,0), (0,0,0),(55,255,0), (0, 128, 0), (0, 0, 0)]

pygame.init()

screen = pygame.display.set_mode((win_width, win_height))
pygame.display.set_caption("Ilya")

clock = pygame.time.Clock()

array = [
[[Cube(vertices0, colors0),Cube(vertices1, colors1)],[Cube(vertices2, colors2),Cube(vertices3, colors3)]],
[[Cube(vertices4, colors4),Cube(vertices5, colors5)],[Cube(vertices6, colors6),Cube(vertices7, colors7)]]
]

while True:
clock.tick(50)
screen.fill((0,32,0))

order_for_drawing = []
index = 0
for i in range(2):
for k in range(2):
for j in range(2):
order_for_drawing.append([array[i][k][j].depth,array[i][k][j]])

for i in sorted(order_for_drawing,key=itemgetter(0),reverse=False):
i[1].drawing()

pressed = pygame.key.get_pressed()

if pressed[pygame.K_UP]:
anglex +=4

if pressed[pygame.K_DOWN]:
anglex -=4

if pressed[pygame.K_RIGHT]:
angley +=4

if pressed[pygame.K_LEFT]:
angley -=4

if pressed[pygame.K_s]:
anglez +=4

if pressed[pygame.K_a]:
anglez -=4

for i in range(2):
for k in range(2):
for j in range(2):
array[i][k][j].make_new_vert(anglex,angley,anglez)

for event in pygame.event.get():
#if event.type == pygame.KEYDOWN:

if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

if pressed[pygame.K_q] and event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
order_for_drawing1 = []
index1 = 0
list1 = []
constant1 = 0
widthavg = 0
depthavg = 0
heightavg = 0
for i in range(2):
for k in range(2):
for j in range(2):
order_for_drawing1.append([array[i][k][j].width,array[i][k][j]])

for i in sorted(order_for_drawing1,key=itemgetter(0),reverse=True):
index1+=1
list1.append(i[1])
if index1 == 4:
break
for i in list1:
widthavg += i.width
depthavg += i.depth
heightavg += i.height
widthavg = widthavg/4.0
depthavg =  depthavg/4.0
heightavg = heightavg/4.0
constant = math.sqrt(math.pow(widthavg,2) + math.pow(heightavg,2) + math.pow(depthavg,2))
ux = widthavg/constant
uy = heightavg/constant
uz = depthavg/constant
print ux, uy, uz
rotational_matrix = construct_matrix(ux, uy, uz, 90.0)
print rotational_matrix
#for i in range(45):
for j in list1:
j.make_new_vert_matrix(rotational_matrix)

anglex = 0
angley = 0
anglez = 0
pygame.display.update()```

#2
May 16th, 2013, 09:11 AM
 b49P23TIvg
Contributing User

Join Date: Aug 2011
Posts: 4,155
Time spent in forums: 1 Month 3 Weeks 2 Days 8 h 29 m 53 sec
Reputation Power: 455
On removing
os.environ['SDL_VIDEODRIVER']='windib'
your program works such that the entire cube rotates using a, s, and arrow keys. What keys should I press to duplicate the deformation? And provide any other information I might need to duplicate the problem.

Also, I'm not sure why you have more than 6 colors.
__________________
[code]Code tags[/code] are essential for python code!

Last edited by b49P23TIvg : May 16th, 2013 at 10:02 AM.

#3
May 16th, 2013, 03:46 PM
 imp96
Registered User

Join Date: May 2013
Posts: 3
Time spent in forums: 1 h 37 m 17 sec
Reputation Power: 0
Quote:
 Originally Posted by b49P23TIvg On removing os.environ['SDL_VIDEODRIVER']='windib' your program works such that the entire cube rotates using a, s, and arrow keys. What keys should I press to duplicate the deformation? And provide any other information I might need to duplicate the problem. Also, I'm not sure why you have more than 6 colors.

I have more than six colours for testing purposes so that you can see each individual cube.
Hold Q and the press the up arrow to move the right side.
Rotate the cube before hand so that 3 faces can be seen, then hold Q and press the up arrow.

#4
May 17th, 2013, 12:49 AM
 b49P23TIvg
Contributing User

Join Date: Aug 2011
Posts: 4,155
Time spent in forums: 1 Month 3 Weeks 2 Days 8 h 29 m 53 sec
Reputation Power: 455
This will take some work to figure out.

If you separated the logical blocks of code with
elif
to make rotating the entire cube ... What I'm getting at is that if "q" is held down then only 4 cubes should rotate.

As it is, looks like you rotate the 4 cubes upon release of "up arrow" (or down), all the while all 8 cubes rotate as long as the arrow key is depressed. This makes me accept that the 4 blocks lose synchronization with the physically correct plane. (Rubik's plane?) I'm not so clear on why they shear into ever higher aspect ratio shapes.

Before sleeping on it I'll bet that taking care to rotate half the blocks while the other part is stationary will fix the problem.

#5
May 17th, 2013, 04:38 PM
 imp96
Registered User

Join Date: May 2013
Posts: 3
Time spent in forums: 1 h 37 m 17 sec
Reputation Power: 0
Quote:
 Originally Posted by b49P23TIvg This will take some work to figure out. If you separated the logical blocks of code with elif to make rotating the entire cube ... What I'm getting at is that if "q" is held down then only 4 cubes should rotate. As it is, looks like you rotate the 4 cubes upon release of "up arrow" (or down), all the while all 8 cubes rotate as long as the arrow key is depressed. This makes me accept that the 4 blocks lose synchronization with the physically correct plane. (Rubik's plane?) I'm not so clear on why they shear into ever higher aspect ratio shapes. Before sleeping on it I'll bet that taking care to rotate half the blocks while the other part is stationary will fix the problem.

Thanks for your response, I didn't even think about that so I will try to see if your suggestion works

 Viewing: Dev Shed Forums > Programming Languages > Python Programming > Need help with 3D rotation