Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillian Padovani Germano <wpgermano@gmail.com>2006-01-29 22:17:53 +0300
committerWillian Padovani Germano <wpgermano@gmail.com>2006-01-29 22:17:53 +0300
commit4b01aa7aa57d144baf1739e4bcd65716f95dabfd (patch)
tree704a96276eab337b8be793cf1ba8679dcf7178dc /release
parent282fbcc763857cf5a6b81f65ddffd589462836b1 (diff)
Scripts:
The orange -> HEAD merge reverted some scripts to older versions. This only affected the ones that already existed before the orange branch. Minor issue, easy to fix. All in all, kudos to kaito, Hos and others for all the hard work in bringing (coding, merging) all these changes to the main branch.
Diffstat (limited to 'release')
-rw-r--r--release/scripts/Apply_def.py64
-rw-r--r--release/scripts/Axiscopy.py18
-rw-r--r--release/scripts/DirectX8Exporter.py307
-rw-r--r--release/scripts/ac3d_export.py3
-rw-r--r--release/scripts/ac3d_import.py12
-rw-r--r--release/scripts/bevel_center.py674
-rw-r--r--release/scripts/bpymodules/meshtools.py31
-rw-r--r--release/scripts/bpymodules/svg2obj.py1283
-rw-r--r--release/scripts/bvh2arm.py364
-rw-r--r--release/scripts/bvh_export.py575
-rw-r--r--release/scripts/bvh_import.py877
-rw-r--r--release/scripts/console.py62
-rw-r--r--release/scripts/hotkeys.py159
-rw-r--r--release/scripts/lightwave_export.py21
-rw-r--r--release/scripts/lightwave_import.py814
-rw-r--r--release/scripts/nendo_export.py21
-rw-r--r--release/scripts/nendo_import.py21
-rw-r--r--release/scripts/obj_export.py508
-rw-r--r--release/scripts/obj_import.py343
-rw-r--r--release/scripts/off_export.py23
-rw-r--r--release/scripts/off_import.py24
-rw-r--r--release/scripts/radiosity_export.py21
-rw-r--r--release/scripts/radiosity_import.py21
-rw-r--r--release/scripts/raw_export.py22
-rw-r--r--release/scripts/raw_import.py21
-rw-r--r--release/scripts/save_theme.py35
-rw-r--r--release/scripts/skin.py4
-rw-r--r--release/scripts/slp_import.py21
-rw-r--r--release/scripts/tex2uvbaker.py105
-rw-r--r--release/scripts/truespace_export.py22
-rw-r--r--release/scripts/truespace_import.py21
-rw-r--r--release/scripts/uv_export.py93
-rw-r--r--release/scripts/videoscape_export.py22
-rw-r--r--release/scripts/vrml97_export.py139
-rw-r--r--release/scripts/wings_export.py21
-rw-r--r--release/scripts/wings_import.py191
-rw-r--r--release/scripts/x3d_export.py126
37 files changed, 4244 insertions, 2845 deletions
diff --git a/release/scripts/Apply_def.py b/release/scripts/Apply_def.py
index bdcae3744ec..f0e3c029b50 100644
--- a/release/scripts/Apply_def.py
+++ b/release/scripts/Apply_def.py
@@ -54,49 +54,55 @@ directly manipulate or export its data.
#
# ***** END GPL LICENCE BLOCK *****
+
import Blender
Blender.Window.EditMode(0)
+NAME_LENGTH = 19
+PREFIX = "_def"
+PREFIX_LENGTH = len(PREFIX)
+
ob_list = Blender.Object.GetSelected()
+
+for ob in ob_list:
+ ob.sel = 0
+
+used_names = [ob.name for ob in Blender.Object.Get()]
+used_names.extend(Blender.NMesh.GetNames())
+
+deformedList = []
for ob in ob_list:
if ob.getType() == "Mesh":
name = ob.getName()
- new_name = name + "_deformed"
+ new_name = "%s_def" % name[:NAME_LENGTH-PREFIX_LENGTH]
num = 0
new_mesh = Blender.NMesh.GetRawFromObject(name)
- mesh = Blender.NMesh.GetRaw(new_name)
- while mesh:
+ while new_name in used_names:
+ new_name = "%s_def.%.3i" % (name[:NAME_LENGTH-(PREFIX_LENGTH+PREFIX_LENGTH)], num)
num += 1
- new_name = name + "_deformed." + "%03i" % num
- mesh = Blender.NMesh.GetRaw(new_name)
+
+ used_names.append(new_name)
+
new_ob = Blender.NMesh.PutRaw(new_mesh, new_name)
new_ob.setMatrix(ob.getMatrix())
- try:
- new_ob = Blender.Object.Get(new_name)
- while 1:
- num += 1
- new_name = name + "_deformed." + "%03i" % num
- new_ob = Blender.Object.Get(new_name)
- except:
- pass
new_ob.setName(new_name)
-
+ deformedList.append(new_ob)
+
+ # Vert groups.
ob_mesh = ob.getData()
new_ob_mesh = new_ob.getData()
-
- # If SubSurf is off on the original, copy the vertex weight
- if not ob_mesh.getMode() & Blender.NMesh.Modes['SUBSURF']:
- for vgroupname in ob_mesh.getVertGroupNames():
+
+ for vgroupname in ob_mesh.getVertGroupNames():
+ new_ob_mesh.addVertGroup(vgroupname)
+ if len(ob_mesh.verts) == len(new_ob_mesh.verts):
vlist = ob_mesh.getVertsFromGroup(vgroupname, True)
- new_ob_mesh.addVertGroup(vgroupname)
- for vpair in vlist:
- new_ob_mesh.assignVertsToGroup(vgroupname, [vpair[0]], vpair[1], 'add')
- # If it's on, just add the vertex groups
- else:
- for vgroupname in ob_mesh.getVertGroupNames():
- new_ob_mesh.addVertGroup(vgroupname)
-
- new_ob_mesh.update()
-
-Blender.Window.EditMode(1)
+ try:
+ for vpair in vlist:
+ new_ob_mesh.assignVertsToGroup(vgroupname, [vpair[0]], vpair[1], 'add')
+ except:
+ pass
+
+for ob in deformedList:
+ ob.sel = 1
+deformedList[0].sel = 1 # Keep the same object active. \ No newline at end of file
diff --git a/release/scripts/Axiscopy.py b/release/scripts/Axiscopy.py
index 0a9a411ef08..a6fa2e8b627 100644
--- a/release/scripts/Axiscopy.py
+++ b/release/scripts/Axiscopy.py
@@ -2,7 +2,7 @@
""" Registration info for Blender menus: <- these words are ignored
Name: 'Axis Orientation Copy'
-Blender: 233
+Blender: 239
Group: 'Object'
Tip: 'Copy the axis orientation of the active object to all selected mesh objects'
"""
@@ -10,7 +10,7 @@ Tip: 'Copy the axis orientation of the active object to all selected mesh object
__author__ = "A Vanpoucke (xand)"
__url__ = ("blender", "elysiun",
"French Blender support forum, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
-__version__ = "1.1 11/05/04"
+__version__ = "2 17/12/05"
__bpydoc__ = """\
This script copies the axis orientation -- X, Y and Z rotations -- of the
@@ -75,7 +75,7 @@ from Blender.Mathutils import *
def applyTransform(mesh,mat):
for v in mesh.verts:
- vec = VecMultMat(v.co,mat)
+ vec = v.co*mat
v.co[0], v.co[1], v.co[2] = vec[0], vec[1], vec[2]
@@ -87,13 +87,13 @@ lenob=len(oblist)
error = 0
for o in oblist[1:]:
if o.getType() != "Mesh":
- Draw.PupMenu("ERROR%t|Selected objects must be meshes")
+ Draw.PupMenu("Error: selected objects must be meshes")
error = 1
if not error:
if lenob<2:
- Draw.PupMenu("ERROR%t|You must select at least 2 objects")
- else :
+ Draw.PupMenu("Error: you must select at least 2 objects")
+ else :
source=oblist[0]
nsource=source.name
texte="Copy axis orientation from: " + nsource + " ?%t|OK"
@@ -102,9 +102,9 @@ if not error:
for cible in oblist[1:]:
if source.rot!=cible.rot:
- rotcible=cible.mat.toEuler().toMatrix()
- rotsource=source.mat.toEuler().toMatrix()
- rotsourcet = CopyMat(rotsource)
+ rotcible=cible.mat.rotationPart().toEuler().toMatrix()
+ rotsource=source.mat.rotationPart().toEuler().toMatrix()
+ rotsourcet = Matrix(rotsource)
rotsourcet.invert()
mat=rotcible*rotsourcet
ncible=cible.name
diff --git a/release/scripts/DirectX8Exporter.py b/release/scripts/DirectX8Exporter.py
index bfe6ccbdc88..0bb436ac86a 100644
--- a/release/scripts/DirectX8Exporter.py
+++ b/release/scripts/DirectX8Exporter.py
@@ -1,17 +1,16 @@
#!BPY
""" Registration info for Blender menus:
-Name: 'DirectX8(.x)...'
-Blender: 239
+Name: 'DirectX(.x)...'
+Blender: 240
Group: 'Export'
Submenu: 'Export all the scene' export
Submenu: 'Export selected obj' exportsel
-Tip: 'Export to DirectX8 text file format format.'
+Tip: 'Export to DirectX text file format format.'
"""
-
__author__ = "Arben (Ben) Omari"
__url__ = ("blender", "elysiun", "Author's site, http://www.omariben.too.it")
-__version__ = "1.0"
+__version__ = "2.0"
__bpydoc__ = """\
This script exports a Blender mesh with armature to DirectX 8's text file
@@ -21,8 +20,8 @@ Notes:<br>
Check author's site or the elYsiun forum for a new beta version of the
DX exporter.
"""
-# DirectX8Exporter.py version 1.0
-# Copyright (C) 2003 Arben OMARI -- omariarben@everyday.com
+# DirectXExporter.py version 2.0
+# Copyright (C) 2006 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
@@ -42,10 +41,17 @@ DX exporter.
import Blender
from Blender import Types, Object, NMesh, Material,Armature
from Blender.Mathutils import *
+import math
-global new_bon,mat_flip,index_list
+global mat_flip,index_list,space,bone_list,mat_dict
+bone_list =[]
index_list = []
-new_bon = {}
+mat_dict = {}
+space = 0
+ANIM = 1
+NORMAL = 1
+TEXCOORDS = 1
+TEXTURE = 1
mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1])
@@ -64,6 +70,7 @@ class xExport:
#Select Scene objects
#***********************************************
def SelectObjs(self):
+ global chld_obj
print "exporting..."
self.writeHeader()
for obj in Object.Get():
@@ -154,115 +161,117 @@ class xExport:
#Export Root Bone
#***********************************************
def writeRootBone(self,am_ob,child_obj):
- global new_bon,mat_flip
- space = 0
- arm = am_ob.getData()
- Blender.Set('curframe',1)
- mat_ob = mat_flip * am_ob.matrixWorld
- self.writeArmFrames(mat_ob, "RootFrame", 0)
- root_bon = arm.getBones()
- mat_r = self.writeCombineMatrix(root_bon[0])
- name_r = root_bon[0].getName()
- new_bon[name_r] = len(root_bon[0].getChildren())
- self.writeArmFrames(mat_r, name_r, 1)
- self.writeListOfChildrens(root_bon[0],2,arm)
- self.file.write("}\n")
- self.exportMeshArm(arm,am_ob,child_obj)
+ global mat_flip,space,root_bon,mat_ob
+ arms = am_ob.getData()
+ self.writeArmFrames(mat_flip, "RootFrame")
+ for bon in arms.bones.values():
+ if bon.hasParent():
+ pass
+ else:
+ root_bon = bon
+ space += 1
+ mat_rb = self.writeCombineMatrix(root_bon)
+ mat_r = mat_rb #* am_ob.matrixLocal
+ name_r = root_bon.name
+ name_f = name_r.replace(".","")
+ self.writeArmFrames(mat_r, name_f)
+ bon_c = self.findChildrens(root_bon)
+ self.writeChildren(bon_c)
+ self.file.write(" }\n")
+ self.exportMeshArm(arms,am_ob,child_obj)
#***********************************************
- #Export Children Bones
+ #Create Children structure
#***********************************************
- def writeListOfChildrens(self,bon,space,arm):
- global new_bon
- bon_c = bon.getChildren()
- Blender.Set('curframe',1)
- for n in range(len(bon_c)):
- name_h = bon_c[n].getName()
- chi_h = bon_c[n].getChildren()
- new_bon[name_h] = len(chi_h)
-
- if bon_c == [] :
- self.CloseBrackets(bon, new_bon, space, arm.getBones()[0])
+ def writeBon(self,bon):
+ global space
+ mat_r = self.writeCombineMatrix(bon)
+ name_r = bon.name
+ name_f = name_r.replace(".","")
+ self.writeArmFrames(mat_r, name_f)
- for nch in range(len(bon_c)):
- mat = self.writeCombineMatrix(bon_c[nch])
- name_ch = bon_c[nch].getName()
- self.writeArmFrames(mat, name_ch,space)
- self.findChildrens(bon_c[nch],space,arm)
+ def findChildrens(self,bon):
+ bon_c = bon.children
+ return bon_c
- #***********************************************
- #Create Children structure
- #***********************************************
- def CloseBrackets(self, bon, new_bon, space, root_bon):
+
+ def writeChildren(self,bon_c):
+ global space,bone_list
+ space += 1
+ if bon_c:
+ for bo in bon_c:
+ if bo.name not in bone_list:
+ self.writeBon(bo)
+ bone_list.append(bo.name)
+ bo_c = bo.children
+ self.writeChildren(bo_c)
+ self.closeBrackets()
+
+
+
+ def closeBrackets(self):
+ global space
+ space = space-1
tab = " "
- self.file.write("%s" % (tab * (space -1)))
+ self.file.write("%s" % (tab * space))
self.file.write("}\n")
- while bon.hasParent():
- if new_bon[bon.getName()] == 0:
- pare = bon.getParent()
- name_p = pare.getName()
- if new_bon[name_p] > 0:
- new_bon[name_p] = new_bon[name_p] - 1
- if new_bon[name_p] == 0 and pare != root_bon:
- self.file.write("%s" % (tab * (space-2)))
- self.file.write("}\n")
- space = space - 1
- bon = pare
- else:
- break
+
#***********************************************
- #Create Children structure
- #***********************************************
- def findChildrens(self,bon_c,space,arm):
- bon_cc = bon_c
- space += 1
- self.writeListOfChildrens(bon_cc,space,arm)
-
-
- #***********************************************
#Offset Matrix
#***********************************************
def writeMatrixOffset(self,bon):
- Blender.Set('curframe',1)
- mat_b = bon.getRestMatrix()
- mat_b.invert()
+ global chld_obj
+ Blender.Set('curframe', 1)
+ pose = chld_obj.getPose()
+ pos_b = pose.bones[bon.name]
+ mat_b = pos_b.poseMatrix
+ mat_b.invert()
return mat_b
-
-
#***********************************************
#Combine Matrix
#***********************************************
def writeCombineMatrix(self,bon):
- Blender.Set('curframe',1)
- mat_b = bon.getRestMatrix()
+ global chld_obj
+ Blender.Set('curframe', 1)
+ pose = chld_obj.getPose()
+ pos_b = pose.bones[bon.name]
+ mat_b = pos_b.poseMatrix
if bon.hasParent():
- pare = bon.getParent()
- mat_p = pare.getRestMatrix()
- else :
+ pare = bon.parent
+ pos_p = pose.bones[pare.name]
+ mat_p = pos_p.poseMatrix
+
+ else:
mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
mat_p.invert()
- mat_rb = mat_b * mat_p
- return mat_rb
-
+ mat_f = mat_b * mat_p
+
+ return mat_f
#***********************************************
#Combine Matrix
#***********************************************
- def writeCombineAnimMatrix(self,bon):
-
- mat_b = bon.getRestMatrix()
+ def writeAnimCombineMatrix(self,bon,fre):
+ global chld_obj
+ Blender.Set('curframe', fre)
+ pose = chld_obj.getPose()
+ pos_b = pose.bones[bon.name]
+ mat_b = pos_b.poseMatrix
if bon.hasParent():
- pare = bon.getParent()
- mat_p = pare.getRestMatrix()
- else :
+ pare = bon.parent
+ pos_p = pose.bones[pare.name]
+ mat_p = pos_p.poseMatrix
+
+ else:
mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
mat_p.invert()
- mat_rb = mat_b * mat_p
- return mat_rb
+ mat_f = mat_b * mat_p
+
+ return mat_f
#*********************************************************************************************************************************************
@@ -271,16 +280,23 @@ class xExport:
#***********************************************
def writeSkinWeights(self, arm, mesh):
global index_list
-
+ v_dict = {}
Blender.Set('curframe',1)
self.file.write(" XSkinMeshHeader {\n")
max_infl = 0
- for bo in arm.getBones() :
- name = bo.getName()
+ #this part supply the missing getVertexInfluences(index)
+ for v in index_list:
+ v_dict[v] = []
+ for bo in arm.bones.values() :
+ name = bo.name
+
try :
vertx_list = mesh.getVertsFromGroup(name,1)
+ for vn in vertx_list:
+ v_dict[vn[0]].append(name)
+ #---------------------------------------------------
for inde in vertx_list :
- vert_infl = mesh.getVertexInfluences(inde[0])
+ vert_infl = v_dict[inde[0]]
ln_infl = len(vert_infl)
if ln_infl > max_infl :
max_infl = ln_infl
@@ -288,20 +304,21 @@ class xExport:
except:
pass
- self.file.write(" %s; \n" % (max_infl))
- self.file.write(" %s; \n" % (max_infl * 3))
- self.file.write(" %s; \n" % (len(arm.getBones())))
+ self.file.write(" %d; \n" % (max_infl))
+ self.file.write(" %d; \n" % (max_infl * 3))
+ self.file.write(" %d; \n" % (len(arm.bones.values())))
self.file.write(" }\n")
- for bo in arm.getBones() :
+ for bo in arm.bones.values() :
bo_list = []
weight_list = []
- name = bo.getName()
+ name = bo.name
+ f_name = name.replace(".","")
try :
vert_list = mesh.getVertsFromGroup(name,1)
le = 0
for indx in vert_list:
- ver_infl = mesh.getVertexInfluences(indx[0])
+ ver_infl = v_dict[indx[0]]
len_infl = float(len(ver_infl))
infl = 1 / len_infl
i = -1
@@ -314,28 +331,27 @@ class xExport:
self.file.write(" SkinWeights {\n")
- self.file.write(' "%s"; \n' % (name))
- self.file.write(' %s; \n' % (le))
+ self.file.write(' "%s"; \n' % (f_name))
+ self.file.write(' %d; \n' % (le))
count = 0
for ind in bo_list :
count += 1
if count == len(bo_list):
- self.file.write(" %s; \n" % (ind))
+ self.file.write(" %d; \n" % (ind))
else :
- self.file.write(" %s, \n" % (ind))
+ self.file.write(" %d, \n" % (ind))
cou = 0
for wegh in weight_list :
cou += 1
if cou == len(weight_list):
- self.file.write(" %s; \n" % (round(wegh,6)))
+ self.file.write(" %f; \n" % (round(wegh,6)))
else :
- self.file.write(" %s, \n" % (round(wegh,6)))
+ self.file.write(" %f, \n" % (round(wegh,6)))
matx = self.writeMatrixOffset(bo)
-
- self.writeOffsFrames(matx, name, 1)
+ self.writeOffsFrames(matx, name)
except :
pass
self.file.write(" }\n")
@@ -344,7 +360,8 @@ class xExport:
#***********************************************
# Write Matrices
#***********************************************
- def writeArmFrames(self, matx, name, space):
+ def writeArmFrames(self, matx, name):
+ global space
tab = " "
self.file.write("%s" % (tab * space))
self.file.write("Frame ")
@@ -352,16 +369,16 @@ class xExport:
self.file.write("%s" % (tab * space))
self.file.write(" FrameTransformMatrix {\n")
self.file.write("%s" % (tab * space))
- self.file.write(" %s,%s,%s,%s,\n" %
+ self.file.write(" %f,%f,%f,%f,\n" %
(round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
self.file.write("%s" % (tab * space))
- self.file.write(" %s,%s,%s,%s,\n" %
+ self.file.write(" %f,%f,%f,%f,\n" %
(round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
self.file.write("%s" % (tab * space))
- self.file.write(" %s,%s,%s,%s,\n" %
+ self.file.write(" %f,%f,%f,%f,\n" %
(round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
self.file.write("%s" % (tab * space))
- self.file.write(" %s,%s,%s,%s;;\n" %
+ self.file.write(" %f,%f,%f,%f;;\n" %
(round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],6)))
self.file.write("%s" % (tab * space))
self.file.write(" }\n")
@@ -369,19 +386,20 @@ class xExport:
#***********************************************
# Write Matrices
#***********************************************
- def writeOffsFrames(self, matx, name, space):
+ def writeOffsFrames(self, matx, name):
+ space = 1
tab = " "
self.file.write("%s" % (tab * space))
- self.file.write(" %s,%s,%s,%s,\n" %
+ self.file.write(" %f,%f,%f,%f,\n" %
(round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
self.file.write("%s" % (tab * space))
- self.file.write(" %s,%s,%s,%s,\n" %
+ self.file.write(" %f,%f,%f,%f,\n" %
(round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
self.file.write("%s" % (tab * space))
- self.file.write(" %s,%s,%s,%s,\n" %
+ self.file.write(" %f,%f,%f,%f,\n" %
(round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
self.file.write("%s" % (tab * space))
- self.file.write(" %s,%s,%s,%s;;\n" %
+ self.file.write(" %f,%f,%f,%f;;\n" %
(round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],6)))
self.file.write("%s" % (tab * space))
self.file.write(" }\n")
@@ -445,7 +463,8 @@ template SkinWeights {\n\
mat_ob.invert()
mat = mat_arm * mat_ob
mat.invert()
- self.writeArmFrames(mat, name.name, 1)
+ name_f = name.name.replace(".","")
+ self.writeArmFrames(mat, name_f)
mesh = NMesh.GetRawFromObject(name.name)
self.file.write("Mesh {\n")
numface=len(mesh.faces)
@@ -461,8 +480,8 @@ template SkinWeights {\n\
for n in range(len(face.v)):
index_list.append(face.v[n].index)
vec_vert = Vector([face.v[n].co[0], face.v[n].co[1], face.v[n].co[2], 1])
- f_vec_vert = VecMultMat(vec_vert, mat)
- self.file.write("%s; %s; %s;" % (f_vec_vert[0], f_vec_vert[1], f_vec_vert[2]))
+ f_vec_vert = vec_vert * mat
+ self.file.write("%f; %f; %f;" % (round(f_vec_vert[0],4), round(f_vec_vert[1],4), round(f_vec_vert[2],4)))
if counter == numface :
if n == len(face.v)-1 :
self.file.write(";\n")
@@ -505,7 +524,8 @@ template SkinWeights {\n\
global index_list
#ROTATION
mat_ob = mat_flip * name.matrixWorld
- self.writeArmFrames(mat_ob, name.name, 0)
+ name_f = name.name.replace(".","")
+ self.writeArmFrames(mat_ob, name_f)
self.file.write("Mesh {\n")
numface=len(mesh.faces)
@@ -589,10 +609,9 @@ template SkinWeights {\n\
##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))
+ name_m = mat.name
+ name_f = name_m.replace(".","")
+ self.file.write(" %s "% (name_f))
self.file.write("{\n")
self.file.write(" %s; %s; %s;" % (mat.R, mat.G, mat.B))
self.file.write("%s;;\n" % (mat.alpha))
@@ -609,7 +628,7 @@ template SkinWeights {\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(" TextureFilename {")
self.file.write(' "%s" ;'% (mat))
self.file.write(" }\n")
self.file.write(" }\n")
@@ -711,47 +730,45 @@ template SkinWeights {\n\
-
+
+
#***********************************************
#WRITE ANIMATION KEYS
#***********************************************
def writeAnimation(self,arm_ob):
+ global mat_dict
arm = arm_ob.getData()
act_list = arm_ob.getAction()
ip = act_list.getAllChannelIpos()
- for bon in arm.getBones() :
+ for bon in arm.bones.values() :
point_list = []
+ name = bon.name
+ name_f = name.replace(".", "")
try :
ip_bon_channel = ip[bon.name]
ip_bon_name = ip_bon_channel.getName()
-
+
ip_bon = Blender.Ipo.Get(ip_bon_name)
poi = ip_bon.getCurves()
+
for po in poi[3].getPoints():
a = po.getPoints()
point_list.append(int(a[0]))
- point_list.pop(0)
-
-
+ #point_list.pop(0)
+
self.file.write(" Animation { \n")
- self.file.write(" {%s}\n" %(bon.getName()))
+ self.file.write(" {%s}\n" %(name_f))
self.file.write(" AnimationKey { \n")
self.file.write(" 4;\n")
- self.file.write(" %s; \n" % (len(point_list)+1))
-
- self.file.write(" %s;" % (1))
- self.file.write("16;")
- mat = self.writeCombineMatrix(bon)
- self.writeFrames(mat)
- self.file.write(",\n")
+ self.file.write(" %s; \n" % (len(point_list)))
for fr in point_list:
+ mat = self.writeAnimCombineMatrix(bon,fr)
+
self.file.write(" %s;" % (fr))
self.file.write("16;")
- Blender.Set('curframe',fr)
- mat_new = self.writeCombineAnimMatrix(bon)
- self.writeFrames(mat_new)
+ self.writeFrames(mat)
if fr == point_list[len(point_list)-1]:
self.file.write(";\n")
@@ -864,8 +881,8 @@ arg = __script__['arg']
if arg == 'exportsel':
fname = Blender.sys.makename(ext = ".x")
- Blender.Window.FileSelector(my_callback_sel, "Export DirectX8", fname)
+ Blender.Window.FileSelector(my_callback_sel, "Export DirectX", fname)
else:
fname = Blender.sys.makename(ext = ".x")
- Blender.Window.FileSelector(my_callback, "Export DirectX8", fname)
-
+ Blender.Window.FileSelector(my_callback, "Export DirectX", fname)
+ \ No newline at end of file
diff --git a/release/scripts/ac3d_export.py b/release/scripts/ac3d_export.py
index b9b7b8e5ae6..ea9ba239003 100644
--- a/release/scripts/ac3d_export.py
+++ b/release/scripts/ac3d_export.py
@@ -202,7 +202,8 @@ def transform_verts(verts, m):
vecs = []
for v in verts:
vec = Mathutils.Vector([v[0],v[1],v[2], 1])
- vecs.append(Mathutils.VecMultMat(vec, m))
+ #vecs.append(Mathutils.VecMultMat(vec, m))
+ vecs.append(vec*m)
return vecs
# ---
diff --git a/release/scripts/ac3d_import.py b/release/scripts/ac3d_import.py
index d2505022adf..4dcde65fb4a 100644
--- a/release/scripts/ac3d_import.py
+++ b/release/scripts/ac3d_import.py
@@ -10,7 +10,7 @@ Tip: 'Import an AC3D (.ac) file.'
__author__ = "Willian P. Germano"
__url__ = ("blender", "elysiun", "AC3D's homepage, http://www.ac3d.org",
"PLib 3d gaming lib, http://plib.sf.net")
-__version__ = "2.36 2005-04-14"
+__version__ = "2.36a 2005-12-04"
__bpydoc__ = """\
This script imports AC3D models into Blender.
@@ -43,9 +43,9 @@ users can configure (see config options above).
# $Id$
#
# --------------------------------------------------------------------------
-# AC3DImport version 2.36 Apr 14, 2005
+# AC3DImport version 2.36a Dec 04, 2005
# Program versions: Blender 2.36+ and AC3Db files (means version 0xb)
-# changed: updated to use the Scripts Config Editor facilities
+# changed: fixed a bug: error on 1 vertex "closed" polylines
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -366,7 +366,7 @@ class AC3DImport:
faces.append(cut)
face = face[1:]
- if flaglow == 1:
+ if flaglow == 1 and faces:
face = [faces[-1][-1], faces[0][0]]
faces.append(face)
@@ -498,7 +498,9 @@ class AC3DImport:
for vi in range(len(f)):
bface.v.append(mesh.verts[f[vi][0]])
bface.uv.append((f[vi][1][0], f[vi][1][1]))
- mesh.faces.append(bface)
+ #mesh.faces.append(bface)
+ # quick hack, will switch from NMesh to Mesh later:
+ if len(bface.v) > 1: mesh.addFace(bface)
mesh.mode = 0
object = Blender.NMesh.PutRaw(mesh)
diff --git a/release/scripts/bevel_center.py b/release/scripts/bevel_center.py
index 6025cef7f0e..1e3fb3c78d7 100644
--- a/release/scripts/bevel_center.py
+++ b/release/scripts/bevel_center.py
@@ -2,21 +2,21 @@
""" Registration info for Blender menus
Name: 'Bevel Center'
-Blender: 236
+Blender: 240
Group: 'Mesh'
-Tip: 'Bevel selected vertices'
+Tip: 'Bevel selected faces, edges, and vertices'
"""
-__author__ = "Loic Berthe"
+__author__ = "Loic BERTHE"
__url__ = ("blender", "elysiun")
-__version__ = "1.0"
+__version__ = "2.0"
__bpydoc__ = """\
-This script implements vertex bevelling in Blender.
+This script implements vertex and edges bevelling in Blender.
Usage:
-Select the mesh you want to work on, enter Edit Mode and select the vertices
+Select the mesh you want to work on, enter Edit Mode and select the edges
to bevel. Then run this script from the 3d View's Mesh->Scripts menu.
You can control the thickness of the bevel with the slider -- redefine the
@@ -24,358 +24,295 @@ end points for bigger or smaller ranges. The thickness can be changed even
after applying the bevel, as many times as needed.
For an extra smoothing after or instead of direct bevel, set the level of
-recursiveness and use the "Recursive" button.
+recursiveness and use the "Recursive" button.
+
+This "Recursive" Button, won't work in face select mode, unless you choose
+"faces" in the select mode menu.
Notes:<br>
- You can undo and redo your steps just like with normal mesh operations in
+ You can undo and redo your steps just like with normal mesh operations in
Blender.
"""
-# $Id$
-#
######################################################################
-# Bevel Center v1 for Blender
-#
-# This script lets you bevel the selected vertices and control the
+# Bevel Center v2.0 for Blender
+
+# This script lets you bevel the selected vertices or edges and control the
# thickness of the bevel
-#
-# (c) 2004 Loïc Berthe (loic.berthe@lilotux.net)
+
+# (c) 2004-2006 Loïc Berthe (loic+blender@lilotux.net)
# released under Blender Artistic License
-#
+
######################################################################
import Blender
-from Blender import NMesh, Window
+from Blender import NMesh, Window, Scene
from Blender.Draw import *
+from Blender.Mathutils import *
from Blender.BGL import *
-from math import pi, sin, sqrt
-
######################################################################
-# Functions to handle the global structures of the script NV, NE and NC
-# which contain informations about the vertices, faces and corners to be
-# created
-
-class Dir:
- def __init__(self, co):
- self.co = co
-
-def add_to_NV(old,co,new):
- dir = Dir(co)
- #
- if old in NV.keys():
- NV[old][dir] = new
- else:
- NV[old] = {dir:new}
-
-def is_in_NV(old,co):
- if old in NV.keys():
- for dir in NV[old]:
- if dir.co == co : return NV[old][dir]
- #
- return False
-
-def add_to_NE(old, new):
- ind1 = old[0].index
- ind2 = old[1].index
- if ind1 > ind2:
- new.reverse()
- ind1,ind2 = ind2,ind1
- id = str(ind1)+"_"+str(ind2)
- if id in NE.keys():
- [NE[id].append(v) for v in new]
- else:
- NE[id] = new
-
-def add_to_NC(old,edge):
- if old in NC.keys():
- NC[old].append(edge)
- else:
- NC[old] = [edge]
-
-######################################################################
-# Geometric functions
-
-def norm(vec):
- n = sqrt(vec[0]**2+vec[1]**2+vec[2]**2)
- return [vec[0]/n,vec[1]/n,vec[2]/n]
-
-def parall_coord(old, dir):
- co = old.co
- vec = [0.0,0.0,0.0]
- nco = [0.0,0.0,0.0]
- #
- if len(dir) == 1:
- for i in range(3): vec[i] = dir[0].co[i] - co[i]
- vec = norm(vec)
- #
- elif len(dir) == 2:
- vec1 = [0.0,0.0,0.0]
- vec2 = [0.0,0.0,0.0]
- for i in range(3):
- vec1[i] = dir[0].co[i] - co[i]
- vec2[i] = dir[1].co[i] - co[i]
- vec1 = norm(vec1)
- vec2 = norm(vec2)
- for i in range(3) : vec[i] = vec1[i]+vec2[i]
- #
- for i in range(3): nco[i] = co[i] + dist.val*vec[i]
- return (nco,vec)
-
-def get_vert(old, dir):
- """ Look in NV if a vertice corresponding to the vertex old and the
- direction dir already exists, and create one otherwise"""
- (nco, vec) = parall_coord(old, dir)
- v = is_in_NV(old,vec)
- if v: return v
- #
- v = NMesh.Vert(nco[0],nco[1],nco[2])
- v.sel = 1
+# Functions to handle the global structures of the script NF, NE and NC
+# which contain informations about faces and corners to be created
+
+global E_selected
+E_selected = NMesh.EdgeFlags['SELECT']
+
+def make_sel_vert(*co):
+ vi= NMesh.Vert(*co)
+ v.sel = 1
me.verts.append(v)
- add_to_NV(old,vec,v)
return v
-
-######################################################################
-# Functions to create the differents faces
+
+def make_sel_face(verts):
+ f = NMesh.Face(verts)
+ f.sel = 1
+ me.addFace(f)
+
+def add_to_NV(old,dir,new):
+ if old in NV.keys(): NV[old][dir] = new
+ else: NV[old] = {dir:new}
+
+def get_v(old, *neighbors):
+
+ # compute the direction of the new vert
+ if len(neighbors) == 1 : dir = (neighbors[0].co - old.co).normalize()
+ else : dir = (neighbors[0].co - old.co).normalize() + (neighbors[1].co-old.co).normalize()
+
+ # look in NV if this vert already exists
+ key = tuple(dir)
+ if old in NV and key in NV[old] : return NV[old][key]
-def make_NF():
- """ Analyse the mesh, sort the faces containing selected vertices and
- create a liste NF : NF = [[flag, vertlist, old_face]]. Flag describes the
- topology of the face."""
- #
+ # else, create it
+ new = old.co + dist.val*dir
+ v = make_sel_vert(new.x,new.y,new.z)
+ add_to_NV(old,key,v)
+ return v
+
+def make_faces():
+ """ Analyse the mesh, make the faces corresponding to selected faces and
+ fill the structures NE and NC """
+
+ # make the differents flags consistent
+ for e in me.edges:
+ if e.flag & E_selected :
+ e.v1.sel = 1
+ e.v2.sel = 1
+
+ NF =[] # NF : New faces
for f in me.faces:
V = f.v
- v_sel = [x.sel for x in V]
- nb_sel = sum(v_sel)
- if nb_sel == 0 :
- pass
- else:
- nb_v = len(V)
- #
- if nb_v == 4:
- #
- if nb_sel == 4:
- NF.append([1,V,f])
- #
- elif nb_sel == 3:
- if v_sel == [0,1,1,1]: V = [V[1],V[2],V[3],V[0]]
- elif v_sel == [1,0,1,1]: V = [V[2],V[3],V[0],V[1]]
- elif v_sel == [1,1,0,1]: V = [V[3],V[0],V[1],V[2]]
- NF.append([2,V,f])
- #
- elif nb_sel == 2:
- if v_sel == [1,0,1,0] or v_sel == [0,1,0,1]:
- if v_sel == [0,1,0,1]: V = [V[1],V[2],V[3],V[0]]
- NF.append([5,[V[0],V[1],V[3]],f])
- NF.append([5,[V[2],V[1],V[3]]])
- else:
- if v_sel == [0,1,1,0]: V = [V[1],V[2],V[3],V[0]]
- elif v_sel == [0,0,1,1]: V = [V[2],V[3],V[0],V[1]]
- elif v_sel == [1,0,0,1]: V = [V[3],V[0],V[1],V[2]]
- NF.append([3,V,f])
- #
- else:
- if v_sel == [0,1,0,0]: V = [V[1],V[2],V[3],V[0]]
- elif v_sel == [0,0,1,0]: V = [V[2],V[3],V[0],V[1]]
- elif v_sel == [0,0,0,1]: V = [V[3],V[0],V[1],V[2]]
- NF.append([4,V,f])
- #
- elif nb_v == 3:
- #
- if nb_sel == 3:
- NF.append([6,V,f])
- #
- elif nb_sel == 2:
- if v_sel == [0,1,1]: V = [V[1],V[2],V[0]]
- elif v_sel == [1,0,1]: V = [V[2],V[0],V[1]]
- NF.append([7,V,f])
- #
- else:
- if v_sel == [0,1,0]: V = [V[1],V[2],V[0]]
- elif v_sel == [0,0,1]: V = [V[2],V[0],V[1]]
- NF.append([5,V,f])
+ nV = len(V)
+ enumV = range(nV)
+ E = [me.findEdge(V[i],V[(i+1) % nV]) for i in enumV]
+ Esel = [x.flag & E_selected for x in E]
+
+ # look for selected vertices and creates a list containing the new vertices
+ newV = V[:]
+ changes = False
+ for (i,v) in enumerate(V):
+ if v.sel :
+ changes = True
+ if Esel[i-1] == 0 and Esel[i] == 1 : newV[i] = get_v(v,V[i-1])
+ elif Esel[i-1] == 1 and Esel[i] == 0 : newV[i] = get_v(v,V[(i+1) % nV])
+ elif Esel[i-1] == 1 and Esel[i] == 1 : newV[i] = get_v(v,V[i-1],V[(i+1) % nV])
+ else : newV[i] = [get_v(v,V[i-1]),get_v(v,V[(i+1) % nV])]
+
+ if changes:
+ # determine and store the face to be created
-def make_faces():
- """ Make the new faces according to NF """
- #
- for N in NF:
- cas = N[0]
- V = N[1]
- #
- if cas < 6:
- new_v = [0,0,0,0]
- if cas == 1: # v_sel = [1,1,1,1]
- for i in range(-1,3):
- new_v[i] = get_vert(V[i],[V[i-1],V[i+1]])
- new_f = NMesh.Face(new_v)
- me.faces.append(new_f)
- for i in range(-1,3):
- add_to_NE([V[i],V[i+1]],[new_v[i],new_v[i+1]])
- #
- elif cas == 2: # v_sel = [1,1,1,0]
- new_v[0] = get_vert(V[0],[V[3]])
- new_v[1] = get_vert(V[1],[V[0],V[2]])
- new_v[2] = get_vert(V[2],[V[3]])
- new_v[3] = V[3]
- #
- new_f = NMesh.Face(new_v)
- me.faces.append(new_f)
- #
- add_to_NE([V[0],V[1]],[new_v[0],new_v[1]])
- add_to_NE([V[1],V[2]],[new_v[1],new_v[2]])
- #
- elif cas == 3: # v_sel = [1,1,0,0]
- new_v[0] = get_vert(V[0],[V[3]])
- new_v[1] = get_vert(V[1],[V[2]])
- new_v[2] = V[2]
- new_v[3] = V[3]
- #
- new_f = NMesh.Face(new_v)
- me.faces.append(new_f)
- #
- add_to_NE([V[0],V[1]],[new_v[0],new_v[1]])
- #
- elif cas == 4: # v_sel = [1,0,0,0]
- new_v[0] = get_vert(V[0],[V[3]])
- new_v[1] = get_vert(V[0],[V[1]])
- new_v[2] = V[1]
- new_v[3] = V[3]
- #
- new_f = NMesh.Face(new_v)
- me.faces.append(new_f)
- #
- add_to_NC(V[0], new_v[0:2])
- #
- new_v[0] = V[1]
- new_v[1] = V[2]
- new_v[2] = V[3]
- #
- new_f = NMesh.Face(new_v[:3])
- me.faces.append(new_f)
- #
- else: # v_sel = [1,0,0]
- new_v[0] = get_vert(V[0],[V[2]])
- new_v[1] = get_vert(V[0],[V[1]])
- new_v[2] = V[1]
- new_v[3] = V[2]
- #
- new_f = NMesh.Face(new_v)
- me.faces.append(new_f)
- #
- add_to_NC(V[0], new_v[0:2])
- #
- else:
- new_v = [0,0,0]
- #
- if cas == 6: # v_sel = [1,1,1]
- for i in range(-1,2):
- new_v[i] = get_vert(V[i],[V[i-1],V[i+1]])
- new_f = NMesh.Face(new_v)
- me.faces.append(new_f)
- for i in range(-1,2):
- add_to_NE([V[i],V[i+1]],[new_v[i],new_v[i+1]])
- #
- elif cas == 7: # v_sel = [1,1,0]
- new_v[0] = get_vert(V[0],[V[2]])
- new_v[1] = get_vert(V[1],[V[2]])
- new_v[2] = V[2]
- #
- new_f = NMesh.Face(new_v)
- me.faces.append(new_f)
- add_to_NE([V[0],V[1]],[new_v[0],new_v[1]])
+ lenV = [len(x) for x in newV]
+
+ if 2 not in lenV :
+ new_f = NMesh.Face(newV)
+ if sum(Esel) == nV : new_f.sel = 1
+ NF.append(new_f)
+
+ else :
+ nb2 = lenV.count(2)
+
+ if nV == 4 : # f is a quad
+ if nb2 == 1 :
+ ind2 = lenV.index(2)
+ NF.append(NMesh.Face([newV[ind2-1],newV[ind2][0],newV[ind2][1],newV[ind2-3]]))
+ NF.append(NMesh.Face([newV[ind2-1],newV[ind2-2],newV[ind2-3]]))
+
+ elif nb2 == 2 :
+ # We must know if the tuples are neighbours
+ ind2 = ''.join([str(x) for x in lenV+lenV[:1]]).find('22')
+
+ if ind2 != -1 : # They are
+ NF.append(NMesh.Face([newV[ind2][0],newV[ind2][1],newV[ind2-3][0],newV[ind2-3][1]]))
+ NF.append(NMesh.Face([newV[ind2][0],newV[ind2-1],newV[ind2-2],newV[ind2-3][1]]))
+
+ else: # They aren't
+ ind2 = lenV.index(2)
+ NF.append(NMesh.Face([newV[ind2][0],newV[ind2][1],newV[ind2-2][0],newV[ind2-2][1]]))
+ NF.append(NMesh.Face([newV[ind2][1],newV[ind2-3],newV[ind2-2][0]]))
+ NF.append(NMesh.Face([newV[ind2][0],newV[ind2-1],newV[ind2-2][1]]))
+
+ elif nb2 == 3 :
+ ind2 = lenV.index(3)
+ NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2],newV[ind2-3][0]]))
+ NF.append(NMesh.Face([newV[ind2-1][0],newV[ind2-1][1],newV[ind2-3][0],newV[ind2-3][1]]))
+ NF.append(NMesh.Face([newV[ind2-3][1],newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0]]))
+
+ else:
+ if (newV[0][1].co-newV[3][0].co).length + (newV[1][0].co-newV[2][1].co).length \
+ < (newV[0][0].co-newV[1][1].co).length + (newV[2][0].co-newV[3][1].co).length :
+ ind2 = 0
+ else :
+ ind2 = 1
+ NF.append(NMesh.Face([newV[ind2-1][0],newV[ind2-1][1],newV[ind2][0],newV[ind2][1]]))
+ NF.append(NMesh.Face([newV[ind2][1],newV[ind2-3][0],newV[ind2-2][1],newV[ind2-1][0]]))
+ NF.append(NMesh.Face([newV[ind2-3][0],newV[ind2-3][1],newV[ind2-2][0],newV[ind2-2][1]]))
+
+ else : # f is a tri
+ if nb2 == 1:
+ ind2 = lenV.index(2)
+ NF.append(NMesh.Face([newV[ind2-2],newV[ind2-1],newV[ind2][0],newV[ind2][1]]))
+
+ elif nb2 == 2:
+ ind2 = lenV.index(3)
+ NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2],newV[ind2-2][0]]))
+ NF.append(NMesh.Face([newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0],newV[ind2-1][1]]))
+
+ else:
+ ind2 = min(((newV[i][1].co-newV[i-1][0].co).length, i) for i in enumV)[1]
+ NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2][0],newV[ind2][1],newV[ind2-2][0]]))
+ NF.append(NMesh.Face([newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0],newV[ind2-1][1]]))
+
+ # Preparing the corners
+ for i in enumV:
+ if lenV[i] == 2 : NC.setdefault(V[i],[]).append(newV[i])
+
+ old_faces.append(f)
+
+ # Preparing the Edges
+ for i in enumV:
+ if Esel[i]:
+ verts = [newV[i],newV[(i+1) % nV]]
+ if V[i].index > V[(i+1) % nV].index : verts.reverse()
+ NE.setdefault(E[i],[]).append(verts)
+
+ # Create the faces
+ for f in NF: me.addFace(f)
def make_edges():
""" Make the faces corresponding to selected edges """
- #
- for l in NE.values():
- if len(l) == 4:
- f = NMesh.Face([l[0],l[1],l[3],l[2]])
- me.faces.append(f)
+
+ for old,new in NE.iteritems() :
+ if len(new) == 1 : # This edge was on a border
+ oldv = [old.v1, old.v2]
+ if old.v1.index < old.v2.index : oldv.reverse()
+
+ make_sel_face(oldv+new[0])
+
+ me.findEdge(*oldv).flag |= E_selected
+ me.findEdge(*new[0]).flag |= E_selected
+
+ for v in oldv : NV_ext.add(v)
+
+ else:
+ make_sel_face(new[0] + new[1][::-1])
+
+ me.findEdge(*new[0]).flag |= E_selected
+ me.findEdge(*new[1]).flag |= E_selected
def make_corners():
- """ Make the faces corresponding to selected corners """
- #
+ """ Make the faces corresponding to corners """
+
for v in NV.keys():
V = NV[v].values()
- nb_v = len(V)
- #
- if nb_v < 3:
- pass
- #
- elif nb_v == 3:
- new_f = NMesh.Face(V)
- me.faces.append(new_f)
- #
+ nV = len(V)
+
+ if nV == 1: pass
+
+ elif nV == 2 :
+ if v in NV_ext:
+ make_sel_face(V+[v])
+ me.findEdge(*V).flag |= E_selected
+
else:
- # We need to know which are the edges around the corner.
- # First, we look for the quads surrounding the corner.
- q = [NE[id] for id in NE.keys() if str(v.index) in id.split('_')]
- #
- # We will put the associated edges in the list eed
- is_in_v = lambda x:x in V
- eed = [filter(is_in_v, l) for l in q]
- #
- # We will add the edges coming from faces where only one vertice is selected.
- # They are stocked in NC.
- if v in NC.keys():
- eed = eed+NC[v]
- b = eed.pop()
- # b will contain the sorted list of vertices
- #
- while eed:
- for l in eed:
- if l[0] == b[-1]:
- b.append(l[1])
- eed.remove(l)
- break
- elif l[1] == b[-1]:
- b.append(l[0])
- eed.remove(l)
- break
- # Now we can create the faces
- if nb_v == 4:
- new_f = NMesh.Face(b[:4])
- me.faces.append(new_f)
- #
- else:
- co = [0.0, 0.0,0.0]
- vec = [0.0, 0.0,0.0]
- for x in V:
- co[0] += x[0]
- co[1] += x[1]
- co[2] += x[2]
- #
- for dir in NV[v]:
- vec[0] += dir.co[0]
- vec[1] += dir.co[1]
- vec[2] += dir.co[2]
- #
- co = [x/nb_v for x in co]
- vec = [x/nb_v for x in vec]
- center = NMesh.Vert(co[0],co[1],co[2])
- center.sel = 1
- me.verts.append(center)
- add_to_NV(v,vec,center)
- #
- for k in range(nb_v):
- new_f = NMesh.Face([center, b[k], b[k+1]])
- me.faces.append(new_f)
- #
+ if nV == 3 and v not in NV_ext : make_sel_face(V)
+
+ else :
+
+ # We need to know which are the edges around the corner.
+ # First, we look for the quads surrounding the corner.
+ eed = []
+ for old, new in NE.iteritems():
+ if v in (old.v1,old.v2) :
+ if v.index == min(old.v1.index,old.v2.index) : ind = 0
+ else : ind = 1
+
+ if len(new) == 1: eed.append([v,new[0][ind]])
+ else : eed.append([new[0][ind],new[1][ind]])
+
+ # We will add the edges coming from faces where only one vertice is selected.
+ # They are stored in NC.
+ if v in NC: eed = eed+NC[v]
+
+ # Now we have to sort these vertices
+ hc = {}
+ for (a,b) in eed :
+ hc.setdefault(a,[]).append(b)
+ hc.setdefault(b,[]).append(a)
+
+ for x0,edges in hc.iteritems():
+ if len(edges) == 1 : break
+
+ b = [x0] # b will contain the sorted list of vertices
+
+ for i in range(len(hc)-1):
+ for x in hc[x0] :
+ if x not in b : break
+ b.append(x)
+ x0 = x
+
+ b.append(b[0])
+
+ # Now we can create the faces
+ if len(b) == 5: make_sel_face(b[:4])
+
+ else:
+ New_V = Vector(0.0, 0.0,0.0)
+ New_d = [0.0, 0.0,0.0]
+
+ for x in hc.keys(): New_V += x.co
+ for dir in NV[v] :
+ for i in xrange(3): New_d[i] += dir[i]
+
+ New_V *= 1./len(hc)
+ for i in range(3) : New_d[i] /= nV
+
+ center = make_sel_vert(New_V.x,New_V.y,New_V.z)
+ add_to_NV(v,tuple(New_d),center)
+
+ for k in range(len(b)-1): make_sel_face([center, b[k], b[k+1]])
+
+ if 2 < nV and v in NC :
+ for edge in NC[v] : me.findEdge(*edge).flag |= E_selected
def clear_old():
""" Erase old faces and vertices """
- for F in NF:
- if len(F) == 3:
- me.faces.remove(F[2])
- #
+
+ for f in old_faces: me.removeFace(f)
+
for v in NV.keys():
- me.verts.remove(v)
+ if v not in NV_ext : me.verts.remove(v)
+
+ for e in me.edges:
+ if e.flag & E_selected :
+ e.v1.sel = 1
+ e.v2.sel = 1
+
######################################################################
# Interface
-#
+
global dist
-NV = {}
+
dist = Create(0.2)
left = Create(0.0)
right = Create(1.0)
@@ -393,83 +330,79 @@ def draw():
global EVENT_NOEVENT, EVENT_BEVEL, EVENT_UPDATE, EVENT_RECURS, EVENT_EXIT
glClear(GL_COLOR_BUFFER_BIT)
- Button("Bevel",EVENT_BEVEL,10,100,300,25)
- left=Number('', EVENT_NOEVENT,10,70,50, 20,left.val,0,right.val,'Set the minimum of the slider')
- right = Number("",EVENT_NOEVENT,260,70,50,20,right.val,left.val,200,"Set the maximum of the slider")
- dist=Slider("Thickness ",EVENT_UPDATE,65,70,190,20,dist.val,left.val,right.val,0,"Thickness of the bevel, can be changed even after bevelling")
- glRasterPos2d(10,40)
+ Button("Bevel",EVENT_BEVEL,10,100,280,25)
+ left=Number('', EVENT_NOEVENT,10,70,45, 20,left.val,0,right.val,'Set the minimum of the slider')
+ right = Number("",EVENT_NOEVENT,245,70,45,20,right.val,left.val,200,"Set the maximum of the slider")
+ dist=Slider("Thickness ",EVENT_UPDATE,60,70,180,20,dist.val,left.val,right.val,0, \
+ "Thickness of the bevel, can be changed even after bevelling")
+ glRasterPos2d(8,40)
Text('To finish, you can use recursive bevel to smooth it')
- num=Number('', EVENT_NOEVENT,10,10,50, 16,num.val,1,100,'Recursion level')
- Button("Recursive",EVENT_RECURS,65,10,100,16)
- Button("Exit",EVENT_EXIT,230,10,80,20)
+ num=Number('', EVENT_NOEVENT,10,10,40, 16,num.val,1,100,'Recursion level')
+ Button("Recursive",EVENT_RECURS,55,10,100,16)
+ Button("Exit",EVENT_EXIT,210,10,80,20)
def event(evt, val):
- if ((evt == QKEY or evt == ESCKEY) and not val):
- Exit()
+ if ((evt == QKEY or evt == ESCKEY) and not val): Exit()
def bevent(evt):
- if evt == EVENT_EXIT :
- Exit()
- #
- elif evt == EVENT_BEVEL:
- bevel()
- #
- elif evt == EVENT_UPDATE:
- try:
- bevel_update()
- except NameError:
- pass
- #
- elif evt == EVENT_RECURS:
- recursive()
+ if evt == EVENT_EXIT : Exit()
+ elif evt == EVENT_BEVEL : bevel()
+ elif evt == EVENT_UPDATE :
+ try: bevel_update()
+ except NameError : pass
+ elif evt == EVENT_RECURS : recursive()
Register(draw, event, bevent)
######################################################################
def bevel():
""" The main function, which creates the bevel """
- global me,NF,NV,NE,NC, old_dist
- #
- is_editmode = Window.EditMode()
- if is_editmode: Window.EditMode(0)
- objects = Blender.Object.GetSelected()
- bev_obj = objects[0]
- if bev_obj.getType() != "Mesh":
- PupMenu("ERROR: active object must be a mesh")
+ global me,NV,NV_ext,NE,NC, old_faces,old_dist
+
+ scn = Scene.GetCurrent()
+ ob = scn.getActiveObject()
+ if ob == None or ob.getType() != 'Mesh':
+ Draw.PupMenu('ERROR%t|Select a mesh object.')
return
- me = NMesh.GetRaw(bev_obj.getData(name_only = True))
- #
- NF = []
+
+ Window.WaitCursor(1) # Change the Cursor
+
+ is_editmode = Window.EditMode()
+ if is_editmode: Window.EditMode(0)
+
+ me = ob.getData()
+
NV = {}
+ NV_ext = set()
NE = {}
NC = {}
- #
- make_NF()
+ old_faces = []
+
make_faces()
make_edges()
make_corners()
clear_old()
- #
+
old_dist = dist.val
- #
+
me.update(1)
if is_editmode: Window.EditMode(1)
+ Window.WaitCursor(0)
Blender.Redraw()
def bevel_update():
""" Use NV to update the bevel """
- global dist, old_dist, NV
- if not NV: return
+ global dist, old_dist
is_editmode = Window.EditMode()
if is_editmode: Window.EditMode(0)
fac = dist.val - old_dist
old_dist = dist.val
- #
+
for old_v in NV.keys():
for dir in NV[old_v].keys():
for i in range(3):
- NV[old_v][dir].co[i] += fac*dir.co[i]
- #
+ NV[old_v][dir].co[i] += fac*dir[i]
+
me.update(1)
if is_editmode: Window.EditMode(1)
Blender.Redraw()
@@ -477,24 +410,23 @@ def bevel_update():
def recursive():
""" Make a recursive bevel... still experimental """
global dist
- #
+ from math import pi, sin
+
if num.val > 1:
a = pi/4
ang = []
for k in range(num.val):
ang.append(a)
a = (pi+2*a)/4
- #
+
l = [2*(1-sin(x))/sin(2*x) for x in ang]
R = dist.val/sum(l)
l = [x*R for x in l]
- #
+
dist.val = l[0]
bevel_update()
- #
+
for x in l[1:]:
dist.val = x
bevel()
-
-# vim:set ts=4 sw=4:
diff --git a/release/scripts/bpymodules/meshtools.py b/release/scripts/bpymodules/meshtools.py
index 4ddf6035e59..bf875abf43c 100644
--- a/release/scripts/bpymodules/meshtools.py
+++ b/release/scripts/bpymodules/meshtools.py
@@ -5,12 +5,28 @@
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | September 28, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
# +---------------------------------------------------------+
# | Common Functions & Global Variables For All IO Modules |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender
import sys
@@ -35,7 +51,16 @@ def append_faces(mesh, faces, facesuv, uvcoords):
for i in range(len(faces)):
if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Generating Faces")
numfaceverts=len(faces[i])
- if numfaceverts <= 4: # This face is a triangle or quad
+ if numfaceverts == 2: #This is not a face is an edge
+ if mesh.edges == None: #first run
+ mesh.addEdgeData()
+ #rev_face = revert(cur_face)
+ i1 = faces[i][0]
+ i2 = faces[i][1]
+ ee = mesh.addEdge(mesh.verts[i1],mesh.verts[i2])
+ ee.flag |= Blender.NMesh.EdgeFlags.EDGEDRAW
+ ee.flag |= Blender.NMesh.EdgeFlags.EDGERENDER
+ elif numfaceverts in [3,4]: # This face is a triangle or quad
face = Blender.NMesh.Face()
for j in range(numfaceverts):
index = faces[i][j]
diff --git a/release/scripts/bpymodules/svg2obj.py b/release/scripts/bpymodules/svg2obj.py
index 98c6a489b0c..2ee133a00ee 100644
--- a/release/scripts/bpymodules/svg2obj.py
+++ b/release/scripts/bpymodules/svg2obj.py
@@ -1,8 +1,41 @@
+# -*- coding: latin-1 -*-
"""
-SVG 2 OBJ translater, 0.3.3
-(c) jm soler juillet/novembre 2004-juin 2005,
-# released under Blender Artistic Licence
- for the Blender 2.37/36/35/34/33 Python Scripts Bundle.
+SVG 2 OBJ translater, 0.4.7
+Copyright (c) jm soler juillet/novembre 2004-janvier 2006,
+# ---------------------------------------------------------------
+ released under GNU Licence
+ for the Blender 2.40 Python Scripts Bundle.
+Ce programme est libre, vous pouvez le redistribuer et/ou
+le modifier selon les termes de la Licence Publique Générale GNU
+publiée par la Free Software Foundation (version 2 ou bien toute
+autre version ultérieure choisie par vous).
+
+Ce programme est distribué car potentiellement utile, mais SANS
+AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties
+de commercialisation ou d'adaptation dans un but spécifique.
+Reportez-vous à la Licence Publique Générale GNU pour plus de détails.
+
+Vous devez avoir reçu une copie de la Licence Publique Générale GNU
+en même temps que ce programme ; si ce n'est pas le cas, écrivez à la
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307, États-Unis.
+
+
+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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ---------------------------------------------------------------
+
#---------------------------------------------------------------------------
# Page officielle :
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm
@@ -40,10 +73,14 @@ Yet done:
L : absolute line to
C : absolute curve to
S : absolute curve to with only one handle
+ H : absolute horizontal line to
+ V : absolute vertical line to
+
l : relative line to 2004/08/03
c : relative curve to 2004/08/03
s : relative curve to with only one handle
-
+ h : relative horizontal line to
+ v : relative vertical line to
A : courbe_vers_a,
V : ligne_tracee_v,
@@ -84,19 +121,70 @@ Changelog:
skew
- added a test on __name__ to load the script
outside from the blender menu
- 0.3.3 : - controle du contenu des transformation de type matrix
- 0.3.4 : - restructuration de la lecture des donnes paths (19/06/05)
+ 0.3.3 : - matrix transform content control
+ 0.3.4 : - paths data reading rewritten (19/06/05)
+ 0.3.5 : - test on empty curve (22/06/05)
+ - removed overlayed points
+ 0.3.6 : - rewriting of the bezier point contruction to correct
+ a problem in the connection between L type point and
+ C or S type point
+ 0.3.7 : - code correction for bezier knot in Curveto command when
+ the command close a path
+ 0.3.8 : - code was aded to manage quadratic bezier,
+ Q,q command and T,t commands, as a normal blender's bezier point
+ - The last modications does not work with gimp 2.0 svg export .
+ corrected too .
+ 0.3.9 : - Path's A,a command for ellipse's arc .
+ 0.4.0 : - To speed up the function filtre_DATA was removed and text
+ variables are changed into numeric variables
+ 0.4.1 : - svg, groups and shapes hierarchy added
+ - now transform properties are computed using a stack with all
+ parented groups
+ - removed or replaced useless functions :
+ - skewY, skewX transforms
+ - radians in rotate transform
+ 0.4.2 : - Added functon to translate others shapes in path
+ rect, line, polyline, polygon
+
+ 0.4.3 : - various corrections
+ text font (id property exported by Adobe Illustrator are between coma)
+ function to code s tag has been rewritten
+
+ 0.4.4 : - various corrections
+ to oblige the script to understand a line feed just after
+ a tag . Rarely encountered problem, but it exits in a svg file
+ format exported by a outliner script for mesh .
+
+ 0.4.5 : - update for CVS only, at least blender 2.38 and upper
+ no BezTriple module in older version
+ added a createCURVES function to avoid to use
+ the OBJ format export/import .
+
+ Perhaps problems with cyclic curves . If a closed curve
+ does not appear closed in blender, enter edit mode select
+ all knot with Akey, do a Hkey to set handle type (without
+ this the knot are recalculated) , and finally use the Ckey
+ to close the curve .
+ Should work ... not guaranted .
+
+ 0.4.6 : - cyclic flag ...
+
+ 0.4.7 : - Management of the svgz files . the complete python or the gzip.py
+ file is needed .
+ Little improvement of the curve drawing using the createCURVES
+ function
==================================================================================
=================================================================================="""
SHARP_IMPORT=0
SCALE=1
-scale=1
-DEBUG =0 #print
+scale_=1
+DEBUG = 0#print
DEVELOPPEMENT=0
import sys
-from math import cos,sin,tan
+from math import cos,sin,tan, atan2, pi, ceil
+PI=pi
import Blender
from Blender import Mathutils
BLversion=Blender.Get('version')
@@ -139,27 +227,69 @@ os.split=split
os.join=join
def filtreFICHIER(nom):
- f=open(nom,'rU')
- t=f.read()
- f.close()
+ """
+ Function filtreFICHIER
+
+ in : string nom , filename
+ out : string t , if correct filecontaint
+
+ Lit le contenu du fichier et en fait une pre-analyse
+ pour savoir s'il merite d'etre traite .
+ """
+ # ----------
+ # 0.4.7
+ # ----------
+ if nom.upper().find('.SVGZ')!=-1:
+ try :
+ import gzip
+ tz=gzip.GzipFile(nom)
+ t=tz.read()
+ except:
+ name = "ERROR: fail to import gzip module or gzip error ... "
+ result = Blender.Draw.PupMenu(name)
+ return "false"
+ else:
+ f=open(nom,'rU')
+ t=f.read()
+ f.close()
+ # ----------
+ # 0.4.7 : end
+ # ----------
- t=t.replace('\r','')
- t=t.replace('\n','')
+ # -----------------
+ # pre-format ...
+ # -----------------
+ # --------------------
+ # 0.4.4 '\r','' --> '\r',' '
+ # '\n','' --> '\n',' '
+ #--------------------
+ t=t.replace('\r',' ')
+ t=t.replace('\n',' ')
+ t=t.replace('svg:','')
if t.upper().find('<SVG')==-1 :
name = "ERROR: invalid or empty file ... " # if no %xN int is set, indices start from 1
result = Blender.Draw.PupMenu(name)
return "false"
- elif t.upper().find('<PATH')==-1:
+ else:
+ return t
+
+ """
+ elif t.upper().find('<PATH')==-1 and\
+ t.upper().find('<RECT')==-1 and\
+ t.upper().find('<LINE')==-1 and\
+ t.upper().find('<POLYLINE')==-1 :
name = "ERROR: there's no Path in this file ... " # if no %xN int is set, indices start from 1
result = Blender.Draw.PupMenu(name)
return "false"
- else:
- return t
+ """
+
#===============================
# Data
#===============================
+
+
#===============================
# Blender Curve Data
#===============================
@@ -172,16 +302,20 @@ class Bez:
def __init__(self):
self.co=[]
self.ha=[0,0]
-
+ self.tag=''
+
class ITEM:
def __init__(self):
- self.type = typBEZIER3D,
+ self.type = typBEZIER3D
self.pntsUV = [0,0]
self.resolUV = [32,0]
self.orderUV = [0,0]
self.flagUV = [0,0]
self.Origine = [0.0,0.0]
self.beziers_knot = []
+ self.fill=0
+ self.closed=0
+ self.color=[0.0,0.0,0.0]
class COURBE:
def __init__(self):
@@ -222,7 +356,7 @@ def test_egalitedespositions(f1,f2):
def Open_GEOfile(dir,nom):
- global SCALE,BOUNDINGBOX, scale
+ global SCALE,BOUNDINGBOX, scale_
if BLversion>=233:
Blender.Load(dir+nom+'OOO.obj', 1)
BO=Blender.Object.Get()
@@ -231,7 +365,7 @@ def Open_GEOfile(dir,nom):
BO[-1].RotZ=3.1416
BO[-1].RotX=3.1416/2.0
- if scale==1:
+ if scale_==1:
BO[-1].LocY+=BOUNDINGBOX['rec'][3]
else:
BO[-1].LocY+=BOUNDINGBOX['rec'][3]/SCALE
@@ -242,14 +376,14 @@ def Open_GEOfile(dir,nom):
print "Not yet implemented"
def create_GEOtext(courbes):
- global SCALE, B, BOUNDINGBOX,scale
- r=BOUNDINGBOX['rec']
+ global SCALE, B, BOUNDINGBOX,scale_
- if scale==1:
+ r=BOUNDINGBOX['rec']
+ if scale_==1:
SCALE=1.0
- elif scale==2:
+ elif scale_==2:
SCALE=r[2]-r[0]
- elif scale==3:
+ elif scale_==3:
SCALE=r[3]-r[1]
t=[]
@@ -284,211 +418,535 @@ def save_GEOfile(dir,nom,t):
f.writelines(t)
f.close()
+#--------------------
+# 0.4.5 : for blender cvs 2.38 ....
+#--------------------
+def createCURVES(courbes):
+ global SCALE, B, BOUNDINGBOX,scale_
+ from Blender import Curve, Object, Scene, BezTriple
+
+ r=BOUNDINGBOX['rec']
+ if scale_==1:
+ SCALE=1.0
+ elif scale_==2:
+ SCALE=r[2]-r[0]
+ elif scale_==3:
+ SCALE=r[3]-r[1]
+
+ [o.select(0) for o in Object.Get()]
+ for I in courbes.ITEM:
+ c = Curve.New()
+ # ----------
+ # 0.4.7
+ # ----------
+ c.setResolu(24)
+ scene = Scene.getCurrent()
+ ob = Object.New('Curve')
+ ob.link(c)
+ scene.link(ob)
+ ob.select(1)
+ bzn=0
+ #for b in courbes.ITEM[I].beziers_knot:
+ for k2 in range(0,len(courbes.ITEM[I].beziers_knot)):
+ bz=ajustement(courbes.ITEM[I].beziers_knot[k2], SCALE)
+ #bz=k1
+ if bzn==0:
+ cp1 = bz[4],bz[5],0.0 , bz[0],bz[1],0.0, bz[2],bz[3],0.0,
+ beztriple1 = BezTriple.New(cp1)
+ bez = c.appendNurb(beztriple1)
+
+ bzn = 1
+ else:
+ cp2 = bz[4],bz[5],0.0 , bz[0],bz[1],0.0, bz[2],bz[3],0.0
+ beztriple2 = BezTriple.New(cp2)
+ bez.append(beztriple2)
+
+ if courbes.ITEM[I].flagUV[0]==1 :
+ #--------------------
+ # 0.4.6 : cyclic flag ...
+ #--------------------
+ bez.flagU += 1
+
-def filtre_DATA(c,D,n):
- global DEBUG,TAGcourbe
- #print 'c',c,'D',D,'n',n
- l=[]
- if len(c[0])==1 and D[c[1]+1].find(',')!=-1:
- for n2 in range(1,n+1):
- ld=D[c[1]+n2].split(',')
- for l_ in ld:
- l.append(l_)
-
- elif len(c[0])==1 and D[c[1]+2][0] not in TAGcourbe:
- for n2 in range(1,n*2+1):
- l.append(D[c[1]+n2])
- if DEBUG==1 : print l
-
- return l
#=====================================================================
#===== SVG format : DEBUT =========================
#=====================================================================
+#--------------------
+# 0.4.2
+#--------------------
+OTHERSSHAPES=['rect','line', 'polyline', 'polygon','circle','ellipse']
+
+#--------------------
+# 0.4.2
+#--------------------
+def rect(prp):
+ D=[]
+ if 'x' not in prp.keys(): x=0.0
+ else : x=float(prp['x'])
+ if 'y' not in prp.keys(): y=0.0
+ else : y=float(prp['y'])
+
+ height=float(prp['height'])
+ width=float(prp['width'])
+
+ """
+ normal rect
+
+ x,y
+ h1
+ *----------*
+ | |
+ | |
+ | |
+ *----------* v1
+ h2
+ """
+ if 'rx' not in prp.keys() or 'rx' not in prp.keys():
+ exec """D=['M','%s','%s','h','%s','v','%s','h','%s','z']"""%(x,y,width,height,-width)
+ else :
+ rx=float(prp['rx'])
+ if 'ry' not in prp.keys() :
+ ry=float(prp['rx'])
+ else : ry=float(prp['ry'])
+ if 'rx' in prp.keys() and prp['rx']<0.0: rx*=-1
+ if 'ry' in prp.keys() and prp['ry']<0.0: ry*=-1
+
+ """
+ rounded corner
+
+ x,y M h1
+ ---*----------*
+ / \
+ / \
+ v2 * * c1
+ | |
+ | |
+ | |
+ c3 * * v2
+ \ /
+ \ /
+ *----------*
+ h2 c2
+ """
+ exec """D=['M','%s','%s',
+ 'h','%s',
+ 'c','%s','%s','%s','%s','%s','%s',
+ 'v','%s',
+ 'c','%s','%s','%s','%s','%s','%s',
+ 'h','%s',
+ 'c','%s','%s','%s','%s','%s','%s',
+ 'v','%s',
+ 'c','%s','%s','%s','%s','%s','%s',
+ 'z']"""%(x+rx,y,
+ width-2*rx,
+ rx,0.0,rx,ry,rx,ry,
+ height-ry,
+ 0.0,ry,-rx,ry,-rx,ry,
+ -width+2*rx,
+ -rx,0.0,-rx,-ry,-rx,-ry,
+ -height+ry,
+ 0.0,0.0,0.0,-ry,rx,-ry
+ )
+
+ return D
+
+#--------------------
+# 0.4.2
+#--------------------
+def circle(prp):
+ if 'cx' not in prp.keys(): cx=0.0
+ else : cx =float(prp['cx'])
+ if 'cy' not in prp.keys(): cy=0.0
+ else : cy =float(prp['cy'])
+ r = float(prp['r'])
+ exec """D=['M','%s','%s',
+ 'C','%s','%s','%s','%s','%s','%s',
+ 'C','%s','%s','%s','%s','%s','%s',
+ 'C','%s','%s','%s','%s','%s','%s',
+ 'C','%s','%s','%s','%s','%s','%s',
+ 'Z']"""%(
+ cx,cy+r,
+ cx-r,cy+r*0.552, cx-0.552*r,cy+r, cx,cy+r,
+ cx+r*0.552,cy+r, cx+r,cy+r*0.552, cx+r,cy,
+ cx+r,cy-r*0.552, cx+r*0.552,cy-r, cx,cy-r,
+ cx-r*0.552,cy-r, cx-r,cy-r*0.552, cx-r,cy
+ )
+ return D
+
+#--------------------
+# 0.4.2
+#--------------------
+def ellipse(prp):
+ if 'cx' not in prp.keys(): cx=0.0
+ else : cx =float(prp['cx'])
+ if 'cy' not in prp.keys(): cy=0.0
+ else : cy =float(prp['cy'])
+ ry = float(prp['rx'])
+ rx = float(prp['ry'])
+
+ exec """D=['M','%s','%s',
+ 'C','%s','%s','%s','%s','%s','%s',
+ 'C','%s','%s','%s','%s','%s','%s',
+ 'C','%s','%s','%s','%s','%s','%s',
+ 'C','%s','%s','%s','%s','%s','%s',
+ 'Z']"""%(
+ cx,cy+rx,
+ cx-ry,cy+rx*0.552, cx-0.552*ry,cy+rx, cx,cy+rx,
+ cx+ry*0.552,cy+rx, cx+ry,cy+rx*0.552, cx+ry,cy,
+ cx+ry,cy-rx*0.552, cx+ry*0.552,cy-rx, cx,cy-rx,
+ cx-ry*0.552,cy-rx, cx-ry,cy-rx*0.552, cx-ry,cy
+ )
+ return D
+#--------------------
+# 0.4.2
+#--------------------
+def line(prp):
+ exec """D=['M','%s','%s',
+ 'L','%s','%s']"""%(prp['x1'],prp['y1'], prp['x2'],prp['y2'])
+ return D
+#--------------------
+# 0.4.2
+#--------------------
+def polyline(prp):
+ if 'points' in prp.keys():
+ #print prp['points']
+ points=prp['points'].split(' ')
+ #print points
+ np=0
+ for p in points:
+ if p!='':
+ p=p.split(',')
+ if np==0:
+ exec "D=['M','%s','%s']"%(p[0],p[1])
+ np+=1
+ else:
+ exec """D.append('L');D.append('%s');D.append('%s')"""%(p[0],p[1])
+ #print D
+ return D
+ else:
+ return []
+
+#--------------------
+# 0.4.2
+#--------------------
+def polygon(prp):
+ D=polyline(prp)
+ if D!=[]:
+ D.append('Z')
+ return D
-def contruit_SYMETRIC(l):
- L=[float(l[0]), float(l[1]),
- float(l[2]),float(l[3])]
- X=L[0]-(L[2]-L[0])
- Y=L[1]-(L[3]-L[1])
- l =[l[0],l[1],"%4s"%X,"%4s"%Y,l[2],l[3]]
- return l
-
-def mouvement_vers(c, D, n0,CP):
+
+#--------------------
+# 0.3.9
+#--------------------
+def calc_arc (cpx,cpy, rx, ry, ang, fa , fs , x, y) :
+ rx=abs(rx)
+ ry=abs(ry)
+ px=abs((cos(ang)*(cpx-x)+sin(ang)*(cpy-y))*0.5)**2.0
+ py=abs((cos(ang)*(cpy-y)-sin(ang)*(cpx-x))*0.5)**2.0
+ pl=px/(rx**2.0)+py/(ry**2.0 )
+ if pl>1.0:
+ pl=pl**0.5;rx*=pl;ry*=pl
+ x0=(cos(ang)/rx)*cpx+(sin(ang)/rx)*cpy
+ y0=(-sin(ang)/ry)*cpx+(cos(ang)/ry)*cpy
+ x1=(cos(ang)/rx)*x+(sin(ang)/rx)*y
+ y1=(-sin(ang)/ry)*x+(cos(ang)/ ry)*y
+ d=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)
+ if abs(d)>0.0 :sq=1.0/d-0.25
+ else: sq=-0.25
+ if sq<0.0 :sq=0.0
+ sf=sq**0.5
+ if fs==fa :sf=-sf
+ xc=0.5*(x0+x1)-sf*(y1-y0)
+ yc=0.5*(y0+y1)+sf*(x1-x0)
+ ang_0=atan2(y0-yc,x0-xc)
+ ang_1=atan2(y1-yc,x1-xc)
+ ang_arc=ang_1-ang_0;
+ if (ang_arc < 0.0 and fs==1) :
+ ang_arc += 2.0 * PI
+ elif (ang_arc>0.0 and fs==0) :
+ ang_arc-=2.0*PI
+ n_segs=int(ceil(abs(ang_arc*2.0/(PI*0.5+0.001))))
+ P=[]
+ for i in range(n_segs):
+ ang0=ang_0+i*ang_arc/n_segs
+ ang1=ang_0+(i+1)*ang_arc/n_segs
+ ang_demi=0.25*(ang1-ang0)
+ t=2.66666*sin(ang_demi)*sin(ang_demi)/sin(ang_demi*2.0)
+ x1=xc+cos(ang0)-t*sin(ang0)
+ y1=yc+sin(ang0)+t*cos(ang0)
+ x2=xc+cos(ang1)
+ y2=yc+sin(ang1)
+ x3=x2+t*sin(ang1)
+ y3=y2-t*cos(ang1)
+ P.append([[(cos(ang)*rx)*x1+(-sin(ang)*ry)*y1,
+ (sin(ang)*rx)*x1+(cos(ang)*ry)*y1],
+ [(cos(ang)*rx)*x3+(-sin(ang)*ry)*y3,
+ (sin(ang)*rx)*x3+(cos(ang)*ry)*y3],
+ [(cos(ang)*rx)*x2+(-sin(ang)*ry)*y2,
+ (sin(ang)*rx)*x2+(cos(ang)*ry)*y2]])
+ return P
+
+
+#--------------------
+# 0.3.9
+#--------------------
+def courbe_vers_a(c,D,n0,CP): #A,a
+ global SCALE
+
+ l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),
+ int(D[c[1]+4]),int(D[c[1]+5]),float(D[c[1]+6]),float(D[c[1]+7])]
+ if c[0]=='a':
+ l[5]=l[5] + CP[0]
+ l[6]=l[6] + CP[1]
+
+ B=Bez()
+ B.co=[ CP[0], CP[1], CP[0], CP[1], CP[0], CP[1] ]
+ B.ha=[0,0]
+ B.tag=c[0]
+
+ POINTS= calc_arc (CP[0],CP[1],
+ l[0], l[1], l[2]*(PI / 180.0),
+ l[3], l[4],
+ l[5], l[6] )
+
+ if DEBUG == 1 : print POINTS
+
+ for p in POINTS :
+ B=Bez()
+ B.co=[ p[2][0],p[2][1], p[0][0],p[0][1], p[1][0],p[1][1]]
+ B.ha=[0,0]
+ B.tag=c[0]
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ BP.co[2]=B.co[2]
+ BP.co[3]=B.co[3]
+ courbes.ITEM[n0].beziers_knot.append(B)
+
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ BP.co[2]=BP.co[0]
+ BP.co[3]=BP.co[1]
+
+ CP=[l[5], l[6]]
+ return courbes,n0,CP
+
+def mouvement_vers(c, D, n0,CP, proprietes):
global DEBUG,TAGcourbe
- #print 'c',c,'D[c[1]+1]',D[c[1]+1]
- l=filtre_DATA(c,D,1)
- #print 'l',l
+ #l=filtre_DATA(c,D,2)
+ l=[float(D[c[1]+1]),float(D[c[1]+2])]
+
+ if c[0]=='m':
+ l=[l[0]+CP[0],
+ l[1] + CP[1]]
+
if n0 in courbes.ITEM.keys():
n0+=1
- #
- # CP=[l[0],l[1]]
- #else:
- # CP=[l[0],l[1]]
- CP=[l[0],l[1]]
+ CP=[l[0],l[1]]
courbes.ITEM[n0]=ITEM()
courbes.ITEM[n0].Origine=[l[0],l[1]]
+ proprietes['n'].append(n0)
+ #print 'prop et item',proprietes['n'], courbes.ITEM.keys()
+
B=Bez()
B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
B.ha=[0,0]
-
+ B.tag=c[0]
courbes.ITEM[n0].beziers_knot.append(B)
- if DEBUG==1: print courbes.ITEM[n0], CP
+ if DEBUG==1: print courbes.ITEM[n0], CP
return courbes,n0,CP
def boucle_z(c,D,n0,CP): #Z,z
#print c, 'close'
- courbes.ITEM[n0].flagUV[0]=1
+ #print courbes.ITEM[n0].beziers_knot
+ courbes.ITEM[n0].flagUV[0]=1
+ #print 'len(courbes.ITEM[n0].beziers_knot)',len(courbes.ITEM[n0].beziers_knot)
+ if len(courbes.ITEM[n0].beziers_knot)>1:
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ BP0=courbes.ITEM[n0].beziers_knot[0]
+ if BP.tag in ['c','C','s','S']:
+ BP.co[2]=BP0.co[2] #4-5 point prec
+ BP.co[3]=BP0.co[3]
+ del courbes.ITEM[n0].beziers_knot[0]
+ else:
+ del courbes.ITEM[n0]
+
+ n0-=1
return courbes,n0,CP
-
-def courbe_vers_s(c,D,n0,CP): #S,s
- l=filtre_DATA(c,D,2)
- if c[0]=='s':
- l=["%4s"%(float(l[0])+float(CP[0])),
- "%4s"%(float(l[1])+float(CP[1])),
- "%4s"%(float(l[2])+float(CP[0])),
- "%4s"%(float(l[3])+float(CP[1]))]
- l=contruit_SYMETRIC(l)
+
+def courbe_vers_q(c,D,n0,CP): #Q,q
+ l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),float(D[c[1]+4])]
+ if c[0]=='q':
+ l=[l[0]+CP[0], l[1]+CP[1], l[2]+CP[0], l[3]+CP[1]]
+ B=Bez()
+ B.co=[l[2], l[3], l[2], l[3], l[0], l[1]] #plus toucher au 2-3
+ B.ha=[0,0]
+ B.tag=c[0]
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ BP.co[2]=BP.co[0]
+ BP.co[3]=BP.co[1]
+ courbes.ITEM[n0].beziers_knot.append(B)
+ if DEBUG==1: print B.co,BP.co
+
+ CP=[l[2],l[3]]
+ if DEBUG==1:
+ pass
+ if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe :
+ c[1]+=4
+ courbe_vers_q(c, D, n0,CP)
+ return courbes,n0,CP
+
+def courbe_vers_t(c,D,n0,CP): #T,t
+ l=[float(D[c[1]+1]),float(D[c[1]+2])]
+ if c[0]=='t':
+ l=[l[0]+CP[0], l[1]+CP[1]]
+
B=Bez()
- B.co=[l[4],l[5],l[2],l[3],l[0],l[1]] #plus toucher au 2-3
+ B.co=[l[0], l[1], l[0], l[1], l[0], l[1]] #plus toucher au 2-3
B.ha=[0,0]
+ B.tag=c[0]
BP=courbes.ITEM[n0].beziers_knot[-1]
- BP.co[2]=l[2] #4-5 point prec
- BP.co[3]=l[3]
+
+ l0=contruit_SYMETRIC([BP.co[0],BP.co[1],BP.co[4],BP.co[5]])
+
+ if BP.tag in ['q','Q','t','T','m','M']:
+ BP.co[2]=l0[2]
+ BP.co[3]=l0[3]
courbes.ITEM[n0].beziers_knot.append(B)
if DEBUG==1: print B.co,BP.co
- CP=[l[4],l[5]]
-
- if len(D)<c[1]+3 and D[c[1]+3] not in TAGcourbe :
- c[1]+=2
- courbe_vers_c(c, D, n0,CP)
- return courbes,n0,CP
-def courbe_vers_a(c,D,n0,CP): #A
- #print c
+ CP=[l[0],l[1]]
+ if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe :
+ c[1]+=4
+ courbe_vers_t(c, D, n0,CP)
return courbes,n0,CP
-def courbe_vers_q(c,D,n0,CP): #Q
- #print c
- return courbes,n0,CP
+#--------------------
+# 0.4.3 : rewritten
+#--------------------
+def contruit_SYMETRIC(l):
+ X=l[2]-(l[0]-l[2])
+ Y=l[3]-(l[1]-l[3])
+ return X,Y
-def courbe_vers_t(c,D,n0,CP): #T
- return courbes,n0,CP
+def courbe_vers_s(c,D,n0,CP): #S,s
+ l=[float(D[c[1]+1]),
+ float(D[c[1]+2]),
+ float(D[c[1]+3]),
+ float(D[c[1]+4])]
+ if c[0]=='s':
+ l=[l[0]+CP[0], l[1]+CP[1],
+ l[2]+CP[0], l[3]+CP[1]]
+ B=Bez()
+ B.co=[l[2],l[3],l[2],l[3],l[0],l[1]] #plus toucher au 2-3
+ B.ha=[0,0]
+ B.tag=c[0]
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ #--------------------
+ # 0.4.3
+ #--------------------
+ BP.co[2],BP.co[3]=contruit_SYMETRIC([BP.co[4],BP.co[5],BP.co[0],BP.co[1]])
+ courbes.ITEM[n0].beziers_knot.append(B)
+ if DEBUG==1: print B.co,BP.co
+ #--------------------
+ # 0.4.3
+ #--------------------
+ CP=[l[2],l[3]]
+ if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe :
+ c[1]+=4
+ courbe_vers_c(c, D, n0,CP)
+ return courbes,n0,CP
def courbe_vers_c(c, D, n0,CP): #c,C
-
- l=filtre_DATA(c,D,3)
-
- print '\n','l',l, 'c',c,'CP', CP
-
+ l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),
+ float(D[c[1]+4]),float(D[c[1]+5]),float(D[c[1]+6])]
if c[0]=='c':
- l=["%4s"%(float(l[0])+float(CP[0])),
- "%4s"%(float(l[1])+float(CP[1])),
- "%4s"%(float(l[2])+float(CP[0])),
- "%4s"%(float(l[3])+float(CP[1])),
- "%4s"%(float(l[4])+float(CP[0])),
- "%4s"%(float(l[5])+float(CP[1]))]
-
- #print l
-
+ l=[l[0]+CP[0],
+ l[1]+CP[1],
+ l[2]+CP[0],
+ l[3]+CP[1],
+ l[4]+CP[0],
+ l[5]+CP[1]]
B=Bez()
B.co=[l[4],
l[5],
- l[0],
- l[1],
+ l[4],
+ l[5],
l[2],
l[3]] #plus toucher au 2-3
-
B.ha=[0,0]
-
+ B.tag=c[0]
BP=courbes.ITEM[n0].beziers_knot[-1]
-
BP.co[2]=l[0]
BP.co[3]=l[1]
-
courbes.ITEM[n0].beziers_knot.append(B)
if DEBUG==1: print B.co,BP.co
-
CP=[l[4],l[5]]
- if DEBUG==1:
- pass #print 'D[c[1]]', D[c[1]], c
- #print D
- if len(D)<c[1]+4 and D[c[1]+4] not in TAGcourbe :
- c[1]+=3
+ if len(D)>c[1]+7 and D[c[1]+7] not in TAGcourbe :
+ c[1]+=6
courbe_vers_c(c, D, n0,CP)
-
return courbes,n0,CP
def ligne_tracee_l(c, D, n0,CP): #L,l
- #print c
-
- l=filtre_DATA(c,D,1)
+ l=[float(D[c[1]+1]),float(D[c[1]+2])]
if c[0]=='l':
- l=["%4s"%(float(l[0])+float(CP[0])),
- "%4s"%(float(l[1])+float(CP[1]))]
-
+ l=[l[0]+CP[0],
+ l[1]+CP[1]]
B=Bez()
B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
B.ha=[0,0]
+ B.tag=c[0]
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ if BP.tag in ['c','C','s','S','m','M']:
+ BP.co[2]=B.co[4]
+ BP.co[3]=B.co[5]
courbes.ITEM[n0].beziers_knot.append(B)
-
- CP=[l[0],l[1]]
-
- if len(D)<c[1]+2 and D[c[1]+2] not in TAGcourbe :
- c[1]+=1
+ CP=[B.co[0],B.co[1]]
+ if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe :
+ c[1]+=2
ligne_tracee_l(c, D, n0,CP) #L
-
return courbes,n0,CP
def ligne_tracee_h(c,D,n0,CP): #H,h
- #print '|',c[0],'|',len(c[0]),' --> ',CP[0]
- #print 'D :',D,' \n CP :', CP
if c[0]=='h':
- l=["%4s"%(float(D[c[1]+1])+float(CP[0])),"%4s"%float(CP[1])]
+ l=[float(D[c[1]+1])+float(CP[0]),CP[1]]
else:
- l=["%4s"%float(D[c[1]+1]),"%4s"%float(CP[1])]
+ l=[float(D[c[1]+1]),CP[1]]
B=Bez()
B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
B.ha=[0,0]
+ B.tag=c[0]
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ if BP.tag in ['c','C','s','S','m','M']:
+ BP.co[2]=B.co[4]
+ BP.co[3]=B.co[5]
courbes.ITEM[n0].beziers_knot.append(B)
-
CP=[l[0],l[1]]
- #print 'CP', CP
return courbes,n0,CP
-def ligne_tracee_v(c,D,n0,CP): #V, v
- #l=filtre_DATA(c,D,0)
-
+def ligne_tracee_v(c,D,n0,CP): #V, v
if c[0]=='v':
- l=["%4s"%float(CP[0]),
- "%4s"%(float(D[c[1]+1])+float(CP[1]))]
- #print '|',c[0],'|', len(c[0]) ,' --> ',CP
+ l=[CP[0], float(D[c[1]+1])+CP[1]]
else:
- l=["%4s"%float(CP[0]),
- "%4s"%float(D[c[1]+1])]
- #print '|',c[0],'|', len(c[0]) ,' --> ',CP
-
+ l=[CP[0], float(D[c[1]+1])]
B=Bez()
B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
B.ha=[0,0]
+ B.tag=c[0]
+ BP=courbes.ITEM[n0].beziers_knot[-1]
+ if BP.tag in ['c','C','s','S','m','M']:
+ BP.co[2]=B.co[4]
+ BP.co[3]=B.co[5]
courbes.ITEM[n0].beziers_knot.append(B)
-
CP=[l[0],l[1]]
- #print 'CP', CP
- return courbes,n0,CP
-
-def boucle_tracee_z(c,D,n0,CP): #Z
- #print c
- #CP=[]
return courbes,n0,CP
Actions= { "C" : courbe_vers_c,
@@ -517,81 +975,8 @@ Actions= { "C" : courbe_vers_c,
TAGcourbe=Actions.keys()
TAGtransform=['M','L','C','S','H','V','T','Q']
tagTRANSFORM=0
-
-def get_content(val,t0):
- t=t0[:]
- if t.find(' '+val+'="')!=-1:
- t=t[t.find(' '+val+'="')+len(' '+val+'="'):]
- val=t[:t.find('"')]
- t=t[t.find('"'):]
- return t0,val
- else:
- return t0,0
-
-def get_tag(val,t):
- t=t[t.find('<'+val):]
- val=t[:t.find('>')+1]
- t=t[t.find('>')+1:]
- if DEBUG==3 : print t[:10], val
- return t,val
-
-def get_data(val,t):
- t=t[t.find('<'+val):]
- val=t[:t.find('</'+val+'>')]
- t=t[t.find('</'+val+'>')+3+len(val):]
- if DEBUG==3 : print t[:10], val
- return t,val
-
-def get_val(val,t):
- d=""
- #print t
- for l in t:
- if l.find(val+'="')!=-1:
- #print 'l', l
- # 0.2.7 : - correction for inskape 0.40 cvs SVG
- l=l.replace('>','')
- # 0.2.7 : -- end
- d=l[l[:-1].rfind('"')+1:-1]
- #print 'd', d
- for nn in d:
- if '0123456789.'.find(nn)==-1:
- d=d.replace(nn,"")
- #print d
- d=float(d)
- break
- #else:
- # print l
- d=0.0
- return d
-
-
-
-def get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox):
- if viewbox==0:
- h=get_val('height',SVG)
- if DEBUG==1 : print 'h : ',h
- w=get_val('width',SVG)
- if DEBUG==1 : print 'w :',w
- BOUNDINGBOX['rec']=[0.0,0.0,w,h]
- r=BOUNDINGBOX['rec']
- BOUNDINGBOX['coef']=w/h
- else:
- viewbox=viewbox.split()
- BOUNDINGBOX['rec']=[float(viewbox[0]),float(viewbox[1]),float(viewbox[2]),float(viewbox[3])]
- r=BOUNDINGBOX['rec']
- BOUNDINGBOX['coef']=(r[2]-r[0])/(r[3]-r[1])
-
- return BOUNDINGBOX
-
-# 0.2.8 : - correction for inskape 0.40 cvs SVG
-def repack_DATA2(DATA):
- for d in Actions.keys():
- DATA=DATA.replace(d,d+' ')
- return DATA
-
-
+
def wash_DATA(ndata):
- print 'ndata', ndata, len(ndata)
if ndata!='':
while ndata[0]==' ':
ndata=ndata[1:]
@@ -599,17 +984,21 @@ def wash_DATA(ndata):
ndata=ndata[:-1]
if ndata[0]==',':ndata=ndata[1:]
if ndata[-1]==',':ndata=ndata[:-1]
- if ndata.find('-')!=-1 and ndata[ndata.find('-')-1] not in [' ',' ']:
+ #--------------------
+ # 0.4.0 : 'e'
+ #--------------------
+ if ndata.find('-')!=-1 and ndata[ndata.find('-')-1] not in [' ', ',', 'e']:
ndata=ndata.replace('-',',-')
ndata=ndata.replace(',,',',')
ndata=ndata.replace(' ',',')
ndata=ndata.split(',')
for n in ndata :
- if n=='' : ndata.remove(n)
+ if n=='' : ndata.remove(n)
return ndata
-
-
-# 0.3.4 : - restructuration de la lecture des donnes paths
+
+#--------------------
+# 0.3.4 : - reading data rewrittten
+#--------------------
def list_DATA(DATA):
"""
cette fonction doit retourner une liste proposant
@@ -618,238 +1007,304 @@ def list_DATA(DATA):
Par exemple :
d="'M0,14.0 z" devient ['M','0.0','14.0','z']
"""
- while DATA.count(' ')!=0 :
- DATA=DATA.replace(' ',' ')
-
tagplace=[]
- DATA=DATA.replace('\n','')
-
for d in Actions.keys():
b1=0
b2=len(DATA)
while DATA.find(d,b1,b2)!=-1 :
- #print d, b1
tagplace.append(DATA.find(d,b1,b2))
b1=DATA.find(d,b1,b2)+1
tagplace.sort()
tpn=range(len(tagplace)-1)
- DATA2=[]
-
- for t in tpn:
-
- DATA2.append(DATA[tagplace[t]:tagplace[t]+1])
- print DATA2[-1]
-
- ndata=DATA[tagplace[t]+1:tagplace[t+1]]
- if DATA2[-1] not in ['z','Z'] :
+ #--------------------
+ # 0.3.5 :: short data,only one tag
+ #--------------------
+ if len(tagplace)-1>0:
+ DATA2=[]
+ for t in tpn:
+ DATA2.append(DATA[tagplace[t]:tagplace[t]+1])
+ ndata=DATA[tagplace[t]+1:tagplace[t+1]]
+ if DATA2[-1] not in ['z','Z'] :
+ ndata=wash_DATA(ndata)
+ for n in ndata : DATA2.append(n)
+ DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1])
+ if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1:
+ ndata=DATA[tagplace[t+1]+1:-1]
ndata=wash_DATA(ndata)
for n in ndata : DATA2.append(n)
-
- DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1])
-
- print DATA2[-1]
-
- if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1:
- ndata=DATA[tagplace[t+1]+1:-1]
- ndata=wash_DATA(ndata)
- for n in ndata : DATA2.append(n)
-
+ else:
+ #--------------------
+ # 0.3.5 : short data,only one tag
+ #--------------------
+ DATA2=[]
+ DATA2.append(DATA[tagplace[0]:tagplace[0]+1])
+ ndata=DATA[tagplace[0]+1:]
+ ndata=wash_DATA(ndata)
+ for n in ndata : DATA2.append(n)
return DATA2
-
# 0.3
-def translate(tx,ty):
+def translate(tx=None,ty=None):
return [1, 0, tx], [0, 1, ty],[0,0,1]
-
# 0.3.2
-def scale(sx,sy):
+def scale(sx=None,sy=None):
+ if sy==None: sy=sx
return [sx, 0, 0], [0, sy, 0],[0,0,1]
-# 0.3.2
+# 0.4.1 : transslate a in radians
def rotate(a):
- return [cos(a), -sin(a), 0], [sin(a), cos(a),0],[0,0,1]
+ return [cos(a*3.1416/90.0), -sin(a*3.1416/90.0), 0], [sin(a*3.1416/90.0), cos(a*3.1416/90.0),0],[0,0,1]
# 0.3.2
def skewX(a):
return [1, tan(a), 0], [0, 1, 0],[0,0,1]
-# 0.3.2
-def skewX(a):
+# 0.4.1
+def skewY(a):
return [1, 0, 0], [tan(a), 1 , 0],[0,0,1]
# 0.3.2
def matrix(a,b,c,d,e,f):
- return [a,b,e],[c,d,f],[0,0,1]
+ return [a,c,e],[b,d,f],[0,0,1]
-# 0.3.3
-def controle_CONTENU(val,t):
+# 0.4.2 : rewritten
+def control_CONTAINT(txt):
"""
- une matrice peut s'ecrire : matrix(a,b,c,d,e,f) ou matrix(a b c d e f)
+ les descriptions de transformation peuvent être seules ou plusieurs et
+ les séparateurs peuvent avoir été oubliés
"""
- if val.find('matrix') and t.find(val+'(')!=-1 and t.find(val+',')==-1:
- t0=t[t.find(val+'(')+len(val+'('):]
- t0=t0[:t0.find(')')]
- val=t0[:]
- while val.find(' ')!=-1:
- val=val.replace(' ',' ')
- val=val.replace(' ',',')
- t=t.replace(t0,val)
- return val
- else:
- return -1
-
-# 0.3
-def get_TRANSFORM(STRING):
- STRING,TRANSFORM=get_content('transform',STRING)
- #print 'TRANSFORM 1 :', TRANSFORM
- for t in ['translate','scale','rotate','matrix','skewX','skewY'] :
- if TRANSFORM.find(t)!=-1 and TRANSFORM.count('(')==1:
- #print 'TRANSFORM 2 :', TRANSFORM
- print ' getcontent ', t,' ',controle_CONTENU(t,TRANSFORM)
- exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%TRANSFORM
- return T
-
-# 0.3
-def G_move(l,a,t):
- if a==0:
- v=Mathutils.Vector([float(l[0]),float(l[1]),1.0])
- v=Mathutils.MatMultVec(t, v)
- return str(v[0]),str(v[1])
- else :
- #print 'l', l ,'t', t, 'a', a
- l=l.split(',')
- v=Mathutils.Vector([float(l[0]),float(l[1]),1.0])
- v=Mathutils.MatMultVec(t, v)
- return str(v[0])+','+str(v[1])
-
-# 0.3
-def transform_DATA(D1,TRANSFORM):
- for cell in range(len(D1)):
- if D1[cell] in TAGtransform:
- if D1[cell+1].find(',')==-1:
- if D1[cell] in ['C', 'S','Q', 'M','L','T',]: #2 valeurs
- D1[cell+1],D1[cell+2]=G_move([D1[cell+1],D1[cell+2]],0,TRANSFORM)
- if D1[cell] in ['C', 'S','Q'] :
- D1[cell+3],D1[cell+4]=G_move([D1[cell+3],D1[cell+4]],0,TRANSFORM)
- if D1[cell] in ['C']:
- D1[cell+5],D1[cell+6]=G_move([D1[cell+5],D1[cell+6]],0,TRANSFORM)
- else :
- if D1[cell] == 'C': #6 valeurs
- D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
- D1[cell+2]=G_move(D1[cell+2],-1,TRANSFORM)
- D1[cell+3]=G_move(D1[cell+3],-1,TRANSFORM)
- elif D1[cell] in ['M','L','T']: #2 valeurs
- D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
- elif D1[cell] == ['S','Q']: #4 valeurs
- D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
- D1[cell+2]=G_move(D1[cell+2],-1,TRANSFORM)
- if D1[cell] == 'H': #1 valeurs x
- n=0
- D1[cell+1]=G_move(D1[cell+1],0,TRANSFORM)
- elif D1[cell] == 'V': #1 valeurs y
- n=0
- D1[cell+1]=G_move(D1[cell+1],1,TRANSFORM)
- return D1
-
-def format_PATH(t,TRANSFORM):
- global tagTRANSFORM
-
- t,PATH=get_tag('path',t)
-
- if PATH.find(' transform="')!=-1:
- TRANSFORM2=get_TRANSFORM(PATH)
- # 0.3.3
- TRANSFORM=TRANSFORM*TRANSFORM2
- #TRANSFORM[1]+=TRANSFORM2[1]
- tagTRANSFORM+=1
-
- if PATH.find(' id="')!=-1:
- PATH,ID=get_content('id',PATH)
- #print 'ident = ', ID
-
- if PATH.find(' STROKE="')!=-1:
- PATH,ID=get_content('stroke',PATH)
- #print 'path stroke = ', ID
-
- if PATH.find(' stroke-width="')!=-1:
- PATH,ID=get_content('stroke-width',PATH)
- #print 'path stroke-width = ', ID
-
- if PATH.find(' d="')!=-1:
- PATH,D=get_content('d',PATH)
- D=list_DATA(D)
-
- if tagTRANSFORM in [1,2] : D=transform_DATA(D,TRANSFORM)
- return t,D
-
+ t0=0
+ tlist=[]
+ while txt.count(')',t0)>0:
+ t1=txt.find(')',t0)
+ nt0=txt[t0:t1+1]
+ t2=nt0[nt0.find('(')+1:-1]
+ val=nt0[:nt0.find('(')]
+ while t2.find(' ')!=-1:
+ t2=t2.replace(' ',' ')
+ t2=t2.replace(' ',',')
+ if t2.find('e'):
+ t3=t2.split(',')
+ t2=''
+ for t in t3 :
+ t=str(float(t))
+ t2=str(t3).replace(']','').replace('[','').replace('\'','')
+ if val=='rotate' :
+ t3=t2.split(',')
+ if len(t3)==3:
+ tlist.append('translate('+t3[1]+','+t3[2]+')')
+ tlist.append('rotate('+t3[0]+')')
+ tlist.append('translate(-'+t3[1]+',-'+t3[2]+')')
+ else:
+ tlist.append(val+'('+t2+')')
+ t0=t1+1
+ return tlist
+
+# 0.4.1 : apply transform stack
+def courbe_TRANSFORM(Courbe,proprietes):
+ # 1/ deplier le STACK
+ # créer une matrice pour chaque transformation
+ ST=[]
+ #print proprietes['stack']
+ for st in proprietes['stack'] :
+ if st and type(st)==list:
+ for t in st:
+ exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%control_CONTAINT(t)[0]
+ ST.append(T)
+ elif st :
+ exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%control_CONTAINT(st)[0]
+ ST.append(T)
+ if 'transform' in proprietes.keys():
+ for trans in control_CONTAINT(proprietes['transform']):
+ exec """a,b,c=%s;T=Mathutils.Matrix(a,b,c)"""%trans
+ ST.append(T)
+ #print ST
+ ST.reverse()
+ for n in proprietes['n']:
+ if n in Courbe.keys():
+ for bez0 in Courbe[n].beziers_knot:
+ bez=bez0.co
+ for b in [0,2,4]:
+ for t in ST:
+ v=Mathutils.Vector([bez[b],bez[b+1],1.0])
+ #v=Mathutils.MatMultVec(t, v)
+ v=t * v
+ bez[b]=v[0]
+ bez[b+1]=v[1]
+
+def filtre(d):
+ for nn in d:
+ if '0123456789.'.find(nn)==-1:
+ d=d.replace(nn,"")
+ return d
+def get_BOUNDBOX(BOUNDINGBOX,SVG):
+ if 'viewbox' not in SVG.keys():
+ h=float(filtre(SVG['height']))
+ if DEBUG==1 : print 'h : ',h
+ w=float(filtre(SVG['width']))
+ if DEBUG==1 : print 'w :',w
+ BOUNDINGBOX['rec']=[0.0,0.0,w,h]
+ r=BOUNDINGBOX['rec']
+ BOUNDINGBOX['coef']=w/h
+ else:
+ viewbox=SVG['viewbox'].split()
+ BOUNDINGBOX['rec']=[float(viewbox[0]),float(viewbox[1]),float(viewbox[2]),float(viewbox[3])]
+ r=BOUNDINGBOX['rec']
+ BOUNDINGBOX['coef']=(r[2]-r[0])/(r[3]-r[1])
+ return BOUNDINGBOX
+# 0.4.1 : attributs ex : 'id=', 'transform=', 'd=' ...
+def collecte_ATTRIBUTS(data):
+ data=data.replace(' ',' ')
+ ELEM={'TYPE':data[1:data.find(' ')]}
+ t1=len(data)
+ t2=0
+ ct=data.count('="')
+ while ct>0:
+ t0=data.find('="',t2)
+ t2=data.find(' ',t2)+1
+ id=data[t2:t0]
+ t2=data.find('"',t0+2)
+ if id!='d':
+ exec "ELEM[id]=\"\"\"%s\"\"\""%(data[t0+2:t2].replace('\\','/'))
+ else:
+ exec "ELEM[id]=[%s,%s]"%(t0+2,t2)
+ ct=data.count('="',t2)
+ return ELEM
+
+# --------------------------------------------
+# 0.4.1 : to avoid to use sax and ths xml
+# tools of the complete python
+# --------------------------------------------
+def contruit_HIERARCHIE(t):
+ global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
+ TRANSFORM=0
+ t=t.replace('\t',' ')
+ while t.find(' ')!=-1:
+ t=t.replace(' ',' ')
+ n0=0
+ t0=t1=0
+ baliste=[]
+ balisetype=['?','?','/','/','!','!']
+ BALISES=['D', #DECL_TEXTE',
+ 'D', #DECL_TEXTE',
+ 'F', #FERMANTE',
+ 'E', #ELEM_VIDE',
+ 'd', #DOC',
+ 'R', #REMARQUES',
+ 'C', #CONTENU',
+ 'O' #OUVRANTE'
+ ]
+ STACK=[]
+ while t1<len(t) and t0>-1:
+ t0=t.find('<',t0)
+ t1=t.find('>',t0)
+ ouvrante=0
+ #--------------------
+ # 0.4.4 , add 'else:' and 'break' to the 'if' statement
+ #--------------------
+ if t0>-1 and t1>-1:
+ if t[t0+1] in balisetype:
+ b=balisetype.index(t[t0+1])
+ if t[t0+2]=='-':
+ b=balisetype.index(t[t0+1])+1
+ balise=BALISES[b]
+ if b==2:
+ parent=STACK.pop(-1)
+ if parent!=None and TRANSFORM>0:
+ TRANSFORM-=1
+ elif t[t1-1] in balisetype:
+ balise=BALISES[balisetype.index(t[t1-1])+1]
+ else:
+ t2=t.find(' ',t0)
+ if t2>t1: t2=t1
+ ouvrante=1
+ NOM=t[t0+1:t2]
+ if t.find('</'+NOM)>-1:
+ balise=BALISES[-1]
+ else:
+ balise=BALISES[-2]
+ if balise=='E' or balise=='O':
+ proprietes=collecte_ATTRIBUTS(t[t0:t1+ouvrante])
+ if balise=='O' and 'transform' in proprietes.keys():
+ STACK.append(proprietes['transform'])
+ TRANSFORM+=1
+ elif balise=='O' :
+ STACK.append(None)
+ proprietes['stack']=STACK[:]
+ D=[]
+ if proprietes['TYPE'] in ['path'] and (proprietes['d'][1]-proprietes['d'][0]>1):
+ D=list_DATA(t[proprietes['d'][0]+t0:proprietes['d'][1]+t0])
+ elif proprietes['TYPE'] in OTHERSSHAPES:
+ exec "D=%s(proprietes)"% proprietes['TYPE']
+ if len(D)>0:
+ cursor=0
+ proprietes['n']=[]
+ for cell in D:
+ if DEBUG==2 : print 'cell : ',cell ,' --'
+ if len(cell)>=1 and cell[0] in TAGcourbe:
+ prop=''
+ if cell[0] in ['m','M']:
+ prop=',proprietes'
+ exec """courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP%s)"""%prop
+ cursor+=1
+ if TRANSFORM>0 or 'transform' in proprietes.keys() :
+ courbe_TRANSFORM(courbes.ITEM,proprietes)
+ elif proprietes['TYPE'] in ['svg'] :
+ BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,proprietes)
+ else:
+ #--------------------
+ # 0.4.4
+ #--------------------
+ break
+ t1+=1
+ t0=t1
def scan_FILE(nom):
- global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale, tagTRANSFORM
+ global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
dir,name=split(nom)
name=name.split('.')
- n0=0
result=0
-
t=filtreFICHIER(nom)
-
if t!='false':
+ Blender.Window.EditMode(0)
if not SHARP_IMPORT:
warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3"
- scale = Blender.Draw.PupMenu(warning)
- npat=0
- l=0
- do=0
- t,SVG=get_tag('svg',t)
-
- SVG,viewbox=get_content('viewBox',SVG)
-
- SVG=SVG.split(' ')
- if DEBUG==1 : print SVG
- if viewbox==0:
- BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,0)
- else:
- BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox)
-
- while t.find('<g')!=-1:
- t,G=get_data('g',t)
- TRANSFORM=Mathutils.Matrix([1.0,0.0,0.0],[0.0,1.0,0.0],[0,0,1])
- tagTRANSFORM=0
- if G.find(' transform="')!=-1:
- TRANSFORM=get_TRANSFORM(G)
- tagTRANSFORM=1
-
- while G.find('path')!=-1:
- G,D=format_PATH(G,TRANSFORM)
- #print D
- cursor=0
- for cell in D:
- if DEBUG==2 : print 'cell : ',cell ,' --'
- if len(cell)>=1 and cell[0] in TAGcourbe:
- courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP)
- cursor+=1
-
- # 0.3.1
- while t.find('path')!=-1:
- TRANSFORM=Mathutils.Matrix([1.0,0.0,0.0],[0.0,1.0,0.0],[0,0,1])
- t,D=format_PATH(t,TRANSFORM)
- cursor=0
- for cell in D:
- if DEBUG==2 : print 'cell : ',cell ,' --'
- if len(cell)>=1 and cell[0] in TAGcourbe:
- courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP)
- cursor+=1
-
+ scale_ = Blender.Draw.PupMenu(warning)
+ # 0.4.1 : to avoid to use sax and the xml
+ # tools of the complete python
+ contruit_HIERARCHIE(t)
+ r=BOUNDINGBOX['rec']
+ if scale_==1:
+ SCALE=1.0
+ elif scale==2:
+ SCALE=r[2]-r[0]
+ elif scale_==3:
+ SCALE=r[3]-r[1]
courbes.number_of_items=len(courbes.ITEM.keys())
-
for k in courbes.ITEM.keys():
courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
- if courbes.number_of_items>0:
+ #--------------------
+ # 0.4.5
+ #--------------------
+ CVS=2
+ if BLversion>=238 :
+ warning = "CVS version you can import as : %t| Blender internal, experimental ? %x1 | Old proofed method, import using Blender OBJ format %x2"
+ CVS=Blender.Draw.PupMenu(warning)
+
+ if courbes.number_of_items>0 and CVS==2:
if len(PATTERN.keys() )>0:
if DEBUG == 3 : print len(PATTERN.keys() )
t=create_GEOtext(courbes)
save_GEOfile(dir,name[0],t)
Open_GEOfile(dir,name[0])
+
+ elif courbes.number_of_items>0 and CVS==1 :
+ #--------------------
+ # 0.4.5
+ #--------------------
+ createCURVES(courbes)
+
else:
- pass
+ pass
def ajustement(v,s):
@@ -868,4 +1323,4 @@ def fonctionSELECT(nom):
scan_FILE(nom)
if __name__=='__main__':
- Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .SVG FILE')
+ Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .SVG FILE') \ No newline at end of file
diff --git a/release/scripts/bvh2arm.py b/release/scripts/bvh2arm.py
index ec04f59d60f..e4430cdad96 100644
--- a/release/scripts/bvh2arm.py
+++ b/release/scripts/bvh2arm.py
@@ -1,40 +1,60 @@
#!BPY
"""
-Name: 'BVH Empties to Armature'
-Blender: 237
+Name: 'Empties to Armature'
+Blender: 241
Group: 'Animation'
-Tooltip: 'Create Armature from Empties created by BVH importer'
+Tooltip: 'Create Armature from a parented-empties chain'
"""
-__author__ = " Jean-Baptiste PERIN (jb_perin(at)yahoo.fr)"
+__author__ = " Jean-Baptiste PERIN (jb_perin(at)yahoo.fr) with valuable help from Vincent BILLET "
__url__ = ("blender", "elysiun",
-"BVH 2 ARMATURE, http://www.zoo-logique.org/3D.Blender/index.php3?zoo=dld&rep=zip ",
+"BVH 2 ARMATURE, http://perso.wanadoo.fr/jb.perin/",
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
-__version__ = "2.2"
+__version__ = "2.42"
-__bpydoc__ = """ BVH2ARM.py v2.2
+__bpydoc__ = """ BVH2ARM.py
Script for generating armature on BVH empties.
-This script generates an armature and make bones
-follow empties created by Blender BVH import script.
-
+This script generates an armature upon an empty-made parented chain,
+and make the armature follow the empties
+
Usage:<br>
- Import a bvh in Blender (File->Import->BVH);<br>
- - Launch this script (Alt-P);<br>
+ - Rotate some empties to match your model and insert Rot key for them. <br>
+ - Select the root empty of the hierarchical chain.<br>
+ - Launch this script ;<br>
- Set up variables:<br>
- "hipbonename": the name of the main bone;<br>
+ "hipbonename": the name of the main bone (automatically set to the selected empty).<br>
"startframe": the first frame of your anim;<br>
"endframe": the last frame of your anim;<br>
- "decimation": the frequency (in number of frame) to which the armature is updated;<br>
- "scale" to size the created armature.<br>
- - Press "Create Armature".
+ "decimation": the frequency (in number of frame) to which the armature's pos is updated;<br>
+- Press "Create Armature".
+Notes: <br>
+- The start frame configuration is used as the rest pose for the armature.<br>
+- If the armature already exists when script is launched, the current armature is re-used.
"""
-
-#----------------------------------------------
-# (c) Jean-Baptiste PERIN june 2005, released under Blender Artistic Licence
-# for the Blender 2.34-2.36 Python Scripts Bundle.
-#----------------------------------------------
+# --------------------------------------------------------------------------
+# BVH2ARM.py
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
@@ -50,6 +70,9 @@ dicEmptyChild={}
dicBoneRestInvEmpRest={}
dicEmpRestInvBoneRest={}
restFrame = 1
+bonerest={}
+emprest={}
+emp2bone={}
########################################################################
#
@@ -111,8 +134,8 @@ def getEmpty(name):
p = o
return p
-def getChild(emp, emp_list):
- return dicEmptyChild[emp.getName()]
+##def getChild(emp, emp_list):
+## return dicEmptyChild[emp.getName()]
#########
@@ -206,32 +229,6 @@ def GetOrCreateCurve(ipo, curvename):
#
########################################################################
-def computeRootQuat2(empty, bone):
-
- M1=dicBoneRestInvEmpRest[bone.getName()].rotationPart()
- M2=dicEmpRestInvBoneRest[bone.getName()].rotationPart()
- emprot = empty.getMatrix('worldspace').rotationPart()
- emprot.transpose()
- mat = M1*emprot*M2
- mat.transpose()
- return (mat.toQuat())
-
- #emprest = dicEmptiesRestMatrix[empty.getName()].rotationPart()
- #invemprest= dicEmptiesRestMatrix[empty.getName()].rotationPart()
- ##invemprest= emprest
- ##invemprest.invert()
- ##invemprest= dicEmptiesInvRestMatrix[empty.getName()].rotationPart()
- #emprot = empty.getMatrix('worldspace').rotationPart()
- #bonerest = dicBoneRestMatrix[bone.getName()].rotationPart()
- #invbonerest = dicBoneRestMatrix[bone.getName()].rotationPart()
- #invbonerest.invert()
- #T2=emprot*invemprest
- #T2.transpose()
- #mat = bonerest*invemprest*T2*emprest*invbonerest
- #mat.transpose()
- #return (mat.toQuat())
-
-
#########
@@ -239,27 +236,6 @@ def computeRootQuat2(empty, bone):
# in :
# out :
#########
-def computeRootPos(empty, bone):
- vec = computeScaledPos(empty.getMatrix('worldspace').translationPart()) - dicBoneRestMatrix[bone.getName()].translationPart()
- mat = dicBoneRestMatrix[bone.getName()].rotationPart()
- vec2 = Mathutils.MatMultVec (mat, vec)
- return vec2
-
-
-def computeRelativePos(empty,bone):
- vec = computeScaledPos(empty.getMatrix('worldspace').translationPart()) - dicBoneRestMatrix[bone.getName()].translationPart()
- rootempty = getEmpty(hipbonename)
- vec3 = computeScaledPos(rootempty.getMatrix('worldspace').translationPart())
- mat = dicBoneRestMatrix[bone.getName()].rotationPart()
- vec2 = Mathutils.MatMultVec (mat, vec-vec3)
- return vec2
-
-
- #########
-# Cette fonction
-# in :
-# out :
-#########
def computeScaledPos(vec):
global scalef
vec2 = Mathutils.Vector([vec[0]*scalef, vec[1]*scalef, vec[2]*scalef])
@@ -277,31 +253,28 @@ def computeScaledPos(vec):
# out :
#########
def createBone (armature, empty, bone, empties):
+ global bonerest, emprest
children = getChildren(empty, empties)
- for ch in children:
+ if len(children) != 0:
+ for ch in children:
if len(children) >= 2:
bonename = empty.getName()[1:len(empty.getName())]+'_'+ch.getName()[1:len(ch.getName())]
else :
bonename = empty.getName()[1:len(empty.getName())]
- b=Blender.Armature.Bone.New(bonename)
- b.setHead(computeScaledPos(empty.getMatrix('worldspace').translationPart()))
- b.setTail(computeScaledPos(ch.getMatrix('worldspace').translationPart()))
- #b.setParent(bone)
- matrice = empty.getMatrix('worldspace')
- invmatrice = empty.getMatrix('worldspace')
- invmatrice.invert()
- invmatricet=empty.getMatrix('worldspace')
- invmatricet.invert()
- invmatricet.transpose()
- dicEmptiesRestMatrix[empty.getName()] = matrice
- dicEmptiesInvRestMatrix[empty.getName()] = invmatrice
- armature.addBone(b)
- invbonerest=b.getRestMatrix()
- invbonerest.invert()
- dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
- dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
- dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
- dicBone[b.getName()]=b
+ print "creating Bone %s"%(bonename)
+ b=Blender.Armature.Editbone()
+ b.head = (computeScaledPos(empty.getMatrix('worldspace').translationPart()))
+ b.tail = (computeScaledPos(ch.getMatrix('worldspace').translationPart()))
+ b.parent = bone
+ # armature.makeEditable() should already be editable????
+ armature.bones[bonename] = b
+ #print b.matrix
+ bonerest[bonename]=Blender.Mathutils.Matrix(b.matrix).resize4x4()
+ emprest[empty.getName()]=Blender.Mathutils.Matrix(empty.getMatrix('localspace')).resize4x4()
+ #M = Blender.Mathutils.Matrix(emprest[empty.getName()])
+ #emp2bone[bonename] = Blender.Mathutils.Matrix(M.invert().rotationPart()*bonerest[bonename].rotationPart()).resize4x4()
+ #print emp2bone[bonename].rotationPart().toEuler()
+ dicBone[b.name]=b
createBone(armature, ch, b, empties)
#########
@@ -310,13 +283,12 @@ def createBone (armature, empty, bone, empties):
# out :
#########
def f_createBone (armData, empty, bone, empties):
- bones = armData.getBones()
-
+ bones = armData.bones.values()
def getBone(bonename):
bone = None
for b in bones:
#print b.getName()
- if b.getName() == bonename:
+ if b.name == bonename:
bone = b
return bone
@@ -328,56 +300,41 @@ def f_createBone (armData, empty, bone, empties):
bonename = empty.getName()[1:len(empty.getName())]
#b=Blender.Armature.Bone.New(bonename)
b=getBone(bonename)
- #b.setHead(empty.getMatrix('worldspace').translationPart())
- #b.setTail(ch.getMatrix('worldspace').translationPart())
- #b.setParent(bone)
- matrice = empty.getMatrix('worldspace')
- invmatrice = empty.getMatrix('worldspace')
- invmatrice.invert()
- invmatricet=empty.getMatrix('worldspace')
- invmatricet.invert()
- invmatricet.transpose()
- dicEmptiesRestMatrix[empty.getName()] = matrice
- dicEmptiesInvRestMatrix[empty.getName()] = invmatrice
- #armature.addBone(b)
- invbonerest=b.getRestMatrix()
- invbonerest.invert()
- dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
- dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
- dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
- dicBone[b.getName()]=b
+ b.head = (computeScaledPos(empty.getMatrix('worldspace').translationPart()))
+ b.tail = (computeScaledPos(ch.getMatrix('worldspace').translationPart()))
+ b.parent = bone
+ bonerest[bonename]=Blender.Mathutils.Matrix(b.matrix).resize4x4()
+ emprest[empty.getName()]=Blender.Mathutils.Matrix(empty.getMatrix('localspace')).resize4x4()
+ dicBone[b.name]=b
#print "Ajout de ", b.getName()," au dictionnaire"
f_createBone(armData, ch, b, empties)
-
#########
# Cette fonction fabrique une arma
# in :
# out :
#########
-def createArmature (rootEmpty, empties):
- armData=Blender.Armature.New('monArmature')
+def createArmature (armObj, rootEmpty, empties):
+ global bonerest, emprest
+ armData=Blender.Armature.Armature('monArmature')
children = getChildren(rootEmpty, empties)
+ armObj.link(armData)
+ armData.makeEditable()
for ch in children:
- b=Blender.Armature.Bone.New(rootEmpty.getName()[1:len(rootEmpty.getName())] + ch.getName()[1:len(ch.getName())])
- b.setHead(computeScaledPos(rootEmpty.getMatrix('worldspace').translationPart()))
- b.setTail(computeScaledPos(ch.getMatrix('worldspace').translationPart()))
- armData.addBone(b)
- matrice = ch.getMatrix('worldspace')
- invmatrice = ch.getMatrix('worldspace')
- invmatrice.invert()
- invmatricet=ch.getMatrix('worldspace')
- invmatricet.invert()
- invmatricet.transpose()
- dicEmptiesRestMatrix[rootEmpty.getName()] = matrice
- dicEmptiesInvRestMatrix[rootEmpty.getName()] = invmatrice
- invbonerest=b.getRestMatrix()
- invbonerest.invert()
- dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
- dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
- dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
- dicBone[b.getName()]=b
+ b=Blender.Armature.Editbone()
+ bonename = rootEmpty.getName()[1:len(rootEmpty.getName())] + ch.getName()[1:len(ch.getName())]
+ print "creating Bone %s"%(bonename)
+
+ #print b, dir([b])
+ b.head=(computeScaledPos(rootEmpty.getMatrix('worldspace').translationPart()))
+ b.tail=(computeScaledPos(ch.getMatrix('worldspace').translationPart()))
+
+ bonerest[bonename]=Blender.Mathutils.Matrix(b.matrix).resize4x4()
+ emprest[rootEmpty.getName()]=Blender.Mathutils.Matrix(rootEmpty.getMatrix('localspace')).resize4x4()
+ armData.bones[bonename] = b
+ dicBone[b.name]=b
createBone(armData, ch, b, empties)
+ armData.update()
return armData
@@ -388,37 +345,27 @@ def createArmature (rootEmpty, empties):
# out :
#########
def f_createArmature (rootEmpty, empties, armData):
- bones = armData.getBones()
+ armData.makeEditable()
+ bones = armData.bones.values()
def getBone(bonename):
bone = None
for b in bones:
#print b.getName()
- if b.getName() == bonename:
+ if b.name == bonename:
bone = b
return bone
children = getChildren(rootEmpty, empties)
for ch in children:
b=getBone(rootEmpty.getName()[1:len(rootEmpty.getName())] + ch.getName()[1:len(ch.getName())])
- matrice = ch.getMatrix('worldspace')
- invmatrice = ch.getMatrix('worldspace')
- invmatrice.invert()
- invmatricet=ch.getMatrix('worldspace')
- invmatricet.invert()
- invmatricet.transpose()
- dicEmptiesRestMatrix[rootEmpty.getName()] = matrice
- dicEmptiesInvRestMatrix[rootEmpty.getName()] = invmatrice
- invbonerest=b.getRestMatrix()
- invbonerest.invert()
- dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
- dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
- dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
- dicBone[b.getName()]=b
+ dicBone[b.name]=b
#print "Ajout de ", b.getName()," au dictionnaire"
-
+ bonerest[b.name]=Blender.Mathutils.Matrix(b.matrix).resize4x4()
+ emprest[rootEmpty.getName()]=Blender.Mathutils.Matrix(rootEmpty.getMatrix('localspace')).resize4x4()
f_createBone(armData, ch, b, empties)
+ armData.update()
#########
@@ -426,20 +373,34 @@ def f_createArmature (rootEmpty, empties, armData):
# in :
# out :
#########
-def moveBones(armature, empty, empties):
+def moveBones(larmature, empty, empties):
+ #print "move bones"
+ global bonerest, emprest
children = dicEmptyChild[empty.getName()]
+ thepose = larmature.getPose()
for ch in children:
if len(children) >= 2:
bonename = empty.getName()[1:len(empty.getName())]+'_'+ch.getName()[1:len(ch.getName())]
else :
bonename = empty.getName()[1:len(empty.getName())]
- bone = dicBone[bonename]
- #bone.setLoc(computeRootPos(empty,bone))
- bone.setLoc(computeRelativePos(empty,bone))
- bone.setQuat(computeRootQuat2(empty,bone))
- chch = dicEmptyChild[ch.getName()]
+ thebone = thepose.bones[bonename]
+ trMatrix = empty.getMatrix('localspace')
+ bonerestmat = Blender.Mathutils.Matrix(bonerest[bonename])
+ invbonerestmat = Blender.Mathutils.Matrix(bonerest[bonename])
+ invbonerestmat.invert()
+ trMatrix[3][0] = 0.0
+ trMatrix[3][1] = 0.0
+ trMatrix[3][2] = 0.0
+ invemprestmat = Blender.Mathutils.Matrix(emprest[empty.getName()].rotationPart()).resize4x4()
+ invemprestmat.invert()
+ emprestmat = Blender.Mathutils.Matrix(emprest[empty.getName()].rotationPart()).resize4x4()
+ thebone.localMatrix = bonerestmat* invemprestmat *trMatrix * invbonerestmat
+ thepose.update()
+ thebone.insertKey(larmature, Blender.Get('curframe'), [Blender.Object.Pose.ROT, Blender.Object.Pose.LOC])
+ thepose.update()
+ chch = dicEmptyChild[ch.getName()]
if len(chch) >= 1:
- moveBones(armature, ch, empties)
+ moveBones(larmature, ch, empties)
#########
@@ -447,26 +408,20 @@ def moveBones(armature, empty, empties):
# in :
# out :
#########
-def moveArmature (armature, empties):
+def moveArmature (larmature, empties):
+ global bonerest, emprest
+ #print "move armature"
+ thepose = larmature.getPose()
+ #armature.makeEditable()
root = Blender.Object.Get(hipbonename)
children = dicEmptyChild[hipbonename]
for ch in children:
b=dicBone[hipbonename[1:len(hipbonename)] + ch.getName()[1:len(ch.getName())]]
- #b.setLoc(computeRootPos(root, b))
- b.setLoc([0.0, 0.0, 0.0])
- b.setQuat(computeRootQuat2(root, b))
- moveBones(armature, ch, empties)
+
+ moveBones(larmature, ch, empties)
+ #armature.update()
-def eraseIPO (objectname):
- object = Blender.Object.Get(objectname)
- lIpo = object.getIpo()
- if lIpo != None:
- nbCurves = lIpo.getNcurves()
- for i in range(nbCurves):
- nbBezPoints = lIpo.getNBezPoints(i)
- for j in range(nbBezPoints):
- lIpo.delBezPoint(i)
########################################################################
@@ -512,7 +467,7 @@ def Main():
lesEmpties = getEmpties()
#print dicEmptyChild
-
+ print "creating armature"
#armData = createArmature(em0, lesEmpties)
objects = Blender.Object.Get()
if 'OBArmature' in map(names,objects):
@@ -523,15 +478,16 @@ def Main():
#print armData.getBones()
f_createArmature(em0, lesEmpties, armData)
else:
- armData= createArmature(em0, lesEmpties)
armObj=Blender.Object.New('Armature', 'OBArmature')
- armObj.link(armData)
+ armData= createArmature(armObj, em0, lesEmpties)
+ #armObj.link(armData)
scn = Blender.Scene.getCurrent()
scn.link (armObj)
print 'OBArmature'+' was created'
#return myobj
-
+ print emprest
+ armData.drawType = Blender.Armature.STICK
##-----------
## Creation de l'ipo de l'armature
##-----------
@@ -540,7 +496,11 @@ def Main():
curvX = GetOrCreateCurve(lipo, 'LocX')
curvY = GetOrCreateCurve(lipo, 'LocY')
curvZ = GetOrCreateCurve(lipo, 'LocZ')
+ curvrX = GetOrCreateCurve(lipo, 'RotX')
+ curvrY = GetOrCreateCurve(lipo, 'RotY')
+ curvrZ = GetOrCreateCurve(lipo, 'RotZ')
+ print "animating armature"
#armData.drawAxes(1)
#armData.drawNames(1)
@@ -549,13 +509,16 @@ def Main():
Blender.Redraw()
+ action = Blender.Armature.NLA.NewAction()
+ action.setActive(armObj)
+
+
+
##-----------
## Enregistrement de la position de l'armature
##-----------
- bones = armData.getBones()
- for bo in bones:
- bo.setPose([Blender.Armature.Bone.ROT, Blender.Armature.Bone.LOC])
+ bones = armData.bones.values()
curvX.addBezier((Blender.Get("curframe"), getEmpty(hipbonename).getMatrix('worldspace').translationPart()[0]*scalef))
curvY.addBezier((Blender.Get("curframe"), getEmpty(hipbonename).getMatrix('worldspace').translationPart()[1]*scalef))
@@ -566,6 +529,12 @@ def Main():
curvY.setExtrapolation('Constant')
curvZ.setInterpolation('Linear')
curvZ.setExtrapolation('Constant')
+ curvrX.setInterpolation('Linear')
+ curvrX.setExtrapolation('Constant')
+ curvrY.setInterpolation('Linear')
+ curvrY.setExtrapolation('Constant')
+ curvrZ.setInterpolation('Linear')
+ curvrZ.setExtrapolation('Constant')
Blender.Redraw()
@@ -576,18 +545,19 @@ def Main():
## Positionnement des os
##-----------
- moveArmature(armData, lesEmpties)
+ moveArmature(armObj, lesEmpties)
##-----------
## Enregistrement de la position de l'armature
##-----------
- for bo in bones:
- bo.setPose([Blender.Armature.Bone.ROT, Blender.Armature.Bone.LOC])
curvX.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[0])*scalef))
curvY.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[1])*scalef))
curvZ.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[2])*scalef))
+ curvrX.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').rotationPart().toEuler()[0])*scalef/10))
+ curvrY.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').rotationPart().toEuler()[1])*scalef/10))
+ curvrZ.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').rotationPart().toEuler()[2])*scalef/10))
##-----------
## Passage a la frame suivante
@@ -596,6 +566,12 @@ def Main():
print num_frame
Blender.Set("curframe", num_frame)
+ curvX.Recalc()
+ curvY.Recalc()
+ curvZ.Recalc()
+ curvrX.Recalc()
+ curvrY.Recalc()
+ curvrZ.Recalc()
Blender.Set("curframe",startframe)
Blender.Redraw()
@@ -627,26 +603,35 @@ def button_event(evt):
global endframe, startframe, insertionframe, hipbonename, framedecimation , scalef
if evt==1:
startframe = SFrame2.val
- insertionframe = IFrame.val
+ insertionframe = 100 #IFrame.val
endframe = EFrame.val
hipbonename = HBName.val
framedecimation = FrameDecimation.val
- scalef= eval(str(ScaleF.val))
+ scalef= 1.0 #eval(str(ScaleF.val))
#print "scalef = ", scalef
if startframe>=endframe:
Msg = 'Start frame must be lower than End frame'
+ error_txt = "Error|Start frame must be lower than End frame"
+ Blender.Draw.PupMenu(error_txt)
else:
ob = getEmpty(hipbonename)
if (ob!=None):
if ob.getParent()!=None:
Msg = 'Empty '+hipbonename+ ' is not a root bone.'
+ error_txt = "Error|Empty %s is not a root bone"%hipbonename
+ Blender.Draw.PupMenu(error_txt)
else:
if (0.0 > scalef):
Msg = 'Scale factor must be greater than 0'
+ error_txt = "Error|Scale factor must be greater than 0"
+ Blender.Draw.PupMenu(error_txt)
else:
#Blender.Draw.Exit()
Main()
+ #Main()
else:
+ error_txt = "Error|Empty %s not found"%hipbonename
+ Blender.Draw.PupMenu(error_txt)
Msg = 'Empty '+ hipbonename+ ' not found'
#Blender.Draw.Redraw(1)
@@ -655,6 +640,9 @@ def button_event(evt):
ob = getEmpty(hipbonename)
if (ob!=None):
if ob.getParent()!=None:
+ error_txt = "Error|Empty %s is not a root bone"%hipbonename
+ Blender.Draw.PupMenu(error_txt)
+
Msg = 'Empty '+hipbonename+ ' is not a root bone.'
else:
#Blender.Draw.Exit()
@@ -671,15 +659,17 @@ def GUI():
Blender.BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT)
Blender.BGL.glColor3f(1,1,1)
Blender.BGL.glRasterPos2i(20,200)
- Blender.Draw.Text ("BVH 2 ARMATURE v2.2 by Jean-Baptiste PERIN", 'normal')
- HBName = Blender.Draw.String("HipBoneName: ", 0, 20, 175, 250, 20, '_Hips', 100)
+ selobj = Blender.Object.GetSelected()
+ if len(selobj) == 1 and type (selobj[0]) == Blender.Types.ObjectType:
+ hipname = selobj[0].getName()
+ else:
+ hipname = '_Hips'
+ Blender.Draw.Text ("BVH 2 ARMATURE v%s by %s"%(__version__, __author__), 'normal')
+ HBName = Blender.Draw.String("HipBoneName: ", 0, 20, 175, 250, 20, hipname, 100)
SFrame2 = Blender.Draw.Number("Startframe: ", 0, 20, 150, 250, 20, 1, 1,3000,"Start frame of anim")
EFrame = Blender.Draw.Number("Endframe: ", 0, 20, 125, 250, 20, Blender.Get("endframe"), 1,3000,"Last frame of anim")
- #IFrame = Blender.Draw.Number("Insertionframe: ", 0, 20, 100, 250, 20, Blender.Get("staframe"), 1,3000,"")
- FrameDecimation = Blender.Draw.Number("FrameDecimation: ", 0, 20, 75, 250, 20,5, 1,10,'number of frame to skip between two action keys')
- ScaleF = Blender.Draw.Number("Scale: ", 0, 20, 50, 250, 20, 1.0, 0.0, 10.0, 'Scale Factor')
+ FrameDecimation = Blender.Draw.Number("FrameDecimation: ", 0, 20, 75, 250, 20,1, 1,10,'number of frame to skip between two action keys')
Blender.Draw.Toggle("Create Armature", 1, 20, 10, 100, 20, 0, "Create Armature")
- #Blender.Draw.Toggle("Remove Empties", 2, 200, 10, 100, 20, 0, "Remove Empties")
Blender.BGL.glRasterPos2i(20,40)
Blender.Draw.Text (Msg, 'normal')
diff --git a/release/scripts/bvh_export.py b/release/scripts/bvh_export.py
index 84425626cee..7c6ac4c7e36 100644
--- a/release/scripts/bvh_export.py
+++ b/release/scripts/bvh_export.py
@@ -9,7 +9,7 @@ Tip: 'Export a (.bvh) motion capture file'
__author__ = "Campbell Barton"
__url__ = ("blender", "elysiun")
-__version__ = "1.0 03/30/04"
+__version__ = "1.1 12/16/05"
__bpydoc__ = """\
This script exports animation data to BVH motion capture file format.
@@ -30,12 +30,11 @@ Notes:<br>
# BVH Export script 1.0 by Campbell Barton #
# Copyright MetaVR 30/03/2004, #
# if you have any questions about this script #
-# email me ideasman@linuxmail.org #
-# #
+# email me cbarton@metavr.com #
#===============================================#
# --------------------------------------------------------------------------
-# BVH Export v0.9 by Campbell Barton (AKA Ideasman)
+# BVH Export v1.1 by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -46,12 +45,12 @@ Notes:<br>
#
# 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
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
@@ -59,348 +58,328 @@ Notes:<br>
import Blender
from Blender import Scene, Object
import math
+time = Blender.sys.time
from math import *
# Get the current scene.
scn = Scene.GetCurrent()
context = scn.getRenderingContext()
-frameRate = 0.3333 # 0.04 = 25fps
-scale = 1
+frameRate = 1.0/context.framesPerSec() # 0.04 = 25fps
+scale = 1.0
-indent = ' ' # 2 space indent per object
+indent = '\t' # 2 space indent per object
prefixDelimiter = '_'
# Vars used in eular rotation funtcion
RAD_TO_DEG = 180.0/3.14159265359
-
+DEG_TO_RAD = math.pi/180.0
#====================================================#
# Search for children of this object and return them #
#====================================================#
def getChildren(parent):
- children = [] # We'll assume none.
- for child in Object.Get():
- if child.getParent() == Object.Get(parent):
- children.append( child.getName() )
- return children
+ children = [] # We'll assume none.
+ for child in Object.Get():
+ if child.parent == parent:
+ children.append( child )
+ return children
#====================================================#
-# MESSY BUT WORKS: Make a string that shows the #
-# hierarchy as a list and then eval it #
+# MESSY BUT WORKS: Make a string that shows the #
+# hierarchy as a list and then eval it #
#====================================================#
def getHierarchy(root, hierarchy):
- hierarchy = hierarchy + '["' + root + '",'
- for child in getChildren(root):
- hierarchy = getHierarchy(child, hierarchy)
- hierarchy += '],'
- return hierarchy
+ hierarchy = '%s["%s",' % (hierarchy, root.name)
+ for child in getChildren(root):
+ hierarchy = getHierarchy(child, hierarchy)
+ hierarchy = '%s],' % hierarchy
+ return hierarchy
#====================================================#
-# Strips the prefix off the name before writing #
+# Strips the prefix off the name before writing #
#====================================================#
def stripName(name): # name is a string
-
- # WARNING!!! Special case for a custom RIG for output
- # for MetaVR's HPX compatable RIG.
- print 'stripname', name[0:10]
- if name[0:10] == 'Transform(':
- name = name[10:]
- while name[-1] != ')':
- name = name[0:-1]
- print name
- name = name[:-1]
-
-
- return name[1+name.find(prefixDelimiter): ]
-
-
-#====================================================#
-# Return a 6 deciaml point floating point value #
-# as a string that dosent have any python chars #
-#====================================================#
-def saneFloat(float):
- #return '%(float)b' % vars() # 6 fp as house.hqx
- return str('%f' % float) + ' '
-
-
+
+ # WARNING!!! Special case for a custom RIG for output
+ # for MetaVR's HPX compatable RIG.
+ # print 'stripname', name[0:10]
+ if name.lower().startswith('transform('):
+ name = name[10:].split(prefixDelimiter)[0]
+ return name.split('_')[0]
+
#====================================================#
# Recieves an object name, gets all the data for that#
# node from blender and returns it for formatting #
# and writing to a file. #
#====================================================#
-def getNodeData(nodeName):
- Object.Get(nodeName)
- # Get real location
- offset = Object.Get(nodeName).getLocation()
- offset = (offset[0]*scale, offset[1]*scale, offset[2]*scale,)
-
- #=========================#
- # Test for X/Y/Z IPO's #
- #=========================#
- obipo = Object.Get(nodeName).getIpo()
-
- # IF we dont have an IPO then dont check the curves.
- # This was added to catch end nodes that never have an IPO, only an offset.
- if obipo == None:
- xloc=yloc=zloc=xrot=yrot=zrot = 0
-
- else: # Do have an IPO, checkout which curves are in use.
- # Assume the rot's/loc's exist until proven they dont
- xloc=yloc=zloc=xrot=yrot=zrot = 1
- if obipo.getCurve('LocX') == None:
- xloc = 0
- if obipo.getCurve('LocY') == None:
- yloc = 0
- if obipo.getCurve('LocZ') == None:
- zloc = 0
-
- # Now for the rotations, Because of the conversion of rotation coords
- # if there is one rotation er need to store all 3
- if obipo.getCurve('RotX') == None and \
- obipo.getCurve('RotY') == None and \
- obipo.getCurve('RotZ') == None:
- xrot=yrot=zrot = 0
-
- # DUMMY channels xloc, yloc, zloc, xrot, yrot, zrot
- # [<bool>, <bool>, <bool>, <bool>, <bool>, <bool>]
- channels = [xloc, yloc, zloc, xrot, yrot, zrot]
-
- return offset, channels
+def getNodeData(nodeOb):
+ ob = nodeOb
+ obipo = ob.getIpo()
+ # Get real location
+ offset = [o*scale for o in ob.getLocation()]
+
+ #=========================#
+ # Test for X/Y/Z IPO's #
+ #=========================#
+
+ # IF we dont have an IPO then dont check the curves.
+ # This was added to catch end nodes that never have an IPO, only an offset.
+
+ # DUMMY channels xloc, yloc, zloc, xrot, yrot, zrot
+ # [<bool>, <bool>, <bool>, <bool>, <bool>, <bool>]
+ channels = [0,0,0,0,0,0] # xloc,yloc,zloc,xrot,yrot,zrot
+ if obipo != None: # Do have an IPO, checkout which curves are in use.
+ # Assume the rot's/loc's dont exist until they proven they do.
+ if obipo.getCurve('LocX') != None:
+ channels[0] = 1
+ if obipo.getCurve('LocY') != None:
+ channels[1] = 1
+ if obipo.getCurve('LocZ') != None:
+ channels[2] = 1
+
+ # Now for the rotations, Because of the conversion of rotation coords
+ # if there is one rotation er need to store all 3
+ if obipo.getCurve('RotX') != None or \
+ obipo.getCurve('RotY') != None or \
+ obipo.getCurve('RotZ') != None:
+ channels[3] = channels[4] = channels[5] = 1
+ #print ob, channels
+ return offset, channels
#====================================================#
-# Return the BVH hierarchy to a file from a list #
+# Writes the BVH hierarchy to a file #
# hierarchy: is a list of the empty hierarcht #
-# bvhHierarchy: a string, in the bvh format to write #
# level: how many levels we are down the tree, #
# ...used for indenting #
# Also gathers channelList , so we know the order to #
-# write the motiondata in #
+# write the motiondata in #
#====================================================#
-def hierarchy2bvh(hierarchy, bvhHierarchy, level, channelList, nodeObjectList):
- nodeName = hierarchy[0]
-
- # Add object to nodeObjectList
- nodeObjectList.append(Object.Get(nodeName))
-
- #============#
- # JOINT NAME #
- #============#
- bvhHierarchy += level * indent
- if level == 0:
- # Add object to nodeObjectList
- nodeObjectList.append(Object.Get(nodeName))
- bvhHierarchy+= 'ROOT '
- bvhHierarchy += stripName(nodeName) + '\n'
- # If this is the last object in the list then we
- # dont bother withwriting its real name, use "End Site" instead
- elif len(hierarchy) == 1:
- bvhHierarchy+= 'End Site\n'
- # Ok This is a normal joint
- else:
- # Add object to nodeObjectList
- nodeObjectList.append(Object.Get(nodeName))
- bvhHierarchy+= 'JOINT '
- bvhHierarchy += stripName(nodeName) + '\n'
- #================#
- # END JOINT NAME #
- #================#
-
- # Indent again, this line is just for the brackets
- bvhHierarchy += level * indent + '{' + '\n'
-
- # Indent
- level += 1
-
- #================================================#
- # Data for writing to a file offset and channels #
- #================================================#
- offset, channels = getNodeData(nodeName)
-
- #============#
- # Offset #
- #============#
- bvhHierarchy += level * indent + 'OFFSET ' + saneFloat(scale * offset[0]) + ' ' + saneFloat(scale * offset[1]) + ' ' + saneFloat(scale * offset[2]) + '\n'
-
- #============#
- # Channels #
- #============#
- if len(hierarchy) != 1:
- # Channels, remember who is where so when we write motiondata
- bvhHierarchy += level * indent + 'CHANNELS '
- # Count the channels
- chCount = 0
- for chn in channels:
- chCount += chn
- bvhHierarchy += str(chCount) + ' '
- if channels[0]:
- bvhHierarchy += 'Xposition '
- channelList.append([len(nodeObjectList)-1, 0])
- if channels[1]:
- bvhHierarchy += 'Yposition '
- channelList.append([len(nodeObjectList)-1, 1])
- if channels[2]:
- bvhHierarchy += 'Zposition '
- channelList.append([len(nodeObjectList)-1, 2])
- if channels[5]:
- bvhHierarchy += 'Zrotation '
- channelList.append([len(nodeObjectList)-1, 5])
- if channels[3]:
- bvhHierarchy += 'Xrotation '
- channelList.append([len(nodeObjectList)-1, 3])
- if channels[4]:
- bvhHierarchy += 'Yrotation '
- channelList.append([len(nodeObjectList)-1, 4])
-
- bvhHierarchy += '\n'
-
- # Loop through children if any and run this function (recursively)
- for hierarchyIdx in range(len(hierarchy)-1):
- bvhHierarchy, level, channelList, nodeObjectList = hierarchy2bvh(hierarchy[hierarchyIdx+1], bvhHierarchy, level, channelList, nodeObjectList)
- # Unindent
- level -= 1
- bvhHierarchy += level * indent + '}' + '\n'
-
- return bvhHierarchy, level, channelList, nodeObjectList
+def hierarchy2bvh(file, hierarchy, level, channelList, nodeObjectList):
+ nodeName = hierarchy[0]
+ ob = Object.Get(nodeName)
+ '''
+ obipo = ob.getIpo()
+ if obipo != None:
+ obcurves = obipo.getCurves()
+ else:
+ obcurves = None
+ '''
+ #============#
+ # JOINT NAME #
+ #============#
+ file.write(level * indent)
+ if level == 0:
+ # Add object to nodeObjectList
+ #nodeObjectList.append( (ob, obipo, obcurves) )
+ nodeObjectList.append( ob )
+ file.write( 'ROOT %s\n' % stripName(nodeName) )
+ # If this is the last object in the list then we
+ # dont bother withwriting its real name, use "End Site" instead
+ elif len(hierarchy) == 1:
+ file.write( 'End Site\n' )
+ # Ok This is a normal joint
+ else:
+ # Add object to nodeObjectList
+ #nodeObjectList.append((ob, obipo, obcurves))
+ nodeObjectList.append( ob )
+ file.write( 'JOINT %s\n' % stripName(nodeName) )
+ #================#
+ # END JOINT NAME #
+ #================#
+
+ # Indent again, this line is just for the brackets
+ file.write( '%s{\n' % (level * indent) )
+
+ # Indent
+ level += 1
+
+ #================================================#
+ # Data for writing to a file offset and channels #
+ #================================================#
+ offset, channels = getNodeData(ob)
+
+ #============#
+ # Offset #
+ #============#
+ file.write( '%sOFFSET %.6f %.6f %.6f\n' %\
+ (level*indent, scale*offset[0], scale*offset[1], scale*offset[2]) )
+
+ #============#
+ # Channels #
+ #============#
+ if len(hierarchy) != 1:
+ # Channels, remember who is where so when we write motiondata
+ file.write('%sCHANNELS %i ' % (level*indent, len([c for c in channels if c ==1]) ))
+ if channels[0]:
+ file.write('Xposition ')
+ channelList.append([len(nodeObjectList)-1, 0])
+ if channels[1]:
+ file.write('Yposition ')
+ channelList.append([len(nodeObjectList)-1, 1])
+ if channels[2]:
+ file.write('Zposition ')
+ channelList.append([len(nodeObjectList)-1, 2])
+ if channels[5]:
+ file.write('Zrotation ')
+ channelList.append([len(nodeObjectList)-1, 5])
+ if channels[3]:
+ file.write('Xrotation ')
+ channelList.append([len(nodeObjectList)-1, 3])
+ if channels[4]:
+ file.write('Yrotation ')
+ channelList.append([len(nodeObjectList)-1, 4])
+ file.write('\n')
+
+ # Loop through children if any and run this function (recursively)
+ for hierarchyIdx in range(len(hierarchy)-1):
+ level = hierarchy2bvh(file, hierarchy[hierarchyIdx+1], level, channelList, nodeObjectList)
+ # Unindent
+ level -= 1
+ file.write('%s}\n' % (level * indent))
+
+ return level
# added by Ben Batt 30/3/2004 to make the exported rotations correct
def ZYXToZXY(x, y, z):
- '''
- Converts a set of Euler rotations (x, y, z) (which are intended to be
- applied in z, y, x order) into a set which are intended to be applied in
- z, x, y order (the order expected by .bvh files)
- '''
- A,B = cos(x),sin(x)
- C,D = cos(y),sin(y)
- E,F = cos(z),sin(z)
-
- x = asin(-B*C)
- y = atan2(D, A*C)
- z = atan2(-B*D*E + A*F, B*D*F + A*E)
-
- # this seems to be necessary - not sure why (right/left-handed coordinates?)
- x = -x
- return x*RAD_TO_DEG, y*RAD_TO_DEG, z*RAD_TO_DEG
-
-
-
-def getIpoLocation(object, frame):
- x = y = z = 0
- obipo = object.getIpo()
- for i in range(object.getIpo().getNcurves()):
- if obipo.getCurves()[i].getName() =='LocX':
- x = object.getIpo().EvaluateCurveOn(i,frame)
- elif obipo.getCurves()[i].getName() =='LocY':
- y = object.getIpo().EvaluateCurveOn(i,frame)
- elif obipo.getCurves()[i].getName() =='LocZ':
- z = object.getIpo().EvaluateCurveOn(i,frame)
- return x, y, z
-
+ '''
+ Converts a set of Euler rotations (x, y, z) (which are intended to be
+ applied in z, y, x order, into a set which are intended to be applied in
+ z, x, y order (the order expected by .bvh files)
+ '''
+ A,B = cos(x),sin(x)
+ C,D = cos(y),sin(y)
+ E,F = cos(z),sin(z)
+
+ x = asin(-B*C)
+ y = atan2(D, A*C)
+ z = atan2(-B*D*E + A*F, B*D*F + A*E)
+
+ # this seems to be necessary - not sure why (right/left-handed coordinates?)
+ # x = -x # x is negative, see below.
+ return -x*RAD_TO_DEG, y*RAD_TO_DEG, z*RAD_TO_DEG
+
+
+''' # UNUSED, JUST GET OBJECT LOC/ROT
+def getIpoLocation(object, obipo, curves, frame):
+ x = y = z = rx = ry = rz =0
+ if obipo:
+ for i in range(obipo.getNcurves()):
+ if curves[i].getName() =='LocX':
+ x = obipo.EvaluateCurveOn(i,frame)
+ elif curves[i].getName() =='LocY':
+ y = obipo.EvaluateCurveOn(i,frame)
+ elif curves[i].getName() =='LocZ':
+ z = obipo.EvaluateCurveOn(i,frame)
+ elif curves[i].getName() =='RotX':
+ rx = obipo.EvaluateCurveOn(i,frame)
+ elif curves[i].getName() =='RotY':
+ ry = obipo.EvaluateCurveOn(i,frame)
+ elif curves[i].getName() =='RotZ':
+ rz = obipo.EvaluateCurveOn(i,frame)
+ return x, y, z, rx*10*DEG_TO_RAD, ry*10*DEG_TO_RAD, rz*10*DEG_TO_RAD
+'''
#====================================================#
# Return the BVH motion for the spesified frame #
# hierarchy: is a list of the empty hierarcht #
-# bvhHierarchy: a string, in the bvh format to write #
# level: how many levels we are down the tree, #
# ...used for indenting #
#====================================================#
-def motion2bvh(frame, chennelList, nodeObjectList):
-
- motionData = '' # We'll append the frames to the string.
-
- for chIdx in chennelList:
- ob = nodeObjectList[chIdx[0]]
- chType = chIdx[1]
-
- # Get object rotation
- x, y, z = ob.getEuler()
-
- # Convert the rotation from ZYX order to ZXY order
- x, y, z = ZYXToZXY(x, y, z)
-
-
- # Using regular Locations stuffs upIPO locations stuffs up
- # Get IPO locations instead
- xloc, yloc, zloc = getIpoLocation(ob, frame)
-
- # WARNING non standard Location
- xloc, zloc, yloc = -xloc, yloc, zloc
-
-
- if chType == 0:
- motionData += saneFloat(scale * (xloc))
- if chType == 1:
- motionData += saneFloat(scale * (yloc))
- if chType == 2:
- motionData += saneFloat(scale * (zloc))
- if chType == 3:
- motionData += saneFloat(x)
- if chType == 4:
- motionData += saneFloat(y)
- if chType == 5:
- motionData += saneFloat(z)
-
- motionData += ' '
-
- motionData += '\n'
- return motionData
+def motion2bvh(file, frame, chennelList, nodeObjectList):
+ for chIdx in chennelList:
+ #ob, obipo, obcurves = nodeObjectList[chIdx[0]]
+ ob = nodeObjectList[chIdx[0]]
+ chType = chIdx[1]
+
+ # Get object rotation
+ x, y, z = ob.getEuler()
+
+ # Convert the rotation from ZYX order to ZXY order
+ x, y, z = ZYXToZXY(x, y, z)
+
+ # Location
+ xloc, yloc, zloc = ob.matrixLocal[3][:3]
+
+ # Using regular Locations stuffs upIPO locations stuffs up
+ # Get IPO locations instead
+ #xloc, yloc, zloc, x, y, z = getIpoLocation(ob, obipo, obcurves, frame)
+ # Convert the rotation from ZYX order to ZXY order
+ #x, y, z = ZYXToZXY(x, y, z)
+
+
+ # WARNING non standard Location
+ # xloc, zloc, yloc = -xloc, yloc, zloc
+
+ if chType == 0:
+ file.write('%.6f ' % (scale * xloc))
+ if chType == 1:
+ file.write('%.6f ' % (scale * yloc))
+ if chType == 2:
+ file.write('%.6f ' % (scale * zloc))
+ if chType == 3:
+ file.write('%.6f ' % x)
+ if chType == 4:
+ file.write('%.6f ' % y)
+ if chType == 5:
+ file.write('%.6f ' % z)
+ file.write('\n')
+
def saveBVH(filename):
-
- if filename.find('.bvh', -4) <= 0: filename += '.bvh' # for safety
-
- # Here we store a serialized list of blender objects as they appier
- # in the hierarchy, this is refred to when writing motiondata
- nodeObjectList = []
-
- # In this list we store a 2 values for each node
- # 1) An index pointing to a blender object
- # in objectList
- # 2) The type if channel x/y/z rot:x/y/z - Use 0-5 to indicate this
- chennelList = []
-
- print ''
- print 'BVH 1.0 by Campbell Barton (Ideasman) - ideasman@linuxmail.org'
-
- # Get the active object and recursively traverse its kids to build
- # the BVH hierarchy, then eval the string to make a hierarchy list.
- hierarchy = eval(getHierarchy(Object.GetSelected()[0].getName(),''))[0] # somhow this returns a tuple with one list in it.
-
- # Put all data in the file we have selected file.
- file = open(filename, "w")
- file.write('HIERARCHY\n') # all bvh files have this on the first line
-
- # Write the whole hirarchy to a list
- bvhHierarchy, level, chennelList, nodeObjectList = hierarchy2bvh(hierarchy, '', 0, chennelList, nodeObjectList)
- file.write( bvhHierarchy ) # Rwite the var fileBlock to the output.
- bvhHierarchy = None # Save a tit bit of memory
-
- #====================================================#
- # MOTION: Loop through the frames ande write out #
- # the motion data for each #
- #====================================================#
- # Do some basic motion file header stuff
- file.write('MOTION\n')
- file.write( 'Frames: ' + str(1 + context.endFrame() - context.startFrame()) + '\n' )
- file.write( 'Frame Time: ' + saneFloat(frameRate) + '\n' )
-
- #print 'WARNING- exact frames might be stuffed up- inclusive whatever, do some tests later on.'
- frames = range(context.startFrame(), context.endFrame()+1)
- print 'exporting ' + str(len(frames)) + ' of motion...'
-
- for frame in frames:
- context.currentFrame(frame)
- scn.update(1) # Update locations so we can write the new locations
- #Blender.Window.RedrawAll() # causes crash
-
- file.write( motion2bvh(frame, chennelList, nodeObjectList) )
-
- file.write('\n') # newline
- file.close()
- print 'done'
-
+ t = time()
+ if not filename.lower().endswith('.bvh'):
+ filename += '.bvh' # for safety
+
+ # Here we store a serialized list of blender objects as they appier
+ # in the hierarchy, this is refred to when writing motiondata
+ nodeObjectList = []
+
+ # In this list we store a 2 values for each node
+ # 1) An index pointing to a blender object
+ # in objectList
+ # 2) The type if channel x/y/z rot:x/y/z - Use 0-5 to indicate this
+ chennelList = []
+
+ print '\nBVH 1.1 by Campbell Barton (Ideasman) - cbarton@metavr.com'
+
+ # Get the active object and recursively traverse its kids to build
+ # the BVH hierarchy, then eval the string to make a hierarchy list.
+ hierarchy = eval(getHierarchy(scn.getActiveObject(),''))[0] # somhow this returns a tuple with one list in it.
+
+ # Put all data in the file we have selected file.
+ file = open(filename, "w")
+ file.write('HIERARCHY\n') # all bvh files have this on the first line
+
+ # Write the whole hirarchy to a list
+ level = 0 # Indenting level, start with no indent
+ level = hierarchy2bvh(file, hierarchy, level, chennelList, nodeObjectList)
+
+ #====================================================#
+ # MOTION: Loop through the frames ande write out #
+ # the motion data for each #
+ #====================================================#
+ # Do some basic motion file header stuff
+ file.write( 'MOTION\n' )
+ file.write( 'Frames: %i\n' % ( 1 + context.endFrame() - context.startFrame() ) )
+ file.write( 'Frame Time: %.6f\n' % frameRate )
+
+ frames = range(context.startFrame()+1, context.endFrame()+1)
+ print 'exporting %i of motion...' % len(frames)
+
+ for frame in frames:
+ context.currentFrame(frame)
+ scn.update(1) # Update locations so we can write the new locations. This is the SLOW part.
+ # Blender.Window.RedrawAll() # Debugging.
+
+ motion2bvh(file, frame, chennelList, nodeObjectList) # Write the motion to a file.
+
+ file.write('\n') # newline
+ file.close()
+ print '...Done in %.4f seconds.' % (time()-t)
+
Blender.Window.FileSelector(saveBVH, 'Export BVH')
diff --git a/release/scripts/bvh_import.py b/release/scripts/bvh_import.py
index 17ce01c0cab..05f40f018dc 100644
--- a/release/scripts/bvh_import.py
+++ b/release/scripts/bvh_import.py
@@ -2,14 +2,14 @@
"""
Name: 'Motion Capture (.bvh)...'
-Blender: 236
+Blender: 239
Group: 'Import'
Tip: 'Import a (.bvh) motion capture file'
"""
__author__ = "Campbell Barton"
-__url__ = ("blender", "elysiun", "http://jmsoler.free.fr/util/blenderfile/py/bvh_import.py")
-__version__ = "1.0.2 04/12/28"
+__url__ = ("blender", "elysiun")
+__version__ = "1.0.4 05/12/04"
__bpydoc__ = """\
This script imports BVH motion capture data to Blender.
@@ -21,8 +21,8 @@ Missing:<br>
Known issues:<br>
Notes:<br>
- Jean-Michel Soler improved importer to support Poser 3.01 files;<br>
- Jean-Baptiste Perin wrote a script to create an armature out of the
+ Jean-Michel Soler improved importer to support Poser 3.01 files;<br>
+ Jean-Baptiste Perin wrote a script to create an armature out of the
Empties created by this importer, it's in the Scripts window -> Scripts -> Animation menu.
"""
@@ -30,23 +30,43 @@ Empties created by this importer, it's in the Scripts window -> Scripts -> Anima
#
#===============================================#
+# BVH Import script 1.05 patched by Campbell #
+# Modified to use Mathutils for matrix math, #
+# Fixed possible joint naming bug, #
+# Imports BVH's with bad EOF gracefully #
+# Fixed duplicate joint names, make them unique #
+# Use \r as well as \n for newlines #
+# Added suppot for nodes with 0 motion channels #
+# Rotation IPOs never cross more then 180d #
+# fixes sub frame tweening and time scaling #
+# 5x overall speedup. #
+# 06/12/2005, #
+#===============================================#
+
+#===============================================#
+# BVH Import script 1.04 patched by jms #
+# Small modif for blender 2.40 #
+# 04/12/2005, #
+#===============================================#
+
+#===============================================#
# BVH Import script 1.03 patched by Campbell #
# Small optimizations and scale input #
-# 01/01/2005, #
+# 01/01/2005, #
#===============================================#
#===============================================#
# BVH Import script 1.02 patched by Jm Soler #
-# to the Poser 3.01 bvh file #
-# 28/12/2004, #
+# to the Poser 3.01 bvh file #
+# 28/12/2004, #
#===============================================#
#===============================================#
# BVH Import script 1.0 by Campbell Barton #
# 25/03/2004, euler rotation code taken from #
# Reevan Mckay's BVH import script v1.1 #
-# if you have any questions about this script #
-# email me ideasman@linuxmail.org #
+# if you have any questions about this scrip. #
+# email me cbarton@metavr.com #
#===============================================#
#===============================================#
@@ -57,7 +77,7 @@ Empties created by this importer, it's in the Scripts window -> Scripts -> Anima
#===============================================#
# --------------------------------------------------------------------------
-# BVH Import v0.9 by Campbell Barton (AKA Ideasman)
+# BVH Import v1.05 by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -68,457 +88,410 @@ Empties created by this importer, it's in the Scripts window -> Scripts -> Anima
#
# 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
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
-
-import string
-import math
import Blender
from Blender import Window, Object, Scene, Ipo, Draw
from Blender.Scene import Render
-# # PSYCO IS CRASHING ON MY SYSTEM
-# # Attempt to load psyco, speed things up
-# try:
-# print 'using psyco to speed up BVH importing'
-# import psyco
-# psyco.full()
-#
-# except:
-# print 'psyco is not present on this system'
-
-# Default scale
-scale = 0.01
-
-# Update as we load?
-debug = 0
-
-# Get the current scene.
-scn = Scene.GetCurrent()
-context = scn.getRenderingContext()
-
-# Here we store the Ipo curves in the order they load.
-channelCurves = []
-
-# Object list
-# We need this so we can loop through the objects and edit there IPO's
-# Chenging there rotation to EULER rotation
-objectList = []
-
-def getScale():
- return Draw.PupFloatInput('BVH Scale: ', 0.01, 0.001, 10.0, 0.1, 3)
-
-def MAT(m):
- if len(m) == 3:
- return Blender.Mathutils.Matrix(m[0], m[1], m[2])
- elif len(m) == 4:
- return Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3])
-
-
-
-#===============================================#
-# eulerRotation: converts X, Y, Z rotation #
-# to eular Rotation. This entire function #
-# is copied from Reevan Mckay's BVH script #
-#===============================================#
-# Vars used in eular rotation funtcion
-DEG_TO_RAD = math.pi/180.0
-RAD_TO_DEG = 180.0/math.pi
-PI=3.14159
-
-def eulerRotate(x,y,z):
- #=================================
- def RVMatMult3 (mat1,mat2):
- #=================================
- mat3=[[0.0,0.0,0.0],[0.0,0.0,0.0],[0.0,0.0,0.0]]
- for i in range(3):
- for k in range(3):
- for j in range(3):
- mat3[i][k]=mat3[i][k]+mat1[i][j]*mat2[j][k]
- return mat3
-
-
- #=================================
- def RVAxisAngleToMat3 (rot4):
- # Takes a direction vector and
- # a rotation (in rads) and
- # returns the rotation matrix.
- # Graphics Gems I p. 466:
- #=================================
- mat3=[[0.0,0.0,0.0],[0.0,0.0,0.0],[0.0,0.0,0.0]]
- if math.fabs(rot4[3])>0.01:
- s=math.sin(rot4[3])
- c=math.cos(rot4[3])
- t=1.0-math.cos(rot4[3])
- else:
- s=rot4[3]
- c=1.0
- t=0.0
-
- x=rot4[0]; y=rot4[1]; z=rot4[2]
-
- mat3[0][0]=t*x*x+c
- mat3[0][1]=t*x*y+s*z
- mat3[0][2]=t*x*z-s*y
-
- mat3[1][0]=t*x*y-s*z
- mat3[1][1]=t*y*y+c
- mat3[1][2]=t*y*z+s*x
-
- mat3[2][0]=t*x*z+s*y
- mat3[2][1]=t*y*z-s*x
- mat3[2][2]=t*z*z+c
-
- return mat3
-
- eul = [x,y,z]
-
- for jj in range(3):
- while eul[jj] < 0:
- eul[jj] = eul[jj] + 360.0
- while eul[jj] >= 360.0:
- eul[jj] = eul[jj] - 360.0
-
- eul[0] = eul[0]*DEG_TO_RAD
- eul[1] = eul[1]*DEG_TO_RAD
- eul[2] = eul[2]*DEG_TO_RAD
-
- xmat=RVAxisAngleToMat3([1,0,0,eul[0]])
- ymat=RVAxisAngleToMat3([0,1,0,eul[1]])
- zmat=RVAxisAngleToMat3([0,0,1,eul[2]])
-
- mat=[[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]]
-
- # Standard BVH multiplication order
- mat=RVMatMult3 (zmat,mat)
- mat=RVMatMult3 (xmat,mat)
- mat=RVMatMult3 (ymat,mat)
-
-
- '''
- # Screwy Animation Master BVH multiplcation order
- mat=RVMatMult3 (ymat,mat)
- mat=RVMatMult3 (xmat,mat)
- mat=RVMatMult3 (zmat,mat)
- '''
- mat = MAT(mat)
-
- eul = mat.toEuler()
- x =- eul[0]/-10
- y =- eul[1]/-10
- z =- eul[2]/-10
-
- return x, y, z # Returm euler roration values.
-
-
-
-#===============================================#
-# makeJoint: Here we use the node data #
-# from the BVA file to create an empty #
-#===============================================#
-def makeJoint(name, parent, prefix, offset, channels):
- global scale
- # Make Empty, with the prefix in front of the name
- ob = Object.New('Empty', prefix + name) # New object, ob is shorter and nicer to use.
- scn.link(ob) # place the object in the current scene
-
- # Offset Empty
- ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale)
-
- # Make me a child of another empty.
- # Vale of None will make the empty a root node (no parent)
- if parent[-1] != None:
- obParent = Object.Get(prefix + parent[-1]) # We use this a bit so refrence it here.
- obParent.makeParent([ob], 0, 1) #ojbs, noninverse, 1 = not fast.
-
- # Add Ipo's for necessary channels
- newIpo = Ipo.New('Object', prefix + name)
- ob.setIpo(newIpo)
- for channelType in channels:
- if channelType == 'Xposition':
- newIpo.addCurve('LocX')
- newIpo.getCurve('LocX').setInterpolation('Linear')
- if channelType == 'Yposition':
- newIpo.addCurve('LocY')
- newIpo.getCurve('LocY').setInterpolation('Linear')
- if channelType == 'Zposition':
- newIpo.addCurve('LocZ')
- newIpo.getCurve('LocZ').setInterpolation('Linear')
-
- if channelType == 'Zrotation':
- newIpo.addCurve('RotZ')
- newIpo.getCurve('RotZ').setInterpolation('Linear')
- if channelType == 'Yrotation':
- newIpo.addCurve('RotY')
- newIpo.getCurve('RotY').setInterpolation('Linear')
- if channelType == 'Xrotation':
- newIpo.addCurve('RotX')
- newIpo.getCurve('RotX').setInterpolation('Linear')
-
- # Add to object list
- objectList.append(ob)
-
- # Redraw if debugging
- if debug: Blender.Redraw()
-
-
-#===============================================#
-# makeEnd: Here we make an end node #
-# This is needed when adding the last bone #
-#===============================================#
-def makeEnd(parent, prefix, offset):
- # Make Empty, with the prefix in front of the name, end nodes have no name so call it its parents name+'_end'
- ob = Object.New('Empty', prefix + parent[-1] + '_end') # New object, ob is shorter and nicer to use.
- scn.link(ob)
-
- # Dont check for a parent, an end node MUST have a parent
- obParent = Object.Get(prefix + parent[-1]) # We use this a bit so refrence it here.
- obParent.makeParent([ob], 0, 1) #ojbs, noninverse, 1 = not fast.
-
- # Offset Empty
- ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale)
-
- # Redraw if debugging
- if debug: Blender.Redraw()
-
-
-
-
-#===============================================#
-# MAIN FUNCTION - All things are done from here #
-#===============================================#
-def loadBVH(filename):
- global scale
- print ''
- print 'BVH Importer 1.0 by Campbell Barton (Ideasman) - ideasman@linuxmail.org'
- alpha='abcdefghijklmnopqrstuvewxyz'
- ALPHA=alpha+alpha.upper()
- ALPHA+=' 0123456789+-{}. '
- time1 = Blender.sys.time()
- tmpScale = getScale()
- if tmpScale != None:
- scale = tmpScale
-
- # File loading stuff
- # Open the file for importing
- file = open(filename, 'r')
- fileData = file.readlines()
- # Make a list of lines
- lines = []
- for fileLine in fileData:
- fileLine=fileLine.replace('..','.')
- newLine = string.split(fileLine)
- if newLine != []:
- t=[]
- for n in newLine:
- for n0 in n:
- if n0 not in ALPHA:
- n=n.replace(n0,'')
- t.append(n)
- lines.append(t)
-
-
- del fileData
- # End file loading code
-
- # Call object names with this prefix, mainly for scenes with multiple BVH's - Can imagine most partr names are the same
- # So in future
- #prefix = str(len(lines)) + '_'
-
- prefix = '_'
-
- # Create Hirachy as empties
- if lines[0][0] == 'HIERARCHY':
- print 'Importing the BVH Hierarchy for:', filename
- else:
- return 'ERROR: This is not a BVH file'
-
- # A liniar list of ancestors to keep track of a single objects heratage
- # at any one time, this is appended and removed, dosent store tree- just a liniar list.
- # ZERO is a place holder that means we are a root node. (no parents)
- parent = [None]
-
- #channelList [(<objectName>, [channelType1, channelType2...]), (<objectName>, [channelType1, channelType2...)]
- channelList = []
- channelIndex = -1
-
-
-
- lineIdx = 1 # An index for the file.
- while lineIdx < len(lines) -1:
- #...
- if lines[lineIdx][0] == 'ROOT' or lines[lineIdx][0] == 'JOINT':
- if lines[lineIdx][0] == 'JOINT' and len(lines[lineIdx])>2:
- for j in range(2,len(lines[lineIdx])) :
- lines[lineIdx][1]+='_'+lines[lineIdx][j]
-
- # MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
-
- print len(parent) * ' ' + 'node:',lines[lineIdx][1],' parent:',parent[-1]
- print lineIdx
- name = lines[lineIdx][1]
- print name,lines[lineIdx+1],lines[lineIdx+2]
- lineIdx += 2 # Incriment to the next line (Offset)
- offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
- lineIdx += 1 # Incriment to the next line (Channels)
-
- # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
- # newChannel has Indecies to the motiondata,
- # -1 refers to the last value that will be added on loading at a value of zero
- # We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
- newChannel = [-1, -1, -1, -1, -1, -1]
- for channel in lines[lineIdx][2:]:
- channelIndex += 1 # So the index points to the right channel
- if channel == 'Xposition':
- newChannel[0] = channelIndex
- elif channel == 'Yposition':
- newChannel[1] = channelIndex
- elif channel == 'Zposition':
- newChannel[2] = channelIndex
- elif channel == 'Xrotation':
- newChannel[3] = channelIndex
- elif channel == 'Yrotation':
- newChannel[4] = channelIndex
- elif channel == 'Zrotation':
- newChannel[5] = channelIndex
-
- channelList.append(newChannel)
-
- channels = lines[lineIdx][2:]
-
- # Call funtion that uses the gatrhered data to make an empty.
- makeJoint(name, parent, prefix, offset, channels)
-
- # If we have another child then we can call ourselves a parent, else
- parent.append(name)
-
- # Account for an end node
- if lines[lineIdx][0] == 'End' and lines[lineIdx][1] == 'Site': # There is somtimes a name afetr 'End Site' but we will ignore it.
- lineIdx += 2 # Incriment to the next line (Offset)
- offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
- makeEnd(parent, prefix, offset)
-
- # Just so we can remove the Parents in a uniform way- End end never has kids
- # so this is a placeholder
- parent.append(None)
-
- if lines[lineIdx] == ['}']:
- parent = parent[:-1] # Remove the last item
-
-
- #=============================================#
- # BVH Structure loaded, Now import motion #
- #=============================================#
- if lines[lineIdx] == ['MOTION']:
- print '\nImporting motion data'
- lineIdx += 3 # Set the cursor to the forst frame
-
- #=============================================#
- # Loop through frames, each line a frame #
- #=============================================#
- currentFrame = 1
- print 'frames: ',
-
-
- #=============================================#
- # Add a ZERO keyframe, this keeps the rig #
- # so when we export we know where all the #
- # joints start from #
- #=============================================#
- obIdx = 0
- while obIdx < len(objectList) -1:
- if channelList[obIdx][0] != -1:
- objectList[obIdx].getIpo().getCurve('LocX').addBezier((currentFrame,0))
- if channelList[obIdx][1] != -1:
- objectList[obIdx].getIpo().getCurve('LocY').addBezier((currentFrame,0))
- if channelList[obIdx][2] != -1:
- objectList[obIdx].getIpo().getCurve('LocZ').addBezier((currentFrame,0))
- if channelList[obIdx][3] != '-1' or channelList[obIdx][4] != '-1' or channelList[obIdx][5] != '-1':
- objectList[obIdx].getIpo().getCurve('RotX').addBezier((currentFrame,0))
- objectList[obIdx].getIpo().getCurve('RotY').addBezier((currentFrame,0))
- objectList[obIdx].getIpo().getCurve('RotZ').addBezier((currentFrame,0))
- obIdx += 1
-
- while lineIdx < len(lines):
-
- # Exit loop if we are past the motiondata.
- # Some BVH's have extra tags like 'CONSTRAINTS and MOTIONTAGS'
- # I dont know what they do and I dont care, they'll be ignored here.
- if len(lines[lineIdx]) < len(objectList):
- print '...ending on unknown tags'
- break
-
-
- currentFrame += 1 # Incriment to next frame
-
- #=============================================#
- # Import motion data and assign it to an IPO #
- #=============================================#
- lines[lineIdx].append('0') # Use this as a dummy var for objects that dont have a rotate channel.
- obIdx = 0
- if debug: Blender.Redraw()
- while obIdx < len(objectList) -1:
- if channelList[obIdx][0] != -1:
- VAL0=lines[lineIdx][channelList[obIdx][0]]
- if VAL0.find('.')==-1:
- VAL0=VAL0[:len(VAL0)-6]+'.'+VAL0[-6:]
- objectList[obIdx].getIpo().getCurve('LocX').addBezier((currentFrame, scale * float(VAL0)))
-
- if channelList[obIdx][1] != -1:
- VAL1=lines[lineIdx][channelList[obIdx][1]]
- if VAL1.find('.')==-1:
- VAL1=VAL1[:len(VAL1)-6]+'.'+VAL1[-6:]
- objectList[obIdx].getIpo().getCurve('LocY').addBezier((currentFrame, scale * float(VAL1)))
-
- if channelList[obIdx][2] != -1:
- VAL2=lines[lineIdx][channelList[obIdx][2]]
- if VAL2.find('.')==-1:
- VAL2=VAL2[:len(VAL2)-6]+'.'+VAL2[-6:]
- objectList[obIdx].getIpo().getCurve('LocZ').addBezier((currentFrame, scale * float(VAL2)))
-
- if channelList[obIdx][3] != '-1' or channelList[obIdx][4] != '-1' or channelList[obIdx][5] != '-1':
- VAL3=lines[lineIdx][channelList[obIdx][3]]
- if VAL3.find('.')==-1:
- VAL3=VAL3[:len(VAL3)-6]+'.'+VAL3[-6:]
-
- VAL4=lines[lineIdx][channelList[obIdx][4]]
- if VAL4.find('.')==-1:
- VAL4=VAL4[:len(VAL4)-6]+'.'+VAL4[-6:]
-
- VAL5=lines[lineIdx][channelList[obIdx][5]]
- if VAL5.find('.')==-1:
- VAL5=VAL5[:len(VAL5)-6]+'.'+VAL5[-6:]
-
- x, y, z = eulerRotate(float(VAL3), float(VAL4), float(VAL5))
-
- objectList[obIdx].getIpo().getCurve('RotX').addBezier((currentFrame, x))
- objectList[obIdx].getIpo().getCurve('RotY').addBezier((currentFrame, y))
- objectList[obIdx].getIpo().getCurve('RotZ').addBezier((currentFrame, z))
-
- obIdx += 1
- # Done importing motion data #
-
- # lines[lineIdx] = None # Scrap old motion data, save some memory?
- lineIdx += 1
- # We have finished now
- print currentFrame, 'done.'
-
- # No point in looking further, when this loop is done
- # There is nothine else left to do
- print 'Imported ', currentFrame, ' frames'
- break
-
- # Main file loop
- lineIdx += 1
- print "bvh import time: ", Blender.sys.time() - time1
-
-Blender.Window.FileSelector(loadBVH, "Import BVH")
+# Attempt to load psyco, speed things up
+try:
+ import psyco
+ psyco.full()
+ print 'using psyco to speed up BVH importing'
+except:
+ #print 'psyco is not present on this system'
+ pass
+
+
+
+def main():
+ global scale
+ scale = None
+
+ # Update as we load?
+ debug = 0
+
+ def getScale():
+ return Draw.PupFloatInput('BVH Scale: ', 0.01, 0.001, 10.0, 0.1, 3)
+
+
+ #===============================================#
+ # MAIN FUNCTION - All things are done from here #
+ #===============================================#
+ def loadBVH(filename):
+ global scale
+ print '\nBVH Importer 1.05 by Campbell Barton (Ideasman) - cbarton@metavr.com'
+
+ objectCurveMapping = {}
+ objectNameMapping = {}
+ objectMotiondataMapping = {}
+
+ # Here we store the Ipo curves in the order they load.
+ channelCurves = []
+
+ # Object list
+ # We need this so we can loop through the objects and edit there IPO's
+ # Chenging there rotation to EULER rotation
+ objectList = []
+
+ if scale == None:
+ tempscale = getScale()
+ if tempscale:
+ scale = tempscale
+ else:
+ scale = 0.01
+
+ Window.WaitCursor(1)
+ # Unique names, dont reuse any of these names.
+ uniqueObNames = [ob.name for ob in Object.Get()]
+
+
+ # FUNCTIONS ====================================#
+ def getUniqueObName(name):
+ i = 0
+ newname = name[:min(len(name), 12)] # Concatinate to 12 chars
+ while newname in uniqueObNames:
+ newname = name + str(i)
+ i+=1
+ return newname
+
+ # Change the order rotation is applied.
+ RotationMatrix = Blender.Mathutils.RotationMatrix
+ MATRIX_IDENTITY_3x3 = Blender.Mathutils.Matrix([1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0])
+ def eulerRotate(x,y,z):
+ x,y,z = x%360,y%360,z%360 # Clamp all values between 0 and 360, values outside this raise an error.
+ xmat = RotationMatrix(x,3,'x')
+ ymat = RotationMatrix(y,3,'y')
+ zmat = RotationMatrix(z,3,'z')
+ # Standard BVH multiplication order, apply the rotation in the order Z,X,Y
+ return (ymat*(xmat * (zmat * MATRIX_IDENTITY_3x3))).toEuler()
+
+
+ currentFrame = 1 # Set the initial frame to import all data to.
+
+ #===============================================#
+ # makeJoint: Here we use the node data #
+ # from the BVA file to create an empty #
+ #===============================================#
+ BVH2BLEND_TX_NAME = {'Xposition':'LocX','Yposition':'LocY','Zposition':'LocZ','Xrotation':'RotX','Yrotation':'RotY','Zrotation':'RotZ'}
+ def makeJoint(name, parent, offset, channels):
+ ob = Object.New('Empty', name) # New object, ob is shorter and nicer to use.
+
+ objectNameMapping[name] = ob
+ scn.link(ob) # place the object in the current scene
+ ob.sel = 1
+
+ # Make me a child of another empty.
+ # Vale of None will make the empty a root node (no parent)
+ if parent[-1]: # != None
+ obParent = objectNameMapping[parent[-1]] # We use this a bit so refrence it here.
+ obParent.makeParent([ob], 1, 0) #ojbs, noninverse, 1 = not fast.
+
+ # Offset Empty from BVH's initial joint location.
+ ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale)
+
+ # Add Ipo's for necessary channels
+ newIpo = Ipo.New('Object', name)
+ ob.setIpo(newIpo)
+ obname = ob.name
+ for channelType in channels:
+ channelType = BVH2BLEND_TX_NAME[channelType]
+ curve = newIpo.addCurve(channelType)
+ curve.setInterpolation('Linear')
+ objectCurveMapping[(obname, channelType)] = curve
+
+ # Add to object list
+ objectList.append(ob)
+
+ # Redraw if debugging
+ if debug: Blender.Redraw()
+
+
+ #===============================================#
+ # makeEnd: Here we make an end node #
+ # This is needed when adding the last bone #
+ #===============================================#
+ def makeEnd(parent, offset):
+ new_name = parent[-1] + '_end'
+ ob = Object.New('Empty', new_name) # New object, ob is shorter and nicer to use.
+ objectNameMapping[new_name] = ob
+ scn.link(ob)
+ ob.sel = 1
+
+ # Dont check for a parent, an end node MUST have a parent
+ obParent = objectNameMapping[parent[-1]] # We use this a bit so refrence it here.
+ obParent.makeParent([ob], 1, 0) #ojbs, noninverse, 1 = not fast.
+
+ # Offset Empty
+ ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale)
+
+ # Redraw if debugging
+ if debug: Blender.Redraw()
+ # END FUNCTION DEFINITIONS ====================================#
+
+
+
+
+ time1 = Blender.sys.time()
+
+ # Get the current scene.
+ scn = Scene.GetCurrent()
+ #context = scn.getRenderingContext()
+
+ # DeSelect All
+ for ob in scn.getChildren():
+ ob.sel = 0
+
+ # File loading stuff
+ # Open the file for importing
+ file = open(filename, 'r')
+
+ # Seperate into a list of lists, each line a list of words.
+ lines = file.readlines()
+ # Non standard carrage returns?
+ if len(lines) == 1:
+ lines = lines[0].split('\r')
+
+ # Split by whitespace.
+ lines =[ll for ll in [ [w for w in l.split() if w != '\n' ] for l in lines] if ll]
+ # End file loading code
+
+
+
+ # Create Hirachy as empties
+ if lines[0][0] == 'HIERARCHY':
+ print 'Importing the BVH Hierarchy for:', filename
+ else:
+ return 'ERROR: This is not a BVH file'
+
+ # A liniar list of ancestors to keep track of a single objects heratage
+ # at any one time, this is appended and removed, dosent store tree- just a liniar list.
+ # ZERO is a place holder that means we are a root node. (no parents)
+ parent = [None]
+
+ #channelList, sync with objectList: [[channelType1, channelType2...], [channelType1, channelType2...)]
+ channelList = []
+ channelIndex = -1
+
+ lineIdx = 0 # An index for the file.
+ while lineIdx < len(lines) -1:
+ #...
+ if lines[lineIdx][0] == 'ROOT' or lines[lineIdx][0] == 'JOINT':
+
+ # Join spaces into 1 word with underscores joining it.
+ if len(lines[lineIdx]) > 2:
+ lines[lineIdx][1] = '_'.join(lines[lineIdx][1:])
+ lines[lineIdx] = lines[lineIdx][:2]
+
+ # MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
+
+ # Make sure the names are unique- Object names will match joint names exactly and both will be unique.
+ name = getUniqueObName(lines[lineIdx][1])
+ uniqueObNames.append(name)
+
+ print '%snode: %s, parent: %s' % (len(parent) * ' ', name, parent[-1])
+
+ lineIdx += 2 # Incriment to the next line (Offset)
+ offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
+ lineIdx += 1 # Incriment to the next line (Channels)
+
+ # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
+ # newChannel references indecies to the motiondata,
+ # if not assigned then -1 refers to the last value that will be added on loading at a value of zero, this is appended
+ # We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
+ newChannel = [-1, -1, -1, -1, -1, -1]
+ for channel in lines[lineIdx][2:]:
+ channelIndex += 1 # So the index points to the right channel
+ if channel == 'Xposition':
+ newChannel[0] = channelIndex
+ elif channel == 'Yposition':
+ newChannel[1] = channelIndex
+ elif channel == 'Zposition':
+ newChannel[2] = channelIndex
+ elif channel == 'Xrotation':
+ newChannel[3] = channelIndex
+ elif channel == 'Yrotation':
+ newChannel[4] = channelIndex
+ elif channel == 'Zrotation':
+ newChannel[5] = channelIndex
+
+ channelList.append(newChannel)
+
+ channels = lines[lineIdx][2:]
+
+ # Call funtion that uses the gatrhered data to make an empty.
+ makeJoint(name, parent, offset, channels)
+
+ # If we have another child then we can call ourselves a parent, else
+ parent.append(name)
+
+ # Account for an end node
+ if lines[lineIdx][0] == 'End' and lines[lineIdx][1] == 'Site': # There is somtimes a name after 'End Site' but we will ignore it.
+ lineIdx += 2 # Incriment to the next line (Offset)
+ offset = ( float(lines[lineIdx][1]), float(lines[lineIdx][2]), float(lines[lineIdx][3]) )
+ makeEnd(parent, offset)
+
+ # Just so we can remove the Parents in a uniform way- End end never has kids
+ # so this is a placeholder
+ parent.append(None)
+
+ if len(lines[lineIdx]) == 1 and lines[lineIdx][0] == '}': # == ['}']
+ parent.pop() # Remove the last item
+
+ #=============================================#
+ # BVH Structure loaded, Now import motion #
+ #=============================================#
+ if len(lines[lineIdx]) == 1 and lines[lineIdx][0] == 'MOTION':
+ print '\nImporting motion data'
+ lineIdx += 3 # Set the cursor to the first frame
+
+ #=============================================#
+ # Add a ZERO keyframe, this keeps the rig #
+ # so when we export we know where all the #
+ # joints start from #
+ #=============================================#
+
+ for obIdx, ob in enumerate(objectList):
+ obname = ob.name
+ if channelList[obIdx][0] != -1:
+ objectCurveMapping[obname, 'LocX'].addBezier((currentFrame,0))
+ objectMotiondataMapping[obname, 'LocX'] = []
+ if channelList[obIdx][1] != -1:
+ objectCurveMapping[obname, 'LocY'].addBezier((currentFrame,0))
+ objectMotiondataMapping[obname, 'LocY'] = []
+ if channelList[obIdx][2] != -1:
+ objectCurveMapping[obname, 'LocZ'].addBezier((currentFrame,0))
+ objectMotiondataMapping[obname, 'LocZ'] = []
+ if\
+ channelList[obIdx][3] != -1 or\
+ channelList[obIdx][4] != -1 or\
+ channelList[obIdx][5] != -1:
+ objectMotiondataMapping[obname, 'RotX'] = []
+ objectMotiondataMapping[obname, 'RotY'] = []
+ objectMotiondataMapping[obname, 'RotZ'] = []
+
+ #=============================================#
+ # Loop through frames, each line a frame #
+ #=============================================#
+ MOTION_DATA_LINE_LEN = len(lines[lineIdx])
+ while lineIdx < len(lines):
+ line = lines[lineIdx]
+ if MOTION_DATA_LINE_LEN != len(line):
+ print 'ERROR: Incomplete motion data on line %i, finishing import.' % lineIdx
+ break
+
+ # Exit loop if we are past the motiondata.
+ # Some BVH's have extra tags like 'CONSTRAINTS and MOTIONTAGS'
+ # I dont know what they do and I dont care, they'll be ignored here.
+ if len(line) < len(objectList):
+ print '...ending on unknown tags'
+ break
+
+
+ currentFrame += 1 # Incriment to next frame
+
+ #=============================================#
+ # Import motion data and assign it to an IPO #
+ #=============================================#
+ line.append(0.0) # Use this as a dummy var for objects that dont have a loc/rotate channel.
+
+ if debug: Blender.Redraw()
+ for obIdx, ob in enumerate(objectList):
+ obname = ob.name
+ obChannel = channelList[obIdx]
+ if channelList[obIdx][0] != -1:
+ objectMotiondataMapping[obname, 'LocX'].append((currentFrame, scale * float( line[obChannel[0]] )))
+
+ if channelList[obIdx][1] != -1:
+ objectMotiondataMapping[obname, 'LocY'].append((currentFrame, scale * float( line[obChannel[1]] )))
+
+ if channelList[obIdx][2] != -1:
+ objectMotiondataMapping[obname, 'LocZ'].append((currentFrame, scale * float( line[obChannel[2]] )))
+
+ if obChannel[3] != -1 or obChannel[4] != -1 or obChannel[5] != -1:
+ x, y, z = eulerRotate(float( line[obChannel[3]] ), float( line[obChannel[4]] ), float( line[obChannel[5]] ))
+ x,y,z = x/10.0, y/10.0, z/10.0 # For IPO's 36 is 360d
+ motionMappingRotX = objectMotiondataMapping[obname, 'RotX']
+ motionMappingRotY = objectMotiondataMapping[obname, 'RotY']
+ motionMappingRotZ = objectMotiondataMapping[obname, 'RotZ']
+
+ # Make interpolation not cross between 180d, thjis fixes sub frame interpolation and time scaling.
+ # Will go from (355d to 365d) rather then to (355d to 5d) - inbetween these 2 there will now be a correct interpolation.
+ if len(motionMappingRotX) > 1:
+ while (motionMappingRotX[-1][1] - x) > 18: x+=36
+ while (motionMappingRotX[-1][1] - x) < -18: x-=36
+
+ while (motionMappingRotY[-1][1] - y) > 18: y+=36
+ while (motionMappingRotY[-1][1] - y) < -18: y-=36
+
+ while (motionMappingRotZ[-1][1] - z) > 18: z+=36
+ while (motionMappingRotZ[-1][1] - z) < -18: z-=36
+
+ motionMappingRotX.append((currentFrame, x))
+ motionMappingRotY.append((currentFrame, y))
+ motionMappingRotZ.append((currentFrame, z))
+ # Done importing motion data #
+
+ lineIdx += 1
+
+ #=======================================#
+ # Now Write the motion to the IPO's #
+ #=======================================#
+ for key, motion_data in objectMotiondataMapping.iteritems():
+
+ # Strip the motion data where all the points have the same falue.
+ i = len(motion_data) -2
+ while i > 0 and len(motion_data) > 2:
+ if motion_data[i][1] == motion_data[i-1][1] == motion_data[i+1][1]:
+ motion_data.pop(i)
+ i-=1
+ # Done stripping.
+
+ obname, tx_type = key
+ curve = objectCurveMapping[obname, tx_type]
+ for point_data in motion_data:
+ curve.addBezier( point_data )
+ # Imported motion to an IPO
+
+ # No point in looking further, when this loop is done
+ # There is nothine else left to do
+ break
+
+ # Main file loop
+ lineIdx += 1
+
+ print 'bvh import time for %i frames: %.6f' % (currentFrame, Blender.sys.time() - time1)
+ Window.RedrawAll()
+ Window.WaitCursor(0)
+
+ Blender.Window.FileSelector(loadBVH, "Import BVH")
+
+ #=============#
+ # TESTING #
+ #=============#
+ '''
+ #loadBVH('/metavr/mocap/bvh/boxer.bvh')
+ #loadBVH('/metavr/mocap/bvh/dg-306-g.bvh') # Incompleate EOF
+ #loadBVH('/metavr/mocap/bvh/wa8lk.bvh') # duplicate joint names, \r line endings.
+ #loadBVH('/metavr/mocap/bvh/walk4.bvh') # 0 channels
+ scale = 0.01
+ import os
+ DIR = '/metavr/mocap/bvh/'
+ for f in os.listdir(DIR):
+ if f.endswith('.bvh'):
+ s = Scene.New(f)
+ s.makeCurrent()
+ loadBVH(DIR + f)
+ '''
+if __name__ == '__main__':
+ main() \ No newline at end of file
diff --git a/release/scripts/console.py b/release/scripts/console.py
index 4ce58e06e10..c5d2eb5568e 100644
--- a/release/scripts/console.py
+++ b/release/scripts/console.py
@@ -29,6 +29,26 @@ Usage:<br>
__author__ = "Campbell Barton AKA Ideasman"
__url__ = ["http://members.iinet.net.au/~cpbarton/ideasman/", "blender", "elysiun"]
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
import Blender
from Blender import *
import sys as python_sys
@@ -132,7 +152,7 @@ def unzip(list):
this function will fail
"""
- if len(list) == 0: return ()
+ if not list: return ()
l = []
for t in range(len(list[0])):
l.append(map( lambda x,t=t: x[t], list ))
@@ -213,7 +233,7 @@ def rdir(dirString, depth=0):
# Dont bother with this data.
continue
- if type(dirItem) != type('str'):
+ if type(dirItem) != types.StringType:
print dirItem, type(dirItem)
if dirItem not in COLLECTED_VAR_NAMES.keys():
@@ -229,17 +249,17 @@ def rdir(dirString, depth=0):
#print type(dirItem)
#if type(dirData) == types.ClassType or \
# type(dirData) == types.ModuleType:
-
- if type(dirData) != types.StringType and\
- type(dirData) != types.DictType and\
- type(dirData) != types.DictionaryType and\
- type(dirData) != types.FloatType and\
- type(dirData) != types.IntType and\
- type(dirData) != types.NoneType and\
- type(dirData) != types.StringTypes and\
- type(dirData) != types.TypeType and\
- type(dirData) != types.TupleType and\
- type(dirData) != types.BuiltinFunctionType:
+ type_dirData = type(dirData)
+ if type_dirData != types.StringType and\
+ type_dirData != types.DictType and\
+ type_dirData != types.DictionaryType and\
+ type_dirData != types.FloatType and\
+ type_dirData != types.IntType and\
+ type_dirData != types.NoneType and\
+ type_dirData != types.StringTypes and\
+ type_dirData != types.TypeType and\
+ type_dirData != types.TupleType and\
+ type_dirData != types.BuiltinFunctionType:
# print type(dirData), dirItem
# Dont loop up dirs for strings ints etc.
if dirItem not in dirStringSplit:
@@ -519,16 +539,17 @@ def handle_event(evt, val):
menuList.sort()
choice = PupMenuLess( # Menu for the user to choose the autocompleate
- 'Choices (Shift for Whole name, Ctrl for Docs)%t|' + # Title Text
+ 'Choices (Shift for local name, Ctrl for Docs)%t|' + # Title Text
'|'.join(['%s, %s' % m for m in menuList])) # Use Absolute names m[0]
if choice != -1:
if Window.GetKeyQualifiers() & Window.Qual.CTRL: # Help
cmdBuffer[-1].cmd = ('help(%s%s) ' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0]))
elif Window.GetKeyQualifiers() & Window.Qual.SHIFT: # Put in the long name
- cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0], cmdBuffer[-1].cmd[cursor:]))
- else: # Only paste in the Short name
cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][1], cmdBuffer[-1].cmd[cursor:]))
+ else: # Only paste in the Short name
+ cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0], cmdBuffer[-1].cmd[cursor:]))
+
else:
# print 'NO EDITVAR'
@@ -539,11 +560,8 @@ def handle_event(evt, val):
# Quit from menu only
#if (evt == Draw.ESCKEY and not val):
# Draw.Exit()
- if evt == Draw.MOUSEX: # AVOID TOO MANY REDRAWS.
- return
- elif evt == Draw.MOUSEY:
- return
-
+ if evt == Draw.MOUSEX or evt == Draw.MOUSEY: # AVOID TOO MANY REDRAWS.
+ return
global cursor
@@ -805,4 +823,4 @@ cmdBuffer.append(cmdLine(' ', 0, 0))
def main():
Draw.Register(draw_gui, handle_event, handle_button_event)
-main()
+main() \ No newline at end of file
diff --git a/release/scripts/hotkeys.py b/release/scripts/hotkeys.py
index d56951959c3..843664edb05 100644
--- a/release/scripts/hotkeys.py
+++ b/release/scripts/hotkeys.py
@@ -11,7 +11,7 @@ __author__ = "Jean-Michel Soler (jms)"
__url__ = ("blender", "elysiun",
"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm",
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
-__version__ = "10/04/2005"
+__version__ = "12/18/2005"
__bpydoc__ = """\
This script is a reference about all hotkeys and mouse actions in Blender.
@@ -26,10 +26,9 @@ Notes:<br>
"""
-# $Id$
#------------------------
# Hotkeys script
-# jm soler (2003-->10/2004)
+# jm soler (2003-->12/2005)
# -----------------------
# Page officielle :
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm
@@ -75,16 +74,17 @@ hotkeys={
['Ctrl-,', 'Set Median Point rotation scaling pivot'],
['.', 'Set 3D cursor as rotation scaling pivot'],
['Ctrl-.', 'Set Individual Object Centers as rotation scaling pivot'],
-['~', 'Display all layers (German keys: ö)'],
-['Shift-~', 'Display all/previous layers (German keys: Shift-ö)'],
+['~', 'Display all layers (German keys: ö,french keyboard: ù)'],
+['Shift-~', 'Display all/previous layers (German keys: Shift-ö, french keyboard: shift-ù)'],
['Space', 'Popup menu'],
['Space', '3D View: camera selected + fly mode, accept'],
+['Ctrl-Space', 'Manipulator (transform widget) Menu'],
['TAB', 'Enter/exit Edit Mode'],
['TAB', 'Edit Mode and Numerical Edit (see N key) : move to next input value'],
['TAB', 'Sequencer: Edit meta strip'],
['TAB', 'IPO: Edit selected'],
-['Ctrl-TAB', 'Enter/exit Pose Mode'],
-['Shift-TAB', 'Enter Object Mode'],
+['Ctrl-TAB', 'ARMATURE : Enter/exit Pose Mode'],
+['Shift-TAB', 'EDIT MODE : Enter Object Mode'],
['Ctrl-Open menu /', ''],
['Ctrl-Load Image', 'Opens a thumbnail browser instead of file browser for images']
],
@@ -97,20 +97,25 @@ hotkeys={
['LMB hold down', 'Popup menu'],
['LMB hold down drag', 'Gesture'],
['Ctrl-LMB', 'IPO: Add key'],
+['Ctrl-LMB', '3D View: OBJECT or EDIT mode, select with the Lasso tool'],
+['Ctrl-LMB', '3D View: ARMATURE EDIT mode, add a new bone to the selected end '],
+['Shift-LMB','MANIPULATOR (transform widget): select the axe to remove in the current transformation ( if there is a problem with small step adjustment, first select the axe or axes with LBM alone)'],
['MMB', 'Rotate'],
['Ctrl-MMB', 'Zoom view'],
['Shift-MMB', 'Move view'],
['RMB', 'Select'],
['RMB drag', 'Border select circle: subtract from selection'],
['RMB hold down', 'Popup menu'],
-['Alt+Ctrl-RMB', 'Edit Mode: Select edge'],
+['Alt-RMB', 'Object Mode :Select but in a displayed list of objects located under the mouse cursor'],
+['Alt-RMB', 'Edit Mode: Select EDGES LOOP '],
+['Alt+Ctrl-RMB', 'Edit Mode: Select FACES LOOP'],
['Alt+Ctrl-RMB', 'UV Image Editor: Select face'],
['Shift-RMB', 'Add/subtract to/from selection'],
['Wheel', 'Zoom view'],
['Transformations:', ''],
['Drag+Ctrl', 'Step adjustment'],
-['Drag+Ctrl+Shift', 'Small step adjustment'],
-['Drag+Shift', 'Fine adjustment'],
+['Drag+Ctrl+Shift', 'Small step adjustment (Transform Widget : first select the axe or axes with LBM alone)'],
+['Drag+Shift', 'Fine adjustment (Transform Widget : first select the axe or axes with LBM alone)'],
['LMB', 'Confirm transformation'],
['MMB', 'Toggle optional transform feature'],
['RMB', 'Abort transformation']
@@ -118,33 +123,36 @@ hotkeys={
'F-Keys ':[
['F1', 'Open File'],
+['Shift-F1', 'Library Data Select'],
['F2', 'Save File'],
+['Shift-F2', 'Export DXF'],
+['Ctrl-F2', 'Save/export in vrml 1.0 format' ],
['F3', 'Save image'],
+['Ctrl-F3', 'Save image : dump 3d view'],
+['Ctrl-Shift-F3', 'Save image : dump screen'],
['F4', 'Logic Window (may change)'],
-['F5', 'Material Window'],
-['F6', 'Texture Window'],
-['F7', 'Object Window'],
-['F8', 'World Window'],
-['F9', 'Edit Mode Window'],
-['F10', 'Render Window'],
-['F11', 'Recall the last rendered image'],
-['F12', 'Render current Scene'],
-['Ctrl-Shift-F12', 'NLA Editor'],
-['Shift-F1', 'Library Data Select'],
-['Shift-F2', 'Export DXF'],
['Shift-F4', 'Object manager Data Select '],
+['F5', 'Material Window'],
['Shift-F5', '3D Window'],
+['F6', 'Texture Window'],
['Shift-F6', 'IPO Window'],
+['F7', 'Object Window'],
['Shift-F7', 'Buttons Window'],
+['F8', 'World Window'],
['Shift-F8', 'Video Sequencer Window'],
+['F9', 'Edit Mode Window'],
['Shift-F9', 'OOP Window'],
['Alt-Shift-F9', 'OutLiner Window'],
+['F10', 'Render Window'],
['Shift-F10', 'UV Image Editor'],
+['F11', 'Recall the last rendered image'],
['Shift-F11', 'Text Editor'],
+['ctrl-F11', 'replay the last rendered animation'],
+['F12', 'Render current Scene'],
+['Ctrl-F12', 'Render animation'],
+['Ctrl-Shift-F12', 'NLA Editor'],
['Shift-F12', 'Action Editor'],
-['Ctrl-F2', 'Save/export in vrml 1.0 format' ],
-['Ctrl-F3', 'Save image : dump 3d view'],
-['Ctrl-Shift-F3', 'Save image : dump screen']
+['Shift-F12', 'Action Editor']
],
'Numbers ':[
@@ -152,7 +160,10 @@ hotkeys={
['1..2..0-=', 'Edit Mode with Size, Grab, rotate tools : enter value'],
['Alt-1..2..0', 'Show layer 11..12..20'],
['Shift-1..2..0-=', 'Toggle layer 1..2..12'],
-['Shift-ALT-...', 'Toggle layer 11..12..20']
+['Shift-ALT-...', 'Toggle layer 11..12..20'],
+['Crtl-Shift-ALT-3', 'Edit Mode & Face Mode : Triangle faces'],
+['Crtl-Shift-ALT-4', 'Edit Mode & Face Mode : Quad faces'],
+['Crtl-Shift-ALT-5', 'Edit Mode & Face Mode : Non quad or triangle faces'],
],
'Numpad ':[
@@ -167,9 +178,10 @@ hotkeys={
['Numpad +', 'In OutLiner window, Expand one level of the hierarchy'],
['Alt-Numpad -', 'Proportional vertex Edit Mode: Decrease range of influence'],
['Ctrl-Numpad +', 'Edit Mode: Select Less vertices'],
-['Numpad INS', 'Set Camera view'],
-['Ctrl-Numpad INS', 'Set active object as camera'],
-['Alt-Numbad INS', 'Restore old camera'],
+['Numpad 0', 'Set Camera view'],
+['Ctrl-Numpad 0', 'Set active object as camera'],
+['Alt-Numbad 0', 'Restore old camera'],
+['Ctrl-Alt-Numpad 0', 'Align active camera to view'],
['Numpad 1', 'Front view'],
['Ctrl-Numpad 1', 'Back view'],
['Numpad 3', 'Right view'],
@@ -179,7 +191,9 @@ hotkeys={
['Numpad 5', 'Toggle orthogonal/perspective view'],
['Numpad 9', 'Redraw view'],
['Numpad 4', 'Rotate view left'],
+['ctrl-Shift-Numpad 4', 'Previous Screen'],
['Numpad 6', 'Rotate view right'],
+['ctrl-Shift-Numpad 6', 'Next Screen'],
['Numpad 8', 'Rotate view up'],
['Numpad 2', 'Rotate view down']
],
@@ -207,6 +221,7 @@ hotkeys={
['Alt-Up', 'Blender in Fullscreen mode'],
['Ctrl-Left', 'Previous screen'],
['Ctrl-Right', 'Next screen'],
+['Ctrl-Alt-C', 'Object Mode : Add Constraint'],
['Ctrl-Down', 'Maximize window toggle'],
['Ctrl-Up', 'Maximize window toggle'],
['Shift-Arrow', 'Toggle first frame/ last frame']
@@ -268,6 +283,12 @@ hotkeys={
['EZ', 'Edit Mode: Extrude along Z axis'],
['Alt-E', 'Edit Mode: exit Edit Mode'],
['Ctrl-E', 'Edit Mode: Edge Specials menu'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Mark seams'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Clear seams'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Rotate Edge CW'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Rotate Edge CCW'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Loop Cut'],
+['Ctrl-E', 'Edit Mode: Edge Specials menu, Edge Slide'],
['Shift-E', 'Edit Mode: SubSurf Edge Sharpness']
],
@@ -287,6 +308,7 @@ hotkeys={
['Alt-G', 'Clear location'],
['Shift-ALT-G', 'Remove selected objects from group'],
['Ctrl-G', 'Add selected objects to group'],
+['Ctrl-Alt-G', 'MANIPULATOR (transform widget): set in Grab Mode'],
['Shift-G', 'Selected Group menu']
],
@@ -295,11 +317,11 @@ hotkeys={
['H', 'Curves: Set handle type'],
['H', 'Action editor: Handle type aligned'],
['H', 'Action editor: Handle type free'],
-['Alt-H', 'Show Hidden vertices/faces'],
+['Alt-H', 'Edit Mode : Show Hidden vertices/faces'],
['Shift-H', 'Curves: Automatic handle calculation'],
['Shift-H', 'Action editor: Handle type auto'],
-['Shift-H', 'Edit Mode, Hide deselected vertices/faces'],
-['Ctrl-H', 'Edit Mode, Add a hook on selected points or show the hook menu .']
+['Shift-H', 'Edit Mode : Hide deselected vertices/faces'],
+['Ctrl-H', 'Edit Mode : Add a hook on selected points or show the hook menu .']
],
"I":[
@@ -329,7 +351,7 @@ hotkeys={
"L":[
['L', 'Make local menu'],
-['L', 'Edit mode: Select linked vertices (near mouse pointer)'],
+['L', 'Edit Mode: Select linked vertices (near mouse pointer)'],
['L', 'OOPS window: Select linked objects'],
['L', 'UV Face Select: Select linked faces'],
['Ctrl-L', 'Make links menu (for instance : to scene...)'],
@@ -353,7 +375,7 @@ hotkeys={
['N', 'OOPS window: Rename object/linked objects'] ,
['Ctrl-N', 'Armature: Recalculate bone roll angles'] ,
['Ctrl-N', 'Edit Mode: Recalculate normals to outside'] ,
-['Ctrl-ALT-N', 'Edit Mode: Recalculate normals to inside'] ],
+['Ctrl-Shift-N', 'Edit Mode: Recalculate normals to inside'] ],
"O":[
['O', 'Edit Mode/UV Image Editor: Toggle proportional vertex editing'],
@@ -365,6 +387,7 @@ hotkeys={
"P":[
['P', 'Object Mode: Start realtime engine'],
['P', 'Edit mode: Seperate vertices to new object'],
+['shift-P', 'Edit mode: Push-Pull'],
['P', 'UV Image Editor: Pin UVs'],
['Alt-P', 'Clear parent relationship'],
['Alt-P', 'UV Image Editor: Unpin UVs'],
@@ -387,6 +410,7 @@ hotkeys={
['RZZ', "Rotate around object's local Z axis"],
['Alt-R', 'Clear object rotation'],
['Ctrl-R', 'Edit Mode: Knife, cut selected edges, accept left mouse/ cancel right mouse'],
+['Ctrl-Alt-R', 'MANIPULATOR (transform widget): set in Rotate Mode'],
['Shift-R', 'Edit Mode: select Face Loop'],
['Shift-R', 'Nurbs: Select row'] ],
@@ -400,8 +424,11 @@ hotkeys={
['SYY', 'Flip around Y axis and show axis'] ,
['SZZ', 'Flip around Z axis and show axis'] ,
['Alt-S', 'Edit mode: Shrink/fatten (Scale along vertex normals)'] ,
+['Ctrl-Shift-S', 'Edit mode: To Sphere'] ,
+['Ctrl-Alt-Shift-S', 'Edit mode: Shear'] ,
['Alt-S', 'Clear object size'] ,
['Ctrl-S', 'Edit mode: Shear'] ,
+['Ctrl-Alt-G', 'MANIPULATOR (transform widget): set in Size Mode'],
['Shift-S', 'Cursor/Grid snap menu'] ],
"T":[
@@ -418,18 +445,18 @@ hotkeys={
"U":[
['U', 'Make single user menu (for import completly linked object to another scene for instance) '] ,
['U', '3D View: Make Single user Menu'] ,
-['U', 'Edit Mode: Reload object data from before entering Edit Mode'] ,
['U', 'UV Face Select: Automatic UV calculation menu'] ,
['U', 'Vertex-/Weightpaint mode: Undo'] ,
['Ctrl-U', 'Save current state as user default'],
['Shift-U', 'Edit Mode: Redo Menu'],
-['Alt-U', 'Edit Mode: Undo Menu'] ],
+['Alt-U', 'Edit Mode & Object Mode: Undo Menu']],
"V":[
['V', 'Curves/Nurbs: Vector handle'],
+['V', 'Edit Mode : Rip selected vertices'],
['V', 'Vertexpaint mode'],
['V', 'UV Image Editor: Stitch UVs'],
-['V', 'Action editor: Vector'],
+['V', 'Action editor: Vector'],
['Alt-V', "Scale object to match image texture's aspect ratio"],
['Shift-V', 'Edit mode: Align view to selected vertices'],
['Shift-V', 'UV Image Editor: Limited Stitch UVs popup'],
@@ -437,13 +464,37 @@ hotkeys={
],
"W":[
-['W', 'Object Mode: Boolean operations menu'],
-['W', 'Edit mode: Specials menu'],
+['W', 'Edit Mode: Specials menu'],
+['W', 'Edit Mode: Specials menu, ARMATURE 1 Subdivide'],
+['W', 'Edit Mode: Specials menu, ARMATURE 2 Flip Left-Right Name'],
+['W', 'Edit Mode: Specials menu, CURVE 1 Subdivide'],
+['W', 'Edit Mode: Specials menu, CURVE 2 Swich Direction'],
+['W', 'Edit Mode: Specials menu, MESH 1 Subdivide'],
+['W', 'Edit Mode: Specials menu, MESH 2 Subdivide Multi'],
+['W', 'Edit Mode: Specials menu, MESH 3 Subdivide Multi Fractal'],
+['W', 'Edit Mode: Specials menu, MESH 4 Subdivide Smooth'],
+['W', 'Edit Mode: Specials menu, MESH 5 Merge'],
+['W', 'Edit Mode: Specials menu, MESH 6 Remove Double'],
+['W', 'Edit Mode: Specials menu, MESH 7 Hide'],
+['W', 'Edit Mode: Specials menu, MESH 8 Reveal'],
+['W', 'Edit Mode: Specials menu, MESH 9 Select Swap'],
+['W', 'Edit Mode: Specials menu, MESH 10 Flip Normal'],
+['W', 'Edit Mode: Specials menu, MESH 11 Smooth'],
+['W', 'Edit Mode: Specials menu, MESH 12 Bevel'],
+['W', 'Edit Mode: Specials menu, MESH 13 Set Smooth'],
+['W', 'Edit Mode : Specials menu, MESH 14 Set Solid'],
+['W', 'Object Mode : on MESH objects, Boolean Tools menu'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 1 Intersect'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 2 union'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 3 difference'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 4 Add an intersect Modifier'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 5 Add an union Modifier'],
+['W', 'Object Mode : on MESH objects, Boolean Tools 6 Add a difference Modifier'],
+['W', 'Object mode : on TEXT object, Split characters, a new TEXT object by character in the selected string '],
['W', 'UV Image Editor: Weld/Align'],
['WX', 'UV Image Editor: Weld/Align X axis'],
['WY', 'UV Image Editor: Weld/Align Y axis'],
['Ctrl-W', 'Save current file'] ,
-['Ctrl-W', 'Nurbs: Switch direction'] ,
['Shift-W', 'Warp/bend selected vertices around cursor'],
['alt-W', 'Export in videoscape format']
],
@@ -456,13 +507,15 @@ hotkeys={
],
"Y":[
-['Y', 'Mesh: Split selected vertices/faces from the rest'] ],
+['Y', 'Edit Mode & Mesh : Split selected vertices/faces from the rest'],
+['Ctrl-Y', 'Object Mode : Redo'],
+],
"Z":[
['Z', 'Render Window: 200% zoom from mouse position'],
['Z', 'Switch 3d draw type : solide/ wireframe (see also D)'],
['Alt-Z', 'Switch 3d draw type : solid / textured (see also D)'],
-['Ctrl-Z', 'Switch 3d draw type : shaded (see also D)'],
+['Ctrl-Z', 'Object Mode : Undo'],
['Shift-Z', 'Switch 3d draw type : shaded / wireframe (see also D)'],
]}]}
@@ -498,12 +551,15 @@ def searchfor(SEARCHLINE):
#print 'k, l : ', k, l, l[1]
if l[1].upper().find(SEARCHLINE.upper())!=-1:
FINDLIST.append(l)
+
elif k == 'Letters ':
for l in hotL :
for l0 in hotkeys['Letters '][0][l][:-1]:
#print 'k, l : ',l, k, l0
if l0[1].upper().find(SEARCHLINE.upper())!=-1:
FINDLIST.append(l0)
+ #print 'FINDLIST',FINDLIST
+ FINDLIST.append(['Find list','Entry'])
return FINDLIST
@@ -569,6 +625,7 @@ def draw():
listed=hot.index(k)
l=0
size[3]=size[3]-4
+
if hot[listed]!='Letters ' and hot[listed]!='Search ' :
size[3]=size[3]-8
SCROLL=size[3]/21
@@ -594,17 +651,19 @@ def draw():
glRasterPos2f(4+8*15, size[3]-(58+21*l))
Text(' : '+n[1])
l+=1
+
elif hot[listed]=='Search ' :
r=[0,size[3]-70,
size[2], size[3]-44]
trace_rectangle4(r,c2)
SEARCHLINE=String(' ', LINE, 42, size[3]-68,200,18,SEARCHLINE.val, 256,'')
if len(FINDED)>0:
- LEN=len(FINDED)
- size[3]=size[3]-8
- SCROLL=size[3]/21
- END=-1
- if SCROLL < len(FINDED):
+ LEN=len(FINDED)
+ size[3]=size[3]-8
+ SCROLL=size[3]/21
+ END=-1
+
+ if SCROLL < len(FINDED):
Button('/\\',up,4,size[3]+8,20,14,'Scroll up')
Button('\\/',down,4,size[3]-8,20,14,'Scroll down')
if (SCROLL+UP)<len(FINDED):
@@ -612,9 +671,9 @@ def draw():
else:
END=-1
#UP=len(FINDED)-SCROLL
- else:
- UP=0
- for n in FINDED[UP:END]:
+ else:
+ UP=0
+ for n in FINDED[UP:END]:
if l%2==0:
r=[0,size[3]-(21*l+66+24),
size[2], size[3]-(21*l+43+24)]
@@ -714,4 +773,4 @@ def bevent(evt):
Blender.Window.Redraw()
-Register(draw, event, bevent)
+Register(draw, event, bevent) \ No newline at end of file
diff --git a/release/scripts/lightwave_export.py b/release/scripts/lightwave_export.py
index a109acc02c1..d3d7099594f 100644
--- a/release/scripts/lightwave_export.py
+++ b/release/scripts/lightwave_export.py
@@ -46,12 +46,27 @@ v5.5 format.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | April 21, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write LightWave Object File Format (*.lwo) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
import struct, chunk, os, cStringIO, time, operator
diff --git a/release/scripts/lightwave_import.py b/release/scripts/lightwave_import.py
index 8680890b0ce..da619fcffb0 100644
--- a/release/scripts/lightwave_import.py
+++ b/release/scripts/lightwave_import.py
@@ -1,16 +1,19 @@
#!BPY
"""
Name: 'LightWave + Materials (.lwo)...'
-Blender: 237
+Blender: 239
Group: 'Import'
Tooltip: 'Import LightWave Object File Format (.lwo)'
"""
__author__ = "Alessandro Pirovano, Anthony D'Agostino (Scorpius)"
__url__ = ("blender", "elysiun",
-"Author's homepage, http://www.redrival.com/scorpius", "Author's homepage, http://uaraus.altervista.org")
+"Anthony's homepage, http://www.redrival.com/scorpius", "Alessandro's homepage, http://uaraus.altervista.org")
-importername = "lwo_import 0.1.16"
+importername = "lwo_import 0.2.2b"
+
+# $Id$
+#
# +---------------------------------------------------------+
# | Save your work before and after use. |
# | Please report any useful comment to: |
@@ -22,7 +25,6 @@ importername = "lwo_import 0.1.16"
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | April 21, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
# | Import Export Suite v0.5 |
# +---------------------------------------------------------+
# | Read and write LightWave Object File Format (*.lwo) |
@@ -31,8 +33,36 @@ importername = "lwo_import 0.1.16"
# | Alessandro Pirovano tweaked starting on March 2005 |
# | http://uaraus.altervista.org |
# +---------------------------------------------------------+
+# +----------------------------------------------------------
+# | GPL license block
+# |
+# | 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.
+# |
+# | You should have received a copy of the GNU General Public License
+# | along with this program; if not, write to the Free Software
+# | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# +----------------------------------------------------------
# +---------------------------------------------------------+
# | Release log: |
+# | 0.2.1 : This code works with Blender 2.40 RC1 |
+# | modified material mode assignment to deal with |
+# | Python API modification |
+# | Changed script license to GNU GPL |
+# | 0.2.0: This code works with Blender 2.40a2 or up |
+# | Major rewrite to deal with large meshes |
+# | - 2 pass file parsing |
+# | - lower memory footprint |
+# | (as long as python gc allows) |
+# | 2.40a2 - Removed subsurf settings patches=poly |
+# | 2.40a2 - Edge generation instead of 2vert faces |
# | 0.1.16: fixed (try 2) texture offset calculations |
# | added hint on axis mapping |
# | added hint on texture blending mode |
@@ -69,11 +99,26 @@ import struct, chunk, os, cStringIO, time, operator, copy
# ===========================================================
textname = "lwo_log"
+type_list = type(list())
+type_dict = type(dict())
#uncomment the following line to disable logging facility
-#textname = None 1
+#textname = None
# ===========================================================
+
+# ===========================================================
+# === Make sure it is a string ... deal with strange chars ==
+# ===========================================================
+def safestring(st):
+ myst = ""
+ for ll in xrange(len(st)):
+ if st[ll] < " ":
+ myst += "#"
+ else:
+ myst += st[ll]
+ return myst
+
class dotext:
_NO = 0 #use internal to class only
@@ -87,7 +132,7 @@ class dotext:
self.txtobj = None
return
tlist = Blender.Text.get()
- for i in range(len(tlist)):
+ for i in xrange(len(tlist)):
if (tlist[i].getName()==tname):
tlist[i].clear()
#print tname, " text object found and cleared!"
@@ -120,14 +165,14 @@ class dotext:
def plist(self, pplist, where = _NO):
self.pprint ("list:[")
- for pp in range(len(pplist)):
+ for pp in xrange(len(pplist)):
self.pprint ("[%d] -> %s" % (pp, pplist[pp]), where)
self.pprint ("]")
# end def plist
def pdict(self, pdict, where = _NO):
self.pprint ("dict:{", where)
- for pp in pdict.keys():
+ for pp in pdict.iterkeys():
self.pprint ("[%s] -> %s" % (pp, pdict[pp]), where)
self.pprint ("}")
# end def pdict
@@ -135,12 +180,12 @@ class dotext:
def pprint(self, parg, where = _NO):
if parg == None:
self.pstring("_None_", where)
- elif type(parg) == type ([]):
+ elif type(parg) == type_list:
self.plist(parg, where)
- elif type(parg) == type ({}):
+ elif type(parg) == type_dict:
self.pdict(parg, where)
else:
- self.pstring(parg, where)
+ self.pstring(safestring(str(parg)), where)
# end def pprint
def logcon(self, parg):
@@ -152,6 +197,13 @@ tobj=dotext(textname)
#uncomment the following line to log all messages on both console and logfile
#tobj=dotext(textname,dotext.CON)
+def rlcopy(ll):
+ if type(ll) != type_list:
+ return ll
+ if ll == []:
+ return []
+ cpy = [rlcopy(ii) for ii in ll]
+ return cpy
# ===========================================================
# === Main read functions ===================================
@@ -172,7 +224,9 @@ def read(filename):
start = time.clock()
file = open(filename, "rb")
- # === LWO header ===
+ editmode = Blender.Window.EditMode() # are we in edit mode? If so ...
+ if editmode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh # === LWO header ===
+
form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12))
if (form_type == "LWOB"):
read_lwob(file, filename)
@@ -193,6 +247,8 @@ def read(filename):
tobj.pprint ("#####################################################################")
tobj.logcon (message)
tobj.logcon ("#####################################################################")
+ if editmode: Blender.Window.EditMode(1) # optional, just being nice
+
# enddef read
@@ -234,6 +290,7 @@ def read_lwo2(file, filename, typ="LWO2"):
dir_part = Blender.sys.dirname(filename)
fname_part = Blender.sys.basename(filename)
+ ask_weird = 1
#first initialization of data structures
defaultname = os.path.splitext(fname_part)[0]
@@ -242,17 +299,63 @@ def read_lwo2(file, filename, typ="LWO2"):
clip_list = [] #clip list: global for the whole file?
object_index = 0
object_list = None
+ objspec_list = None
# init value is: object_list = [[None, {}, [], [], {}, {}, 0, {}, {}]]
#0 - objname #original name
#1 - obj_dict = {TAG} #objects created
#2 - verts = [] #object vertexes
#3 - faces = [] #object faces (associations poly -> vertexes)
#4 - obj_dim_dict = {TAG} #tuples size and pos in local object coords - used for NON-UV mappings
- #5 - polytag_dict = {TAG} #tag to polygon mapping
+ #5 - polytag_dict = {TAG} #tag to polygons mapping
#6 - patch_flag #0 = surf; 1 = patch (subdivision surface) - it was the image list
- #7 - uvcoords_dict = {name} #uvmap coordinates (mixed mode per face/per vertex)
- #8 - facesuv_dict = {name} #uvmap coordinates associations poly -> uv tuples
+ #7 - uvcoords_dict = {name} #uvmap coordinates (mixed mode per vertex/per face)
+ #8 - facesuv_dict = {name} #vmad only coordinates associations poly & vertex -> uv tuples
+
+ #pass 1: look in advance for materials
+ tobj.logcon ("#####################################################################")
+ tobj.logcon ("Starting Pass 1: hold on tight")
+ tobj.logcon ("#####################################################################")
+ while 1:
+ try:
+ lwochunk = chunk.Chunk(file)
+ except EOFError:
+ break
+ tobj.pprint(" ")
+ if lwochunk.chunkname == "TAGS": # Tags
+ tobj.pprint("---- TAGS")
+ tag_list.extend(read_tags(lwochunk))
+ elif lwochunk.chunkname == "SURF": # surfaces
+ tobj.pprint("---- SURF")
+ surf_list.append(read_surfs(lwochunk, surf_list, tag_list))
+ elif lwochunk.chunkname == "CLIP": # texture images
+ tobj.pprint("---- CLIP")
+ clip_list.append(read_clip(lwochunk, dir_part))
+ tobj.pprint("read total %s clips up to now" % len(clip_list))
+ else: # Misc Chunks
+ if ask_weird:
+ ckname = safestring(lwochunk.chunkname)
+ if "#" in ckname:
+ choice = Blender.Draw.PupMenu("WARNING: file could be corrupted.%t|Import anyway|Give up")
+ if choice != 1:
+ tobj.logcon("---- %s: Maybe file corrupted. Terminated by user" % lwochunk.chunkname)
+ return
+ ask_weird = 0
+ tobj.pprint("---- %s: skipping (maybe later)" % lwochunk.chunkname)
+ lwochunk.skip()
+ #add default material for orphaned faces, if any
+ surf_list.append({'NAME': "_Orphans", 'g_MAT': Blender.Material.New("_Orphans")})
+
+ #pass 2: effectively generate objects
+ tobj.logcon ("#####################################################################")
+ tobj.logcon ("Pass 2: now for the hard part")
+ tobj.logcon ("#####################################################################")
+ file.seek(0)
+ # === LWO header ===
+ form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12))
+ if (form_type != "LWO2"):
+ tobj.logcon ("??? Inconsistent file type: %s" %form_type)
+ return
while 1:
try:
lwochunk = chunk.Chunk(file)
@@ -263,81 +366,69 @@ def read_lwo2(file, filename, typ="LWO2"):
tobj.pprint("---- LAYR")
objname = read_layr(lwochunk)
tobj.pprint(objname)
- if object_list == None:
- object_list = [[objname, {}, [], [], {}, {}, 0, {}, {}]]
- else:
- object_list.append([objname, {}, [], [], {}, {}, 0, {}, {}])
- object_index += 1
+ if objspec_list != None: #create the object
+ create_objects(clip_list, objspec_list, surf_list)
+ update_material(clip_list, objspec_list, surf_list) #give it all the object
+ objspec_list = [objname, {}, [], [], {}, {}, 0, {}, {}]
+ object_index += 1
elif lwochunk.chunkname == "PNTS": # Verts
tobj.pprint("---- PNTS")
verts = read_verts(lwochunk)
- object_list[object_index][2] = verts
+ objspec_list[2] = verts
elif lwochunk.chunkname == "VMAP": # MAPS (UV)
tobj.pprint("---- VMAP")
- object_list[object_index][7], object_list[object_index][8] = read_vmap(object_list[object_index][7], object_list[object_index][8], object_list[object_index][3], len(object_list[object_index][2]), lwochunk)
+ #objspec_list[7] = read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk)
+ read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk)
elif lwochunk.chunkname == "VMAD": # MAPS (UV) per-face
tobj.pprint("---- VMAD")
- object_list[object_index][7], object_list[object_index][8] = read_vmad(object_list[object_index][7], object_list[object_index][8], object_list[object_index][3], len(object_list[object_index][2]), lwochunk)
+ #objspec_list[7], objspec_list[8] = read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk)
+ read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk)
elif lwochunk.chunkname == "POLS": # Faces v6.0
tobj.pprint("-------- POLS(6)")
faces, flag = read_faces_6(lwochunk)
#flag is 0 for regular polygon, 1 for patches (= subsurf), 2 for anything else to be ignored
if flag<2:
- if object_list[object_index][3] != []:
- object_list.append([object_list[object_index][0], #update name
- {}, #init
- copy.deepcopy(object_list[object_index][2]), #same vertexes
- [], #no faces
- {}, #no need to copy - filled at runtime
- {}, #polygon tagging will follow
- flag, #patch flag
- copy.deepcopy(object_list[object_index][7]), #same uvcoords
- {}]) #no uv mapping
+ if objspec_list[3] != []:
+ #create immediately the object
+ create_objects(clip_list, objspec_list, surf_list)
+ update_material(clip_list, objspec_list, surf_list) #give it all the object
+ #update with new data
+ objspec_list = [objspec_list[0], #update name
+ {}, #init
+ objspec_list[2], #same vertexes
+ faces, #give it the new faces
+ {}, #no need to copy - filled at runtime
+ {}, #polygon tagging will follow
+ flag, #patch flag
+ objspec_list[7], #same uvcoords
+ {}] #no vmad mapping
object_index += 1
#end if already has a face list
- #update uv coords mapping if VMAP already encountered
- for uvname in object_list[object_index][7]:
- tobj.pprint("updating uv to face mapping for %s" % uvname)
- object_list[object_index][8][uvname] = copy.deepcopy(faces)
- object_list[object_index][3] = faces
- objname = object_list[object_index][0]
+ objspec_list[3] = faces
+ objname = objspec_list[0]
if objname == None:
objname = defaultname
#end if processing a valid poly type
- elif lwochunk.chunkname == "TAGS": # Tags
- tobj.pprint("---- TAGS")
- tag_list.extend(read_tags(lwochunk))
elif lwochunk.chunkname == "PTAG": # PTags
tobj.pprint("---- PTAG")
polytag_dict = read_ptags(lwochunk, tag_list)
- for kk in polytag_dict.keys(): object_list[object_index][5][kk] = polytag_dict[kk]
- elif lwochunk.chunkname == "SURF": # surfaces
- tobj.pprint("---- SURF")
- surf_list.append(read_surfs(lwochunk, surf_list, tag_list))
- elif lwochunk.chunkname == "CLIP": # texture images
- tobj.pprint("---- CLIP")
- clip_list.append(read_clip(lwochunk))
- tobj.pprint("read total %s clips" % len(clip_list))
+ for kk, ii in polytag_dict.iteritems(): objspec_list[5][kk] = ii
else: # Misc Chunks
- tobj.pprint("---- %s: skipping" % lwochunk.chunkname)
+ tobj.pprint("---- %s: skipping (definitely!)" % lwochunk.chunkname)
lwochunk.skip()
#uncomment here to log data structure as it is built
#tobj.pprint(object_list)
+ #last object read
+ create_objects(clip_list, objspec_list, surf_list)
+ update_material(clip_list, objspec_list, surf_list) #give it all the object
+ objspec_list = None
+ surf_list = None
+ clip_list = None
+
tobj.pprint ("\n#####################################################################")
- tobj.pprint("Found %d objects:" % len(object_list))
+ tobj.pprint("Found %d objects:" % object_index)
tobj.pprint ("#####################################################################")
- for objspec_list in object_list:
- tobj.pprint ("\n#===================================================================#")
- tobj.pprint("Processing Object: %s" % objspec_list[0])
- tobj.pprint ("#===================================================================#")
- objspec_list[3], objspec_list[5], objspec_list[8] = recalc_faces(objspec_list[2], objspec_list[3], objspec_list[5], objspec_list[8]) #recalculate faces, polytag_dict and uv_mapping get rid of faces fanning
-
- create_objects(objspec_list)
-
- if surf_list != []:
- create_material(clip_list, surf_list, objspec_list, dir_part) #give it all the object
- return
# enddef read_lwo2
@@ -358,8 +449,8 @@ def read_verts(lwochunk):
numverts = lwochunk.chunksize/12
#$verts = []
verts = [None] * numverts
- for i in range(numverts):
- if not i%100 and my_meshtools.show_progress:
+ for i in xrange(numverts):
+ if not i%1000 and my_meshtools.show_progress:
Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
x, y, z = struct.unpack(">fff", data.read(12))
verts[i] = (x, z, y)
@@ -406,13 +497,18 @@ def read_faces_5(lwochunk):
faces = []
i = 0
while i < lwochunk.chunksize:
- if not i%100 and my_meshtools.show_progress:
+ if not i%1000 and my_meshtools.show_progress:
Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
+
+ '''
facev = []
numfaceverts, = struct.unpack(">H", data.read(2))
- for j in range(numfaceverts):
+ for j in xrange(numfaceverts):
index, = struct.unpack(">H", data.read(2))
facev.append(index)
+ '''
+ numfaceverts, = struct.unpack(">H", data.read(2))
+ facev = [struct.unpack(">H", data.read(2))[0] for j in xrange(numfaceverts)]
facev.reverse()
faces.append(facev)
surfaceindex, = struct.unpack(">H", data.read(2))
@@ -442,46 +538,42 @@ def read_vx(data):
# ======================
# === Read uvmapping ===
# ======================
-def read_vmap(uvcoords_dict, facesuv_dict, faces, maxvertnum, lwochunk):
+def read_vmap(uvcoords_dict, maxvertnum, lwochunk):
if maxvertnum == 0:
tobj.pprint ("Found VMAP but no vertexes to map!")
- return uvcoords_dict, facesuv_dict
+ return uvcoords_dict
data = cStringIO.StringIO(lwochunk.read())
map_type = data.read(4)
if map_type != "TXUV":
tobj.pprint ("Reading VMAP: No Texture UV map Were Found. Map Type: %s" % map_type)
- return uvcoords_dict, facesuv_dict
+ return uvcoords_dict
dimension, = struct.unpack(">H", data.read(2))
name, i = read_name(data) #i initialized with string lenght + zeros
tobj.pprint ("TXUV %d %s" % (dimension, name))
- #my_uv_list = [None] * maxvertnum
- my_uv_list = [(0.0, 0.0)] * maxvertnum #more safe to have some default coordinates to associate in any case?
- while (i < lwochunk.chunksize - 6): #4+2 header bytes already read
+ #note if there is already a VMAD it will be lost
+ #it is assumed that VMAD will follow the corresponding VMAP
+ try: #if uvcoords_dict.has_key(name):
+ my_uv_dict = uvcoords_dict[name] #update existing
+ except: #else:
+ my_uv_dict = {} #start a brand new: this could be made more smart
+ while (i < lwochunk.chunksize - 6): #4+2 header bytes already read
vertnum, vnum_size = read_vx(data)
u, v = struct.unpack(">ff", data.read(8))
if vertnum >= maxvertnum:
tobj.pprint ("Hem: more uvmap than vertexes? ignoring uv data for vertex %d" % vertnum)
else:
- my_uv_list[vertnum] = (u, v)
+ my_uv_dict[vertnum] = (u, v)
i += 8 + vnum_size
#end loop on uv pairs
- uvcoords_dict[name] = my_uv_list
+ uvcoords_dict[name] = my_uv_dict
#this is a per-vertex mapping AND the uv tuple is vertex-ordered, so faces_uv is the same as faces
- if faces == []:
- tobj.pprint ("no faces read yet! delaying uv to face assignments")
- facesuv_dict[name] = []
- else:
- #deepcopy so we could modify it without actually modify faces
- tobj.pprint ("faces already present: proceeding with assignments")
- facesuv_dict[name] = copy.deepcopy(faces)
- return uvcoords_dict, facesuv_dict
-
+ #return uvcoords_dict
+ return
# ========================
# === Read uvmapping 2 ===
# ========================
-def read_vmad(uvcoords_dict, facesuv_dict, faces, maxvertnum, lwochunk):
- maxfacenum = len(faces)
+def read_vmad(uvcoords_dict, facesuv_dict, maxfacenum, maxvertnum, lwochunk):
if maxvertnum == 0 or maxfacenum == 0:
tobj.pprint ("Found VMAD but no vertexes to map!")
return uvcoords_dict, facesuv_dict
@@ -493,14 +585,13 @@ def read_vmad(uvcoords_dict, facesuv_dict, faces, maxvertnum, lwochunk):
dimension, = struct.unpack(">H", data.read(2))
name, i = read_name(data) #i initialized with string lenght + zeros
tobj.pprint ("TXUV %d %s" % (dimension, name))
- if uvcoords_dict.has_key(name):
- my_uv_list = uvcoords_dict[name] #update existing
- my_facesuv_list = facesuv_dict[name]
- else:
- my_uv_list = [(0.0, 0.0)] * maxvertnum #start a brand new: this could be made more smart
- my_facesuv_list = copy.deepcopy(faces)
+ try: #if uvcoords_dict.has_key(name):
+ my_uv_dict = uvcoords_dict[name] #update existing
+ except: #else:
+ my_uv_dict = {} #start a brand new: this could be made more smart
+ my_facesuv_list = []
+ newindex = maxvertnum + 10 #why +10? Why not?
#end variable initialization
- lastindex = len(my_uv_list) - 1
while (i < lwochunk.chunksize - 6): #4+2 header bytes already read
vertnum, vnum_size = read_vx(data)
i += vnum_size
@@ -510,18 +601,15 @@ def read_vmad(uvcoords_dict, facesuv_dict, faces, maxvertnum, lwochunk):
if polynum >= maxfacenum or vertnum >= maxvertnum:
tobj.pprint ("Hem: more uvmap than vertexes? ignorig uv data for vertex %d" % vertnum)
else:
- my_uv_list.append( (u,v) )
- newindex = len(my_uv_list) - 1
- for vi in range(len(my_facesuv_list[polynum])): #polynum starting from 1 or from 0?
- if my_facesuv_list[polynum][vi] == vertnum:
- my_facesuv_list[polynum][vi] = newindex
- #end loop on current face vertexes
+ my_uv_dict[newindex] = (u, v)
+ my_facesuv_list.append([polynum, vertnum, newindex])
+ newindex += 1
i += 8
#end loop on uv pairs
- uvcoords_dict[name] = my_uv_list
+ uvcoords_dict[name] = my_uv_dict
facesuv_dict[name] = my_facesuv_list
- tobj.pprint ("updated %d vertexes data" % (newindex-lastindex))
- return uvcoords_dict, facesuv_dict
+ tobj.pprint ("updated %d vertexes data" % (newindex-maxvertnum-10))
+ return
# =================
@@ -558,7 +646,7 @@ def read_ptags(lwochunk, tag_list):
ptag_dict = {}
i = 0
while(i < lwochunk.chunksize-4): #4 bytes polygon type already read
- if not i%100 and my_meshtools.show_progress:
+ if not i%1000 and my_meshtools.show_progress:
Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading PTAGS")
poln, poln_size = read_vx(data)
i += poln_size
@@ -568,11 +656,12 @@ def read_ptags(lwochunk, tag_list):
return {}
i += 2
tag_key = tag_list[tag_index]
- if not(ptag_dict.has_key(tag_key)):
- ptag_dict[tag_list[tag_index]] = [poln]
- else:
+ try: #if ptag_dict.has_key(tag_key):
ptag_dict[tag_list[tag_index]].append(poln)
- for i in ptag_dict.keys():
+ except: #else:
+ ptag_dict[tag_list[tag_index]] = [poln]
+
+ for i in ptag_dict.iterkeys():
tobj.pprint ("read %d polygons belonging to TAG %s" % (len(ptag_dict[i]), i))
return ptag_dict
@@ -581,7 +670,9 @@ def read_ptags(lwochunk, tag_list):
# ==================
# === Read Clips ===
# ==================
-def read_clip(lwochunk):
+def read_clip(lwochunk, dir_part):
+# img, IMG, g_IMG refers to blender image objects
+# ima, IMAG, g_IMAG refers to clip dictionary 'ID' entries: refer to blok and surf
clip_dict = {}
data = cStringIO.StringIO(lwochunk.read())
image_index, = struct.unpack(">L", data.read(4))
@@ -616,11 +707,30 @@ def read_clip(lwochunk):
n, = struct.unpack(">H", data.read(2))
clip_dict['NEGA'] = n
else: # Misc Chunks
- tobj.pprint("-------- SURF:%s: skipping" % subchunkname)
+ tobj.pprint("-------- CLIP:%s: skipping" % subchunkname)
discard = data.read(subchunklen)
i = i + 6 + subchunklen
#end loop on surf chunks
tobj.pprint("read image:%s" % clip_dict)
+ if clip_dict.has_key('XREF'):
+ tobj.pprint("Cross-reference: no image pre-allocated.")
+ return clip_dict
+ #look for images
+ img = load_image("",clip_dict['NAME'])
+ if img == None:
+ tobj.pprint ( "***No image %s found: trying LWO file subdir" % clip_dict['NAME'])
+ img = load_image(dir_part,clip_dict['BASENAME'])
+ if img == None:
+ tobj.pprint ( "***No image %s found in directory %s: trying Images subdir" % (clip_dict['BASENAME'], dir_part))
+ img = load_image(dir_part+Blender.sys.sep+"Images",clip_dict['BASENAME'])
+ if img == None:
+ tobj.pprint ( "***No image %s found: trying alternate Images subdir" % clip_dict['BASENAME'])
+ img = load_image(dir_part+Blender.sys.sep+".."+Blender.sys.sep+"Images",clip_dict['BASENAME'])
+ if img == None:
+ tobj.pprint ( "***No image %s found: giving up" % clip_dict['BASENAME'])
+ #lucky we are: we have an image
+ tobj.pprint ("Image pre-allocated.")
+ clip_dict['g_IMG'] = img
return clip_dict
@@ -644,7 +754,7 @@ def read_surfblok(subchunkdata):
tobj.pprint ("---------- IMAP")
ordinal, i = read_name(data)
my_dict['ORD'] = ordinal
- my_dict['g_ORD'] = -1
+ #my_dict['g_ORD'] = -1
my_dict['ENAB'] = True
while(i < subchunklen): # ---------left 6------------------------- loop on header parameters
sub2chunkname, = struct.unpack("4s", data.read(4))
@@ -880,27 +990,32 @@ def read_surfs(lwochunk, surf_list, tag_list):
rr, uvname = read_surfblok(data.read(subchunklen))
#paranoia setting: preventing adding an empty dict
if rr != {}:
- if not(my_dict.has_key('BLOK')):
- my_dict['BLOK'] = [rr]
- else:
+ try:
my_dict['BLOK'].append(rr)
+ except:
+ my_dict['BLOK'] = [rr]
+
if uvname != "":
my_dict['UVNAME'] = uvname #theoretically there could be a number of them: only one used per surf
+ if not(my_dict.has_key('g_IMAG')) and (rr.has_key('CHAN')) and (rr.has_key('OPAC')) and (rr.has_key('IMAG')):
+ if (rr['CHAN'] == 'COLR') and (rr['OPAC'] == 0):
+ my_dict['g_IMAG'] = rr['IMAG'] #do not set anything, just save image object for later assignment
subchunklen = 0 #force ending
else: # Misc Chunks
tobj.pprint("-------- SURF:%s: skipping" % subchunkname)
if subchunklen > 0:
discard = data.read(subchunklen)
#end loop on surf chunks
- if my_dict.has_key('BLOK'):
- my_dict['BLOK'].reverse()
+ try: #if my_dict.has_key('BLOK'):
+ my_dict['BLOK'].reverse() #texture applied in reverse order with respect to reading from lwo
+ except:
+ pass
+ #uncomment this if material pre-allocated by read_surf
+ my_dict['g_MAT'] = Blender.Material.New(my_dict['NAME'])
+ tobj.pprint("-> Material pre-allocated.")
return my_dict
-
-
-
-
# ===========================================================
# === Generation Routines ===================================
# ===========================================================
@@ -922,7 +1037,7 @@ def find_ear(normal, list_dict, verts, face):
mla = 1
mlb = 2
- for c in range(nv):
+ for c in xrange(nv):
a = (c+1) % nv; b = (a+1) % nv
if list_dict['P'][a] > 0.0: #we have to start from a convex vertex
@@ -934,7 +1049,7 @@ def find_ear(normal, list_dict, verts, face):
#tobj.pprint (" ok, this one passed")
concave = 0
concave_inside = 0
- for xx in range(nv): #looking for concave vertex
+ for xx in xrange(nv): #looking for concave vertex
if (list_dict['P'][xx] <= 0.0) and (xx != b) and (xx != c): #cannot be a: it's convex
#ok, found concave vertex
concave = 1
@@ -1009,12 +1124,12 @@ def reduce_face(verts, face):
vi = face[mvi]
list_dict['D'][mvi] = dist_vector(verts[vi_hiend], verts[vi])
#list of cross products - normals evaluated into vertexes
- for vi in range(nv):
+ for vi in xrange(nv):
list_dict['X'][vi] = Blender.Mathutils.CrossVecs(list_dict['D'][vi], list_dict['D'][vi-1])
my_face_normal = Blender.Mathutils.Vector([list_dict['X'][0][0], list_dict['X'][0][1], list_dict['X'][0][2]])
#list of dot products
list_dict['P'][0] = 1.0
- for vi in range(1, nv):
+ for vi in xrange(1, nv):
list_dict['P'][vi] = Blender.Mathutils.DotVecs(my_face_normal, list_dict['X'][vi])
#is there at least one concave vertex?
#one_concave = reduce(lambda x, y: (x) or (y<=0.0), list_dict['P'], 0)
@@ -1064,63 +1179,37 @@ def reduce_face(verts, face):
# =========================
# === Recalculate Faces ===
# =========================
-# --------- this do the standard face + ptag_dict + uv-map recalc
-def recalc_faces(verts, faces, polytag_dict, facesuv_dict):
- # init local face list
- my_faces = []
- # init local uvface dict
- my_facesuv = {}
- for uvname in facesuv_dict:
- my_facesuv[uvname] = []
- replaced_faces_dict = {}
- j = 0
- if len(faces)==0:
- return faces, polytag_dict, facesuv_dict
- for i in range(len(faces)):
- # i = index that spans on original faces
- # j = index that spans on new faces
- if not i%100 and my_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Recalculating faces")
- numfaceverts=len(faces[i])
- if numfaceverts < 4: #This face is a triangle or quad: more strict - it has to be a triangle
- my_faces.append(faces[i]) #ok, leave it alone ....
- for uvname in facesuv_dict:
- my_facesuv[uvname].append(facesuv_dict[uvname][i])
- replaced_faces_dict[i] = [j] #.... but change the nuber order of the face
- j += 1
- else: # Reduce n-sided convex polygon.
- meta_faces = reduce_face(verts, faces[i]) # Indices of triangles.
- this_faces = [] # list of triangles poly replacing original face
- this_faces_index = []
- for mf in meta_faces:
- ll = len(mf)
- if ll == 3: #triangle
- this_faces.append([faces[i][mf[0]], faces[i][mf[1]], faces[i][mf[2]]])
- else: #quads
- this_faces.append([faces[i][mf[0]], faces[i][mf[1]], faces[i][mf[2]], faces[i][mf[3]]])
- for uvname in facesuv_dict:
- if ll == 3: #triangle
- my_facesuv[uvname].append([facesuv_dict[uvname][i][mf[0]], facesuv_dict[uvname][i][mf[1]], facesuv_dict[uvname][i][mf[2]]])
- else: #quads
- my_facesuv[uvname].append([facesuv_dict[uvname][i][mf[0]], facesuv_dict[uvname][i][mf[1]], facesuv_dict[uvname][i][mf[2]], facesuv_dict[uvname][i][mf[3]]])
- this_faces_index.append(j)
- j +=1
- my_faces.extend(this_faces)
- replaced_faces_dict[i] = this_faces_index #face i substituted by this list of faces
- #endif on face vertex number
- #end loop on every face
- #now we have the new faces list and a dictionary replacement.
- #going for polygon tagging
- my_ptag_dict = {}
- for tag in polytag_dict: #for every tag group
- my_ptag_dict[tag] = [] #rebuild a new entry
- for poly in polytag_dict[tag]: #take every element of old face list
- my_ptag_dict[tag].extend(replaced_faces_dict[poly]) #substitutes the element of new face list
- return my_faces, my_ptag_dict, my_facesuv
-
-# ========================================
-# === Revert list keeping first vertex ===
-# ========================================
+def get_uvface(complete_list, facenum):
+ # extract from the complete list only vertexes of the desired polygon
+ my_facelist = []
+ for elem in complete_list:
+ if elem[0] == facenum:
+ my_facelist.append(elem)
+ return my_facelist
+
+def get_newindex(polygon_list, vertnum):
+ # extract from the polygon list the new index associated to a vertex
+ if polygon_list == []:
+ return -1
+ for elem in polygon_list:
+ if elem[1] == vertnum:
+ return elem[2]
+ #tobj.pprint("WARNING: expected vertex %s for polygon %s. Polygon_list dump follows" % (vertnum, polygon_list[0][0]))
+ #tobj.pprint(polygon_list)
+ return -1
+
+def get_surf(surf_list, cur_tag):
+ for elem in surf_list:
+ if elem['NAME'] == cur_tag:
+ return elem
+ return {}
+
+
+
+# ==========================================
+# === Revert list (keeping first vertex) ===
+# ==========================================
def revert (llist):
#different flavors: the reverse one is the one that works better
#rhead = [llist[0]]
@@ -1128,59 +1217,202 @@ def revert (llist):
#rhead.extend(rtail)
#return rhead
#--------------
- rhead=copy.deepcopy(llist)
+ rhead=rlcopy(llist)
rhead.reverse()
return rhead
#--------------
#return llist
+
# ====================================
# === Modified Create Blender Mesh ===
# ====================================
-def my_create_mesh(complete_vertlist, complete_facelist, current_facelist, objname, not_used_faces):
+def my_create_mesh(clip_list, surf, objspec_list, current_facelist, objname, not_used_faces):
#take the needed faces and update the not-used face list
- vertex_map = [-1] * len(complete_vertlist)
+ complete_vertlist = objspec_list[2]
+ complete_facelist = objspec_list[3]
+ uvcoords_dict = objspec_list[7]
+ facesuv_dict = objspec_list[8]
+ vertex_map = {} #implementation as dict
cur_ptag_faces = []
+ cur_ptag_faces_indexes = []
+ maxface = len(complete_facelist)
for ff in current_facelist:
+ if ff >= maxface:
+ tobj.logcon("Non existent face addressed: Giving up with this object")
+ return None, not_used_faces #return the created object
cur_face = complete_facelist[ff]
- cur_ptag_faces.append(cur_face)
+ cur_ptag_faces_indexes.append(ff)
if not_used_faces != []: not_used_faces[ff] = -1
- for vv in cur_face:
- vertex_map[vv] = 1
- #end loop on vertex on this face
+ for vv in cur_face: vertex_map[vv] = 1
#end loop on faces
+ store_edge = 0
+
+ msh = Blender.NMesh.GetRaw()
+ # Name the Object
+ if not my_meshtools.overwrite_mesh_name:
+ objname = my_meshtools.versioned_name(objname)
+ Blender.NMesh.PutRaw(msh, objname) # Name the Mesh
+ obj = Blender.Object.GetSelected()[0]
+ obj.name=objname
+ # Associate material and mesh properties => from create materials
+ msh = obj.getData()
+ mat_index = len(msh.getMaterials(1))
+ mat = None
+ if surf.has_key('g_MAT'):
+ mat = surf['g_MAT']
+ msh.addMaterial(mat)
+ msh.mode |= Blender.NMesh.Modes.AUTOSMOOTH #smooth it anyway
+ if surf.has_key('SMAN'):
+ #not allowed mixed mode mesh (all the mesh is smoothed and all with the same angle)
+ #only one smoothing angle will be active! => take the max one
+ s = int(surf['SMAN']/3.1415926535897932384626433832795*180.0) #lwo in radians - blender in degrees
+ if msh.getMaxSmoothAngle() < s: msh.setMaxSmoothAngle(s)
+
+ img = None
+ if surf.has_key('g_IMAG'):
+ ima = lookup_imag(clip_list, surf['g_IMAG'])
+ if ima != None:
+ img = ima['g_IMG']
+
+ #uv_flag = ((surf.has_key('UVNAME')) and (uvcoords_dict.has_key(surf['UVNAME'])) and (img != None))
+ uv_flag = ((surf.has_key('UVNAME')) and (uvcoords_dict.has_key(surf['UVNAME'])))
+
+ if uv_flag: #assign uv-data; settings at mesh level
+ msh.hasFaceUV(1)
+ msh.update(1)
- mesh = Blender.NMesh.GetRaw()
+ tobj.pprint ("\n#===================================================================#")
+ tobj.pprint("Processing Object: %s" % objname)
+ tobj.pprint ("#===================================================================#")
- #append vertexes
jj = 0
- for i in range(len(complete_vertlist)):
- if vertex_map[i] == 1:
- if not i%100 and my_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(complete_vertlist), "Generating Verts")
- x, y, z = complete_vertlist[i]
- mesh.verts.append(Blender.NMesh.Vert(x, y, z))
- vertex_map[i] = jj
- jj += 1
+ vertlen = len(vertex_map)
+ maxvert = len(complete_vertlist)
+ for i in vertex_map.iterkeys():
+ if not jj%1000 and my_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/vertlen, "Generating Verts")
+ if i >= maxvert:
+ tobj.logcon("Non existent vertex addressed: Giving up with this object")
+ return obj, not_used_faces #return the created object
+ x, y, z = complete_vertlist[i]
+ msh.verts.append(Blender.NMesh.Vert(x, y, z))
+ vertex_map[i] = jj
+ jj += 1
#end sweep over vertexes
-
+
+ ALPHA_FACE_MODE = (surf.has_key('TRAN') and mat.getAlpha()<1.0)
#append faces
- for i in range(len(cur_ptag_faces)):
- if not i%100 and my_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(cur_ptag_faces), "Generating Faces")
- face = Blender.NMesh.Face()
- rev_face = revert(cur_ptag_faces[i])
- for vi in rev_face:
- #for vi in cur_ptag_faces[i]:
- index = vertex_map[vi]
- face.v.append(mesh.verts[index])
- #end sweep over vertexes
- mesh.faces.append(face)
- #end sweep over faces
+ jj = 0
+ for i in cur_ptag_faces_indexes:
+ if not jj%1000 and my_meshtools.show_progress: Blender.Window.DrawProgressBar(float(jj)/len(cur_ptag_faces_indexes), "Generating Faces")
+ cur_face = complete_facelist[i]
+ numfaceverts = len(cur_face)
+ vmad_list = [] #empty VMAD in any case
+ if uv_flag: #settings at original face level
+ if facesuv_dict.has_key(surf['UVNAME']): #yes = has VMAD; no = has VMAP only
+ vmad_list = get_uvface(facesuv_dict[surf['UVNAME']],i) #this for VMAD
+
+ if numfaceverts == 2:
+ #This is not a face is an edge
+ store_edge = 1
+ if msh.edges == None: #first run
+ msh.addEdgeData()
+ #rev_face = revert(cur_face)
+ i1 = vertex_map[cur_face[1]]
+ i2 = vertex_map[cur_face[0]]
+ ee = msh.addEdge(msh.verts[i1],msh.verts[i2])
+ ee.flag |= Blender.NMesh.EdgeFlags.EDGEDRAW
+ ee.flag |= Blender.NMesh.EdgeFlags.EDGERENDER
+
+ elif numfaceverts == 3:
+ #This face is a triangle skip face reduction
+ face = Blender.NMesh.Face()
+ msh.faces.append(face)
+ # Associate face properties => from create materials
+ if mat != None: face.materialIndex = mat_index
+ face.smooth = 1 #smooth it anyway
+
+ #rev_face = revert(cur_face)
+ rev_face = [cur_face[2], cur_face[1], cur_face[0]]
+
+ for vi in rev_face:
+ index = vertex_map[vi]
+ face.v.append(msh.verts[index])
+
+ if uv_flag:
+ ni = get_newindex(vmad_list, vi)
+ if ni > -1:
+ uv_index = ni
+ else: #VMAP - uses the same criteria as face
+ uv_index = vi
+ try: #if uvcoords_dict[surf['UVNAME']].has_key(uv_index):
+ uv_tuple = uvcoords_dict[surf['UVNAME']][uv_index]
+ except: #else:
+ uv_tuple = (0,0)
+ face.uv.append(uv_tuple)
+
+ if uv_flag and img != None:
+ face.mode |= Blender.NMesh.FaceModes['TEX']
+ face.image = img
+ face.mode |= Blender.NMesh.FaceModes.TWOSIDE #set it anyway
+ face.transp = Blender.NMesh.FaceTranspModes['SOLID']
+ face.flag = Blender.NMesh.FaceTranspModes['SOLID']
+ #if surf.has_key('SIDE'):
+ # msh.faces[f].mode |= Blender.NMesh.FaceModes.TWOSIDE #set it anyway
+ if ALPHA_FACE_MODE:
+ face.transp = Blender.NMesh.FaceTranspModes['ALPHA']
- if not my_meshtools.overwrite_mesh_name:
- objname = my_meshtools.versioned_name(objname)
- Blender.NMesh.PutRaw(mesh, objname) # Name the Mesh
- obj = Blender.Object.GetSelected()[0]
- obj.name=objname # Name the Object
+ elif numfaceverts > 3:
+ #Reduce all the faces with more than 3 vertexes (& test if the quad is concave .....)
+
+ meta_faces = reduce_face(complete_vertlist, cur_face) # Indices of triangles.
+ for mf in meta_faces:
+ face = Blender.NMesh.Face()
+ msh.faces.append(face)
+
+ if len(mf) == 3: #triangle
+ #rev_face = revert([cur_face[mf[0]], cur_face[mf[1]], cur_face[mf[2]]])
+ rev_face = [cur_face[mf[2]], cur_face[mf[1]], cur_face[mf[0]]]
+ else: #quads
+ #rev_face = revert([cur_face[mf[0]], cur_face[mf[1]], cur_face[mf[2]], cur_face[mf[3]]])
+ rev_face = [cur_face[mf[3]], cur_face[mf[2]], cur_face[mf[1]], cur_face[mf[0]]]
+
+ # Associate face properties => from create materials
+ if mat != None: face.materialIndex = mat_index
+ face.smooth = 1 #smooth it anyway
+
+ for vi in rev_face:
+ index = vertex_map[vi]
+ face.v.append(msh.verts[index])
+
+ if uv_flag:
+ ni = get_newindex(vmad_list, vi)
+ if ni > -1:
+ uv_index = ni
+ else: #VMAP - uses the same criteria as face
+ uv_index = vi
+ try: #if uvcoords_dict[surf['UVNAME']].has_key(uv_index):
+ uv_tuple = uvcoords_dict[surf['UVNAME']][uv_index]
+ except: #else:
+ uv_tuple = (0,0)
+ face.uv.append(uv_tuple)
+
+ if uv_flag and img != None:
+ face.mode |= Blender.NMesh.FaceModes['TEX']
+ face.image = img
+ face.mode |= Blender.NMesh.FaceModes.TWOSIDE #set it anyway
+ face.transp = Blender.NMesh.FaceTranspModes['SOLID']
+ face.flag = Blender.NMesh.FaceTranspModes['SOLID']
+ #if surf.has_key('SIDE'):
+ # msh.faces[f].mode |= Blender.NMesh.FaceModes.TWOSIDE #set it anyway
+ if ALPHA_FACE_MODE:
+ face.transp = Blender.NMesh.FaceTranspModes['ALPHA']
+
+ jj += 1
+
+ if not(uv_flag): #clear eventual UV data
+ msh.hasFaceUV(0)
+ msh.update(1,store_edge)
Blender.Redraw()
return obj, not_used_faces #return the created object
@@ -1191,8 +1423,12 @@ def my_create_mesh(complete_vertlist, complete_facelist, current_facelist, objna
def set_subsurf(obj):
msh = obj.getData()
msh.setSubDivLevels([2, 2])
- msh.mode |= Blender.NMesh.Modes.SUBSURF
- msh.update(1)
+ #does not work any more in 2.40 alpha 2
+ #msh.mode |= Blender.NMesh.Modes.SUBSURF
+ if msh.edges != None:
+ msh.update(1,1)
+ else:
+ msh.update(1)
obj.makeDisplayList()
return
@@ -1212,7 +1448,7 @@ def obj_size_pos(obj):
# =========================
# === Create the object ===
# =========================
-def create_objects(objspec_list):
+def create_objects(clip_list, objspec_list, surf_list):
nf = len(objspec_list[3])
not_used_faces = range(nf)
ptag_dict = objspec_list[5]
@@ -1223,33 +1459,36 @@ def create_objects(objspec_list):
endchar = ""
if (objspec_list[6] == 1):
middlechar = endchar = "#"
- for cur_tag in ptag_dict.keys():
+ for cur_tag in ptag_dict.iterkeys():
if ptag_dict[cur_tag] != []:
- cur_obj, not_used_faces= my_create_mesh(objspec_list[2], objspec_list[3], ptag_dict[cur_tag], objspec_list[0][:9]+middlechar+cur_tag[:9], not_used_faces)
- if objspec_list[6] == 1:
- set_subsurf(cur_obj)
- obj_dict[cur_tag] = cur_obj
- obj_dim_dict[cur_tag] = obj_size_pos(cur_obj)
- obj_list.append(cur_obj)
+ cur_surf = get_surf(surf_list, cur_tag)
+ cur_obj, not_used_faces= my_create_mesh(clip_list, cur_surf, objspec_list, ptag_dict[cur_tag], objspec_list[0][:9]+middlechar+cur_tag[:9], not_used_faces)
+ #does not work any more in 2.40 alpha 2
+ #if objspec_list[6] == 1:
+ # set_subsurf(cur_obj)
+ if cur_obj != None:
+ obj_dict[cur_tag] = cur_obj
+ obj_dim_dict[cur_tag] = obj_size_pos(cur_obj)
+ obj_list.append(cur_obj)
#end loop on current group
#and what if some faces not used in any named PTAG? get rid of unused faces
- for ff in range(nf):
- tt = nf-1-ff #reverse order
- if not_used_faces[tt] == -1:
- not_used_faces.pop(tt)
+ orphans = []
+ for tt in not_used_faces:
+ if tt > -1: orphans.append(tt)
#end sweep on unused face list
- if not_used_faces != []:
- cur_obj, not_used_faces = my_create_mesh(objspec_list[2], objspec_list[3], not_used_faces, objspec_list[0][:9]+middlechar+"lone", [])
- #my_meshtools.create_mesh(objspec_list[2], not_used_faces, "_unk") #vert, faces, name
- #cur_obj = Blender.Object.GetSelected()[0]
- if objspec_list[6] == 1:
- set_subsurf(cur_obj)
- obj_dict["lone"] = cur_obj
- obj_dim_dict["lone"] = obj_size_pos(cur_obj)
- obj_list.append(cur_obj)
+ not_used_faces = None
+ if orphans != []:
+ cur_surf = get_surf(surf_list, "_Orphans")
+ cur_obj, not_used_faces = my_create_mesh(clip_list, cur_surf, objspec_list, orphans, objspec_list[0][:9]+middlechar+"Orphans", [])
+ if cur_obj != None:
+ if objspec_list[6] == 1:
+ set_subsurf(cur_obj)
+ obj_dict["_Orphans"] = cur_obj
+ obj_dim_dict["_Orphans"] = obj_size_pos(cur_obj)
+ obj_list.append(cur_obj)
objspec_list[1] = obj_dict
objspec_list[4] = obj_dim_dict
- scene = Blender.Scene.getCurrent () # get the current scene
+ scene = Blender.Scene.GetCurrent () # get the current scene
ob = Blender.Object.New ('Empty', objspec_list[0]+endchar) # make empty object
scene.link (ob) # link the object into the scene
ob.makeParent(obj_list, 1, 0) # set the root for created objects (no inverse, update scene hyerarchy (slow))
@@ -1304,7 +1543,7 @@ def lookup_imag(clip_list,ima_id):
# ===================================================
# === Create and assign image mapping to material ===
# ===================================================
-def create_blok(surf, mat, clip_list, dir_part, obj_size, obj_pos):
+def create_blok(surf, mat, clip_list, obj_size, obj_pos):
def output_size_ofs(size, pos, blok):
#just automate repetitive task
@@ -1351,21 +1590,10 @@ def create_blok(surf, mat, clip_list, dir_part, obj_size, obj_pos):
if ima == None:
tobj.pprint ( "***Block index image not within CLIP list? Quitting Block")
break #safety check (paranoia setting)
- #look for images
- img = load_image("",ima['NAME'])
- if img == None:
- tobj.pprint ( "***No image %s found: trying LWO file subdir" % ima['NAME'])
- img = load_image(dir_part,ima['BASENAME'])
+ img = ima['g_IMG']
if img == None:
- tobj.pprint ( "***No image %s found in directory %s: trying Images subdir" % (ima['BASENAME'], dir_part))
- img = load_image(dir_part+Blender.sys.sep+"Images",ima['BASENAME'])
- if img == None:
- tobj.pprint ( "***No image %s found: trying alternate Images subdir" % ima['BASENAME'])
- img = load_image(dir_part+Blender.sys.sep+".."+Blender.sys.sep+"Images",ima['BASENAME'])
- if img == None:
- tobj.pprint ( "***No image %s found: giving up" % ima['BASENAME'])
+ tobj.pprint ("***Failed to pre-allocate image %s found: giving up" % ima['BASENAME'])
break
- #lucky we are: we have an image
tname = str(ima['ID'])
if blok.has_key('CHAN'):
tname = tname + "+" + blok['CHAN']
@@ -1406,8 +1634,6 @@ def create_blok(surf, mat, clip_list, dir_part, obj_size, obj_pos):
if blok.has_key('CHAN'):
if blok['CHAN'] == 'COLR':
tobj.pprint ("!!!Set Texture -> MapTo -> Col = %.3f" % set_dvar)
- if set_blendmode == 0:
- surf['g_IM'] = img #do not set anything, just save image object for later assignment
if blok['CHAN'] == 'BUMP':
mapflag = Blender.Texture.MapTo.NOR
tobj.pprint ("!!!Set Texture -> MapTo -> Nor = %.3f" % set_dvar)
@@ -1462,21 +1688,22 @@ def create_blok(surf, mat, clip_list, dir_part, obj_size, obj_pos):
# ========================================
# === Create and assign a new material ===
# ========================================
-#def create_material(surf_list, ptag_dict, obj, clip_list, uv_dict, dir_part):
-def create_material(clip_list, surf_list, objspec, dir_part):
+#def update_material(surf_list, ptag_dict, obj, clip_list, uv_dict, dir_part):
+def update_material(clip_list, objspec, surf_list):
if (surf_list == []) or (objspec[5] == {}) or (objspec[1] == {}):
+ tobj.pprint( "something getting wrong in update_material: dump follows ...")
tobj.pprint( surf_list)
tobj.pprint( objspec[5])
tobj.pprint( objspec[1])
- tobj.pprint( "something getting wrong in create_material ...")
return
obj_dict = objspec[1]
+ all_faces = objspec[3]
obj_dim_dict = objspec[4]
ptag_dict = objspec[5]
uvcoords_dict = objspec[7]
facesuv_dict = objspec[8]
for surf in surf_list:
- if (surf['NAME'] in ptag_dict.keys()):
+ if (surf['NAME'] in ptag_dict.iterkeys()):
tobj.pprint ("#-------------------------------------------------------------------#")
tobj.pprint ("Processing surface (material): %s" % surf['NAME'])
tobj.pprint ("#-------------------------------------------------------------------#")
@@ -1487,7 +1714,13 @@ def create_material(clip_list, surf_list, objspec, dir_part):
obj_size = obj_dim_dict[surf['NAME']][0]
obj_pos = obj_dim_dict[surf['NAME']][1]
tobj.pprint(surf)
- mat = Blender.Material.New(surf['NAME'])
+ #uncomment this if material pre-allocated by read_surf
+ mat = surf['g_MAT']
+ if mat == None:
+ tobj.pprint ("Sorry, no pre-allocated material to update. Giving up for %s." % surf['NAME'])
+ break
+ #mat = Blender.Material.New(surf['NAME'])
+ #surf['g_MAT'] = mat
if surf.has_key('COLR'):
mat.rgbCol = surf['COLR']
if surf.has_key('LUMI'):
@@ -1500,8 +1733,12 @@ def create_material(clip_list, surf_list, objspec, dir_part):
mat.setRef(surf['DIFF']) #lwo [0.0, 1.0] - blender [0.0, 1.0]
if surf.has_key('REFL'):
mat.setRayMirr(surf['REFL']) #lwo [0.0, 1.0] - blender [0.0, 1.0]
- #mat.setMode('RAYMIRROR')
- mat.mode |= Blender.Material.Modes.RAYMIRROR
+ #mat.setMode('RAYMIRROR') NO! this will reset all the other modes
+ #mat.mode |= Blender.Material.Modes.RAYMIRROR No more usable?
+ mm = mat.getMode()
+ mm |= Blender.Material.Modes.RAYMIRROR
+ mm &= 327679 #4FFFF this is implementation dependent
+ mat.setMode(mm)
#WARNING translucency not implemented yet check 2.36 API
#if surf.has_key('TRNL'):
#
@@ -1512,55 +1749,27 @@ def create_material(clip_list, surf_list, objspec, dir_part):
mat.setHardness(glo)
if surf.has_key('TRAN'):
mat.setAlpha(1.0-surf['TRAN']) #lwo [0.0, 1.0] - blender [1.0, 0.0]
- mat.mode |= Blender.Material.Modes.RAYTRANSP
+ #mat.mode |= Blender.Material.Modes.RAYTRANSP
+ mm = mat.getMode()
+ mm |= Blender.Material.Modes.RAYTRANSP
+ mm &= 327679 #4FFFF this is implementation dependent
+ mat.setMode(mm)
if surf.has_key('RIND'):
s = surf['RIND']
if s < 1.0: s = 1.0
if s > 3.0: s = 3.0
mat.setIOR(s) #clipped to blender [1.0, 3.0]
- mat.mode |= Blender.Material.Modes.RAYTRANSP
+ #mat.mode |= Blender.Material.Modes.RAYTRANSP
+ mm = mat.getMode()
+ mm |= Blender.Material.Modes.RAYTRANSP
+ mm &= 327679 #4FFFF this is implementation dependent
+ mat.setMode(mm)
if surf.has_key('BLOK') and surf['BLOK'] != []:
#update the material according to texture.
- create_blok(surf, mat, clip_list, dir_part, obj_size, obj_pos)
+ create_blok(surf, mat, clip_list, obj_size, obj_pos)
#finished setting up the material
- #associate material to mesh
- msh = cur_obj.getData()
- mat_index = len(msh.getMaterials(1))
- msh.addMaterial(mat)
- msh.mode |= Blender.NMesh.Modes.AUTOSMOOTH #smooth it anyway
- msh.update(1)
- for f in range(len(msh.faces)):
- msh.faces[f].materialIndex = mat_index
- msh.faces[f].smooth = 1 #smooth it anyway
- msh.faces[f].mode |= Blender.NMesh.FaceModes.TWOSIDE #set it anyway
- msh.faces[f].transp = Blender.NMesh.FaceTranspModes['SOLID']
- msh.faces[f].flag = Blender.NMesh.FaceTranspModes['SOLID']
- if surf.has_key('SMAN'):
- #not allowed mixed mode mesh (all the mesh is smoothed and all with the same angle)
- #only one smoothing angle will be active! => take the max one
- s = int(surf['SMAN']/3.1415926535897932384626433832795*180.0) #lwo in radians - blender in degrees
- if msh.getMaxSmoothAngle() < s: msh.setMaxSmoothAngle(s)
- #if surf.has_key('SIDE'):
- # msh.faces[f].mode |= Blender.NMesh.FaceModes.TWOSIDE #set it anyway
- if surf.has_key('TRAN') and mat.getAlpha()<1.0:
- msh.faces[f].transp = Blender.NMesh.FaceTranspModes['ALPHA']
- if surf.has_key('UVNAME') and facesuv_dict.has_key(surf['UVNAME']):
- #assign uv-data
- msh.hasFaceUV(1)
- #WARNING every block could have its own uvmap set of coordinate. take only the first one
- facesuv_list = facesuv_dict[surf['UVNAME']]
- #print "facesuv_list: ",f , facelist[f]
- rev_face = revert(facesuv_list[facelist[f]])
- for vi in rev_face:
- msh.faces[f].uv.append(uvcoords_dict[surf['UVNAME']][vi])
- if surf.has_key('g_IM'):
- msh.faces[f].mode |= Blender.NMesh.FaceModes['TEX']
- msh.faces[f].image = surf['g_IM']
- #end loop over faces
- msh.update(1)
- mat_index += 1
- #end if exist faces ib this object belonging to surf
- #end loop on surfaces
+ #end if exist SURF
+ #end loop on materials (SURFs)
return
@@ -1578,13 +1787,13 @@ def read_faces_6(lwochunk):
if polygon_type == 'PTCH': subsurf = 1
i = 0
while(i < lwochunk.chunksize-4):
- if not i%100 and my_meshtools.show_progress:
+ if not i%1000 and my_meshtools.show_progress:
Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
facev = []
numfaceverts, = struct.unpack(">H", data.read(2))
i += 2
- for j in range(numfaceverts):
+ for j in xrange(numfaceverts):
index, index_size = read_vx(data)
i += index_size
facev.append(index)
@@ -1602,3 +1811,4 @@ def fs_callback(filename):
read(filename)
Blender.Window.FileSelector(fs_callback, "Import LWO")
+
diff --git a/release/scripts/nendo_export.py b/release/scripts/nendo_export.py
index 830c4303f56..ff9600769d0 100644
--- a/release/scripts/nendo_export.py
+++ b/release/scripts/nendo_export.py
@@ -53,12 +53,27 @@ field.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | September 25, 2001 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Nendo File Format (*.nendo) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
import struct, time, sys, os
diff --git a/release/scripts/nendo_import.py b/release/scripts/nendo_import.py
index e7f3071bd99..e34101ad1e1 100644
--- a/release/scripts/nendo_import.py
+++ b/release/scripts/nendo_import.py
@@ -48,12 +48,27 @@ edges during the course of modeling.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | September 25, 2001 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Nendo File Format (*.nendo) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
import struct, time, sys, os
diff --git a/release/scripts/obj_export.py b/release/scripts/obj_export.py
index c220d66b709..b57343e36dc 100644
--- a/release/scripts/obj_export.py
+++ b/release/scripts/obj_export.py
@@ -21,7 +21,7 @@ Run this script from "File->Export" menu to export all meshes.
# --------------------------------------------------------------------------
-# OBJ Export v0.9b by Campbell Barton (AKA Ideasman)
+# OBJ Export v1.0 by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
@@ -42,12 +42,18 @@ Run this script from "File->Export" menu to export all meshes.
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
-#==================================================#
-# New name based on old with a different extension #
-#==================================================#
-def newFName(ext):
- return Get('filename')[: -len(Get('filename').split('.', -1)[-1]) ] + ext
+import Blender
+from Blender import Mesh, Scene, Window, sys, Image, Draw
+
+# Returns a tuple - path,extension.
+# 'hello.obj' > ('hello', '.obj')
+def splitExt(path):
+ dotidx = path.rfind('.')
+ if dotidx == -1:
+ return path, ''
+ else:
+ return path[:dotidx], path[dotidx:]
def fixName(name):
if name == None:
@@ -55,10 +61,53 @@ def fixName(name):
else:
return name.replace(' ', '_')
+# Used to add the scene name into the filename without using odd chars
+def saneFilechars(name):
+ for ch in ' /\\~!@#$%^&*()+=[];\':",./<>?\t\r\n':
+ name = name.replace(ch, '_')
+ return name
+def sortPair(a,b):
+ return min(a,b), max(a,b)
-
-from Blender import *
+def getMeshFromObject(object, name=None, mesh=None):
+ if mesh:
+ mesh.verts = None # Clear the mesh
+ else:
+ if not name:
+ mesh = Mesh.New()
+ else:
+ mesh = Mesh.New(name)
+
+
+ type = object.getType()
+ dataname = object.getData(1)
+
+ try:
+ mesh.getFromObject(object.name)
+ except:
+ return None
+
+ if type == 'Mesh':
+ tempMe = Mesh.Get( dataname )
+ mesh.materials = tempMe.materials
+ mesh.degr = tempMe.degr
+ mesh.mode = tempMe.mode
+ else:
+ try:
+ # Will only work for curves!!
+ # Text- no material access in python interface.
+ # Surf- no python interface
+ # MBall- no material access in python interface.
+
+ data = object.getData()
+ materials = data.getMaterials()
+ mesh.materials = materials
+ print 'assigning materials for non mesh'
+ except:
+ print 'Cant assign materials to', type
+
+ return mesh
global MTL_DICT
@@ -66,17 +115,17 @@ global MTL_DICT
# (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
MTL_DICT = {}
-def save_mtl(filename):
+def write_mtl(filename):
global MTL_DICT
- world = World.GetCurrent()
+ world = Blender.World.GetCurrent()
if world:
worldAmb = world.getAmb()
else:
worldAmb = (0,0,0) # Default value
file = open(filename, "w")
- file.write('# Blender MTL File: %s\n' % Get('filename').split('\\')[-1].split('/')[-1])
+ file.write('# Blender MTL File: %s\n' % Blender.Get('filename').split('\\')[-1].split('/')[-1])
file.write('# Material Count: %i\n' % len(MTL_DICT))
# Write material/image combinations we have used.
for key, mtl_mat_name in MTL_DICT.iteritems():
@@ -96,7 +145,7 @@ def save_mtl(filename):
file.write('illum 2\n') # light normaly
else:
- mat = Material.Get(key[0])
+ mat = Blender.Material.Get(key[0])
file.write('Ns %s\n' % round((mat.getHardness()-1) * 1.9607843137254901 ) ) # Hardness, convert blenders 1-511 to MTL's
file.write('Ka %s %s %s\n' % tuple([round(c*mat.getAmb(), 6) for c in worldAmb]) ) # Ambient, uses mirror colour,
file.write('Kd %s %s %s\n' % tuple([round(c*mat.getRef(), 6) for c in mat.getRGBCol()]) ) # Diffuse
@@ -105,7 +154,7 @@ def save_mtl(filename):
file.write('d %s\n' % round(mat.getAlpha(), 6)) # Alpha (obj uses 'd' for dissolve)
# 0 to disable lighting, 1 for ambient & diffuse only (specular color set to black), 2 for full lighting.
- if mat.getMode() & Material.Modes['SHADELESS']:
+ if mat.getMode() & Blender.Material.Modes['SHADELESS']:
file.write('illum 0\n') # ignore lighting
elif mat.getSpec() == 0:
file.write('illum 1\n') # no specular.
@@ -120,7 +169,7 @@ def save_mtl(filename):
elif key[0] != None: # No face image. if we havea material search for MTex image.
for mtex in mat.getTextures():
- if mtex and mtex.tex.type == Texture.Types.IMAGE:
+ if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE:
try:
filename = mtex.tex.image.filename.split('\\')[-1].split('/')[-1]
file.write('map_Kd %s\n' % filename) # Diffuse mapping image
@@ -133,24 +182,84 @@ def save_mtl(filename):
file.close()
+def copy_file(source, dest):
+ file = open(source, 'rb')
+ data = file.read()
+ file.close()
+
+ file = open(dest, 'wb')
+ file.write(data)
+ file.close()
-def save_obj(filename):
- global MTL_DICT
+def copy_images(dest_dir):
+ if dest_dir[-1] != sys.sep:
+ dest_dir += sys.sep
+ # Get unique image names
+ uniqueImages = {}
+ for matname, imagename in MTL_DICT.iterkeys(): # Only use image name
+ if imagename != None:
+ uniqueImages[imagename] = None # Should use sets here. wait until Python 2.4 is default.
+
+ # Now copy images
+ copyCount = 0
+
+ for imageName in uniqueImages.iterkeys():
+ print imageName
+ bImage = Image.Get(imageName)
+ image_path = sys.expandpath(bImage.filename)
+ if sys.exists(image_path):
+ # Make a name for the target path.
+ dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
+ if not sys.exists(dest_image_path): # Image isnt alredy there
+ print '\tCopying "%s" > "%s"' % (image_path, dest_image_path)
+ copy_file(image_path, dest_image_path)
+ copyCount+=1
+ print '\tCopied %d images' % copyCount
+
+def write(filename, objects,\
+EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False,\
+EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\
+EXPORT_APPLY_MODIFIERS=True, EXPORT_BLEN_OBS=True,\
+EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False):
+ '''
+ Basic write function. The context and options must be alredy set
+ This can be accessed externaly
+ eg.
+ write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
+ '''
+ print 'OBJ Export path: "%s"' % filename
+ global MTL_DICT
+ temp_mesh_name = '~tmp-mesh'
time1 = sys.time()
scn = Scene.GetCurrent()
file = open(filename, "w")
# Write Header
- file.write('# Blender OBJ File: %s\n' % (Get('filename').split('/')[-1].split('\\')[-1] ))
- file.write('# www.blender.org\n')
+ file.write('# Blender v%s OBJ File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ))
+ file.write('# www.blender3d.org\n')
# Tell the obj file what material file to use.
mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1])
file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] ))
-
+
+ # Get the container mesh.
+ if EXPORT_APPLY_MODIFIERS:
+ containerMesh = meshName = tempMesh = None
+ for meshName in Blender.NMesh.GetNames():
+ if meshName.startswith(temp_mesh_name):
+ tempMesh = Mesh.Get(meshName)
+ if not tempMesh.users:
+ containerMesh = tempMesh
+ if not containerMesh:
+ containerMesh = Mesh.New(temp_mesh_name)
+ del meshName
+ del tempMesh
+
+
+
# Initialize totals, these are updated each object
totverts = totuvco = totno = 1
@@ -158,28 +267,61 @@ def save_obj(filename):
globalNormals = {}
# Get all meshs
- for ob in scn.getChildren():
- #for ob in Object.GetSelected():
- try:
- # Will work for non meshes now! :)
- m = NMesh.GetRawFromObject(ob.name)
- except:
- continue
+ for ob in objects:
- faces = [ f for f in m.faces if len(f) > 2 ]
+ # Will work for non meshes now! :)
+ if EXPORT_APPLY_MODIFIERS or ob.getType() != 'Mesh':
+ m = getMeshFromObject(ob, temp_mesh_name, containerMesh)
+ if not m:
+ continue
+
+ # We have a valid mesh
+ if m and EXPORT_APPLY_MODIFIERS and EXPORT_TRI:
+ # Add a dummy object to it.
+ oldmode = Mesh.Mode()
+ Mesh.Mode(Mesh.SelectModes['FACE'])
+ quadcount = 0
+ for f in m.faces:
+ if len(f.v) == 4:
+ f.sel = 1
+ quadcount +=1
+
+ if quadcount:
+ tempob = Blender.Object.New('Mesh')
+ tempob.link(m)
+ scn.link(tempob)
+ m.quadToTriangle(0) # more=0 shortest length
+ oldmode = Mesh.Mode(oldmode)
+ scn.unlink(tempob)
+ Mesh.Mode(oldmode)
+
+ else: # We are a mesh. get the data.
+ m = ob.getData(mesh=1)
- if not faces: # Make sure there is somthing to write
+ faces = [ f for f in m.faces ]
+ if EXPORT_EDGES:
+ edges = [ ed for ed in m.edges ]
+ else:
+ edges = []
+
+ if not (len(faces)+len(edges)): # Make sure there is somthing to write
continue # dont bother with this mesh.
m.transform(ob.matrix)
# # Crash Blender
#materials = m.getMaterials(1) # 1 == will return None in the list.
- materials = m.getMaterials()
-
+ materials = m.materials
+ materialNames = []
if materials:
- materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken.
+ for mat in materials:
+ if mat: # !=None
+ materialNames.append(mat.name)
+ else:
+ materialNames.append(None)
+ # Cant use LC because some materials are None.
+ # materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken.
else:
materialNames = []
@@ -190,52 +332,62 @@ def save_obj(filename):
# Sort by Material, then images
# so we dont over context switch in the obj file.
- faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth)))
+ if m.faceUV and EXPORT_UV:
+ faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth)))
+ else:
+ faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth)))
# Set the default mat to no material and no image.
contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get.
contextSmooth = None # Will either be true or false, set bad to force initialization switch.
- file.write('o %s_%s\n' % (fixName(ob.name), fixName(m.name))) # Write Object name
+ if EXPORT_BLEN_OBS or EXPORT_GROUP_BY_OB:
+ obnamestring = '%s_%s' % (fixName(ob.name), fixName(ob.getData(1)))
+ if EXPORT_BLEN_OBS:
+ file.write('o %s\n' % obnamestring) # Write Object name
+ else: # if EXPORT_GROUP_BY_OB:
+ file.write('g %s\n' % obnamestring)
+
# Vert
for v in m.verts:
file.write('v %.6f %.6f %.6f\n' % tuple(v.co))
# UV
- if m.hasFaceUV():
+ if m.faceUV and EXPORT_UV:
for f in faces:
for uvKey in f.uv:
+ uvKey = tuple(uvKey)
if not globalUVCoords.has_key(uvKey):
globalUVCoords[uvKey] = totuvco
totuvco +=1
file.write('vt %.6f %.6f 0.0\n' % uvKey)
# NORMAL, Smooth/Non smoothed.
-
- for f in faces:
- if f.smooth:
- for v in f.v:
- noKey = tuple(v.no)
+ if EXPORT_NORMALS:
+ for f in faces:
+ if f.smooth:
+ for v in f.v:
+ noKey = tuple(v.no)
+ if not globalNormals.has_key( noKey ):
+ globalNormals[noKey] = totno
+ totno +=1
+ file.write('vn %.6f %.6f %.6f\n' % noKey)
+ else:
+ # Hard, 1 normal from the face.
+ noKey = tuple(f.no)
if not globalNormals.has_key( noKey ):
globalNormals[noKey] = totno
totno +=1
file.write('vn %.6f %.6f %.6f\n' % noKey)
- else:
- # Hard, 1 normal from the face.
- noKey = tuple(f.no)
- if not globalNormals.has_key( noKey ):
- globalNormals[noKey] = totno
- totno +=1
- file.write('vn %.6f %.6f %.6f\n' % noKey)
uvIdx = 0
for f in faces:
# MAKE KEY
- if f.image: # Object is always true.
+ if EXPORT_UV and m.faceUV and f.image: # Object is always true.
key = materialNames[f.mat], f.image.name
else:
key = materialNames[f.mat], None # No image, use None instead.
@@ -243,31 +395,34 @@ def save_obj(filename):
# CHECK FOR CONTEXT SWITCH
if key == contextMat:
pass # Context alredy switched, dont do anythoing
- elif key[0] == None and key[1] == None:
- # Write a null material, since we know the context has changed.
- file.write('usemtl (null)\n') # mat, image
-
else:
- try: # Faster to try then 2x dict lookups.
+ if key[0] == None and key[1] == None:
+ # Write a null material, since we know the context has changed.
+ matstring = '(null)'
+ file.write('usemtl (null)\n') # mat, image
- # We have the material, just need to write the context switch,
- file.write('usemtl %s\n' % MTL_DICT[key]) # mat, image
-
- except KeyError:
- # First add to global dict so we can export to mtl
- # Then write mtl
-
- # Make a new names from the mat and image name,
- # converting any spaces to underscores with fixName.
-
- # If none image dont bother adding it to the name
- if key[1] == None:
- tmp_matname = MTL_DICT[key] ='%s' % fixName(key[0])
- file.write('usemtl %s\n' % tmp_matname) # mat, image
+ else:
+ try: # Faster to try then 2x dict lookups.
+ # We have the material, just need to write the context switch,
+ matstring = MTL_DICT[key]
+
+
+ except KeyError:
+ # First add to global dict so we can export to mtl
+ # Then write mtl
- else:
- tmp_matname = MTL_DICT[key] = '%s_%s' % (fixName(key[0]), fixName(key[1]))
- file.write('usemtl %s\n' % tmp_matname) # mat, image
+ # Make a new names from the mat and image name,
+ # converting any spaces to underscores with fixName.
+
+ # If none image dont bother adding it to the name
+ if key[1] == None:
+ matstring = MTL_DICT[key] ='%s' % fixName(key[0])
+ else:
+ matstring = MTL_DICT[key] = '%s_%s' % (fixName(key[0]), fixName(key[1]))
+
+ if EXPORT_GROUP_BY_MAT:
+ file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), matstring) ) # can be mat_image or (null)
+ file.write('usemtl %s\n' % matstring) # can be mat_image or (null)
contextMat = key
@@ -279,57 +434,198 @@ def save_obj(filename):
contextSmooth = f.smooth
file.write('f')
- if m.hasFaceUV():
- if f.smooth: # Smoothed, use vertex normals
- for vi, v in enumerate(f.v):
- file.write( ' %d/%d/%d' % (\
- v.index+totverts,\
- globalUVCoords[ f.uv[vi] ],\
- globalNormals[ tuple(v.no) ])) # vert, uv, normal
- else: # No smoothing, face normals
- no = globalNormals[ tuple(f.no) ]
+ if m.faceUV and EXPORT_UV:
+ if EXPORT_NORMALS:
+ if f.smooth: # Smoothed, use vertex normals
+ for vi, v in enumerate(f.v):
+ file.write( ' %d/%d/%d' % (\
+ v.index+totverts,\
+ globalUVCoords[ tuple(f.uv[vi]) ],\
+ globalNormals[ tuple(v.no) ])) # vert, uv, normal
+ else: # No smoothing, face normals
+ no = globalNormals[ tuple(f.no) ]
+ for vi, v in enumerate(f.v):
+ file.write( ' %d/%d/%d' % (\
+ v.index+totverts,\
+ globalUVCoords[ tuple(f.uv[vi]) ],\
+ no)) # vert, uv, normal
+
+ else: # No Normals
for vi, v in enumerate(f.v):
- file.write( ' %d/%d/%d' % (\
+ file.write( ' %d/%d' % (\
v.index+totverts,\
- globalUVCoords[ f.uv[vi] ],\
- no)) # vert, uv, normal
-
+ globalUVCoords[ tuple(f.uv[vi])])) # vert, uv
+
+
else: # No UV's
- if f.smooth: # Smoothed, use vertex normals
- for v in f.v:
- file.write( ' %d//%d' % (\
- v.index+totverts,\
- globalNormals[ tuple(v.no) ]))
- else: # No smoothing, face normals
- no = globalNormals[ tuple(f.no) ]
+ if EXPORT_NORMALS:
+ if f.smooth: # Smoothed, use vertex normals
+ for v in f.v:
+ file.write( ' %d//%d' % (\
+ v.index+totverts,\
+ globalNormals[ tuple(v.no) ]))
+ else: # No smoothing, face normals
+ no = globalNormals[ tuple(f.no) ]
+ for v in f.v:
+ file.write( ' %d//%d' % (\
+ v.index+totverts,\
+ no))
+ else: # No Normals
for v in f.v:
- file.write( ' %d//%d' % (\
- v.index+totverts,\
- no))
+ file.write( ' %d' % (\
+ v.index+totverts))
file.write('\n')
+ # Write edges.
+ if EXPORT_EDGES:
+ edgeUsers = {}
+ for f in faces:
+ for i in xrange(len(f.v)):
+ faceEdgeVKey = sortPair(f.v[i].index, f.v[i-1].index)
+
+ # We dont realy need to keep count. Just that a face uses it
+ # so dont export.
+ edgeUsers[faceEdgeVKey] = 1
+
+ for ed in edges:
+ edgeVKey = sortPair(ed.v1.index, ed.v2.index)
+ if not edgeUsers.has_key(edgeVKey): # No users? Write the edge.
+ file.write('f %d %d\n' % (edgeVKey[0]+totverts, edgeVKey[1]+totverts))
+
# Make the indicies global rather then per mesh
totverts += len(m.verts)
file.close()
# Now we have all our materials, save them
- save_mtl(mtlfilename)
+ if EXPORT_MTL:
+ write_mtl(mtlfilename)
+ if EXPORT_COPY_IMAGES:
+ dest_dir = filename
+ # Remove chars until we are just the path.
+ while dest_dir and dest_dir[-1] not in '\\/':
+ dest_dir = dest_dir[:-1]
+ if dest_dir:
+ copy_images(dest_dir)
+ else:
+ print '\tError: "%s" could not be used as a base for an image path.' % filename
+
+ print "OBJ Export time: %.2f" % (sys.time() - time1)
+
- print "obj export time: %.2f" % (sys.time() - time1)
-Window.FileSelector(save_obj, 'Export Wavefront OBJ', newFName('obj'))
+def write_ui(filename):
+
+ for s in Window.GetScreenInfo():
+ Window.QHandle(s['id'])
+
+ EXPORT_APPLY_MODIFIERS = Draw.Create(1)
+ EXPORT_TRI = Draw.Create(0)
+ EXPORT_EDGES = Draw.Create(0)
+ EXPORT_NORMALS = Draw.Create(0)
+ EXPORT_UV = Draw.Create(1)
+ EXPORT_MTL = Draw.Create(1)
+ EXPORT_SEL_ONLY = Draw.Create(1)
+ EXPORT_ALL_SCENES = Draw.Create(0)
+ EXPORT_ANIMATION = Draw.Create(0)
+ EXPORT_COPY_IMAGES = Draw.Create(0)
+ EXPORT_BLEN_OBS = Draw.Create(1)
+ EXPORT_GROUP_BY_OB = Draw.Create(0)
+ EXPORT_GROUP_BY_MAT = Draw.Create(0)
+
+
+ # Get USER Options
+ pup_block = [\
+ ('Mesh Options...'),\
+ ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data from each object. May break vert order for morph targets.'),\
+ ('Triangulate', EXPORT_TRI, 'Triangulate quads (Depends on "Apply Modifiers").'),\
+ ('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\
+ ('Normals', EXPORT_NORMALS, 'Export vertex normal data (Ignored on import).'),\
+ ('UVs', EXPORT_UV, 'Export texface UV coords.'),\
+ ('Materials', EXPORT_MTL, 'Write a seperate MTL file with the OBJ.'),\
+ ('Context...'),\
+ ('Selection Only', EXPORT_SEL_ONLY, 'Only export objects in visible selection. Else export whole scene.'),\
+ ('All Scenes', EXPORT_ALL_SCENES, 'Each scene as a seperate OBJ file.'),\
+ ('Animation', EXPORT_ANIMATION, 'Each frame as a numbered OBJ file.'),\
+ ('Copy Images', EXPORT_COPY_IMAGES, 'Copy image files to the export directory, never overwrite.'),\
+ ('Grouping...'),\
+ ('Objects', EXPORT_BLEN_OBS, 'Export blender objects as OBJ objects.'),\
+ ('Object Groups', EXPORT_GROUP_BY_OB, 'Export blender objects as OBJ groups.'),\
+ ('Material Groups', EXPORT_GROUP_BY_MAT, 'Group by materials.'),\
+ ]
+
+ if not Draw.PupBlock('Export...', pup_block):
+ return
+
+ Window.WaitCursor(1)
+
+ EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val
+ EXPORT_TRI = EXPORT_TRI.val
+ EXPORT_EDGES = EXPORT_EDGES.val
+ EXPORT_NORMALS = EXPORT_NORMALS.val
+ EXPORT_UV = EXPORT_UV.val
+ EXPORT_MTL = EXPORT_MTL.val
+ EXPORT_SEL_ONLY = EXPORT_SEL_ONLY.val
+ EXPORT_ALL_SCENES = EXPORT_ALL_SCENES.val
+ EXPORT_ANIMATION = EXPORT_ANIMATION.val
+ EXPORT_COPY_IMAGES = EXPORT_COPY_IMAGES.val
+ EXPORT_BLEN_OBS = EXPORT_BLEN_OBS.val
+ EXPORT_GROUP_BY_OB = EXPORT_GROUP_BY_OB.val
+ EXPORT_GROUP_BY_MAT = EXPORT_GROUP_BY_MAT.val
+
+
+
+ base_name, ext = splitExt(filename)
+ context_name = [base_name, '', '', ext] # basename, scene_name, framenumber, extension
+
+ # Use the options to export the data using write()
+ # def write(filename, objects, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False, EXPORT_APPLY_MODIFIERS=True):
+ orig_scene = Scene.GetCurrent()
+ if EXPORT_ALL_SCENES:
+ export_scenes = Scene.Get()
+ else:
+ export_scenes = [orig_scene]
+
+ # Export all scenes.
+ for scn in export_scenes:
+ scn.makeCurrent() # If alredy current, this is not slow.
+ context = scn.getRenderingContext()
+ orig_frame = Blender.Get('curframe')
+
+ if EXPORT_ALL_SCENES: # Add scene name into the context_name
+ context_name[1] = '_%s' % saneFilechars(scn.name) # WARNING, its possible that this could cause a collision. we could fix if were feeling parranoied.
+
+ # Export an animation?
+ if EXPORT_ANIMATION:
+ scene_frames = range(context.startFrame(), context.endFrame()+1) # up to and including the end frame.
+ else:
+ scene_frames = [orig_frame] # Dont export an animation.
+
+ # Loop through all frames in the scene and export.
+ for frame in scene_frames:
+ if EXPORT_ANIMATION: # Add frame to the filename.
+ context_name[2] = '_%.6d' % frame
+
+ Blender.Set('curframe', frame)
+ if EXPORT_SEL_ONLY:
+ export_objects = Blender.Object.GetSelected() # Export Context
+ else:
+ export_objects = scn.getChildren()
+
+ # EXPORT THE FILE.
+ write(''.join(context_name), export_objects,\
+ EXPORT_TRI, EXPORT_EDGES, EXPORT_NORMALS,\
+ EXPORT_UV, EXPORT_MTL, EXPORT_COPY_IMAGES,\
+ EXPORT_APPLY_MODIFIERS,\
+ EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT)
+
+ Blender.Set('curframe', orig_frame)
+
+ # Restore old active scene.
+ orig_scene.makeCurrent()
+ Window.WaitCursor(0)
-'''
-TIME = sys.time()
-import os
-OBJDIR = '/obj_out/'
-for scn in Scene.Get():
- scn.makeCurrent()
- obj = OBJDIR + scn.name
- print obj
- save_obj(obj)
-print "TOTAL EXPORT TIME: ", sys.time() - TIME
-'''
+if __name__ == '__main__':
+ Window.FileSelector(write_ui, 'Export Wavefront OBJ', sys.makename(ext='.obj'))
diff --git a/release/scripts/obj_import.py b/release/scripts/obj_import.py
index d8788f6d042..f2bcaf853e7 100644
--- a/release/scripts/obj_import.py
+++ b/release/scripts/obj_import.py
@@ -269,8 +269,6 @@ def comprehansiveImageLoad(imagePath, filePath):
break
return img
-
-
# No go.
print '\t\tImage Not Found "%s"' % imagePath
return None
@@ -279,22 +277,6 @@ def comprehansiveImageLoad(imagePath, filePath):
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#==================================================================================#
# This function sets textures defined in .mtl file #
#==================================================================================#
@@ -377,9 +359,7 @@ def load_mtl(dir, mtl_file, meshDict, materialDict):
l = fileLines[lIdx].split()
# Detect a line that will be ignored
- if len(l) == 0:
- pass
- elif l[0] == '#' or len(l) == 0:
+ if len(l) == 0 or l[0].startswith('#'):
pass
elif l[0] == 'newmtl':
currentMat = getMat('_'.join(l[1:]), materialDict) # Material should alredy exist.
@@ -428,30 +408,27 @@ def load_mtl(dir, mtl_file, meshDict, materialDict):
# Returns unique name of object/mesh (preserve overwriting existing meshes) #
#===========================================================================#
def getUniqueName(name):
- newName = name
+ newName = name[:19] # 19 chars is the longest name.
uniqueInt = 0
- while 1:
- try:
- ob = Object.Get(newName)
- # Okay, this is working, so lets make a new name
- newName = '%s.%d' % (name, uniqueInt)
- uniqueInt +=1
- except AttributeError:
- if newName not in NMesh.GetNames():
- return newName
- else:
- newName = '%s.%d' % (name, uniqueInt)
- uniqueInt +=1
+ while newName in getUniqueName.uniqueNames:
+ newName = '%s.%.3i' % (name[:15], uniqueInt)
+ uniqueInt +=1
+ getUniqueName.uniqueNames.append(newName)
+ return newName
+getUniqueName.uniqueNames = []
#==================================================================================#
# This loads data from .obj file #
#==================================================================================#
-def load_obj(file):
+def load_obj(file, IMPORT_MTL=1, IMPORT_EDGES=1, IMPORT_SMOOTH_ALL=0):
print '\nImporting OBJ file: "%s"' % file
time1 = sys.time()
+ getUniqueName.uniqueNames.extend( [ob.name for ob in Object.Get()] )
+ getUniqueName.uniqueNames.extend( NMesh.GetNames() )
+
# Deselect all objects in the scene.
# do this first so we dont have to bother, with objects we import
for ob in Scene.GetCurrent().getChildren():
@@ -467,9 +444,9 @@ def load_obj(file):
DIR = stripFile(file)
tempFile = open(file, 'r')
- fileLines = tempFile.readlines()
+ fileLines = tempFile.readlines()
tempFile.close()
-
+ del tempFile
uvMapList = [] # store tuple uv pairs here
# This dummy vert makes life a whole lot easier-
@@ -489,7 +466,10 @@ def load_obj(file):
currentMat = nullMat # Use this mat.
currentImg = None # Null image is a string, otherwise this should be set to an image object.\
- currentSmooth = False
+ if IMPORT_SMOOTH_ALL:
+ currentSmooth = True
+ else:
+ currentSmooth = False
# Store a list of unnamed names
currentUnnamedGroupIdx = 1
@@ -503,63 +483,36 @@ def load_obj(file):
#==================================================================================#
# Load all verts first (texture verts too) #
#==================================================================================#
- nonVertFileLines = []
- smoothingGroups = {}
- materialDict = {} # Store all imported materials as unique dict, names are key
- lIdx = 0
+
print '\tfile length: %d' % len(fileLines)
- while lIdx < len(fileLines):
- # Ignore vert normals
- if fileLines[lIdx].startswith('vn'):
- lIdx+=1
- continue
-
- # Dont Bother splitting empty or comment lines.
- if len(fileLines[lIdx]) == 0 or\
- fileLines[lIdx][0] == '\n' or\
- fileLines[lIdx][0] == '#':
- pass
-
- else:
- fileLines[lIdx] = fileLines[lIdx].split()
- l = fileLines[lIdx]
-
- # Splitting may
- if len(l) == 0:
- pass
- # Verts
- elif l[0] == 'v':
- vertList.append( NMesh.Vert(float(l[1]), float(l[2]), float(l[3]) ) )
-
- # UV COORDINATE
- elif l[0] == 'vt':
- uvMapList.append( (float(l[1]), float(l[2])) )
-
- # Smoothing groups, make a list of unique.
- elif l[0] == 's':
- if len(l) > 1:
- smoothingGroups['_'.join(l[1:])] = None # Can we assign something more usefull? cant use sets yet
-
- # Keep Smoothing group line
- nonVertFileLines.append(l)
-
- # Smoothing groups, make a list of unique.
- elif l[0] == 'usemtl':
- if len(l) > 1:
- materialDict['_'.join(l[1:])] = None # Can we assign something more usefull? cant use sets yet
-
- # Keep Smoothing group line
- nonVertFileLines.append(l)
-
- else:
- nonVertFileLines.append(l)
- lIdx+=1
-
-
- del fileLines
- fileLines = nonVertFileLines
- del nonVertFileLines
+ # Ignore normals and comments.
+ fileLines = [lsplit for l in fileLines if not l.startswith('vn') if not l.startswith('#') for lsplit in (l.split(),) if lsplit]
+ Vert = NMesh.Vert
+ vertList = [Vert(float(l[1]), float(l[2]), float(l[3]) ) for l in fileLines if l[0] == 'v']
+ uvMapList = [(float(l[1]), float(l[2])) for l in fileLines if l[0] == 'vt']
+ smoothingGroups = dict([('_'.join(l[1:]), None) for l in fileLines if l[0] == 's' ])
+ materialDict = dict([('_'.join(l[1:]), None) for l in fileLines if l[0] == 'usemtl']) # Store all imported materials as unique dict, names are key
+ print '\tvert:%i texverts:%i smoothgroups:%i materials:%s' % (len(vertList), len(uvMapList), len(smoothingGroups), len(materialDict))
+
+ # Replace filelines, Excluding v excludes "v ", "vn " and "vt "
+
+ # Remove any variables we may have created.
+ try: del _dummy
+ except: pass
+ try: del _x
+ except: pass
+ try: del _y
+ except: pass
+ try: del _z
+ except: pass
+ try: del lsplit
+ except: pass
+ del Vert
+
+ # With negative values this is used a lot. make faster access.
+ len_uvMapList = len(uvMapList)
+ len_vertList = len(vertList)
# Only want unique keys anyway
smoothingGroups['(null)'] = None # Make sure we have at least 1.
@@ -572,7 +525,7 @@ def load_obj(file):
# Make a list of all unused vert indicies that we can copy from
- VERT_USED_LIST = [0]*len(vertList)
+ VERT_USED_LIST = [0]*len_vertList
# Here we store a boolean list of which verts are used or not
# no we know weather to add them to the current mesh
@@ -584,9 +537,9 @@ def load_obj(file):
# We ignore it when naming the object.
currentObjectName = 'unnamed_obj_0' # If we cant get one, use this
- meshDict = {} # The 3 variables below are stored in a tuple within this dict for each mesh
+ #meshDict = {} # The 3 variables below are stored in a tuple within this dict for each mesh
currentMesh = NMesh.GetRaw() # The NMesh representation of the OBJ group/Object
- currentUsedVertList = {} # A Dict of smooth groups, each smooth group has a list of used verts and they are generated on demand so as to save memory.
+ #currentUsedVertList = {} # A Dict of smooth groups, each smooth group has a list of used verts and they are generated on demand so as to save memory.
currentMaterialMeshMapping = {} # Used to store material indicies so we dont have to search the mesh for materials every time.
# Every mesh has a null smooth group, this is used if there are no smooth groups in the OBJ file.
@@ -595,14 +548,13 @@ def load_obj(file):
# For direct accsess to the Current Meshes, Current Smooth Groups- Used verts.
# This is of course context based and changes on the fly.
- currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
-
# Set the initial '(null)' Smooth group, every mesh has one.
- currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup
+ currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
+ currentUsedVertList= {currentSmoothGroup: currentUsedVertListSmoothGroup }
# 0:NMesh, 1:SmoothGroups[UsedVerts[0,0,0,0]], 2:materialMapping['matname':matIndexForThisNMesh]
- meshDict[currentObjectName] = (currentMesh, currentUsedVertList, currentMaterialMeshMapping)
+ meshDict = {currentObjectName: (currentMesh, currentUsedVertList, currentMaterialMeshMapping) }
# Only show the bad uv error once
badObjUvs = 0
@@ -611,20 +563,23 @@ def load_obj(file):
#currentMesh.verts.append(vertList[0]) # So we can sync with OBJ indicies where 1 is the first item.
- if len(uvMapList) > 1:
+ if len_uvMapList > 1:
currentMesh.hasFaceUV(1) # Turn UV's on if we have ANY texture coords in this obj file.
#==================================================================================#
# Load all faces into objects, main loop #
#==================================================================================#
- lIdx = 0
+ #lIdx = 0
# Face and Object loading LOOP
- while lIdx < len(fileLines):
- l = fileLines[lIdx]
-
+ #while lIdx < len(fileLines):
+ # l = fileLines[lIdx]
+ #for lIdx
+ for l in fileLines:
+ if len(l) == 0:
+ continue
# FACE
- if l[0] == 'f':
+ elif l[0] == 'f':
# Make a face with the correct material.
# Add material to mesh
@@ -646,15 +601,19 @@ def load_obj(file):
vtIdxLs = []
- fHasUV = len(uvMapList) # Assume the face has a UV until it sho it dosent, if there are no UV coords then this will start as 0.
+ fHasUV = len_uvMapList # Assume the face has a UV until it sho it dosent, if there are no UV coords then this will start as 0.
for v in l[1:]:
# OBJ files can have // or / to seperate vert/texVert/normal
# this is a bit of a pain but we must deal with it.
objVert = v.split('/')
# Vert Index - OBJ supports negative index assignment (like python)
+ index = int(objVert[0])-1
+ # Account for negative indicies.
+ if index < 0:
+ index = len_vertList+index+1
- vIdxLs.append(int(objVert[0])-1)
+ vIdxLs.append(index)
if fHasUV:
# UV
index = 0 # Dummy var
@@ -662,15 +621,17 @@ def load_obj(file):
index = vIdxLs[-1]
elif objVert[1]: # != '' # Its possible that theres no texture vert just he vert and normal eg 1//2
index = int(objVert[1])-1
-
- if len(uvMapList) > index:
+ if index < 0:
+ index = len_uvMapList+index+1
+
+ if len_uvMapList > index:
vtIdxLs.append(index) # Seperate UV coords
else:
# BAD FILE, I have found this so I account for it.
# INVALID UV COORD
# Could ignore this- only happens with 1 in 1000 files.
badObjFaceTexCo +=1
- vtIdxLs.append(0)
+ vtIdxLs.append(1)
fHasUV = 0
@@ -678,12 +639,26 @@ def load_obj(file):
# The OBJ file would have to be corrupt or badly written for thi to happen
# but account for it anyway.
if len(vtIdxLs) > 0:
- if vtIdxLs[-1] > len(uvMapList):
+ if vtIdxLs[-1] > len_uvMapList:
fHasUV = 0
badObjUvs +=1 # ERROR, Cont
# Quads only, we could import quads using the method below but it polite to import a quad as a quad.
- if len(vIdxLs) == 4:
+ #print lIdx, len(vIdxLs), len(currentUsedVertListSmoothGroup)
+ #print fileLines[lIdx]
+ if len(vIdxLs) == 2:
+ if IMPORT_EDGES:
+ # Edge
+ for i in (0,1):
+ if currentUsedVertListSmoothGroup[vIdxLs[i]] == 0:
+ faceQuadVList[i] = vertList[vIdxLs[i]]
+ currentMesh.verts.append(faceQuadVList[i])
+ currentUsedVertListSmoothGroup[vIdxLs[i]] = len(currentMesh.verts)-1
+ else:
+ faceQuadVList[i] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[i]]]
+
+ currentMesh.addEdge(faceQuadVList[0], faceQuadVList[1])
+ elif len(vIdxLs) == 4:
# Have found some files where wach face references the same vert
# - This causes a bug and stopts the import so lets check here
@@ -751,22 +726,20 @@ def load_obj(file):
if len(l) == 1:
currentSmooth = True
currentSmoothGroup = '(null)'
- try:
- currentUsedVertListSmoothGroup = currentUsedVertList[currentSmoothGroup]
- except KeyError:
- currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
- currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup
-
else:
- if l[1] == 'off':
- currentSmooth = False
+ if l[1] == 'off': # We all have a null group so dont need to try, will try anyway to avoid code duplication.
+ if not IMPORT_SMOOTH_ALL:
+ currentSmooth = False
currentSmoothGroup = '(null)'
- # We all have a null group so dont need to try
- currentUsedVertListSmoothGroup = currentUsedVertList['(null)']
else:
currentSmooth = True
currentSmoothGroup = '_'.join(l[1:])
-
+ try:
+ currentUsedVertListSmoothGroup = currentUsedVertList[currentSmoothGroup]
+ except KeyError:
+ currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
+
+
# OBJECT / GROUP
elif l[0] == 'o' or l[0] == 'g':
@@ -783,10 +756,10 @@ def load_obj(file):
else: # No name given
# Make a new empty name
if l[0] == 'g': # Make a blank group name
- currentObjectName = 'unnamed_grp_%d' % currentUnnamedGroupIdx
+ currentObjectName = 'unnamed_grp_%.4d' % currentUnnamedGroupIdx
currentUnnamedGroupIdx +=1
else: # is an object.
- currentObjectName = 'unnamed_ob_%d' % currentUnnamedObjectIdx
+ currentObjectName = 'unnamed_ob_%.4d' % currentUnnamedObjectIdx
currentUnnamedObjectIdx +=1
@@ -801,11 +774,10 @@ def load_obj(file):
currentUsedVertList = {}
# Sg is a string
- currentSmoothGroup = '(null)'
- currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
- currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup
- currentMaterialMeshMapping = {}
+ ########currentSmoothGroup = '(null)' # From examplesm changing the g/o shouldent change the smooth group.
+ currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
+ currentMaterialMeshMapping = {}
meshDict[currentObjectName] = (currentMesh, currentUsedVertList, currentMaterialMeshMapping)
currentMesh.hasFaceUV(1)
contextMeshMatIdx = -1
@@ -822,8 +794,13 @@ def load_obj(file):
contextMeshMatIdx -1
# For new meshes switch smoothing groups to null
- currentSmoothGroup = '(null)'
- currentUsedVertListSmoothGroup = currentUsedVertList[currentSmoothGroup]
+ ########currentSmoothGroup = '(null)' # From examplesm changing the g/o shouldent change the smooth group.
+ try:
+ currentUsedVertListSmoothGroup = currentUsedVertList[currentSmoothGroup]
+ except:
+ currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
+
+
# MATERIAL
elif l[0] == 'usemtl':
@@ -859,11 +836,12 @@ def load_obj(file):
# MATERIAL FILE
elif l[0] == 'mtllib':
mtl_fileName.append(' '.join(l[1:]) ) # SHOULD SUPPORT MULTIPLE MTL?
- lIdx+=1
+ #lIdx+=1
# Applies material properties to materials alredy on the mesh as well as Textures.
- for mtl in mtl_fileName:
- load_mtl(DIR, mtl, meshDict, materialDict)
+ if IMPORT_MTL:
+ for mtl in mtl_fileName:
+ load_mtl(DIR, mtl, meshDict, materialDict)
importedObjects = []
@@ -894,45 +872,78 @@ def load_obj(file):
print "obj import time: ", sys.time() - time1
+
+def load_obj_ui(file):
-# Batch directory loading.
-def load_obj_dir(obj_dir):
+ IMPORT_MTL = Draw.Create(1)
+ IMPORT_DIR = Draw.Create(0)
+ IMPORT_NEW_SCENE = Draw.Create(0)
+ IMPORT_EDGES = Draw.Create(1)
+ IMPORT_SMOOTH_ALL = Draw.Create(0)
- # Strip file
- obj_dir = stripFile(obj_dir)
- time = sys.time()
- objFiles = [f for f in os.listdir(obj_dir) if f.lower().endswith('obj')]
+ # Get USER Options
+ pup_block = [\
+ ('Material (*.mtl)', IMPORT_MTL, 'Imports material settings and images from the obj\'s .mtl file'),\
+ ('All *.obj\'s in dir', IMPORT_DIR, 'Import all obj files in this dir (avoid overlapping data with "Create scene")'),\
+ ('Create scene', IMPORT_NEW_SCENE, 'Imports each obj into its own scene, named from the file'),\
+ 'Geometry...',\
+ ('Edges', IMPORT_EDGES, 'Import faces with 2 verts as in edge'),\
+ ('Smooths all faces', IMPORT_SMOOTH_ALL, 'Smooth all faces even if they are not in a smoothing group'),\
+ ]
+
+ if not os:
+ pup_block.pop(1) # Make sure this is the IMPORT_DIR option that requires OS
+ if not Draw.PupBlock('Import...', pup_block):
+ return
+
+ Window.WaitCursor(1)
Window.DrawProgressBar(0, '')
+ time = sys.time()
+
+ IMPORT_MTL = IMPORT_MTL.val
+ IMPORT_DIR = IMPORT_DIR.val
+ IMPORT_NEW_SCENE = IMPORT_NEW_SCENE.val
+ IMPORT_EDGES = IMPORT_EDGES.val
+ IMPORT_SMOOTH_ALL = IMPORT_SMOOTH_ALL.val
+
+ #orig_scene = Scene.GetCurrent()
+
+ obj_dir = stripFile(file)
+ if IMPORT_DIR:
+ obj_files = [(obj_dir,f) for f in os.listdir(obj_dir) if f.lower().endswith('obj')]
+ else:
+ obj_files = [(obj_dir,stripPath(file))]
+
+ obj_len = len(obj_files)
count = 0
- obj_len = len(objFiles)
- for obj in objFiles:
- count+=1
-
- newScn = Scene.New(obj)
- newScn.makeCurrent()
-
- Window.DrawProgressBar((float(count)/obj_len) - 0.01, '%s: %i of %i' % (obj, count, obj_len))
-
- load_obj(obj_dir + obj)
-
+ for d, f in obj_files:
+ count+= 1
+ if not sys.exists(d+f):
+ print 'Error: "%s%s" does not exist' % (d,f)
+ else:
+ if IMPORT_NEW_SCENE:
+ scn = Scene.New('.'.join(f.split('.')[0:-1]))
+ scn.makeCurrent()
+
+
+ Window.DrawProgressBar((float(count)/obj_len) - 0.01, '%s: %i of %i' % (f, count, obj_len))
+ load_obj(d+f, IMPORT_MTL, IMPORT_EDGES, IMPORT_SMOOTH_ALL)
+
+
+ #orig_scene.makeCurrent() # We can leave them in there new scene.
Window.DrawProgressBar(1, '')
- print 'Total obj import "%s" dir: %.2f' % (obj_dir, sys.time() - time)
-
+ Window.WaitCursor(0)
+
+ if count > 1:
+ print 'Total obj import "%s" dir: %.2f' % (obj_dir, sys.time() - time)
+
def main():
- TEXT_IMPORT = 'Import a Wavefront OBJ'
- TEXT_BATCH_IMPORT = 'Import *.obj to Scenes'
-
- if Window.GetKeyQualifiers() & Window.Qual.SHIFT:
- if not os:
- Draw.PupMenu('Module "os" not found, needed for batch load, using normal selector.')
- Window.FileSelector(load_obj, TEXT_IMPORT)
- else:
- Window.FileSelector(load_obj_dir, TEXT_BATCH_IMPORT)
- else:
- Window.FileSelector(load_obj, TEXT_IMPORT)
+ Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ')
+
+
if __name__ == '__main__':
- main()
+ main() \ No newline at end of file
diff --git a/release/scripts/off_export.py b/release/scripts/off_export.py
index 8465720478f..53bd9ef6a6f 100644
--- a/release/scripts/off_export.py
+++ b/release/scripts/off_export.py
@@ -28,17 +28,34 @@ Notes:<br>
Only exports a single selected mesh.
"""
+# $Id:
+#
# +---------------------------------------------------------+
# | Copyright (c) 2002 Anthony D'Agostino |
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | February 3, 2001 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Object File Format (*.off) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
#import time
diff --git a/release/scripts/off_import.py b/release/scripts/off_import.py
index cbaab483154..452a91ffc5f 100644
--- a/release/scripts/off_import.py
+++ b/release/scripts/off_import.py
@@ -29,18 +29,34 @@ Notes:<br>
UV Coordinate support has been added.
"""
-
+# $Id:
+#
# +---------------------------------------------------------+
# | Copyright (c) 2002 Anthony D'Agostino |
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | February 3, 2001 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Object File Format (*.off) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
#import time
diff --git a/release/scripts/radiosity_export.py b/release/scripts/radiosity_export.py
index 4f7766c3dd5..43ec7d9838c 100644
--- a/release/scripts/radiosity_export.py
+++ b/release/scripts/radiosity_export.py
@@ -46,12 +46,27 @@ specular highlights to the vertex colors.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | April 11, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Radiosity File Format (*.radio) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
#import time
diff --git a/release/scripts/radiosity_import.py b/release/scripts/radiosity_import.py
index 704a87becf5..d2d45568b99 100644
--- a/release/scripts/radiosity_import.py
+++ b/release/scripts/radiosity_import.py
@@ -31,12 +31,27 @@ file to open.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | April 11, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Radiosity File Format (*.radio) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
#import time
diff --git a/release/scripts/raw_export.py b/release/scripts/raw_export.py
index f52f0404e19..b8469adc5f4 100644
--- a/release/scripts/raw_export.py
+++ b/release/scripts/raw_export.py
@@ -25,7 +25,6 @@ Usage:<br>
Select meshes to be exported and run this script from "File->Export" menu.
"""
-
# $Id$
#
# +---------------------------------------------------------+
@@ -33,12 +32,27 @@ Usage:<br>
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | April 28, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write RAW Triangle File Format (*.raw) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
import sys
#import time
diff --git a/release/scripts/raw_import.py b/release/scripts/raw_import.py
index c793791664f..a452bb4b40e 100644
--- a/release/scripts/raw_import.py
+++ b/release/scripts/raw_import.py
@@ -38,12 +38,27 @@ tolerance.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | April 28, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write RAW Triangle File Format (*.raw) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
#import time
diff --git a/release/scripts/save_theme.py b/release/scripts/save_theme.py
index 79205c0d478..936c12a46f8 100644
--- a/release/scripts/save_theme.py
+++ b/release/scripts/save_theme.py
@@ -2,14 +2,14 @@
"""
Name: 'Save Current Theme...'
-Blender: 237
+Blender: 240
Group: 'Export'
-Tooltip: 'Save current theme as a bpython script'
+Tooltip: 'Save current theme as a BPython script'
"""
__author__ = "Willian P. Germano"
__url__ = ("blender", "elysiun")
-__version__ = "2.37 2005/06/06"
+__version__ = "2.41 2006/01/16"
__bpydoc__ = """\
This script saves the current Theme in Blender as a Blender Python script.
@@ -39,15 +39,32 @@ some information on it before sharing it with others.
# $Id$
#
# --------------------------------------------------------------------------
-# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
+# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig com br
# --------------------------------------------------------------------------
-# Released under the Blender Artistic License (BAL):
-# http://download.blender.org/documentation/html/x21254.html
-#
# The scripts generated by this script are put under Public Domain by
# default, but you are free to edit the ones you generate with this script
# and change their license to another one of your choice.
# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2005: Willian P. Germano, wgermano _at_ ig.com.br
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
import Blender
from Blender.Window import Theme, FileSelector
@@ -70,13 +87,13 @@ def write_theme(filename):
# \"\"\"
# Name: '%s'
-# Blender: 237
+# Blender: 241
# Group: 'Themes'
# Tooltip: 'Change current theme'
# \"\"\"
__%s__ = "????"
-__%s__ = "2.37"
+__%s__ = "2.41"
__%s__ = ["blender"]
__%s__ = \"\"\"\\
You can edit this section to write something about your script that can
diff --git a/release/scripts/skin.py b/release/scripts/skin.py
index adf49b1af7b..c319de31915 100644
--- a/release/scripts/skin.py
+++ b/release/scripts/skin.py
@@ -483,7 +483,9 @@ def main():
if choice == 1 and len(edgeOrderedList) > 2: # Loop
skin2EdgeLoops(edgeOrderedList[0], edgeOrderedList[-1], me, ob, 0)
+ print '\nArray done in %.4f sec.' % (sys.time()-time1)
me.update(1, 1, 0)
if is_editmode: Window.EditMode(1)
-main()
+if __name__ == '__main__':
+ main()
diff --git a/release/scripts/slp_import.py b/release/scripts/slp_import.py
index 246f84ec02b..4944c34045d 100644
--- a/release/scripts/slp_import.py
+++ b/release/scripts/slp_import.py
@@ -36,12 +36,27 @@ tolerance.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | May 3, 2004 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write SLP Triangle File Format (*.slp) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
#import time
diff --git a/release/scripts/tex2uvbaker.py b/release/scripts/tex2uvbaker.py
index 0324d9c0290..2a25a3d8516 100644
--- a/release/scripts/tex2uvbaker.py
+++ b/release/scripts/tex2uvbaker.py
@@ -2,7 +2,7 @@
""" Registration info for Blender menus:
Name: 'Texture Baker'
-Blender: 236
+Blender: 239
Group: 'UV'
Tooltip: 'Procedural to uvmapped texture baker'
"""
@@ -11,7 +11,7 @@ __author__ = "Jean-Michel Soler (jms)"
__url__ = ("blender", "elysiun",
"Official Page, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_mesh3d2uv2d_en.htm",
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
-__version__ = "0.3.1 2005/10/21"
+__version__ = "0.3.2 2005/12/28"
__bpydoc__ = """\
This script "bakes" Blender procedural materials (including textures): it saves
@@ -49,6 +49,10 @@ Notes:<br>
#
# Released under Blender Artistic Licence
#
+# 0.3.2
+# blender 2.40 update to deal with the new shape
+# key system .
+#
# 0.3.1
# stupid bug correction
#
@@ -433,6 +437,85 @@ def REST_Shadeless(SHADEDict):
# release : 0.2.6 , 2005/05/29 , end
#-----------------------------------
+
+#-----------------------------------
+# release : 0.3.2 , 2005/12/28 , 13h00
+#-----------------------------------
+def Blender240update(MESH2,FRAME):
+ """
+# ---------------------------
+# Function Blender240update
+#
+# IN : MESH2 a mesh data bloc
+# FRAME , the animation frame limit
+#
+# ADD : an ipo curve to the shape key
+# named "Key 1"
+#
+# OUT : nothing
+# ---------------------------
+ """
+ # ---------------------------
+ # recuperation des clef de morphing pour ce mesh
+ # ---------------------------
+ key = MESH2.getKey()
+ # ---------------------------
+ # recuperation de l'Ipo
+ # ---------------------------
+ ipo = key.ipo
+ # ---------------------------
+ # si l'ipo n'existe pas on la cree
+ # ---------------------------
+ if ipo == None:
+ noipo = Blender.Ipo.New("Key","keyipo")
+ key.ipo = noipo
+ # ---------------------------
+ # raccourci de l'expression
+ # ---------------------------
+ ipo = key.ipo
+ # ---------------------------
+ # identification de la clef de morphing
+ # ---------------------------
+ keyidentity = "Key 1"
+ # ---------------------------
+ # recuperation de la courbe correspondante
+ # c'est toujours la courbe 0
+ # ---------------------------
+ ipocurve = ipo.getCurve(0)
+ # ---------------------------
+ # si la courbe n'existe pas (normalement, elle n'existe pas mais
+ # on gère le risque pour faciliter une eventuelle récupération de
+ # cette fonction dans un autre script ou pour les cas , certe peu
+ # probable, ou blender viendrait a etre modifie pour les ajouter
+ # automatiquement ) on la cree ...
+ # ---------------------------
+ if ipocurve == None:
+ ipocurve = ipo.addCurve(keyidentity)
+ # ---------------------------
+ # On applique l'attribut d'inetrpolation qui permet d'avoir
+ # une ligne droite
+ # ---------------------------
+ ipocurve.setInterpolation("Linear")
+ # ---------------------------
+ # On retire tous les sommets qui pourraient se trouver sur la
+ # courbe (dans l'état actuel, cette opération est une sécurité
+ # superflue ) .
+ # ---------------------------
+ while len(ipocurve.getPoints()) > 0:
+ ipocurve.delBezier(0)
+ ipocurve.recalc()
+ # ---------------------------
+ # On ajouter les sommets necessaires ...
+ # ---------------------------
+ ipocurve.addBezier((-1,1))
+ # ---------------------------
+ # ... ce dernire n'est peut-être pas absolument obligatoire .
+ # ---------------------------
+ ipocurve.addBezier((FRAME+1,1))
+#-----------------------------------
+# release : 0.3.2 , 2005/12/28 , end
+#-----------------------------------
+
def Mesh2UVCoord (LIMIT):
"""
# ---------------------------
@@ -444,7 +527,7 @@ def Mesh2UVCoord (LIMIT):
"""
global PUTRAW, FRAME, SCENELAYERS
- try :
+ try:
MESH3D = Object.GetSelected()[0]
if MESH3D.getType() == 'Mesh':
MESH = MESH3D.getData()
@@ -454,7 +537,8 @@ def Mesh2UVCoord (LIMIT):
CurSCENE=Blender.Scene.getCurrent()
except:
NewOBJECT, CurSCENE = GET_newobject('Mesh','UVOBJECT')
- MESH2 = NewOBJECT.getData()
+ MESH2 = NewOBJECT.getData()
+ MESH2.edges=[]
NewOBJECT.layers=[RENDERLAYER]
MESH2.faces=[]
@@ -485,13 +569,12 @@ def Mesh2UVCoord (LIMIT):
NewOBJECT.setLocation (OBJPOS, OBJPOS, 0.0)
NewOBJECT.setEuler (0.0, 0.0, 0.0)
-
MESH2.removeAllKeys()
MESH2.update()
MESH2.insertKey (1, 'absolute')
MESH2.update()
-
+
for f in MESH2.faces:
for v in f.v:
for n in [0,1]:
@@ -506,6 +589,14 @@ def Mesh2UVCoord (LIMIT):
MESH2.insertKey (FRAME, 'absolute')
MESH2.update()
+ #-----------------------------------
+ # release : 0.3.2 , 2005/12/28 , 13h00
+ #-----------------------------------
+ Blender240update(MESH2,FRAME)
+ #-----------------------------------
+ # release : 0.3.2 , 2005/12/28 , end
+ #-----------------------------------
+
imagename = 'uvtext'
name = "CHANGE IMAGE NAME ? %t | Replace it | No replace | Script help"
@@ -551,4 +642,4 @@ def Mesh2UVCoord (LIMIT):
result = Draw.PupMenu(name)
print 'problem : no object selected or not mesh'
-Mesh2UVCoord(LIMIT)
+Mesh2UVCoord(LIMIT) \ No newline at end of file
diff --git a/release/scripts/truespace_export.py b/release/scripts/truespace_export.py
index af9aa2a5a23..a9f1688ae46 100644
--- a/release/scripts/truespace_export.py
+++ b/release/scripts/truespace_export.py
@@ -49,7 +49,6 @@ For Cameras: The matrix here gets a little confusing, and I'm not sure of
how to handle it.
"""
-
# $Id$
#
# +---------------------------------------------------------+
@@ -57,12 +56,27 @@ how to handle it.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | June 12, 2001 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Caligari trueSpace File Format (*.cob) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
import struct, os, cStringIO, time
diff --git a/release/scripts/truespace_import.py b/release/scripts/truespace_import.py
index 40326612f3f..ff655e1614c 100644
--- a/release/scripts/truespace_import.py
+++ b/release/scripts/truespace_import.py
@@ -62,12 +62,27 @@ how to handle it.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | June 12, 2001 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Caligari trueSpace File Format (*.cob) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
import struct, chunk, os, cStringIO, time
diff --git a/release/scripts/uv_export.py b/release/scripts/uv_export.py
index 78d173d88fb..bf02c323f61 100644
--- a/release/scripts/uv_export.py
+++ b/release/scripts/uv_export.py
@@ -9,7 +9,7 @@ Tooltip: 'Export the UV face layout of the selected object to a .TGA file'
__author__ = "Martin 'theeth' Poirier"
__url__ = ("http://www.blender.org", "http://www.elysiun.com")
-__version__ = "1.3a"
+__version__ = "1.4"
__bpydoc__ = """\
This script exports the UV face layout of the selected mesh object to
@@ -26,8 +26,9 @@ There are more options to configure, like setting export path, if image should
use object's name and more.
Notes:<br>
- Jean-Michel Soler (jms) wrote TGA functions used by this script.
- Zaz added the default path code and Selected Face option.
+ Jean-Michel Soler (jms) wrote TGA functions used by this script.<br>
+ Zaz added the default path code and Selected Face option.<br>
+ Macouno fixed a rounding error in the step calculations<br>
"""
@@ -62,19 +63,22 @@ Notes:<br>
# Communicate problems and errors on:
# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
# --------------------------
-# Version 1.1
+# Version 1.1
# Clear a bug that crashed the script when UV coords overlapped in the same faces
# --------------------------
-# Version 1.2
+# Version 1.2
# Now with option to use the object's name as filename
# --------------------------
-# Version 1.3 Updates by Zaz from Elysiun.com
+# Version 1.3 Updates by Zaz from Elysiun.com
# Default path is now the directory of the last saved .blend
# New options: Work on selected face only & Scale image when face wraps
# --------------------------
-# Version 1.3a
+# Version 1.3a
# Corrected a minor typo and added the tga extension to both export call
# --------------------------
+# Version 1.4 Updates by Macouno from Elysiun.com
+# Fixed rounding error that can cause breaks in lines.
+# --------------------------
import Blender
from math import *
@@ -134,42 +138,42 @@ def bevent(evt):
UV_Export(bSize.val, bWSize.val, bFile.val + ".tga")
def Buffer(height=16, width=16, profondeur=3,rvb=255 ):
- """
- reserve l'espace memoire necessaire
- """
- p=[rvb]
- b=p*height*width*profondeur
- return b
+ """
+ reserve l'espace memoire necessaire
+ """
+ p=[rvb]
+ b=p*height*width*profondeur
+ return b
def write_tgafile(loc2,bitmap,width,height,profondeur):
- f=open(loc2,'wb')
+ f=open(loc2,'wb')
- Origine_en_haut_a_gauche=32
- Origine_en_bas_a_gauche=0
+ Origine_en_haut_a_gauche=32
+ Origine_en_bas_a_gauche=0
- Data_Type_2=2
- RVB=profondeur*8
- RVBA=32
- entete0=[]
- for t in range(18):
- entete0.append(chr(0))
+ Data_Type_2=2
+ RVB=profondeur*8
+ RVBA=32
+ entete0=[]
+ for t in range(18):
+ entete0.append(chr(0))
- entete0[2]=chr(Data_Type_2)
- entete0[13]=chr(width/256)
- entete0[12]=chr(width % 256)
- entete0[15]=chr(height/256)
- entete0[14]=chr(height % 256)
- entete0[16]=chr(RVB)
- entete0[17]=chr(Origine_en_bas_a_gauche)
+ entete0[2]=chr(Data_Type_2)
+ entete0[13]=chr(width/256)
+ entete0[12]=chr(width % 256)
+ entete0[15]=chr(height/256)
+ entete0[14]=chr(height % 256)
+ entete0[16]=chr(RVB)
+ entete0[17]=chr(Origine_en_bas_a_gauche)
- #Origine_en_haut_a_gauche
+ #Origine_en_haut_a_gauche
- for t in entete0:
- f.write(t)
+ for t in entete0:
+ f.write(t)
- for t in bitmap:
- f.write(chr(t))
- f.close()
+ for t in bitmap:
+ f.write(chr(t))
+ f.close()
def UV_Export(size, wsize, file):
obj = Blender.Object.GetSelected()
@@ -238,11 +242,12 @@ def UV_Export(size, wsize, file):
co2 = f[index + 1]
else:
co2 = f[0]
- step = int(size*sqrt((co1[0]-co2[0])**2+(co1[1]-co2[1])**2))
+
+ step = int(ceil(size*sqrt((co1[0]-co2[0])**2+(co1[1]-co2[1])**2)))
if step:
- for t in range(step + 1):
- x = int((co1[0] + t*(co2[0]-co1[0])/step) * size)
- y = int((co1[1] + t*(co2[1]-co1[1])/step) * size)
+ for t in range(step):
+ x = int(floor((co1[0] + t*(co2[0]-co1[0])/step) * size))
+ y = int(floor((co1[1] + t*(co2[1]-co1[1])/step) * size))
if bWrap.val:
x = x % wrapSize
@@ -251,16 +256,17 @@ def UV_Export(size, wsize, file):
x = int ((x - minx) * scale)
y = int ((y - miny) * scale)
- co = x * 3 + y * 3 * size
+ co = x * 3 + y * 3 * size;
+
img[co] = 0
img[co+1] = 0
- img[co+2] = 255
+ img[co+2] = 0
if wsize > 1:
for x in range(-1*wsize + 1,wsize):
for y in range(-1*wsize,wsize):
img[co + 3 * x + y * 3 * size] = 0
img[co + 3 * x + y * 3 * size +1] = 0
- img[co + 3 * x + y * 3 * size +2] = 255
+ img[co + 3 * x + y * 3 * size +2] = 0
for v in f:
x = int(v[0] * size)
@@ -276,8 +282,7 @@ def UV_Export(size, wsize, file):
co = x * 3 + y * 3 * size
img[co] = 0
img[co+1] = 0
- img[co+2] = 0
-
+ img[co+2] = 255
write_tgafile(file,img,size,size,3)
diff --git a/release/scripts/videoscape_export.py b/release/scripts/videoscape_export.py
index 37905239496..49160e8b48d 100644
--- a/release/scripts/videoscape_export.py
+++ b/release/scripts/videoscape_export.py
@@ -43,7 +43,6 @@ specular highlights to the vertex colors.
5. The Videoscape format also allows vertex colors to be specified.
"""
-
# $Id$
#
# +---------------------------------------------------------+
@@ -51,12 +50,27 @@ specular highlights to the vertex colors.
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | June 5, 2001 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Write Videoscape File Format (*.obj NOT WAVEFRONT OBJ) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
#import time
diff --git a/release/scripts/vrml97_export.py b/release/scripts/vrml97_export.py
index 3b7751c5fec..41201d45315 100644
--- a/release/scripts/vrml97_export.py
+++ b/release/scripts/vrml97_export.py
@@ -4,6 +4,7 @@ Name: 'VRML97 (.wrl)...'
Blender: 235
Group: 'Export'
Submenu: 'All Objects...' all
+Submenu: 'All Objects compressed...' comp
Submenu: 'Selected Objects...' selected
Tooltip: 'Export to VRML97 file (.wrl)'
"""
@@ -12,8 +13,8 @@ __author__ = ("Rick Kimball", "Ken Miller", "Steve Matthews", "Bart")
__url__ = ["blender", "elysiun",
"Author's (Rick) homepage, http://kimballsoftware.com/blender",
"Author's (Bart) homepage, http://www.neeneenee.de/vrml"]
-__version__ = "2005/06/03"
-
+__email__ = ["Bart, bart:neeneenee*de"]
+__version__ = "2006/01/17"
__bpydoc__ = """\
This script exports to VRML97 format.
@@ -37,8 +38,6 @@ for each texture);<br>
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
-# Copyright (C) 2003,2004: Rick Kimball rick@vrmlworld.net
-#
# 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
@@ -61,7 +60,7 @@ for each texture);<br>
####################################
import Blender
-from Blender import Object, NMesh, Lamp, Draw, BGL, Image, Text
+from Blender import Object, NMesh, Lamp, Draw, BGL, Image, Text, sys, Mathutils
from Blender.Scene import Render
try:
from os.path import exists, join
@@ -80,15 +79,9 @@ world = Blender.World.Get()
worldmat = Blender.Texture.Get()
filename = Blender.Get('filename')
_safeOverwrite = True
-radD=math.pi/180.0
+extension = ''
ARG=''
-def rad2deg(v):
- return round(v*180.0/math.pi,4)
-
-def deg2rad(v):
- return (v*math.pi)/180.0;
-
class DrawTypes:
"""Object DrawTypes enum values
BOUNDS - draw only the bounding box of the object
@@ -161,11 +154,12 @@ class VRML2Export:
##########################################################
def writeHeader(self):
+ bfile = sys.expandpath(Blender.Get('filename'))
self.file.write("#VRML V2.0 utf8\n\n")
self.file.write("# This file was authored with Blender (http://www.blender.org/)\n")
self.file.write("# Blender version %s\n" % Blender.Get('version'))
- self.file.write("# Blender file %s\n" % filename)
- self.file.write("# Exported using VRML97 exporter v1.50 (2005/06/03)\n\n")
+ self.file.write("# Blender file %s\n" % sys.basename(bfile))
+ self.file.write("# Exported using VRML97 exporter v1.55 (2006/01/17)\n\n")
def writeInline(self):
inlines = Blender.Scene.Get()
@@ -205,9 +199,8 @@ class VRML2Export:
def writeViewpoint(self, thisObj):
context = scene.getRenderingContext()
ratio = float(context.imageSizeY())/float(context.imageSizeX())
- lens = (360* (math.atan(ratio *16 / thisObj.data.getLens()) / 3.141593))*(3.141593/180)
- if lens > 3.14:
- lens = 3.14
+ lens = (360* (math.atan(ratio *16 / thisObj.data.getLens()) / math.pi))*(math.pi/180)
+ lens = min(lens, math.pi)
# get the camera location, subtract 90 degress from X to orient like VRML does
loc = self.rotatePointForVRML(thisObj.loc)
rot = [thisObj.RotX - 1.57, thisObj.RotY, thisObj.RotZ]
@@ -271,8 +264,8 @@ class VRML2Export:
ambientIntensity = 0
# compute cutoff and beamwidth
- intensity=min(lamp.energy/1.5,1.0)
- beamWidth=deg2rad(lamp.spotSize)*.37;
+ intensity=min(lamp.energy/1.75,1.0)
+ beamWidth=((lamp.spotSize*math.pi)/180.0)*.37;
cutOffAngle=beamWidth*1.3
(dx,dy,dz)=self.computeDirection(object)
@@ -303,7 +296,7 @@ class VRML2Export:
ambi = 0
ambientIntensity = 0
- intensity=min(lamp.energy/1.5, 1.0)
+ intensity=min(lamp.energy/1.75,1.0)
(dx,dy,dz)=self.computeDirection(object)
self.writeIndented("DEF %s DirectionalLight {\n" % self.cleanStr(object.name),1)
self.writeIndented("ambientIntensity %s\n" % (round(ambientIntensity,self.cp)))
@@ -322,7 +315,7 @@ class VRML2Export:
ambientIntensity = 0
om = object.getMatrix()
location=self.rotVertex(om, (0,0,0));
- intensity=min(lamp.energy/1.5,1.0)
+ intensity=min(lamp.energy/1.75,1.0)
radius = lamp.dist
self.writeIndented("DEF %s PointLight {\n" % self.cleanStr(object.name),1)
self.writeIndented("ambientIntensity %s\n" % (round(ambientIntensity,self.cp)))
@@ -346,28 +339,10 @@ class VRML2Export:
self.writeIndented("# location %s %s %s\n" % (round(location[0],3), round(location[1],3), round(location[2],3)))
self.writeIndented("}\n",-1)
self.writeIndented("\n")
- def createDef(self, name):
- name = name + str(self.nodeID)
- self.nodeID=self.nodeID+1
- if len(name) <= 3:
- newname = "_" + str(self.nodeID)
- return "%s" % (newname)
- else:
- for bad in [' ','"','#',"'",',','.','[','\\',']','{','}']:
- name=name.replace(bad,'_')
- if name in self.namesReserved:
- newname = name[0:3] + "_" + str(self.nodeID)
- return "%s" % (newname)
- elif name[0].isdigit():
- newname = "_" + name + str(self.nodeID)
- return "%s" % (newname)
- else:
- newname = name
- return "%s" % (newname)
def secureName(self, name):
name = name + str(self.nodeID)
- self.nodeID=self.nodeID+1
+ self.nodeID += 1
if len(name) <= 3:
newname = "_" + str(self.nodeID)
return "%s" % (newname)
@@ -385,13 +360,14 @@ class VRML2Export:
return "%s" % (newname)
def writeIndexedFaceSet(self, object, normals = 0):
-
imageMap={} # set of used images
sided={} # 'one':cnt , 'two':cnt
vColors={} # 'multi':1
meshName = self.cleanStr(object.name)
mesh=object.getData()
meshME = self.cleanStr(mesh.name)
+ if len(mesh.faces) == 0:
+ return
for face in mesh.faces:
if face.mode & Blender.NMesh.FaceModes['HALO'] and self.halonode == 0:
self.writeIndented("Billboard {\n",1)
@@ -437,23 +413,22 @@ class VRML2Export:
issmooth=0
if len(maters) > 0 or mesh.hasFaceUV():
- self.writeIndented("appearance Appearance {\n", 1)
-
- # right now this script can only handle a single material per mesh.
- if len(maters) >= 1:
- mat=Blender.Material.Get(maters[0].name)
- self.writeMaterial(mat, self.cleanStr(maters[0].name,''))
- if len(maters) > 1:
- print "Warning: mesh named %s has multiple materials" % meshName
- print "Warning: only one material per object handled"
- else:
- self.writeIndented("material NULL\n")
+ self.writeIndented("appearance Appearance {\n", 1)
+ # right now this script can only handle a single material per mesh.
+ if len(maters) >= 1:
+ mat=Blender.Material.Get(maters[0].name)
+ matFlags = mat.getMode()
+ if not matFlags & Blender.Material.Modes['TEXFACE']:
+ self.writeMaterial(mat, self.cleanStr(maters[0].name,''))
+ if len(maters) > 1:
+ print "Warning: mesh named %s has multiple materials" % meshName
+ print "Warning: only one material per object handled"
#-- textures
if mesh.hasFaceUV():
for face in mesh.faces:
if (hasImageTexture == 0) and (face.image):
- self.writeImageTexture(face.image.name)
+ self.writeImageTexture(face.image.name, face.image.filename)
hasImageTexture=1 # keep track of face texture
if self.tilenode == 1:
self.writeIndented("textureTransform TextureTransform { scale %s %s }\n" % (face.image.xrep, face.image.yrep))
@@ -501,7 +476,7 @@ class VRML2Export:
if face.smooth:
issmooth=1
if issmooth==1 and self.wire == 0:
- creaseAngle=(mesh.getMaxSmoothAngle())*radD
+ creaseAngle=(mesh.getMaxSmoothAngle())*(math.pi/180.0)
self.writeIndented("creaseAngle %s\n" % (round(creaseAngle,self.cp)))
#--- output vertexColors
@@ -636,22 +611,27 @@ class VRML2Export:
self.matNames[matName]=1
- ambient = mat.amb/2
+ ambient = mat.amb/3
diffuseR, diffuseG, diffuseB = mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2]
if len(world) > 0:
ambi = world[0].getAmb()
- ambi0, ambi1, ambi2 = ambi[0], ambi[1], ambi[2]
+ ambi0, ambi1, ambi2 = (ambi[0]*mat.amb)*2, (ambi[1]*mat.amb)*2, (ambi[2]*mat.amb)*2
else:
- ambi = 0
ambi0, ambi1, ambi2 = 0, 0, 0
- emisR, emisG, emisB = (diffuseR*mat.emit+ambi0)/4, (diffuseG*mat.emit+ambi1)/4, (diffuseB*mat.emit+ambi2)/4
+ emisR, emisG, emisB = (diffuseR*mat.emit+ambi0)/2, (diffuseG*mat.emit+ambi1)/2, (diffuseB*mat.emit+ambi2)/2
- shininess = mat.hard/255.0
- specR = (mat.specCol[0]+0.001)/(1.05/(mat.getSpec()+0.001))
- specG = (mat.specCol[1]+0.001)/(1.05/(mat.getSpec()+0.001))
- specB = (mat.specCol[2]+0.001)/(1.05/(mat.getSpec()+0.001))
+ shininess = mat.hard/512.0
+ specR = (mat.specCol[0]+0.001)/(1.25/(mat.getSpec()+0.001))
+ specG = (mat.specCol[1]+0.001)/(1.25/(mat.getSpec()+0.001))
+ specB = (mat.specCol[2]+0.001)/(1.25/(mat.getSpec()+0.001))
transp = 1-mat.alpha
-
+ matFlags = mat.getMode()
+ if matFlags & Blender.Material.Modes['SHADELESS']:
+ ambient = 1
+ shine = 1
+ specR = emitR = diffuseR
+ specG = emitG = diffuseG
+ specB = emitB = diffuseB
self.writeIndented("material DEF MA_%s Material {\n" % matName, 1)
self.writeIndented("diffuseColor %s %s %s\n" % (round(diffuseR,self.cp), round(diffuseG,self.cp), round(diffuseB,self.cp)))
self.writeIndented("ambientIntensity %s\n" % (round(ambient,self.cp)))
@@ -661,14 +641,14 @@ class VRML2Export:
self.writeIndented("transparency %s\n" % (round(transp,self.cp)))
self.writeIndented("}\n",-1)
- def writeImageTexture(self, name):
+ def writeImageTexture(self, name, filename):
if self.texNames.has_key(name):
self.writeIndented("texture USE %s\n" % self.cleanStr(name))
self.texNames[name] += 1
return
else:
self.writeIndented("texture DEF %s ImageTexture {\n" % self.cleanStr(name), 1)
- self.writeIndented("url \"%s\"\n" % name)
+ self.writeIndented("url \"%s\"\n" % name.split("\\")[-1].split("/")[-1])
self.writeIndented("}\n",-1)
self.texNames[name] = 1
@@ -687,7 +667,7 @@ class VRML2Export:
if worldname in self.namesStandard:
self.writeIndented("Background {\n",1)
else:
- self.writeIndented("DEF %s Background {\n" % self.createDef(worldname),1)
+ self.writeIndented("DEF %s Background {\n" % self.secureName(worldname),1)
# No Skytype - just Hor color
if blending == 0:
self.writeIndented("groundColor %s %s %s\n" % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp)))
@@ -956,11 +936,8 @@ class VRML2Export:
def writeIndented(self, s, inc=0):
if inc < 1:
self.indentLevel = self.indentLevel + inc
-
- spaces=""
- for x in xrange(self.indentLevel):
- spaces = spaces + "\t"
- self.file.write(spaces + s)
+
+ self.file.write( self.indentLevel*"\t" + s)
if inc > 0:
self.indentLevel = self.indentLevel + inc
@@ -1016,7 +993,9 @@ def select_file(filename):
if(result != 1):
return
- if filename.find('.wrl', -4) < 0: filename += '.wrl'
+ if not filename.endswith(extension):
+ filename += extension
+
wrlexport=VRML2Export(filename)
wrlexport.export(scene, world, worldmat)
@@ -1026,7 +1005,7 @@ def createWRLPath():
if filename.find('.') != -1:
filename = filename.split('.')[0]
- filename += ".wrl"
+ filename += extension
print filename
return filename
@@ -1041,8 +1020,14 @@ except:
print "older version"
if Blender.Get('version') < 235:
- print "Warning: VRML97 export failed, wrong blender version!"
- print " You aren't running blender version 2.35 or greater"
- print " download a newer version from http://blender3d.org/"
+ print "Warning: VRML97 export failed, wrong blender version!"
+ print " You aren't running blender version 2.35 or greater"
+ print " download a newer version from http://blender3d.org/"
else:
- Blender.Window.FileSelector(select_file,"Export VRML97",createWRLPath())
+ if ARG == 'comp':
+ extension=".wrz"
+ from gzip import *
+ else:
+ extension=".wrl"
+ Blender.Window.FileSelector(select_file,"Export VRML97",createWRLPath())
+
diff --git a/release/scripts/wings_export.py b/release/scripts/wings_export.py
index c262f3faabd..8477f9e076a 100644
--- a/release/scripts/wings_export.py
+++ b/release/scripts/wings_export.py
@@ -50,12 +50,27 @@ Notes:<br>
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | Feb 19, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
# | Read and write Wings3D File Format (*.wings) |
# +---------------------------------------------------------+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
import struct, time, sys, os, zlib, cStringIO
diff --git a/release/scripts/wings_import.py b/release/scripts/wings_import.py
index 70f124b3bac..8bba6f52de7 100644
--- a/release/scripts/wings_import.py
+++ b/release/scripts/wings_import.py
@@ -11,7 +11,7 @@ __author__ = "Anthony D'Agostino (Scorpius)"
__url__ = ("blender", "elysiun",
"Author's homepage, http://www.redrival.com/scorpius",
"Wings 3D, http://www.wings3d.com")
-__version__ = "Part of IOSuite 0.5"
+__version__ = "Update on version from IOSuite 0.5"
__bpydoc__ = """\
This script imports Wings3D files to Blender.
@@ -37,7 +37,8 @@ fanning algorithm. Convex polygons (i.e., shaped like the letter "U")
require a different algorithm, and will be triagulated incorrectly.
Notes:<br>
- Last tested with Wings 3D 0.98.25 & Blender 2.35a.
+ Last tested with Wings 3D 0.98.25 & Blender 2.35a.<br>
+ This version has improvements made by Adam Saltsman (AdamAtomic) and Toastie.
"""
# $Id$
@@ -47,15 +48,29 @@ Notes:<br>
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | Feb 19, 2002 |
-# | Released under the Blender Artistic Licence (BAL) |
-# | Import Export Suite v0.5 |
-# +---------------------------------------------------------+
-# | Read and write Wings3D File Format (*.wings) |
-# +---------------------------------------------------------+
+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
import Blender, meshtools
import struct, time, sys, os, zlib, cStringIO
-
+
# ==============================================
# === Read The 'Header' Common To All Chunks ===
# ==============================================
@@ -79,26 +94,28 @@ def read_mode(data):
# === Read Hard Edges ===
# =======================
def read_hardedges(data):
+ hardedge_table = {} # hard edges table
tag = data.read(1)
if tag == '\x6A':
- return # There are no hard edges
+ return hardedge_table # There are no hard edges
elif tag == '\x6B':
numhardedges, = struct.unpack(">H", data.read(2))
- print "numhardedges:", numhardedges
+ #print "numhardedges:", numhardedges
for i in range(numhardedges):
- data.read(1)
+ hardedge_table[i] = struct.unpack(">B", data.read(1))[0]
elif tag == '\x6C':
numhardedges, = struct.unpack(">L", data.read(4))
- print "numhardedges:", numhardedges
+ #print "numhardedges:", numhardedges
for i in range(numhardedges):
misc = data.read(1)
if misc == '\x61': # next value is stored as a byte
- data.read(1)
+ hardedge_table[i] = struct.unpack(">B", data.read(1))[0]
elif misc == '\x62': # next value is stored as a long
- data.read(4)
+ hardedge_table[i] = struct.unpack(">L", data.read(4))[0]
data.read(1) # 6A
else:
print tag
+ return hardedge_table
# ==================
# === Read Edges ===
@@ -134,6 +151,7 @@ def read_edges(data):
# === Read Faces ===
# ==================
def read_faces(data):
+ mat_table = {} #list of faces and material names
misc, numfaces = struct.unpack(">BL", data.read(5))
for i in range(numfaces):
if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces")
@@ -141,10 +159,10 @@ def read_faces(data):
data.read(4)
read_chunkheader(data)
misc, namelen = struct.unpack(">BH", data.read(3))
- materialname = data.read(namelen)
- data.read(1)
+ mat_table[i] = data.read(namelen)
+ data.read(1) # 6A?
data.read(1) # 6A
- return numfaces
+ return mat_table
# ==================
# === Read Verts ===
@@ -169,8 +187,10 @@ def make_face_table(edge_table): # For Wings
for i in range(len(edge_table)):
Lf = edge_table[i][2]
Rf = edge_table[i][3]
- face_table[Lf] = i
- face_table[Rf] = i
+ if Lf >= 0:
+ face_table[Lf] = i
+ if Rf >= 0:
+ face_table[Rf] = i
return face_table
# =======================
@@ -198,14 +218,17 @@ def make_faces(edge_table): # For Wings
if i == edge_table[current_edge][3]:
next_edge = edge_table[current_edge][7] # Right successor edge
next_vert = edge_table[current_edge][0]
- else:
+ elif i == edge_table[current_edge][2]:
next_edge = edge_table[current_edge][5] # Left successor edge
next_vert = edge_table[current_edge][1]
+ else:
+ break
face_verts.append(next_vert)
current_edge = next_edge
if current_edge == face_table[i]: break
- face_verts.reverse()
- faces.append(face_verts)
+ if len(face_verts) > 0:
+ face_verts.reverse()
+ faces.append(face_verts)
return faces
# =======================
@@ -223,7 +246,7 @@ def dump_wings(filename):
file.close()
data = zlib.decompress(data)
if dsize != len(data): print "ERROR: uncompressed size does not match."
- data = cStringIO.StringIO(data)
+ data = cStringIO.StringIO(data)
print "header:", header
print read_chunkheader(data) # === wings chunk ===
data.read(4) # misc bytes
@@ -236,9 +259,10 @@ def dump_wings(filename):
objname = data.read(namelen)
print read_chunkheader(data) # === winged chunk ===
edge_table = read_edges(data)
- numfaces = read_faces(data)
+ mat_table = read_faces(data)
+ numfaces = len(mat_table)
verts = read_verts(data)
- read_hardedges(data)
+ hardedge_table = read_hardedges(data)
face_table = {} # contains an incident edge
vert_table = {} # contains an incident edge
@@ -255,25 +279,26 @@ def dump_wings(filename):
print
print "Ä"*79
print "edge_table:"
- pprint.pprint(edge_table)
+ #pprint.pprint(edge_table)
#for i in range(len(edge_table)): print "%2d" % (i), edge_table[i]
print
print "face_table:"
- pprint.pprint(face_table)
+ #pprint.pprint(face_table)
#for i in range(len(face_table)): print "%2d %2d" % (i, face_table[i])
print
print "vert_table:"
- pprint.pprint(vert_table)
+ #pprint.pprint(vert_table)
#for i in range(len(vert_table)): print "%2d %2d" % (i, vert_table[i])
file.close()
end = time.clock()
print '\a\r',
- sys.stderr.write("\nDone in %.2f %s" % (end-start, "seconds"))
+ sys.stderr.write("\nDone in %.2f %s\a\r" % (end-start, "seconds"))
# =========================
# === Read Wings Format ===
# =========================
def read(filename):
+
start = time.clock()
file = open(filename, "rb")
header = file.read(15)
@@ -299,9 +324,113 @@ def read(filename):
objname = data.read(namelen)
read_chunkheader(data) # winged chunk
edge_table = read_edges(data)
- numfaces = read_faces(data)
+ mat_table = read_faces(data)
+ numfaces = len(mat_table)
verts = read_verts(data)
- read_hardedges(data)
+ hardedge_table = read_hardedges(data)
+
+ # Manually split hard edges
+ # TODO: Handle the case where there are 2+ edges on a face
+ duped = {}
+ processed = []
+ cleanup = []
+ oldedgecount = len(edge_table)
+ for i in range(len(verts)):
+ duped[i] = -1
+ for j in range(len(hardedge_table)):
+ hardedge = hardedge_table[j]
+ oldedge = edge_table[hardedge]
+ newedge = [] # Copy old edge into a new list
+ for k in range(len(oldedge)):
+ newedge.append(oldedge[k])
+
+ # Duplicate start vert if not duped already
+ sv = newedge[0]
+ if duped[sv] == -1:
+ verts.append(verts[sv])
+ duped[sv] = len(verts)-1
+ newedge[0] = duped[sv]
+
+ # Duplicate end vert if not duped already
+ ev = newedge[1]
+ if duped[ev] == -1:
+ verts.append(verts[ev])
+ duped[ev] = len(verts)-1
+ newedge[1] = duped[ev]
+
+ # Decide which way to cut the edge
+ flip = 0
+ for v in range(len(processed)):
+ if processed[v][0] == oldedge[0]:
+ flip = 1
+ elif processed[v][1] == oldedge[1]:
+ flip = 1
+ if flip == 0:
+ of = 3
+ oe1 = 6
+ oe2 = 7
+ nf = 2
+ ne1 = 4
+ ne2 = 5
+ else:
+ of = 2
+ oe1 = 4
+ oe2 = 5
+ nf = 3
+ ne1 = 6
+ ne2 = 7
+
+ # Fix up side-specific edge fields
+ oldedge[of] = -1
+ oldedge[oe1] = -1
+ oldedge[oe2] = -1
+ newedge[nf] = -1
+ newedge[ne1] = -1
+ newedge[ne2] = -1
+
+ # Store new edge's neighbors for cleanup later
+ cleanup.append(edge_table[newedge[oe1]])
+ cleanup.append(edge_table[newedge[oe2]])
+
+ #DEBUG
+ # Sv Ev | Lf Rf | Lp Ls | Rp Rs
+ #print "Old Edge:",hardedge,oldedge
+ #print "New Edge:",len(edge_table),newedge
+
+ # Add this new edge to the edge table
+ edge_table[len(edge_table)] = newedge
+ if flip == 0:
+ processed.append(oldedge) # mark it off as processed
+
+ # Cycle through cleanup list and fix it up
+ for c in range(len(cleanup)):
+ cleanupedge = cleanup[c]
+
+ # Fix up their verts in case they were duped
+ sv = cleanupedge[0]
+ if sv < len(duped):
+ if duped[sv] >= 0:
+ cleanupedge[0] = duped[sv]
+ ev = cleanupedge[1]
+ if ev < len(duped):
+ if duped[ev] >= 0:
+ cleanupedge[1] = duped[ev]
+
+ # Fix up edge info (in case a hard edge was replaced with a new one)
+ edgecount = c/2
+ hardedge = hardedge_table[edgecount] # look up what edge we were replacing
+ newedgenum = oldedgecount+edgecount # calculate new edge's index
+ if cleanupedge[4] == hardedge:
+ cleanupedge[4] = newedgenum
+ if cleanupedge[5] == hardedge:
+ cleanupedge[5] = newedgenum
+ if cleanupedge[6] == hardedge:
+ cleanupedge[6] = newedgenum
+ if cleanupedge[7] == hardedge:
+ cleanupedge[7] = newedgenum
+
+ #for i in range(len(edge_table)): print "%2d" % (i), edge_table[i]
+
read_mode(data)
faces = make_faces(edge_table)
message += "%s %8s %8s %8s\n" % (objname.ljust(15), len(faces), len(edge_table), len(verts))
diff --git a/release/scripts/x3d_export.py b/release/scripts/x3d_export.py
index 322af5eac25..9239db6ab9e 100644
--- a/release/scripts/x3d_export.py
+++ b/release/scripts/x3d_export.py
@@ -4,16 +4,15 @@ Name: 'X3D Extensible 3D (.x3d)...'
Blender: 235
Group: 'Export'
Submenu: 'All Objects...' all
+Submenu: 'All Objects compressed...' comp
Submenu: 'Selected Objects...' selected
Tooltip: 'Export to Extensible 3D file (.x3d)'
"""
__author__ = ("Bart")
+__email__ = ["Bart, bart:neeneenee*de"]
__url__ = ["Author's (Bart) homepage, http://www.neeneenee.de/vrml"]
-__version__ = "2005/06/06"
-
-
-
+__version__ = "2006/01/17"
__bpydoc__ = """\
This script exports to X3D format.
@@ -37,8 +36,6 @@ for each texture);<br>
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
-# Copyright (C) 2003,2004: Bart bart@neeneenee.de
-#
# 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
@@ -61,7 +58,7 @@ for each texture);<br>
####################################
import Blender
-from Blender import Object, NMesh, Lamp, Draw, BGL, Image, Text
+from Blender import Object, NMesh, Lamp, Draw, BGL, Image, Text, sys, Mathutils
from Blender.Scene import Render
try:
from os.path import exists, join
@@ -80,14 +77,8 @@ world = Blender.World.Get()
worldmat = Blender.Texture.Get()
filename = Blender.Get('filename')
_safeOverwrite = True
-radD=math.pi/180.0
ARG=''
-
-def rad2deg(v):
- return round(v*180.0/math.pi,4)
-
-def deg2rad(v):
- return (v*math.pi)/180.0;
+extension = ''
class DrawTypes:
"""Object DrawTypes enum values
@@ -177,13 +168,14 @@ class VRML2Export:
##########################################################
def writeHeader(self):
+ bfile = sys.expandpath(Blender.Get('filename'))
self.file.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
self.file.write("<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n")
self.file.write("<X3D version=\"3.0\" profile=\"Immersive\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema-instance\" xsd:noNamespaceSchemaLocation=\"http://www.web3d.org/specifications/x3d-3.0.xsd\">\n")
self.file.write("<head>\n")
- self.file.write("\t<meta name=\"filename\" content=\"%s\" />\n" % filename)
+ self.file.write("\t<meta name=\"filename\" content=\"%s\" />\n" % sys.basename(bfile))
self.file.write("\t<meta name=\"generator\" content=\"Blender %s\" />\n" % Blender.Get('version'))
- self.file.write("\t<meta name=\"translator\" content=\"X3D exporter v1.50 (2005/06/06)\" />\n")
+ self.file.write("\t<meta name=\"translator\" content=\"X3D exporter v1.55 (2006/01/17)\" />\n")
self.file.write("</head>\n")
self.file.write("<Scene>\n")
@@ -224,9 +216,8 @@ class VRML2Export:
def writeViewpoint(self, thisObj):
context = scene.getRenderingContext()
ratio = float(context.imageSizeY())/float(context.imageSizeX())
- lens = (360* (math.atan(ratio *16 / thisObj.data.getLens()) / 3.141593))*(3.141593/180)
- if lens > 3.14:
- lens = 3.14
+ lens = (360* (math.atan(ratio *16 / thisObj.data.getLens()) / math.pi))*(math.pi/180)
+ lens = min(lens, math.pi)
# get the camera location, subtract 90 degress from X to orient like X3D does
loc = self.rotatePointForVRML(thisObj.loc)
rot = [thisObj.RotX - 1.57, thisObj.RotY, thisObj.RotZ]
@@ -283,8 +274,8 @@ class VRML2Export:
ambientIntensity = 0
# compute cutoff and beamwidth
- intensity=min(lamp.energy/1.5,1.0)
- beamWidth=deg2rad(lamp.spotSize)*.37;
+ intensity=min(lamp.energy/1.75,1.0)
+ beamWidth=((lamp.spotSize*math.pi)/180.0)*.37;
cutOffAngle=beamWidth*1.3
(dx,dy,dz)=self.computeDirection(object)
@@ -314,7 +305,7 @@ class VRML2Export:
ambi = 0
ambientIntensity = 0
- intensity=min(lamp.energy/1.5, 1.0)
+ intensity=min(lamp.energy/1.75,1.0)
(dx,dy,dz)=self.computeDirection(object)
self.file.write("<DirectionalLight DEF=\"%s\" " % safeName)
self.file.write("ambientIntensity=\"%s\" " % (round(ambientIntensity,self.cp)))
@@ -332,7 +323,7 @@ class VRML2Export:
ambientIntensity = 0
om = object.getMatrix()
location=self.rotVertex(om, (0,0,0));
- intensity=min(lamp.energy/1.5,1.0)
+ intensity=min(lamp.energy/1.75,1.0)
radius = lamp.dist
self.file.write("<PointLight DEF=\"%s\" " % safeName)
self.file.write("ambientIntensity=\"%s\" " % (round(ambientIntensity,self.cp)))
@@ -354,24 +345,6 @@ class VRML2Export:
self.writeIndented("# location %s %s %s\n" % (round(location[0],3), round(location[1],3), round(location[2],3)))
self.writeIndented("/>\n",-1)
self.writeIndented("\n")
- def createDef(self, name):
- name = name + str(self.nodeID)
- self.nodeID=self.nodeID+1
- if len(name) <= 3:
- newname = "_" + str(self.nodeID)
- return "%s" % (newname)
- else:
- for bad in [' ','"','#',"'",',','.','[','\\',']','{','}']:
- name=name.replace(bad,'_')
- if name in self.namesReserved:
- newname = name[0:3] + "_" + str(self.nodeID)
- return "%s" % (newname)
- elif name[0].isdigit():
- newname = "_" + name + str(self.nodeID)
- return "%s" % (newname)
- else:
- newname = name
- return "%s" % (newname)
def secureName(self, name):
name = name + str(self.nodeID)
@@ -393,13 +366,14 @@ class VRML2Export:
return "%s" % (newname)
def writeIndexedFaceSet(self, object, normals = 0):
-
imageMap={} # set of used images
sided={} # 'one':cnt , 'two':cnt
vColors={} # 'multi':1
meshName = self.cleanStr(object.name)
mesh=object.getData()
meshME = self.cleanStr(mesh.name)
+ if len(mesh.faces) == 0:
+ return
for face in mesh.faces:
if face.mode & Blender.NMesh.FaceModes['HALO'] and self.halonode == 0:
self.writeIndented("<Billboard axisOfRotation=\"0 0 0\">\n",1)
@@ -436,17 +410,16 @@ class VRML2Export:
issmooth=0
if len(maters) > 0 or mesh.hasFaceUV():
- self.writeIndented("<Appearance>\n", 1)
-
- # right now this script can only handle a single material per mesh.
- if len(maters) >= 1:
- mat=Blender.Material.Get(maters[0].name)
- self.writeMaterial(mat, self.cleanStr(maters[0].name,''))
- if len(maters) > 1:
- print "Warning: mesh named %s has multiple materials" % meshName
- print "Warning: only one material per object handled"
- else:
- self.writeIndented("<material NULL />\n")
+ self.writeIndented("<Appearance>\n", 1)
+ # right now this script can only handle a single material per mesh.
+ if len(maters) >= 1:
+ mat=Blender.Material.Get(maters[0].name)
+ matFlags = mat.getMode()
+ if not matFlags & Blender.Material.Modes['TEXFACE']:
+ self.writeMaterial(mat, self.cleanStr(maters[0].name,''))
+ if len(maters) > 1:
+ print "Warning: mesh named %s has multiple materials" % meshName
+ print "Warning: only one material per object handled"
#-- textures
if mesh.hasFaceUV():
@@ -489,7 +462,7 @@ class VRML2Export:
if face.smooth:
issmooth=1
if issmooth==1 and self.wire == 0:
- creaseAngle=(mesh.getMaxSmoothAngle())*radD
+ creaseAngle=(mesh.getMaxSmoothAngle())*(math.pi/180.0)
self.file.write("creaseAngle=\"%s\" " % (round(creaseAngle,self.cp)))
#--- output vertexColors
@@ -640,22 +613,27 @@ class VRML2Export:
self.matNames[matName]=1
- ambient = mat.amb/2
+ ambient = mat.amb/3
diffuseR, diffuseG, diffuseB = mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2]
if len(world) > 0:
ambi = world[0].getAmb()
- ambi0, ambi1, ambi2 = ambi[0], ambi[1], ambi[2]
+ ambi0, ambi1, ambi2 = (ambi[0]*mat.amb)*2, (ambi[1]*mat.amb)*2, (ambi[2]*mat.amb)*2
else:
- ambi = 0
ambi0, ambi1, ambi2 = 0, 0, 0
- emisR, emisG, emisB = (diffuseR*mat.emit+ambi0)/4, (diffuseG*mat.emit+ambi1)/4, (diffuseB*mat.emit+ambi2)/4
+ emisR, emisG, emisB = (diffuseR*mat.emit+ambi0)/2, (diffuseG*mat.emit+ambi1)/2, (diffuseB*mat.emit+ambi2)/2
- shininess = mat.hard/255.0
- specR = (mat.specCol[0]+0.001)/(1.05/(mat.getSpec()+0.001))
- specG = (mat.specCol[1]+0.001)/(1.05/(mat.getSpec()+0.001))
- specB = (mat.specCol[2]+0.001)/(1.05/(mat.getSpec()+0.001))
+ shininess = mat.hard/512.0
+ specR = (mat.specCol[0]+0.001)/(1.25/(mat.getSpec()+0.001))
+ specG = (mat.specCol[1]+0.001)/(1.25/(mat.getSpec()+0.001))
+ specB = (mat.specCol[2]+0.001)/(1.25/(mat.getSpec()+0.001))
transp = 1-mat.alpha
-
+ matFlags = mat.getMode()
+ if matFlags & Blender.Material.Modes['SHADELESS']:
+ ambient = 1
+ shine = 1
+ specR = emitR = diffuseR
+ specG = emitG = diffuseG
+ specB = emitB = diffuseB
self.writeIndented("<Material DEF=\"MA_%s\" " % matName, 1)
self.file.write("diffuseColor=\"%s %s %s\" " % (round(diffuseR,self.cp), round(diffuseG,self.cp), round(diffuseB,self.cp)))
self.file.write("specularColor=\"%s %s %s\" " % (round(specR,self.cp), round(specG,self.cp), round(specB,self.cp)))
@@ -690,7 +668,7 @@ class VRML2Export:
mix0, mix1, mix2 = mix0/2, mix1/2, mix2/2
self.file.write("<Background ")
if worldname not in self.namesStandard:
- self.file.write("DEF=\"%s\" " % self.createDef(worldname))
+ self.file.write("DEF=\"%s\" " % self.secureName(worldname))
# No Skytype - just Hor color
if blending == 0:
self.file.write("groundColor=\"%s %s %s\" " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp)))
@@ -1016,7 +994,9 @@ def select_file(filename):
if(result != 1):
return
- if filename.find('.x3d', -4) < 0: filename += '.x3d'
+ if not filename.endswith(extension):
+ filename += extension
+
wrlexport=VRML2Export(filename)
wrlexport.export(scene, world, worldmat)
@@ -1026,7 +1006,7 @@ def createWRLPath():
if filename.find('.') != -1:
filename = filename.split('.')[0]
- filename += ".x3d"
+ filename += extension
print filename
return filename
@@ -1041,8 +1021,14 @@ except:
print "older version"
if Blender.Get('version') < 235:
- print "Warning: X3D export failed, wrong blender version!"
- print " You aren't running blender version 2.35 or greater"
- print " download a newer version from http://blender3d.org/"
+ print "Warning: X3D export failed, wrong blender version!"
+ print " You aren't running blender version 2.35 or greater"
+ print " download a newer version from http://blender3d.org/"
else:
- Blender.Window.FileSelector(select_file,"Export X3D",createWRLPath())
+ if ARG == 'comp':
+ from gzip import *
+ extension=".x3dz"
+ else:
+ extension=".x3d"
+ Blender.Window.FileSelector(select_file,"Export X3D",createWRLPath())
+