Merge pull request #395 from fdefelici/maya_plugin

Maya Plugin v0.0.1
This commit is contained in:
Tom Finegan 2018-05-24 10:27:19 -07:00 committed by GitHub
commit a37163c368
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 625860 additions and 1 deletions

View File

@ -42,6 +42,7 @@ option(ENABLE_WEXTRA "" OFF)
option(IGNORE_EMPTY_BUILD_TYPE "" OFF)
option(BUILD_UNITY_PLUGIN "Build plugin library for Unity" OFF)
option(BUILD_FOR_GLTF "" OFF)
option(BUILD_MAYA_PLUGIN "Build plugin library for Maya" OFF)
if (BUILD_FOR_GLTF)
# Override settings when building for GLTF.
@ -108,6 +109,10 @@ if (BUILD_UNITY_PLUGIN)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared library for unity plugin.")
draco_enable_feature(FEATURE "BUILD_UNITY_PLUGIN")
endif ()
if (BUILD_MAYA_PLUGIN)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared library for maya plugin.")
draco_enable_feature(FEATURE "BUILD_MAYA_PLUGIN")
endif ()
if(ENABLE_EXTRA_SPEED)
if(MSVC)
@ -588,7 +593,13 @@ set(draco_unity_plug_sources
"${draco_src_root}/unity/draco_unity_plugin.cc"
"${draco_src_root}/unity/draco_unity_plugin.h")
include_directories("${draco_root}/src" "${draco_build_dir}")
set(draco_maya_plug_sources
"${draco_src_root}/maya/draco_maya_plugin.cc"
"${draco_src_root}/maya/draco_maya_plugin.h")
include_directories("${draco_root}/src" "${draco_build_dir}")
#
# Draco targets.
@ -784,7 +795,11 @@ else ()
${draco_points_enc_sources})
add_library(draco_unity_plugin OBJECT
${draco_unity_plug_sources})
add_library(draco_maya_plugin OBJECT
${draco_maya_plug_sources})
# Library targets that consume the object collections.
add_library(dracodec
${draco_version_sources}
@ -867,6 +882,43 @@ else ()
set_target_properties(dracodec_unity PROPERTIES BUNDLE true)
endif ()
endif ()
if (BUILD_MAYA_PLUGIN)
add_library(draco_maya_wrapper
MODULE
${draco_version_sources}
$<TARGET_OBJECTS:draco_maya_plugin>
$<TARGET_OBJECTS:draco_compression_attributes_pred_schemes_enc>
$<TARGET_OBJECTS:draco_attributes>
$<TARGET_OBJECTS:draco_compression_attributes_dec>
$<TARGET_OBJECTS:draco_compression_decode>
$<TARGET_OBJECTS:draco_compression_mesh_dec>
$<TARGET_OBJECTS:draco_compression_point_cloud_dec>
$<TARGET_OBJECTS:draco_compression_attributes_enc>
$<TARGET_OBJECTS:draco_compression_encode>
$<TARGET_OBJECTS:draco_compression_mesh_enc>
$<TARGET_OBJECTS:draco_compression_point_cloud_enc>
$<TARGET_OBJECTS:draco_core>
$<TARGET_OBJECTS:draco_core_bit_coders>
$<TARGET_OBJECTS:draco_enc_config>
$<TARGET_OBJECTS:draco_dec_config>
$<TARGET_OBJECTS:draco_io>
$<TARGET_OBJECTS:draco_mesh>
$<TARGET_OBJECTS:draco_metadata>
$<TARGET_OBJECTS:draco_metadata_dec>
$<TARGET_OBJECTS:draco_point_cloud>
$<TARGET_OBJECTS:draco_points_dec>
$<TARGET_OBJECTS:draco_metadata_enc>
$<TARGET_OBJECTS:draco_points_enc>)
# For Mac, we need to build a .bundle for plugin.
if (APPLE)
set_target_properties(draco_maya_wrapper PROPERTIES BUNDLE true)
endif ()
endif ()
set(draco_header_only_targets
draco_compression_attributes_pred_schemes_dec
draco_dec_config
@ -883,6 +935,9 @@ else ()
set_target_properties(draco PROPERTIES SOVERSION 1)
if (BUILD_UNITY_PLUGIN AND (NOT APPLE))
set_target_properties(dracodec_unity PROPERTIES SOVERSION 1)
endif ()
if (BUILD_MAYA_PLUGIN)
set_target_properties(draco_maya_wrapper PROPERTIES SOVERSION 1)
endif ()
endif ()
@ -945,6 +1000,11 @@ else ()
install(TARGETS dracodec_unity
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
endif ()
if (BUILD_MAYA_PLUGIN)
install(TARGETS draco_maya_wrapper
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
endif ()
install(TARGETS draco_decoder draco_encoder DESTINATION
"${CMAKE_INSTALL_PREFIX}/bin")

2
maya/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
__pycache__/
*.pyc

76
maya/README.md Normal file
View File

@ -0,0 +1,76 @@
# Description
Plugin to add support for Draco files (.drc) in Autodesk Maya.
# Features
The following `features` are offered:
* Support .drc format: TRIANGULAR MESH (no POINT CLOUD)
* Import .drc file into Maya by "Import menu" and "Drag & Drop"
* Export from Maya into .drc file by "Export Selection menu"
With the following `constraints`:
* Import feature is limited to attributes: Vertices, Normals and Uvs
* Export feature is limited to attributes: Vertices, Normals and Uvs
* Meshes has to be made of Triangular Polygons
| Read [Release doc](./RELEASE.md) for details about what is implemented and what will be done next.
# Supported OS / Maya Version
Currently the plugin has been built for the following `OS`:
* Windows x64
and tested against Maya versions:
* Maya 2017
* Maya 2018
| Note: if you want you can build the plugin for your `OS / architecture`. Refer to `Build from Sources` section
# Installation
## On Windows
1. Copy the folder `draco_maya` under Maya pluging folder.
| E.g.: C:\Users\<USER>\Documents\maya\<VERSION>\plug-ins
2. Open Maya go to menu: `Windows -> Settings\Preferences -> Plug-in Manager`
3. Use `Browse` button, point to `draco_maya` folder and select `draco_maya_plugin.py` as plugin file
# Usage
Use the regular Maya Import/Export functionalities.
# Build From Source
You can build the plugins on your own for OSX/Win/Linux. Source code for the wrapper is here: [src/draco/maya/](../src/draco/maya). Following is detailed building instruction.
### Mac OS X
On Mac OS X, run the following command to generate Xcode projects:
~~~~~ bash
$ cmake path/to/draco -G Xcode -DBUILD_MAYA_PLUGIN=ON
~~~~~
Then open the project use Xcode and build.
You should be able to find the library under:
~~~~ bash
path/to/build/Debug(or Release)/draco_maya_wrapper.bundle
~~~~
### Windows
On Windows, run the following command to generate Visual Studio projects:
32-bit version:
~~~~~ bash
cmake path/to/draco -G "Visual Studio 15 2017" -DBUILD_MAYA_PLUGIN=ON -DBUILD_SHARED_LIBS=ON
~~~~~
64-bit version:
~~~~~ bash
cmake path/to/draco -G "Visual Studio 15 2017 Win64" -DBUILD_MAYA_PLUGIN=ON -DBUILD_SHARED_LIBS=ON
~~~~~
Then open the project use VS and build.
You should be able to find the library under:
~~~~ bash
path/to/build/Debug(or Release)/draco_maya_wrapper.dll
~~~~
### Linux
[TODO]

15
maya/RELEASE.md Normal file
View File

@ -0,0 +1,15 @@
# Next Features
* Add Support for Mesh Vertex Color attribute
* Add possibility to tweak Draco Export settings from Maya
* Include binaries for Mac OS
* Include binaries for Linux
# Relase v0.0.1
* Support .drc format: TRIANGULAR MESH (no POINT CLOUD)
* Import .drc file into Maya by "Import menu" and "Drag & Drop"
* Export from Maya into .drc file by "Export Selection menu"
* Export is done using default draco settings
* Handling Mesh made of Tringular Meshes
* Mesh attributes supported: Vertices, Normals and Uvs
* Plugin built for Windows x64

View File

@ -0,0 +1,203 @@
import sys
import maya.api.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
from draco_maya_wrapper import Draco
from draco_maya_wrapper import DrcMesh
__author__ = "Mattia Pezzano, Federico de Felici, Duccio Lenkowicz"
__version__ = "0.1"
class DracoTranslator(OpenMayaMPx.MPxFileTranslator):
def __init__(self):
OpenMayaMPx.MPxFileTranslator.__init__(self)
def maya_useNewAPI(self):
return True
def haveWriteMethod(self):
return True
def haveReadMethod(self):
return True
def filter(self):
return "*.drc"
def defaultExtension(self):
return "drc"
def writer(self, fileObject, optionString, accessMode):
exportUVs = True
exportNormals = True
selection = OpenMaya.MGlobal.getActiveSelectionList()
dagIterator = OpenMaya.MItSelectionList(selection, OpenMaya.MFn.kGeometric)
drcIndices = []
drcVertices = []
drcNormals = []
drcUvs = []
indicesOffset = 0
while not dagIterator.isDone():
dagPath = dagIterator.getDagPath()
try:
fnMesh = OpenMaya.MFnMesh(dagPath)
except Exception as e:
dagIterator.next()
continue
meshPoints = fnMesh.getPoints(OpenMaya.MSpace.kWorld)
polygonsIterator = OpenMaya.MItMeshPolygon(dagPath)
meshNormals = normals = u = v = uvSetsNames = uvs = None
if exportNormals:
meshNormals = fnMesh.getNormals()
normals = {}
if exportUVs:
uvSetsNames = fnMesh.getUVSetNames()
u, v = fnMesh.getUVs(uvSetsNames[0])
uvs = {}
while not polygonsIterator.isDone():
if not polygonsIterator.hasValidTriangulation():
raise ValueError("The mesh has not valid triangulation")
polygonVertices = polygonsIterator.getVertices()
numTriangles = polygonsIterator.numTriangles()
localindices = []
for i in range(numTriangles):
points, indices = polygonsIterator.getTriangle(i)
drcIndices.append(indicesOffset)
indicesOffset += 1
drcIndices.append(indicesOffset)
indicesOffset += 1
drcIndices.append(indicesOffset)
indicesOffset += 1
localindices.append(indices[0])
localindices.append(indices[1])
localindices.append(indices[2])
localIndex = []
for gt in range(len(indices)):
for gv in range(len(polygonVertices)):
if indices[gt] == polygonVertices[gv]:
localIndex.append(gv)
break
if exportNormals:
normals[indices[0]] = meshNormals[polygonsIterator.normalIndex(localIndex[0])]
normals[indices[1]] = meshNormals[polygonsIterator.normalIndex(localIndex[1])]
normals[indices[2]] = meshNormals[polygonsIterator.normalIndex(localIndex[2])]
if exportUVs and polygonsIterator.hasUVs():
uvID = [0, 0, 0]
for vtxInPolygon in range(3):
uvID[vtxInPolygon] = polygonsIterator.getUVIndex(localIndex[vtxInPolygon], uvSetsNames[0])
uvs[indices[0]] = (u[uvID[0]], v[uvID[0]])
uvs[indices[1]] = (u[uvID[1]], v[uvID[1]])
uvs[indices[2]] = (u[uvID[2]], v[uvID[2]])
for i in localindices:
drcVertices.append(meshPoints[i].x)
drcVertices.append(meshPoints[i].y)
drcVertices.append(meshPoints[i].z)
if exportNormals:
drcNormals.append(normals[i][0])
drcNormals.append(normals[i][1])
drcNormals.append(normals[i][2])
if exportUVs and polygonsIterator.hasUVs():
drcUvs.append(uvs[i][0])
drcUvs.append(uvs[i][1])
polygonsIterator.next(None)
dagIterator.next()
drcMesh = DrcMesh()
drcMesh.faces_num = len(drcIndices) / 3
drcMesh.faces_len = len(drcIndices)
drcMesh.faces = drcIndices
drcMesh.vertices_num = len(drcVertices) / 3
drcMesh.vertices_len = len(drcVertices)
drcMesh.vertices = drcVertices
if exportNormals:
drcMesh.normals = drcNormals
drcMesh.normals_len = len(drcNormals)
drcMesh.normals_num = len(drcVertices) / 3
if exportUVs:
drcMesh.uvs = drcUvs
drcMesh.uvs_len = len(drcUvs)
drcMesh.uvs_num = len(drcVertices) / 3
draco = Draco()
draco.encode(drcMesh, fileObject.fullName())
def reader(self, fileObject, optionString, accessMode):
drc = Draco()
mesh = drc.decode(fileObject.fullName())
# vertices, normals, uvs
vertices = []
normals = []
us = OpenMaya.MFloatArray()
vs = OpenMaya.MFloatArray()
poly_count = [3] * mesh.faces_num
for n in range(mesh.vertices_num):
i = 3 * n
vertices.append(OpenMaya.MPoint(mesh.vertices[i], mesh.vertices[i + 1], mesh.vertices[i + 2]))
if mesh.normals:
normals.append(OpenMaya.MFloatVector(mesh.normals[i], mesh.normals[i + 1], mesh.normals[i + 2]))
if mesh.uvs:
i = 2 * n
us.append(mesh.uvs[i])
vs.append(mesh.uvs[i + 1])
#create mesh
fnMesh = OpenMaya.MFnMesh()
newMesh = fnMesh.create(vertices, poly_count, mesh.faces)
if mesh.normals:
fnMesh.setVertexNormals(normals, range(len(vertices)))
if mesh.uvs:
uvSetsNames = fnMesh.getUVSetNames()
fnMesh.setUVs(us, vs, uvSetsNames[0])
fnMesh.assignUVs(poly_count, mesh.faces)
fnMesh.updateSurface()
slist = OpenMaya.MGlobal.getSelectionListByName("initialShadingGroup")
initialSG = slist.getDependNode(0)
fnSG = OpenMaya.MFnSet(initialSG)
if fnSG.restriction() == OpenMaya.MFnSet.kRenderableOnly:
fnSG.addMember(newMesh)
def translatorCreator():
return OpenMayaMPx.asMPxPtr(DracoTranslator())
def initializePlugin(mobject):
print('init')
mplugin = OpenMayaMPx.MFnPlugin(
mobject, "Autodesk", __version__, "Any")
try:
mplugin.registerFileTranslator(
'drc',
None,
translatorCreator)
except Exception as e:
sys.stderr.write("Failed to register command: drc\n")
raise
def uninitializePlugin(mobject):
print('uninit')

Binary file not shown.

View File

@ -0,0 +1,123 @@
"""
Draco wrapper for Maya extensions
"""
import os
import ctypes
__author__ = "Mattia Pezzano, Federico de Felici, Duccio Lenkowicz"
__version__ = "0.1"
class Drc2PyMesh(ctypes.Structure):
_fields_ = [
("faces_num", ctypes.c_uint),
("faces", ctypes.POINTER(ctypes.c_uint)),
("vertices_num", ctypes.c_uint),
("vertices", ctypes.POINTER(ctypes.c_float)),
("normals_num", ctypes.c_uint),
("normals", ctypes.POINTER(ctypes.c_float)),
("uvs_num", ctypes.c_uint),
("uvs_real_num", ctypes.c_uint),
("uvs", ctypes.POINTER(ctypes.c_float))
]
class DrcMesh:
def __init__(self):
self.faces = []
self.faces_len = 0
self.faces_num = 0
self.vertices = []
self.vertices_len = 0
self.vertices_num = 0
self.normals = []
self.normals_len = 0
self.normals_num = 0
self.uvs = []
self.uvs_len = 0
self.uvs_num = 0
def array_to_ptr(array, size, ctype):
carr = (ctype * size)(*array)
return ctypes.cast(carr, ctypes.POINTER(ctype))
# TODO: Add integration for reading Linux lib
class Draco:
def __init__(self):
# Lib loading
dir_path = os.path.dirname(os.path.realpath(__file__))
lib_path = os.path.join(dir_path, 'draco_maya_wrapper')
self.drc_lib = ctypes.CDLL(lib_path)
# Mapping decode funct
self.drc_decode = self.drc_lib.drc2py_decode
self.drc_decode.argtype = [ ctypes.POINTER(ctypes.c_char), ctypes.c_uint, ctypes.POINTER(ctypes.POINTER(Drc2PyMesh)) ]
self.drc_decode.restype = ctypes.c_uint
# Mapping free funct
self.drc_free = self.drc_lib.drc2py_free
self.drc_free.argtype = ctypes.POINTER(ctypes.POINTER(Drc2PyMesh))
self.drc_free.restype = None
# Mapping encode funct
self.drc_encode = self.drc_lib.drc2py_encode
self.drc_encode.argtype = [ ctypes.POINTER(Drc2PyMesh), ctypes.c_char_p ]
self.drc_encode.restype = ctypes.c_uint
def decode(self, file_path):
# Open drc file
file = None
bytes = None
try:
file = open(file_path, 'rb')
bytes = file.read()
except IOError as err:
raise Exception('[ERROR] Failure opening file: ['+ os.path.realpath(file_path) + '] => ' + repr(err))
return None
finally:
if file: file.close()
# Decode drc file
size = len(bytes)
mesh_ptr = ctypes.POINTER(Drc2PyMesh)()
self.drc_decode(bytes, size, ctypes.byref(mesh_ptr))
mesh = mesh_ptr.contents
# Preparing result to decouple from ctypes types
result = type('', (), {})()
result.faces = mesh.faces[0:mesh.faces_num * 3]
result.faces_len = mesh.faces_num * 3
result.faces_num = mesh.faces_num
result.vertices = mesh.vertices[0:mesh.vertices_num * 3]
result.vertices_len = mesh.vertices_num * 3
result.vertices_num = mesh.vertices_num
result.normals = mesh.normals[0:mesh.normals_num * 3]
result.normals_len = mesh.normals_num * 3
result.normals_num = mesh.normals_num
result.uvs = mesh.uvs[0:mesh.uvs_num * 2]
result.uvs_len = mesh.uvs_num * 2
result.uvs_num = mesh.uvs_num
# Free memory allocated by the lib
self.drc_free(ctypes.byref(mesh_ptr))
mesh_ptr = None
return result
def encode(self, mesh_data, file):
mesh = Drc2PyMesh()
mesh.faces = array_to_ptr(mesh_data.faces, mesh_data.faces_num * 3, ctypes.c_uint)
mesh.faces_num = ctypes.c_uint(mesh_data.faces_num)
mesh.vertices = array_to_ptr(mesh_data.vertices, mesh_data.vertices_num * 3, ctypes.c_float)
mesh.vertices_num = ctypes.c_uint(mesh_data.vertices_num)
mesh.normals = array_to_ptr(mesh_data.normals, mesh_data.normals_num * 3, ctypes.c_float)
mesh.normals_num = ctypes.c_uint(mesh_data.normals_num)
mesh.uvs = array_to_ptr(mesh_data.uvs, mesh_data.uvs_num * 3, ctypes.c_float)
mesh.uvs_num = ctypes.c_uint(mesh_data.uvs_num)
mesh_ptr = ctypes.byref(mesh)
file_ptr = ctypes.c_char_p(file.encode())
self.drc_encode(mesh_ptr, file_ptr)

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,124 @@
import unittest
import os
import sys
dir_path = os.path.dirname(os.path.realpath(__file__))
root_path = os.path.join(dir_path, '../draco_maya')
sys.path.insert(0, root_path)
def file_del(file_path):
if os.path.isfile(file_path):
os.remove(file_path)
from draco_maya_wrapper import Draco, DrcMesh
class DracoTest(unittest.TestCase):
def setUp(self):
self.drc = Draco()
def test_decode_bunny_drc(self):
mesh = self.drc.decode(os.path.join(dir_path, 'res/bunny.drc'))
# Faces check
self.assertEqual(69451, mesh.faces_num, 'Number of faces')
self.assertEqual(208353, mesh.faces_len,'Length of faces array precalculated')
self.assertEqual(208353, len(mesh.faces),'Length of faces array by len')
# Vertices check
self.assertEqual(34834, mesh.vertices_num, 'Number of vertices')
self.assertEqual(104502, mesh.vertices_len,'Length of vertices array precalculated')
self.assertEqual(104502, len(mesh.vertices),'Length of vertices array by len')
# Normals check
self.assertEqual(0, mesh.normals_num, 'Number of normals')
self.assertEqual(0, mesh.normals_len,'Length of normals array precalculated')
self.assertEqual(0, len(mesh.normals),'Length of normals array by len')
# Uvs check
self.assertEqual(0, mesh.uvs_num, 'Number of uvs')
self.assertEqual(0, mesh.uvs_len,'Length of uvs ')
self.assertEqual(0, len(mesh.uvs),'Length of uvs array by len')
def test_decode_trooper_drc(self):
mesh = self.drc.decode(os.path.join(dir_path, 'res/stormtrooper.drc'))
# Faces check
self.assertEqual(6518, mesh.faces_num, 'Number of faces')
self.assertEqual(19554, mesh.faces_len,'Length of faces array precalculated')
self.assertEqual(19554, len(mesh.faces),'Length of faces array by len')
# Vertices check
self.assertEqual(5176, mesh.vertices_num, 'Number of vertices')
self.assertEqual(15528, mesh.vertices_len,'Length of vertices array precalculated')
self.assertEqual(15528, len(mesh.vertices),'Length of vertices array by len')
# Normals check
self.assertEqual(5176, mesh.normals_num, 'Number of normals')
self.assertEqual(15528, mesh.normals_len, 'Length of normals array precalculated')
self.assertEqual(15528, len(mesh.normals),'Length of normals array by len')
# Uvs check
self.assertEqual(5176, mesh.uvs_num, 'Number of uvs')
self.assertEqual(10352, mesh.uvs_len, 'Length of uvs array')
self.assertEqual(10352, len(mesh.uvs), 'Length of uvs array by len')
def test_decode_unexistent_drc(self):
self.assertRaises(Exception, self.drc.decode, 'res/unexistent.drc')
def test_encode_triangle_mesh(self):
mesh = DrcMesh()
mesh.faces = [0, 1, 2]
mesh.faces_num = 1
mesh.vertices = [0, 0, 0, 1, 1, 1, 2, 2, 2]
mesh.vertices_num = 3
file = os.path.join(dir_path,'triangle.drc')
file_del(file)
self.drc.encode(mesh, file)
self.assertTrue(os.path.isfile(file), 'File should exists!')
file_del(file)
def test_encode_and_decode_triangle_mesh(self):
mesh = DrcMesh()
mesh.faces = [0, 1, 2]
mesh.faces_num = 1
mesh.vertices = [0, 0, 0, 1, 1, 1, 2, 2, 2]
mesh.vertices_num = 3
file = os.path.join(dir_path, 'res/triangle.drc')
file_del(file)
self.drc.encode(mesh, file)
dmesh = self.drc.decode(file)
# Faces check
self.assertEqual(1, dmesh.faces_num, 'Number of faces')
self.assertEqual(3, dmesh.faces_len,'Length of faces array precalculated')
self.assertEqual([0, 1, 2], dmesh.faces, 'Face Array')
# Vertices check
self.assertEqual(3, dmesh.vertices_num, 'Number of vertices')
self.assertEqual(9, dmesh.vertices_len,'Length of vertices array precalculated')
self.assertEqual([0, 0, 0, 1, 1, 1, 2, 2, 2], dmesh.vertices, 'Vertex Array')
file_del(file)
def test_decode_and_encode_stoormtrup_drc(self):
# Step1: decode
mesh = self.drc.decode(os.path.join(dir_path, 'res/stormtrooper.drc'))
# Step2: encode
file = os.path.join(dir_path, 'res/stormtrooper_copy.drc')
file_del(file)
self.drc.encode(mesh, file)
# Step3: re-decode and test
dmesh = self.drc.decode(file)
# Faces check
self.assertEqual(6518, dmesh.faces_num, 'Number of faces')
self.assertEqual(19554, dmesh.faces_len,'Length of faces array precalculated')
self.assertEqual(19554, len(dmesh.faces),'Length of faces array by len')
# Vertices check
self.assertEqual(5176, dmesh.vertices_num, 'Number of vertices')
self.assertEqual(15528, dmesh.vertices_len,'Length of vertices array precalculated')
self.assertEqual(15528, len(dmesh.vertices),'Length of vertices array by len')
# Normals check
self.assertEqual(5176, dmesh.normals_num, 'Number of normals')
self.assertEqual(15528, dmesh.normals_len, 'Length of normals array precalculated')
self.assertEqual(15528, len(dmesh.normals),'Length of normals array by len')
file_del(file)
if __name__ == '__main__':
unittest.main()

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,29 @@
# Blender v2.66 (sub 1) OBJ File: ''
# www.blender.org
g Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 1.000012 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
s off
f 1/1/1 2/2/1 3/3/1 4/4/1
f 5/4/2 8/1/2 7/5/2 6/3/2
f 1/2/3 5/3/3 6/4/3 2/1/3
f 2/4/4 6/1/4 7/2/4 3/3/4
f 3/1/5 7/2/5 8/3/5 4/4/5
f 5/3/6 1/4/6 4/1/6 8/2/6

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

View File

@ -0,0 +1,9 @@
# This file uses centimeters as units for non-parametric coordinates.
v -0.500000 -0.000000 -0.917102
v 0.500000 -0.000000 -0.917102
v -0.500000 0.000000 -1.917102
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
f 1/1 2/2 3/3

View File

@ -0,0 +1,248 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "draco/maya/draco_maya_plugin.h"
#ifdef BUILD_MAYA_PLUGIN
namespace draco {
namespace maya {
static void decode_faces(std::unique_ptr<draco::Mesh> &drc_mesh, Drc2PyMesh* out_mesh) {
int num_faces = drc_mesh->num_faces();
out_mesh->faces = new int[num_faces*3];
out_mesh->faces_num = num_faces;
for (int i = 0; i < num_faces; i++) {
const draco::Mesh::Face &face = drc_mesh->face(draco::FaceIndex(i));
out_mesh->faces[i * 3 + 0] = face[0].value();
out_mesh->faces[i * 3 + 1] = face[1].value();
out_mesh->faces[i * 3 + 2] = face[2].value();
}
}
static void decode_vertices(std::unique_ptr<draco::Mesh> &drc_mesh, Drc2PyMesh* out_mesh) {
const auto pos_att = drc_mesh->GetNamedAttribute(draco::GeometryAttribute::POSITION);
if (pos_att == nullptr) {
out_mesh->vertices = new float[0];
out_mesh->vertices_num = 0;
return;
}
int num_vertices = drc_mesh->num_points();
out_mesh->vertices = new float[num_vertices * 3];
out_mesh->vertices_num = num_vertices;
for (int i = 0; i < num_vertices; i++) {
draco::PointIndex pi(i);
const draco::AttributeValueIndex val_index = pos_att->mapped_index(pi);
float out_vertex[3];
bool is_ok = pos_att->ConvertValue<float, 3>(val_index, out_vertex);
if (!is_ok) return;
out_mesh->vertices[i * 3 + 0] = out_vertex[0];
out_mesh->vertices[i * 3 + 1] = out_vertex[1];
out_mesh->vertices[i * 3 + 2] = out_vertex[2];
}
}
static void decode_normals(std::unique_ptr<draco::Mesh> &drc_mesh, Drc2PyMesh* out_mesh) {
const auto normal_att = drc_mesh->GetNamedAttribute(draco::GeometryAttribute::NORMAL);
if (normal_att == nullptr) {
out_mesh->normals = new float[0];
out_mesh->normals_num = 0;
return;
}
int num_normals = drc_mesh->num_points();
out_mesh->normals = new float[num_normals * 3];
out_mesh->normals_num = num_normals;
for (int i = 0; i < num_normals; i++) {
draco::PointIndex pi(i);
const draco::AttributeValueIndex val_index = normal_att->mapped_index(pi);
float out_normal[3];
bool is_ok = normal_att->ConvertValue<float, 3>(val_index, out_normal);
if (!is_ok) return;
out_mesh->normals[i * 3 + 0] = out_normal[0];
out_mesh->normals[i * 3 + 1] = out_normal[1];
out_mesh->normals[i * 3 + 2] = out_normal[2];
}
}
static void decode_uvs(std::unique_ptr<draco::Mesh> &drc_mesh, Drc2PyMesh* out_mesh) {
const auto uv_att = drc_mesh->GetNamedAttribute(draco::GeometryAttribute::TEX_COORD);
if (uv_att == nullptr) {
out_mesh->uvs = new float[0];
out_mesh->uvs_num = 0;
out_mesh->uvs_real_num = 0;
return;
}
int num_uvs = drc_mesh->num_points();
out_mesh->uvs = new float[num_uvs * 2];
out_mesh->uvs_num = num_uvs;
out_mesh->uvs_real_num = uv_att->size();
for (int i = 0; i < num_uvs; i++) {
draco::PointIndex pi(i);
const draco::AttributeValueIndex val_index = uv_att->mapped_index(pi);
float out_uv[2];
bool is_ok = uv_att->ConvertValue<float, 2>(val_index, out_uv);
if (!is_ok) return;
out_mesh->uvs[i * 2 + 0] = out_uv[0];
out_mesh->uvs[i * 2 + 1] = out_uv[1];
}
}
void drc2py_free(Drc2PyMesh **mesh_ptr) {
Drc2PyMesh *mesh = *mesh_ptr;
if (!mesh) return;
if (mesh->faces) {
delete[] mesh->faces;
mesh->faces = nullptr;
mesh->faces_num = 0;
}
if (mesh->vertices) {
delete[] mesh->vertices;
mesh->vertices = nullptr;
mesh->vertices_num = 0;
}
if (mesh->normals) {
delete[] mesh->normals;
mesh->normals = nullptr;
mesh->normals_num = 0;
}
if (mesh->uvs) {
delete[] mesh->uvs;
mesh->uvs = nullptr;
mesh->uvs_num = 0;
}
delete mesh;
*mesh_ptr = nullptr;
}
DecodeResult drc2py_decode(char *data, unsigned int length, Drc2PyMesh **res_mesh) {
draco::DecoderBuffer buffer;
buffer.Init(data, length);
auto type_statusor = draco::Decoder::GetEncodedGeometryType(&buffer);
if (!type_statusor.ok()) {
return DecodeResult::KO_GEOMETRY_TYPE_INVALID;
}
const draco::EncodedGeometryType geom_type = type_statusor.value();
if (geom_type != draco::TRIANGULAR_MESH) {
return DecodeResult::KO_TRIANGULAR_MESH_NOT_FOUND;
}
draco::Decoder decoder;
auto statusor = decoder.DecodeMeshFromBuffer(&buffer);
if (!statusor.ok()) {
return DecodeResult::KO_MESH_DECODING;
}
std::unique_ptr<draco::Mesh> drc_mesh = std::move(statusor).value();
*res_mesh = new Drc2PyMesh();
decode_faces(drc_mesh, *res_mesh);
decode_vertices(drc_mesh, *res_mesh);
decode_normals(drc_mesh, *res_mesh);
decode_uvs(drc_mesh, *res_mesh);
return DecodeResult::OK;
}
//As encode refereces see https://github.com/google/draco/issues/116
EncodeResult drc2py_encode(Drc2PyMesh *in_mesh, char* file_path) {
if (in_mesh->faces_num == 0) return EncodeResult::KO_WRONG_INPUT;
if (in_mesh->vertices_num == 0) return EncodeResult::KO_WRONG_INPUT;
// TODO: Add check to protect against quad faces. At the moment only Tringular faces are supported
std::unique_ptr<draco::Mesh> drc_mesh(new draco::Mesh());
// Marshall Faces
int num_faces = in_mesh->faces_num;
drc_mesh->SetNumFaces(num_faces);
for (int i = 0; i < num_faces; ++i) {
Mesh::Face face;
face[0] = in_mesh->faces[i * 3 + 0];
face[1] = in_mesh->faces[i * 3 + 1];
face[2] = in_mesh->faces[i * 3 + 2];
drc_mesh->SetFace(FaceIndex(i), face);
}
// Marshall Vertices
int num_points = in_mesh->vertices_num;
drc_mesh->set_num_points(num_points);
GeometryAttribute va;
va.Init(GeometryAttribute::POSITION, nullptr, 3, DT_FLOAT32, false, sizeof(float) * 3, 0);
int pos_att_id = drc_mesh->AddAttribute(va, true, num_points);
float point[3];
for (int i = 0; i < num_points; ++i) {
point[0] = in_mesh->vertices[i * 3 + 0];
point[1] = in_mesh->vertices[i * 3 + 1];
point[2] = in_mesh->vertices[i * 3 + 2];
drc_mesh->attribute(pos_att_id)->SetAttributeValue(AttributeValueIndex(i), point);
}
// Marshall Normals
int num_normals = in_mesh->normals_num;
int norm_att_id;
if (num_normals > 0) {
GeometryAttribute va;
va.Init(GeometryAttribute::NORMAL, nullptr, 3, DT_FLOAT32, false, sizeof(float) * 3, 0);
norm_att_id = drc_mesh->AddAttribute(va, true, num_normals);
float norm[3];
for (int i = 0; i < num_normals; ++i) {
norm[0] = in_mesh->normals[i * 3 + 0];
norm[1] = in_mesh->normals[i * 3 + 1];
norm[2] = in_mesh->normals[i * 3 + 2];
drc_mesh->attribute(norm_att_id)->SetAttributeValue(AttributeValueIndex(i), norm);
}
}
// Marshall Uvs
int num_uvs = in_mesh->uvs_num;
int uv_att_id;
if (num_uvs > 0) {
GeometryAttribute va;
va.Init(GeometryAttribute::TEX_COORD, nullptr, 2, DT_FLOAT32, false, sizeof(float) * 2, 0);
uv_att_id = drc_mesh->AddAttribute(va, true, num_uvs);
float uv[3];
for (int i = 0; i < num_uvs; ++i) {
uv[0] = in_mesh->uvs[i * 2 + 0];
uv[1] = in_mesh->uvs[i * 2 + 1];
drc_mesh->attribute(uv_att_id)->SetAttributeValue(AttributeValueIndex(i), uv);
}
}
// Deduplicate Attribs and Points
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
drc_mesh->DeduplicateAttributeValues();
drc_mesh->DeduplicatePointIds();
#endif
// Encode Mesh
draco::Encoder encoder; //Use default encode settings (See draco_encoder.cc Options struct)
draco::EncoderBuffer buffer;
const draco::Status status = encoder.EncodeMeshToBuffer(*drc_mesh, &buffer);
if (!status.ok()) {
//Use status.error_msg() to check the error
return EncodeResult::KO_MESH_ENCODING;
}
// Save to file
std::string file = file_path;
std::ofstream out_file(file, std::ios::binary);
if (!out_file) {
return EncodeResult::KO_FILE_CREATION;
}
out_file.write(buffer.data(), buffer.size());
return EncodeResult::OK;
}
} // namespace maya
} // namespace draco
#endif // BUILD_MAYA_PLUGIN

View File

@ -0,0 +1,71 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef DRACO_MAYA_PLUGIN_H_
#define DRACO_MAYA_PLUGIN_H_
//#include "draco/compression/config/compression_shared.h"
#include "draco/compression/decode.h"
#include "draco/compression/encode.h"
#include <fstream>
#ifdef BUILD_MAYA_PLUGIN
// If compiling with Visual Studio.
#if defined(_MSC_VER)
#define EXPORT_API __declspec(dllexport)
#else
// Other platforms don't need this.
#define EXPORT_API
#endif // defined(_MSC_VER)
namespace draco {
namespace maya {
enum class EncodeResult { OK=0, KO_WRONG_INPUT=-1, KO_MESH_ENCODING=-2, KO_FILE_CREATION=-3 };
enum class DecodeResult { OK=0, KO_GEOMETRY_TYPE_INVALID = -1, KO_TRIANGULAR_MESH_NOT_FOUND = -2, KO_MESH_DECODING = -3 };
extern "C" {
struct EXPORT_API Drc2PyMesh {
Drc2PyMesh()
: faces_num(0),
faces(nullptr),
vertices_num(0),
vertices(nullptr),
normals_num(0),
normals(nullptr),
uvs_num(0),
uvs_real_num(0),
uvs(nullptr) {}
int faces_num;
int* faces;
int vertices_num;
float* vertices;
int normals_num;
float* normals;
int uvs_num;
int uvs_real_num;
float* uvs;
};
EXPORT_API DecodeResult drc2py_decode(char *data, unsigned int length, Drc2PyMesh **res_mesh);
EXPORT_API void drc2py_free(Drc2PyMesh **res_mesh);
EXPORT_API EncodeResult drc2py_encode(Drc2PyMesh *in_mesh, char* file_path);
} // extern "C"
} // namespace maya
} // namespace draco
#endif // BUILD_MAYA_PLUGIN
#endif // DRACO_MAYA_PLUGIN_H_