Beispiel #1
0
def parse_vmd_morphframe(raw:bytearray, moreinfo:bool) -> List[vmdstruct.VmdMorphFrame]:
	# get all the morph-frames, store in a list of lists
	morphframe_list = []
	# is there enough file left to read a single number?
	if (len(raw) - core.get_readfrom_byte()) < struct.calcsize(fmt_number):
		core.MY_PRINT_FUNC("Warning: expected morphframe_ct field but file ended unexpectedly! Assuming 0 morphframes and continuing...")
		return morphframe_list
	
	############################
	# get the number of morph frames
	morphframe_ct = core.my_unpack(fmt_number, raw)
	if moreinfo: core.MY_PRINT_FUNC("...# of morphframes         = %d" % morphframe_ct)
	for z in range(morphframe_ct):
		try:
			# unpack the morphframe
			(mname_str, f, v) = core.my_unpack(fmt_morphframe, raw)
			morphframe_list.append(vmdstruct.VmdMorphFrame(name=mname_str, f=f, val=v))
			
			# display progress printouts
			core.print_progress_oneline(core.get_readfrom_byte() / len(raw))
		except Exception as e:
			core.MY_PRINT_FUNC(e.__class__.__name__, e)
			core.MY_PRINT_FUNC("frame=", z)
			core.MY_PRINT_FUNC("totalframes=", morphframe_ct)
			core.MY_PRINT_FUNC("section=morphframe")
			core.MY_PRINT_FUNC("Err: something went wrong while parsing, file is probably corrupt/malformed")
			raise RuntimeError()
	
	return morphframe_list
Beispiel #2
0
def read_vmd(vmd_filename: str, moreinfo=False) -> vmdstruct.Vmd:
    vmd_filename_clean = core.get_clean_basename(vmd_filename) + ".vmd"
    # creates object 	(header, boneframe_list, morphframe_list, camframe_list, lightframe_list, shadowframe_list, ikdispframe_list)
    # assumes the calling function already verified correct file extension
    core.MY_PRINT_FUNC("Begin reading VMD file '%s'" % vmd_filename_clean)
    vmd_bytes = core.read_binfile_to_bytes(vmd_filename)
    core.MY_PRINT_FUNC("...total size   = %sKB" % round(len(vmd_bytes) / 1024))
    core.MY_PRINT_FUNC("Begin parsing VMD file '%s'" % vmd_filename_clean)
    core.reset_unpack()
    core.set_encoding("shift_jis")

    # !!!! this does eliminate all the garbage data MMD used to pack strings so this isnt 100% reversable !!!
    # read the bytes object and return all the data from teh VMD broken up into a list of lists
    # also convert things from packed formats to human-readable scales
    # (quaternion to euler, radians to degrees, floats to ints, etc)
    # also generate the bonedict and morphdict

    core.print_progress_oneline(0)
    A = parse_vmd_header(vmd_bytes, moreinfo)
    B = parse_vmd_boneframe(vmd_bytes, moreinfo)
    C = parse_vmd_morphframe(vmd_bytes, moreinfo)
    D = parse_vmd_camframe(vmd_bytes, moreinfo)
    E = parse_vmd_lightframe(vmd_bytes, moreinfo)
    F = parse_vmd_shadowframe(vmd_bytes, moreinfo)
    G = parse_vmd_ikdispframe(vmd_bytes, moreinfo)
    if moreinfo: core.print_failed_decodes()

    bytes_remain = len(vmd_bytes) - core.get_readfrom_byte()
    if bytes_remain != 0:
        # padding with my SIGNATURE is acceptable, anything else is strange
        leftover = vmd_bytes[core.get_readfrom_byte():]
        if leftover == bytes(SIGNATURE, encoding="shift_jis"):
            core.MY_PRINT_FUNC(
                "...note: this VMD file was previously modified with this tool!"
            )
        else:
            core.MY_PRINT_FUNC(
                "Warning: finished parsing but %d bytes are left over at the tail!"
                % bytes_remain)
            core.MY_PRINT_FUNC(
                "The file may be corrupt or maybe it contains unknown/unsupported data formats"
            )
            core.MY_PRINT_FUNC(leftover)

    core.MY_PRINT_FUNC("Done parsing VMD file '%s'" % vmd_filename_clean)

    vmd = vmdstruct.Vmd(A, B, C, D, E, F, G)
    # this is where sorting happens, if it happens
    if GUARANTEE_FRAMES_SORTED:
        # bones & morphs: primarily sorted by NAME, with FRAME# as tiebreaker. the second sort is the primary one.
        vmd.boneframes.sort(key=lambda x: x.f)  # frame#
        vmd.boneframes.sort(key=lambda x: x.name)  # name
        vmd.morphframes.sort(key=lambda x: x.f)
        vmd.morphframes.sort(key=lambda x: x.name)
        # all of these only sort by frame number.
        vmd.camframes.sort(key=lambda x: x.f)  # frame#
        vmd.lightframes.sort(key=lambda x: x.f)
        vmd.shadowframes.sort(key=lambda x: x.f)
        vmd.ikdispframes.sort(key=lambda x: x.f)
    return vmd
Beispiel #3
0
def parse_vmd_boneframe(raw:bytearray, moreinfo:bool) -> List[vmdstruct.VmdBoneFrame]:
	# get all the bone-frames, store in a list of lists
	boneframe_list = []
	# verify that there is enough file left to read a single number
	if (len(raw) - core.get_readfrom_byte()) < struct.calcsize(fmt_number):
		core.MY_PRINT_FUNC("Warning: expected boneframe_ct field but file ended unexpectedly! Assuming 0 boneframes and continuing...")
		return boneframe_list

	############################
	# get the number of bone-frames
	boneframe_ct = core.my_unpack(fmt_number, raw)
	if moreinfo: core.MY_PRINT_FUNC("...# of boneframes          = %d" % boneframe_ct)
	for z in range(boneframe_ct):
		try:
			# unpack the bone-frame into variables
			(bname_str, f, xp, yp, zp, xrot_q, yrot_q, zrot_q, wrot_q) = core.my_unpack(fmt_boneframe_no_interpcurve, raw)
			# break inter_curve into its individual pieces, knowing that the 3rd and 4th bytes in line1 are overwritten with phys
			# therefore we need to get their data from line2 which is left-shifted by 1 byte, but otherwise a copy
			(x_ax, y_ax, phys1, phys2, x_ay, y_ay, z_ay, r_ay, x_bx, y_bx, z_bx, r_bx, x_by, y_by, z_by, r_by,
			 z_ax, r_ax) = core.my_unpack(fmt_boneframe_interpcurve, raw)
			# convert the quaternion angles to euler angles
			(xrot, yrot, zrot) = core.quaternion_to_euler([wrot_q, xrot_q, yrot_q, zrot_q])
			# interpret the physics enable/disable bytes
			if (phys1, phys2) == (z_ax, r_ax):
				# if they match the values they should be, they were never overwritten in the first place???
				phys_off = False
			elif (phys1, phys2) == (0, 0):
				# phys stays on
				phys_off = False
			elif (phys1, phys2) == (99, 15):
				# phys turns off
				phys_off = True
			else:
				core.MY_PRINT_FUNC("Warning: found unusual values where I expected to find physics enable/disable! Assuming this means physics off")
				core.MY_PRINT_FUNC(bname_str, "f=", str(f), "(phys1,phys2)=", str((phys1, phys2)))
				phys_off = True
			# store them all on the list
			# create a list to hold all the boneframe data, then append it onto the return-list
			interp_list = [x_ax, y_ax, z_ax, r_ax, x_ay, y_ay, z_ay, r_ay, x_bx, y_bx, z_bx, r_bx, x_by, y_by, z_by, r_by]
			this_boneframe = vmdstruct.VmdBoneFrame(
				name=bname_str, f=f, pos=[xp,yp,zp], rot=[xrot,yrot,zrot], phys_off=phys_off, interp=interp_list
			)
			boneframe_list.append(this_boneframe)
			# display progress printouts
			core.print_progress_oneline(core.get_readfrom_byte() / len(raw))
		except Exception as e:
			core.MY_PRINT_FUNC(e.__class__.__name__, e)
			core.MY_PRINT_FUNC("frame=", z)
			core.MY_PRINT_FUNC("totalframes=", boneframe_ct)
			core.MY_PRINT_FUNC("section=boneframe")
			core.MY_PRINT_FUNC("Err: something went wrong while parsing, file is probably corrupt/malformed")
			raise RuntimeError()
	
	return boneframe_list
Beispiel #4
0
def parse_vmd_camframe(raw: bytearray,
                       moreinfo: bool) -> List[vmdstruct.VmdCamFrame]:
    camframe_list = []
    # is there enough file left to read a single number?
    if (len(raw) - core.get_readfrom_byte()) < struct.calcsize(fmt_number):
        core.MY_PRINT_FUNC(
            "Warning: expected camframe_ct field but file ended unexpectedly! Assuming 0 camframes and continuing..."
        )
        return camframe_list
    ############################
    # get the number of cam frames
    camframe_ct = core.my_unpack(fmt_number, raw)
    if moreinfo:
        core.MY_PRINT_FUNC("...# of camframes           = %d" % camframe_ct)
    for z in range(camframe_ct):
        try:
            # unpack into variables
            (f, d, xp, yp, zp, xr, yr, zr, x_ax, x_bx, x_ay, x_by, y_ax, y_bx,
             y_ay, y_by, z_ax, z_bx, z_ay, z_by, r_ax, r_bx, r_ay, r_by,
             dist_ax, dist_bx, dist_ay, dist_by, ang_ax, ang_bx, ang_ay,
             ang_by, fov, per) = core.my_unpack(fmt_camframe, raw)

            interp_list = [
                x_ax, x_bx, x_ay, x_by, y_ax, y_bx, y_ay, y_by, z_ax, z_bx,
                z_ay, z_by, r_ax, r_bx, r_ay, r_by, dist_ax, dist_bx, dist_ay,
                dist_by, ang_ax, ang_bx, ang_ay, ang_by
            ]
            this_camframe = vmdstruct.VmdCamFrame(
                f=f,
                dist=d,
                pos=[xp, yp, zp],
                rot=[
                    math.degrees(j) for j in (xr, yr, zr)
                ],  # angle comes in as radians, convert radians to degrees
                interp=interp_list,
                fov=fov,
                perspective=per)
            camframe_list.append(this_camframe)
            # display progress printouts
            core.print_progress_oneline(core.get_readfrom_byte() / len(raw))
        except Exception as e:
            core.MY_PRINT_FUNC(e.__class__.__name__, e)
            core.MY_PRINT_FUNC("frame=", z)
            core.MY_PRINT_FUNC("totalframes=", camframe_ct)
            core.MY_PRINT_FUNC("section=camframe")
            core.MY_PRINT_FUNC(
                "Err: something went wrong while parsing, file is probably corrupt/malformed"
            )
            raise RuntimeError()

    return camframe_list
Beispiel #5
0
def parse_vmd_ikdispframe(raw: bytearray,
                          moreinfo: bool) -> List[vmdstruct.VmdIkdispFrame]:
    ikdispframe_list = []
    # is there enough file left to read a single number?
    if (len(raw) - core.get_readfrom_byte()) < struct.calcsize(fmt_number):
        core.MY_PRINT_FUNC(
            "Warning: expected ikdispframe_ct field but file ended unexpectedly! Assuming 0 ikdispframes and continuing..."
        )
        return ikdispframe_list

    ############################
    # if it exists, get the number of ikdisp frames
    ikdispframe_ct = core.my_unpack(fmt_number, raw)
    if moreinfo:
        core.MY_PRINT_FUNC("...# of ik/disp frames      = %d" % ikdispframe_ct)
    for i in range(ikdispframe_ct):
        try:
            (f, disp, numbones) = core.my_unpack(fmt_ikdispframe, raw)
            ikbones = []
            for j in range(numbones):
                (ikname, enable) = core.my_unpack(fmt_ikframe, raw)
                ikbones.append(vmdstruct.VmdIkbone(name=ikname, enable=enable))
            ikdispframe_list.append(
                vmdstruct.VmdIkdispFrame(f=f, disp=disp, ikbones=ikbones))
        except Exception as e:
            core.MY_PRINT_FUNC(e.__class__.__name__, e)
            core.MY_PRINT_FUNC("frame=", i)
            core.MY_PRINT_FUNC("totalframes=", ikdispframe_ct)
            core.MY_PRINT_FUNC("section=ikdispframe")
            core.MY_PRINT_FUNC(
                "Err: something went wrong while parsing, file is probably corrupt/malformed"
            )
            raise RuntimeError()
    return ikdispframe_list
Beispiel #6
0
def parse_vmd_shadowframe(raw: bytearray,
                          moreinfo: bool) -> List[vmdstruct.VmdShadowFrame]:
    shadowframe_list = []
    # is there enough file left to read a single number?
    if (len(raw) - core.get_readfrom_byte()) < struct.calcsize(fmt_number):
        core.MY_PRINT_FUNC(
            "Warning: expected shadowframe_ct field but file ended unexpectedly! Assuming 0 shadowframes and continuing..."
        )
        return shadowframe_list

    ############################
    # if it exists, get the number of shadowframes
    shadowframe_ct = core.my_unpack(fmt_number, raw)
    if moreinfo:
        core.MY_PRINT_FUNC("...# of shadowframes        = %d" % shadowframe_ct)
    for i in range(shadowframe_ct):
        try:
            (f, m, v) = core.my_unpack(fmt_shadowframe, raw)
            v = round(10000 - (v * 100000))
            # stored as 0.0 to 0.1 ??? why would it use this range!? also its range-inverted
            # [0,9999] -> [0.1, 0.0]
            shadowframe_list.append(
                vmdstruct.VmdShadowFrame(f=f, mode=m, val=v))
        except Exception as e:
            core.MY_PRINT_FUNC(e.__class__.__name__, e)
            core.MY_PRINT_FUNC("frame=", i)
            core.MY_PRINT_FUNC("totalframes=", shadowframe_ct)
            core.MY_PRINT_FUNC("section=shadowframe")
            core.MY_PRINT_FUNC(
                "Err: something went wrong while parsing, file is probably corrupt/malformed"
            )
            raise RuntimeError()
    return shadowframe_list
Beispiel #7
0
def parse_vmd_lightframe(raw: bytearray,
                         moreinfo: bool) -> List[vmdstruct.VmdLightFrame]:
    lightframe_list = []
    # is there enough file left to read a single number?
    if (len(raw) - core.get_readfrom_byte()) < struct.calcsize(fmt_number):
        core.MY_PRINT_FUNC(
            "Warning: expected lightframe_ct field but file ended unexpectedly! Assuming 0 lightframes and continuing..."
        )
        return lightframe_list
    ############################
    # if it exists, get the number of lightframes
    lightframe_ct = core.my_unpack(fmt_number, raw)
    if moreinfo:
        core.MY_PRINT_FUNC("...# of lightframes         = %d" % lightframe_ct)
    for i in range(lightframe_ct):
        try:
            (f, r, g, b, x, y, z) = core.my_unpack(fmt_lightframe, raw)
            # the r g b actually come back as floats [0.0-1.0), representing (int)/256, i'll convert them back to ints
            lightframe_list.append(
                vmdstruct.VmdLightFrame(
                    f=f,
                    color=[round(j * 256) for j in (r, g, b)],
                    pos=[x, y, z]))
        except Exception as e:
            core.MY_PRINT_FUNC(e.__class__.__name__, e)
            core.MY_PRINT_FUNC("frame=", i)
            core.MY_PRINT_FUNC("totalframes=", lightframe_ct)
            core.MY_PRINT_FUNC("section=lightframe")
            core.MY_PRINT_FUNC(
                "Err: something went wrong while parsing, file is probably corrupt/malformed"
            )
            raise RuntimeError()

    return lightframe_list