Esempio n. 1
0
def raylength():
    """
    Objects can only be grabbed if they are hit by the Ray-Sensor called 'Ray'.
    Set the ray's length ,
    so that it hits objects in a certain radius around the human's z-axis
    """
    co = logic.getCurrentController()
    cam = co.owner
    ray = co.sensors['Ray']

    dir = Vector(ray.rayDirection)
    xy = Matrix.OrthoProjection('XY', 3) * dir
    # API Change in 2.59 builds - Vectors are now column vectors

    ray.range = 0.8 / xy.length
def interact(cont):
    """
    Script for opening doors, drawers and grabbing objects
    
    press left mousebutton to open, close or grab
    press right mousebutton to drop the currently selected object
    """

    ow = cont.owner

    # get the suffix of the human to reference the right objects
    suffix = ow.name[-4:] if ow.name[-4] == "." else ""

    right_hand = objects['IK_Target_Empty.R' + suffix]
    look = objects['Target_Empty' + suffix]
    human = objects[ow.parent.parent.parent.name + suffix]

    # if the human is external, do nothing
    if human.get('External_Robot_Tag') or human['disable_keyboard_control']:
        return

    lmb = cont.sensors['LMB']
    ray = cont.sensors['Ray']
    cam = ray.owner
    lay_down_ray = cont.sensors['LayDownRay']
    rmb = cont.sensors['RMB']
    space = cont.sensors['SPACEBAR']
    head = objects['Head_Empty' + suffix]
    hand = objects['Hand.R' + suffix]

    # Get the focusing object:
    # A ray sensor is attached to the HumanCamera sensor.
    # It returns all colliding objects in a 10 cm range of the hand.
    # We filter the result to keep only objects that have the 'Object'
    # property or that have children with the 'Object' property.
    focus = None
    prox_obj = ray.hitObject  # focused object
    if prox_obj:
        if 'Object' in prox_obj:
            focus = prox_obj
        elif 'Door' in prox_obj or 'Drawer' in prox_obj or 'Switch' in prox_obj:
            focus = prox_obj
        else:
            for obj in prox_obj.children:
                if 'Object' in obj:
                    focus = obj

    # set the overlay scene and change the displayed text
    # and texture
    if human['Manipulate'] and focus:

        can_be_manipulated = False

        if focus in passive_objects.graspable_objects():
            can_be_manipulated = True
            if not ow['selected']:
                ow['Status'] = 'Pick up ' + passive_objects.label(focus)
            else:
                ow['Status'] = passive_objects.label(focus)
        elif 'Door' in focus or 'Drawer' in focus:
            can_be_manipulated = True

            try:
                if focus['Open']:
                    ow['Status'] = 'Close ' + str(focus['Description'])
                else:
                    ow['Status'] = 'Open ' + str(focus['Description'])
            except KeyError:
                logger.warning('Key missing in focused Object ' + focus.name +
                               ' --- no description given')
        elif 'Switch' in focus:
            can_be_manipulated = True
            if objects[focus['Switch']]['On']:
                ow['Status'] = "Turn off " + focus['Switch']
            else:
                ow['Status'] = "Turn on " + focus['Switch']
        else:
            ow['Status'] = None
    else:
        ow['Status'] = None

    if human['Manipulate']:
        if not crosshairs in scene.post_draw:
            scene.post_draw.append(crosshairs)
    else:
        if crosshairs in scene.post_draw:
            scene.post_draw.remove(crosshairs)

    if ow['Status']:
        if not write_interaction_status in scene.post_draw:
            scene.post_draw.append(write_interaction_status)
        if not status_image in scene.post_draw:
            scene.post_draw.append(status_image)
    else:
        if write_interaction_status in scene.post_draw:
            scene.post_draw.remove(write_interaction_status)
        if status_image in scene.post_draw:
            scene.post_draw.remove(status_image)

    if space.positive:
        # blocks mouse movement if interactable object is focused
        try:
            if ('Door' in focus or 'Object' in focus
                    or 'Drawer' in focus) and not ow['selected']:

                human['FOCUSED'] = True
                vect = Matrix.OrthoProjection('XY',
                                              3) * human.getVectTo(focus)[1]
                human.alignAxisToVect(vect, 0, 1.0)
                # align the local x axis to point to the focused object
            else:
                human['FOCUSED'] = False
        except TypeError:
            human['FOCUSED'] = False
    else:
        human['FOCUSED'] = False

    try:
        if focus in passive_objects.graspable_objects():
            if lmb.positive and not ow['selected']:
                # set a property - a property-sensor will fire the grab-function
                ow['grabbing'] = focus
        elif 'Door' in focus and lmb.positive:
            open_door(focus)
            # if you decide to use IPOs for the doors,
            # comment the previous line and uncomment the next line
            # the logic can be set with code in morse utils, which is currently
            # commented
            # focus['Open'] = not focus['Open']
        elif 'Drawer' in focus and lmb.positive:
            focus['Open'] = not focus['Open']
        elif 'Switch' in focus and lmb.positive:
            objects[focus['Switch']]['On'] = not objects[focus['Switch']]['On']
    except TypeError:
        pass

    if rmb.positive:  #drop selected Object
        ow['grabbing'] = None
        focused_object = lay_down_ray.hitObject
        if focused_object != None:
            actor_focused = blenderapi.objectdata(
                focused_object.name).game.use_actor
        # accurate placing of objects under certain conditions
        if human['Manipulate'] and lay_down_ray.positive \
           and focused_object != ow['selected'] \
           and actor_focused:
            # check not to lay the object on itself
            if ow['selected']:
                right_hand['LayDown'] = lay_down_ray.hitPosition
                right_hand['LayDownObj'] = focused_object
        # otherwise just drop the object
        else:
            if ow['selected']:
                ow['selected'].removeParent()
                ow['selected'] = None
                right_hand['moveArm'] = True
Esempio n. 3
0
def to_base_vertices(deform_verts: bmesh.types.BMVertSeq, to_world_matrix, target_direction, target_origin, deform_vertex_index_weights: Dict[int, float], base_area_factor: float, project_vertically: bool) -> List[Vector]:
    ortho_projection_matrix = Matrix.OrthoProjection(target_direction, 4)

    f_l = 1
    intrinsic_matrix = Matrix([
        [f_l, 0.0, 0.0, 0.0],
        [0.0, f_l, 0.0, 0.0],
        [0.0, 0.0, f_l, 0.0],
        [0.0, 0.0, 0.0, 1.0]
    ])

    wide_projection_matrix: Matrix = intrinsic_matrix @ ortho_projection_matrix @ Matrix.Translation(-target_origin)

    wide_project_2d_vertices: Set[Tuple[float, float]] = set()
    wide_project_3d_vertices: List[Vector] = []

    deform_verts.ensure_lookup_table()
    for deform_vertex_index, deform_vertex_weight in deform_vertex_index_weights.items():
        wide_project_3d_vertex = wide_projection_matrix @ (to_world_matrix @ deform_verts[deform_vertex_index].co)
        wide_project_2d_vertex = wide_project_3d_vertex / wide_project_3d_vertex[2]

        wide_project_2d_vertices.add(wide_project_2d_vertex[0:2])
        wide_project_3d_vertices.append(wide_project_3d_vertex * (deform_vertex_weight**base_area_factor))

    box_fit_angle: float = mathutils.geometry.box_fit_2d(list(wide_project_2d_vertices))
    rotate_matrix: Matrix = Matrix.Rotation(+box_fit_angle, 4, target_direction) @ ortho_projection_matrix

    x_min = float('+inf')
    x_max = float('-inf')
    z_min = float('+inf')
    z_max = float('-inf')

    for vertex in wide_project_3d_vertices:
        rotate_vertex: Vector = rotate_matrix @ vertex

        if x_min > rotate_vertex.x:
            x_min = rotate_vertex.x

        if x_max < rotate_vertex.x:
            x_max = rotate_vertex.x

        if z_min > rotate_vertex.z:
            z_min = rotate_vertex.z

        if z_max < rotate_vertex.z:
            z_max = rotate_vertex.z

    rotate_matrix_invert: Matrix
    if project_vertically:
        front_vector = Vector([0, -1, 0])
        rotate_matrix_invert = Matrix.Rotation(-box_fit_angle, 4, front_vector) @ Matrix.OrthoProjection(front_vector, 4)
    else:
        rotate_matrix_invert = Matrix.Rotation(-box_fit_angle, 4, target_direction) @ ortho_projection_matrix

    base_vertices: List[Vector] = [
        rotate_matrix_invert @ Vector([x_min, 0, 0]),
        rotate_matrix_invert @ Vector([0, 0, z_min]),
        rotate_matrix_invert @ Vector([x_max, 0, 0]),
        rotate_matrix_invert @ Vector([0, 0, z_max]),
    ]

    return base_vertices