robolib.systems.render_system

render_system.py - The main (3D cameras) render system used by the simulator and other tools (e.g. map editor)

 1"""render_system.py - The main (3D cameras) render system used by the simulator and other tools (e.g. map editor)"""
 2from typing import Callable
 3import raylib as rl
 4
 5from microecs import World, EntityId
 6
 7from robolib.constants import DEFAULT_BACKGROUND
 8from robolib.traits import Drawable
 9from robolib.components import HasFPV, HasModel, HasPose, HasCollision, ColliderKinds, GroundFloor
10from robolib.camera import Camera
11
12class RenderSystem:
13    """Only the main 3D render camera(s). For FPV rendering on a texture, use FPVRenderSystem."""
14    def __call__(self, world: World, camera: Camera, extra_drawables: list[Drawable] | None = None,
15                 camera_entity_id: EntityId | None = None, wireframe_mode: bool = False,
16                 collision_mode: bool = False, display_uav_trace: bool = False, uav_traces: dict | None = None,
17                 display_hud: bool = False, extra_callables: list[Callable] | None = None):
18        rl.ClearBackground(DEFAULT_BACKGROUND)
19
20        rl.BeginMode3D(camera.camera[0])
21
22        if wireframe_mode:
23            rl.rlEnableWireMode()
24
25        if collision_mode:
26            qr = world.query(HasModel, HasPose, exclude=[HasCollision])
27            for model, pose, scale in zip(qr.model, qr.pose, qr.scale):
28                rl.DrawModel(model.item().model, pose[0:3, 3].tolist(), scale.item(), rl.WHITE)
29
30            qr = world.query(HasModel, HasPose, GroundFloor)
31            for model, pose, scale in zip(qr.model, qr.pose, qr.scale):
32                rl.DrawModel(model.item().model, pose[0:3, 3].tolist(), scale.item(), rl.WHITE)
33
34            qr = world.query(HasModel, HasPose, HasCollision, exclude=[GroundFloor])
35            collider_size = qr.collider_bbox[:, 1] - qr.collider_bbox[:, 0]
36            for pose, kind, radius, size, colliding in zip(qr.pose, qr.collider_kind, qr.collider_radii,
37                                                           collider_size, qr.is_colliding):
38                color = rl.RED if colliding else rl.GREEN
39                if kind == ColliderKinds.SPHERE:
40                    rl.DrawSphere(pose[0:3, 3].tolist(), radius.item(), color)
41                else: # AABB
42                    rl.DrawCube(pose[0:3, 3].tolist(), *size.tolist(), color)
43
44        else:
45            qr = world.query(HasModel, HasPose)
46            for i, (model, pose, scale) in enumerate(zip(qr.model, qr.pose, qr.scale)):
47                if camera_entity_id is not None and qr.entity_ids[i] == camera_entity_id: # don't draw yourself in FPV
48                    continue
49                rl.DrawModel(model.item().model, pose[0:3, 3].tolist(), scale.item(), rl.WHITE)
50
51        for drawable in (extra_drawables or []): # e.g. plugins
52            drawable.draw(world=world, entity_id=camera_entity_id)
53        for callable_fn in (extra_callables or []):
54            callable_fn(world=world)
55
56        if display_uav_trace:
57            assert uav_traces is not None, uav_traces
58            for traces in uav_traces.values():
59                for trace in traces.keys():
60                    rl.DrawSphere(trace, 0.05, rl.GREEN)
61
62        rl.EndMode3D()
63
64        if wireframe_mode:
65            rl.rlDisableWireMode()
66
67        if display_hud:
68            n_robots = len(world.query(HasFPV))
69            msg = f"{camera.label}\nObjects: {len(world)} (robots: {n_robots})"
70            rl.DrawText(msg.encode(), 10, 10, 20, rl.DARKGRAY)
71            rl.DrawFPS(rl.GetScreenWidth() - 80, 10)
class RenderSystem:
13class RenderSystem:
14    """Only the main 3D render camera(s). For FPV rendering on a texture, use FPVRenderSystem."""
15    def __call__(self, world: World, camera: Camera, extra_drawables: list[Drawable] | None = None,
16                 camera_entity_id: EntityId | None = None, wireframe_mode: bool = False,
17                 collision_mode: bool = False, display_uav_trace: bool = False, uav_traces: dict | None = None,
18                 display_hud: bool = False, extra_callables: list[Callable] | None = None):
19        rl.ClearBackground(DEFAULT_BACKGROUND)
20
21        rl.BeginMode3D(camera.camera[0])
22
23        if wireframe_mode:
24            rl.rlEnableWireMode()
25
26        if collision_mode:
27            qr = world.query(HasModel, HasPose, exclude=[HasCollision])
28            for model, pose, scale in zip(qr.model, qr.pose, qr.scale):
29                rl.DrawModel(model.item().model, pose[0:3, 3].tolist(), scale.item(), rl.WHITE)
30
31            qr = world.query(HasModel, HasPose, GroundFloor)
32            for model, pose, scale in zip(qr.model, qr.pose, qr.scale):
33                rl.DrawModel(model.item().model, pose[0:3, 3].tolist(), scale.item(), rl.WHITE)
34
35            qr = world.query(HasModel, HasPose, HasCollision, exclude=[GroundFloor])
36            collider_size = qr.collider_bbox[:, 1] - qr.collider_bbox[:, 0]
37            for pose, kind, radius, size, colliding in zip(qr.pose, qr.collider_kind, qr.collider_radii,
38                                                           collider_size, qr.is_colliding):
39                color = rl.RED if colliding else rl.GREEN
40                if kind == ColliderKinds.SPHERE:
41                    rl.DrawSphere(pose[0:3, 3].tolist(), radius.item(), color)
42                else: # AABB
43                    rl.DrawCube(pose[0:3, 3].tolist(), *size.tolist(), color)
44
45        else:
46            qr = world.query(HasModel, HasPose)
47            for i, (model, pose, scale) in enumerate(zip(qr.model, qr.pose, qr.scale)):
48                if camera_entity_id is not None and qr.entity_ids[i] == camera_entity_id: # don't draw yourself in FPV
49                    continue
50                rl.DrawModel(model.item().model, pose[0:3, 3].tolist(), scale.item(), rl.WHITE)
51
52        for drawable in (extra_drawables or []): # e.g. plugins
53            drawable.draw(world=world, entity_id=camera_entity_id)
54        for callable_fn in (extra_callables or []):
55            callable_fn(world=world)
56
57        if display_uav_trace:
58            assert uav_traces is not None, uav_traces
59            for traces in uav_traces.values():
60                for trace in traces.keys():
61                    rl.DrawSphere(trace, 0.05, rl.GREEN)
62
63        rl.EndMode3D()
64
65        if wireframe_mode:
66            rl.rlDisableWireMode()
67
68        if display_hud:
69            n_robots = len(world.query(HasFPV))
70            msg = f"{camera.label}\nObjects: {len(world)} (robots: {n_robots})"
71            rl.DrawText(msg.encode(), 10, 10, 20, rl.DARKGRAY)
72            rl.DrawFPS(rl.GetScreenWidth() - 80, 10)

Only the main 3D render camera(s). For FPV rendering on a texture, use FPVRenderSystem.