Fusion-Power-Plant-Framework / bluemira

Bluemira is an integrated inter-disciplinary design tool for future fusion reactors. It incorporates several modules, some of which rely on other codes, to carry out a range of typical conceptual fusion reactor design activities.
https://bluemira.readthedocs.io/
GNU Lesser General Public License v2.1
59 stars 16 forks source link

Improve CAD viewer camera #3236

Open je-cook opened 5 months ago

je-cook commented 5 months ago

Description of issue / requirement to address

Our freecad cad viewer has a slight hack in it that rotates the CAD instead of the camera of the viewer

Proposed solution

The camera can be accessed here: https://github.com/Fusion-Power-Plant-Framework/bluemira/blob/4eb798780bd379a562a5872f710bb4fc18eb0325/bluemira/codes/_freecadapi.py#L2407 with some of the below dump of exploratory code being useful, its half translated from c++ ie the pointers dont work:

    camera = viewer.getSoEventManager().getCamera()
    cam_pos = camera.position.getValue().getValue()

    direction = (0, 0, -1)
    orient = s
    direction *= orient

    focal_point = cam_pos + camera.focalDistance.getValue() * direction

    # rotation_dist = camera.focalDistance.getValue() * coin.SbVec3f(0, 0, 1)
    # new_rot_cen = orient * = rotation_dist
    front_orient = np.sqrt(2) / 2

    orientation = (front_orient, 0, 0, front_orient)
    # // Distance from rotation center to camera position in camera coordinate system
    rotationCenterDistanceCam: SbVec3f = camera.focalDistance.getValue() * SbVec3f(
        0, 0, 1
    )

    # // Set to the given orientation
    camera.orientation = orientation

    # // Distance from rotation center to new camera position in global coordinate system
    newRotationCenterDistance: SbVec3f = camera.orientation.getValue().multVec(
        rotationCenterDistanceCam, newRotationCenterDistance
    )
    # // Reposition camera so the rotation center stays in the same place
    # // Optionally add translation to move to center

    camera.position = focal_point + newRotationCenterDistance

    # vprt = coin.SbViewportRegion()
    # action = coin.SoGetBoundingBoxAction(vprt)
    # root.getBoundingBox(action)
    # action.getBoundingBox().getSize().getValue()

With the above you need to remvoe the rotate=True from the viewer and the rotate argument completely as mentioned in #3235

Alternative solutions

leave as is, it does work.

Additional context

This may lead to us being able to specify the viewing angle say for an autogenerated image in future.

je-cook commented 7 hours ago

Track camera position


def callback(*args):
    cam, sensor = args
    print()
    print("Cam position : {}".format(cam.position.getValue().getValue()))
    print("Cam rotation : {}".format(cam.orientation.getValue().getValue()))

camera = viewer.getSoEventManager().getCamera()
node_sensor = coin.SoNodeSensor(callback, camera)
node_sensor.attach(camera)
je-cook commented 5 hours ago

Fixed in #3304