# 3D Wireframe Cube

## Introduction

This snippet presents a rotating wireframe cube written using pygame. It consists of a set of 3D points, an inlined rotation matrix, and a very simple linear transformation to move the 3D points into 2D space.

One of the curious aspects of this snippet is that due to the way the linear transormation is done, there's no perspective and thus you may see the cube rotating right or rotating left, depending on the way you look at it. Try it!

## Code

```   1 from pygame.locals import *
2 import pygame.draw
3 import pygame.time
4 from math import sin, cos
5
6 ORIGINX = 0
7 ORIGINY = 0
8
9 def draw_3dline(surface, color, a, b):
10     """Convert 3D coordinates to 2D and draw line."""
11     ax, ay = a[0]+(a[2]*0.3)+ORIGINX, a[1]+(a[2]*0.3)+ORIGINY
12     bx, by = b[0]+(b[2]*0.3)+ORIGINX, b[1]+(b[2]*0.3)+ORIGINY
13     pygame.draw.line(surface, color, (ax, ay), (bx, by))
14
15 def draw_cube(surface, color, cube):
16     """Draw 3D cube."""
17     a, b, c, d, e, f, g, h = cube
18     draw_3dline(surface, color, a, b)
19     draw_3dline(surface, color, b, c)
20     draw_3dline(surface, color, c, d)
21     draw_3dline(surface, color, d, a)
22
23     draw_3dline(surface, color, e, f)
24     draw_3dline(surface, color, f, g)
25     draw_3dline(surface, color, g, h)
26     draw_3dline(surface, color, h, e)
27
28     draw_3dline(surface, color, a, e)
29     draw_3dline(surface, color, b, f)
30     draw_3dline(surface, color, c, g)
31     draw_3dline(surface, color, d, h)
32
33 def rotate_3dpoint(p, angle, axis):
34     """Rotate a 3D point around given axis."""
35     ret = [0, 0, 0]
36     cosang = cos(angle)
37     sinang = sin(angle)
38     ret[0] += (cosang+(1-cosang)*axis[0]*axis[0])*p[0]
39     ret[0] += ((1-cosang)*axis[0]*axis[1]-axis[2]*sinang)*p[1]
40     ret[0] += ((1-cosang)*axis[0]*axis[2]+axis[1]*sinang)*p[2]
41     ret[1] += ((1-cosang)*axis[0]*axis[1]+axis[2]*sinang)*p[0]
42     ret[1] += (cosang+(1-cosang)*axis[1]*axis[1])*p[1]
43     ret[1] += ((1-cosang)*axis[1]*axis[2]-axis[0]*sinang)*p[2]
44     ret[2] += ((1-cosang)*axis[0]*axis[2]-axis[1]*sinang)*p[0]
45     ret[2] += ((1-cosang)*axis[1]*axis[2]+axis[0]*sinang)*p[1]
46     ret[2] += (cosang+(1-cosang)*axis[2]*axis[2])*p[2]
47     return ret
48
49 def rotate_object(obj, angle, axis):
50     """Rotate an object around given axis."""
51     for i in range(len(obj)):
52         obj[i] = rotate_3dpoint(obj[i], angle, axis)
53
54 def main():
55     global ORIGINX, ORIGINY
56     pygame.init()
57     screen = pygame.display.set_mode((320,200),
58                                      HWSURFACE|DOUBLEBUF)
59     # Move origin to center of screen
60     ORIGINX = screen.get_width()/2
61     ORIGINY = screen.get_height()/2
62     cube = [(-50, 50, 50), ( 50, 50, 50),
63             ( 50,-50, 50), (-50,-50, 50),
64             (-50, 50,-50), ( 50, 50,-50),
65             ( 50,-50,-50), (-50,-50,-50)]
66     while True:
67         draw_cube(screen, 255, cube)
68         event = pygame.event.poll()
69         if event.type == QUIT or (event.type == KEYDOWN and
70                                   event.key == K_ESCAPE):
71             break
72         pygame.display.flip()
73         pygame.time.delay(50)
74         draw_cube(screen, 0, cube)
75         rotate_object(cube, 0.1, (0,1,0))
76         rotate_object(cube, 0.01, (0,0,1))
77         rotate_object(cube, 0.01, (1,0,0))
78
79 if __name__ == "__main__":
80     main()
81
82 # vim:ts=4:sw=4
83
```

## Author

Gustavo Niemeyer <gustavo@niemeyer.net>

snippets/cube (last edited 2008-03-03 03:34:41 by GustavoNiemeyer)