Esempio n. 1
0
def deriveCollision(obj):
    """This function derives the collision information from an object.

    :param obj: The blender object to derive the collision information from.
    :type obj: bpy_types.Object
    :return: dict
    """
    try:
        collision = initObjectProperties(obj,
                                         phobostype='collision',
                                         ignoretypes='geometry')
        collision['geometry'] = deriveGeometry(obj)
        collision['pose'] = deriveObjectPose(obj)
        # the bitmask is cut to length = 16 and reverted for int parsing
        try:
            collision['bitmask'] = int(
                ''.join([
                    '1' if group else '0'
                    for group in obj.rigid_body.collision_groups[:16]
                ])[::-1], 2)
            for group in obj.rigid_body.collision_groups[16:]:
                if group:
                    log((
                        'Object {0} is on a collision layer higher than ' +
                        '16. These layers are ignored when exporting.').format(
                            obj.name), "WARNING")
                    break
        except AttributeError:
            pass
    except KeyError:
        log("Missing data in collision object " + obj.name, "ERROR")
        return None
    return collision
Esempio n. 2
0
def deriveCollision(obj):
    """This function derives the collision information from an object.

    :param obj: The blender object to derive the collision information from.
    :type obj: bpy_types.Object
    :return: dict

    """
    try:
        collision = initObjectProperties(obj,
                                         phobostype='collision',
                                         ignoretypes='geometry')
        collision['geometry'] = deriveGeometry(obj)
        collision['pose'] = deriveObjectPose(obj)
        # the bitmask is cut to length = 16 and reverted for int parsing
        try:
            collision['bitmask'] = int(
                ''.join([
                    '1' if group else '0'
                    for group in obj.rigid_body.collision_groups[:16]
                ])[::-1], 2)
        except AttributeError:
            pass
    except KeyError:
        log("Missing data in collision object " + obj.name, "ERROR",
            "deriveCollision")
        return None
    return collision
Esempio n. 3
0
def deriveVisual(obj):
    """This function derives the visual information from an object.

    :param obj: The blender object to derive the visuals from.
    :type obj: bpy_types.Object
    :return: dict
    """
    try:
        visual = initObjectProperties(obj,
                                      phobostype='visual',
                                      ignoretypes='geometry')
        visual['geometry'] = deriveGeometry(obj)
        visual['pose'] = deriveObjectPose(obj)
        if obj.lod_levels:
            if 'lodmaxdistances' in obj:
                maxdlist = obj['lodmaxdistances']
            else:
                maxdlist = [
                    obj.lod_levels[i + 1].distance
                    for i in range(len(obj.lod_levels) - 1)
                ] + [100.0]
            lodlist = []
            for i in range(len(obj.lod_levels)):
                filename = obj.lod_levels[
                    i].object.data.name + ioUtils.getOutputMeshtype()
                lodlist.append({
                    'start': obj.lod_levels[i].distance,
                    'end': maxdlist[i],
                    'filename': os.path.join('meshes', filename)
                })
            visual['lod'] = lodlist
    except KeyError:
        log("Missing data in visual object " + obj.name, "ERROR")
        return None
    return visual
Esempio n. 4
0
def deriveCollision(obj):
    """Returns the collision information from the specified object.

    Args:
      obj(bpy.types.Object): object to derive the collision information from

    Returns:
      : dict -- phobos representation of the collision object

    """
    collision = initObjectProperties(obj, phobostype='collision', ignoretypes='geometry')
    collision['geometry'] = deriveGeometry(obj)
    collision['pose'] = deriveObjectPose(obj)

    # the bitmask is cut to length = 16 and reverted for int parsing
    if 'collision_groups' in dir(obj.rigid_body):
        collision['bitmask'] = int(
            ''.join(['1' if group else '0' for group in obj.rigid_body.collision_groups[:16]])[
                ::-1
            ],
            2,
        )
        for group in obj.rigid_body.collision_groups[16:]:
            if group:
                log(
                    (
                        "Object {0} is on a collision layer higher than 16. These layers are "
                        + "ignored when exporting."
                    ).format(obj.name),
                    'WARNING',
                )
                break
    return collision
Esempio n. 5
0
def createHelperInertialObjects(link, autocalc=True):
    """Creates inertial representations for helper inertials from the visual/
    collision objects of a link. The new inertials can be calculated
    automatically or remain empty (based on the autocalc parameter)

    :param link: the link which contains the visual/collision objects
    :type link: bpy_types.Object
    :param autocalc: If set to False the new inertial object will contain no
    inertia information.
    :type autocalc: bool
    """
    viscols = getInertiaRelevantObjects(link)
    for obj in viscols:
        inertialdata = {
            'mass': 0,
            'inertia': [0, 0, 0, 0, 0, 0],
            'pose': {
                'translation': obj.matrix_local.to_translation()
            }
        }
        if autocalc:
            mass = obj['mass'] if 'mass' in obj else None
            geometry = deriveGeometry(obj)
            data = geometry if geometry['type'] != 'mesh' else obj.data
            if mass is not None and data is not None:
                inert = calculateInertia(mass, data)
                if inert is not None:
                    inertialdata['mass'] = mass
                    inertialdata['inertia'] = inert
        createInertial(obj.name, inertialdata, parentobj=obj, helper=True)
Esempio n. 6
0
def deriveEntity(primitive, outpath):
    """This function handles a primitive entity in a scene to export it
    
    # TODO is this even a heightmap?

    Args:
      smurf(bpy.types.Object): The heightmap root object.
      outpath(str): The path to export to. Not used for primitives
      savetosubfolder(bool): If True data will be exported into subfolders. Not used for primitives
      primitive: 

    Returns:
      dict - An entry for the scenes entitiesList

    """
    entity = models.initObjectProperties(primitive, 'entity', ['geometry'])
    pose = deriveObjectPose(primitive)
    entity['geometry'] = deriveGeometry(primitive)
    entity['position'] = {'x': pose['translation'][0],
                          'y': pose['translation'][1],
                          'z': pose['translation'][2]}
    entity['rotation'] = {'w': pose['rotation_quaternion'][0],
                          'x': pose['rotation_quaternion'][1],
                          'y': pose['rotation_quaternion'][2],
                          'z': pose['rotation_quaternion'][3]}
    if 'radius' in entity['geometry']:
        entity['radius'] = entity['geometry']['radius']
    #entity['extend'] = {'x': entity['geometry']['size'][0],
    #                    'y': entity['geometry']['size'][1],
    #                    'z': entity['geometry']['size'][2]}
    entity['extend'] = {'x': primitive.dimensions[0],
                        'y': primitive.dimensions[1],
                        'z': primitive.dimensions[2]}
    return entity
Esempio n. 7
0
def calculateInertia(obj, mass, geometry=None):
    """Calculates the inertia of an object using the specified mass and
       optionally geometry.

    Args:
        obj(bpy.types.Object): object to calculate inertia from
        mass(float): mass of object
        geometry(dict, optional): geometry part of the object dictionary

    Returns(tuple):
        tuple(6) of upper diagonal of the inertia 3x3 tensor
    """
    inertia = None
    if not geometry:
        geometry = deriveGeometry(obj)
        if not geometry:
            return None
    if geometry['type'] == 'box':
        inertia = calculateBoxInertia(mass, geometry['size'])
    elif geometry['type'] == 'cylinder':
        inertia = calculateCylinderInertia(mass, geometry['radius'], geometry['length'])
    elif geometry['type'] == 'sphere':
        inertia = calculateSphereInertia(mass, geometry['radius'])
    elif geometry['type'] == 'capsule':
        inertia = calculateCapsuleInertia(mass, geometry['radius'], geometry['length'])
    elif geometry['type'] == 'mesh':
        sUtils.selectObjects((obj,), clear=True, active=0)
        inertia = calculateMeshInertia(mass, obj.data)
    return inertia
Esempio n. 8
0
def createInertials(link, empty=False, preserve_children=False):
    """Creates inertial representations for visual and collision objects in link.

    :param link: The link you want to create the inertial for.
    :type link: bpy_types.Object
    :param empty: If set to True the new inertial object will contain no information.
    :type empty: bool
    :param preserve_children: If set to False existing inertial objects will be deleted.
    :type preserve_children: bool

    """
    viscols = getInertiaRelevantObjects(link)
    # clean existing data
    if not preserve_children:
        oldinertials = sUtils.getImmediateChildren(link, ['inertial'])
    else:
        try:
            oldinertials = [bpy.data.objects['inertial_' + link.name]]
        except KeyError:
            oldinertials = None
    if oldinertials:
        sUtils.selectObjects(oldinertials, clear=True, active=0)
        bpy.ops.object.delete()
    if not preserve_children:
        for obj in viscols:
            if not empty:
                mass = obj['mass'] if 'mass' in obj else None
                geometry = deriveGeometry(obj)
                if mass is not None and geometry is not None:
                    if geometry['type'] == 'mesh':
                        sUtils.selectObjects([obj])
                        bpy.context.scene.objects.active = obj
                        inert = calculateMeshInertia(obj.data, mass)
                    else:
                        inert = calculateInertia(mass, geometry)
                    if inert is not None:
                        inertial = createInertial(obj)
                        inertial['mass'] = mass
                        inertial['inertia'] = inert
            else:
                createInertial(obj)
    # compose inertial object for link
    if not empty:
        mass, com, inert = fuseInertiaData(
            sUtils.getImmediateChildren(link, ['inertial']))
        if mass and com and inert:
            inertial = createInertial(link)
            com_translate = mathutils.Matrix.Translation(com)
            inertial.matrix_local = com_translate
            bpy.ops.transform.translate(value=(
                0, 0, 0
            ))  # FIXME: this is a trick to force Blender to apply matrix_local
            inertial['inertial/mass'] = mass
            inertial['inertial/inertia'] = inertiaMatrixToList(inert)
    else:
        createInertial(link)
Esempio n. 9
0
def calculateInertia(obj,
                     mass,
                     geometry_dict=None,
                     errors=None,
                     adjust=False,
                     logging=False):
    """Calculates the inertia of an object using the specified mass and
       optionally geometry.

    Args:
      obj(bpy.types.Object): object to calculate inertia from
      mass(float): mass of object
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple): (Default value = None)
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple):
    tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None)
      errors: (Default value = None)
      adjust: (Default value = False)
      logging: (Default value = False)

    Returns:

    """
    if errors and not adjust:
        if logging:
            log("Can not calculate inertia from object.", 'ERROR')
        return None

    inertia = None
    if not geometry_dict:
        geometry = deriveGeometry(obj)

    # Get the rotation of the object
    object_rotation = obj.rotation_euler.to_matrix()

    if geometry['type'] == 'box':
        inertia = calculateBoxInertia(mass, geometry['size'])
    elif geometry['type'] == 'cylinder':
        inertia = calculateCylinderInertia(mass, geometry['radius'],
                                           geometry['length'])
    elif geometry['type'] == 'sphere':
        inertia = calculateSphereInertia(mass, geometry['radius'])
    elif geometry['type'] == 'mesh':
        sUtils.selectObjects((obj, ), clear=True, active=0)
        inertia = calculateMeshInertia(mass, obj.data, scale=obj.scale)

    # Correct the inertia orientation to account for Cylinder / mesh orientation issues
    inertia = object_rotation * inertiaListToMatrix(
        inertia) * object_rotation.transposed()

    return inertiaMatrixToList(inertia)
Esempio n. 10
0
def deriveVisual(obj, logging=True, **kwargs):
    """This function derives the visual information from an object.
    
    Contains these keys:
        *name*: name of the visual
        *geometry*: derived according to `deriveGeometry`
        *pose*: derived according to `deriveObjectPose`
        *lod*: (opt.) level of detail levels

    Args:
      obj(bpy.types.Object): object to derive the visual representation from
      logging: (Default value = True)
      **kwargs: 

    Returns:
      : dict -- model representation of the visual object

    """
    visual = initObjectProperties(obj,
                                  phobostype='visual',
                                  ignoretypes='geometry')
    visual['geometry'] = deriveGeometry(obj, logging=logging)
    visual['pose'] = deriveObjectPose(obj, logging=logging)

    # check for material of the visual
    material = deriveMaterial(obj.active_material, logging=logging)
    if material:
        visual['material'] = material['name']

    if obj.lod_levels:
        if 'lodmaxdistances' in obj:
            maxdlist = obj['lodmaxdistances']
        else:
            maxdlist = [
                obj.lod_levels[i + 1].distance
                for i in range(len(obj.lod_levels) - 1)
            ] + [100.0]
        lodlist = []
        for i in range(len(obj.lod_levels)):
            filename = obj.lod_levels[
                i].object.data.name + ioUtils.getOutputMeshtype()
            lodlist.append({
                'start': obj.lod_levels[i].distance,
                'end': maxdlist[i],
                'filename': os.path.join('meshes', filename),
            })
        visual['lod'] = lodlist
    return visual
Esempio n. 11
0
def calculateInertia(obj, mass, geometry_dict=None, errors=None, adjust=False, logging=False):
    """Calculates the inertia of an object using the specified mass and
       optionally geometry.

    Args:
      obj(bpy.types.Object): object to calculate inertia from
      mass(float): mass of object
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple): (Default value = None)
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple):
    tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None)
      errors: (Default value = None)
      adjust: (Default value = False)
      logging: (Default value = False)

    Returns:

    """
    if errors and not adjust:
        if logging:
            log("Can not calculate inertia from object.", 'ERROR')
        return None

    inertia = None
    if not geometry_dict:
        geometry = deriveGeometry(obj)

    # Get the rotation of the object
    object_rotation = obj.rotation_euler.to_matrix()

    if geometry['type'] == 'box':
        inertia = calculateBoxInertia(mass, geometry['size'])
    elif geometry['type'] == 'cylinder':
        inertia = calculateCylinderInertia(mass, geometry['radius'], geometry['length'])
    elif geometry['type'] == 'sphere':
        inertia = calculateSphereInertia(mass, geometry['radius'])
    elif geometry['type'] == 'mesh':
        sUtils.selectObjects((obj,), clear=True, active=0)
        inertia = calculateMeshInertia(mass, obj.data)

    # Correct the inertia orientation to account for Cylinder / mesh orientation issues
    inertia = object_rotation * inertiaListToMatrix(inertia) * object_rotation.transposed()

    return inertiaMatrixToList(inertia)
Esempio n. 12
0
def calculateInertia(obj,
                     mass,
                     geometry_dict=None,
                     errors=None,
                     adjust=False,
                     logging=False):
    """Calculates the inertia of an object using the specified mass and
       optionally geometry.

    Args:
      obj(bpy.types.Object): object to calculate inertia from
      mass(float): mass of object
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple): (Default value = None)
      geometry_dict(dict, optional): geometry part of the object dictionary
    Returns(tuple):
    tuple(6) of upper diagonal of the inertia 3x3 tensor (Default value = None)
      errors: (Default value = None)
      adjust: (Default value = False)
      logging: (Default value = False)

    Returns:

    """
    if errors and not adjust:
        if logging:
            log("Can not calculate inertia from object.", 'ERROR')
        return None

    inertia = None
    if not geometry_dict:
        geometry = deriveGeometry(obj)

    if geometry['type'] == 'box':
        inertia = calculateBoxInertia(mass, geometry['size'])
    elif geometry['type'] == 'cylinder':
        inertia = calculateCylinderInertia(mass, geometry['radius'],
                                           geometry['length'])
    elif geometry['type'] == 'sphere':
        inertia = calculateSphereInertia(mass, geometry['radius'])
    elif geometry['type'] == 'mesh':
        sUtils.selectObjects((obj, ), clear=True, active=0)
        inertia = calculateMeshInertia(mass, obj.data)
    return inertia
Esempio n. 13
0
def createInertialObjects(link, autocalc=True):
    """Creates inertial objects from inertials of the visual/collision objects of a link.

    The new inertials can be calculated automatically or remain empty (based on the autocalc
    parameter).

    :param link: the link which contains the visual/collision objects
    :type link: bpy_types.Object
    :param autocalc: If set to False the new inertial object will contain no inertia information.
    :type autocalc: bool

    :return: the newly created inertial objects
    :rtype: list of bpy.types.Object
    """
    assert link.phobostype == 'link', 'Not a link object: ' + link.phobostype + '.'
    viscols = getInertiaRelevantObjects(link)

    inertialobjs = []
    for obj in viscols:
        inertialdata = {
            'mass': 0,
            'inertia': [0, 0, 0, 0, 0, 0],
            'pose': {
                'translation': obj.matrix_local.to_translation()
            }
        }
        if autocalc:
            mass = obj['mass'] if 'mass' in obj else None
            geometry = deriveGeometry(obj)
            if mass and geometry:
                inert = calculateInertia(obj, mass, geometry)
                if inert is not None:
                    inertialdata['mass'] = mass
                    inertialdata['inertia'] = inert
        # Create the object as a child of the parent object
        inertialobjs.append(
            createInertial(obj.name,
                           inertialdata,
                           parentobj=obj,
                           effectiveParent=link))
    if not inertialobjs:
        log('No objects to calculate inertias from.', 'WARNING')
    return inertialobjs
Esempio n. 14
0
def deriveEntity(primitive, outpath):
    """This function handles a primitive entity in a scene to export it
    
    # TODO is this even a heightmap?

    Args:
      smurf(bpy.types.Object): The heightmap root object.
      outpath(str): The path to export to. Not used for primitives
      savetosubfolder(bool): If True data will be exported into subfolders. Not used for primitives
      primitive: 

    Returns:
      : dict - An entry for the scenes entitiesList

    """
    entity = models.initObjectProperties(primitive, 'entity', ['geometry'])
    pose = deriveObjectPose(primitive)
    entity['geometry'] = deriveGeometry(primitive)
    entity['position'] = {
        'x': pose['translation'][0],
        'y': pose['translation'][1],
        'z': pose['translation'][2],
    }
    entity['rotation'] = {
        'w': pose['rotation_quaternion'][0],
        'x': pose['rotation_quaternion'][1],
        'y': pose['rotation_quaternion'][2],
        'z': pose['rotation_quaternion'][3],
    }
    if 'radius' in entity['geometry']:
        entity['radius'] = entity['geometry']['radius']
    # entity['extend'] = {'x': entity['geometry']['size'][0],
    #                    'y': entity['geometry']['size'][1],
    #                    'z': entity['geometry']['size'][2]}
    entity['extend'] = {
        'x': primitive.dimensions[0],
        'y': primitive.dimensions[1],
        'z': primitive.dimensions[2],
    }
    return entity
Esempio n. 15
0
def deriveEntity(entity, outpath, savetosubfolder):
    """This function handles a primitive entity in a scene to export it

    :param smurf: The heightmap root object.
    :type smurf: bpy.types.Object
    :param outpath: The path to export to. Not used for primitives
    :type outpath: str
    :param savetosubfolder: If True data will be exported into subfolders. Not used for primitives
    :type savetosubfolder: bool
    :return: dict - An entry for the scenes entitiesList

    """

    primitive = entity

    log(
        "Exporting " + nUtils.getObjectName(primitive, 'entity') +
        " as entity of type 'primitive", "INFO")
    entity = models.initObjectProperties(primitive, 'entity', ['geometry'])
    pose = deriveObjectPose(primitive)
    entity['geometry'] = deriveGeometry(primitive)
    entity['position'] = {
        'x': pose['translation'][0],
        'y': pose['translation'][1],
        'z': pose['translation'][2]
    }
    entity['rotation'] = {
        'w': pose['rotation_quaternion'][0],
        'x': pose['rotation_quaternion'][1],
        'y': pose['rotation_quaternion'][2],
        'z': pose['rotation_quaternion'][3]
    }
    entity['extend'] = {
        'x': entity['geometry']['size'][0],
        'y': entity['geometry']['size'][1],
        'z': entity['geometry']['size'][2]
    }
    return entity
Esempio n. 16
0
def deriveEntity(primitive, outpath, savetosubfolder=True):
    """This function handles a primitive entity in a scene to export it

    :param smurf: The heightmap root object.
    :type smurf: bpy.types.Object
    :param outpath: The path to export to. Not used for primitives
    :type outpath: str
    :param savetosubfolder: If True data will be exported into subfolders. Not used for primitives
    :type savetosubfolder: bool
    :return: dict - An entry for the scenes entitiesList

    """
    entity = models.initObjectProperties(primitive, 'entity', ['geometry'])
    pose = deriveObjectPose(primitive)
    entity['geometry'] = deriveGeometry(primitive)
    entity['position'] = {
        'x': pose['translation'][0],
        'y': pose['translation'][1],
        'z': pose['translation'][2]
    }
    entity['rotation'] = {
        'w': pose['rotation_quaternion'][0],
        'x': pose['rotation_quaternion'][1],
        'y': pose['rotation_quaternion'][2],
        'z': pose['rotation_quaternion'][3]
    }
    if 'radius' in entity['geometry']:
        entity['radius'] = entity['geometry']['radius']
    #entity['extend'] = {'x': entity['geometry']['size'][0],
    #                    'y': entity['geometry']['size'][1],
    #                    'z': entity['geometry']['size'][2]}
    entity['extend'] = {
        'x': primitive.dimensions[0],
        'y': primitive.dimensions[1],
        'z': primitive.dimensions[2]
    }
    return entity