forked from bartvdbraak/blender
c702b237d5
-- adding help_browser.py to show help for installed scripts; -- updated scripts to include basic doc info to be shown with above script: script authors can / will / should update with more info, of course; -- updated some scripts to newer versions: disp_paint, fixfromarmature, hotkeys, etc.
457 lines
15 KiB
Python
457 lines
15 KiB
Python
#!BPY
|
|
|
|
""" Registration info for Blender menus:
|
|
Name: 'DirectX (.x)...'
|
|
Blender: 234
|
|
Group: 'Export'
|
|
Submenu: 'Only mesh data...' mesh
|
|
Submenu: 'Animation(not armature yet)...' anim
|
|
Tip: 'Export to DirectX text file format'
|
|
"""
|
|
|
|
__author__ = "Arben (Ben) Omari"
|
|
__url__ = ("blender", "elysiun", "Author's site, http://www.omariben.too.it")
|
|
__version__ = "1.0"
|
|
|
|
__bpydoc__ = """\
|
|
This script exports Blender uv-textured meshes with animation frame keys to
|
|
DirectX 7's text file format.
|
|
|
|
Usage:
|
|
|
|
Run the script and check console for possible warning messages.
|
|
|
|
Supported:<br>
|
|
UV-textured meshes with animation frame (location, rotation) keys.
|
|
|
|
Known issues:<br>
|
|
Some DX format viewers don't support Material names with dots
|
|
('.') in them.
|
|
|
|
Notes:<br>
|
|
Check author's site or the elYsiun forum for a new beta version of the
|
|
DX exporter.
|
|
"""
|
|
|
|
|
|
# $Id$
|
|
#
|
|
# DirectX.py version 1.0
|
|
# Copyright (C) 2003 Arben OMARI -- omariarben@everyday.com
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
|
|
# This script export meshes created with Blender in DirectX file format
|
|
# it exports meshes,materials,normals,texturecoords and and animations
|
|
|
|
# Grab the latest version here :www.omariben.too.it
|
|
|
|
import Blender
|
|
from Blender import Types, Object, NMesh, Material
|
|
#import string
|
|
from math import *
|
|
|
|
|
|
|
|
|
|
#***********************************************
|
|
#***********************************************
|
|
# EXPORTER
|
|
#***********************************************
|
|
#***********************************************
|
|
|
|
class xExport:
|
|
def __init__(self, filename):
|
|
self.file = open(filename, "w")
|
|
|
|
#***********************************************
|
|
# Export animations
|
|
#***********************************************
|
|
def exportAnim(self):
|
|
tex = []
|
|
print "exporting ..."
|
|
self.writeHeader()
|
|
for name in Object.Get():
|
|
obj = name.getData()
|
|
if type(obj) == Types.NMeshType :
|
|
|
|
self.writeFrames(name, obj)
|
|
self.writeMeshcoord(name, obj )
|
|
self.writeMeshMaterialList(name, obj, tex)
|
|
self.writeMeshNormals(name, obj)
|
|
self.writeMeshTextureCoords(name, obj)
|
|
self.file.write("}\n")
|
|
self.file.write("}\n")
|
|
self.writeAnimation(name, obj)
|
|
|
|
self.writeEnd()
|
|
|
|
#***********************************************
|
|
# Export geometry
|
|
#***********************************************
|
|
def exportTex(self):
|
|
tex = []
|
|
print "exporting ..."
|
|
self.writeHeader()
|
|
for name in Object.Get():
|
|
obj = name.getData()
|
|
if type(obj) == Types.NMeshType :
|
|
self.writeMeshcoord(name, obj )
|
|
self.writeMeshMaterialList(name, obj, tex)
|
|
self.writeMeshNormals(name, obj)
|
|
self.writeMeshTextureCoords(name, obj)
|
|
self.file.write("}\n")
|
|
|
|
self.writeEnd()
|
|
|
|
#***********************************************
|
|
#HEADER
|
|
#***********************************************
|
|
def writeHeader(self):
|
|
self.file.write("xof 0302txt 0064\n")
|
|
self.file.write("\n")
|
|
self.file.write("Header{\n")
|
|
self.file.write("1;0;1;\n")
|
|
self.file.write("}\n")
|
|
|
|
#***********************************************
|
|
#CLOSE FILE
|
|
#***********************************************
|
|
def writeEnd(self):
|
|
self.file.close()
|
|
print "... finished"
|
|
|
|
|
|
|
|
#***********************************************
|
|
#EXPORT TEXTURES
|
|
#***********************************************
|
|
def writeTextures(self,name, tex):
|
|
mesh = name.data
|
|
for face in mesh.faces:
|
|
if face.image and face.image.name not in tex:
|
|
tex.append(face.image.name)
|
|
|
|
|
|
#***********************************************
|
|
#EXPORT MESH DATA
|
|
#***********************************************
|
|
def writeMeshcoord(self, name, obj ):
|
|
|
|
self.file.write("Mesh Mesh_%s {\n" % (name.name))
|
|
numfaces=len(obj.faces)
|
|
#POSITION
|
|
loc = name.getMatrix()
|
|
x = loc[3][0]
|
|
y = loc[3][1]
|
|
z = loc[3][2]
|
|
#VERTICES NUMBER
|
|
mesh = name.data
|
|
numvert = 0
|
|
for face in mesh.faces:
|
|
numvert = numvert + len(face.v)
|
|
self.file.write("%s;\n" % (numvert))
|
|
#VERTICES COORDINATES
|
|
counter = 0
|
|
for face in mesh.faces:
|
|
counter += 1
|
|
if counter == numfaces:
|
|
if len(face.v) == 4:
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[0].co[0] + x), face.v[0].co[1] + y, face.v[0].co[2] + z))
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[1].co[0] + x), face.v[1].co[1] + y, face.v[1].co[2] + z))
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[2].co[0] + x), face.v[2].co[1] + y, face.v[2].co[2] + z))
|
|
self.file.write("%s; %s; %s;;\n" % ((face.v[3].co[0] + x), face.v[3].co[1] + y, face.v[3].co[2] + z))
|
|
elif len(face.v) == 3 :
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[0].co[0] + x), face.v[0].co[1] + y, face.v[0].co[2] + z))
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[1].co[0] + x), face.v[1].co[1] + y, face.v[1].co[2] + z))
|
|
self.file.write("%s; %s; %s;;\n" % ((face.v[2].co[0] + x), face.v[2].co[1] + y, face.v[2].co[2] + z))
|
|
|
|
else :
|
|
if len(face.v) == 4:
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[0].co[0] + x), face.v[0].co[1] + y, face.v[0].co[2] + z))
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[1].co[0] + x), face.v[1].co[1] + y, face.v[1].co[2] + z))
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[2].co[0] + x), face.v[2].co[1] + y, face.v[2].co[2] + z))
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[3].co[0] + x), face.v[3].co[1] + y, face.v[3].co[2] + z))
|
|
elif len(face.v) == 3:
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[0].co[0] + x), face.v[0].co[1] + y, face.v[0].co[2] + z))
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[1].co[0] + x), face.v[1].co[1] + y, face.v[1].co[2] + z))
|
|
self.file.write("%s; %s; %s;,\n" % ((face.v[2].co[0] + x), face.v[2].co[1] + y, face.v[2].co[2] + z))
|
|
|
|
|
|
|
|
#FACES NUMBER
|
|
|
|
self.file.write("%s;\n" % (numfaces))
|
|
#FACES INDEX
|
|
numface=len(obj.faces)
|
|
coun,counter = 0, 0
|
|
for face in mesh.faces :
|
|
coun += 1
|
|
if coun == numface:
|
|
if len(face.v) == 3:
|
|
self.file.write("3; %s; %s; %s;;\n" % (counter, counter + 1, counter + 2))
|
|
counter += 3
|
|
elif len(face.v) == 4:
|
|
self.file.write("4; %s; %s; %s; %s;;\n" % (counter, counter + 1, counter + 2, counter + 3))
|
|
counter += 4
|
|
elif len(face.v) == 2:
|
|
print "WARNING:the mesh has faces with less then 3 vertices"
|
|
else:
|
|
|
|
if len(face.v) == 3:
|
|
self.file.write("3; %s; %s; %s;,\n" % (counter, counter + 1, counter + 2))
|
|
counter += 3
|
|
elif len(face.v) == 4:
|
|
self.file.write("4; %s; %s; %s; %s;,\n" % (counter, counter + 1, counter + 2, counter + 3))
|
|
counter += 4
|
|
elif len(face.v) == 2:
|
|
print "WARNING:the mesh has faces with less then 3 vertices"
|
|
|
|
|
|
|
|
|
|
|
|
#***********************************************
|
|
#MESH MATERIAL LIST
|
|
#***********************************************
|
|
def writeMeshMaterialList(self, name, obj, tex):
|
|
self.file.write(" MeshMaterialList {\n")
|
|
#HOW MANY MATERIALS ARE USED
|
|
count = 0
|
|
for mat in Material.Get():
|
|
count+=1
|
|
self.file.write(" %s;\n" % (len(tex) + count))
|
|
#HOW MANY FACES IT HAS
|
|
numfaces=len(obj.faces)
|
|
self.file.write(" %s;\n" % (numfaces))
|
|
##MATERIALS INDEX FOR EVERY FACE
|
|
counter = 0
|
|
for face in obj.faces :
|
|
counter += 1
|
|
mater = face.materialIndex
|
|
if counter == numfaces:
|
|
if face.image and face.image.name in tex :
|
|
self.file.write(" %s;;\n" % (tex.index(face.image.name) + count))
|
|
else :
|
|
self.file.write(" %s;;\n" % (mater))
|
|
else :
|
|
if face.image and face.image.name in tex :
|
|
self.file.write(" %s,\n" % (tex.index(face.image.name) + count))
|
|
else :
|
|
self.file.write(" %s,\n" % (mater))
|
|
|
|
##MATERIAL NAME
|
|
for mat in Material.Get():
|
|
self.file.write(" Material")
|
|
for a in range(0,len(mat.name)):
|
|
if mat.name[a] == ".":
|
|
print "WARNING:the material " + mat.name + " contains '.' within.Many viewers may refuse to read the exported file"
|
|
self.file.write(" %s "% (mat.name))
|
|
self.file.write("{\n")
|
|
self.file.write(" %s; %s; %s;" % (mat.R, mat.G, mat.B))
|
|
self.file.write("%s;;\n" % (mat.alpha))
|
|
self.file.write(" %s;\n" % (mat.spec))
|
|
self.file.write(" %s; %s; %s;;\n" % (mat.specR, mat.specG, mat.specB))
|
|
self.file.write(" 0.0; 0.0; 0.0;;\n")
|
|
self.file.write(" }\n")
|
|
|
|
for mat in tex:
|
|
self.file.write(" Material Mat")
|
|
self.file.write("%s "% (len(tex)))
|
|
self.file.write("{\n")
|
|
self.file.write(" 1.0; 1.0; 1.0; 1.0;;\n")
|
|
self.file.write(" 1.0;\n")
|
|
self.file.write(" 1.0; 1.0; 1.0;;\n")
|
|
self.file.write(" 0.0; 0.0; 0.0;;\n")
|
|
self.file.write(" TextureFilename {\n")
|
|
self.file.write(' "%s" ;'% (face.image.name))
|
|
self.file.write(" }\n")
|
|
self.file.write(" }\n")
|
|
self.file.write(" }\n")
|
|
#***********************************************
|
|
#MESH NORMALS
|
|
#***********************************************
|
|
def writeMeshNormals(self,name,obj):
|
|
self.file.write(" MeshNormals {\n")
|
|
#VERTICES NUMBER
|
|
numvert=len(obj.verts)
|
|
self.file.write("%s;\n" % (numvert))
|
|
#VERTICES NORMAL
|
|
counter = 0
|
|
for vert in obj.verts:
|
|
counter += 1
|
|
if counter == numvert:
|
|
self.file.write("%s; %s; %s;;\n" % (vert.no[0], vert.no[1], vert.no[2]))
|
|
else :
|
|
self.file.write("%s; %s; %s;,\n" % (vert.no[0], vert.no[1], vert.no[2]))
|
|
#FACES NUMBER
|
|
numfaces=len(obj.faces)
|
|
self.file.write("%s;\n" % (numfaces))
|
|
#FACES INDEX
|
|
counter = 0
|
|
for face in obj.faces :
|
|
counter += 1
|
|
if counter == numfaces:
|
|
if len(face.v) == 3:
|
|
self.file.write("3; %s; %s; %s;;\n" % (face[0].index, face[1].index, face[2].index))
|
|
elif len(face.v) == 4:
|
|
self.file.write("4; %s; %s; %s; %s;;\n" % (face[0].index, face[1].index, face[2].index, face[3].index))
|
|
else:
|
|
if len(face.v) == 3:
|
|
self.file.write("3; %s; %s; %s;,\n" % (face[0].index, face[1].index, face[2].index))
|
|
elif len(face.v) == 4 :
|
|
self.file.write("4; %s; %s; %s; %s;,\n" % (face[0].index, face[1].index, face[2].index, face[3].index))
|
|
self.file.write("}\n")
|
|
#***********************************************
|
|
#MESH TEXTURE COORDS
|
|
#***********************************************
|
|
def writeMeshTextureCoords(self, name, obj):
|
|
if obj.hasFaceUV():
|
|
self.file.write("MeshTextureCoords {\n")
|
|
#VERTICES NUMBER
|
|
mesh = name.data
|
|
numvert = 0
|
|
for face in mesh.faces:
|
|
numvert = numvert + len(face.v)
|
|
self.file.write("%s;\n" % (numvert))
|
|
#UV COORDS
|
|
counter = -1
|
|
for face in mesh.faces:
|
|
counter += 1
|
|
if len(face.v) == 4:
|
|
self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[0][0], -mesh.faces[counter].uv[0][1]))
|
|
self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[1][0], -mesh.faces[counter].uv[1][1]))
|
|
self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[2][0], -mesh.faces[counter].uv[2][1]))
|
|
self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[3][0], -mesh.faces[counter].uv[3][1]))
|
|
elif len(face.v) == 3:
|
|
self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[0][0], -mesh.faces[counter].uv[0][1]))
|
|
self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[1][0], -mesh.faces[counter].uv[1][1]))
|
|
self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[2][0], -mesh.faces[counter].uv[2][1]))
|
|
|
|
self.file.write("}\n")
|
|
|
|
#***********************************************
|
|
#FRAMES
|
|
#***********************************************
|
|
def writeFrames(self, name, obj):
|
|
matx = name.getMatrix()
|
|
self.file.write("Frame Fr_")
|
|
self.file.write("%s {\n" % (obj.name))
|
|
self.file.write(" FrameTransformMatrix {\n")
|
|
self.file.write(" %s,%s,%s,%s,\n" %
|
|
(round(matx[0][0],6),round(matx[0][1],6),round(matx[0][2],6),round(matx[0][3],6)))
|
|
self.file.write(" %s,%s,%s,%s,\n" %
|
|
(round(matx[1][0],6),round(matx[1][1],6),round(matx[1][2],6),round(matx[1][3],6)))
|
|
self.file.write(" %s,%s,%s,%s,\n" %
|
|
(round(matx[2][0],6),round(matx[2][1],6),round(matx[2][2],6),round(matx[2][3],6)))
|
|
self.file.write(" %s,%s,%s,%s;;\n" %
|
|
(round(matx[3][0],6),round(matx[3][1],6),round(matx[3][2],6),round(matx[3][3],6)))
|
|
self.file.write(" }\n")
|
|
#***********************************************
|
|
#WRITE ANIMATION KEYS
|
|
#***********************************************
|
|
def writeAnimation(self, name, obj):
|
|
startFr = Blender.Get('staframe')
|
|
endFr = Blender.Get('endframe')
|
|
self.file.write("AnimationSet animset_")
|
|
self.file.write("%s {\n" % (obj.name))
|
|
self.file.write(" Animation anim_")
|
|
self.file.write("%s { \n" % (obj.name))
|
|
self.file.write(" {Fr_")
|
|
self.file.write("%s }\n" % (obj.name))
|
|
self.file.write(" AnimationKey { \n")
|
|
self.file.write(" 0;\n")
|
|
self.file.write(" %s; \n" % (endFr))
|
|
for fr in range(startFr,endFr + 1) :
|
|
self.file.write(" %s; " % (fr))
|
|
self.file.write("4; ")
|
|
Blender.Set('curframe',fr)
|
|
rot = name.rot
|
|
rot_x = rot[0]
|
|
rot_y = rot[1]
|
|
rot_z = rot[2]
|
|
quat = self.euler2quat(rot_x,rot_y,rot_z)
|
|
self.file.write("%s, %s, %s,%s;;" %
|
|
(quat[0],quat[1],quat[2],quat[3]))
|
|
if fr == endFr:
|
|
self.file.write(";\n")
|
|
else:
|
|
self.file.write(",\n")
|
|
self.file.write(" }\n")
|
|
self.file.write(" AnimationKey { \n")
|
|
self.file.write(" 2;\n")
|
|
self.file.write(" %s; \n" % (endFr))
|
|
for fr in range(startFr,endFr + 1) :
|
|
self.file.write(" %s; " % (fr))
|
|
self.file.write("3; ")
|
|
Blender.Set('curframe',fr)
|
|
loc = name.loc
|
|
self.file.write("%s, %s, %s;;" %
|
|
(loc[0],loc[1],loc[2]))
|
|
if fr == endFr:
|
|
self.file.write(";\n")
|
|
else:
|
|
self.file.write(",\n")
|
|
self.file.write(" }\n")
|
|
self.file.write(" AnimationKey { \n")
|
|
self.file.write(" 1;\n")
|
|
self.file.write(" %s; \n" % (endFr))
|
|
for fr in range(startFr,endFr + 1) :
|
|
self.file.write(" %s; " % (fr))
|
|
self.file.write("3; ")
|
|
Blender.Set('curframe',fr)
|
|
size = name.size
|
|
self.file.write("%s, %s, %s;;" %
|
|
(size[0],size[1],size[2]))
|
|
if fr == endFr:
|
|
self.file.write(";\n")
|
|
else:
|
|
self.file.write(",\n")
|
|
self.file.write(" }\n")
|
|
self.file.write(" }\n")
|
|
self.file.write(" }\n")
|
|
|
|
def euler2quat(self,rot_x,rot_y,rot_z):
|
|
c_x = cos(rot_x / 2)
|
|
c_y = cos(rot_y / 2)
|
|
c_z = cos(rot_z / 2)
|
|
|
|
s_x = sin(rot_x / 2)
|
|
s_y = sin(rot_y / 2)
|
|
s_z = sin(rot_z / 2)
|
|
|
|
cy_cz = c_y * c_z
|
|
sy_sz = s_y * s_z
|
|
|
|
quat_w = c_x * cy_cz - s_x * sy_sz
|
|
quat_x = s_x * cy_cz + c_x * sy_sz
|
|
quat_y = c_x * s_y * c_z - s_x * c_y * s_z
|
|
quat_z = c_x * c_y * s_z + s_x * s_y * c_z
|
|
|
|
return(quat_w,quat_x,quat_y,quat_z)
|
|
|
|
#***********************************************
|
|
# MAIN
|
|
#***********************************************
|
|
|
|
|
|
def my_callback(filename):
|
|
if filename.find('.x', -2) <= 0: filename += '.x' # add '.x' if the user didn't
|
|
xexport = xExport(filename)
|
|
arg = __script__['arg']
|
|
if arg == 'anim':
|
|
xexport.exportAnim()
|
|
else:
|
|
xexport.exportTex()
|
|
|
|
fname = Blender.sys.makename(ext = ".x")
|
|
Blender.Window.FileSelector(my_callback, "Export DirectX",fname)
|