vertex position
This commit is contained in:
parent
63299d123b
commit
76c91020b1
18
NinjaBone.py
18
NinjaBone.py
@ -49,24 +49,24 @@ class NinjaBone: # {
|
||||
for j in range(4):
|
||||
t = 0.0
|
||||
for k in range(4):
|
||||
t = t + (a[i][k] * b[k][j])
|
||||
t = t + (b[i][k] * a[k][j])
|
||||
tmp[i][j] = t
|
||||
return tmp
|
||||
|
||||
def multiplyLocal(self, factor):
|
||||
a = self.worldMatrix
|
||||
b = factor
|
||||
tmp = self.multiply(a, b)
|
||||
self.worldMatrix = tmp
|
||||
return None
|
||||
|
||||
def multiplyWorld(self, factor):
|
||||
a = self.localMatrix
|
||||
b = factor
|
||||
tmp = self.multiply(a, b)
|
||||
self.localMatrix = tmp
|
||||
return None
|
||||
|
||||
def multiplyWorld(self, factor):
|
||||
a = self.worldMatrix
|
||||
b = factor
|
||||
tmp = self.multiply(a, b)
|
||||
self.worldMatrix = tmp
|
||||
return None
|
||||
|
||||
def setName(self, num):
|
||||
self.save()
|
||||
self.id = num
|
||||
@ -163,4 +163,4 @@ class NinjaBone: # {
|
||||
y = res[1] / res[3]
|
||||
z = res[2] / res[3]
|
||||
vertex.setPosition(x, y, z)
|
||||
return None
|
||||
return vertex
|
||||
|
@ -32,6 +32,7 @@ from NinjaMaterial import NinjaMaterial
|
||||
from NinjaVertex import NinjaVertex
|
||||
from NinjaFace import NinjaFace
|
||||
from NinjaBone import NinjaBone
|
||||
from matrix_44 import Mat4
|
||||
|
||||
class NinjaModel: # {
|
||||
|
||||
@ -72,32 +73,27 @@ class NinjaModel: # {
|
||||
return None
|
||||
|
||||
def parseModel(self):
|
||||
print("Execute parse")
|
||||
|
||||
while self.file.tell() < self.length:
|
||||
|
||||
bytes = self.file.read(4)
|
||||
|
||||
if(bytes == b'NJTL') :
|
||||
print('Found Ninja Texture List')
|
||||
bytes = self.file.read(4)
|
||||
len = struct.unpack('I', bytes)[0]
|
||||
pos = self.file.tell() + len
|
||||
self.readNjtl()
|
||||
self.file.seek(pos, 0)
|
||||
elif (bytes == b'NJCM') :
|
||||
print('Found Ninja Chunk Model')
|
||||
bytes = self.file.read(4)
|
||||
len = struct.unpack('I', bytes)[0]
|
||||
pos = self.file.tell() + len
|
||||
self.pof = self.file.tell()
|
||||
self.readNjcm(None)
|
||||
self.readNjcm(None, None)
|
||||
self.file.seek(pos, 0)
|
||||
elif (bytes == b'NMDM') :
|
||||
print('Found Ninja Direct Motion')
|
||||
|
||||
self.file.close()
|
||||
print("End Parse")
|
||||
return None
|
||||
|
||||
def readNjtl(self):
|
||||
@ -122,52 +118,67 @@ class NinjaModel: # {
|
||||
name += ch.decode()
|
||||
return None
|
||||
|
||||
def readNjcm(self, parentBone):
|
||||
def readNjcm(self, parentBone, ptx):
|
||||
|
||||
bytes = self.file.read(52)
|
||||
b = struct.unpack('IIfffiiifffII', bytes)
|
||||
|
||||
flags = b[0]
|
||||
model_ofs = b[1]
|
||||
|
||||
|
||||
c = 2 * 3.141592 / 0xFFFF;
|
||||
pos = ( b[2], b[3], b[4] )
|
||||
rot = ( b[5], b[6], b[7] )
|
||||
rot = ( b[5] * c, b[6] * c, b[7] *c)
|
||||
scl = ( b[8], b[9], b[10] )
|
||||
|
||||
child_ofs = b[11]
|
||||
sibling_ofs = b[12]
|
||||
|
||||
self.bone = NinjaBone()
|
||||
|
||||
if ( (flags & 0x04) == 0):
|
||||
self.bone.setScale(scl)
|
||||
|
||||
if ( (flags & 0x02) == 0):
|
||||
self.bone.setRotation(rot, flags & 0x20)
|
||||
|
||||
if ( (flags & 0x01) == 0):
|
||||
self.bone.setPosition(pos)
|
||||
|
||||
num = len(self.bones)
|
||||
self.bone.setName(num)
|
||||
self.bones.append(self.bone)
|
||||
|
||||
print()
|
||||
print(self.bone.name)
|
||||
print("Flags: %d" % flags);
|
||||
print(pos)
|
||||
|
||||
mtx = Mat4()
|
||||
|
||||
if ( (flags & 0x04) == 0):
|
||||
mtx.scale(scl)
|
||||
self.bone.setScale(scl)
|
||||
|
||||
if ( (flags & 0x02) == 0):
|
||||
mtx.rotate(rot)
|
||||
self.bone.setRotation(rot, flags & 0x20)
|
||||
|
||||
if ( (flags & 0x01) == 0):
|
||||
mtx.translate(pos)
|
||||
self.bone.setPosition(pos)
|
||||
|
||||
if ptx is not None:
|
||||
mtx.multiply(ptx.getMatrix())
|
||||
|
||||
self.mtx = mtx
|
||||
|
||||
if parentBone:
|
||||
parentBone.add(self.bone)
|
||||
|
||||
if model_ofs:
|
||||
print("Reading model for Bone: %s" % self.bone.name)
|
||||
self.file.seek(model_ofs + self.pof, 0)
|
||||
self.readModel()
|
||||
|
||||
if child_ofs:
|
||||
self.file.seek(child_ofs + self.pof, 0)
|
||||
self.readNjcm(self.bone)
|
||||
self.readNjcm(self.bone, mtx)
|
||||
|
||||
if sibling_ofs:
|
||||
self.file.seek(sibling_ofs + self.pof, 0)
|
||||
self.readNjcm(parentBone)
|
||||
self.readNjcm(parentBone, ptx)
|
||||
|
||||
return None
|
||||
|
||||
def readModel(self):
|
||||
@ -180,9 +191,6 @@ class NinjaModel: # {
|
||||
center = (m[2], m[3], m[4])
|
||||
radius = m[5]
|
||||
|
||||
#if self.strip_count > 0:
|
||||
# return None
|
||||
|
||||
if vertex_ofs:
|
||||
self.file.seek(vertex_ofs + self.pof, 0)
|
||||
self.readVertexList()
|
||||
@ -191,15 +199,10 @@ class NinjaModel: # {
|
||||
self.file.seek(chunk_ofs + self.pof, 0)
|
||||
self.readChunkList()
|
||||
|
||||
print(self.vertex_list)
|
||||
print(self.index_lookup)
|
||||
|
||||
return None
|
||||
|
||||
def readVertexList(self):
|
||||
|
||||
print("Reading vertex list")
|
||||
|
||||
bytes = self.file.read(8)
|
||||
c = struct.unpack('BBHHH', bytes)
|
||||
chunk_head = c[0]
|
||||
@ -211,22 +214,26 @@ class NinjaModel: # {
|
||||
if chunk_head != 41:
|
||||
print("ERROR!!! NEW VERTEX TYPE!!!!")
|
||||
|
||||
print("Chunk Head: %d" % chunk_head)
|
||||
print("Chunk Flag: %d" % chunk_flag)
|
||||
print("Vertex Ofs: %d" % vertex_ofs)
|
||||
print("Vertex Count: %d" % vertex_count)
|
||||
|
||||
for i in range(vertex_count):
|
||||
|
||||
bytes = self.file.read(24)
|
||||
v = struct.unpack('ffffff', bytes)
|
||||
|
||||
pos = [ v[0], v[1], v[2] ]
|
||||
pos = self.mtx.apply(pos)
|
||||
|
||||
vertex = NinjaVertex()
|
||||
vertex.setPosition( v[0], v[1], v[2] )
|
||||
vertex.setPosition( pos[0], pos[1], pos[2] )
|
||||
vertex.setNormal( v[3], v[4], v[5] )
|
||||
vertex.setSkinWeight(0, self.bone.id, 1.0)
|
||||
self.bone.apply(vertex)
|
||||
|
||||
#print("vertex in: %s" % vertex)
|
||||
#vertex = self.bone.apply(vertex)
|
||||
#print("vertex out: %s" % vertex)
|
||||
|
||||
while len(self.index_lookup) < vertex_ofs + 1:
|
||||
self.index_lookup.append(None)
|
||||
|
||||
self.index_lookup[vertex_ofs] = len(self.vertex_list)
|
||||
vertex_ofs += 1
|
||||
self.vertex_list.append(vertex)
|
||||
@ -260,11 +267,8 @@ class NinjaModel: # {
|
||||
if chunk_head == 255:
|
||||
break
|
||||
elif chunk_head == 0:
|
||||
print("Null Chunk")
|
||||
continue
|
||||
elif chunk_head >= 1 and chunk_head <= 5:
|
||||
print("Tiny Chunk Found!!!")
|
||||
|
||||
if chunk_head == 1:
|
||||
print("Blend Alpha Adjust!!")
|
||||
elif chunk_head == 2:
|
||||
@ -275,9 +279,7 @@ class NinjaModel: # {
|
||||
print("Save offset!!!")
|
||||
elif chunk_head == 5:
|
||||
print("Jumpt to offset!!!")
|
||||
|
||||
elif chunk_head >= 17 and chunk_head <= 23:
|
||||
print("Chunk: Material")
|
||||
bytes = self.file.read(2)
|
||||
short_len = struct.unpack('H', bytes)
|
||||
self.material = NinjaMaterial()
|
||||
@ -311,7 +313,6 @@ class NinjaModel: # {
|
||||
coef = c[3] / 255.0
|
||||
|
||||
elif chunk_head >= 8 and chunk_head <= 9:
|
||||
print("Chunk: Tiny")
|
||||
bytes = self.file.read(2)
|
||||
chunk_body = struct.unpack('H', bytes)[0]
|
||||
mip_depth = chunk_flag & 0x07
|
||||
@ -325,7 +326,6 @@ class NinjaModel: # {
|
||||
self.material = self.material.clone()
|
||||
self.material.setTexIndex(tex_id)
|
||||
elif chunk_head >= 64 and chunk_head <= 66:
|
||||
print("Chunk Strip!!!")
|
||||
|
||||
bytes = self.file.read(4)
|
||||
h = struct.unpack('HH', bytes)
|
||||
@ -354,14 +354,11 @@ class NinjaModel: # {
|
||||
|
||||
strip_count = chunk_body & 0x3fff;
|
||||
user_offset = chunk_body >> 14
|
||||
print("Strip count: %d" % strip_count)
|
||||
|
||||
for i in range (strip_count): # {
|
||||
|
||||
print("Strip Start: 0x%08x" % self.file.tell())
|
||||
bytes = self.file.read(2)
|
||||
strip_len = struct.unpack('h', bytes)[0]
|
||||
print("Strip Count: %d" % strip_len)
|
||||
clockwise = strip_len < 0
|
||||
strip_len = abs(strip_len)
|
||||
strip = []
|
||||
@ -398,8 +395,6 @@ class NinjaModel: # {
|
||||
|
||||
# }
|
||||
|
||||
print(indices)
|
||||
|
||||
for k in range(len(strip) - 2): #{
|
||||
|
||||
if ((clockwise and not (k % 2)) or ( not clockwise and k % 2)):
|
||||
@ -415,8 +410,6 @@ class NinjaModel: # {
|
||||
bi = b['index']
|
||||
ci = c['index']
|
||||
|
||||
print("Face: %d %d %d" % (ai, bi, ci))
|
||||
|
||||
va = self.vertex_list[a['index']]
|
||||
vb = self.vertex_list[a['index']]
|
||||
vc = self.vertex_list[a['index']]
|
||||
@ -427,13 +420,11 @@ class NinjaModel: # {
|
||||
face.setNormals(va.norm, vb.norm, vc.norm)
|
||||
face.setDiffuseUv(a['uv'], b['uv'], c['uv'])
|
||||
self.face_list.append(face)
|
||||
print(face)
|
||||
# }
|
||||
|
||||
# }
|
||||
|
||||
self.strip_count = self.strip_count + 1
|
||||
print("Strip End: 0x%08x" % self.file.tell())
|
||||
else:
|
||||
print("Unknown Chunk Type %d" % chunk_head)
|
||||
print("Unknown Chunk Flag %d" % chunk_flag)
|
||||
@ -444,7 +435,6 @@ class NinjaModel: # {
|
||||
return None
|
||||
|
||||
def export(self):
|
||||
print("EXPORTING DMF!!!")
|
||||
pre, ext = os.path.splitext(self.model_name)
|
||||
pre = pre.replace('/', '_')
|
||||
f = open('output/' + pre + '.DMF', 'wb')
|
||||
|
@ -31,9 +31,10 @@ nj = NinjaModel(model_file, texture_file)
|
||||
nj.parse()
|
||||
nj.export()
|
||||
|
||||
|
||||
"""
|
||||
model_file = 'MISC/BUTTON01.NJ'
|
||||
texture_file = 'MISC/BUTTON01.PVR'
|
||||
nj = NinjaModel(model_file, texture_file)
|
||||
nj.parse()
|
||||
nj.export()
|
||||
"""
|
||||
|
141
matrix_44.py
Normal file
141
matrix_44.py
Normal file
@ -0,0 +1,141 @@
|
||||
#==============================================================
|
||||
"""
|
||||
Mat4 - Transformation matrix interface library
|
||||
Copyright Benjamin Collins 2016,2018
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"""
|
||||
#==============================================================
|
||||
|
||||
import math
|
||||
|
||||
class Mat4:
|
||||
|
||||
#constructor
|
||||
def __init__(self):
|
||||
self.mtx = self.identity()
|
||||
|
||||
# return matrix
|
||||
def getMatrix(self):
|
||||
return self.mtx
|
||||
|
||||
# create identity
|
||||
def identity(self):
|
||||
return [
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1]
|
||||
]
|
||||
|
||||
# mutliply by 4x4 matrix
|
||||
def multiply(self, factor):
|
||||
tmp = self.identity()
|
||||
|
||||
for i in range(4):
|
||||
for j in range(4):
|
||||
t = 0.0
|
||||
for k in range(4):
|
||||
t = t + (self.mtx[i][k] * factor[k][j])
|
||||
tmp[i][j] = t
|
||||
|
||||
self.mtx = tmp
|
||||
|
||||
# apply matrix to vec3
|
||||
def apply(self, vec3):
|
||||
vec3.append(1)
|
||||
res = [0,0,0,0]
|
||||
for i in range(4):
|
||||
t = 0.0
|
||||
for j in range(4):
|
||||
t = t + (vec3[j] * self.mtx[j][i])
|
||||
res[i] = t
|
||||
x = res[0] / res[3];
|
||||
y = res[1] / res[3];
|
||||
z = res[2] / res[3];
|
||||
return [x, y, z]
|
||||
|
||||
# scale by vec3
|
||||
def scale(self, vec3):
|
||||
tmp = self.identity()
|
||||
# x
|
||||
tmp[0][0] = vec3[0]
|
||||
# y
|
||||
tmp[1][1] = vec3[1]
|
||||
# z
|
||||
tmp[2][2] = vec3[2]
|
||||
self.multiply(tmp)
|
||||
|
||||
# translate by vec3
|
||||
def translate(self, vec3):
|
||||
tmp = self.identity()
|
||||
# x
|
||||
tmp[3][0] = vec3[0]
|
||||
# y
|
||||
tmp[3][1] = vec3[1]
|
||||
# z
|
||||
tmp[3][2] = vec3[2]
|
||||
self.multiply(tmp)
|
||||
|
||||
# rotate by vec3
|
||||
def rotate(self, vec3, zxy_order = False):
|
||||
|
||||
if zxy_order:
|
||||
z = vec3[0]
|
||||
x = vec3[1]
|
||||
y = vec3[2]
|
||||
else:
|
||||
x = vec3[0]
|
||||
y = vec3[1]
|
||||
z = vec3[2]
|
||||
|
||||
# rotate x-axis
|
||||
tmp = self.identity()
|
||||
c = math.cos(x)
|
||||
s = math.sin(x)
|
||||
tmp[1][1] = c;
|
||||
tmp[1][2] = s;
|
||||
tmp[2][1] = -s;
|
||||
tmp[2][2] = c;
|
||||
self.multiply(tmp)
|
||||
|
||||
# rotate y-axis
|
||||
tmp = self.identity()
|
||||
c = math.cos(y)
|
||||
s = math.sin(y)
|
||||
tmp[0][0] = c;
|
||||
tmp[0][2] = -s;
|
||||
tmp[2][0] = s;
|
||||
tmp[2][2] = c;
|
||||
self.multiply(tmp)
|
||||
|
||||
# rotate z-axis
|
||||
tmp = self.identity()
|
||||
c = math.cos(z)
|
||||
s = math.sin(z)
|
||||
tmp[0][0] = c;
|
||||
tmp[0][1] = s;
|
||||
tmp[1][0] = -s;
|
||||
tmp[1][1] = c;
|
||||
self.multiply(tmp)
|
||||
|
||||
#==============================================================
|
||||
"""
|
||||
Program End
|
||||
"""
|
||||
#==============================================================
|
Loading…
Reference in New Issue
Block a user