コード例 #1
0
 def branchentry(self, branch):
     if not isinstance(branch, NifFormat.bhkConvexVerticesShape):
         # keep recursing
         return True
     else:
         self.toaster.msg("checking vertices and planes")
         for v4 in branch.vertices:
             v = NifFormat.Vector3()
             v.x = v4.x
             v.y = v4.y
             v.z = v4.z
             num_intersect = 0
             for n4 in branch.normals:
                 n = NifFormat.Vector3()
                 n.x = n4.x
                 n.y = n4.y
                 n.z = n4.z
                 d   = n4.w
                 if abs(v * n + d) < 0.01:
                     num_intersect += 1
             if num_intersect == 0:
                 self.toaster.logger.error(
                     "vertex %s does not intersect with any plane" % v)
             elif num_intersect == 1:
                 self.toaster.logger.warn(
                     "vertex %s only intersects with one plane" % v)
             elif num_intersect == 2:
                 self.toaster.logger.warn(
                     "vertex %s only intersects with two planes" % v)
         # stop recursing
         return False
コード例 #2
0
    def import_egm_morphs(self, egmdata, b_obj, v_map, n_verts):
        """Import all EGM morphs as shape keys for blender object."""
        # XXX if there is an egm, the assumption is that there is only one
        # XXX mesh in the nif
        b_mesh = b_obj.data
        sym_morphs = [list(morph.get_relative_vertices())
                      for morph in egmdata.sym_morphs]
        asym_morphs = [list(morph.get_relative_vertices())
                      for morph in egmdata.asym_morphs]
        
        # insert base key at frame 1, using absolute keys
        sk_basis = b_obj.shape_key_add("Basis")
        b_mesh.shape_keys.use_relative = False

        morphs = ([(morph, "EGM SYM %i" % i)
                   for i, morph in enumerate(sym_morphs)]
                  + 
                  [(morph, "EGM ASYM %i" % i)
                   for i, morph in enumerate(asym_morphs)])

        for morphverts, keyname in morphs:
            #convert tuples into vector here so we can simply add in morph_mesh()
            morphvert_out = []
            for u in morphverts:
                v = NifFormat.Vector3()
                v.x, v.y, v.z = u
                morphvert_out.append(v)
            self.morph_mesh(b_mesh, n_verts, morphvert_out, v_map)
            shape_key = b_obj.shape_key_add(keyname, from_mix=False)
コード例 #3
0
    def build_nif_matrix(cls):

        n_mat = NifFormat.Matrix44()
        translation = (2.0, 3.0, 4.0)
        scale = 2.0

        n_rhs_rot_x = (1.0, 0.0, 0.0, 0.0, 0.866, 0.5, 0.0, -0.5, 0.866)

        n_rhs_rot_y = (0.5, 0.0, -0.866, 0.0, 1.0, 0.0, 0.866, 0.0, 0.5)

        n_rhs_rot_z = (0, 1, 0, -1, 0, 0, 0, 0, 1)

        n_rhs_rot_x = cls.create_matrix(n_rhs_rot_x)
        n_rhs_rot_y = cls.create_matrix(n_rhs_rot_y)
        n_rhs_rot_z = cls.create_matrix(n_rhs_rot_z)

        n_mat33 = n_rhs_rot_z * n_rhs_rot_y * n_rhs_rot_x

        n_vec3 = NifFormat.Vector3()
        n_vec3.x = translation[0]
        n_vec3.y = translation[1]
        n_vec3.z = translation[2]

        n_mat.set_scale_rotation_translation(scale, n_mat33, n_vec3)

        return n_mat
コード例 #4
0
    def build_nif_matrix(cls):
         
        n_mat = NifFormat.Matrix44()
        translation = (2.0, 3.0, 4.0)
        scale = 2.0
        
        rhsrotx = (1.0, 0.0, 0.0,
                   0.0, 0.866, 0.5,
                   0.0, -0.5, 0.866)
        
        rhsroty = (0.5, 0.0, -0.866,
                   0.0, 1.0, 0.0,
                   0.866, 0.0, 0.5)
       
        rhsrotz = (0, 1, 0,
                   -1, 0, 0,
                   0, 0, 1)
        
        rhsrotx = cls.create_matrix(rhsrotx)
        rhsroty = cls.create_matrix(rhsroty)
        rhsrotz = cls.create_matrix(rhsrotz)
         
        n_mat33 = rhsrotz * rhsroty * rhsrotx
         
        n_vec3 = NifFormat.Vector3()
        n_vec3.x = translation[0]
        n_vec3.y = translation[1]
        n_vec3.z = translation[2]
 
        n_mat.set_scale_rotation_translation(scale, n_mat33, n_vec3)
        
        return n_mat
コード例 #5
0
    def get_skin_deformation_from_partition(n_geom):
        """ Workaround because pyffi does not support this skinning method """

        # todo [pyffi] integrate this into pyffi!!!
        #              so that NiGeometry.get_skin_deformation() deals with this as intended

        # mostly a copy from pyffi...
        skin_inst = n_geom.skin_instance
        skin_data = skin_inst.data
        skin_partition = skin_inst.skin_partition
        skel_root = skin_inst.skeleton_root
        vertices = [
            NifFormat.Vector3() for _ in range(n_geom.data.num_vertices)
        ]

        # ignore normals for now, not needed for import
        sum_weights = [0.0 for _ in range(n_geom.data.num_vertices)]
        skin_offset = skin_data.get_transform()

        # store one transform per bone
        bone_transforms = []
        for i, bone_block in enumerate(skin_inst.bones):
            bone_data = skin_data.bone_list[i]
            bone_offset = bone_data.get_transform()
            bone_matrix = bone_block.get_transform(skel_root)
            transform = bone_offset * bone_matrix * skin_offset
            bone_transforms.append(transform)

        # now the actual unique bit
        for block in skin_partition.skin_partition_blocks:
            # create all vgroups for this block's bones
            block_bone_transforms = [bone_transforms[i] for i in block.bones]

            # go over each vert in this block
            for vert_index, vertex_weights, bone_indices in zip(
                    block.vertex_map, block.vertex_weights,
                    block.bone_indices):
                # skip verts that were already processed in an earlier block
                if sum_weights[vert_index] != 0:
                    continue

                # go over all 4 weight / bone pairs and transform this vert
                for weight, b_i in zip(vertex_weights, bone_indices):
                    if weight > 0:
                        transform = block_bone_transforms[b_i]
                        vertices[vert_index] += weight * (
                            n_geom.data.vertices[vert_index] * transform)
                        sum_weights[vert_index] += weight

        for i, s in enumerate(sum_weights):
            if abs(s - 1.0) > 0.01:
                print(
                    f"Vertex {i:d} has weights not summing to one: {sum_weights['i']:d}"
                )

        return vertices
コード例 #6
0
    def branchentry(self, branch):
        if not isinstance(branch, NifFormat.NiGeometryData):
            # keep recursing
            return True
        else:
            report = {}
            self.toaster.msg("getting bounding sphere")
            center = NifFormat.Vector3()
            center.x = branch.center.x
            center.y = branch.center.y
            center.z = branch.center.z
            radius = branch.radius

            self.toaster.msg("checking that all vertices are inside")
            maxr = 0.0
            maxv = None
            for vert in branch.vertices:
                dist = vert - center
                if dist * dist > maxr:
                    maxr = dist * dist
                    maxv = vert
            maxr = maxr ** 0.5

            if maxr > 1.01 * radius + 0.01:
                #raise ValueError(
                self.toaster.logger.warn(
                   "not all vertices inside bounding sphere (vertex %s, error %s)"
                   % (maxv, abs(maxr - radius)))
                report["vertex_outside"] = maxv.as_tuple()

            self.toaster.msg("recalculating bounding sphere")
            branch.update_center_radius()

            self.toaster.msg("comparing old and new spheres")
            if center != branch.center:
               self.toaster.logger.warn(
                   "center does not match; original %s, calculated %s"
                   % (center, branch.center))
               report["center"] = {
                   "orig": center.as_tuple(),
                   "calc": branch.center.as_tuple(),
                   }
            if abs(radius - branch.radius) > NifFormat.EPSILON:
               self.toaster.logger.warn(
                   "radius does not match; original %s, calculated %s"
                   % (radius, branch.radius))
               report["radius"] = {
                   "orig": radius,
                   "calc": branch.radius,
                   }
            if report:
                self.append_report(report)
            # stop recursing
            return False
コード例 #7
0
    def branchentry(self, branch):
        if not isinstance(branch, NifFormat.bhkMoppBvTreeShape):
            # keep recursing
            return True
        else:
            mopp = [b for b in branch.mopp_data]
            o = NifFormat.Vector3()
            o.x = branch.origin.x
            o.y = branch.origin.y
            o.z = branch.origin.z
            scale = branch.scale

            self.toaster.msg("recalculating mopp origin and scale")
            branch.update_origin_scale()

            if branch.origin != o:
                self.toaster.logger.warn("origin mismatch")
                self.toaster.logger.warn("(was %s and is now %s)"
                                         % (o, branch.origin))
            if abs(branch.scale - scale) > 0.5:
                self.toaster.logger.warn("scale mismatch")
                self.toaster.logger.warn("(was %s and is now %s)"
                                         % (scale, branch.scale))

            self.toaster.msg("parsing mopp")
            # ids = indices of bytes processed, tris = triangle indices
            ids, tris = branch.parse_mopp(verbose=True)

            error = False

            # check triangles
            counts = [tris.count(i) for i in range(branch.shape.data.num_triangles)]
            missing = [i for i in range(branch.shape.data.num_triangles)
                       if counts[i] != 1]
            if missing:
                self.toaster.logger.error(
                    "some triangles never visited, or visited more than once")
                self.toaster.logger.debug(
                    "triangles index, times visited")
                for i in missing:
                    self.toaster.logger.debug(i, counts[i])
                error = True

            wrong = [i for i in tris if i > branch.shape.data.num_triangles]
            if wrong:
                self.toaster.logger.error("invalid triangle indices")
                self.toaster.logger.debug(wrong)
                error = True

            # check bytes
            counts = [ids.count(i) for i in range(branch.mopp_data_size)]
            missing = [i for i in range(branch.mopp_data_size) if counts[i] != 1]
            if missing:
                self.toaster.logger.error(
                    "some bytes never visited, or visited more than once")
                self.toaster.logger.debug(
                    "byte index, times visited, value")
                for i in missing:
                    self.toaster.logger.debug(i, counts[i], "0x%02X" % mopp[i])
                    self.toaster.logger.debug([mopp[k] for k in range(i, min(branch.mopp_data_size, i + 10))])
                error = True

            #if error:
            #    raise ValueError("mopp parsing failed")

            # stop recursing
            return False
コード例 #8
0
ファイル: ua.py プロジェクト: qbx2/pyffi
def DrawOffset(v, off):
    w = NifFormat.Vector3()
    w.x = v.x + off.x
    w.y = v.y + off.y
    w.z = v.z + off.z
    DrawLine(v, w)