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.

Thanks in advance.

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 aa = math.cos(rad_theta) + math.pow(ux,2)*(1-math.cos(rad_theta)) ab = ux*uy*(1-math.cos(rad_theta))-uz*math.sin(rad_theta) ac = ux*uz*(1-math.cos(rad_theta)) + uy*math.sin(rad_theta) ba = uy*ux*(1-math.cos(rad_theta) + uz*math.sin(rad_theta)) bb = math.cos(rad_theta) + (math.pow(uy,2)*(1-math.cos(rad_theta))) bc = uy*uz*(1-math.cos(rad_theta)) - ux*math.sin(rad_theta) print bc ca = uz*ux*(1-math.cos(rad_theta)) - uy*math.sin(rad_theta) cb = uz*uy*(1-math.cos(rad_theta)) + ux*math.sin(rad_theta) cc = math.cos(rad_theta) + math.pow(uz,2)*(1-math.cos(rad_theta)) 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 xmidprime = x*math.cos(radz) - y*math.sin(radz) ymidprime = x*math.sin(radz) + y*math.cos(radz) yprime = ymidprime*math.cos(radx) - z*math.sin(radx) zmidprime = ymidprime*math.sin(radx) + z*math.cos(radx) zprime = zmidprime*math.cos(rady) - xmidprime*math.sin(rady) xprime = zmidprime*math.sin(rady) + xmidprime*math.cos(rady) 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()

Tweet This+ 1 thisPost To Linkedin