the stride was 1 byte off and the submesh headers had an extra 2 bytes in the last 2 samples.
The Forum is up for sale: XeNTaX Forum looking for new owner
Sudden Attack - Noesis Script Creation
-
Acewell
- VIP member

- Posts: 1330
- Joined: Wed Nov 05, 2008 12:16 pm
- Has thanked: 2710 times
- Been thanked: 883 times
Re: Sudden Attack - Noesis Script Creation
okay i updated the script with a quick fix, it may or may not break other models, if it does just comment out lines 34-37 and shift+tab line 38.
the stride was 1 byte off and the submesh headers had an extra 2 bytes in the last 2 samples.
the stride was 1 byte off and the submesh headers had an extra 2 bytes in the last 2 samples.
Last edited by Acewell on Sun Mar 19, 2017 7:43 pm, edited 1 time in total.
Re: Sudden Attack - Noesis Script Creation
QuickBMS can not extract .rezshakotay2 wrote:Is #rapi.rpgBindUV1BufferOfs() still commented out in your code?
delete the # then (which disables the line from being "executed", so it's just a comment)
I'd suggest to read chrrox' Noesis tutorial to gain more understanding
otherwise you'll fall from one trouble into the other, I guess.
did you follow mariokart64n's tutorial?
" msh.setIndices(ltb.faceArray)"
" msh.setPositions(ltb.vertArray)"
is a little bit uncommon to me (doesn't seem to be part of the rapi.rpg interface)
You might be required to use self.setUVs([]) to get the uvs.
-
Xr79
- veteran
- Posts: 91
- Joined: Sat Oct 05, 2013 11:45 pm
- Has thanked: 19 times
- Been thanked: 3 times
Re: Sudden Attack - Noesis Script Creation
Hey Acewell, I know this is an old post, I wanted to thank you for your work on the script! seriously it's awesome, there are Kpop stars in the sudden attack files and I really wanted to get the models.
but I've run into a bit of a problem. I followed your directions on commenting your script and then none of the models will open, the script compiles and works but none of the models open any more. are you sure you got the right lines to comment out there?
here is an example of one of the files that does not work with your script.
i managed to get all the files from the game even tho it's shut down for some reason you can download it on the korean site.
thank you in advance if you can offer any help with this.
-
Acewell
- VIP member

- Posts: 1330
- Joined: Wed Nov 05, 2008 12:16 pm
- Has thanked: 2710 times
- Been thanked: 883 times
Re: Sudden Attack - Noesis Script Creation
that is a question you should probably ask yourself.
i can't see invisible samples, maybe you forgot to link it?here is an example of one of the files that does not work with your script.
i don't really think there is much more i can do with this game model format.
i don't do much with model scripts any more anyway because i have
a large backlog of texture samples from many other topics to examine
and i plan to get most of them out of the way this year.
-
Xr79
- veteran
- Posts: 91
- Joined: Sat Oct 05, 2013 11:45 pm
- Has thanked: 19 times
- Been thanked: 3 times
Re: Sudden Attack - Noesis Script Creation
If I'm being honest I wasn't expecting you to take the time to message me back, I thought it was just a shot in the dark. there was a problem sharing the sample, it's to big and all my online store are full right now.Acewell wrote: ↑Mon Feb 25, 2019 8:44 amthat is a question you should probably ask yourself.![]()
i can't see invisible samples, maybe you forgot to link it?here is an example of one of the files that does not work with your script.
i don't really think there is much more i can do with this game model format.
i don't do much with model scripts any more anyway because i have
a large backlog of texture samples from many other topics to examine
and i plan to get most of them out of the way this year.![]()
but maybe you could show what lines to comment out? I did 34-37 and shift tabbed 38 like you said to, but it didn't work. I use note pad ++
34 if vertex_stride == 31:
35 vertex_stride = 32
36 bs.seek(0x18, NOESEEK_REL)
37 else:
38 bs.seek(0x16, NOESEEK_REL)
-
Acewell
- VIP member

- Posts: 1330
- Joined: Wed Nov 05, 2008 12:16 pm
- Has thanked: 2710 times
- Been thanked: 883 times
Re: Sudden Attack - Noesis Script Creation
yes those are the correct lines.
when i say comment them they will result to look like this:
the indent of line 38 is critical, this might be where it breaks for you.
line 38 should be indented the same as line 33.
if it still doesn't work with your sample then it just doesn't work.
there is no guarantee the script works with all game samples.
when i say comment them they will result to look like this:
Code: Select all
# if vertex_stride == 31:
# vertex_stride = 32
# bs.seek(0x18, NOESEEK_REL)
# else:
bs.seek(0x16, NOESEEK_REL)line 38 should be indented the same as line 33.
if it still doesn't work with your sample then it just doesn't work.
there is no guarantee the script works with all game samples.
-
mariokart64n
- ultra-veteran

- Posts: 585
- Joined: Sun Jun 05, 2005 12:00 pm
- Location: Ontario, Canada
- Has thanked: 36 times
- Been thanked: 240 times
Re: Sudden Attack - Noesis Script Creation
I was contacted about adding bone and weight support for the Noesis python plugin for sudden attack.
I started by examining my old python script, and any other scripts written by others to determine if my involvement was required.
From what I discovered there are many scripts from several people; me, TRDaz, Acewell, finale00, zaramot, shakotay2, and possibly more in circulation
All of the previous scripts suffer from a range of problems;
- Incomplete Parsing of the file Header (Address of vertex buffer sometimes incorrect)
- Incomplete Reading of the vertex data (Doesn't read the bones or the weights)
- Lack of Vertex Type detection (resulted in many 'variant' versions of the scripts to work with each ltb model.)
As far as I understand .ltb likely stands for "Lith Tech Binary" and is used in a wide range of games using the LithTech Engine including the LithTech Jupiter Engine.
Technically this Topic for "Sudden Attack" should belong in this other Topic discussing and dealing with Lith Tech Engine models in general
viewtopic.php?f=16&t=7230
However the samples that were provided to me were exclusively from Sudden Attack so i will drop my update here;
This is a Noesis Python Plugin for Sudden Attack
(has also been tested with the samples posted in this Topic by others)
Supports:
- Improved Reading and detection of file header and vertex definitions
- Mesh, Bones, Weights
Not Supported
-Materials
***see dtx script to unpack textures: viewtopic.php?p=164339#p164339

I started by examining my old python script, and any other scripts written by others to determine if my involvement was required.
From what I discovered there are many scripts from several people; me, TRDaz, Acewell, finale00, zaramot, shakotay2, and possibly more in circulation
All of the previous scripts suffer from a range of problems;
- Incomplete Parsing of the file Header (Address of vertex buffer sometimes incorrect)
- Incomplete Reading of the vertex data (Doesn't read the bones or the weights)
- Lack of Vertex Type detection (resulted in many 'variant' versions of the scripts to work with each ltb model.)
As far as I understand .ltb likely stands for "Lith Tech Binary" and is used in a wide range of games using the LithTech Engine including the LithTech Jupiter Engine.
Technically this Topic for "Sudden Attack" should belong in this other Topic discussing and dealing with Lith Tech Engine models in general
viewtopic.php?f=16&t=7230
However the samples that were provided to me were exclusively from Sudden Attack so i will drop my update here;
This is a Noesis Python Plugin for Sudden Attack
(has also been tested with the samples posted in this Topic by others)
Supports:
- Improved Reading and detection of file header and vertex definitions
- Mesh, Bones, Weights
Not Supported
-Materials
***see dtx script to unpack textures: viewtopic.php?p=164339#p164339

Code: Select all
# Python Script Plugin for Noesis
#
# Read Mesh from Lith Tech Binary
#
# Author: mariokart64n
# Date: June 20 2020
# Source: https://forum.xentax.com/viewtopic.php?f=16&t=15997
#
showConsole = False
NOEPY_HEADER = 0x00090001 # LTB
from inc_noesis import *
class ltb_unk032: # 112bytes
name_length = 0
name = ""
unk100 = 0
unk101 = 0.0
unk102 = 0.0
unk103 = 0.0
unk104 = 0.0
unk105 = 0.0
unk106 = 0.0
unk107 = 0.0
unk108 = 0.0
unk109 = 0.0
unk110 = 0.0
unk111 = 0.0
unk112 = 0.0
unk113 = 0.0
unk114 = 0.0
unk115 = 0.0
unk116 = 0.0
unk117 = 0.0
unk118 = 0.0
unk119 = 0.0
unk120 = 0.0
unk121 = 0.0
unk122 = 0.0
unk123 = 0.0
unk124 = 0.0
unk125 = 0.0
unk126 = 0.0
unk127 = 0.0
def read_unk032(self, f=NoeBitStream()):
self.name_length = f.readUShort()
self.name = f.readBytes(name_length).decode("UTF-8").rstrip("\0")
self.unk100 = f.readUInt()
self.unk101 = f.readFloat()
self.unk102 = f.readFloat()
self.unk103 = f.readFloat()
self.unk104 = f.readFloat()
self.unk105 = f.readFloat()
self.unk106 = f.readFloat()
self.unk107 = f.readFloat()
self.unk108 = f.readFloat()
self.unk109 = f.readFloat()
self.unk110 = f.readFloat()
self.unk111 = f.readFloat()
self.unk112 = f.readFloat()
self.unk113 = f.readFloat()
self.unk114 = f.readFloat()
self.unk115 = f.readFloat()
self.unk116 = f.readFloat()
self.unk117 = f.readFloat()
self.unk118 = f.readFloat()
self.unk119 = f.readFloat()
self.unk120 = f.readFloat()
self.unk121 = f.readFloat()
self.unk122 = f.readFloat()
self.unk123 = f.readFloat()
self.unk124 = f.readFloat()
self.unk125 = f.readFloat()
self.unk126 = f.readFloat()
self.unk127 = f.readFloat()
class ltb_node:
node_name_length = 0
node_name = ""
index = 0
unk091 = 0
unk092 = 0
matrix = []
childCount = 0
children = []
parent = -1
def read_node(self, f=NoeBitStream()):
self.node_name_length = f.readUShort()
self.node_name = f.readBytes(self.node_name_length).decode("UTF-8").rstrip("\0")
self.index = f.readUByte()
self.unk091 = f.readUByte()
self.unk092 = f.readUByte()
self.matrix = [
f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat(),
f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat(),
f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat(),
f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
]
self.childCount = f.readUInt()
class ltb_vert:
position = []
normal = []
weights = []
texcoord = []
binormal = []
tangent = []
class ltb_unk061:
vert_pos = 0
vert_count = 0
unk072 = 0 # 4 bone indices
unk073 = 0
unk074 = 0
unk075 = 0
face_count = 0 # 3 times face count?
def read_unk061(self, f=NoeBitStream()):
self.vert_pos = f.readUShort()
self.vert_count = f.readUShort()
self.unk072 = f.readUByte()
self.unk073 = f.readUByte()
self.unk074 = f.readUByte()
self.unk075 = f.readUByte()
if self.unk072 == 0xFF:
self.unk072 = 0
if self.unk073 == 0xFF:
self.unk073 = 0
if self.unk074 == 0xFF:
self.unk074 = 0
if self.unk075 == 0xFF:
self.unk075 = 0
self.face_count = f.readUInt()
class ltb_geo:
unk038 = 0
unk039 = 0
unk041 = 0
unk042 = 0
unk043 = 0
unk044 = 0
unk045 = 0
unk046 = 0
unk047 = 0 # addr to small table
vertex_count = 0
face_count = 0
unk050 = 0 # Vertex Format?
unk040 = 0 # Vertex Format?
unk051 = []
unk052 = 0
unk053 = 0
unk054 = 0
unk055 = 0
unk056 = 0
unk057 = 0
verts = ltb_vert()
faces = []
unk060 = 0 # mesh table? or bone palette?
unk061 = [] # mesh table? or bone palette?
unk062 = 0
unk063 = []
def guessTableAddr(self, limit, faceCount, f=NoeBitStream()):
pos = f.tell()
c = 0
i = 1
p = ltb_unk061()
c = pos
stop = False
f.seek(-4, NOESEEK_REL)
if f.readUInt() > 0:
while i < limit and stop == False:
f.seek((pos - (i * 0x0C) - 0x04), NOESEEK_ABS)
if f.readUInt() == i:
p.read_unk061(f)
if p.face_count <= faceCount:
c = f.tell() - 0x10
stop = True
i = i + 1
f.seek(pos, NOESEEK_ABS)
return c
def read_geo(self, f=NoeBitStream()):
i = 1
ii = 1
self.verts = ltb_vert()
weight = []
boneid = []
vertex_addr = 0
vertex_stride = 0
unk040_addr = 0
unk60_addr = 0
self.unk038 = f.readUInt()
self.unk039 = f.readUInt()
self.unk041 = f.readUInt()
self.unk042 = f.readUInt()
self.unk043 = f.readUInt()
self.unk044 = f.readUInt()
self.unk045 = f.readUByte()
self.unk046 = f.readUInt()
self.unk047 = f.readUInt()
unk040_addr = f.tell() + self.unk047
self.vertex_count = f.readUInt()
self.face_count = f.readUInt()
self.unk050 = f.readUInt()
self.unk040 = f.readUByte()
if self.unk040 > 0:
self.unk051 = [int] * self.unk040
for i in range(0, self.unk040):
self.unk051[i] = f.readUByte()
self.unk052 = f.readUShort()
self.unk053 = f.readUShort()
self.unk054 = f.readUShort()
self.unk055 = f.readUInt()
self.unk056 = f.readUInt()
self.unk057 = f.readUInt()
vertex_addr = f.tell()
f.seek(unk040_addr, NOESEEK_ABS)
unk60_addr = self.guessTableAddr(((unk040_addr - vertex_addr) / 12), (self.face_count * 3), f)
vertex_stride = int((unk60_addr - vertex_addr - (self.face_count * 6)) / self.vertex_count)
vertex_stride += int((2 - (vertex_stride % 2)) % 2)
vertex_addr = unk60_addr - (self.face_count * 6) - (self.vertex_count * vertex_stride)
if self.vertex_count > 0:
self.verts.position = [NoeVec3] * self.vertex_count
self.verts.weights = [NoeVertWeight] * self.vertex_count
self.verts.normal = [NoeVec3] * self.vertex_count
self.verts.texcoord = [NoeVec3] * self.vertex_count
self.verts.binormal = [NoeVec3] * self.vertex_count
self.verts.tangent = [NoeVec3] * self.vertex_count
for i in range(0, self.vertex_count):
f.seek((vertex_addr + (i * vertex_stride)), NOESEEK_ABS)
self.verts.position[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.normal[i] = NoeVec3((0.0, 0.0, 0.0))
self.verts.texcoord[i] = NoeVec3((0.0, 0.0, 0.0))
self.verts.binormal[i] = NoeVec3((0.0, 0.0, 0.0))
self.verts.tangent[i] = NoeVec3((0.0, 0.0, 0.0))
weight = [1.0, 0.0, 0.0, 0.0]
boneid = [0, 0, 0, 0]
if vertex_stride == 32:
self.verts.normal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.texcoord[i] = NoeVec3((f.readFloat(), 1.0 - f.readFloat(), 0))
elif vertex_stride == 36:
weight = [f.readFloat(), 0.0, 0.0, 0.0]
weight[1] = 1.0 - weight[0]
self.verts.normal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.texcoord[i] = NoeVec3((f.readFloat(), 1.0 - f.readFloat(), 0))
elif vertex_stride == 40:
weight = [f.readFloat(), f.readFloat(), 0.0, 0.0]
weight[2] = 1.0 - (weight[0] + weight[1])
self.verts.normal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.texcoord[i] = NoeVec3((f.readFloat(), 1.0 - f.readFloat(), 0))
elif vertex_stride == 44:
weight = [f.readFloat(), f.readFloat(), f.readFloat(), 0.0]
weight[3] = 1.0 - (weight[0] + weight[1] + weight[2])
self.verts.normal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.texcoord[i] = NoeVec3((f.readFloat(), 1.0 - f.readFloat(), 0))
elif vertex_stride == 56:
self.verts.normal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.texcoord[i] = NoeVec3((f.readFloat(), 1.0 - f.readFloat(), 0))
self.verts.binormal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.tangent[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
elif vertex_stride == 60:
weight = [f.readFloat(), 0.0, 0.0, 0.0]
weight[1] = 1.0 - weight[0]
self.verts.normal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.texcoord[i] = NoeVec3((f.readFloat(), 1.0 - f.readFloat(), 0))
self.verts.binormal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.tangent[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
elif vertex_stride == 64:
weight = [f.readFloat(), f.readFloat(), 0.0, 0.0]
weight[2] = 1.0 - (weight[0] + weight[1])
self.verts.normal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.texcoord[i] = NoeVec3((f.readFloat(), 1.0 - f.readFloat(), 0))
self.verts.binormal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.tangent[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
elif vertex_stride == 68:
weight = [f.readFloat(), f.readFloat(), f.readFloat(), 0.0]
weight[3] = 1.0 - (weight[0] + weight[1] + weight[2])
self.verts.normal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.texcoord[i] = NoeVec3((f.readFloat(), 1.0 - f.readFloat(), 0))
self.verts.binormal[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.tangent[i] = NoeVec3((f.readFloat(), f.readFloat(), f.readFloat()))
self.verts.weights[i] = NoeVertWeight(boneid, weight)
f.seek((vertex_addr + (self.vertex_count * vertex_stride)), NOESEEK_ABS)
if self.face_count > 0:
self.faces = [int] * (self.face_count * 3)
for i in range(0, self.face_count * 3):
self.faces[i] = f.readUShort()
if unk60_addr < unk040_addr:
f.seek(unk60_addr, NOESEEK_ABS)
self.unk060 = f.readUInt()
if self.unk060 > 0:
self.unk061 = [ltb_unk061] * self.unk060
for i in range(0, self.unk060):
self.unk061[i] = ltb_unk061()
self.unk061[i].read_unk061(f)
for ii in range(0, self.unk061[i].vert_count):
self.verts.weights[ii + self.unk061[i].vert_pos].indices = [self.unk061[i].unk072, self.unk061[i].unk073, self.unk061[i].unk074, self.unk061[i].unk075]
if self.unk047 > 0:
f.seek(unk040_addr, NOESEEK_ABS)
self.unk062 = f.readUByte()
self.unk063 = [int] * self.unk062
for i in range(0, self.unk062):
self.unk063[i] = f.readUByte()
class ltb_mesh:
mesh_name_length = 0
mesh_name = ""
lod_count = 0
unk031 = []
unk036 = 0
unk037 = 0
lods = []
def read_mesh(self, f=NoeBitStream()):
i = 1
m = 1
self.mesh_name_length = f.readUShort()
self.mesh_name = f.readBytes(self.mesh_name_length).decode("UTF-8").rstrip("\0")
self.lod_count = f.readUInt()
if self.lod_count > 0:
self.unk031 = [float] * self.lod_count
for i in range(0, self.lod_count):
self.unk031[i] = f.readFloat()
self.unk036 = f.readUInt()
self.unk037 = f.readUInt()
self.lods = [ltb_geo] * self.lod_count
for m in range(0, self.lod_count):
self.lods[m] = ltb_geo()
self.lods[m].read_geo(f)
class ltb_file:
unk001 = 0
unk002 = 0
unk003 = 0
unk004 = 0
unk005 = 0
unk006 = 0
unk007 = 0
unk008 = 0
unk009 = 0
node_count = 0
mesh_count = 0
unk012 = 0
total_face_count = 0
unk014 = 0
unk015 = 0
total_lod_count = 0
unk017 = 0
unk018 = 0
unk019 = 0
unk020 = 0
unk021 = 0
unk022 = 0
unk057 = 0
unk058 = ""
unk023 = 0.0
unk024 = 0
unk025 = []
unk026 = 0
unk027 = 0
meshs = []
nodes = []
def read_ltb(self, f=NoeBitStream()):
i = 1
ii = 1
self.unk001 = f.readUShort()
self.unk002 = f.readUShort()
self.unk003 = f.readUInt()
self.unk004 = f.readUInt()
self.unk005 = f.readUInt()
self.unk006 = f.readUInt()
self.unk007 = f.readUInt()
self.unk008 = f.readUInt()
self.unk009 = f.readUInt()
self.node_count = f.readUInt()
self.mesh_count = f.readUInt()
self.unk012 = f.readUInt()
self.total_face_count = f.readUInt()
self.unk014 = f.readUInt()
self.unk015 = f.readUInt()
self.total_lod_count = f.readUInt()
self.unk017 = f.readUInt()
self.unk018 = f.readUInt()
self.unk019 = f.readUInt()
self.unk020 = f.readUInt()
self.unk021 = f.readUInt()
self.unk022 = f.readUInt()
self.unk057 = f.readUShort()
self.unk058 = f.readBytes(self.unk057).decode("UTF-8").rstrip("\0")
self.unk023 = f.readFloat()
self.unk024 = f.readUInt()
if self.unk024 > 0: # 64bytes, looks like a matrix
self.unk025 = [[float], [float], [float], [float], [float], [float], [float], [float], [float], [float], [float], [float], [float], [float], [float], [float]] * self.unk024
for i in range(0, self.unk024):
self.unk025[i] = [
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
]
for ii in range(0, 16):
self.unk025[i][ii] = f.readFloat()
self.unk026 = f.readUShort()
self.unk027 = f.readUShort()
self.meshs = [ltb_mesh] * self.mesh_count
for i in range(0, self.mesh_count):
self.meshs[i] = ltb_mesh()
self.meshs[i].read_mesh(f)
self.nodes = [ltb_node] * self.node_count
for i in range(0, self.node_count):
self.nodes[i] = ltb_node()
self.nodes[i].read_node(f)
def getChildren(self, i):
c = 0
p = i
x = 0
if i < self.node_count:
self.nodes[i].children = []
for c in range(0, self.nodes[i].childCount):
p = p + 1
self.nodes[i].children.append(p)
if p <= self.node_count:
p = self.getChildren(p)
return p
def getParent(self):
for i in range(0, self.node_count):
self.nodes[i].parent = -1
for ii in range(0, self.node_count):
if ii != i and self.nodes[i].parent == -1:
for iii in range(0, len(self.nodes[ii].children)):
if self.nodes[ii].children[iii] == int(i):
self.nodes[i].parent = ii
def create_bone_list(self):
# generate the parents from the child counts
self.getChildren(0)
self.getParent()
BoneList = []
BoneMatrix43 = NoeMat43()
BoneMatrix44 = NoeMat44()
BoneName = ""
ParentName = ""
i = 0
NumBones = self.node_count
if NumBones > 0:
BoneList = [NoeBone] * NumBones
for i in range(0, NumBones):
BoneMatrix44 = NoeMat44((
NoeVec4((self.nodes[i].matrix[0], self.nodes[i].matrix[4], self.nodes[i].matrix[8], self.nodes[i].matrix[12])),
NoeVec4((self.nodes[i].matrix[1], self.nodes[i].matrix[5], self.nodes[i].matrix[9], self.nodes[i].matrix[13])),
NoeVec4((self.nodes[i].matrix[2], self.nodes[i].matrix[6], self.nodes[i].matrix[10], self.nodes[i].matrix[14])),
NoeVec4((self.nodes[i].matrix[3], self.nodes[i].matrix[7], self.nodes[i].matrix[11], self.nodes[i].matrix[15]))
))
BoneMatrix43 = BoneMatrix44.toMat43()
#BoneMatrix43 = BoneMatrix43.inverse()
BoneName = "bone%03i" % i
ParentName = "bone%03i" % self.nodes[i].parent
if self.nodes[i].node_name != "":
BoneName = self.nodes[i].node_name
if self.nodes[i].parent > -1 and self.nodes[i].parent < NumBones:
if self.nodes[self.nodes[i].parent].node_name != "":
ParentName = self.nodes[self.nodes[i].parent].node_name
BoneList[i] = (NoeBone(i, BoneName, BoneMatrix43, ParentName, self.nodes[i].parent))
#BoneList[i] = (NoeBone(i, self.nodes[i].node_name, BoneMatrix43, None, -1))
else:
BoneList[i] = (NoeBone(i, self.nodes[i].node_name, BoneMatrix43, None, -1))
return BoneList
def create_mesh_list(self, f = NoeBitStream()):
mshList = []
if self.mesh_count > 0:
mshList = [NoeMesh] * self.mesh_count
for i in range(0, self.mesh_count):
mshList[i] = NoeMesh(self.meshs[i].lods[0].faces, self.meshs[i].lods[0].verts.position, self.meshs[i].mesh_name)
#mshList[i].setIndices(self.meshs[i].lods[0].faces)
#mshList[i].setPositions(self.meshs[i].lods[0].verts.position)
mshList[i].setNormals(self.meshs[i].lods[0].verts.normal)
mshList[i].setUVs(self.meshs[i].lods[0].verts.texcoord, 0)
mshList[i].setWeights(self.meshs[i].lods[0].verts.weights)
return mshList
def noepyLoadModel(data, mdlList):
f = NoeBitStream(data)
if f.readUInt() != NOEPY_HEADER:
return 0
# Check if there is a texture library
#filename = rapi.getInputName()
#filename = filename[:-3] + {'LTB': 'DTX'}[filename[-3:].upper()]
#if rapi.checkFileExists(filename):
# t = NoeBitStream(rapi.loadIntoByteArray(filename))
f.seek(0x00, NOESEEK_ABS)
ltb = ltb_file()
ltb.read_ltb(f)
BoneList = []
MeshList = []
BoneList = ltb.create_bone_list()
MeshList = ltb.create_mesh_list(f)
mdl = NoeModel()
mdl.setBones(BoneList)
mdl.setMeshes(MeshList)
mdlList.append(mdl)
return 1
def noepyCheckType(data):
if len(data) < 8:
return 0
f = NoeBitStream(data)
if f.readUInt() != NOEPY_HEADER:
return 0
return 1
def registerNoesisTypes():
if showConsole == True:
noesis.logPopup()
for i in range(0, 30): print("\n")
handle = noesis.register("Lith Tech Binary (PC)", ".ltb")
noesis.setHandlerTypeCheck(handle, noepyCheckType)
noesis.setHandlerLoadModel(handle, noepyLoadModel)
return 1
You do not have the required permissions to view the files attached to this post.
Maxscript and other finished work I've done can be found on my DeviantArt account
