Collada
-=-=-=- -Fixed some DAE import & export bugs -Changed Collada exporter to use the mesh loops API -Added tangent export to Collada exporter -Added triangulation option to Collada exporter -Changed a little how normalmaps are handled in shader. Not sure if it's working properly, be careful. -Fixed some strange bug with kinematic bodies #776 -Fix release compilaiton issues #782
This commit is contained in:
parent
13a848e332
commit
a84ba9c853
25 changed files with 363 additions and 198 deletions
|
|
@ -83,6 +83,17 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
|
|||
description="Apply modifiers to mesh objects (on a copy!).",
|
||||
default=True,
|
||||
)
|
||||
use_tangent_arrays = BoolProperty(
|
||||
name="Tangent Arrays",
|
||||
description="Export Tangent and Binormal arrays (for normalmapping).",
|
||||
default=False,
|
||||
)
|
||||
use_triangles = BoolProperty(
|
||||
name="Triangulate",
|
||||
description="Export Triangles instead of Polygons.",
|
||||
default=False,
|
||||
)
|
||||
|
||||
use_copy_images = BoolProperty(
|
||||
name="Copy Images",
|
||||
description="Copy Images (create images/ subfolder)",
|
||||
|
|
@ -118,6 +129,7 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
|
|||
description="Remove double keyframes",
|
||||
default=True,
|
||||
)
|
||||
|
||||
anim_optimize_precision = FloatProperty(
|
||||
name="Precision",
|
||||
description=("Tolerence for comparing double keyframes "
|
||||
|
|
@ -126,6 +138,7 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
|
|||
soft_min=1, soft_max=16,
|
||||
default=6.0,
|
||||
)
|
||||
|
||||
use_metadata = BoolProperty(
|
||||
name="Use Metadata",
|
||||
default=True,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import time
|
|||
import math # math.pi
|
||||
import shutil
|
||||
import bpy
|
||||
import bmesh
|
||||
from mathutils import Vector, Matrix
|
||||
|
||||
#according to collada spec, order matters
|
||||
|
|
@ -125,6 +126,12 @@ class DaeExporter:
|
|||
tup = (self.vertex.x,self.vertex.y,self.vertex.z,self.normal.x,self.normal.y,self.normal.z)
|
||||
for t in self.uv:
|
||||
tup = tup + (t.x,t.y)
|
||||
if (self.color!=None):
|
||||
tup = tup + (self.color.x,self.color.y,self.color.z)
|
||||
if (self.tangent!=None):
|
||||
tup = tup + (self.tangent.x,self.tangent.y,self.tangent.z)
|
||||
if (self.bitangent!=None):
|
||||
tup = tup + (self.bitangent.x,self.bitangent.y,self.bitangent.z)
|
||||
#for t in self.bones:
|
||||
# tup = tup + (t)
|
||||
#for t in self.weights:
|
||||
|
|
@ -135,7 +142,9 @@ class DaeExporter:
|
|||
def __init__(self):
|
||||
self.vertex = Vector( (0.0,0.0,0.0) )
|
||||
self.normal = Vector( (0.0,0.0,0.0) )
|
||||
self.color = Vector( (0.0,0.0,0.0) )
|
||||
self.tangent = None
|
||||
self.bitangent = None
|
||||
self.color = None
|
||||
self.uv = []
|
||||
self.uv2 = Vector( (0.0,0.0) )
|
||||
self.bones=[]
|
||||
|
|
@ -442,10 +451,18 @@ class DaeExporter:
|
|||
self.mesh_cache[node.data]=meshdata
|
||||
return meshdata
|
||||
|
||||
if (len(node.modifiers) and self.config["use_mesh_modifiers"]):
|
||||
mesh=node.to_mesh(self.scene,True,"RENDER") #is this allright?
|
||||
else:
|
||||
mesh=node.data
|
||||
apply_modifiers = len(node.modifiers) and self.config["use_mesh_modifiers"]
|
||||
|
||||
mesh=node.to_mesh(self.scene,apply_modifiers,"RENDER") #is this allright?
|
||||
|
||||
triangulate=self.config["use_triangles"]
|
||||
if (triangulate):
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(mesh)
|
||||
bmesh.ops.triangulate(bm, faces=bm.faces)
|
||||
bm.to_mesh(mesh)
|
||||
bm.free()
|
||||
|
||||
|
||||
mesh.update(calc_tessface=True)
|
||||
vertices=[]
|
||||
|
|
@ -462,20 +479,22 @@ class DaeExporter:
|
|||
has_uv=False
|
||||
has_uv2=False
|
||||
has_weights=armature!=None
|
||||
has_colors=False
|
||||
has_tangents=self.config["use_tangent_arrays"] # could detect..
|
||||
has_colors=len(mesh.vertex_colors)
|
||||
mat_assign=[]
|
||||
|
||||
uv_layer_count=len(mesh.uv_textures)
|
||||
mesh.calc_tangents()
|
||||
|
||||
for fi in range(len(mesh.tessfaces)):
|
||||
f=mesh.tessfaces[fi]
|
||||
|
||||
for fi in range(len(mesh.polygons)):
|
||||
f=mesh.polygons[fi]
|
||||
|
||||
if (not (f.material_index in surface_indices)):
|
||||
surface_indices[f.material_index]=[]
|
||||
print("Type: "+str(type(f.material_index)))
|
||||
print("IDX: "+str(f.material_index)+"/"+str(len(mesh.materials)))
|
||||
|
||||
|
||||
try:
|
||||
#Bizarre blender behavior i don't understand, so catching exception
|
||||
mat = mesh.materials[f.material_index]
|
||||
|
|
@ -489,35 +508,42 @@ class DaeExporter:
|
|||
|
||||
indices = surface_indices[f.material_index]
|
||||
vi=[]
|
||||
#make triangles always
|
||||
#vertices always 3
|
||||
"""
|
||||
if (len(f.vertices)==3):
|
||||
vi.append(0)
|
||||
vi.append(1)
|
||||
vi.append(2)
|
||||
elif (len(f.vertices)==4):
|
||||
#todo, should use shortest path
|
||||
vi.append(0)
|
||||
vi.append(1)
|
||||
vi.append(2)
|
||||
vi.append(0)
|
||||
vi.append(2)
|
||||
vi.append(3)
|
||||
"""
|
||||
|
||||
for x in vi:
|
||||
mv = mesh.vertices[f.vertices[x]]
|
||||
for lt in range(f.loop_total):
|
||||
loop_index = f.loop_start + lt
|
||||
ml = mesh.loops[loop_index]
|
||||
mv = mesh.vertices[ml.vertex_index]
|
||||
|
||||
v = self.Vertex()
|
||||
v.vertex = Vector( mv.co )
|
||||
|
||||
for xt in mesh.tessface_uv_textures:
|
||||
d = xt.data[fi]
|
||||
uvsrc = [d.uv1,d.uv2,d.uv3,d.uv4]
|
||||
v.uv.append( Vector( uvsrc[x] ) )
|
||||
for xt in mesh.uv_layers:
|
||||
v.uv.append( Vector( xt.data[loop_index].uv ) )
|
||||
|
||||
if (has_colors):
|
||||
v.color = Vector( mesh.vertex_colors[0].data[loop_index].color )
|
||||
|
||||
v.normal = Vector( ml.normal )
|
||||
|
||||
if (has_tangents):
|
||||
v.tangent = Vector( ml.tangent )
|
||||
v.bitangent = Vector( ml.bitangent )
|
||||
|
||||
if (f.use_smooth):
|
||||
v.normal=Vector( mv.normal )
|
||||
else:
|
||||
v.normal=Vector( f.normal )
|
||||
|
||||
# if (armature):
|
||||
# v.vertex = node.matrix_world * v.vertex
|
||||
|
|
@ -531,6 +557,7 @@ class DaeExporter:
|
|||
continue;
|
||||
name = node.vertex_groups[vg.group].name
|
||||
if (name in si["bone_index"]):
|
||||
#could still put the weight as 0.0001 maybe
|
||||
if (vg.weight>0.001): #blender has a lot of zero weight stuff
|
||||
v.bones.append(si["bone_index"][name])
|
||||
v.weights.append(vg.weight)
|
||||
|
|
@ -546,7 +573,11 @@ class DaeExporter:
|
|||
vertices.append(v)
|
||||
vertex_map[tup]=idx
|
||||
|
||||
indices.append(idx)
|
||||
vi.append(idx)
|
||||
|
||||
if (len(vi)>2):
|
||||
#only triangles and above
|
||||
indices.append(vi)
|
||||
|
||||
|
||||
meshid = self.new_id("mesh")
|
||||
|
|
@ -586,6 +617,37 @@ class DaeExporter:
|
|||
self.writel(S_GEOM,4,'</technique_common>')
|
||||
self.writel(S_GEOM,3,'</source>')
|
||||
|
||||
if (has_tangents):
|
||||
self.writel(S_GEOM,3,'<source id="'+meshid+'-tangents">')
|
||||
float_values=""
|
||||
for v in vertices:
|
||||
float_values+=" "+str(v.tangent.x)+" "+str(v.tangent.y)+" "+str(v.tangent.z)
|
||||
self.writel(S_GEOM,4,'<float_array id="'+meshid+'-tangents-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>')
|
||||
self.writel(S_GEOM,4,'<technique_common>')
|
||||
self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-tangents-array" count="'+str(len(vertices))+'" stride="3">')
|
||||
self.writel(S_GEOM,5,'<param name="X" type="float"/>')
|
||||
self.writel(S_GEOM,5,'<param name="Y" type="float"/>')
|
||||
self.writel(S_GEOM,5,'<param name="Z" type="float"/>')
|
||||
self.writel(S_GEOM,4,'</accessor>')
|
||||
self.writel(S_GEOM,4,'</technique_common>')
|
||||
self.writel(S_GEOM,3,'</source>')
|
||||
|
||||
self.writel(S_GEOM,3,'<source id="'+meshid+'-bitangents">')
|
||||
float_values=""
|
||||
for v in vertices:
|
||||
float_values+=" "+str(v.bitangent.x)+" "+str(v.bitangent.y)+" "+str(v.bitangent.z)
|
||||
self.writel(S_GEOM,4,'<float_array id="'+meshid+'-bitangents-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>')
|
||||
self.writel(S_GEOM,4,'<technique_common>')
|
||||
self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-bitangents-array" count="'+str(len(vertices))+'" stride="3">')
|
||||
self.writel(S_GEOM,5,'<param name="X" type="float"/>')
|
||||
self.writel(S_GEOM,5,'<param name="Y" type="float"/>')
|
||||
self.writel(S_GEOM,5,'<param name="Z" type="float"/>')
|
||||
self.writel(S_GEOM,4,'</accessor>')
|
||||
self.writel(S_GEOM,4,'</technique_common>')
|
||||
self.writel(S_GEOM,3,'</source>')
|
||||
|
||||
|
||||
|
||||
# UV Arrays
|
||||
|
||||
for uvi in range(uv_layer_count):
|
||||
|
|
@ -608,36 +670,75 @@ class DaeExporter:
|
|||
self.writel(S_GEOM,4,'</technique_common>')
|
||||
self.writel(S_GEOM,3,'</source>')
|
||||
|
||||
# Color Arrays
|
||||
|
||||
if (has_colors):
|
||||
self.writel(S_GEOM,3,'<source id="'+meshid+'-colors">')
|
||||
float_values=""
|
||||
for v in vertices:
|
||||
float_values+=" "+str(v.color.x)+" "+str(v.color.y)+" "+str(v.color.z)
|
||||
self.writel(S_GEOM,4,'<float_array id="'+meshid+'-colors-array" count="'+str(len(vertices)*3)+'">'+float_values+'</float_array>')
|
||||
self.writel(S_GEOM,4,'<technique_common>')
|
||||
self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-colors-array" count="'+str(len(vertices))+'" stride="3">')
|
||||
self.writel(S_GEOM,5,'<param name="X" type="float"/>')
|
||||
self.writel(S_GEOM,5,'<param name="Y" type="float"/>')
|
||||
self.writel(S_GEOM,5,'<param name="Z" type="float"/>')
|
||||
self.writel(S_GEOM,4,'</accessor>')
|
||||
self.writel(S_GEOM,4,'</technique_common>')
|
||||
self.writel(S_GEOM,3,'</source>')
|
||||
|
||||
# Triangle Lists
|
||||
self.writel(S_GEOM,3,'<vertices id="'+meshid+'-vertices">')
|
||||
self.writel(S_GEOM,4,'<input semantic="POSITION" source="#'+meshid+'-positions"/>')
|
||||
self.writel(S_GEOM,3,'</vertices>')
|
||||
|
||||
prim_type=""
|
||||
if (triangulate):
|
||||
prim_type="triangles"
|
||||
else:
|
||||
prim_type="polygons"
|
||||
|
||||
|
||||
for m in surface_indices:
|
||||
indices = surface_indices[m]
|
||||
mat = materials[m]
|
||||
|
||||
if (mat!=None):
|
||||
matref = self.new_id("trimat")
|
||||
self.writel(S_GEOM,3,'<triangles count="'+str(int(len(indices)/3))+'" material="'+matref+'">') # todo material
|
||||
self.writel(S_GEOM,3,'<'+prim_type+' count="'+str(int(len(indices)))+'" material="'+matref+'">') # todo material
|
||||
mat_assign.append( (mat,matref) )
|
||||
else:
|
||||
self.writel(S_GEOM,3,'<triangles count="'+str(int(len(indices)/3))+'">') # todo material
|
||||
self.writel(S_GEOM,4,'<input semantic="VERTEX" source="#'+meshid+'-vertices" offset="0"/>')
|
||||
self.writel(S_GEOM,4,'<input semantic="NORMAL" source="#'+meshid+'-normals" offset="1"/>')
|
||||
extra_indices=0
|
||||
for uvi in range(uv_layer_count):
|
||||
self.writel(S_GEOM,4,'<input semantic="TEXCOORD" source="#'+meshid+'-texcoord-'+str(uvi)+'" offset="'+str(2+uvi)+'" set="'+str(uvi)+'"/>')
|
||||
extra_indices+=1
|
||||
self.writel(S_GEOM,3,'<'+prim_type+' count="'+str(int(len(indices)))+'">') # todo material
|
||||
|
||||
int_values="<p>"
|
||||
for i in range(len(indices)):
|
||||
int_values+=" "+str(indices[i]) # vertex index
|
||||
int_values+=" "+str(indices[i]) # normal index
|
||||
for e in range(extra_indices):
|
||||
int_values+=" "+str(indices[i]) # normal index
|
||||
int_values+="</p>"
|
||||
self.writel(S_GEOM,4,int_values)
|
||||
self.writel(S_GEOM,3,'</triangles>')
|
||||
|
||||
self.writel(S_GEOM,4,'<input semantic="VERTEX" source="#'+meshid+'-vertices" offset="0"/>')
|
||||
self.writel(S_GEOM,4,'<input semantic="NORMAL" source="#'+meshid+'-normals" offset="0"/>')
|
||||
|
||||
for uvi in range(uv_layer_count):
|
||||
self.writel(S_GEOM,4,'<input semantic="TEXCOORD" source="#'+meshid+'-texcoord-'+str(uvi)+'" offset="0" set="'+str(uvi)+'"/>')
|
||||
|
||||
if (has_colors):
|
||||
self.writel(S_GEOM,4,'<input semantic="COLOR" source="#'+meshid+'-colors" offset="0"/>')
|
||||
if (has_tangents):
|
||||
self.writel(S_GEOM,4,'<input semantic="TEXTANGENT" source="#'+meshid+'-tangents" offset="0"/>')
|
||||
self.writel(S_GEOM,4,'<input semantic="TEXBINORMAL" source="#'+meshid+'-bitangents" offset="0"/>')
|
||||
|
||||
if (triangulate):
|
||||
int_values="<p>"
|
||||
for p in indices:
|
||||
for i in p:
|
||||
int_values+=" "+str(i)
|
||||
int_values+=" </p>"
|
||||
self.writel(S_GEOM,4,int_values)
|
||||
else:
|
||||
for p in indices:
|
||||
int_values="<p>"
|
||||
for i in p:
|
||||
int_values+=" "+str(i)
|
||||
int_values+=" </p>"
|
||||
self.writel(S_GEOM,4,int_values)
|
||||
|
||||
self.writel(S_GEOM,3,'</'+prim_type+'>')
|
||||
|
||||
|
||||
self.writel(S_GEOM,2,'</mesh>')
|
||||
|
|
@ -1355,6 +1456,8 @@ class DaeExporter:
|
|||
self.writel(S_ANIM_CLIPS,0,'</library_animation_clips>')
|
||||
|
||||
for s in self.skeletons:
|
||||
if (s.animation_data==None):
|
||||
continue
|
||||
if s in cached_actions:
|
||||
s.animation_data.action = bpy.data.actions[cached_actions[s]]
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue