Skip to content

Commit 5fde6d4

Browse files
Merge branch 'main' into feat/documentation
2 parents fd0c892 + afdd564 commit 5fde6d4

21 files changed

+275
-185
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# image files
1+
# rendered files
22
*.png
3+
*.mov
34

45
# Byte-compiled / optimized / DLL files
56
__pycache__/

examples/br2/callbacks.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ def update_states(
142142
)
143143

144144
def set_keyframe(self, keyframe: int) -> None:
145-
self.bending_actuation.set_keyframe(keyframe)
146-
self.rotation_CW_actuation.set_keyframe(keyframe)
147-
self.rotation_CCW_actuation.set_keyframe(keyframe)
145+
self.bending_actuation.update_keyframe(keyframe)
146+
self.rotation_CW_actuation.update_keyframe(keyframe)
147+
self.rotation_CCW_actuation.update_keyframe(keyframe)
148148

149149

150150
class BlenderBR2CallBack(BasicCallBackBaseClass):

examples/camera_movement.py

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,40 @@ def main(
1212
camera_orbiting_radius: float = 1.0,
1313
):
1414

15-
# Create a new scene
15+
# Clear all mesh objects in the new scene
1616
bsr.clear_mesh_objects()
1717

1818
# Set the camera film background to transparent
1919
bsr.camera.set_film_transparent()
2020

21+
# Set the render file path
22+
bsr.camera.set_file_path(filename + "/frame")
23+
24+
# Set resolution
25+
bsr.camera.set_resolution(1920, 1080)
26+
2127
# Set the camera look at location
2228
bsr.camera.look_at = np.array([0.0, 0.0, 0.0])
2329

24-
# Set a frame at the origin
30+
# Set a pose at the origin
2531
_ = Pose(
2632
positions=np.zeros(3),
2733
directors=np.identity(3),
2834
unit_length=0.25,
2935
)
3036

31-
# Set the current frame number
32-
bsr.frame_manager.frame_current = 0
33-
34-
# Set the initial keyframe number
35-
bsr.frame_manager.set_frame_start()
36-
37-
# Set the camera orbiting keyframes
37+
# Set the camera orbiting angles
3838
angles = np.linspace(
3939
0.0, 360.0, int(frame_rate * total_time), endpoint=False
4040
)
41-
for k, angle in enumerate(angles):
41+
42+
# Set the initial frame
43+
frame_start = 0
44+
bsr.frame_manager.frame_start = frame_start
45+
46+
for frame_current, angle in bsr.frame_manager.enumerate(
47+
angles, frame_current_init=frame_start
48+
):
4249

4350
# Set the camera location
4451
bsr.camera.location = np.array(
@@ -49,35 +56,22 @@ def main(
4956
]
5057
)
5158

52-
# Update the keyframe
53-
bsr.camera.set_keyframe(bsr.frame_manager.frame_current)
54-
55-
if k != len(angles) - 1:
56-
# Update the keyframe number
57-
bsr.frame_manager.update()
58-
else:
59-
# Set the final keyframe number
60-
bsr.frame_manager.set_frame_end()
59+
# Set and update the camera in current frame
60+
bsr.camera.update_keyframe(frame_current)
6161

6262
# Set the frame rate
63-
bsr.frame_manager.set_frame_rate(fps=frame_rate)
63+
bsr.frame_manager.frame_rate = frame_rate
6464

6565
# Set the view distance
6666
bsr.set_view_distance(distance=5)
6767

68-
# Deslect all objects
68+
# Deselect all objects
6969
bsr.deselect_all()
7070

7171
# Select the camera object
7272
bsr.camera.select()
7373

74-
# Set the render file path
75-
bsr.camera.set_file_path("render/" + filename)
76-
77-
# set resolution
78-
bsr.camera.set_resolution(1920, 1080)
79-
80-
# render the scene
74+
# Render the scene
8175
bsr.camera.render(
8276
frames=np.arange(
8377
bsr.frame_manager.frame_start, bsr.frame_manager.frame_end + 1
@@ -90,3 +84,7 @@ def main(
9084

9185
if __name__ == "__main__":
9286
main()
87+
print("\n\nTo convert the frames into a video, run the following command:")
88+
print(
89+
r"ffmpeg -threads 8 -r 60 -i camera_movement/frame_%03d.png -b:v 90M -c:v prores -pix_fmt yuva444p10le camera_movement.mov"
90+
)
File renamed without changes.

examples/pose_demo.py

Lines changed: 70 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,87 +6,107 @@
66

77

88
def angle_to_color(angle: float) -> np.ndarray:
9-
# Normalize angle to 0-360 range
9+
"""
10+
Convert angle to RGB color value
11+
12+
Parameters
13+
----------
14+
angle : float
15+
The angle in degrees
16+
17+
Returns
18+
-------
19+
np.ndarray
20+
The RGBA color value
21+
"""
22+
23+
# Reset angle range to 0-360 degrees
1024
angle = angle % 360
1125

1226
# Convert angle to radians
1327
rad = np.radians(angle)
1428

1529
# Calculate RGB values
1630
if angle < 120:
17-
r = np.cos(rad) / 2 + 0.5
18-
g = np.sin(rad) / 2 + 0.5
19-
b = 0
31+
rad = 3 * rad / 2
32+
r = 0.5 + np.sin(rad) / 2
33+
g = 0.5 - np.sin(rad) / 2
34+
b = 0.5 - np.sin(rad) / 2
2035
elif angle < 240:
21-
r = 0
22-
g = np.cos(rad - 2 * np.pi / 3) / 2 + 0.5
23-
b = np.sin(rad - 2 * np.pi / 3) / 2 + 0.5
36+
rad = rad - 2 * np.pi / 3
37+
rad = 3 * rad / 2
38+
r = 0.5 - np.sin(rad) / 2
39+
g = 0.5 + np.sin(rad) / 2
40+
b = 0.5 - np.sin(rad) / 2
2441
else:
25-
r = np.sin(rad - 4 * np.pi / 3) / 2 + 0.5
26-
g = 0
27-
b = np.cos(rad - 4 * np.pi / 3) / 2 + 0.5
42+
rad = rad - 2 * np.pi / 3 * 2
43+
rad = 3 * rad / 2
44+
r = 0.5 - np.sin(rad) / 2
45+
g = 0.5 - np.sin(rad) / 2
46+
b = 0.5 + np.sin(rad) / 2
2847

2948
# Return RGBA numpy array
3049
return np.array([r, g, b, 1.0])
3150

3251

33-
def main(filename: str = "pose_demo5"):
34-
35-
# initial values for frame rate and period
36-
frame_rate = 60
37-
total_time = 5
38-
39-
# calculates total number of frames in the visualization
40-
total_frames = frame_rate * total_time
41-
42-
# clears all mesh objects
52+
def main(
53+
filename: str = "pose_demo",
54+
frame_rate: int = 60,
55+
total_time: float = 5.0,
56+
):
57+
# Clear all mesh objects in the new scene
4358
bsr.clear_mesh_objects()
44-
bsr.frame_manager.set_frame_start()
4559

46-
# intializes pose instance and angle
47-
pose_object = Pose(
48-
positions=np.array([1, 0, 0]), directors=np.eye(3), thickness_ratio=0.1
60+
# Initialize pose instance
61+
pose = Pose(
62+
positions=np.array([1, 0, 0]),
63+
directors=np.eye(3),
64+
thickness_ratio=0.1,
65+
)
66+
67+
# Create an array of angles from 0 to 360 degrees
68+
angles = np.linspace(
69+
0.0, 360.0, int(frame_rate * total_time), endpoint=False
4970
)
50-
theta = 0
5171

52-
# iterates through each frame in total time duration
53-
for frame in range(total_frames):
54-
theta = 2 * np.pi * frame / total_frames
72+
# Set the initial frame
73+
frame_start = 0
74+
bsr.frame_manager.frame_start = frame_start
5575

56-
# defines path of of motion for positions of pose object
57-
new_positions = np.array([np.cos(theta), np.sin(theta), 0])
58-
pose_object.positions = new_positions
76+
for frame_current, angle in bsr.frame_manager.enumerate(
77+
angles, frame_current_init=frame_start
78+
):
79+
# Define path of of motion for positions of pose object
80+
positions = [np.cos(np.radians(angle)), np.sin(np.radians(angle)), 0.0]
5981

60-
# defines directors of pose object
61-
d2 = np.array([-np.sin(theta), np.cos(theta), 0])
62-
d3 = np.array([0, 0, 1])
82+
# Define directors of pose object
83+
d2 = [-np.sin(np.radians(angle)), np.cos(np.radians(angle)), 0.0]
84+
d3 = [0, 0, 1]
6385
d1 = np.cross(d2, d3)
64-
new_directors = np.column_stack((d1, d2, d3))
65-
pose_object.directors = new_directors
66-
67-
# updates positions and directors of pose object at each keyframe
68-
pose_object.update_states(new_positions, new_directors)
86+
directors = np.column_stack((d1, d2, d3))
6987

70-
# converts angle to rgb color value at each frame
71-
color = angle_to_color(np.degrees(theta))
88+
# Update positions and directors of pose object at each keyframe
89+
pose.update_states(
90+
positions=np.array(positions),
91+
directors=directors,
92+
)
7293

73-
# updates pose object's colors
74-
pose_object.update_material(color=color)
94+
# Convert angle to rgb color value at each frame
95+
color = angle_to_color(angle)
7596

76-
# sets and updates keyframes
77-
pose_object.set_keyframe(frame)
78-
bsr.frame_manager.update()
97+
# Update pose object's colors
98+
pose.update_material(color=color)
7999

80-
# Set the final keyframe number
81-
bsr.frame_manager.set_frame_end()
100+
# Set and update the pose in current frame
101+
pose.update_keyframe(frame_current)
82102

83103
# Set the frame rate
84-
bsr.frame_manager.set_frame_rate(fps=frame_rate)
104+
bsr.frame_manager.frame_rate = frame_rate
85105

86106
# Set the view distance
87107
bsr.set_view_distance(distance=5)
88108

89-
# Deslect all objects
109+
# Deselect all objects
90110
bsr.deselect_all()
91111

92112
# Select the camera object

examples/single_rigid_rod_spring_action.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def analytical_solution(t, y0: float, v0: float):
6161
# update the rod
6262
keyframe = int(time_index / simulation_ratio) + 1
6363
rod.update_states(positions=positions, radii=radii)
64-
rod.set_keyframe(keyframe)
64+
rod.update_keyframe(keyframe)
6565

6666
bsr.save("single_rigid_rod_spring_action.blend")
6767

poetry.lock

Lines changed: 15 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/bsr/_camera.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def select(self) -> None:
3939
"""
4040
bpy.context.view_layer.objects.active = self._camera
4141

42-
def set_keyframe(self, keyframe: int) -> None:
42+
def update_keyframe(self, keyframe: int) -> None:
4343
"""
4444
Sets a keyframe at the given frame.
4545

src/bsr/_light.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def location(self, location: np.ndarray) -> None:
4646
"""
4747
self._light.location = location
4848

49-
def set_keyframe(self, keyframe: int) -> None:
49+
def update_keyframe(self, keyframe: int) -> None:
5050
"""
5151
Sets a keyframe at the given frame.
5252

0 commit comments

Comments
 (0)