def make_mesh(self, parent_node, obj): """ Make mesh-type object. """ gltf_node = None # merged nodes if self.can_merge(obj): collection = get_object_collection(obj) for child in self._root['nodes']: if child['name'] == collection.name: # got existing glTF node gltf_node = child mesh_id = gltf_node['mesh'] # got existing glTF mesh gltf_mesh = self._root['meshes'][mesh_id] break else: # glTF-node - glTF-mesh pair not found # create new pair gltf_node, gltf_mesh = self._make_node_mesh(parent_node, collection.name, obj, can_merge=True) if gltf_mesh: self.make_geom(gltf_node, gltf_mesh, obj, can_merge=True) # separate nodes if not self.can_merge(obj) or self._keep: obj_props = get_object_properties(obj) if obj_props.get('type') == 'Portal': vertices = [list(vertex.co) for vertex in obj.data.vertices] gltf_node = { 'name': obj.name, 'extras': { 'vertices': json.dumps(vertices) }, } self._setup_node(gltf_node, obj, can_merge=False) self._add_child(parent_node, gltf_node) return gltf_node gltf_node, gltf_mesh = self._make_node_mesh(parent_node, obj.name, obj, can_merge=False) if gltf_mesh: self.make_geom(gltf_node, gltf_mesh, obj, can_merge=False) return gltf_node
def can_merge(self, obj): if not self._merge: return False collection = get_object_collection(obj) if not collection: return False if is_collision(obj): return False obj_props = get_object_properties(obj) if obj_props.get('type') in NOT_MERGED_TYPES: return False return True
def _setup_node(self, node, obj=None, can_merge=False): if obj is None: return armature = get_armature(obj) obj_matrix = self._transform(get_object_matrix(obj, armature=armature)) # get custom object properties obj_props = get_object_properties(obj) if not can_merge and not armature: if self._geom_scale == 1: node.update({ 'rotation': quat_to_list(obj_matrix.to_quaternion()), 'scale': list(obj_matrix.to_scale()), 'translation': list(obj_matrix.to_translation()), # 'matrix': matrix_to_list(obj_matrix), }) else: x, y, z = list(obj_matrix.to_translation()) x *= self._geom_scale y *= self._geom_scale z *= self._geom_scale node.update({ 'rotation': quat_to_list(obj_matrix.to_quaternion()), 'scale': list(obj_matrix.to_scale()), 'translation': [x, y, z], }) # setup collisions if not can_merge and is_collision( obj) and obj_props.get('type') != 'Portal': collision = {} node['extensions'] = { 'BLENDER_physics': collision, } # collision shape shape = { 'shapeType': obj.rigid_body.collision_shape, 'boundingBox': [ obj.dimensions[i] / obj_matrix.to_scale()[i] * self._geom_scale for i in range(3) ], } if obj.rigid_body.collision_shape == 'MESH': shape['mesh'] = node.pop('mesh') collision['collisionShapes'] = [shape] collision['static'] = obj.rigid_body.type == 'PASSIVE' # don't actually collide (ghost) if (not obj.collision or not obj.collision.use): collision['intangible'] = True if self._set_origin: obj.select_set(state=True) set_active_object(obj) x1, y1, z1 = obj.location # set origin to the center of bounds bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS') x2, y2, z2 = obj.location if 'extras' not in node: node['extras'] = {} node['extras']['origin'] = [x2 - x1, y2 - y1, z2 - z1] # setup custom properties with tags if (obj_props or can_merge) and 'extras' not in node: node['extras'] = {} for k, v in obj_props.items(): if node['extras'].get(k): # tag exists tag = node['extras'].get(k) if type(v) in (tuple, list, dict): tag = json.dumps(v) else: tag = '{}'.format(v) node['extras'][k] = tag # if can_merge and 'type' not in obj_props: if can_merge: node['extras']['type'] = 'Merged'
def _setup_node(self, node, obj=None, can_merge=False): if obj is None: return armature = get_armature(obj) obj_matrix = get_object_matrix(obj, armature=armature) # get custom object properties obj_props = get_object_properties(obj) if not can_merge and not armature: node.add_matrix4(matrix_to_panda(obj_matrix)) if obj_props.get('type') == 'Portal': node.set_portal_flag(True) # setup collisions if not can_merge and is_collision(obj): # collision name node.set_collision_name(obj.name) # collision solid type shape = { 'BOX': EggGroup.CST_box, 'SPHERE': EggGroup.CST_sphere, 'CAPSULE': EggGroup.CST_tube, 'MESH': EggGroup.CST_polyset, }.get(obj.rigid_body.collision_shape, EggGroup.CST_polyset) # custom shape if obj.rigid_body.collision_shape == 'CONVEX_HULL': # trying to guess the best shape polygons = list( filter(lambda x: isinstance(x, EggPolygon), node.get_children())) if len(polygons) == 1 and polygons[0].is_planar(): # shape = EggGroup.CST_plane # <- is it infinite? shape = EggGroup.CST_polygon node.set_cs_type(shape) # collision flags # inherit collision by children nodes? flags = EggGroup.CF_descend if (not obj.collision or not obj.collision.use): # don't actually collide (ghost) flags |= EggGroup.CF_intangible node.set_collide_flags(flags) # setup custom properties with tags for k, v in obj_props.items(): if node.get_tag(k): # tag exists tag = node.get_tag(k) if type(v) in (tuple, list, dict): tag = json.dumps(v) else: tag = '{}'.format(v) node.set_tag(k, tag) if can_merge and 'type' not in obj_props: node.set_tag('type', 'Merged')
def _setup_node(self, node, obj=None, can_merge=False): if obj is None: return armature = get_armature(obj) obj_matrix = get_object_matrix(obj, armature=armature) # get custom object properties obj_props = get_object_properties(obj) if not can_merge and not armature: if self._geom_scale == 1: node.update({ 'rotation': quat_to_list(obj_matrix.to_quaternion()), 'scale': list(obj_matrix.to_scale()), 'translation': list(obj_matrix.to_translation()), }) else: x, y, z = list(obj_matrix.to_translation()) x *= self._geom_scale y *= self._geom_scale z *= self._geom_scale node.update({ 'rotation': quat_to_list(obj_matrix.to_quaternion()), 'scale': list(obj_matrix.to_scale()), 'translation': [x, y, z], }) # setup collisions if not can_merge and is_collision(obj) and obj_props.get('type') != 'Portal': collision = {} node['extensions'] = { 'BLENDER_physics': collision, } # collision shape shape = { 'shapeType': obj.rigid_body.collision_shape, 'boundingBox': [ obj.dimensions[i] / obj_matrix.to_scale()[i] for i in range(3) ], } if obj.rigid_body.collision_shape == 'MESH': shape['mesh'] = node.pop('mesh') collision['collisionShapes'] = [shape] collision['static'] = obj.rigid_body.type == 'PASSIVE' # don't actually collide (ghost) if (not obj.collision or not obj.collision.use): collision['intangible'] = True # setup custom properties with tags if (obj_props or can_merge) and 'extras' not in node: node['extras'] = {} for k, v in obj_props.items(): if node['extras'].get(k): # tag exists tag = node['extras'].get(k) if type(v) in (tuple, list, dict): tag = json.dumps(v) else: tag = '{}'.format(v) node['extras'][k] = tag if can_merge and 'type' not in obj_props: node['extras']['type'] = 'Merged'