bgfx/3rdparty/openctm/plugins/blender/openctm_import.py
2012-10-07 20:41:18 -07:00

226 lines
No EOL
6.1 KiB
Python

#!BPY
"""
Name: 'OpenCTM (*.ctm)...'
Blender: 248
Group: 'Import'
Tooltip: 'Import an OpenCTM file'
"""
import bpy
import Blender
from Blender import Mesh, Scene, Window, sys, Image, Draw
import BPyMesh
import math
import ctypes
from ctypes import *
from ctypes.util import find_library
import os
__author__ = "Marcus Geelnard"
__version__ = "0.4"
__bpydoc__ = """\
This script imports OpenCTM files into Blender. It supports normals,
colours, and UV coordinates per vertex.
"""
# Copyright (C) 2009-2010: Marcus Geelnard
#
# This program is released to the public domain.
#
# Portions of this code are taken from ply_import.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
# - Better error reporting
#
# v0.1, 2009-05-31
# - First test version with an alpha version of the OpenCTM API
#
def file_callback(filename):
Window.WaitCursor(1)
try:
# 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
ctmLoad = libHDL.ctmLoad
ctmLoad.argtypes = [c_void_p, c_char_p]
ctmGetInteger = libHDL.ctmGetInteger
ctmGetInteger.argtypes = [c_void_p, c_int]
ctmGetInteger.restype = c_int
ctmGetString = libHDL.ctmGetString
ctmGetString.argtypes = [c_void_p, c_int]
ctmGetString.restype = c_char_p
ctmGetIntegerArray = libHDL.ctmGetIntegerArray
ctmGetIntegerArray.argtypes = [c_void_p, c_int]
ctmGetIntegerArray.restype = POINTER(c_int)
ctmGetFloatArray = libHDL.ctmGetFloatArray
ctmGetFloatArray.argtypes = [c_void_p, c_int]
ctmGetFloatArray.restype = POINTER(c_float)
ctmGetNamedAttribMap = libHDL.ctmGetNamedAttribMap
ctmGetNamedAttribMap.argtypes = [c_void_p, c_char_p]
ctmGetNamedAttribMap.restype = c_int
# Create an OpenCTM context
ctm = ctmNewContext(0x0101) # CTM_IMPORT
try:
# Load the file
ctmLoad(ctm, c_char_p(filename))
err = ctmGetError(ctm)
if err != 0:
s = ctmErrorString(err)
Blender.Draw.PupMenu('Could not load the file: ' + s)
return
# Get the mesh properties
vertexCount = ctmGetInteger(ctm, 0x0301) # CTM_VERTEX_COUNT
triangleCount = ctmGetInteger(ctm, 0x0302) # CTM_TRIANGLE_COUNT
hasNormals = ctmGetInteger(ctm, 0x0303) # CTM_HAS_NORMALS
texMapCount = ctmGetInteger(ctm, 0x0304) # CTM_UV_MAP_COUNT
# Get indices
pindices = ctmGetIntegerArray(ctm, 0x0601) # CTM_INDICES
# Get vertices
pvertices = ctmGetFloatArray(ctm, 0x0602) # CTM_VERTICES
# Get normals
if hasNormals == 1:
pnormals = ctmGetFloatArray(ctm, 0x0603) # CTM_NORMALS
else:
pnormals = None
# Get texture coordinates
if texMapCount > 0:
ptexCoords = ctmGetFloatArray(ctm, 0x0700) # CTM_UV_MAP_1
else:
ptexCoords = None
# Get colors
colorMap = ctmGetNamedAttribMap(ctm, c_char_p('Color'))
if colorMap != 0:
pcolors = ctmGetFloatArray(ctm, colorMap)
else:
pcolors = None
# We will be creating vectors...
Vector = Blender.Mathutils.Vector
# Create Blender verts and faces
verts = []
for i in range(vertexCount):
verts.append(Vector(pvertices[i * 3], pvertices[i * 3 + 1], pvertices[i * 3 + 2]))
faces = []
for i in range(triangleCount):
faces.append((pindices[i * 3], pindices[i * 3 + 1], pindices[i * 3 + 2]))
# Create a new Blender mesh from the loaded mesh data
objName = Blender.sys.splitext(Blender.sys.basename(filename))[0]
mesh = bpy.data.meshes.new(objName)
mesh.verts.extend(verts)
mesh.faces.extend(faces)
# Add normals?
if pnormals:
i = 0
for v in mesh.verts:
n = Vector(pnormals[i], pnormals[i + 1], pnormals[i + 2])
v.no = n
i += 3
else:
mesh.calcNormals()
# Always use smooth normals - regardless if they are defined or calculated
for f in mesh.faces:
f.smooth = 1
# Add texture coordinates?
if ptexCoords:
mesh.faceUV = 1
for f in mesh.faces:
for j, v in enumerate(f.v):
k = v.index
if k < vertexCount:
uv = f.uv[j]
uv[0] = ptexCoords[k * 2]
uv[1] = ptexCoords[k * 2 + 1]
# Add colors?
if pcolors:
mesh.vertexColors = 1
for f in mesh.faces:
for j, v in enumerate(f.v):
k = v.index
if k < vertexCount:
col = f.col[j]
r = int(round(pcolors[k * 4] * 255.0))
if r < 0: r = 0
if r > 255: r = 255
g = int(round(pcolors[k * 4 + 1] * 255.0))
if g < 0: g = 0
if g > 255: g = 255
b = int(round(pcolors[k * 4 + 2] * 255.0))
if b < 0: b = 0
if b > 255: b = 255
col.r = r
col.g = g
col.b = b
# Select all vertices in the mesh
mesh.sel = True
# Create a new object with the new mesh
scn = bpy.data.scenes.active
scn.objects.selected = []
obj = scn.objects.new(mesh, objName)
scn.objects.active = obj
finally:
# Free the OpenCTM context
ctmFreeContext(ctm)
finally:
Window.WaitCursor(0)
Blender.Redraw()
def main():
Blender.Window.FileSelector(file_callback, 'Import OpenCTM', '*.ctm')
if __name__=='__main__':
main()