Skip to content

Instantly share code, notes, and snippets.

@liyonghelpme
Last active August 15, 2023 00:23
Show Gist options
  • Save liyonghelpme/7b69abc8d0feb8decd65 to your computer and use it in GitHub Desktop.
Save liyonghelpme/7b69abc8d0feb8decd65 to your computer and use it in GitHub Desktop.
ogre skeleton import
#!BPY
""" Registration info for Blender menus:
Name: 'OGRE (.mesh.xml)...'
Blender: 236
Group: 'Import'
Tip: 'Import an Ogre-Mesh (.mesh.xml) file.'
"""
'''
__author__ = "Daniel Wickert"
__version__ = "0.4 05/11/05"
__bpydoc__ = """\
This script imports Ogre-Mesh models into Blender.
Supported:<br>
* multiple submeshes (triangle list)
* uvs
* materials (textures only)
* vertex colours
Missing:<br>
* submeshes provided as triangle strips and triangle fans
* materials (diffuse, ambient, specular, alpha mode, etc.)
* skeletons
* animations
Known issues:<br>
* blender only supports a single uv set, always the first is taken
and only the first texture unit in a material, even if it is not for
the first uv set.
* code is a bit hacky in parts.
"""
'''
# Copyright (c) 2005 Daniel Wickert
#
# 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.
# HISTORY:
# 0.1 04/02/05
# ------------
# * initial implementation. single submesh as triangle list, no uvs
#
# 0.2 04/03/05
# ------------
# * uv support added
# * texture loading added
#
# 0.3 04/09/05
# ------------
# * multiple submeshes added
# * scaling added
# * material parsing (only textures yet)
# * mesh -> mesh.xml conversion if IMPORT_OGREXMLCONVERTER defined
# * vertex colours
#
# 0.3.1 04/11/05
# --------------
# * stdout output streamlined
# * missing materials and textures are now handled gracefully
#
# 0.3.1a 04/11/05
# --------------
# * Mesh is assigned to a correctly named object and added
# to the current scene
#
# 0.4. 05/11/05
# --------------
# * shared vertices support
# * multiple texture coordinates in meshes are handled correctly no,
# but only the first coordinate set is used, since Blender doesn't
# allow multiple uvs.
# * only the first texture_unit's texture is used now.
#
# 0.4.1 06/02/05
# --------------
# * fixed bug: pathes invalid under linux
# * fixed bug: shared vertices were duplicated with each submesh
#
# 0.5.0 06/06/05
# --------------
# * consistent logging scheme with adjustable log level
# * render materials
#
# 0.5.1 13/07/05
# --------------
# * fixed bug: meshes without normals and texture coords cannot be imported
#
# 0.5.2 12/02/06
# --------------
# * fixed bug: multiple blender materials created from one ogre material
#
# TODO: implement a consistent naming scheme:
# bxxx for blender classes; oxxx for ogre(well, sorta) classes
bl_info = {
"name": "ogre mesh import",
"author": "Bartek Skorupa, Greg Zaal",
"version": (0, 1, 6),
"blender": (2, 70, 0),
"location": "File > Import > ogre (.mesh)",
"description": "import ogre mesh file",
"warning": "",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/Nodes/Nodes_Efficiency_Tools",
"category": "Import-Export",
}
__version__ = "1.2.3"
import logging
handle = logging.FileHandler("/Users/liyong/blender.log")
logger = logging.getLogger()
logger.addHandler(handle)
logger.setLevel(logging.INFO)
import bpy
import glob
import os
import re
import xml.sax
import xml.sax.handler
import bmesh
import mathutils
from mathutils import Vector
from mathutils import Matrix
# determines the verbosity of loggin.
# 0 - no logging (fatal errors are still printed)
# 1 - standard logging
# 2 - verbose logging
# 3 - debug level. really boring (stuff like vertex data and verbatim lines)
IMPORT_LOG_LEVEL = 1
IMPORT_SCALE_FACTOR = 1
#IMPORT_OGREXMLCONVERTER = "d:\stuff\Torchlight_modding\orge_tools\OgreXmlConverter.exe"
IMPORT_OGREXMLCONVERTER = "/Users/liyong/Downloads/OgreCommandLineToolsMac_1.8.0/OgreXMLConverter"
#IMPORT_OGREXMLCONVERTER = "F:\\Projekte\\rastullah\checkout\\rl\\branches\python\dependencies\ogre\Tools\Common\\bin\\release\\OgreXmlConverter.exe"
def log(msg):
logger.info(msg)
#if IMPORT_LOG_LEVEL >= 1: print(msg)
def vlog(msg):
if IMPORT_LOG_LEVEL >= 2: print(msg)
def dlog(msg):
if IMPORT_LOG_LEVEL >= 3: print(msg)
class Mesh:
def __init__(self):
self.submeshes = []
self.vertices = []
self.vertexcolours = []
self.normals = []
self.uvs = []
class Submesh:
def __init__(self):
self.vertices = []
self.vertexcolours = []
self.normals = []
self.faces = []
self.uvs = []
self.indextype = ""
self.materialname = ""
self.sharedvertices = 0
class Material:
def __init__(self, name):
self.name = name
self.texname = ""
self.diffuse = (1.0, 1.0, 1.0, 1.0)
self.ambient = (1.0, 1.0, 1.0, 1.0)
self.specular = (0.0, 0.0, 0.0, 0.0)
self.blenderimage = 0
self.loading_failed = 0
def getTexture(self):
if self.blenderimage == 0 and not self.loading_failed:
try:
#f = file(self.texname, 'r')
#f.close()
#self.blenderimage = Blender.Image.Load(self.texname)
if not os.path.exists(self.texname):
self.texname = self.texname.replace('.png', '.dds')
self.blenderimage = bpy.data.images.load(self.texname)
except IOError as err:
errmsg = "Couldn't open %s #%s" \
% (self.texname, err)
log(errmsg)
self.loading_failed = 1;
return self.blenderimage
class OgreMeshSaxHandler(xml.sax.handler.ContentHandler):
global IMPORT_SCALE_FACTOR
def __init__(self):
self.mesh = 0
self.submesh = 0
self.ignore_input = 0
self.load_next_texture_coords = 0
self.skeleton = 0
def startDocument(self):
self.mesh = Mesh()
def startElement(self, name, attrs):
if name == 'skeletonlink':
self.skeleton = attrs.get("name", '')
if name == 'sharedgeometry':
self.submesh = self.mesh
if name == 'submesh':
self.submesh = Submesh()
self.submesh.materialname = attrs.get('material', "")
self.submesh.indextype = attrs.get('operationtype', "")
if attrs.get('usesharedvertices') == 'true':
self.submesh.sharedvertices = 1
if name == 'vertex':
self.load_next_texture_coords = 1
if name == 'face' and self.submesh:
face = (
int(attrs.get('v1',"")),
int(attrs.get('v2',"")),
int(attrs.get('v3',""))
)
self.submesh.faces.append(face)
if name == 'position':
vertex = (
#Ogre x/y/z --> Blender x/-z/y
float(attrs.get('x', "")) * IMPORT_SCALE_FACTOR,
-float(attrs.get('z', "")) * IMPORT_SCALE_FACTOR,
float(attrs.get('y', "")) * IMPORT_SCALE_FACTOR
)
self.submesh.vertices.append(vertex)
if name == 'normal':
normal = (
#Ogre x/y/z --> Blender x/-z/y
float(attrs.get('x', "")),
-float(attrs.get('z', "")),
float(attrs.get('y', ""))
)
self.submesh.normals.append(normal)
if name == 'texcoord' and self.load_next_texture_coords:
uv = (
float(attrs.get('u', "")),
# flip vertical value, Blender's 0/0 is lower left
# whereas Ogre's 0/0 is upper left
1.0 - float(attrs.get('v', ""))
)
self.submesh.uvs.append(uv)
self.load_next_texture_coords = 0
if name == 'colour_diffuse':
self.submesh.vertexcolours.append(attrs.get('value', "").split())
def endElement(self, name):
if name == 'submesh':
self.mesh.submeshes.append(self.submesh)
self.submesh = 0
def setMaterial(ob, mat):
me = ob.data
me.materials.append(mat)
from xml.dom import minidom
def OpenFile(filename):
if filename.find('.xml') == -1:
convert_meshfile(filename)
filename += '.xml'
xml_file = open(filename, 'r')
xml_doc = minidom.parse(xml_file)
xml_file.close()
return xml_doc
def CreateSkeleton(skeleton):
global dirname
if skeleton != 0:
#scene = bpy.context.scene
filename = os.path.join(dirname, skeleton)
xml_doc = OpenFile(filename)
CreateBindSkeleton(xml_doc)
#CreateRestPoseAction(xml_doc)
#OGREBoneIDsDic(xml_doc)
def OGREBonesDic(xmldoc):
OGRE_Bones = {}
OGRE_Bone_List = []
for bones in xmldoc.getElementsByTagName('bones'):
for bone in bones.childNodes:
OGRE_Bone = {}
if bone.localName == 'bone':
BoneName = str(bone.getAttributeNode('name').value)
BoneId = int(bone.getAttributeNode('id').value)
OGRE_Bone['name'] = BoneName
OGRE_Bone['id'] = BoneId
for b in bone.childNodes:
if b.localName == 'position':
x = float(b.getAttributeNode('x').value)
y = float(b.getAttributeNode('y').value)
z = float(b.getAttributeNode('z').value)
OGRE_Bone['position'] = [x,y,z]
if b.localName == 'rotation':
angle = float(b.getAttributeNode('angle').value)
axis = b.childNodes[1]
axisx = float(axis.getAttributeNode('x').value)
axisy = float(axis.getAttributeNode('y').value)
axisz = float(axis.getAttributeNode('z').value)
OGRE_Bone['rotation'] = [axisx,axisy,axisz,angle]
OGRE_Bones[BoneName] = OGRE_Bone
OGRE_Bone_List.append(OGRE_Bone)
for bonehierarchy in xmldoc.getElementsByTagName('bonehierarchy'):
for boneparent in bonehierarchy.childNodes:
if boneparent.localName == 'boneparent':
Bone = str(boneparent.getAttributeNode('bone').value)
Parent = str(boneparent.getAttributeNode('parent').value)
OGRE_Bones[Bone]['parent'] = Parent
#return OGRE_Bone_List
return OGRE_Bones, OGRE_Bone_List
#骨骼的孩子节点
def ChildList(BonesData):
for bone in BonesData.keys():
childlist = []
for key in BonesData.keys():
if BonesData[key].get('parent'):
parent = BonesData[key]['parent']
if parent == bone:
childlist.append(BonesData[key])
BonesData[bone]['children'] = childlist
#获取所有骨骼的孩子列表缓存起来
#没有孩子节点 或者 有超过1个的孩子节点 的骨骼增加一个Helper骨骼 设置父亲为bone
def HelperBones(BonesData):
ChildList(BonesData)
count = 0
for bone in BonesData.keys():
if (len(BonesData[bone]['children']) == 0) or (len(BonesData[bone]['children']) > 1):
HelperBone = {}
HelperBone['position'] = [0.2,0.0,0.0]
HelperBone['parent'] = bone
HelperBone['rotation'] = [1.0,0.0,0.0,0.0]
HelperBone['flag'] = 'helper'
BonesData['Helper'+str(count)] = HelperBone
count+=1
#### 在 0 0 0 位置的骨骼 增加辅助的 0 骨骼到 parent上面
def ZeroBones(BonesData):
for bone in BonesData.keys():
pos = BonesData[bone]['position']
if (math.sqrt(pos[0]**2+pos[1]**2+pos[2]**2)) == 0:
ZeroBone = {}
ZeroBone['position'] = [0.2,0.0,0.0]
ZeroBone['rotation'] = [1.0,0.0,0.0,0.0]
if (BonesData[bone].get('parent')):
ZeroBone['parent'] = BonesData[bone]['parent']
ZeroBone['flag'] = 'zerobone'
BonesData['Zero'+bone] = ZeroBone
if (BonesData[bone].get('parent')):
BonesData[BonesData[bone]['parent']]['children'].append('Zero'+bone)
#计算骨骼长度
def CalcBoneLength(vec):
return math.sqrt(vec[0]**2+vec[1]**2+vec[2]**2)
#有parent的骨骼 设置父子关系
#创建特定位置的空物体
def CreateEmptys(BonesDic):
scn = Scene.GetCurrent()
for bone in BonesDic.keys():
obj = Object.New('Empty',bone)
scn.objects.link(obj)
for bone in BonesDic.keys():
if BonesDic[bone].has_key('parent'):
Parent = Object.Get(BonesDic[bone]['parent'])
object = Object.Get(bone)
Parent.makeParent([object])
for bone in BonesDic.keys():
obj = Object.Get(bone)
rot = BonesDic[bone]['rotation']
loc = BonesDic[bone]['position']
euler = Mathutils.RotationMatrix(math.degrees(rot[3]),3,'r',Mathutils.Vector(rot[0],-rot[2],rot[1])).toEuler()
obj.setLocation(loc[0],-loc[2],loc[1])
obj.setEuler(math.radians(euler[0]),math.radians(euler[1]),math.radians(euler[2]))
Redraw()
for bone in BonesDic.keys():
obj = Object.Get(bone)
rotmatAS = obj.getMatrix().rotationPart()
BonesDic[bone]['rotmatAS'] = rotmatAS
for bone in BonesDic.keys():
obj = Object.Get(bone)
scn.objects.unlink(obj)
del obj
def SetRestMatrix(BonesDic):
#for key in BonesDic.keys():
# bone =
pass
def SortData(bone, BonesData):
waitToVisit = [bone]
while len(waitToVisit) > 0:
b = waitToVisit.pop(0)
BonesData.append(b)
for c in b['children']:
waitToVisit.append(c)
def FindRoot(BonesList):
for c in BonesList:
if c['name'] == 'root':
return c
import mathutils
#create blender armature submesh multiple mesh use shared vertex or not share
#convert ogre joint to bones
def CreateBindSkeleton(xmldoc):
BonesDic, BonesList = OGREBonesDic(xmldoc)
#BonesData = BonesDic
BonesData = []
ChildList(BonesDic)
root = FindRoot(BonesList)
#root = BonesList[0]
if root == None:
log("not find root bone "+str(BonesList))
return
#sort from root
SortData(root, BonesData)
if len(BonesData) != len(BonesList):
log("sort bone not equal "+ str(len(BonesList)))
log("data is "+str(len(BonesData)))
log("lost Number is "+str(len(BonesList) - len(BonesData)))
setA = set([k['name'] for k in BonesList])
setB = set([k['name'] for k in BonesData])
difSet = setA-setB
for k in difSet:
log('lost '+k)
log(BonesDic[k])
return
#HelperBones(BonesDic)
#ZeroBones(BonesDic)
#CreateEmptys(BonesDic)
#SetBonesASPositions(BonesDic)
#BonesData = BonesDic
#scn = bpy.context.scene
#obj = bpy.data.objects.new("obj", objmesh)
#obj.location = bpy.context.scene.cursor_location
#bpy.context.scene.objects.link(obj)
arm = bpy.ops.object.add(type="ARMATURE", enter_editmode=True)
ob = bpy.context.object
ob.location = bpy.context.scene.cursor_location
ob.show_x_ray = True
amt = ob.data
amt.show_axes = True
for k in BonesData:
bone = amt.edit_bones.new(k['name'])
#posit
if k.get('parent'):
parent = amt.edit_bones[k['parent']]
bone.parent = parent
bone.head = parent.tail
bone.use_connect = False
(trans, rot, scale) = parent.matrix.decompose()
else:
bone.head = k['position']
#rot = mathutils.Matrix.Translation((0, 0, 0))
rot = Matrix.Rotation(k['rotation'][3], 3, k['rotation'][:3])
#rot = Matrix.Rotation(k['rotation'][3], 3, k['rotation'][:3])
#bone.head = k['position']
bone.tail = rot*Vector((0.3, 0, 0))+bone.head
log("create bone finish "+str(len(BonesList)))
def CreateBlenderMesh(name, mesh, materials):
#bmesh = Blender.NMesh.GetRaw()
#bmesh = bpy.data.meshes.new("test")
# dict matname:blender material
bmaterials = {}
bmat_idx = -1
log("Mesh with %d shared vertices." % len(mesh.vertices))
vertex_count = len(mesh.vertices)
shareVert = mesh.vertices
shareNormal = mesh.normals
shareUV = mesh.uvs
submesh_count = len(mesh.submeshes)
vertex_offset = 0
faces = []
for j in range(0, submesh_count):
submesh = mesh.submeshes[j]
vert = submesh.vertices
faces = submesh.faces
uvs = submesh.uvs
if submesh.sharedvertices == 1:
vert = shareVert
uvs = shareUV
objmesh = bpy.data.meshes.new("mesh"+str(j))
obj = bpy.data.objects.new("obj"+str(j), objmesh)
obj.location = bpy.context.scene.cursor_location
bpy.context.scene.objects.link(obj)
objmesh.from_pydata(vert, [], faces)
objmesh.update(calc_edges=True)
#obj.select = True
obj.select = True
bpy.context.scene.objects.active = obj
bpy.ops.object.mode_set(mode="EDIT")
#if bpy.context.mode == 'EDIT_MESH':
#for f in bm.faces:
#add uv coordinate
obj = bpy.context.active_object
me = obj.data
bm = bmesh.from_edit_mesh(me)
uv_layer = bm.loops.layers.uv.verify()
bm.faces.layers.tex.verify()
for f in bm.faces:
for l in f.loops:
luv = l[uv_layer]
ind = l.vert.index
luv.uv = Vector(uvs[ind])
bmesh.update_edit_mesh(me)
bpy.ops.object.mode_set(mode="OBJECT")
#bmesh.from_pydata(vert, [], faces)
#break
if materials.get(submesh.materialname):
omat = materials[submesh.materialname]
bmat = 0
if not bmaterials.get(submesh.materialname):
bmat = create_blender_material(omat)
bmaterials[submesh.materialname] = bmat
else:
bmat = bmaterials[submesh.materialname]
setMaterial(obj, bmat)
#设置模型材质
bpy.ops.object.join()
"""
for i in range(0, vertex_count):
ogre_v = mesh.vertices[i]
dlog(" vertex %d with XYZ: %f %f %f" %\
(i, ogre_v[0], ogre_v[1], ogre_v[2]))
blender_v = Blender.NMesh.Vert(ogre_v[0], ogre_v[1], ogre_v[2])
if len(mesh.normals):
# Set the normals
blender_v.no[0] = mesh.normals[i][0]
blender_v.no[1] = mesh.normals[i][1]
blender_v.no[2] = mesh.normals[i][2]
if len(mesh.uvs):
# Set the sticky per vertex uvs
blender_v.uvco[0] = mesh.uvs[i][0]
blender_v.uvco[1] = mesh.uvs[i][1]
bmesh.verts.append(blender_v)
submesh_count = len(mesh.submeshes)
vertex_offset = 0
for j in range(0, submesh_count):
submesh = mesh.submeshes[j]
if materials.has_key(submesh.materialname):
omat = materials[submesh.materialname]
bmat = 0
if (not bmaterials.has_key(omat.name)):
bmat = create_blender_material(omat)
bmaterials[submesh.materialname] = bmat
bmesh.addMaterial(bmat)
else:
bmat = bmaterials[submesh.materialname]
bmat_idx = bmesh.materials.index(bmat)
else:
omat = 0
bmat = 0
bmat_idx = -1
log("Submesh %d with %d vertices and %d faces..." % \
(j, len(submesh.vertices), len(submesh.faces)))
# transfer vertices
vertex_count = len(submesh.vertices)
for i in range(0, vertex_count):
ogre_v = submesh.vertices[i]
blender_v = Blender.NMesh.Vert(ogre_v[0], ogre_v[1], ogre_v[2])
if len(submesh.normals):
# Set the normals
blender_v.no[0] = submesh.normals[i][0]
blender_v.no[1] = submesh.normals[i][1]
blender_v.no[2] = submesh.normals[i][2]
if len(submesh.uvs):
# Set the sticky per vertex uvs
blender_v.uvco[0] = submesh.uvs[i][0]
blender_v.uvco[1] = submesh.uvs[i][1]
bmesh.verts.append(blender_v)
# transfer faces
face_count = len(submesh.faces)
# decide whether to take colours and uvs from shared buffer or
# from the submesh
faces = submesh.faces
if submesh.sharedvertices == 1:
uvs = mesh.uvs
vertexcolours = mesh.vertexcolours
else:
uvs = submesh.uvs
vertexcolours = submesh.vertexcolours
for i in range(0, face_count):
ogre_f = submesh.faces[i]
dlog("face %d : %f/%f/%f" % (i, ogre_f[0], ogre_f[1], ogre_f[1]))
f = Blender.NMesh.Face()
if omat and omat.getTexture():
f.mode |= Blender.NMesh.FaceModes['TEX']
f.image = omat.getTexture()
if bmat:
f.materialIndex = bmat_idx
f.v.append(bmesh.verts[ogre_f[0] + vertex_offset])
f.v.append(bmesh.verts[ogre_f[1] + vertex_offset])
f.v.append(bmesh.verts[ogre_f[2] + vertex_offset])
if len(uvs):
f.uv.append(uvs[ogre_f[0]])
f.uv.append(uvs[ogre_f[1]])
f.uv.append(uvs[ogre_f[2]])
if len(submesh.vertexcolours):
f.mode |= Blender.NMesh.FaceModes['SHAREDCOL']
for k in range(3):
col = Blender.NMesh.Col()
col.r = int(float(vertexcolours[ogre_f[k]][0])*255.0)
col.g = int(float(vertexcolours[ogre_f[k]][1])*255.0)
col.b = int(float(vertexcolours[ogre_f[k]][2])*255.0)
col.a = 255
f.col.append(col)
bmesh.faces.append(f)
# vertices of the new submesh are appended to the NMesh's vertex buffer
# this offset is added to the indices in the index buffer, so that
# the right vertices are indexed
vertex_offset += vertex_count
log("done.")
# bmesh.hasVertexUV(len(submesh.uvs))
# TODO: investigate and fix
# Why oh why ain't this line working...
# bmesh.hasFaceUV(len(submesh.uvs))
# ...have to hard set it.
bmesh.hasFaceUV(1)
"""
# create the mesh
#object = Blender.Object.New('Mesh', name)
#object.link(bmesh)
return None
def convert_meshfile(filename):
log("convert file "+filename)
if IMPORT_OGREXMLCONVERTER != '':
commandline = IMPORT_OGREXMLCONVERTER +' -log /Users/liyong/err.log '+ ' "' + filename + '"' + ' "'+ filename + '.xml' + '"'
log("executing %s" % commandline)
log(os.path.abspath('.'))
status = os.system(commandline)
log('status '+str(status))
log("done.")
#set ambient diffuse specular emissive color
#def collect_materials(dirname):
# matname_pattern = re.compile('^\s*material\s+(.*?)\s*$')
def collect_materials(dirname):
# preparing some patterns
# to collect the material name
matname_pattern = re.compile('^\s*material\s+(.*?)\s*$')
# to collect the texture name
texname_pattern = re.compile('^\s*texture\s+(.*?)\s*$')
# to collect the diffuse colour
diffuse_alpha_pattern = re.compile(\
'^\s*diffuse\s+([^\s]+?)\s+([^\s]+?)\s+([^\s]+?)\s+([^\s]+).*$')
diffuse_pattern = re.compile(\
'^\s*diffuse\s+([^\s]+?)\s+([^\s]+?)\s+([^\s]+).*$')
# to collect the specular colour
specular_pattern = re.compile(\
'^\s*specular\s+([^\s]+?)\s+([^\s]+?)\s+([^\s]+).*$')
ambient_pattern = re.compile(
'^\s*ambient\s+([^\s]+?)\s+([^\s]+?)\s+([^\s]+).*$')
# the dictionary where to put the materials
materials = {}
# for all lines in all material files..
material_files = glob.glob(dirname + '/*.material')
material = 0
for filename in material_files:
f = open(filename, 'r')
line_number = 0
for line in f:
try:
line_number = line_number + 1
dlog("line to be matched: %s" % line)
#m = matname_pattern.match(line)
mat_name = matname_pattern.findall(line)
if len(mat_name) > 0:
material = Material(mat_name[0])
materials[material.name] = material
vlog("parsing material %s" % mat_name[0])
#m = texname_pattern.match(line)
tex_name = texname_pattern.findall(line)
# load only the first texture unit's texture
# TODO change to use the first one using the first uv set
if len(tex_name) > 0 and not material.texname:
#if m and not material.texname:
material.texname = dirname + '/' + tex_name[0]
m = diffuse_alpha_pattern.match(line)
if not m:
m = diffuse_pattern.match(line)
if m:
vlog(" parsing diffuse..")
groups = m.groups()
r = float(groups[0])
g = float(groups[1])
b = float(groups[2])
#TODO: alpha still untested
if len(groups) > 3:
a = float(groups[3])
else:
a = 1.0
material.diffuse = (r, g, b, a)
vlog(" diffuse: %s" % str(material.diffuse))
m = specular_pattern.match(line)
if m:
vlog(" parsing specular..")
groups = m.groups()
r = float(groups[0])
g = float(groups[1])
b = float(groups[2])
material.specular = (r, g, b, 1.0)
vlog(" specular: %s" % str(material.specular))
except Exception as e:
log(" error parsing material %s in %s on line % d: " % \
(material.name, filename, line_number))
log(" exception: %s" % str(e))
return materials
def create_blender_material(omat):
mat = bpy.data.materials.new(omat.name)
mat.diffuse_color = omat.diffuse[:3]
mat.diffuse_shader = 'LAMBERT'
mat.diffuse_intensity = 1.0
mat.specular_color = omat.specular[:3]
mat.specular_shader = 'COOKTORR'
mat.specular_intensity = 1.0
mat.alpha = omat.diffuse[3]
mat.ambient = 1
img = omat.getTexture()
if img:
cTex = bpy.data.textures.new(omat.texname, type="IMAGE")
cTex.image = img
mtex = mat.texture_slots.add()
mtex.texture = cTex
mtex.texture_coords = "UV"
mtex.use_map_color_diffuse = True
#mtex.use_map_color_emission = True
#mtex.emission_color_factor = 0.5
#mtex.use_map_density = True
mtex.mapping = "FLAT"
return mat
'''
bmat = Blender.Material.New(omat.name)
bmat.rgbCol = (omat.diffuse[0], omat.diffuse[1], omat.diffuse[2])
bmat.specCol = (omat.specular[0], omat.specular[1], omat.specular[2])
bmat.alpha = omat.diffuse[3]
img = omat.getTexture()
if img:
tex = Blender.Texture.New(omat.texname)
tex.setType('Image')
tex.setImage(omat.getTexture())
bmat.setTexture(0, tex, Blender.Texture.TexCo.UV,\
Blender.Texture.MapTo.COL)
return bmat
'''
#return None
dirname = None
basename = None
def fileselection_callback(filename):
log("Reading mesh file %s..." % filename)
filename = os.path.expanduser(filename)
#if fileName:
# (shortName, ext) = os.path.splitext(filename)
# is this a mesh file instead of an xml file?
if (filename.lower().find('.xml') == -1):
# No. Use the xml converter to fix this
log("No mesh.xml file. Trying to convert it from binary mesh format.")
convert_meshfile(filename)
filename += '.xml'
global dirname
global basename
dirname = os.path.dirname(filename)
basename = os.path.basename(filename)
#dirname = sys.dirname(filename)
#basename = Blender.sys.basename(filename)
# parse material files and make up a dictionary: {mat_name:material, ..}
materials = collect_materials(dirname)
#create materials
# prepare the SAX parser and parse the file using our own content handler
parser = xml.sax.make_parser()
handler = OgreMeshSaxHandler()
parser.setContentHandler(handler)
parser.parse(open(filename))
# create the mesh from the parsed data and link it to a fresh object
#scene = Blender.Scene.GetCurrent()
meshname = basename[0:basename.lower().find('.mesh.xml')]
obj = CreateBlenderMesh(meshname, handler.mesh, materials)
amt = CreateSkeleton(handler.skeleton)
#scene.link(object)
#object.select = True
log("import completed.")
#Blender.Redraw()
def clearScene():
#global toggle
scn = bpy.context.scene
log("clearScene ")
for ob in scn.objects:
if ob.type in ["MESH", "CURVE", "TEXT"]:
scn.objects.active = ob
bpy.ops.object.mode_set(mode='OBJECT')
scn.objects.unlink(ob)
del ob
return scn
#Blender.Window.FileSelector(fileselection_callback, "Import OGRE", "*.xml")
from bpy.props import *
class IMPORT_OT_OGRE(bpy.types.Operator):
bl_idname = "import_scene.ogre_mesh"
bl_description = 'Import from mesh file format (.mesh)'
bl_label = "Import mesh" +' v.'+ __version__
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_options = {'UNDO'}
filepath = StringProperty(
subtype='FILE_PATH',
)
def draw(self, context):
layout0 = self.layout
#layout0.enabled = False
#col = layout0.column_flow(2,align=True)
layout = layout0.box()
col = layout.column()
#col.prop(self, 'KnotType') waits for more knottypes
#col.label(text="import Parameters")
#col.prop(self, 'replace')
#col.prop(self, 'new_scene')
#row = layout.row(align=True)
#row.prop(self, 'curves')
#row.prop(self, 'circleResolution')
#row = layout.row(align=True)
#row.prop(self, 'merge')
#if self.merge:
# row.prop(self, 'mergeLimit')
#row = layout.row(align=True)
#row.label('na')
#row.prop(self, 'draw_one')
#row.prop(self, 'thic_on')
#col = layout.column()
#col.prop(self, 'codec')
#row = layout.row(align=True)
#ow.prop(self, 'debug')
#if self.debug:
# row.prop(self, 'verbose')
def execute(self, context):
'''
global toggle, theMergeLimit, theCodec, theCircleRes
O_Merge = T_Merge if self.merge else 0
#O_Replace = T_Replace if self.replace else 0
O_NewScene = T_NewScene if self.new_scene else 0
O_Curves = T_Curves if self.curves else 0
O_ThicON = T_ThicON if self.thic_on else 0
O_DrawOne = T_DrawOne if self.draw_one else 0
O_Debug = T_Debug if self.debug else 0
O_Verbose = T_Verbose if self.verbose else 0
toggle = O_Merge | O_DrawOne | O_NewScene | O_Curves | O_ThicON | O_Debug | O_Verbose
theMergeLimit = self.mergeLimit*1e-4
theCircleRes = self.circleResolution
theCodec = self.codec
'''
#bpy.ops.wm.read_homefile()
clearScene()
#readAndBuildDxfFile(self.filepath)
fileselection_callback(self.filepath)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
wm.fileselect_add(self)
return {'RUNNING_MODAL'}
def menu_func(self, context):
self.layout.operator(IMPORT_OT_OGRE.bl_idname, text="ogre (.mesh)")
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_import.append(menu_func)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_import.remove(menu_func)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment