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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
|
#!BPY
"""
Name: 'OpenCTM (*.ctm)...'
Blender: 248
Group: 'Export'
Tooltip: 'Export active object to OpenCTM (compressed) format'
"""
import bpy
import Blender
from Blender import Mesh, Scene, Window, sys, Image, Draw
import BPyMesh
import ctypes
from ctypes import *
from ctypes.util import find_library
import os
__author__ = "Marcus Geelnard"
__version__ = "0.4"
__bpydoc__ = """\
This script exports OpenCTM files from Blender. It supports normals,
colours, and UV coordinates per vertex. Only one mesh can be exported
at a time.
"""
# Copyright (C) 2009-2010: Marcus Geelnard
#
# This program is released to the public domain.
#
# Portions of this code are taken from ply_export.py in Blender
# 2.48.
#
# The script uses the OpenCTM shared library (.so, .dll, etc). If no
# such library can be found, the script will exit with an error
# message.
#
# v0.4, 2009-09-14
# - Updated to OpenCTM API version 0.8 (texture maps are now called UV maps)
#
# v0.3, 2009-08-09
# - Changed vertex color attribute name to "Color"
#
# v0.2, 2009-06-30
# - Added precision settings for MG2 export
# - Added some error checking
#
# v0.1, 2009-05-31
# - First test version with an alpha version of the OpenCTM API
#
def file_callback(filename):
if not filename.lower().endswith('.ctm'):
filename += '.ctm'
# Get object mesh from the selected object
scn = bpy.data.scenes.active
ob = scn.objects.active
if not ob:
Blender.Draw.PupMenu('Error%t|Select 1 active object')
return
mesh = BPyMesh.getMeshFromObject(ob, None, False, False, scn)
if not mesh:
Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object')
return
# Check which mesh properties are present...
hasVertexUV = mesh.vertexUV or mesh.faceUV
hasVertexColors = mesh.vertexColors
# Show a GUI for the export settings
pupBlock = []
EXPORT_APPLY_MODIFIERS = Draw.Create(1)
pupBlock.append(('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data.'))
EXPORT_NORMALS = Draw.Create(1)
pupBlock.append(('Normals', EXPORT_NORMALS, 'Export vertex normal data.'))
if hasVertexUV:
EXPORT_UV = Draw.Create(1)
pupBlock.append(('UVs', EXPORT_UV, 'Export texface UV coords.'))
if hasVertexColors:
EXPORT_COLORS = Draw.Create(1)
pupBlock.append(('Colors', EXPORT_COLORS, 'Export vertex Colors.'))
EXPORT_MG2 = Draw.Create(0)
pupBlock.append(('Fixed Point', EXPORT_MG2, 'Use limited precision algorithm (MG2 method = better compression).'))
if not Draw.PupBlock('Export...', pupBlock):
return
# Adjust export settings according to GUI selections
EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val
EXPORT_NORMALS = EXPORT_NORMALS.val
if hasVertexUV:
EXPORT_UV = EXPORT_UV.val
else:
EXPORT_UV = False
if hasVertexColors:
EXPORT_COLORS = EXPORT_COLORS.val
else:
EXPORT_COLORS = False
EXPORT_MG2 = EXPORT_MG2.val
# If the user wants to export MG2, then show another GUI...
if EXPORT_MG2:
pupBlock = []
EXPORT_VPREC = Draw.Create(0.01)
pupBlock.append(('Vertex', EXPORT_VPREC, 0.0001, 1.0, 'Relative vertex precision (fixed point).'))
if EXPORT_NORMALS:
EXPORT_NPREC = Draw.Create(1.0/256.0)
pupBlock.append(('Normal', EXPORT_NPREC, 0.0001, 1.0, 'Normal precision (fixed point).'))
if EXPORT_UV:
EXPORT_UVPREC = Draw.Create(1.0/1024.0)
pupBlock.append(('UV', EXPORT_UVPREC, 0.0001, 1.0, 'UV precision (fixed point).'))
if EXPORT_COLORS:
EXPORT_CPREC = Draw.Create(1.0/256.0)
pupBlock.append(('Color', EXPORT_CPREC, 0.0001, 1.0, 'Color precision (fixed point).'))
if not Draw.PupBlock('Fixed point precision...', pupBlock):
return
# Adjust export settings according to GUI selections
if EXPORT_MG2:
EXPORT_VPREC = EXPORT_VPREC.val
else:
EXPORT_VPREC = 0.1
if EXPORT_MG2 and EXPORT_NORMALS:
EXPORT_NPREC = EXPORT_NPREC.val
else:
EXPORT_NPREC = 0.1
if EXPORT_MG2 and EXPORT_UV:
EXPORT_UVPREC = EXPORT_UVPREC.val
else:
EXPORT_UVPREC = 0.1
if EXPORT_MG2 and EXPORT_COLORS:
EXPORT_CPREC = EXPORT_CPREC.val
else:
EXPORT_CPREC = 0.1
is_editmode = Blender.Window.EditMode()
if is_editmode:
Blender.Window.EditMode(0, '', 0)
Window.WaitCursor(1)
try:
# Get the mesh, again, if we wanted modifiers (from GUI selection)
if EXPORT_APPLY_MODIFIERS:
mesh = BPyMesh.getMeshFromObject(ob, None, EXPORT_APPLY_MODIFIERS, False, scn)
if not mesh:
Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object')
return
mesh.transform(ob.matrixWorld, True)
# Count triangles (quads count as two triangles)
triangleCount = 0
for f in mesh.faces:
if len(f.v) == 4:
triangleCount += 2
else:
triangleCount += 1
# Extract indices from the Blender mesh (quads are split into two triangles)
pindices = cast((c_int * 3 * triangleCount)(), POINTER(c_int))
i = 0
for f in mesh.faces:
pindices[i] = c_int(f.v[0].index)
pindices[i + 1] = c_int(f.v[1].index)
pindices[i + 2] = c_int(f.v[2].index)
i += 3
if len(f.v) == 4:
pindices[i] = c_int(f.v[0].index)
pindices[i + 1] = c_int(f.v[2].index)
pindices[i + 2] = c_int(f.v[3].index)
i += 3
# Extract vertex array from the Blender mesh
vertexCount = len(mesh.verts)
pvertices = cast((c_float * 3 * vertexCount)(), POINTER(c_float))
i = 0
for v in mesh.verts:
pvertices[i] = c_float(v.co.x)
pvertices[i + 1] = c_float(v.co.y)
pvertices[i + 2] = c_float(v.co.z)
i += 3
# Extract normals
if EXPORT_NORMALS:
pnormals = cast((c_float * 3 * vertexCount)(), POINTER(c_float))
i = 0
for v in mesh.verts:
pnormals[i] = c_float(v.no.x)
pnormals[i + 1] = c_float(v.no.y)
pnormals[i + 2] = c_float(v.no.z)
i += 3
else:
pnormals = POINTER(c_float)()
# Extract UVs
if EXPORT_UV:
ptexCoords = cast((c_float * 2 * vertexCount)(), POINTER(c_float))
if mesh.faceUV:
for f in mesh.faces:
for j, v in enumerate(f.v):
k = v.index
if k < vertexCount:
uv = f.uv[j]
ptexCoords[k * 2] = uv[0]
ptexCoords[k * 2 + 1] = uv[1]
else:
i = 0
for v in mesh.verts:
ptexCoords[i] = c_float(v.uvco[0])
ptexCoords[i + 1] = c_float(v.uvco[1])
i += 2
else:
ptexCoords = POINTER(c_float)()
# Extract colors
if EXPORT_COLORS:
pcolors = cast((c_float * 4 * vertexCount)(), POINTER(c_float))
for f in mesh.faces:
for j, v in enumerate(f.v):
k = v.index
if k < vertexCount:
col = f.col[j]
pcolors[k * 4] = col.r / 255.0
pcolors[k * 4 + 1] = col.g / 255.0
pcolors[k * 4 + 2] = col.b / 255.0
pcolors[k * 4 + 3] = 1.0
else:
pcolors = POINTER(c_float)()
# Load the OpenCTM shared library
if os.name == 'nt':
libHDL = WinDLL('openctm.dll')
else:
libName = find_library('openctm')
if not libName:
Blender.Draw.PupMenu('Could not find the OpenCTM shared library')
return
libHDL = CDLL(libName)
if not libHDL:
Blender.Draw.PupMenu('Could not open the OpenCTM shared library')
return
# Get all the functions from the shared library that we need
ctmNewContext = libHDL.ctmNewContext
ctmNewContext.argtypes = [c_int]
ctmNewContext.restype = c_void_p
ctmFreeContext = libHDL.ctmFreeContext
ctmFreeContext.argtypes = [c_void_p]
ctmGetError = libHDL.ctmGetError
ctmGetError.argtypes = [c_void_p]
ctmGetError.restype = c_int
ctmErrorString = libHDL.ctmErrorString
ctmErrorString.argtypes = [c_int]
ctmErrorString.restype = c_char_p
ctmFileComment = libHDL.ctmFileComment
ctmFileComment.argtypes = [c_void_p, c_char_p]
ctmDefineMesh = libHDL.ctmDefineMesh
ctmDefineMesh.argtypes = [c_void_p, POINTER(c_float), c_int, POINTER(c_int), c_int, POINTER(c_float)]
ctmSave = libHDL.ctmSave
ctmSave.argtypes = [c_void_p, c_char_p]
ctmAddUVMap = libHDL.ctmAddUVMap
ctmAddUVMap.argtypes = [c_void_p, POINTER(c_float), c_char_p, c_char_p]
ctmAddUVMap.restype = c_int
ctmAddAttribMap = libHDL.ctmAddAttribMap
ctmAddAttribMap.argtypes = [c_void_p, POINTER(c_float), c_char_p]
ctmAddAttribMap.restype = c_int
ctmCompressionMethod = libHDL.ctmCompressionMethod
ctmCompressionMethod.argtypes = [c_void_p, c_int]
ctmVertexPrecisionRel = libHDL.ctmVertexPrecisionRel
ctmVertexPrecisionRel.argtypes = [c_void_p, c_float]
ctmNormalPrecision = libHDL.ctmNormalPrecision
ctmNormalPrecision.argtypes = [c_void_p, c_float]
ctmUVCoordPrecision = libHDL.ctmUVCoordPrecision
ctmUVCoordPrecision.argtypes = [c_void_p, c_int, c_float]
ctmAttribPrecision = libHDL.ctmAttribPrecision
ctmAttribPrecision.argtypes = [c_void_p, c_int, c_float]
# Create an OpenCTM context
ctm = ctmNewContext(0x0102) # CTM_EXPORT
try:
# Set the file comment
ctmFileComment(ctm, c_char_p('%s - created by Blender %s (www.blender.org)' % (ob.getName(), Blender.Get('version'))))
# Define the mesh
ctmDefineMesh(ctm, pvertices, c_int(vertexCount), pindices, c_int(triangleCount), pnormals)
# Add UV coordinates?
if EXPORT_UV:
tm = ctmAddUVMap(ctm, ptexCoords, c_char_p(), c_char_p())
if EXPORT_MG2:
ctmUVCoordPrecision(ctm, tm, EXPORT_UVPREC)
# Add colors?
if EXPORT_COLORS:
cm = ctmAddAttribMap(ctm, pcolors, c_char_p('Color'))
if EXPORT_MG2:
ctmAttribPrecision(ctm, cm, EXPORT_CPREC)
# Set compression method
if EXPORT_MG2:
ctmCompressionMethod(ctm, 0x0203) # CTM_METHOD_MG2
ctmVertexPrecisionRel(ctm, EXPORT_VPREC)
if EXPORT_NORMALS:
ctmNormalPrecision(ctm, EXPORT_NPREC)
else:
ctmCompressionMethod(ctm, 0x0202) # CTM_METHOD_MG1
# Save the file
ctmSave(ctm, c_char_p(filename))
# Check for errors
e = ctmGetError(ctm)
if e != 0:
s = ctmErrorString(e)
Blender.Draw.PupMenu('Error%t|Could not save the file: ' + s)
finally:
# Free the OpenCTM context
ctmFreeContext(ctm)
finally:
Window.WaitCursor(0)
if is_editmode:
Blender.Window.EditMode(1, '', 0)
def main():
Blender.Window.FileSelector(file_callback, 'Export OpenCTM', Blender.sys.makename(ext='.ctm'))
if __name__=='__main__':
main()
|