Important information: this site is currently scheduled to go offline indefinitely by end of the year.
[HELP] Get Bone and Animation for model
- shakotay2
- MEGAVETERAN
- Posts: 4284
- Joined: Fri Apr 20, 2012 9:24 am
- Location: Nexus, searching for Jim Kirk
- Has thanked: 1147 times
- Been thanked: 2242 times
Re: [HELP] Get Bone and Animation for model
Maybe it's a problem with the null (or root) bone's translation? I had a similar problem here when the indian's legs were moved by rotation only:
viewtopic.php?f=16&t=12979&p=107315&hil ... im#p107315
After fixing he proceeded correctly but I don't have the time to check the details again.
quote "So we would need the translation values/bones' positions for the initial pose, apply them once at animation startup then play rotations only."
(Well, this was easy because it were ASCII files, iirc. Would be hard to do it with binary ani files.)
viewtopic.php?f=16&t=12979&p=107315&hil ... im#p107315
After fixing he proceeded correctly but I don't have the time to check the details again.
quote "So we would need the translation values/bones' positions for the initial pose, apply them once at animation startup then play rotations only."
(Well, this was easy because it were ASCII files, iirc. Would be hard to do it with binary ani files.)
Tuts: a) Bigchillghost, viewtopic.php?f=29&t=17889
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
-
- advanced
- Posts: 53
- Joined: Tue Jun 26, 2018 10:03 am
- Has thanked: 2 times
- Been thanked: 1 time
Re: [HELP] Get Bone and Animation for model
shakotay2 wrote:Maybe it's a problem with the null (or root) bone's translation? I had a similar problem here when the indian's legs were moved by rotation only:
viewtopic.php?f=16&t=12979&p=107315&hil ... im#p107315
After fixing he proceeded correctly but I don't have the time to check the details again.
quote "So we would need the translation values/bones' positions for the initial pose, apply them once at animation startup then play rotations only."
(Well, this was easy because it were ASCII files, iirc. Would be hard to do it with binary ani files.)
Root bone is Bip01 or Scene Root?
- shakotay2
- MEGAVETERAN
- Posts: 4284
- Joined: Fri Apr 20, 2012 9:24 am
- Location: Nexus, searching for Jim Kirk
- Has thanked: 1147 times
- Been thanked: 2242 times
Re: [HELP] Get Bone and Animation for model
"Scene Root" obviously. This seems a little bit strange to me: we don't have any bone with Scene Root as a parent in the smd (from Noesis smd export).
It should read 14 "Bip01 Pelvis" 0, shouldn't it?
In the bone.txt file created by the script it reads:
0: Bip01, p Scene Root
14: Bip01 Pelvis, p Bip01
So looks ok to me.
It should read 14 "Bip01 Pelvis" 0, shouldn't it?
Code: Select all
nodes
0 "Scene Root" -1
1 "Bip01 Footsteps" -1
2 "Bip01 Head" 13
3 "Bip01 L Calf" 10
4 "Bip01 L Clavicle" 13
5 "Bip01 L Finger0" 8
6 "Bip01 L Foot" 9
7 "Bip01 L Forearm" 12
8 "Bip01 L Hand" 7
9 "Bip01 L HorseLink" 3
10 "Bip01 L Thigh" 26
11 "Bip01 L Toe0" 6
12 "Bip01 L UpperArm" 4
13 "Bip01 Neck" 27
14 "Bip01 Pelvis" -1
15 "Bip01 Ponytail1" 2
16 "Bip01 R Calf" 23
17 "Bip01 R Clavicle" 13
18 "Bip01 R Finger0" 21
19 "Bip01 R Foot" 22
20 "Bip01 R Forearm" 25
21 "Bip01 R Hand" 20
22 "Bip01 R HorseLink" 16
23 "Bip01 R Thigh" 26
24 "Bip01 R Toe0" 19
25 "Bip01 R UpperArm" 17
26 "Bip01 Spine" 14
27 "Bip01 Spine1" 26
28 "Bip01 Tail" 26
29 "Bip01 Tail1" 28
30 "Bip01 Tail2" 29
end
0: Bip01, p Scene Root
14: Bip01 Pelvis, p Bip01
So looks ok to me.
Tuts: a) Bigchillghost, viewtopic.php?f=29&t=17889
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
-
- advanced
- Posts: 53
- Joined: Tue Jun 26, 2018 10:03 am
- Has thanked: 2 times
- Been thanked: 1 time
Re: [HELP] Get Bone and Animation for model
shakotay2 wrote:"Scene Root" obviously. This seems a little bit strange to me: we don't have any bone with Scene Root as a parent in the smd (from Noesis smd export).
It should read 14 "Bip01 Pelvis" 0, shouldn't it?In the bone.txt file created by the script it reads:Code: Select all
nodes 0 "Scene Root" -1 1 "Bip01 Footsteps" -1 2 "Bip01 Head" 13 3 "Bip01 L Calf" 10 4 "Bip01 L Clavicle" 13 5 "Bip01 L Finger0" 8 6 "Bip01 L Foot" 9 7 "Bip01 L Forearm" 12 8 "Bip01 L Hand" 7 9 "Bip01 L HorseLink" 3 10 "Bip01 L Thigh" 26 11 "Bip01 L Toe0" 6 12 "Bip01 L UpperArm" 4 13 "Bip01 Neck" 27 14 "Bip01 Pelvis" -1 15 "Bip01 Ponytail1" 2 16 "Bip01 R Calf" 23 17 "Bip01 R Clavicle" 13 18 "Bip01 R Finger0" 21 19 "Bip01 R Foot" 22 20 "Bip01 R Forearm" 25 21 "Bip01 R Hand" 20 22 "Bip01 R HorseLink" 16 23 "Bip01 R Thigh" 26 24 "Bip01 R Toe0" 19 25 "Bip01 R UpperArm" 17 26 "Bip01 Spine" 14 27 "Bip01 Spine1" 26 28 "Bip01 Tail" 26 29 "Bip01 Tail1" 28 30 "Bip01 Tail2" 29 end
0: Bip01, p Scene Root
14: Bip01 Pelvis, p Bip01
So looks ok to me.
--> Something is wrong in code.. let me check again.It should like you wrote14 "Bip01 Pelvis" -1
So we should remove "Scene Root"?
- shakotay2
- MEGAVETERAN
- Posts: 4284
- Joined: Fri Apr 20, 2012 9:24 am
- Location: Nexus, searching for Jim Kirk
- Has thanked: 1147 times
- Been thanked: 2242 times
Re: [HELP] Get Bone and Animation for model
I wouldn't say so; in the bone.txt file Scene Root is the parent of Bip01 and Bip01 is the parent of Pelvis.
Question is why the node "Bip01" doesn't appear in the smd file.
Question is why the node "Bip01" doesn't appear in the smd file.
Tuts: a) Bigchillghost, viewtopic.php?f=29&t=17889
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
- shakotay2
- MEGAVETERAN
- Posts: 4284
- Joined: Fri Apr 20, 2012 9:24 am
- Location: Nexus, searching for Jim Kirk
- Has thanked: 1147 times
- Been thanked: 2242 times
Re: [HELP] Get Bone and Animation for model
The node Scene Root is missing in your bone.txt file.
Usually first node should read like so: 0 "Bip01" -1
In the smd created by Noesis the -1 is in the last node; could work but not sure:
Usually first node should read like so: 0 "Bip01" -1
In the smd created by Noesis the -1 is in the last node; could work but not sure:
Code: Select all
version 1
nodes
0 "Bip01" 31
1 "Bip01 Footsteps" 0
2 "Bip01 Head" 13
3 "Bip01 L Calf" 10
4 "Bip01 L Clavicle" 13
5 "Bip01 L Finger0" 8
6 "Bip01 L Foot" 9
7 "Bip01 L Forearm" 12
8 "Bip01 L Hand" 7
9 "Bip01 L HorseLink" 3
10 "Bip01 L Thigh" 26
11 "Bip01 L Toe0" 6
12 "Bip01 L UpperArm" 4
13 "Bip01 Neck" 27
14 "Bip01 Pelvis" 0
15 "Bip01 Ponytail1" 2
16 "Bip01 R Calf" 23
17 "Bip01 R Clavicle" 13
18 "Bip01 R Finger0" 21
19 "Bip01 R Foot" 22
20 "Bip01 R Forearm" 25
21 "Bip01 R Hand" 20
22 "Bip01 R HorseLink" 16
23 "Bip01 R Thigh" 26
24 "Bip01 R Toe0" 19
25 "Bip01 R UpperArm" 17
26 "Bip01 Spine" 14
27 "Bip01 Spine1" 26
28 "Bip01 Tail" 26
29 "Bip01 Tail1" 28
30 "Bip01 Tail2" 29
31 "Scene Root" -1
end
Tuts: a) Bigchillghost, viewtopic.php?f=29&t=17889
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
b) Extracting simple models: http://forum.xentax.com/viewtopic.php?f=29&t=10894
"Quoting the whole thing. Would u ever stop this nonsense?"
-
- advanced
- Posts: 53
- Joined: Tue Jun 26, 2018 10:03 am
- Has thanked: 2 times
- Been thanked: 1 time
Re: [HELP] Get Bone and Animation for model
So I should remove Scene Root out bone list and make Bip01 has parent index is -1?shakotay2 wrote:The node Scene Root is missing in your bone.txt file.
Usually first node should read like so: 0 "Bip01" -1
In the smd created by Noesis the -1 is in the last node; could work but not sure:Code: Select all
version 1 nodes 0 "Bip01" 31 1 "Bip01 Footsteps" 0 2 "Bip01 Head" 13 3 "Bip01 L Calf" 10 4 "Bip01 L Clavicle" 13 5 "Bip01 L Finger0" 8 6 "Bip01 L Foot" 9 7 "Bip01 L Forearm" 12 8 "Bip01 L Hand" 7 9 "Bip01 L HorseLink" 3 10 "Bip01 L Thigh" 26 11 "Bip01 L Toe0" 6 12 "Bip01 L UpperArm" 4 13 "Bip01 Neck" 27 14 "Bip01 Pelvis" 0 15 "Bip01 Ponytail1" 2 16 "Bip01 R Calf" 23 17 "Bip01 R Clavicle" 13 18 "Bip01 R Finger0" 21 19 "Bip01 R Foot" 22 20 "Bip01 R Forearm" 25 21 "Bip01 R Hand" 20 22 "Bip01 R HorseLink" 16 23 "Bip01 R Thigh" 26 24 "Bip01 R Toe0" 19 25 "Bip01 R UpperArm" 17 26 "Bip01 Spine" 14 27 "Bip01 Spine1" 26 28 "Bip01 Tail" 26 29 "Bip01 Tail1" 28 30 "Bip01 Tail2" 29 31 "Scene Root" -1 end
-
- advanced
- Posts: 53
- Joined: Tue Jun 26, 2018 10:03 am
- Has thanked: 2 times
- Been thanked: 1 time
Re: [HELP][Scion of Fate] Get Bone and Animation for model
I re-post full script here.Currently the script can parse SKIN, BON and Animation but the animation still not right (rotation is good but the translation is fail..the mesh can move forward but floating little up and down)
Sample data: ( A Monster Cat in game)
Sample data 2: https://1drv.ms/u/s!AtK3xgihMkhwhI5X4qoASMisva14PQ (Blacksmith)
Blacksmith's IDLE animation demo: https://www.youtube.com/watch?v=AEAQaz0KKWo
Current problem is the translation animation (Mesh floating up and down a little)
Code: Select all
# Noesis Python model import+export test module, imports/exports some data from/to a made-up format
from os.path import *
from math import *
from inc_noesis import *
MAIN_BON_FILE_NAME = ""
ROOT_DIR = ""
FILE_BON_PATH = ""
ROOT_DIR = dirname(dirname(dirname(abspath(__file__))))
FILE_BON_PATH = ROOT_DIR + "\\YulgangVN\\Bones\\"
MESH_LIST = []
BONE_LIST = []
ANI_LIST = []
# registerNoesisTypes is called by Noesis to allow the script to register formats.
# Do not implement this function in script files unless you want them to be dedicated format modules!
def registerNoesisTypes():
handle = noesis.register("YulgangVN - SKIN", ".skin;.bon;.ani")
noesis.setHandlerTypeCheck(handle, checkSkinType)
noesis.setHandlerLoadModel(handle, checkSkinLoad)
# noesis.setHandlerWriteModel(handle, noepyWriteModel)
# noesis.setHandlerWriteAnim(handle, noepyWriteAnim)
noesis.logPopup()
# print("The log can be useful for catching debug prints from preview loads.\nBut don't leave it on when you release your script, or it will probably annoy people.")
return 1
# check if it's this type based on the data
def checkSkinType(data):
if len(data) < 16:
return 0
return 1
# load the model
def checkSkinLoad(data, mdlList):
global MESH_LIST
global BONE_LIST
global ANI_LIST
ctx = rapi.rpgCreateContext()
filePath = rapi.getInputName() # get file path
fileExt = filePath.split('.')[-1] # get file extesion
boneData = rapi.loadPairedFile("YulgangVN - BON", ".bon")
aniData = rapi.loadPairedFile("YulgangVN - Ani", ".ani")
# create parser
yulgangParser = YulgangParser(data, boneData, aniData, fileExt)
MESH_LIST = yulgangParser.parseSkin()
BONE_LIST = yulgangParser.parseBon()
ANI_LIST = yulgangParser.parseAni()
mdl = NoeModel(MESH_LIST, BONE_LIST, ANI_LIST)
# important, don't forget to put your loaded model in the mdlList
mdlList.append(mdl)
return 1
def normalize(v, tolerance=0.0001):
mag2 = sum(n * n for n in v)
# print(mag2)
if mag2 != 0.0:
if abs(mag2 - 1.0) > tolerance:
mag = sqrt(mag2)
v = tuple(n / mag for n in v)
return v
def axisangle_to_q(v, theta):
v = normalize(v)
x, y, z = v
theta /= 2
w = cos(theta)
x = x * sin(theta)
y = y * sin(theta)
z = z * sin(theta)
return x, y, z, w
class YulgangParser(object):
def __init__(self, skinData, boneData, aniData, fileExt=""):
self.skinStream = NoeBitStream(skinData)
self.bonStream = NoeBitStream(boneData)
self.aniStream = NoeBitStream(aniData)
self.fileExt = fileExt
self.bones = {} # new
return
def parseBon(self):
global BONE_LIST
if self.bonStream is None:
print('Data stream is null')
# MAIN_BON_FILE_NAME = filePath.split('\\')[4]
# boneFile = open(FILE_BON_PATH + 'bone' + ".txt", "w")
boneNameList = [] # create arrray to contain all bone name
boneCount = self.bonStream.readInt() # read bone count
print('Bone Count: ' + str(boneCount))
noeBones = []
for i in range(boneCount):
currentOffset = self.bonStream.tell() # get current offset
boneName = self.bonStream.readString() # read current bone name
boneNameList.append(boneName)
self.bonStream.seek(currentOffset + 50,
NOESEEK_ABS) # seek 50 bytes
bonePName = self.bonStream.readString() # read parent bone name
self.bonStream.seek(currentOffset + 100,
NOESEEK_ABS) # seek 50 bytes
boneMatrix = NoeMat44.fromBytes(
self.bonStream.readBytes(64)).toMat43()
# create NoeBone
noeBone = NoeBone(len(noeBones), boneName,
boneMatrix, bonePName, -1)
# new - it creat dict bonename==> index
self.bones[boneName] = noeBone
noeBones.append(noeBone)
# check if bone doesnt have info from birnary file, create empty infor for it
# e.x: Scene Root
for noeBone in noeBones:
if noeBone.parentName not in boneNameList:
parentBone = NoeBone(
len(noeBones), noeBone.parentName, NoeMat43(), "", -1)
self.bones[parentBone.name] = parentBone
noeBones.append(parentBone) # add to main list
break
# calculate bone parent index
for bone in noeBones:
if bone.parentName in self.bones:
bone.parentIndex = self.bones[bone.parentName].index
# boneFile.write(str(bone.index) + "::" + bone.name + "::" +
# bone.parentName + "::" + str(bone.parentIndex) + "\n") # write to file
# print("Write file " + 'bone' + ".txt success!")
# boneFile.close() # close file
return noeBones
def parseSkin(self):
if self.skinStream is None:
print('Data stream is null')
elif self.fileExt != 'skin':
print('Selected file is not Skin format')
self.skinStream.readUByte() # number of mesh in file
vertexCount = self.skinStream.readInt()
indicesCount = self.skinStream.readInt() * 3
weightCount = self.skinStream.readInt()
materialCount = self.skinStream.readInt()
vertPostList = []
indiceList = []
weights = []
vertUVList = []
skinIdList = []
matList = []
skinWeightList = []
skinIndiceList = []
self.skinStream.readBytes(6 * 4) # unknow
self.skinStream.readBytes(16 * 4) # unknow
self.skinStream.readBytes(16 * 4) # unknow
for i in range(vertexCount):
curOffset = self.skinStream.tell()
vertPostList.append(NoeVec3.fromBytes(
self.skinStream.readBytes(12)))
if weightCount == 1:
seekOffset = curOffset + 36
bwgt = [1.0]
bidx = [self.skinStream.read("B")]
self.skinStream.readUByte()
self.skinStream.readUByte()
self.skinStream.readUByte()
self.skinStream.readBytes(4 * 3)
uv = NoeVec3()
uv.vec3 = self.skinStream.read("ff")+(0,)
vertUVList.append(uv)
elif weightCount == 2:
seekOffset = curOffset + 40
w1 = self.skinStream.readFloat()
w2 = 1.0 - w1
bwgt = [w1, w2]
bidx = self.skinStream.read("BB")
self.skinStream.readUByte()
self.skinStream.readUByte()
self.skinStream.readBytes(4 * 3)
uv = NoeVec3()
uv.vec3 = self.skinStream.read("ff")+(0,)
vertUVList.append(uv)
elif weightCount == 3:
seekOffset = curOffset + 44
w1 = self.skinStream.readFloat()
w2 = self.skinStream.readFloat()
w3 = 1.0 - w1 - w2
bwgt = [w1, w2, w3]
bidx = self.skinStream.read("BBB")
# print(bidx)
self.skinStream.readUByte()
self.skinStream.read("fff")
uv = NoeVec3()
uv.vec3 = self.skinStream.read("ff")+(0,)
vertUVList.append(uv)
elif weightCount == 4:
seekOffset = curOffset + 48
w1 = self.skinStream.readFloat()
w2 = self.skinStream.readFloat()
w3 = self.skinStream.readFloat()
w4 = 1.0 - w1 - w2 - w3
bwgt = [w1, w2, w3, w4]
bidx = self.skinStream.read("BBBB")
self.skinStream.read("fff")
uv = NoeVec3()
uv.vec3 = self.skinStream.read("ff")+(0,)
vertUVList.append(uv)
# weights.append(NoeVertWeight(bidx, bwgt))
self.skinStream.seek(seekOffset, NOESEEK_ABS)
skinWeightList.append(bwgt)
skinIndiceList.append(bidx)
# read indiceList
for i in range(indicesCount):
indiceList.append(self.skinStream.readShort())
# read matertial list
meshList = []
new = open("log.txt", 'w') # outside Noesis log file
for i in range(materialCount):
weights = []
new.write(str(i)+"\n")
mat = NoeMaterial("", "")
matList.append(mat)
self.skinStream.readInt()
matIDStart = self.skinStream.readInt() * 3
matIDCount = self.skinStream.readInt() * 3
self.skinStream.readInt()
self.skinStream.readInt()
boneMap = self.skinStream.read("28i")
# print(boneMap)
mesh = NoeMesh(indiceList[matIDStart:matIDStart+matIDCount], vertPostList, str(i).zfill(2))
mesh.uvs = vertUVList
# procedure to get correct vertex bone index
newSkinIndiceList = []
for i in range(vertexCount):
newSkinIndiceList.append(skinIndiceList[i])
for idx in indiceList[matIDStart:matIDStart+matIDCount]:
bidx = skinIndiceList[idx]
bwgt = skinWeightList[idx]
newbidx = []
new.write(str(idx)+str(bidx)+str(bwgt)+'\n')
for m in range(len(bidx)):
newbidx.append(boneMap[bidx[m]])
newSkinIndiceList[idx] = newbidx
for i in range(vertexCount):
weights.append(NoeVertWeight(
newSkinIndiceList[i], skinWeightList[i]))
mesh.weights = weights
meshList.append(mesh)
new.close()
return meshList
def parseAni(self):
global BONE_LIST
if self.aniStream is None:
print('Ani stream is null')
return 0
if len(BONE_LIST) == 0:
print('Bone List is empty.Please parse BON first')
return 0
print("bones:", len(self.bones))
animList = []
noeKeyFramedBones = []
self.aniStream.seek(512, NOESEEK_ABS) # ignore 512 bytes
boneCount = self.aniStream.readUByte() # get bone count
curBone = NoeBone(0, "", NoeMat43())
for i in range(boneCount):
currentOffset = self.aniStream.tell()
name = self.aniStream.readString() # read bone name
curBone = self.bones[name] # get bone by name
self.aniStream.seek(currentOffset + 50, NOESEEK_ABS) # seek 50 bytes
# get bone pose matrix
matrix44 = NoeMat44.fromBytes(self.aniStream.readBytes(64)) # .inverse()
# print(matrix44)
matrix43 = matrix44.toMat43()
# print(matrix43)
quatFromMatrix = matrix43.toQuat()
transFromMatrix = matrix43[2]
posNoeKeyFramedValues = [] # array contain list translation
translateFrameCount = self.aniStream.readInt()
for j in range(translateFrameCount):
time = self.aniStream.readInt() / 320.0
xp = self.aniStream.readFloat()
yp = self.aniStream.readFloat()
zp = self.aniStream.readFloat()
if time > 0: # ignroe frame 0
vector = NoeVec3((xp, yp, zp))
transMatrix = transFromMatrix.__mul__(vector)
# print(transMatrix)
posKeyFrameValue = NoeKeyFramedValue(time, vector) # create instance
posNoeKeyFramedValues.append(posKeyFrameValue) # add to list
rotNoeKeyFramedValues = [] # array contain list rotation
rotateFrameCount = self.aniStream.readInt()
for j in range(rotateFrameCount):
rotTime = self.aniStream.readInt() / 320.0
v = self.aniStream.read("3f") # read vector
angle = self.aniStream.read("f")[0] # read angle
# convert vector + angle to QUAT
if rotTime > 0: # ignore frame 0
quat = axisangle_to_q(v, angle)
rotMatrix = NoeQuat()
rotMatrix.quat = quat
rotMatrix = quatFromMatrix.__mul__(rotMatrix)
rotKeyFrameValue = NoeKeyFramedValue(
rotTime, rotMatrix) # create instance
rotNoeKeyFramedValues.append(
rotKeyFrameValue) # add to list
# create NoeKeyFramedBone
if len(self.bones) > 0:
actionBone = NoeKeyFramedBone(self.bones[name].index)
else:
actionBone = NoeKeyFramedBone(curBone.index)
actionBone.setRotation(rotNoeKeyFramedValues,
noesis.NOEKF_ROTATION_QUATERNION_4)
actionBone.setTranslation(
posNoeKeyFramedValues, noesis.NOEKF_TRANSLATION_VECTOR_3)
# add to keyframedBones list
noeKeyFramedBones.append(actionBone)
# create NoeKeyFramedAnim
anim = NoeKeyFramedAnim(
"Animation 1", BONE_LIST, noeKeyFramedBones, 10)
# add to animList
animList.append(anim)
return animList
Sample data 2: https://1drv.ms/u/s!AtK3xgihMkhwhI5X4qoASMisva14PQ (Blacksmith)
Blacksmith's IDLE animation demo: https://www.youtube.com/watch?v=AEAQaz0KKWo
Current problem is the translation animation (Mesh floating up and down a little)
You do not have the required permissions to view the files attached to this post.