Using keyboard to move a ball, X and Z axis, in VPython - python

Doing a project for physics class. vPython documentation is not very good I think and it's a bit confusing. I need to move a ball, which currently is being moved by mouse, but I need to make this work with 2 players, so I need to use keyboard events.
Currently this is the code:
#GlowScript 2.7 VPython
scene.range = 30
scene.forward = vec(0,-0.25,-1)
#red side of the field
redField = box()
redField.size = vec(40,1,60)
redField.pos= vec(-20,0,0)
redField.color = color.red
#blue side of the field
redField = box()
redField.size = vec(40,1,60)
redField.pos= vec(20,0,0)
redField.color = color.blue
cueBall = sphere()
cueBall.radius = 1.5
cueBall.pos = vec(0,2,0)
cueBall.vel = vec(3,0,0) # velocity in m/s
cueBall.mass = 2.0
blueBall = sphere()
blueBall.radius = 1.5
blueBall.pos = vec(4,2,0)
blueBall.color = color.blue
blueBall.mass = 1.5
blueBall.vel = vec(0,0,0)
blueBall.force = arrow(axis = vec(0,0,0), color = color.blue)
rail1 = box()
rail1.texture = {'file': "https://i.imgur.com/ss5OcnL.jpg"}
rail1.size = vec(3,3,55)
rail1.pos = vec(-39,1,0)
rail2 = box()
rail2.texture = {'file': "https://i.imgur.com/ss5OcnL.jpg"}
rail2.size = vec(3,3,55)
rail2.pos = vec(39,1,0)
rail3 = box()
rail3.texture = {'file': "https://i.imgur.com/ss5OcnL.jpg"}
rail3.size = vec(80,3,3)
rail3.pos = vec(0,1,29)
rail4 = box()
rail4.texture = {'file': "https://i.imgur.com/ss5OcnL.jpg"}
rail4.size = vec(80,3,3)
rail4.pos = vec(0,1,-29)
redBall = sphere()
redBall.radius = 1.5
redBall.pos = vec(-3,2,0)
redBall.color = color.red
redBall.force = arrow(axis = vec(0,0,0), color = color.red)
redBall.vel = vec(0,0,0)
redBall.mass = 1.5
yBall = sphere()
yBall.radius = 1.5
yBall.pos = vec(-9,2,0)
yBall.color = color.yellow
yBall.vel = vec(0,0,0)
yBall.mass = 1.5
yBall.force = arrow(axis = vec(0,0,0), color = color.yellow)
rail = []
rail.append(rail1, rail2, rail3, rail4)
ball = []
ball.append(cueBall, blueBall, redBall, yBall)
ball[0].force = arrow(axis = vec(0,0,0), color = color.white)
drag = False
chosenObject = None
scene.bind("mousedown", down)
scene.bind("mousemove", move)
scene.bind("mouseup", up)
def down():
nonlocal drag, chosenObject
chosenObject = scene.mouse.pick()
drag = True
def move():
nonlocal drag, chosenObject
if (drag == True):
chosenObject.force.axis = scene.mouse.pos - chosenObject.pos
chosenObject.force.pos = chosenObject.pos
chosenObject.force.axis.y = 0
def up():
nonlocal drag, chosenObject
chosenObject.force.axis = vec(0,0,0)
chosenObject = None
drag = False
elasticConst = 500
dt = 0.01
time = 0
while (True):
rate(1/dt)
for i in range(len(ball)):
ball[i].vel = ball[i].vel + ( ball[i].force.axis * dt / ball[i].mass )
ball[i].force.pos = ball[i].pos
for i in range(len(ball)):
for j in range(len(ball)):
if (i == j): continue
separation = ball[i].pos - ball[j].pos
contactSeparation = separation.norm() * (ball[i].radius + ball[j].radius)
if (separation.mag < contactSeparation.mag):
elasticForce = - elasticConst * (separation - contactSeparation)
ball[i].vel = ball[i].vel + (elasticForce / ball[i].mass) * dt
for i in range(len(ball)):
if ( ball[i].pos.x < rail1.pos.x + 2):
ball[i].pos.x = rail1.pos.x + 2
ball[i].vel.x = - ball[i].vel.x
if ( ball[i].pos.x > rail2.pos.x - 2):
ball[i].pos.x = rail2.pos.x - 2
ball[i].vel.x = - ball[i].vel.x
if ( ball[i].pos.z > rail3.pos.z - 2):
ball[i].pos.z = rail3.pos.z - 2
ball[i].vel.z = - ball[i].vel.z
if ( ball[i].pos.z < rail4.pos.z + 2):
ball[i].pos.z = rail4.pos.z + 2
ball[i].vel.z = - ball[i].vel.z
## for i in range(len(ball)):
# for j in range(len(hole)):
# if ((ball[i].pos - hole[j].pos).mag < ball[i].radius + hole[j].radius):
# ball[i].visible = False
for i in range(len(ball)):
ball[i].pos = ball[i].pos + ball[i].vel * dt
If you could help me understand how I could increment the position variables on keyboard.

Related

Trouble converting code from VBA to Python

I am having issues converting this code from VBA to python, it's a function that needs to be converted to python instead of VBA
Function NC(SPL, pond) As Single
Dim A As Single
Dim B As Single
Dim I As Integer
Dim SPL1(8) As Single
B = 0
If pond = "A" Then
SPL1(1) = SPL(1) + 26.2228
SPL1(2) = SPL(2) + 16.1897
SPL1(3) = SPL(3) + 8.6748
SPL1(4) = SPL(4) + 3.2478
SPL1(5) = SPL(5)
SPL1(6) = SPL(6) - 1.2017
SPL1(7) = SPL(7) - 0.9636
SPL1(8) = SPL(8) + 1.1469
Else
SPL1(1) = SPL(1)
SPL1(2) = SPL(2)
SPL1(3) = SPL(3)
SPL1(4) = SPL(4)
SPL1(5) = SPL(5)
SPL1(6) = SPL(6)
SPL1(7) = SPL(7)
SPL1(8) = SPL(8)
End If
For I = 1 To 8
If I = 1 Then
A = 1.5215 * SPL1(1) - 57.029
ElseIf I = 2 Then
A = 1.2855 * SPL1(2) - 31.628
ElseIf I = 3 Then
A = 1.1853 * SPL1(3) - 18.938
ElseIf I = 4 Then
A = 1.0888 * SPL1(4) - 8.5807
ElseIf I = 5 Then
A = 1.019 * SPL1(5) - 2.0793
ElseIf I = 6 Then
A = 0.9922 * SPL1(6) + 1.2421
ElseIf I = 7 Then
A = 0.9738 * SPL1(7) + 3.2226
ElseIf I = 8 Then
A = 0.9738 * SPL1(8) + 4.1964
End If
If A > B Then
B = A
End If
Next I
NC = Int(Round(B + 0.5))
End Function
This is what I have so far in python but it is giving me an errorcode error in python the error says it's an indexing issue in python I would like to solve that error so that the function works but not sure how exactly to solve it
def NC(SPL,pond):
SPL1 =[(0.0 for x in range(0,8))]
B = 0.0
if pond == 'A':
SPL1[0] = SPL[0] + 26.228
SPL1[1] = SPL[1] + 16.1897
SPL1[2] = SPL[2] + 8.6748
SPL1[3] = SPL[3] + 3.2478
SPL1[4] = SPL[4]
SPL1[5] = SPL[5] - 1.2017
SPL1[6] = SPL[6] - 0.9636
SPL1[7] = SPL[7] + 1.1469
else:
SPL1[0] = SPL[0]
SPL1[1] = SPL[1]
SPL1[2] = SPL[2]
SPL1[3] = SPL[3]
SPL1[4] = SPL[4]
SPL1[5] = SPL[5]
SPL1[6] = SPL[6]
SPL1[7] = SPL[7]
for i in range(0, 8):
if i == 0:
A = 1.5215 * SPL1[0] -57.029
if i == 1:
A = 1.2855 * SPL1[1] -31.628
if i == 2:
A = 1.1853 * SPL1[2] -18.938
if i == 3:
A = 1.0888 * SPL1[3] -8.5807
if i == 4:
A = 1.019 * SPL1[4] -2.0793
if i == 5:
A = 0.9922 * SPL1[5] +1.2421
if i == 6:
A = 0.9738 * SPL1[6] +3.2226
if i == 7:
A = 0.9738 * SPL1[7] +4.1964
if A > B:
B = A
return int(B+0.5)
Python is dynamically typed and 0 base indexed. Also by convention lower-case variable names are used. So your code would be something along the lines of:
def nc(spl, pond):
spl1 =[0.0 for _ in range(8))]
b = 0.0
if pond == 'A':
spl1[0] = spl[0] + 26.228
#and so on
else:
spl1[0] = spl[0]
# and so on
for i in range(0, 8):
if i == 0:
a = 1.5215 * spl1[0] -57.029
# and so on
if a > b:
b = a
return int(b+0.5)

Mpi4py: printing and plotting during execution

I recently start working with mpi in order to use it to accelerate some code (a sph/gravity simulation).
So far it seem to be working. The position of my particle have change between the beginning and the end of the program, task manager show that several python thread are working...
But i have two problem:
1/ i can't print text during the execution of the program. The text is only print once it's finished
2/ I'm unable to create a graph using matplotlib.
In both case, neither python nor mpi return any error. My guess, for the text at least, is that its print when the execution end with mpiexec.
thanks for any insight !
here the code i run it with !mpiexec -n 8 python mpi4py_test.py
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from mpi4py import MPI
class particule:
def __init__(self, h, pos, vel = [0, 0], m = 1, P = 0, density = 0, acc = [0, 0]):
self.x, self.y = pos
self.u, self.v = vel
self.acc_x, self.acc_y = acc
self.m = m
self.h = h # kernel lenght
self.P = P # Pressure
self.density = density
def kernel(part_a, part_b ):
" monaghan cubic spline "
cst = 1 / (np.pi * part_a.h**3)
dist = np.sqrt((part_b.x-part_a.x)**2 + (part_b.y-part_a.y)**2 )
r = dist / h
tmp = 0
if r < 1:
tmp = cst * (1 - 3/2* r**2 + 3/4*r**3)
elif r < 2:
tmp = cst * (1/4*(2-r)**3)
return tmp
def grad_kernel(part_a, part_b):
cst = 1 / (np.pi * part_a.h**3)
dist = np.sqrt((part_b.x-part_a.x)**2 + (part_b.y-part_a.y)**2 )
r = dist / part_a.h
tmp = 0
if r < 1:
tmp = cst * (9/4 * r**2 - 3*r)
elif r < 2:
tmp = cst * (-3/4*(2-r)**2)
return tmp
class hash_grid:
def __init__(self, cell_size):
self.cell_size = cell_size
self.cell = {}
self.part_list = []
def key(self, part):
return (part.x//self.cell_size,
part.y//self.cell_size)
def add(self, part):
tmp = self.key(part)
self.cell.setdefault(tmp, []).append(part)
self.part_list.append(part)
def neighbours(self, part):
idx = self.key(part)
cell_N = None
cell_S = None
cell_E = None
cell_W = None
cell_NE = None
cell_NW = None
cell_SE = None
cell_SW = None
if (idx[0], idx[1]+1) in self.cell: cell_N = (idx[0], idx[1]+1)
if (idx[0], idx[1]-1) in self.cell: cell_S = (idx[0], idx[1]-1)
if (idx[0]+1, idx[1]) in self.cell: cell_E = (idx[0]+1, idx[1])
if (idx[0]-1, idx[1]) in self.cell: cell_W = (idx[0]-1, idx[1])
if (idx[0]+1, idx[1]+1) in self.cell: cell_NE = (idx[0]+1, idx[1]+1)
if (idx[0]-1, idx[1]+1) in self.cell: cell_NW = (idx[0]-1, idx[1]+1)
if (idx[0]+1, idx[1]-1) in self.cell: cell_SE = (idx[0]+1, idx[1]-1)
if (idx[0]-1, idx[1]-1) in self.cell: cell_SW = (idx[0]-1, idx[1]-1)
return [value for cel in (idx, cell_N, cell_S, cell_E, cell_W, cell_NE, cell_NW, cell_SE, cell_SW) if cel!=None for value in self.cell.get(cel) ]
def split(to_split, nb_chunk):
"take a list and split it most evenly possible"
result = []
q, r = divmod(len(to_split), nb_chunk)
curr = 0
last = 0
for i in range(nb_chunk):
if r>0:
last = curr + q + 1
result.append(to_split[curr: last])
r = r-1
curr = last
else:
last = curr + q
result.append(to_split[curr: last])
curr = last
return result
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
if rank == 0:
n_part = 2000
h = 2
grid = hash_grid(h)
points = np.zeros((n_part, 2))
sim_range = 20
dt = 0.005
n_iter = 2500
k = 5
for _i in range(n_part):
pos = np.random.uniform(-sim_range, sim_range, 2)
vel = np.random.uniform(-.2, .2, 2)
p = particule(h, pos, vel)
grid.add(p)
points[_i, :] = pos
for part in grid.part_list:
part.density = 0
part.P = 0
for p in grid.neighbours(part):
part.density = part.density + p.m * kernel(part, p)
part.P = k * ( part.density )**2 # - density_0)
data = split(grid.part_list,8)
for t in range(10):
if rank == 0 :
"1 - verlet 1/2 ; serial"
for i, part in enumerate(grid.part_list):
part.u, part.v = part.u + part.acc_x * dt/2, part.v + part.acc_y * dt/2
part.x, part.y = part.x + part.u * dt, part.y + part.v * dt
"2 - update grid ; serial"
jnk = grid.part_list
del grid
grid=hash_grid(h)
for p in jnk:
grid.add(p)
grid_bcast = grid
data_b = grid
chunk_of_part_list = split(grid.part_list,8)
else:
grid_bcast=None
chunk_of_part_list = None
data_b=None
grid_bcast = comm.bcast(grid_bcast, root=0)
chunk_of_part_list = comm.scatter(chunk_of_part_list, root=0)
"3 - get acc ; parallel"
for part in chunk_of_part_list:
part.acc_x = 0
part.acc_y = 0
for p in grid_bcast.neighbours(part):
if p != part:
r = np.sqrt((p.x-part.x)**2 + (p.y-part.y)**2)
if r==0: pass
else:
part.acc_x = part.acc_x - p.m * (part.P/part.density**2 + p.P/p.density**2) * grad_kernel(part, p) * (p.x - part.x)/r
part.acc_y = part.acc_y - p.m * (part.P/part.density**2 + p.P/p.density**2) * grad_kernel(part, p) * (p.y - part.y)/r
dist = np.sqrt(part.x**2+part.y**2)
part.acc_x = part.acc_x - .5 * part.x -1*part.u
part.acc_y = part.acc_y - .5 * part.y -1*part.v
chunk_of_part_list = comm.gather(chunk_of_part_list,root=0)
"4 - verlet 2/2 ; serial"
if rank == 0:
grid.part_list = list(matplotlib.cbook.flatten(chunk_of_part_list))
for i, part in enumerate(grid.part_list):
part.u, part.v = part.u + part.acc_x * dt/2, part.v + part.acc_y * dt/2
points[i,0], points[i,1] = part.x, part.y # for the figure
if rank==0:
print(t, flush=True)
if rank == 0:
print('point 0', points[0,:])
fig = plt.figure()
ax = fig.add_subplot()
sc = ax.scatter(points[:, 0], points[:, 1],s=3)
ax.set_aspect('equal', 'box')
ax.set_xlim(-sim_range,sim_range)
ax.set_ylim(-sim_range,sim_range)

MPC with python and Error ValueError: `f0` passed has more than 1 dimension

I wrote a MPC with Python and it worked before. After a long time I want to use it again but I got this Error
f0 passed has more than 1 dimension.
But I didn't change anything on my code. It is some kind of strange.
Here is my code:
import numpy as np
import numpy.linalg as npl
import matplotlib.pyplot as plt
from scipy.optimize import minimize
def mpcAugment(Am, Bm, Cm ):
"Function for Augmented Model"
nx, nu = Bm.shape
ny = Cm.shape[0]
A = np.zeros((nx+ny,nx+ny))
A[0:nx,0:nx] = Am
A[nx:nx+ny,0:nx] = Cm#Am
A[nx:nx+ny,nx:nx+ny] = np.eye(ny)
B = np.zeros((nx+ny,nu))
B[0:nx,:nu] = Bm
B[nx:nx+ny,:nu] = Cm#Bm
C = np.zeros((ny,nx+ny))
C[:ny,nx:nx+ny] = np.eye(ny)
return A, B, C
'Define Parameters'
k = 0.4
AICB = 153.8
mcp = 8.8e4
vamb1 = 30
vamb2 = 45
a = -k*AICB/mcp
b = -1/mcp
Ts = 20
VICBref = -5.0
Am = np.array([[1+Ts*a]])
Bm = np.array([[Ts*b]])
Gm = np.array([[-Ts*a]])
Cm = np.array([[1]])
A, B, C = mpcAugment(Am,Bm,Cm)
A, G, C = mpcAugment(Am,Gm,Cm)
nx, nu = B.shape
ny = C.shape[0]
nd = G.shape[1]
Np = 20
Nu = 5
F = np.zeros((Np*ny,nx))
PHI = np.zeros((Np*ny,Nu*nu))
PHIw = np.zeros((Np*ny,Np*nd))
for i in range(0,Np):
Ai = npl.matrix_power(A, i+1)
F[i*ny:(i+1)*ny,:] = C#Ai
for j in range(0, Nu):
if j <= i:
Aij = np.linalg.matrix_power(A, i-j)
PHI[i*ny:(i+1)*ny, j*nu:(j+1)*nu] = C#Aij#B
for j in range(0, Np):
if j <= i:
Aij = np.linalg.matrix_power(A, i-j)
PHIw[i*ny:(i+1)*ny, j*nd:(j+1)*nd] = C#Aij#G
umax = 3100
umin = 0
Q = np.eye(Np*ny)
R = 1e-2*np.eye(Nu*nu)
Rs = VICBref*np.ones((Np*ny,1))
Ainq = np.zeros((2*Nu*nu,Nu*nu))
binq = np.zeros((2*Nu*nu,1))
cinq = np.zeros((2*Nu*nu,1))
for i in range(0,Nu):
binq[i*nu:(i+1)*nu] = umax
binq[(i+Nu)*nu:(Nu+i+1)*nu] = 1
cinq[i*nu:(i+1)*nu] = 1
cinq[(i+Nu)*nu:(Nu+i+1)*nu] = -1
for j in range(0,i+1):
Ainq[i*nu:(i+1)*nu,j*nu:(j+1)*nu] = np.eye(nu)
Ainq[(i+Nu)*nu:(Nu+i+1)*nu,j*nu:(j+1)*nu] = np.eye(nu)
u0 = 0
def objective(du):
dU = np.array(du).reshape((len(du),1))
Y = F#x + PHI#dU + PHIw#w
return np.transpose((Rs-Y))#(Rs-Y)+np.transpose(dU)#R#(dU)
def constraint1(du):
dU = np.array(du).reshape((len(du),1))
return (binq - Ainq#dU - cinq*u0)[0]
#print(objective([1,1,1]))
ulim = (umin, umax)
bnds = np.kron(np.ones((Nu,1)),ulim)
#print(bnds)
Um = np.ones((nu*Nu,1))
Tsim = 5e4
time = np.arange(0,Tsim,Ts)
Nt = len(time)
xm = np.zeros((Nt,1))
um = np.zeros((Nt,nu))
ym = np.zeros((Nt,ny))
xm[0] = 0
ym[0] = Cm.dot(xm[0])
w = np.zeros((Np*nd,1))
print('Am = ',Am)
print('Bm = ',Bm)
print('Cm = ',Cm)
x = np.zeros((nx,1))
x[1] = xm[0]
vamb = vamb1
Vamb = np.zeros((Nt,1))
Ns = int(np.floor(Nt/2))
Vamb[0:Ns] = vamb1*np.ones((Ns,1))
Vamb[Ns:Nt] = vamb2*np.ones((Nt-Ns,1))
Vref = VICBref*np.ones((Nt,1))
con = {'type':'ineq','fun':constraint1}
for i in range(0,Nt-1):
sol = minimize(objective, Um, method = 'SLSQP',constraints = con)
if sol.success == False:
print('Error Cant solve problem')
exit()
Um = sol.x
um[i+1] = um[i] + Um[0]
u0 = um[i+1]
xm[i+1] = Am.dot(xm[i])+Bm.dot(um[i+1])+Gm.dot(Vamb[i])
ym[i+1] = Cm.dot(xm[i+1])
for j in range(0,Np):
if i+j < Nt:
Rs[j] = Vref[i+j]
w[j] = Vamb[i+j]-Vamb[i+j-1]
else:
Rs[j] = Vref[Nt-1]
w[j] = 0
x[0] = xm[i+1] - xm[i]
x[1] = xm[i+1]
print('Q = ',um[i+1],' , VICB = ',xm[i+1], ' vamb = ', Vamb[i])
hour = 60*60
plt.figure()
plt.subplot(2,1,1)
plt.plot(time/hour,ym)
plt.plot(time/hour,Vref,'--')
plt.xlabel('time(hours)')
plt.xlim([0, Tsim/hour])
plt.subplot(2,1,2)
plt.plot(time/hour,um)
plt.xlim([0, Tsim/hour])
plt.show()
It about a controller, which control the temperature of a cool box.
Is that possible that anything changed in main simply code?
I think the problem is now in minimizations part.
I reinstalled all of my libraries and it worked

Why does translation matrix not affect rendering of 3d model in python?

I am very new to coding and decided to start with a 3D engine in python. I followed OLC's tutorial and adapted it for python. However, my translation matrix doesn't seem to be affecting how the model is rendered. Any advice at all, from code improvements, to telling me how bad I am would be much appreciated.
I have tried to re-do the vector multiplication in all sorts of ways, and all kinds of reformatting and re-trying, but I am not even sure what I am looking for in this case. Any help would be much appreciated
As I am new, I apologize for any poor etiquette I may have done on this site.
import math, numpy as np, pygame, sys, os, random, string
from pygame.locals import *
pygame.init()
width,height = 1600,900;cx,cy = width//2,height//2
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
pygame.display.set_caption('3D Graphics')
def loadObj(filename):
tris = []
verts = []
try:
fp = open(filename, "r")
except:
print("File: "+filename+" not found")
sys.exit(1)
for line in fp:
if line.startswith('#'): continue
values = line.split()
if not values: continue
if values[0] == 'v':
#v = vec3(float(values[1]), float(values[2]), float(values[3]))
#verts.append(vec3(int(values[1]), int(values[2]), int(values[3])))
verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))
#verts.append(v)
elif values[0] == 'f':
p = []
for v in values[1:]:
w = v.split("/")
p.append(int(w[0]))
#print(p)
#print(verts[-185])
triTemp = triangle(verts[p[0] - 1], verts[p[1] - 1], verts[p[2]- 1])
tris.append(triTemp)
fp.close()
return tris
class vec3(): #Possibly Obsolete
__slots__ = ['x','y','z','w']
def __init__(self, x, y, z, w):
self.x = x
self.y = y
self.z = z
self.w = w
class triangle():
__slots__ = ['vec1','vec2','vec3']
def __init__(self, vec1, vec2, vec3):
self.vec1 = vec1
self.vec2 = vec2
self.vec3 = vec3
def matrixMakeTranslation(x, y, z):
matrix = np.zeros((4,4))
matrix[0,0] = 1.0
matrix[1,1] = 1.0
matrix[2,2] = 1.0
matrix[3,3] = 1.0
matrix[3,0] = x
matrix[3,1] = y
matrix[3,2] = z
return matrix
def Matrix_MakeRotationX(fAngleRad):
matrix = np.zeros((4,4))
matrix[0,0] = 1.0
matrix[1,1] = (math.cos(fAngleRad * 0.5))
matrix[1,2] = (math.sin(fAngleRad * 0.5))
matrix[2,1] = (-math.sin(fAngleRad * 0.5))
matrix[2,2] = (math.cos(fAngleRad * 0.5))
matrix[3,3] = 1.0
return matrix
def Matrix_MakeRotationZ(fAngleRad):
matrix = np.zeros((4,4))
matrix[0,0] = (math.cos(fAngleRad))
matrix[0,1] = (math.sin(fAngleRad))
matrix[1,0] = (-math.sin(fAngleRad))
matrix[1,1] = (math.cos(fAngleRad))
matrix[2,2] = 1.0
matrix[3,3] = 1.0
return matrix
fNear = float(0.1) #Create the Projection Matrix
fFar = float(1000.0)
fFov = float(90.0)
fAspectRatio = float(height/width)
fFovRad = 1/math.tan(fFov * 0.5 / 180 * math.pi)
projectionMatrix = np.zeros((4,4))
projectionMatrix[0,0] = fAspectRatio * fFovRad
projectionMatrix[1,1] = fFovRad
projectionMatrix[2,2] = fFar / (fFar - fNear)
projectionMatrix[3,2] = float((-fFar * fNear) / (fFar - fNear))
projectionMatrix[2,3] = 1.0
projectionMatrix[3,3] = 0.0
meshname = "teapot.obj" #Load the mesh
tris = loadObj(meshname)
vCamera = np.array([0,0,0,0])
fAngleRad = 0
colour = (255,255,255)
colour2 = (0,0,0)
triProjected = triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0])) #These are used later
triTranslalted = triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0]))
triTransformed= triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0]))
while True: #Begin Loop
for event in pygame.event.get(): #Quit
if event.type == pygame.QUIT: pygame.quit(); sys.exit()
dt = clock.tick()/1000
pygame.display.set_caption('3D Graphics - FPS: %.2f'%int(dt))
print("fps:", clock.get_fps()) #Framerate and caption
pygame.display.update()
screen.fill((0,0,0))
fAngleRad += 0.1
matRotZ = Matrix_MakeRotationZ(fAngleRad * 0.5) #Set up matricies
matRotX = Matrix_MakeRotationX(fAngleRad)
matTrans = matrixMakeTranslation(0.0,0.0,50.0)
matWorld = np.identity(4)
matWorld = matRotZ # matRotX
matWorld = matWorld # matTrans #Seems to be broken. idk why.
for i in tris: #For triangle in all triangles
reDo1 = np.array([i.vec1.x, i.vec1.y, i.vec1.z, i.vec1.w])
reDo2 = np.array([i.vec2.x, i.vec2.y, i.vec2.z, i.vec2.w])
reDo3 = np.array([i.vec3.x, i.vec3.y, i.vec3.z, i.vec3.w])
triTransformed.vec1 = np.matmul(matWorld, reDo1)
triTransformed.vec2 = np.matmul(matWorld, reDo2)
triTransformed.vec3 = np.matmul(matWorld, reDo3)
triProjected.vec1 = np.matmul(projectionMatrix, triTransformed.vec1)
triProjected.vec2 = np.matmul(projectionMatrix, triTransformed.vec2)
triProjected.vec3 = np.matmul(projectionMatrix, triTransformed.vec3)
#Scale Into View
triProjected.vec1[0] += 1.0
triProjected.vec1[1] += 1.0
triProjected.vec2[0] += 1.0
triProjected.vec2[1] += 1.0
triProjected.vec3[0] += 1.0
triProjected.vec3[1] += 1.0
triProjected.vec1[0] *= 0.5 * width
triProjected.vec1[1] *= 0.5 * height
triProjected.vec2[0] *= 0.5 * width
triProjected.vec2[1] *= 0.5 * height
triProjected.vec3[0] *= 0.5 * width
triProjected.vec3[1] *= 0.5 * height
pygame.draw.polygon(screen, colour, [(triProjected.vec1[0], triProjected.vec1[1]),(triProjected.vec2[0], triProjected.vec2[1]),(triProjected.vec3[0], triProjected.vec3[1])])
You are using Homogenious Coordinates to represent the vertices of your model. So the W component must be 1.
When you load your model you are setting W to 0.
verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))
By setting W=0 you are creating a Homogenious Vector (a.k.a "point at infinity" or "ideal point") and by setting W=1 you are creating a Homogeneous Point.
Points can be translated but vectors cannot.
https://en.m.wikipedia.org/wiki/Homogeneous_coordinates

python, matplotlib.animation: My 'planets' aren't rotating?

My planets are not rotating in my plot and im not entirely sure why?
As a side note, is there way to scale the planets radius properly with respect to the sun. And could the initial positions(x,y) be the aphelion distance from the sun? But no worries, no need to answer, just looking form some insight. Thank you.
from pylab import*
from matplotlib.animation import *
earth_radius = 6.3781e6#meters earth radius
suns_radius = 696e6#meters suns radius
mercury_radius = 2439.5e3# meters mercury radius
venus_radius = 6052e3 #meters venus radius
SunEarth_dist = 152e9 #distance from sun to earth approx. 1Au = 152e6km
SunMercury_dist = 69.8e9 #meters
SunVenus_dist = 108.9e9#meters
sun_mass = 1.988e30 #m1 : kg
mercury_mass = .330e24#m2: kg
venus_mass = 4.87e24 #m3 : kg
earth_mass = 5.97e24#m4 : kg
#radius of the planets scaled from the sun
r1 = suns_radius
r2 = mercury_radius
r3 = venus_radius
r4 = earth_radius
n = 10000#number of steps
dt = 10000#step size
G = 6.67384*10**(-11)#gravitational constant
def planets():
tmax = dt* n
t = 0
x = 0
#inital position of the planets
x1 = 3844e8*0.8*0
y1 = 3844e8*0.8*0
x2 = 3844e8*0.8
y2 = -3844e8*0.8*0
x3 = -3844e8*0.8
y3 = 3844e8*0.8*0
x4 = -3844e8*0.8*0
y4 = -3844e8*0.8
#intial velocity of each planet
Velocity_xS = 0
Velocity_yS = 0
Velocity_xM = 800
Velocity_yM= 1700
Velocity_xV = 0
Velocity_yV = -1500
Velocity_xE = 2000
Velocity_yE = 0
#distance between the planets
d12 = sqrt((x1-x2)**2+(y1-y2)**2)
d23 = sqrt((x2-x3)**2+(y2-y3)**2)
d13 = sqrt((x1-x3)**2+(y1-y3)**2)
d14 = sqrt((x1-x4)**2+(y1-y4)**2)
d24 = sqrt((x2-x4)**2+(y2-y4)**2)
d34 = sqrt((x3-x4)**2+(y3-y4)**2)
while t < tmax:
Fg12 = (G*sun_mass*mercury_mass)/d12**2
Fgx12 = -Fg12*((x1-x2))/d12
Fgy12 = -Fg12*((y1-y2))/d12
Fgx21 = -Fg12*((x2-x1))/d12
Fgy21 = -Fg12*((y2-y1))/d12
Fg13 = (G*sun_mass*venus_mass)/d13**2
Fgx13 = -Fg13*((x1-x3))/d13
Fgy13 = -Fg13*((y1-y3))/d13
Fgx31 = -Fg13*((x3-x1))/d13
Fgy31 = -Fg13*((y3-y1))/d13
Fg23 = (G*venus_mass*mercury_mass)/d23**2
Fgx23 = -Fg23*((x2-x3))/d23
Fgy23 = -Fg23*((y2-y3))/d23
Fgx32 = -Fg23*((x3-x2))/d23
Fgy32 = -Fg23*((y3-y2))/d23
Fg14 = (G*sun_mass*earth_mass)/d14**2
Fgx14 = -Fg14*((x1-x4))/d14
Fgy14 = -Fg14*((y1-y4))/d14
Fgx41 = -Fg14*((x4-x1))/d14
Fgy41 = -Fg14*((y4-y1))/d14
Fg24 = (G*sun_mass*earth_mass)/d24**2
Fgx24 = -Fg24*((x2-x4))/d24
Fgy24 = -Fg24*((y2-y4))/d24
Fgx42 = -Fg24*((x4-x2))/d24
Fgy42 = -Fg24*((x4-x2))/d24
Fg34 = (G*sun_mass*earth_mass)/d34**2
Fgx34 = -Fg34*((x3-x4))/d34
Fgy34 = -Fg34*((y3-y4))/d34
Fgx43 = -Fg34*((x4-x3))/d34
Fgy43 = -Fg34*((y4-y3))/d34
Acceleration_xS = Fgx12/sun_mass + Fgx13/sun_mass + Fgx14/sun_mass
Acceleration_yS = Fgy12/sun_mass + Fgy13/sun_mass + Fgy14/sun_mass
Acceleration_xM = Fgx21/mercury_mass + Fgx23/mercury_mass + Fgx24/mercury_mass
Acceleration_yM = Fgy21/mercury_mass + Fgy23/mercury_mass + Fgy24/mercury_mass
Acceleration_xV = Fgx32/venus_mass + Fgx31/venus_mass + Fgx34/venus_mass
Acceleration_yV = Fgy32/venus_mass + Fgy31/venus_mass + Fgy34/venus_mass
Acceleration_xE = Fgx41/earth_mass + Fgx42/earth_mass+ Fgx43/earth_mass
Acceleration_yE = Fgy41/earth_mass + Fgy42/earth_mass + Fgx43/earth_mass
Velocity_xS = Velocity_xS +Acceleration_xS*dt
Velocity_yS = Velocity_yS +Acceleration_yS*dt
Velocity_xM = Velocity_xM +Acceleration_xM*dt
Velocity_yM = Velocity_yM +Acceleration_yM*dt
Velocity_xV = Velocity_xV +Acceleration_xV*dt
Velocity_yV = Velocity_yV +Acceleration_yV*dt
Velocity_xE = Velocity_xE +Acceleration_xE*dt
Velocity_yE = Velocity_yE +Acceleration_yE*dt
#update the position of the planets
x1 = x1 + Velocity_xS*dt
y1 = y1 + Velocity_yS*dt
x2 = x2 + Velocity_xM*dt
y2 = y2 + Velocity_yM*dt
x3 = x3 + Velocity_xV*dt
y3 = y3 + Velocity_yV*dt
x4 = x4 + Velocity_xE*dt
y4 = y4 + Velocity_yE*dt
Sun.center = x1,y1
Mercury.center = x2,y2
Venus.center = x3,y3
Earth.center = x4,y4
d12 = sqrt((x1-x2)**2+(y1-y2)**2)
d23 = sqrt((x2-x3)**2+(y2-y3)**2)
d13 = sqrt((x1-x3)**2+(y1-y3)**2)
d14 = sqrt((x1-x4)**2+(y1-y4)**2)
d24 = sqrt((x2-x4)**2+(y2-y4)**2)
d34 = sqrt((x3-x4)**2+(y3-y4)**2)
t = t+dt
return x, t
def initial_points(planets):
x, t = planets[0], planets[1]
line.set_data(t, x)
ctr = Sun.center
ax.set_xlim(ctr[0]-5e12, ctr[0]+5e12)
ax.set_ylim(ctr[1]-5e12, ctr[1]+5e12)
return line
fig = plt.figure()
ax = plt.axes(xlim=(-5e12, 5e12), ylim=(-5e12, 5e12))
ax.set_aspect("equal")
line, = ax.plot([], [], '', ms=10)
Sun = Circle((0,0), r1, fc='yellow')
ax.add_artist(Sun)
Mercury = Circle((0 ,0), r2, fc='brown')
ax.add_artist(Mercury)
Venus = Circle(( 0,0), r3, fc='green')
ax.add_artist(Venus)
Earth = Circle((0,0), r4, fc='red')
ax.add_artist(Earth)
ani = FuncAnimation(fig, initial_points, planets, blit=False,\
interval=10, repeat=True)
plt.show()

Categories