hub/venv/lib/python3.7/site-packages/trimesh/exchange/openctm.py

162 lines
5.5 KiB
Python
Raw Normal View History

# Modified from the original OpenCTM python binding
# for inclusion in the `trimesh` package:
# https://github.com/mikedh/trimesh
#
# To get shared library this binding imports, you can download
# and install it on Linux using this bash script:
# https://github.com/mikedh/trimesh/blob/master/docker/builds/openctm.bash
# ------------------------------------------------------------------------------
# Copyright (c) 2009-2010 Marcus Geelnard
#
# This software is provided 'as-is', without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software. If you use this software
# in a product, an acknowledgment in the product documentation would be
# appreciated but is not required.
#
# 2. Altered source versions must be plainly marked as such, and must not
# be misrepresented as being the original software.
#
# 3. This notice may not be removed or altered from any source
# distribution.
# ------------------------------------------------------------------------------
import os
import ctypes
_ctm_loaders = {}
_ctm_lib = None
try:
if os.name == 'nt':
# try to import the shared library on windows
_ctm_lib = ctypes.WinDLL('openctm.dll')
else:
# try to import on other platforms
_ctm_lib_name = ctypes.util.find_library('openctm')
if _ctm_lib_name:
_ctm_lib = ctypes.CDLL(_ctm_lib_name)
except BaseException:
pass
if _ctm_lib:
import numpy as np
# Types
CTMfloat = ctypes.c_float
CTMint = ctypes.c_int32
CTMuint = ctypes.c_uint32
CTMcontext = ctypes.c_void_p
CTMenum = ctypes.c_uint32
# boolean
CTM_TRUE = 1
CTM_FALSE = 0
# CTMenum
CTM_NONE = 0x0000
CTM_IMPORT = 0x0101
CTM_EXPORT = 0x0102
CTM_VERTEX_COUNT = 0x0301
CTM_TRIANGLE_COUNT = 0x0302
CTM_HAS_NORMALS = 0x0303
CTM_INDICES = 0x0601
CTM_VERTICES = 0x0602
CTM_NORMALS = 0x0603
# Functions
ctmNewContext = _ctm_lib.ctmNewContext
ctmNewContext.argtypes = [CTMenum]
ctmNewContext.restype = CTMcontext
ctmFreeContext = _ctm_lib.ctmFreeContext
ctmFreeContext.argtypes = [CTMcontext]
ctmGetError = _ctm_lib.ctmGetError
ctmGetError.argtypes = [CTMcontext]
ctmGetError.restype = CTMenum
ctmErrorString = _ctm_lib.ctmErrorString
ctmErrorString.argtypes = [CTMenum]
ctmErrorString.restype = ctypes.c_char_p
ctmGetInteger = _ctm_lib.ctmGetInteger
ctmGetInteger.argtypes = [CTMcontext, CTMenum]
ctmGetInteger.restype = CTMint
ctmGetFloat = _ctm_lib.ctmGetFloat
ctmGetFloat.argtypes = [CTMcontext, CTMenum]
ctmGetFloat.restype = CTMfloat
ctmGetIntegerArray = _ctm_lib.ctmGetIntegerArray
ctmGetIntegerArray.argtypes = [CTMcontext, CTMenum]
ctmGetIntegerArray.restype = ctypes.POINTER(CTMuint)
ctmGetFloatArray = _ctm_lib.ctmGetFloatArray
ctmGetFloatArray.argtypes = [CTMcontext, CTMenum]
ctmGetFloatArray.restype = ctypes.POINTER(CTMfloat)
ctmLoad = _ctm_lib.ctmLoad
ctmLoad.argtypes = [CTMcontext, ctypes.c_char_p]
ctmSave = _ctm_lib.ctmSave
ctmSave.argtypes = [CTMcontext, ctypes.c_char_p]
def load_ctm(file_obj, file_type=None, **kwargs):
"""
Load OpenCTM files from a file object.
Parameters
----------
file_obj : open file- like object
Returns
----------
loaded : dict
kwargs for a Trimesh constructor:
{vertices: (n,3) float, vertices
faces: (m,3) int, indexes of vertices}
"""
ctm = ctmNewContext(CTM_IMPORT)
# !!load file from name
# this should be replaced with something that
# actually uses the file object data to support streams
name = str(file_obj.name).encode('utf-8')
ctmLoad(ctm, name)
err = ctmGetError(ctm)
if err != CTM_NONE:
raise IOError("Error loading file: " + str(ctmErrorString(err)))
# get vertices
vertex_count = ctmGetInteger(ctm, CTM_VERTEX_COUNT)
vertex_ctm = ctmGetFloatArray(ctm, CTM_VERTICES)
# use fromiter to avoid loop
vertices = np.fromiter(vertex_ctm,
dtype=np.float,
count=vertex_count * 3).reshape((-1, 3))
# get faces
face_count = ctmGetInteger(ctm, CTM_TRIANGLE_COUNT)
face_ctm = ctmGetIntegerArray(ctm, CTM_INDICES)
faces = np.fromiter(face_ctm,
dtype=np.int,
count=face_count * 3).reshape((-1, 3))
# create kwargs for trimesh constructor
result = {'vertices': vertices,
'faces': faces}
# get face normals if available
if ctmGetInteger(ctm, CTM_HAS_NORMALS) == CTM_TRUE:
normals_ctm = ctmGetFloatArray(ctm, CTM_NORMALS)
normals = np.fromiter(normals_ctm,
dtype=np.float,
count=face_count * 3).reshape((-1, 3))
result['face_normals'] = normals
# free context
ctmFreeContext(ctm)
return result
# we have a library so add load_ctm
_ctm_loaders = {'ctm': load_ctm}