Perfect World Games for noesis
Posted: Tue Oct 29, 2019 10:53 pm
Since this thread has turned into a Perfect world games thread heres a summery of everything found in here:
1.Saint Seiya Online
Support for .ski, .bon, .stck, .mox, .bmd
skinned mesh + animation + static mesh
2.Perfect World
Support for .ski, .bon, .stck, .mox, .bmd
skinned mesh + animation + static mesh
3.Jade Dynasty
Support for .ski, .bon
skinned mesh
4.Forsaken World
Support .ski, .bon, .mox, .bmd (ski works with Perfect World script )
5.Swordsman Online
Support for .ski, .bon
skinned mesh
.........................................................................................................................
Hi,
In order to complete my basic noesis study i started working on a noesis script for .stck animation based of the following topic:
viewtopic.php?f=16&t=11776&hilit=animation#p98283
iv been working on this for the past few days - most of them trying to resolve an issue where my weights were being assigned to the wrong
bone id, had to ditch the .rapi and learn NoeMesh so i could manipulate the data - finally got it fixed. but now i am stuck with the animation part and have some issues i cant seem to resolve.
i tried following both shakotay2 and killercracker script. (also credit to zaramot - used his script to try and t/s my issues)
i am able to get the correct quat and translation vector but for some frames they are not equal, for example frame 8 has 93 translation vectors and 97 rotation quats, so what do i do with the missing translation? does it mean translation for quat is 0?
additionally what is "at time((i-1) * timeMult)"? is this a maxscript thing? or something that is relevant for my understanding of animations?
in shakotay2 script keyframe 200 was used didnt understand what that was for either?
also the line marked in black box - i understand changing numFrames, but what is rotFrames?
thanks in advance
my current noesis script (animation not working)
1.Saint Seiya Online
Support for .ski, .bon, .stck, .mox, .bmd
skinned mesh + animation + static mesh
2.Perfect World
Support for .ski, .bon, .stck, .mox, .bmd
skinned mesh + animation + static mesh
3.Jade Dynasty
Support for .ski, .bon
skinned mesh
4.Forsaken World
Support .ski, .bon, .mox, .bmd (ski works with Perfect World script )
5.Swordsman Online
Support for .ski, .bon
skinned mesh
.........................................................................................................................
Hi,
In order to complete my basic noesis study i started working on a noesis script for .stck animation based of the following topic:
viewtopic.php?f=16&t=11776&hilit=animation#p98283
iv been working on this for the past few days - most of them trying to resolve an issue where my weights were being assigned to the wrong
bone id, had to ditch the .rapi and learn NoeMesh so i could manipulate the data - finally got it fixed. but now i am stuck with the animation part and have some issues i cant seem to resolve.
i tried following both shakotay2 and killercracker script. (also credit to zaramot - used his script to try and t/s my issues)
i am able to get the correct quat and translation vector but for some frames they are not equal, for example frame 8 has 93 translation vectors and 97 rotation quats, so what do i do with the missing translation? does it mean translation for quat is 0?
additionally what is "at time((i-1) * timeMult)"? is this a maxscript thing? or something that is relevant for my understanding of animations?
in shakotay2 script keyframe 200 was used didnt understand what that was for either?
also the line marked in black box - i understand changing numFrames, but what is rotFrames?
thanks in advance
my current noesis script (animation not working)
Code: Select all
from os.path import *
from math import *
from inc_noesis import *
def ReadStringKnown(f, size): # read string of known size
String = []
k = 0
for i in range(size):
num = int(f.readUByte()) # bug reading 31 as ASCII 0 end existing
if (num > 64 and num < 91) or(num > 45 and num < 58) or (num > 96 and num < 123) or num == 95 : #num == 95 add _ charecter
if k == 0:
k += 1
Name = chr(num)
else:
Name = Name + chr(num)
return Name
def registerNoesisTypes():
handle = noesis.register("Perefect World Mesh", ".ski;.bon;.stck")
noesis.setHandlerTypeCheck(handle, noepyCheckType)
noesis.setHandlerLoadModel(handle, noepyLoadModel)
#opens debug consle
noesis.logPopup()
return 1
def noepyCheckType(data):
'''Verify that the format is supported by this plugin. Default yes'''
#I preform my check while reading mesh data
return 1
#load skeleton data
def Skeleton(data):
bones = []
g = NoeBitStream(data, NOE_LITTLEENDIAN)
g.seek(16,1)
BoneCount = g.readUInt()
g.seek(80,1)
####
for i in range(BoneCount):#BoneCount
boneNameLength = g.readUInt()
boneName = ReadStringKnown(g, boneNameLength)
boneID = g.readUInt()
parentID = g.readInt()
siblingID = g.readUInt()
unkcount = g.readUInt()
tfm2 = NoeMat44.fromBytes( g.readBytes(0x40), NOE_LITTLEENDIAN )
tfm = NoeMat44.fromBytes( g.readBytes(0x40), NOE_LITTLEENDIAN )
#boneMat = tfm.toMat43()
boneMat = tfm.toMat43().inverse()
#print("boneMat =", boneMat)
for j in range(unkcount):
g.seek(4,1)
bones.append( NoeBone(i, boneName, boneMat, None, parentID) )
return bones
def animation (data, bones): #def animation (data, bones):
s = 0
BoneMat = []
Rotation_Arr = []
translation_arr = []
anims = []
animFrameMats = []
animName = "test"
animFrameRate = 30
f = NoeBitStream(data, NOE_LITTLEENDIAN)
Magic = ReadStringKnown(f, 8)
print("anim magic")
print(Magic)
unk = f.readUInt()
boneCount = f.readUInt()
f.seek(20,0)
numFrames = f.readUInt()
ukw = f.readUInt()
for i in range (boneCount):
boneID = f.readUInt()
TransCount = f.readUInt() # number of translation vectors
f.seek(8,1)
for k in range(TransCount):
#Tran = NoeVec3.fromBytes(f.readBytes(12))
x = (f.readFloat())
y = (f.readFloat())
z = (f.readFloat())
translation_arr.append((x,y,z))
f.seek(16,1)
RotCount = f.readUInt() # number of quats
f.seek(8,1)
print("TransCount=",TransCount)
print("RotCount=",RotCount)
for j in range(RotCount):
x = f.readFloat()
y = f.readFloat()
z = f.readFloat()
w = f.readFloat()
Rot = NoeQuat((x,y,z,w))
print("quat - original", Rot)
#Rot = Rot.normalize()
#Rotation_Arr.append((x,y,z,w)) #quat(x,y,z,w)
frameMat = Rot.toMat43(transposed = 1)
frameMat = frameMat.inverse()
print("matrix_inverse =",frameMat)
#uat = frameMat.toQuat()
#rint("quat", quat)
frameMat[3] = translation_arr[s]
#if TransCount >= RotCount:
#if s += 1
#print(frameMat)
animFrameMats.append(frameMat)
f.seek(16,1)
#a = f.tell()
#bones must be a list of NoeBone objects, frameMats must be a flat list of NoeMat43 object
if numFrames < TransCount:
numFrames = TransCount
print(numFrames)
print(len(animFrameMats))
anim = NoeAnim(animName, bones, 80, animFrameMats, animFrameRate) #numFrames
anims.append(anim)
return anims
#load mesh data
def Mesh(data, bones):
ctx = rapi.rpgCreateContext()
bs = NoeBitStream(data, NOE_LITTLEENDIAN)
Magic = noeStrFromBytes(bs.readBytes(8), "ASCII")
print(Magic)
if Magic != "MOXBIKSA":
print("worng file format")
unk2 = bs.readInt()
meshCount = bs.readInt()
bs.seek(12,1)
textureCount = bs.readInt()
materialCount = bs.readInt()
mesh_boneCount = bs.readInt()
null = bs.readInt()
ukw4 = bs.readInt()
bs.seek(60,1)
boneName_Arr = []
texName_Arr = []
for l in range(len(bones)):
print(l)
print(bones[l].name)
for i in range(mesh_boneCount):
count = bs.readInt()
boneName_Arr.append(ReadStringKnown(bs, count))
for i in range(textureCount):
count = bs.readInt()
texName_Arr.append(ReadStringKnown(bs, count))
for i in range(materialCount):
bs.seek(80,1)
for i in range(meshCount):
nameLength = bs.readInt()
meshName = ReadStringKnown(bs, nameLength)
matID = bs.readInt()
ukw2 = bs.readInt()
vertCount = bs.readInt()
faceCount = bs.readInt()
Positions = []
PolygonIndex = []
Normals = []
UV =[]
weightList = []
meshes = []
for j in range(vertCount): # vert position
bonesid = []
weights = []
vx = bs.readFloat()
vy = bs.readFloat()
vz = bs.readFloat()
Positions.append(NoeVec3([vx,vy,vz]))
weight1 = bs.readFloat()
weight2 = bs.readFloat()
weight3 = bs.readFloat()
weight4 = 0.0
for i in range(4):
bone = bs.readUByte()
if bone <= len(boneName_Arr):
name = boneName_Arr[bone]
for l in range(len(bones)):
if bones[l].name == name:
index = bones[l].index
break
else:
index = 300
if i == 0:
bone1 = index
if i == 1:
bone2 = index
if i == 2:
bone3 = index
if i == 3:
bone4 = index
if weight1 != 0:
bonesid.append(bone1)
weights.append(weight1)
if weight2 != 0:
bonesid.append(bone2)
weights.append(weight2)
if weight3 != 0:
bonesid.append(bone3)
weights.append(weight3)
if weight4 != 0:
bonesid.append(bone4)
weights.append(weight4)
weightList.append(NoeVertWeight(bonesid,weights))
#print(j)
#print(vx,vy,vz)
#print(bonesid)
#print(weights)
nx = bs.readFloat()
ny = bs.readFloat()
nz = bs.readFloat()
Normals.append(NoeVec3([nx,ny,nz]))
tu = bs.readFloat()
tv = bs.readFloat() * -1
UV.append(NoeVec3([tu,tv,0.0]))
for j in range(0, int(faceCount)): # faces / triangles
PolygonIndex.append(bs.readUShort())
mesh = NoeMesh(PolygonIndex, Positions, meshName)
mesh.setWeights(weightList)
mesh.setNormals(Normals)
mesh.setUVs(UV)
meshes.append(mesh)
return meshes
def noepyLoadModel(data, mdlList):
ctx = rapi.rpgCreateContext()
skel_data = rapi.loadPairedFile("skel_file- 1", ".bon")
mesh_data = rapi.loadPairedFile("mesh_file- 2", ".ski")
try:
anim_data = rapi.loadPairedFile("anim_file - 3", ".stck")
except:
pass
bones = Skeleton(skel_data) # get skeleton data
anims = animation(anim_data, bones)
#print(anims)
#print(anims[0].bones)
#print(anims[0].name)
#print(anims[0].numFrames)
#print(anims[0].frameMats)
#print(len((anims[0].frameMats)))
meshes = Mesh(mesh_data, bones) # need to edit bone id index
mdl = NoeModel(meshes)
mdl.setBones(bones)
mdl.setAnims(anims)
mdlList.append(mdl)
rapi.rpgClearBufferBinds()
return 1


