Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# Contributors: bart:neeneenee*de, http://www.neeneenee.de/vrml, Campbell Barton
"""
This script exports to X3D format.
Usage:
Run this script from "File->Export" menu. A pop-up will ask whether you
want to export only selected or all relevant objects.
Known issues:
Doesn't handle multiple materials (don't use material indices);<br>
Doesn't handle multiple UV textures on a single mesh (create a mesh for each texture);<br>
Can't get the texture array associated with material * not the UV ones;
"""
import math
import os
import bpy
import mathutils
Campbell Barton
committed
from bpy_extras.io_utils import create_derived_objects, free_derived_objects
Campbell Barton
committed
x3d_names_reserved = {"Anchor", "Appearance", "Arc2D", "ArcClose2D", "AudioClip", "Background", "Billboard",
"BooleanFilter", "BooleanSequencer", "BooleanToggle", "BooleanTrigger", "Box", "Circle2D",
"Collision", "Color", "ColorInterpolator", "ColorRGBA", "component", "Cone", "connect",
"Contour2D", "ContourPolyline2D", "Coordinate", "CoordinateDouble", "CoordinateInterpolator",
"CoordinateInterpolator2D", "Cylinder", "CylinderSensor", "DirectionalLight", "Disk2D",
"ElevationGrid", "EspduTransform", "EXPORT", "ExternProtoDeclare", "Extrusion", "field",
"fieldValue", "FillProperties", "Fog", "FontStyle", "GeoCoordinate", "GeoElevationGrid",
"GeoLocationLocation", "GeoLOD", "GeoMetadata", "GeoOrigin", "GeoPositionInterpolator",
"GeoTouchSensor", "GeoViewpoint", "Group", "HAnimDisplacer", "HAnimHumanoid", "HAnimJoint",
"HAnimSegment", "HAnimSite", "head", "ImageTexture", "IMPORT", "IndexedFaceSet",
"IndexedLineSet", "IndexedTriangleFanSet", "IndexedTriangleSet", "IndexedTriangleStripSet",
"Inline", "IntegerSequencer", "IntegerTrigger", "IS", "KeySensor", "LineProperties", "LineSet",
"LoadSensor", "LOD", "Material", "meta", "MetadataDouble", "MetadataFloat", "MetadataInteger",
"MetadataSet", "MetadataString", "MovieTexture", "MultiTexture", "MultiTextureCoordinate",
"MultiTextureTransform", "NavigationInfo", "Normal", "NormalInterpolator", "NurbsCurve",
"NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
"NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface",
"NurbsSwungSurface", "NurbsTextureCoordinate", "NurbsTrimmedSurface", "OrientationInterpolator",
"PixelTexture", "PlaneSensor", "PointLight", "PointSet", "Polyline2D", "Polypoint2D",
"PositionInterpolator", "PositionInterpolator2D", "ProtoBody", "ProtoDeclare", "ProtoInstance",
"ProtoInterface", "ProximitySensor", "ReceiverPdu", "Rectangle2D", "ROUTE", "ScalarInterpolator",
"Scene", "Script", "Shape", "SignalPdu", "Sound", "Sphere", "SphereSensor", "SpotLight", "StaticGroup",
"StringSensor", "Switch", "Text", "TextureBackground", "TextureCoordinate", "TextureCoordinateGenerator",
"TextureTransform", "TimeSensor", "TimeTrigger", "TouchSensor", "Transform", "TransmitterPdu",
"TriangleFanSet", "TriangleSet", "TriangleSet2D", "TriangleStripSet", "Viewpoint", "VisibilitySensor",
"WorldInfo", "X3D", "XvlShell", "VertexShader", "FragmentShader", "MultiShaderAppearance", "ShaderAppearance"}
def clamp_color(col):
return tuple([max(min(c, 1.0), 0.0) for c in col])
def matrix_direction(mtx):
return (mathutils.Vector((0.0, 0.0, -1.0)) * mtx.to_3x3()).normalized()[:]
Campbell Barton
committed
def clean_str(name, prefix='rsvd_'):
"""cleanStr(name,prefix) - try to create a valid VRML DEF name from object name"""
newName = name
if newName in x3d_names_reserved:
newName = '%s%s' % (prefix, newName)
if newName[0].isdigit():
newName = "%s%s" % ("_", newName)
for bad in [' ', '"', '#', "'", ', ', '.', '[', '\\', ']', '{', '}']:
newName = newName.replace(bad, "_")
return newName
namesFog = ("", "LINEAR", "EXPONENTIAL", "")
##########################################################
# Functions for writing output file
##########################################################
def export(file,
global_matrix,
scene,
use_apply_modifiers=False,
use_selection=True,
EXPORT_TRI=False,):
Campbell Barton
committed
##########################################################
# Writing nodes routines
##########################################################
def writeHeader(ident):
Campbell Barton
committed
filepath = fw.__self__.name
#bfile = sys.expandpath( Blender.Get('filepath') ).replace('<', '<').replace('>', '>')
Campbell Barton
committed
bfile = repr(os.path.basename(filepath).replace('<', '<').replace('>', '>'))[1:-1] # use outfile name
fw("%s<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" % ident)
fw("%s<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n" % ident)
fw("%s<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" % ident)
ident += "\t"
fw("%s<head>\n" % ident)
ident += "\t"
fw("%s<meta name=\"filename\" content=\"%s\" />\n" % (ident, bfile))
fw("%s<meta name=\"generator\" content=\"Blender %s\" />\n" % (ident, bpy.app.version_string))
fw("%s<meta name=\"translator\" content=\"X3D exporter v1.55 (2006/01/17)\" />\n" % ident)
ident = ident[:-1]
fw("%s</head>\n" % ident)
fw("%s<Scene>\n" % ident)
ident += "\t"
return ident
def writeFooter(ident):
Campbell Barton
committed
ident = ident[:-1]
fw("%s</Scene>\n" % ident)
ident = ident[:-1]
fw("%s</X3D>" % ident)
return ident
def writeViewpoint(ident, ob, mat, scene):
loc, quat, scale = mat.decompose()
Campbell Barton
committed
fw("%s<Viewpoint DEF=\"%s\" " % (ident, clean_str(ob.name)))
fw("description=\"%s\" " % ob.name)
fw("centerOfRotation=\"0 0 0\" ")
fw("position=\"%3.2f %3.2f %3.2f\" " % loc[:])
fw("orientation=\"%3.2f %3.2f %3.2f %3.2f\" " % (quat.axis[:] + (quat.angle, )))
fw("fieldOfView=\"%.3g\" " % ob.data.angle)
fw(" />\n")
def writeFog(ident, world):
if world:
mtype = world.mist_settings.falloff
mparam = world.mist_settings
else:
return
mtype = 1 if mtype == 'LINEAR' else 2
Campbell Barton
committed
fw("%s<Fog fogType=\"%s\" " % (ident, __class__.namesFog[mtype]))
fw("color=\"%.3g %.3g %.3g\" " % clamp_color(world.horizon_color))
fw("visibilityRange=\"%.3g\" />\n" % mparam.depth)
else:
return
def writeNavigationInfo(ident, scene):
Campbell Barton
committed
fw('%s<NavigationInfo headlight="false" visibilityLimit="0.0" type=\'"EXAMINE","ANY"\' avatarSize="0.25, 1.75, 0.75" />\n' % ident)
def writeSpotLight(ident, ob, mtx, lamp, world):
Campbell Barton
committed
safeName = clean_str(ob.name)
if world:
ambi = world.ambient_color
amb_intensity = ((ambi[0] + ambi[1] + ambi[2]) / 3.0) / 2.5
del ambi
else:
amb_intensity = 0.0
# compute cutoff and beamwidth
intensity = min(lamp.energy / 1.75, 1.0)
beamWidth = lamp.spot_size * 0.37
# beamWidth=((lamp.spotSize*math.pi)/180.0)*.37
cutOffAngle = beamWidth * 1.3
dx, dy, dz = matrix_direction(mtx)
radius = lamp.distance * math.cos(beamWidth)
# radius = lamp.dist*math.cos(beamWidth)
Campbell Barton
committed
fw("%s<SpotLight DEF=\"%s\" " % (ident, safeName))
fw("radius=\"%.4g\" " % radius)
fw("ambientIntensity=\"%.4g\" " % amb_intensity)
fw("intensity=\"%.4g\" " % intensity)
fw("color=\"%.4g %.4g %.4g\" " % clamp_color(lamp.color))
fw("beamWidth=\"%.4g\" " % beamWidth)
fw("cutOffAngle=\"%.4g\" " % cutOffAngle)
fw("direction=\"%.4g %.4g %.4g\" " % (dx, dy, dz))
fw("location=\"%.4g %.4g %.4g\" />\n" % location)
def writeDirectionalLight(ident, ob, mtx, lamp, world):
Campbell Barton
committed
safeName = clean_str(ob.name)
if world:
ambi = world.ambient_color
# ambi = world.amb
amb_intensity = ((float(ambi[0] + ambi[1] + ambi[2])) / 3.0) / 2.5
else:
ambi = 0
amb_intensity = 0.0
intensity = min(lamp.energy / 1.75, 1.0)
dx, dy, dz = matrix_direction(mtx)
Campbell Barton
committed
fw("%s<DirectionalLight DEF=\"%s\" " % (ident, safeName))
fw("ambientIntensity=\"%.4g\" " % amb_intensity)
fw("color=\"%.4g %.4g %.4g\" " % clamp_color(lamp.color))
fw("intensity=\"%.4g\" " % intensity)
fw("direction=\"%.4g %.4g %.4g\" />\n" % (dx, dy, dz))
def writePointLight(ident, ob, mtx, lamp, world):
Campbell Barton
committed
safeName = clean_str(ob.name)
if world:
ambi = world.ambient_color
# ambi = world.amb
amb_intensity = ((float(ambi[0] + ambi[1] + ambi[2])) / 3.0) / 2.5
else:
ambi = 0.0
amb_intensity = 0.0
intensity = min(lamp.energy / 1.75, 1.0)
Campbell Barton
committed
fw("%s<PointLight DEF=\"%s\" " % (ident, safeName))
fw("ambientIntensity=\"%.4g\" " % amb_intensity)
fw("color=\"%.4g %.4g %.4g\" " % clamp_color(lamp.color))
Campbell Barton
committed
fw("intensity=\"%.4g\" " % intensity)
fw("radius=\"%.4g\" " % lamp.distance)
fw("location=\"%.4g %.4g %.4g\" />\n" % location)
def secureName(name):
name = name + str(secureName.nodeID)
secureName.nodeID += 1
if len(name) <= 3:
newname = "_" + str(secureName.nodeID)
return "%s" % (newname)
else:
for bad in ('"', '#', "'", ', ', '.', '[', '\\', ']', '{', '}'):
name = name.replace(bad, "_")
Campbell Barton
committed
if name in x3d_names_reserved:
newname = name[0:3] + "_" + str(secureName.nodeID)
return "%s" % (newname)
elif name[0].isdigit():
newname = "_" + name + str(secureName.nodeID)
return "%s" % (newname)
else:
newname = name
return "%s" % (newname)
def writeIndexedFaceSet(ident, ob, mesh, mtx, world, EXPORT_TRI=False):
Campbell Barton
committed
shape_name_x3d = clean_str(ob.name)
mesh_name_x3d = clean_str(mesh.name)
if not mesh.faces:
return
Campbell Barton
committed
texface_use_halo = 0
texface_use_billboard = 0
texface_use_collision = 0
use_halonode = False
use_billnode = False
use_collnode = False
if mesh.uv_textures.active: # if mesh.faceUV:
for face in mesh.uv_textures.active.data: # for face in mesh.faces:
texface_use_halo |= face.use_halo
texface_use_billboard |= face.use_billboard
texface_use_collision |= face.use_collision
# texface_use_object_color |= face.use_object_color
Campbell Barton
committed
if texface_use_halo:
fw("%s<Billboard axisOfRotation=\"0 0 0\">\n" % ident)
use_halonode = True
ident += "\t"
elif texface_use_billboard:
fw("%s<Billboard axisOfRotation=\"0 1 0\">\n" % ident)
use_billnode = True
ident += "\t"
elif texface_use_collision:
fw("%s<Collision enabled=\"false\">\n" % ident)
use_collnode = True
ident += "\t"
del texface_use_halo
del texface_use_billboard
del texface_use_collision
# del texface_use_object_color
loc, quat, sca = mtx.decompose()
Campbell Barton
committed
fw("%s<Transform DEF=\"%s\" " % (ident, shape_name_x3d))
fw("translation=\"%.6g %.6g %.6g\" " % loc[:])
fw("scale=\"%.6g %.6g %.6g\" " % sca[:])
fw("rotation=\"%.6g %.6g %.6g %.6g\" " % (quat.axis[:] + (quat.angle, )))
fw(">\n")
Campbell Barton
committed
ident += "\t"
if mesh.tag:
Campbell Barton
committed
fw("%s<Group USE=\"G_%s\" />\n" % (ident, mesh_name_x3d))
else:
mesh.tag = True
Campbell Barton
committed
fw("%s<Group DEF=\"G_%s\">\n" % (ident, mesh_name_x3d))
ident += "\t"
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
is_uv = bool(mesh.uv_textures.active)
# is_col, defined for each material
is_coords_written = False
mesh_materials = mesh.materials[:]
if not mesh_materials:
mesh_materials = [None]
mesh_material_tex = [None] * len(mesh_materials)
mesh_material_mtex = [None] * len(mesh_materials)
mesh_material_images = [None] * len(mesh_materials)
for i, material in enumerate(mesh_materials):
if material:
for mtex in material.texture_slots:
if mtex:
tex = mtex.texture
if tex and tex.type == 'IMAGE':
image = tex.image
if image:
mesh_material_tex[i] = tex
mesh_material_mtex[i] = mtex
mesh_material_images[i] = image
break
mesh_materials_use_face_texture = [getattr(material, "use_face_texture", True) for material in mesh_materials]
mesh_faces = mesh.faces[:]
mesh_faces_materials = [f.material_index for f in mesh_faces]
Campbell Barton
committed
if is_uv and True in mesh_materials_use_face_texture:
mesh_faces_image = [(fuv.image if (mesh_materials_use_face_texture[mesh_faces_materials[i]] and fuv.use_image) else mesh_material_images[mesh_faces_materials[i]]) for i, fuv in enumerate(mesh.uv_textures.active.data)]
mesh_faces_image_unique = set(mesh_faces_image)
elif len(set(mesh_material_images) | {None}) > 1: # make sure there is at least one image
mesh_faces_image = [mesh_material_images[material_index] for material_index in mesh_faces_materials]
mesh_faces_image_unique = set(mesh_faces_image)
else:
mesh_faces_image = [None] * len(mesh_faces)
mesh_faces_image_unique = {None}
# group faces
face_groups = {}
for material_index in range(len(mesh_materials)):
for image in mesh_faces_image_unique:
face_groups[material_index, image] = []
del mesh_faces_image_unique
for i, (material_index, image) in enumerate(zip(mesh_faces_materials, mesh_faces_image)):
face_groups[material_index, image].append(i)
# same as face_groups.items() but sorted so we can get predictable output.
face_groups_items = list(face_groups.items())
face_groups_items.sort(key=lambda m: (m[0][0], getattr(m[0][1], "name", "")))
for (material_index, image), face_group in face_groups_items: # face_groups.items()
if face_group:
material = mesh_materials[material_index]
Campbell Barton
committed
fw("%s<Shape>\n" % ident)
ident += "\t"
is_smooth = False
is_col = (mesh.vertex_colors.active and (material is None or material.use_vertex_color_paint))
# kludge but as good as it gets!
for i in face_group:
if mesh_faces[i].use_smooth:
is_smooth = True
break
Campbell Barton
committed
fw("%s<Appearance>\n" % ident)
ident += "\t"
Campbell Barton
committed
if image:
writeImageTexture(ident, image)
if mesh_materials_use_face_texture[material_index]:
if image.use_tiles:
Campbell Barton
committed
fw("%s<TextureTransform scale=\"%s %s\" />\n" % (ident, image.tiles_x, image.tiles_y))
else:
# transform by mtex
loc = mesh_material_mtex[material_index].offset[:2]
# mtex_scale * tex_repeat
sca_x, sca_y = mesh_material_mtex[material_index].scale[:2]
sca_x *= mesh_material_tex[material_index].repeat_x
sca_y *= mesh_material_tex[material_index].repeat_y
# flip x/y is a sampling feature, convert to transform
if mesh_material_tex[material_index].use_flip_axis:
rot = math.pi / -2.0
sca_x, sca_y = sca_y, -sca_x
else:
rot = 0.0
Campbell Barton
committed
fw("%s<TextureTransform " % ident)
# fw("center=\"%.6g %.6g\" " % (0.0, 0.0))
fw("translation=\"%.6g %.6g\" " % loc)
fw("scale=\"%.6g %.6g\" " % (sca_x, sca_y))
fw("rotation=\"%.6g\" " % rot)
fw("/>\n")
Campbell Barton
committed
if material:
writeMaterial(ident, material, clean_str(material.name, ""), world)
Campbell Barton
committed
Campbell Barton
committed
ident = ident[:-1]
fw("%s</Appearance>\n" % ident)
#-- IndexedFaceSet or IndexedLineSet
Campbell Barton
committed
fw("%s<IndexedFaceSet " % ident)
ident += "\t"
# --- Write IndexedFaceSet Attributes
if mesh.show_double_sided:
fw("solid=\"true\" ")
else:
fw("solid=\"false\" ")
if is_smooth:
Campbell Barton
committed
fw("creaseAngle=\"%.4g\" " % mesh.auto_smooth_angle)
if is_uv:
# "texCoordIndex"
Campbell Barton
committed
fw("%stexCoordIndex=\"" % ident)
j = 0
for i in face_group:
if len(mesh_faces[i].vertices) == 4:
fw("%d %d %d %d -1, " % (j, j + 1, j + 2, j + 3))
j += 4
else:
fw("%d %d %d -1, " % (j, j + 1, j + 2))
j += 3
fw("\" ")
# --- end texCoordIndex
if is_col:
fw("colorPerVertex=\"false\" ")
if True:
# "coordIndex"
if EXPORT_TRI:
for i in face_group:
fv = mesh_faces[i].vertices[:]
if len(fv) == 3:
fw("%i %i %i -1, " % fv)
else:
fw("%i %i %i -1, " % (fv[0], fv[1], fv[2]))
fw("%i %i %i -1, " % (fv[0], fv[2], fv[3]))
else:
for i in face_group:
fv = mesh_faces[i].vertices[:]
if len(fv) == 3:
fw("%i %i %i -1, " % fv)
else:
fw("%i %i %i %i -1, " % fv)
fw("\" ")
# --- end coordIndex
# close IndexedFaceSet
fw(">\n")
# --- Write IndexedFaceSet Elements
if True:
if is_coords_written:
Campbell Barton
committed
fw("%s<Coordinate USE=\"%s%s\" />\n" % (ident, "coord_", mesh_name_x3d))
else:
Campbell Barton
committed
fw("%s<Coordinate DEF=\"%s%s\" " % (ident, "coord_", mesh_name_x3d))
fw("point=\"")
for v in mesh.vertices:
Campbell Barton
committed
fw("%.6g %.6g %.6g, " % v.co[:])
fw("\" />\n")
is_coords_written = True
if is_uv:
Campbell Barton
committed
fw("%s<TextureCoordinate point=\"" % ident)
mesh_faces_uv = mesh.uv_textures.active.data
for i in face_group:
for uv in mesh_faces_uv[i].uv:
Campbell Barton
committed
fw("%.4g %.4g, " % uv[:])
del mesh_faces_uv
Campbell Barton
committed
fw("\" />\n")
if is_col:
Campbell Barton
committed
fw("%s<Color color=\"" % ident)
# XXX, 1 color per face, only
mesh_faces_col = mesh.vertex_colors.active.data
for i in face_group:
Campbell Barton
committed
fw("%.3g %.3g %.3g, " % mesh_faces_col[i].color1[:])
del mesh_faces_col
Campbell Barton
committed
fw("\" />\n")
#--- output vertexColors
#--- output closing braces
Campbell Barton
committed
ident = ident[:-1]
fw("%s</IndexedFaceSet>\n" % ident)
ident = ident[:-1]
fw("%s</Shape>\n" % ident)
ident = ident[:-1]
fw("%s</Group>\n" % ident)
ident = ident[:-1]
fw("%s</Transform>\n" % ident)
if use_halonode:
ident = ident[:-1]
fw("%s</Billboard>\n" % ident)
elif use_billnode:
ident = ident[:-1]
fw("%s</Billboard>\n" % ident)
elif use_collnode:
ident = ident[:-1]
fw("%s</Collision>\n" % ident)
def writeMaterial(ident, mat, matName, world):
# look up material name, use it if available
if mat.tag:
Campbell Barton
committed
fw("%s<Material USE=\"MA_%s\" />\n" % (ident, matName))
else:
mat.tag = True
emit = mat.emit
ambient = mat.ambient / 3.0
diffuseColor = tuple(mat.diffuse_color)
if world:
ambiColor = tuple(((c * mat.ambient) * 2.0) for c in world.ambient_color)
else:
ambiColor = 0.0, 0.0, 0.0
emitColor = tuple(((c * emit) + ambiColor[i]) / 2.0 for i, c in enumerate(diffuseColor))
shininess = mat.specular_hardness / 512.0
specColor = tuple((c + 0.001) / (1.25 / (mat.specular_intensity + 0.001)) for c in mat.specular_color)
transp = 1.0 - mat.alpha
if mat.use_shadeless:
ambient = 1.0
shininess = 0.0
specColor = emitColor = diffuseColor
Campbell Barton
committed
fw("%s<Material DEF=\"MA_%s\" " % (ident, matName))
fw("diffuseColor=\"%.3g %.3g %.3g\" " % clamp_color(diffuseColor))
fw("specularColor=\"%.3g %.3g %.3g\" " % clamp_color(specColor))
fw("emissiveColor=\"%.3g %.3g %.3g\" " % clamp_color(emitColor))
fw("ambientIntensity=\"%.3g\" " % ambient)
fw("shininess=\"%.3g\" " % shininess)
fw("transparency=\"%s\" />\n" % transp)
def writeImageTexture(ident, image):
name = image.name
if image.tag:
Campbell Barton
committed
fw("%s<ImageTexture USE=\"%s\" />\n" % (ident, clean_str(name)))
else:
image.tag = True
Campbell Barton
committed
fw("%s<ImageTexture DEF=\"%s\" " % (ident, clean_str(name)))
filepath = image.filepath
Campbell Barton
committed
relpath = os.path.dirname(fw.__self__.name) # could cache
filepath_full = bpy.path.abspath(filepath)
# collect image paths, can load multiple
Campbell Barton
committed
# [relative, name-only, absolute]
images = []
Campbell Barton
committed
if bpy.path.is_subdir(filepath_full, relpath):
images.append(os.path.relpath(filepath_full, relpath))
images.append(os.path.basename(filepath_full))
Campbell Barton
committed
images.append(filepath_full)
Campbell Barton
committed
fw("url='%s' />\n" % " ".join(["\"%s\"" % f.replace("\\", "/") for f in images]))
def writeBackground(ident, world):
if world:
worldname = world.name
else:
return
blending = world.use_sky_blend, world.use_sky_paper, world.use_sky_real
grd_triple = clamp_color(world.horizon_color)
sky_triple = clamp_color(world.zenith_color)
mix_triple = clamp_color((grd_triple[i] + sky_triple[i]) / 2.0 for i in range(3))
fw("%s<Background DEF=\"%s\" " % (ident, secureName(worldname)))
# No Skytype - just Hor color
if blending == (False, False, False):
Campbell Barton
committed
fw("groundColor=\"%.3g %.3g %.3g\" " % grd_triple)
fw("skyColor=\"%.3g %.3g %.3g\" " % grd_triple)
# Blend Gradient
elif blending == (True, False, False):
Campbell Barton
committed
fw("groundColor=\"%.3g %.3g %.3g, " % grd_triple)
fw("%.3g %.3g %.3g\" groundAngle=\"1.57, 1.57\" " % mix_triple)
fw("skyColor=\"%.3g %.3g %.3g, " % sky_triple)
fw("%.3g %.3g %.3g\" skyAngle=\"1.57, 1.57\" " % mix_triple)
# Blend+Real Gradient Inverse
elif blending == (True, False, True):
Campbell Barton
committed
fw("groundColor=\"%.3g %.3g %.3g, %.3g %.3g %.3g\" " % (sky_triple + grd_triple))
fw("groundAngle=\"1.57\" ")
fw("skyColor=\"%.3g %.3g %.3g, %.3g %.3g %.3g, %.3g %.3g %.3g\" " % (sky_triple + grd_triple + sky_triple))
fw("skyAngle=\"1.57, 3.14159\" ")
# Paper - just Zen Color
elif blending == (False, False, True):
Campbell Barton
committed
fw("groundColor=\"%.3g %.3g %.3g\" " % sky_triple)
fw("skyColor=\"%.3g %.3g %.3g\" " % sky_triple)
# Blend+Real+Paper - komplex gradient
elif blending == (True, True, True):
Campbell Barton
committed
fw("groundColor=\"%.3g %.3g %.3g, " % sky_triple)
fw("%.3g %.3g %.3g\" groundAngle=\"1.57, 1.57\" " % grd_triple)
fw("skyColor=\"%.3g %.3g %.3g, " % sky_triple)
fw("%.3g %.3g %.3g\" skyAngle=\"1.57, 1.57\" " % grd_triple)
# Any Other two colors
else:
Campbell Barton
committed
fw("groundColor=\"%.3g %.3g %.3g\" " % grd_triple)
fw("skyColor=\"%.3g %.3g %.3g\" " % sky_triple)
if tex.type == 'IMAGE' and tex.image:
namemat = tex.name
pic = tex.image
basename = os.path.basename(bpy.path.abspath(pic.filepath))
Campbell Barton
committed
fw("\n\tbackUrl=\"%s\" " % basename)
Campbell Barton
committed
fw("bottomUrl=\"%s\" " % basename)
Campbell Barton
committed
fw("frontUrl=\"%s\" " % basename)
Campbell Barton
committed
fw("leftUrl=\"%s\" " % basename)
Campbell Barton
committed
fw("rightUrl=\"%s\" " % basename)
Campbell Barton
committed
fw("topUrl=\"%s\" " % basename)
Campbell Barton
committed
fw("/>\n")
##########################################################
# export routine
##########################################################
# tag un-exported IDs
bpy.data.meshes.tag(False)
bpy.data.materials.tag(False)
bpy.data.images.tag(False)
print("Info: starting X3D export to %r..." % file.name)
Campbell Barton
committed
ident = ""
ident = writeHeader(ident)
Campbell Barton
committed
writeNavigationInfo(ident, scene)
writeBackground(ident, world)
writeFog(ident, world)
Campbell Barton
committed
ident = "\t\t"
Campbell Barton
committed
if use_selection:
objects = (o for o in scene.objects if o.is_visible(scene) and o.select)
else:
objects = (o for o in scene.objects if o.is_visible(scene))
for ob_main in objects:
free, derived = create_derived_objects(scene, ob_main)
if derived is None:
continue
for ob, ob_mat in derived:
objType = ob.type
objName = ob.name
ob_mat = global_matrix * ob_mat
if objType == 'CAMERA':
writeViewpoint(ident, ob, ob_mat, scene)
elif objType in ('MESH', 'CURVE', 'SURF', 'FONT'):
Campbell Barton
committed
if (objType != 'MESH') or (use_apply_modifiers and ob.is_modified(scene, 'PREVIEW')):
Campbell Barton
committed
try:
me = ob.to_mesh(scene, use_apply_modifiers, 'PREVIEW')
Campbell Barton
committed
except:
me = None
else:
me = ob.data
Campbell Barton
committed
if me is not None:
writeIndexedFaceSet(ident, ob, me, ob_mat, world, EXPORT_TRI=EXPORT_TRI)
Campbell Barton
committed
# free mesh created with create_mesh()
if me != ob.data:
bpy.data.meshes.remove(me)
elif objType == 'LAMP':
data = ob.data
datatype = data.type
if datatype == 'POINT':
writePointLight(ident, ob, ob_mat, data, world)
elif datatype == 'SPOT':
writeSpotLight(ident, ob, ob_mat, data, world)
elif datatype == 'SUN':
writeDirectionalLight(ident, ob, ob_mat, data, world)
else:
writeDirectionalLight(ident, ob, ob_mat, data, world)
else:
#print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType)
pass
if free:
free_derived_objects(ob_main)
ident = writeFooter(ident)
export_main()
file.close()
print("Info: finished X3D export to %r" % file.name)
##########################################################
# Callbacks, needed before Main
##########################################################
def save(operator, context, filepath="",
use_selection=True,
use_apply_modifiers=False,
use_triangulate=False,
use_compress=False,
global_matrix=None,
):
if use_compress:
if not filepath.lower().endswith('.x3dz'):
filepath = '.'.join(filepath.split('.')[:-1]) + '.x3dz'
else:
if not filepath.lower().endswith('.x3d'):
filepath = '.'.join(filepath.split('.')[:-1]) + '.x3d'
if bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='OBJECT')
file = None
if filepath.lower().endswith('.x3dz'):
try:
import gzip
file = gzip.open(filepath, "w")
except:
print("failed to import compression modules, exporting uncompressed")
filepath = filepath[:-1] # remove trailing z
if file is None:
file = open(filepath, "w")
if global_matrix is None:
global_matrix = mathutils.Matrix()
export(file,
global_matrix,
context.scene,
use_apply_modifiers=use_apply_modifiers,
use_selection=use_selection,
EXPORT_TRI=use_triangulate,
)
return {'FINISHED'}