Nekochu commited on
Commit
1f2ad82
·
verified ·
1 Parent(s): 72ad628

Fix ZYX order for BVH format

Browse files
Files changed (1) hide show
  1. app_new.py +14 -14
app_new.py CHANGED
@@ -233,21 +233,21 @@ def _quat_from_two_vectors(v1, v2):
233
  q = np.array([w, cross[0], cross[1], cross[2]])
234
  return q / (np.linalg.norm(q) + 1e-10)
235
 
236
- def _quat_to_euler(q):
237
- """Quaternion to Euler XYZ (degrees)."""
238
  w, x, y, z = q
239
- # Roll (X)
240
- sinr = 2 * (w * x + y * z)
241
- cosr = 1 - 2 * (x * x + y * y)
242
- rx = np.arctan2(sinr, cosr)
243
- # Pitch (Y)
244
- sinp = 2 * (w * y - z * x)
245
- ry = np.arcsin(np.clip(sinp, -1, 1))
246
- # Yaw (Z)
247
  siny = 2 * (w * z + x * y)
248
  cosy = 1 - 2 * (y * y + z * z)
249
  rz = np.arctan2(siny, cosy)
250
- return np.degrees([rx, ry, rz])
 
 
 
 
 
 
 
251
 
252
  def joints_to_bvh(joints, output_path, fps=20):
253
  """Convert joint positions to BVH with proper local rotations."""
@@ -298,9 +298,9 @@ def joints_to_bvh(joints, output_path, fps=20):
298
  local_rot = global_rot
299
 
300
  global_quats[j] = global_rot
301
- all_rotations[frame, j] = _quat_to_euler(local_rot)
302
 
303
- # Write BVH
304
  with open(output_path, "w") as f:
305
  f.write("HIERARCHY\n")
306
  def write_joint(idx, indent):
@@ -308,7 +308,7 @@ def joints_to_bvh(joints, output_path, fps=20):
308
  pre = " " * indent
309
  f.write(f"{'ROOT' if idx==0 else pre+'JOINT'} {name}\n{pre}{{\n")
310
  f.write(f"{pre} OFFSET {off[0]:.6f} {off[1]:.6f} {off[2]:.6f}\n")
311
- f.write(f"{pre} CHANNELS {'6 Xposition Yposition Zposition ' if idx==0 else '3 '}Xrotation Yrotation Zrotation\n")
312
  if children[idx]:
313
  for c in children[idx]: write_joint(c, indent + 1)
314
  else:
 
233
  q = np.array([w, cross[0], cross[1], cross[2]])
234
  return q / (np.linalg.norm(q) + 1e-10)
235
 
236
+ def _quat_to_euler_zyx(q):
237
+ """Quaternion to Euler ZYX order (degrees) - standard BVH format."""
238
  w, x, y, z = q
239
+ # Z rotation (yaw)
 
 
 
 
 
 
 
240
  siny = 2 * (w * z + x * y)
241
  cosy = 1 - 2 * (y * y + z * z)
242
  rz = np.arctan2(siny, cosy)
243
+ # Y rotation (pitch)
244
+ sinp = 2 * (w * y - z * x)
245
+ ry = np.arcsin(np.clip(sinp, -1, 1))
246
+ # X rotation (roll)
247
+ sinr = 2 * (w * x + y * z)
248
+ cosr = 1 - 2 * (x * x + y * y)
249
+ rx = np.arctan2(sinr, cosr)
250
+ return np.degrees([rz, ry, rx]) # ZYX order for BVH
251
 
252
  def joints_to_bvh(joints, output_path, fps=20):
253
  """Convert joint positions to BVH with proper local rotations."""
 
298
  local_rot = global_rot
299
 
300
  global_quats[j] = global_rot
301
+ all_rotations[frame, j] = _quat_to_euler_zyx(local_rot)
302
 
303
+ # Write BVH (ZYX rotation order - standard for BVH)
304
  with open(output_path, "w") as f:
305
  f.write("HIERARCHY\n")
306
  def write_joint(idx, indent):
 
308
  pre = " " * indent
309
  f.write(f"{'ROOT' if idx==0 else pre+'JOINT'} {name}\n{pre}{{\n")
310
  f.write(f"{pre} OFFSET {off[0]:.6f} {off[1]:.6f} {off[2]:.6f}\n")
311
+ f.write(f"{pre} CHANNELS {'6 Xposition Yposition Zposition ' if idx==0 else '3 '}Zrotation Yrotation Xrotation\n")
312
  if children[idx]:
313
  for c in children[idx]: write_joint(c, indent + 1)
314
  else: