I have a .glb
glTF file that specifies a character.
The character has 75 nodes, and no animation track.
I wrote the following code to render the character, and now I would like to apply some rotation to specific nodes before I render it.
My rendering code is:
import math
import pyrender
import numpy as np
from PIL import Image
import trimesh
def rotation_x(angle_degrees):
angle = angle_degrees * math.pi / 180
return np.array([
[1, 0, 0, 0],
[0, math.cos(angle), -math.sin(angle), 0],
[0, math.sin(angle), math.cos(angle), 0],
[0, 0, 0, 1],
])
class Renderer:
def __init__(self, character_path: str):
self.mesh = trimesh.load(character_path)
# Just trying some random rotations
self.rotate("mixamorig:LeftUpLeg", np.array([0.707, 1.0, 0.0, 0.707]))
self.rotate("mixamorig:RightHand", np.array([0.707, 5.0, 0.0, 0.707]))
self.rotate("mixamorig:LeftHand", np.array([0.707, 2.0, 0.0, 0.707]))
self.rotate("mixamorig:Spine", np.array([1.707, 2.0, 0.0, 0.707]))
self.scene = self.make_scene()
self.renderer = pyrender.OffscreenRenderer(viewport_width=1024, viewport_height=1024)
def rotate(self, node_name: str, quaternion: np.ndarray):
raise NotImplementedError()
def make_scene(self):
# Create a pyrender scene
scene = pyrender.Scene()
# Add the mesh to the scene
for geometry in self.mesh.geometry.values():
node = pyrender.Mesh.from_trimesh(geometry, smooth=True)
scene.add(node)
# Set up a camera with an orthographic projection
camera = pyrender.PerspectiveCamera(yfov=float(np.radians(54)), aspectRatio=1)
camera_pose = np.array([
[1, 0, 0, 0],
[0, 1, 0, 3.5], # Move the camera 1 meter up in the y-axis
[0, 0, 1, 4],
[0, 0, 0, 1],
]) @ rotation_x(-20)
scene.add(camera, pose=camera_pose)
# Set up a directional light
light = pyrender.DirectionalLight(color=np.ones(3), intensity=3.0)
light_pose = np.array([
[1, 0, 0, 0],
[0, 1, 0, 5],
[0, 0, 1, 3],
[0, 0, 0, 1],
])
scene.add(light, pose=light_pose)
return scene
def __call__(self):
color, depth = self.renderer.render(self.scene)
return color, depth
I have tried many solutions, but to no avail. This solution returns no errors, but also does not perform the rotation.
def rotate(self, node_name: str, quaternion: np.ndarray):
rotation_matrix = trimesh.transformations.quaternion_matrix(quaternion)
self.mesh.graph[node_name][0].setflags(write=1)
self.mesh.graph[node_name][0][:] = rotation_matrix
How can I control the rotation of a specific node before rendering it?
For testing purposes, the character I am using is: https://firebasestorage.googleapis.com/v0/b/sign-mt-assets/o/3d%2Fcharacter.glb?alt=media