51 lines
1.3 KiB
Python
51 lines
1.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Checks the relative frame used by Sable's OBB collision.
|
|
|
|
Sable gives a ship block OBB the SubLevel pose q_ship and gives the custom player
|
|
OBB q_entity. For an upright player relative to the logical deck, q_entity must be
|
|
q_ship, so inverse(q_ship) * q_entity is identity.
|
|
"""
|
|
import math
|
|
|
|
|
|
def qx(deg):
|
|
a = math.radians(deg) / 2.0
|
|
return (math.cos(a), math.sin(a), 0.0, 0.0) # w,x,y,z
|
|
|
|
|
|
def conj(q):
|
|
w,x,y,z=q
|
|
return (w,-x,-y,-z)
|
|
|
|
|
|
def mul(a,b):
|
|
aw,ax,ay,az=a; bw,bx,by,bz=b
|
|
return (
|
|
aw*bw-ax*bx-ay*by-az*bz,
|
|
aw*bx+ax*bw+ay*bz-az*by,
|
|
aw*by-ax*bz+ay*bw+az*bx,
|
|
aw*bz+ax*by-ay*bx+az*bw,
|
|
)
|
|
|
|
|
|
def rotate(q,v):
|
|
p=(0.0,*v)
|
|
r=mul(mul(q,p),conj(q))
|
|
return r[1:]
|
|
|
|
|
|
def close(a,b,eps=1e-9):
|
|
return all(abs(x-y)<eps for x,y in zip(a,b))
|
|
|
|
for deg in (0,20,90,180):
|
|
ship=qx(deg)
|
|
entity=ship
|
|
relative=mul(conj(ship),entity)
|
|
world_up=rotate(entity,(0.0,1.0,0.0))
|
|
world_gravity=rotate(ship,(0.0,-1.0,0.0))
|
|
assert close(relative,(1.0,0.0,0.0,0.0)) or close(relative,(-1.0,0.0,0.0,0.0))
|
|
assert abs(sum(a*b for a,b in zip(world_up,world_gravity))+1.0)<1e-9
|
|
print(f"X {deg:3d}: relative={relative}, up={world_up}, gravity={world_gravity}")
|
|
|
|
print("OK: player OBB stays upright relative to the logical deck at 0/20/90/180 degrees")
|