Skip to content

Instantly share code, notes, and snippets.

@Numbers11
Created February 24, 2016 14:12
Show Gist options
  • Save Numbers11/f7a44a24df43618149a6 to your computer and use it in GitHub Desktop.
Save Numbers11/f7a44a24df43618149a6 to your computer and use it in GitHub Desktop.
import struct
global file
#import fbx
import sys
import math
#import FbxCommon
import functools
import itertools
import numpy as np
import bpy, mathutils
import bmesh
def readcstr(f):
buf = bytearray()
while True:
b = f.read(1)
if b is None or b == b'\0':
return buf.decode()
else:
buf.extend(b)
class BinaryReaderEOFException(Exception):
def __init__(self):
pass
def __str__(self):
return 'Not enough bytes in file to satisfy read request'
class BinaryReader:
# Map well-known type names into struct format characters.
typeNames = {
'int8' :'b',
'uint8' :'B',
'int16' :'h',
'uint16' :'H',
'int32' :'i',
'uint32' :'I',
'int64' :'q',
'uint64' :'Q',
'float' :'f',
'double' :'d',
'char' :'s'}
def __init__(self, fileName):
self.file = fileName
def read(self, typeName):
typeFormat = BinaryReader.typeNames[typeName.lower()]
typeSize = struct.calcsize(typeFormat)
value = self.file.read(typeSize)
if typeSize != len(value):
raise BinaryReaderEOFException
return struct.unpack(typeFormat, value)[0]
def readString(self, length):
typeFormat = str(length) + "s"
typeSize = struct.calcsize(typeFormat)
value = self.file.read(typeSize)
if typeSize != len(value):
raise BinaryReaderEOFException
return struct.unpack(typeFormat, value)[0]
def __del__(self):
self.file.close()
def readFileHeader():
try:
signature = binaryReader.read('uint32')
unkown1 = binaryReader.read('uint32')
unkown2 = binaryReader.read('uint32')
blocknum = binaryReader.read('uint32')
#print blocknum
blocks = []
for x in range(0, blocknum):
#struct.unpack('4s', name)
block = {}
block["name"] = binaryReader.readString(4)
#pos = BinaryReader.getPos();
pos = file.tell()
block["offset"] = binaryReader.read('uint32')
block["link"] = pos + block["offset"];
block["size"] = binaryReader.read('uint32')
blocks.append(block)
#print block
return blocks
except BinaryReaderEOFException:
# One of our attempts to read a field went beyond the end of the file.
print("Error: File seems to be corrupted.")
def readVBIB(offset):
file.seek(offset)
pos = file.tell()
header = {}
header["vertexHOffset"] = binaryReader.read('uint32')
header["vertexHLink"] = pos + header["vertexHOffset"]
header["vertexHCount"] = binaryReader.read('uint32')
pos = file.tell()
header["indexHOffset"] = binaryReader.read('uint32')
header["indexHLink"] = pos + header["indexHOffset"]
header["indexHCount"] = binaryReader.read('uint32')
return header
def readVertices(offset, count):
vertexgroups = []
for x in range(0, count):
vertices = {}
file.seek(offset + x * 24)
vertices["count"] = binaryReader.read('uint32')
file.seek(offset + x * 24 + 16)
vertices["link"] = offset + x * 24 + 16 + binaryReader.read('uint32')
vertices["vertex"] = []
vertices["boneid"] = []
vertices["boneweight"] = []
file.seek(offset + x * 24 + 4)
vertices["size"] = binaryReader.read('uint32');
file.seek(vertices["link"])
for q in range(0, vertices["count"]):
x = binaryReader.read("float")
y = binaryReader.read("float")
z = binaryReader.read("float")
bonenum = binaryReader.read("uint8")
#print bonenum
#print x, y, z
boneid1 = binaryReader.read("uint8")
boneid2 = binaryReader.read("uint8")
boneid3 = binaryReader.read("uint8")
#print boneid1,boneid2,boneid3
boneweight1 = binaryReader.read("uint8")
boneweight2 = binaryReader.read("uint8")
boneweight3 = binaryReader.read("uint8")
#print boneweight1,boneweight2,boneweight3
#not sure what any of this shit is except the vertices
binaryReader.read("char") #crap?
binaryReader.readString(vertices["size"] - 20) #skip whatever is still there
vertices["vertex"].append((x,y,z))
vertices["boneid"].append([boneid1,boneid2,boneid3])
vertices["boneweight"].append([boneweight1,boneweight2,boneweight3])
vertexgroups.append(vertices)
return vertexgroups
def readAttributes(offset, count):
attributes = {}
for x in range(0, count):
file.seek(offset + x * 24 + 12)
acount = binaryReader.read("uint32")
print( acount)
file.seek(offset + 24 * x + 8)
pos = binaryReader.read("uint32")
# print pos
link = offset + 24 * x + 8 + pos
#print link
for y in range (0,acount):
here = link + y *56
file.seek(here)
name = readcstr(file)
# print name
file.seek(here + 40)
attributes[name] = binaryReader.read("uint32")
return attributes
def readTexcoords(vertices, offset):
htexcoords = []
for x in range (0,len(vertices)):
texcoords = []
for y in range (0,len(vertices[x]["vertex"])):
file.seek(vertices[x]["link"] + y * vertices[x]["size"] + offset)
qbuffer = file.read(2)
u = np.frombuffer(qbuffer, dtype=np.float16)[0]
qbuffer = file.read(2)
v = 1 - np.frombuffer(qbuffer, dtype=np.float16)[0]
texcoords.append((u, v))
htexcoords.append(texcoords)
return htexcoords
def readBlendIndices(vertices, offset):
hblendindices = []
for x in range (0,len(vertices)):
blendindices = []
for y in range (0,len(vertices[x]["vertex"])):
file.seek(vertices[x]["link"] + y * vertices[x]["size"] + offset)
a = binaryReader.read("uint8")
b = binaryReader.read("uint8")
c = binaryReader.read("uint8")
d = binaryReader.read("uint8") #bone num? unused? bullshit? you decide
#print a,b,c,d
blendindices.append((a,b,c,d))
hblendindices.append(blendindices)
return hblendindices
def readBlendWeights(vertices, offset):
hblendweights = []
for x in range (0,len(vertices)):
blendweights = []
for y in range (0,len(vertices[x]["vertex"])):
file.seek(vertices[x]["link"] + y * vertices[x]["size"] + offset)
a = binaryReader.read("uint8")
b = binaryReader.read("uint8")
c = binaryReader.read("uint8")
#print(a,b,c)
blendweights.append((a,b,c))
hblendweights.append(blendweights)
return hblendweights
def readIndices(offset, count):
indexgroups = []
for x in range(0, count):
indices = {}
file.seek(offset + x * 24)
indices["count"] = binaryReader.read('uint32')
file.seek(offset + x * 24 + 16)
indices["link"] = offset + x * 24 + 16 + binaryReader.read('uint32')
indices["index"] = []
file.seek(indices["link"])
for q in range(0, int(indices["count"] / 3)):
a = binaryReader.read("uint16")
b = binaryReader.read("uint16")
c = binaryReader.read("uint16")
#print a,b,c
indices["index"].append((a,b,c))
indexgroups.append(indices)
return indexgroups
####
#blender stuff
def createMesh(origin, verts, faces, texcoords):
# Create mesh and object
me = bpy.data.meshes.new('Mesh')
ob = bpy.data.objects.new('MeshObject', me)
ob.location = origin
# Link object to scene
scn = bpy.context.scene
scn.objects.link(ob)
scn.objects.active = ob
scn.update()
# Create mesh from given verts, edges, faces. Either edges or
# faces should be [], or you ask for problems
me.from_pydata(verts, [], faces)
# Update mesh with new data
me.update(calc_edges=True)
me.uv_textures.new()
uv_data = me.uv_layers[0].data
for i in range(len(uv_data)):
uv_data[i].uv = texcoords[me.loops[i].vertex_index]
return ob
##MAIN PROGRAM
#read data from model
filename = 'C:\\Users\\Bene\\Desktop\\cube\\axe_model.vmesh_c'
file = open(filename, 'rb')
binaryReader = BinaryReader(file)
header = readFileHeader()
#print header
vbibheader = readVBIB(header[3]["link"])
#print vbibheader
hvertices = readVertices(vbibheader["vertexHLink"], vbibheader["vertexHCount"])
hindices = readIndices(vbibheader["indexHLink"], vbibheader["indexHCount"])
print ("Number of vertices: ", hvertices[0]["count"])
print ("Number of indices: ", int(hindices[0]["count"] / 3))
attributes = readAttributes(vbibheader["vertexHLink"], vbibheader["vertexHCount"])
print( attributes)
htexcoords = readTexcoords(hvertices, attributes["TEXCOORD"])
#print htexcoords
if "BLENDWEIGHT" in attributes:
readBlendWeights(hvertices, attributes["BLENDWEIGHT"])
if "BLENDINDICES" in attributes:
readBlendIndices(hvertices, attributes["BLENDINDICES"])
vertices = hvertices[0]["vertex"]
indices = hindices[0]["index"]
texcoords = htexcoords[0]
createMesh((0,0,0), vertices, indices, texcoords)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment