やりたいこと
obj形式の3DモデルをGenesisで読み込んだときに、色情報が無くなって単色になってしまうときがあります。原因は同じobj拡張子でもmtlで色情報を持っているケースと、obj形式単体で色情報を持っているケースがあるからです。前者の場合は、Genesisでも色つきで描画されます。obj単体で色情報を持っているときは、頂点のデータxyzに続いて色情報が記述されているパターンです。
Blender等でExportしたときのobjフォーマットの例。v の行に三つしか値がありません。色の情報は、mtlファイルやそこから読まれるjpgが持っています。
# Blender 4.0.0
# www.blender.org
mtllib tripo_convert_a16ad3f8-f069-47d9-aa04-a853c62a7acd.mtl
o tripo_node_a16ad3f8-f069-47d9-aa04-a853c62a7acd
v -0.403771 -0.423104 -0.470257
v -0.403649 -0.422189 0.471268
v -0.403649 -0.420602 -0.472393
obj単体で色情報をもっているのは中身がこういうケース。vの所にxyzと恐らくrgbが入っています。このフォーマットの時、Genesisは色つきで表示できません。
# https://github.com/mikedh/trimesh
v -0.24586487 0.41282356 0.24905878 0.30196078 0.29019608 0.28627451
v -0.24905884 0.41282356 0.25203604 0.30588235 0.30980392 0.30588235
v -0.24905884 0.40883124 0.24905878 0.30196078 0.29019608 0.28235294
Simlutionの結果だけを表示するなら、それぞれのオブジェクトの位置を取得して別のレンダラーで表示すれば良いんじゃと思ってやってみました。
Genesisの実行
Genesisのソースコード
import os
import genesis as gs
import json
gs.init(backend=gs.gpu)
scene = gs.Scene(
viewer_options=gs.options.ViewerOptions(
camera_pos=(3, -1, 2.0),
camera_lookat=(0.0, 0.0, 0.5),
camera_fov=30,
max_FPS=60,
),
sim_options=gs.options.SimOptions(
dt=0.001,
),
show_viewer=True,
rigid_options=gs.options.RigidOptions(
box_box_detection=True,
),
)
plane = scene.add_entity(
gs.morphs.Plane(),
)
tresure_box_obj_path = 'D:/home/myproj/genesis/UR5/asset/work/tresure_box.obj'
pot_obj_path = 'D:/home/myproj/genesis/UR5/asset/work/pot.obj'
hamburger_obj_path = 'D:/home/myproj/genesis/UR5/asset/work/hamburger.obj'
tresure_scale = 0.5
pot_scale = 0.5
hamburger_scale = 0.5
tresure_box = scene.add_entity(
morph=gs.morphs.Mesh(
file=tresure_box_obj_path,
scale=tresure_scale,
pos=(0.55, -0.01, 0.18),
euler=(1.57, 0.0, 0.0),
convexify = True,
),
)
pot = scene.add_entity(
morph=gs.morphs.Mesh(
file=pot_obj_path,
scale=pot_scale,
pos=(0.55, -0.40, 0.2),
euler=(0, 1.57, 0.0),
convexify = True,
),
)
hamburger = scene.add_entity(
morph=gs.morphs.Mesh(
file=hamburger_obj_path,
scale=hamburger_scale,
pos=(0.55, 0.0, 0.40),
convexify = True,
),
)
scene.build()
for i in range(500):
scene.step()
input()
tresure_box_pose = list(map(float, tresure_box.get_pos()))
pot_pose = list(map(float, pot.get_pos()))
hamburger_pos = list(map(float, hamburger.get_pos()))
tresure_box_quat = list(map(float, tresure_box.get_quat()))
pot_quat = list(map(float, pot.get_quat()))
hamburger_quat = list(map(float, hamburger.get_quat()))
json_file_path = 'D:/home/myproj/genesis/UR5/asset/work/pose.json'
pose_dict = {
'objects':
[ {
'object': 'tresure_box',
'position': tresure_box_pose,
'quaternion': tresure_box_quat,
'scale': tresure_scale,
},
{
'object': 'pot',
'position': pot_pose,
'quaternion': pot_quat,
'scale': pot_scale,
},
{
'object': 'hamburger',
'position': hamburger_pos,
'quaternion': hamburger_quat,
'scale': hamburger_scale,
}]
}
with open(json_file_path, 'w') as f:
json.dump(pose_dict, f, indent=4)
普通にobjファイルを読み込んでシミュレーションした後に、get_pos, get_quatを使ってその物体の姿勢を取り出します。次のプログラムで読み出すために、json等にしてファイルに書き出します。
最後はこんな表示です。色がないですね。

open3dでの描画
Open3d側では、ファイルから情報を読み込んで表示するだけ
import json
import open3d as o3d
import numpy as np
from scipy.spatial.transform import Rotation as R
def apply_pose(mesh, pos, quat):
r = R.from_quat([quat[1], quat[2], quat[3], quat[0]])
transform = np.eye(4)
transform[:3, :3] = r.as_matrix()
transform[:3, 3] = pos
mesh.transform(transform)
def main():
with open("d:/home/myproj/genesis/UR5/asset/work/pose.json", "r") as f:
objs = json.load(f)
meshes = []
for obj in objs["objects"]:
name = obj["object"]
pos = obj["position"]
quat = obj["quaternion"]
scale = obj["scale"]
mesh = o3d.io.read_triangle_mesh(f"d:/home/myproj/genesis/UR5/asset/work/{name}.obj")
mesh.scale(scale, center=mesh.get_center())
apply_pose(mesh, pos, quat)
meshes.append(mesh)
o3d.visualization.draw_geometries(meshes)
if __name__ == "__main__":
main()
結果はこうなります。カメラの位置を合わせてないので表示が一致しませんが、色つきでそれぞれの位置関係はあってそうです。
