Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
usd-core
usd-core
compas >= 2.0
22 changes: 22 additions & 0 deletions scripts/scene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import compas
from compas.scene import Scene
from compas.geometry import Box, Sphere, Translation
from compas.datastructures import Mesh
from compas_usd.conversions import stage_from_scene

scene = Scene()
group1 = scene.add_group(name="Boxes")
group2 = scene.add_group(name="Spheres", transformation=Translation.from_vector([0, 5, 0]))

mesh = Mesh.from_obj(compas.get("tubemesh.obj"))
mesh.flip_cycles()
scene.add(mesh, name="MeshObj", transformation=Translation.from_vector([-5, 0, 0]))

for i in range(5):
group1.add(Box(0.5), name=f"Box{i}", transformation=Translation.from_vector([i, 0, 0]))
group2.add(Sphere(0.5), name=f"Sphere{i}", transformation=Translation.from_vector([i, 0, 0]))

print(scene)

stage = stage_from_scene(scene, "temp/scene.usda")
print(stage)
2 changes: 2 additions & 0 deletions src/compas_usd/conversions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
apply_rotate_and_translate_on_prim,
frame_and_scale_from_prim,
)
from .scene import stage_from_scene

__all__ = [
"prim_from_box",
Expand All @@ -36,4 +37,5 @@
"apply_transformation_on_prim",
"apply_rotate_and_translate_on_prim",
"frame_and_scale_from_prim",
"stage_from_scene",
]
4 changes: 2 additions & 2 deletions src/compas_usd/conversions/geometry.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pxr import UsdGeom
from compas.geometry import Frame
from compas.geometry import Box
from compas.utilities import flatten
from compas.itertools import flatten
from compas.geometry import transpose_matrix

from .transformations import apply_rotate_and_translate_on_prim
Expand Down Expand Up @@ -76,7 +76,7 @@ def prim_from_sphere(stage, path, sphere):
"""
prim = UsdGeom.Sphere.Define(stage, path)
prim.GetPrim().GetAttribute("radius").Set(sphere.radius)
UsdGeom.XformCommonAPI(prim).SetTranslate(tuple(sphere.point))
UsdGeom.XformCommonAPI(prim).SetTranslate(tuple(sphere.frame.point))
return prim


Expand Down
102 changes: 102 additions & 0 deletions src/compas_usd/conversions/scene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from compas.scene import Scene
from compas.scene import SceneObject
from compas.data import Data
from compas.geometry import Box
from compas.geometry import Sphere
from compas.geometry import Transformation
from compas.datastructures import Mesh
from compas_usd.conversions import prim_from_transformation
from compas_usd.conversions import prim_from_box
from compas_usd.conversions import prim_from_sphere
from compas_usd.conversions import prim_from_mesh

from pxr import Usd, UsdGeom


def stage_from_scene(scene: Scene, file_path: str) -> Usd.Stage:
"""
Converts a :class:`compas.scene.Scene` to a USD stage.

Parameters
----------
scene : :class:`compas.scene.Scene`
The scene to convert.
file_path : str
The file path to the USD stage.

Returns
-------
:class:`pxr.Usd.Stage`
The USD stage.
"""
stage = Usd.Stage.CreateNew(file_path)
UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.z)
for obj in scene.root.children:
prim_from_sceneobject(stage, obj, parent_path=[scene.name])

stage.Save()
return stage


def prim_from_sceneobject(stage: Usd.Stage, sceneobject: SceneObject, parent_path=[]) -> Usd.Prim:
"""
Converts a :class:`compas.scene.SceneObject` to a USD prim.

Parameters
----------
stage : :class:`pxr.Usd.Stage`
The USD stage.
sceneobject : :class:`compas.scene.SceneObject`
The scene object to convert.
parent_path : list[str], optional
The path to the parent prim.

Returns
-------
:class:`pxr.Usd.Prim`
The USD prim.
"""
path = parent_path + [f"{sceneobject.name}"]

transformation = (
sceneobject.transformation
if sceneobject.transformation is not None
else Transformation()
)
Comment on lines +61 to +65
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bit convoluted syntax, why not plain:

Suggested change
transformation = (
sceneobject.transformation
if sceneobject.transformation is not None
else Transformation()
)
transformation = sceneobject.transformation
if transformation is None:
transformation = Transformation()


prim = prim_from_transformation(stage, "/" + "/".join(path), transformation)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this path concat using / work on Windows also?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we not use pathlib or at least os.path for this?

if sceneobject.item is not None:
prim_from_item(stage, sceneobject.item, parent_path=path)

for child in sceneobject.children:
prim_from_sceneobject(stage, child, parent_path=path)

return prim


def prim_from_item(stage: Usd.Stage, item: Data, parent_path=[]) -> Usd.Prim:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't use [] empty list as default arg value, this has nasty consequences.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parent_path = parent_path or []

"""
Converts a :class:`compas.scene.SceneObject` to a USD prim.

Parameters
----------
stage : :class:`pxr.Usd.Stage`
The USD stage.
item : :class:`compas.scene.SceneObject`
The item to convert.
parent_path : list[str], optional
The path to the parent prim.

Returns
-------
:class:`pxr.Usd.Prim`
The USD prim.
"""
path = parent_path + [f"{item.name}"]
if isinstance(item, Box):
prim = prim_from_box(stage, "/" + "/".join(path), item)
elif isinstance(item, Sphere):
prim = prim_from_sphere(stage, "/" + "/".join(path), item)
elif isinstance(item, Mesh):
prim = prim_from_mesh(stage, "/" + "/".join(path), item)
Comment on lines +96 to +101
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question about whether these paths using the unix slash work on Windows.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment about using pathlib

return prim