-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLorenzAttractor.py
359 lines (313 loc) · 10.9 KB
/
LorenzAttractor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# -*- coding: utf-8 -*-
"""
Created on Thu Feb 20 15:40:08 2014
@author: Nick Walker; Wesley Gardner
"""
import OpenGL.GLUT as GLUT
import OpenGL.GL as GL
import OpenGL.GLU as GLU
import numpy as np
import time as t
import sys
def getVector(vector_a, vector_b):
#the difference between two vectors
return np.array(vector_b) - np.array(vector_a)
def getVectorMagnitude(vector_a, vector_b):
# r = sqrt(x^2 + y^2 + z^2)
return np.sqrt((vector_b[0] - vector_a[0])**2 + (vector_b[1] - vector_a[1])**2 + (vector_b[2] - vector_a[2])**2)
def rotationMatrix(axis,theta):
#the euler-rodrigues formula
axis = axis / np.sqrt(np.dot(axis,axis))
a = np.cos(theta / 2)
b, c, d = - axis * np.sin(theta/2)
return np.array([[a * a + b * b - c * c - d * d, 2 * (b * c - a * d), 2 * (b * d + a * c)], [2 * (b * c + a * d), a * a + c * c - b * b - d * d, 2 * (c * d - a * b)], [2 * (b * d - a * c), 2 * (c * d + a * b), a * a + d * d - b * b - c * c]])
class LorenzGenerator:
x = 1
y = 1
z = 1
sigma = 10
rho = 28
beta = 8.0/3
dt = .01
def __init__(self, sigma = 10, rho = 28, beta = 8.0/3):
self.sigma = sigma
self.rho = rho
self.beta = beta
def start(self,x0 = 1, y0 = 1, z0 = 1, timeStep = 0.01):
self.x = x0
self.y = y0
self.z = z0
self.dt = timeStep
def setTimestep(self, timeStep):
self.dt = timeStep
def getNextPoint(self):
dx = (self.sigma*(self.y - self.x)) * self.dt
dy=(self.x*(self.rho-self.z) - self.y) * self.dt
dz=(self.x * self.y - self.beta * self.z) * self.dt
self.x += dx
self.y += dy
self.z += dz
return (self.x, self.y, self.z)
class Camera:
"""A Class for Managing a Camera"""
def __init__(self, camera = [10.0, 0.0, 5.0], target = [0.0, 0.0, 0.0], up = [0.0, 0.0, 1.0]):
"""Takes Camera Position, Target Position, Transverse Axis, and Maximum Range as Inputs"""
self._camera = np.array(camera)
self._target = np.array(target)
self._up = np.array(up)
self._fv = (np.array(target) - np.array(camera)) / getVectorMagnitude(np.array(target), np.array(camera))
self._transverse = np.cross(self._up, self._fv)
def calcTargetVector(self):
"""Calculates the location of the Target point"""
self._target = self._camera + self._fv
def calcUpVector(self):
"""Calculates the unit vector of the transverse vector of the Camera"""
self._up = np.cross(self._transverse, self._fv)
def calcTransverseVector(self):
"""Calculates the unit vector of the transverse vector of the Camera"""
self._transverse = np.cross(self._up, self._fv)
def getCamera(self):
"""Returns the Position of the Camera"""
return self._camera
def getTarget(self):
"""Returns the Position of the Target"""
return self._target
def getUp(self):
"""Returns the Position of the Up vector"""
return self._up
def getTransverse(self):
"""Returns the Transverse Axis"""
return self._transverse
def getFacingVector(self):
"""Returns the unit vector of the Camera facing"""
return self._fv
def setCamera(self, camera):
"""Sets the Camera Position"""
self._camera = camera
def setTarget(self, target):
"""Sets the Target Position"""
self._target = target
def forward(self):
"""Moves the Camera Forward"""
step = .5 * self._fv
self._target = self._target + step
self._camera = self._camera + step
GLUT.glutPostRedisplay()
def backward(self):
"""Moves the Camera Backward"""
step = .5 * self._fv
self._target = self._target - step
self._camera = self._camera - step
GLUT.glutPostRedisplay()
def up(self):
"""Moves the Camera Facing Up"""
self._fv = np.dot(rotationMatrix(self._transverse, -2 * np.pi / 180.), np.array(self._fv))
self.calcTargetVector()
#self.calcUpVector()
GLUT.glutPostRedisplay()
def down(self):
"""Moves the Camera Facing Down"""
self._fv = np.dot(rotationMatrix(self._transverse, 2 * np.pi / 180.), np.array(self._fv))
self.calcTargetVector()
#self.calcUpVector()
GLUT.glutPostRedisplay()
def left(self):
"""Moves the Camera Facing Left"""
self._fv = np.dot(rotationMatrix(self._up, -2 * np.pi / 180.), np.array(self._fv))
self._target = self._camera + self._fv
self.calcTransverseVector()
GLUT.glutPostRedisplay()
def right(self):
"""Moves the Camera Facing Right"""
self._fv = np.dot(rotationMatrix(self._up, 2 * np.pi / 180.), np.array(self._fv))
self._target = self._camera + self._fv
self.calcTransverseVector()
GLUT.glutPostRedisplay()
def facing(self, x, y, w, h):
"""Changes the Facing of the Camera Based on the Position of the Mouse"""
ax = 0.0
ay = 0.0
if x > 2 * w / 3.0:
ax = (x - w / 2.0) / (w / 2.0)
if x < 1 * w / 3.0:
ax = - (w / 2.0 - x) / (w / 2.0)
if y > 2 * h / 3.0:
ay = (y - h / 2.0) / (h / 2.0)
if y < 1 * h / 3.0:
ay = - (h / 2.0 - y) / (h / 2.0)
self._fv = np.dot(rotationMatrix(self._up, ax * np.pi / 180.), np.array(self._fv))
self._fv = np.dot(rotationMatrix(self._transverse, ay * np.pi / 180.), np.array(self._fv))
self._target = self._camera + self._fv
self.calcTransverseVector()
GLUT.glutPostRedisplay()
p = LorenzGenerator()
p.start()
P = []
start = t.time()
frames = 0.0
#the position of the camera is set at the edge of the system
camera = [75.0, -75.0, 75.0]
#the point the camera is looking at is set to the center of the system
target = [0.0, 0.0, 0.0]
#the up vector determines what is up
up = [0.0, 0.0, 1.0]
#the maximum viewing range
frange = 1000.0
#ambient light vector
lambient = [0.2, 0.2, 0.2, 1.0]
#diffuse light vector
ldiffuse = [0.5, 0.5, 0.5, 1.0]
#specular light vector
lspecular = [0.5, 0.5, 0.5, 1.0]
#light model ambient vector
lmodelambient = [0.2, 0.2, 0.2, 1.0]
#light position is set a little bit up the z axis
lposition = [0.0, 0.0, 0.0, 0.0]
fx = 256
fy = 256
#initialize our camera, which is a ship, because we're in space
cam = Camera(camera, target, up)
#this makes it so everything starts static
running = False
#idle function to update all object positions and camera facing
def Calculations():
global objects
global test
global frames
global start
global p
global P
if running:
P.append(p.getNextPoint())
w = GLUT.glutGet(GLUT.GLUT_WINDOW_WIDTH)
h = GLUT.glutGet(GLUT.GLUT_WINDOW_HEIGHT)
cam.facing(fx, fy, w, h)
GLUT.glutPostRedisplay()
frames = frames + 1
if frames > 100:
elapsed = t.time() - start
sys.stdout.write('\r')
sys.stdout.write(str(frames / elapsed))
sys.stdout.flush()
frames = 0
start = t.time()
#calls to move the ship, used by mouse function
def forward():
Calculations()
cam.forward()
def backward():
Calculations()
cam.backward()
#passive mouse function that gets the mouse position when it is moved
def motion(x, y):
global fx
global fy
fx = x
fy = y
def init():
#lighting is setup
GL.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, lambient)
GL.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, ldiffuse)
GL.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, lspecular)
GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lposition)
GL.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, lmodelambient)
GL.glEnable(GL.GL_LIGHTING)
GL.glEnable(GL.GL_LIGHT0)
GL.glEnable(GL.GL_DEPTH_TEST)
#display list for the axes and the orbitals
GL.glNewList(1, GL.GL_COMPILE)
GL.glPushMatrix()
GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
GL.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, [1.0, 1.0, 1.0, 1.0])
GL.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0])
GL.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, [1.0, 1.0, 1.0, 1.0])
GL.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, .5)
GL.glBegin(GL.GL_LINES)
GL.glVertex3f(0.0, 0.0, 0.0)
GL.glVertex3f(50.0, 0.0, 0.0)
GL.glEnd()
GL.glBegin(GL.GL_LINES)
GL.glVertex3f(0.0, 0.0, 0.0)
GL.glVertex3f(0.0, 50.0, 0.0)
GL.glEnd()
GL.glBegin(GL.GL_LINES)
GL.glVertex3f(0.0, 0.0, 0.0)
GL.glVertex3f(0.0, 0.0, 50.0)
GL.glEnd()
GL.glPopMatrix()
GL.glEndList()
def display():
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
GL.glLoadIdentity()
#the camera is located where it is and is facing the target with the positive z axis up
GLU.gluLookAt(cam.getCamera()[0], cam.getCamera()[1], cam.getCamera()[2], cam.getTarget()[0], cam.getTarget()[1], cam.getTarget()[2], cam.getUp()[0], cam.getUp()[1], cam.getUp()[2])
GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lposition)
#the display list is called
GL.glCallList(1)
GL.glPushMatrix()
GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
GL.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, [0.0, 1.0, 0.0, 1.0])
GL.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0])
GL.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, [1.0, 1.0, 1.0, 1.0])
GL.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, .5)
#GL.glBegin(GL.GL_LINE_LOOP)
#GL.glBegin(GL.GL_LINES)
GL.glBegin(GL.GL_LINE_STRIP)
for x, y, z in P:
GL.glVertex3f(x, y, z)
GL.glEnd()
GL.glPopMatrix()
GLUT.glutSwapBuffers()
#modifies the perspective for when the window size changes
def reshape(w, h):
GL.glViewport(0, 0, w, h)
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GLU.gluPerspective(60.0, float(w)/h, .01, 1000.0)
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
#keyboard commands
def keyboard(key, x, y):
global running
if key == 'w':
cam.forward()
elif key == 's':
cam.backward()
elif key == 'a':
cam.left()
elif key == 'd':
cam.right()
elif key == 'q':
cam.down()
elif key == 'e':
cam.up()
elif key == '':
sys.exit()
elif key == 'p':
running = not running
#the mouse is used to control the camera
def mouse(button, state, x, y):
if button == GLUT.GLUT_LEFT_BUTTON:
if (state == GLUT.GLUT_DOWN):
GLUT.glutIdleFunc(forward)
elif (state == GLUT.GLUT_UP):
GLUT.glutIdleFunc(Calculations)
elif button == GLUT.GLUT_RIGHT_BUTTON:
if (state == GLUT.GLUT_DOWN):
GLUT.glutIdleFunc(backward)
elif (state == GLUT.GLUT_UP):
GLUT.glutIdleFunc(Calculations)
GLUT.glutInit(sys.argv)
GLUT.glutInitDisplayMode (GLUT.GLUT_DOUBLE | GLUT.GLUT_RGB | GLUT.GLUT_DEPTH)
GLUT.glutInitWindowSize (1024, 576)
GLUT.glutInitWindowPosition (100, 100)
GLUT.glutCreateWindow('Lorentz Attractor')
init()
GLUT.glutDisplayFunc(display)
GLUT.glutReshapeFunc(reshape)
GLUT.glutKeyboardFunc(keyboard)
GLUT.glutMouseFunc(mouse)
GLUT.glutPassiveMotionFunc(motion)
GLUT.glutMotionFunc(motion)
GLUT.glutIdleFunc(Calculations)
GLUT.glutMainLoop()