mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-08-12 20:29:04 +08:00
commit
a37163c368
@ -42,6 +42,7 @@ option(ENABLE_WEXTRA "" OFF)
|
|||||||
option(IGNORE_EMPTY_BUILD_TYPE "" OFF)
|
option(IGNORE_EMPTY_BUILD_TYPE "" OFF)
|
||||||
option(BUILD_UNITY_PLUGIN "Build plugin library for Unity" OFF)
|
option(BUILD_UNITY_PLUGIN "Build plugin library for Unity" OFF)
|
||||||
option(BUILD_FOR_GLTF "" OFF)
|
option(BUILD_FOR_GLTF "" OFF)
|
||||||
|
option(BUILD_MAYA_PLUGIN "Build plugin library for Maya" OFF)
|
||||||
|
|
||||||
if (BUILD_FOR_GLTF)
|
if (BUILD_FOR_GLTF)
|
||||||
# Override settings when building 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.")
|
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared library for unity plugin.")
|
||||||
draco_enable_feature(FEATURE "BUILD_UNITY_PLUGIN")
|
draco_enable_feature(FEATURE "BUILD_UNITY_PLUGIN")
|
||||||
endif ()
|
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(ENABLE_EXTRA_SPEED)
|
||||||
if(MSVC)
|
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.cc"
|
||||||
"${draco_src_root}/unity/draco_unity_plugin.h")
|
"${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.
|
# Draco targets.
|
||||||
@ -784,6 +795,10 @@ else ()
|
|||||||
${draco_points_enc_sources})
|
${draco_points_enc_sources})
|
||||||
add_library(draco_unity_plugin OBJECT
|
add_library(draco_unity_plugin OBJECT
|
||||||
${draco_unity_plug_sources})
|
${draco_unity_plug_sources})
|
||||||
|
add_library(draco_maya_plugin OBJECT
|
||||||
|
${draco_maya_plug_sources})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Library targets that consume the object collections.
|
# Library targets that consume the object collections.
|
||||||
add_library(dracodec
|
add_library(dracodec
|
||||||
@ -867,6 +882,43 @@ else ()
|
|||||||
set_target_properties(dracodec_unity PROPERTIES BUNDLE true)
|
set_target_properties(dracodec_unity PROPERTIES BUNDLE true)
|
||||||
endif ()
|
endif ()
|
||||||
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
|
set(draco_header_only_targets
|
||||||
draco_compression_attributes_pred_schemes_dec
|
draco_compression_attributes_pred_schemes_dec
|
||||||
draco_dec_config
|
draco_dec_config
|
||||||
@ -883,6 +935,9 @@ else ()
|
|||||||
set_target_properties(draco PROPERTIES SOVERSION 1)
|
set_target_properties(draco PROPERTIES SOVERSION 1)
|
||||||
if (BUILD_UNITY_PLUGIN AND (NOT APPLE))
|
if (BUILD_UNITY_PLUGIN AND (NOT APPLE))
|
||||||
set_target_properties(dracodec_unity PROPERTIES SOVERSION 1)
|
set_target_properties(dracodec_unity PROPERTIES SOVERSION 1)
|
||||||
|
endif ()
|
||||||
|
if (BUILD_MAYA_PLUGIN)
|
||||||
|
set_target_properties(draco_maya_wrapper PROPERTIES SOVERSION 1)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@ -945,6 +1000,11 @@ else ()
|
|||||||
install(TARGETS dracodec_unity
|
install(TARGETS dracodec_unity
|
||||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
|
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
endif ()
|
endif ()
|
||||||
|
if (BUILD_MAYA_PLUGIN)
|
||||||
|
install(TARGETS draco_maya_wrapper
|
||||||
|
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
|
endif ()
|
||||||
|
|
||||||
install(TARGETS draco_decoder draco_encoder DESTINATION
|
install(TARGETS draco_decoder draco_encoder DESTINATION
|
||||||
"${CMAKE_INSTALL_PREFIX}/bin")
|
"${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
|
||||||
|
2
maya/.gitignore
vendored
Normal file
2
maya/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.pyc
|
76
maya/README.md
Normal file
76
maya/README.md
Normal 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
15
maya/RELEASE.md
Normal 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
|
||||||
|
|
203
maya/draco_maya/draco_maya_plugin.py
Normal file
203
maya/draco_maya/draco_maya_plugin.py
Normal 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')
|
BIN
maya/draco_maya/draco_maya_wrapper.dll
Normal file
BIN
maya/draco_maya/draco_maya_wrapper.dll
Normal file
Binary file not shown.
123
maya/draco_maya/draco_maya_wrapper.py
Normal file
123
maya/draco_maya/draco_maya_wrapper.py
Normal 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)
|
||||||
|
|
BIN
maya/draco_maya_tests/bin/draco_decoder.exe
Normal file
BIN
maya/draco_maya_tests/bin/draco_decoder.exe
Normal file
Binary file not shown.
BIN
maya/draco_maya_tests/bin/draco_encoder.exe
Normal file
BIN
maya/draco_maya_tests/bin/draco_encoder.exe
Normal file
Binary file not shown.
124
maya/draco_maya_tests/draco_maya_wrapper_test.py
Normal file
124
maya/draco_maya_tests/draco_maya_wrapper_test.py
Normal 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()
|
BIN
maya/draco_maya_tests/res/bunny.drc
Normal file
BIN
maya/draco_maya_tests/res/bunny.drc
Normal file
Binary file not shown.
104285
maya/draco_maya_tests/res/bunny.obj
Normal file
104285
maya/draco_maya_tests/res/bunny.obj
Normal file
File diff suppressed because it is too large
Load Diff
BIN
maya/draco_maya_tests/res/bunny_uv.drc
Normal file
BIN
maya/draco_maya_tests/res/bunny_uv.drc
Normal file
Binary file not shown.
352871
maya/draco_maya_tests/res/bunny_uv.obj
Normal file
352871
maya/draco_maya_tests/res/bunny_uv.obj
Normal file
File diff suppressed because it is too large
Load Diff
BIN
maya/draco_maya_tests/res/cube.drc
Normal file
BIN
maya/draco_maya_tests/res/cube.drc
Normal file
Binary file not shown.
29
maya/draco_maya_tests/res/cube.obj
Normal file
29
maya/draco_maya_tests/res/cube.obj
Normal 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
|
BIN
maya/draco_maya_tests/res/dragon.drc
Normal file
BIN
maya/draco_maya_tests/res/dragon.drc
Normal file
Binary file not shown.
150016
maya/draco_maya_tests/res/dragon.obj
Normal file
150016
maya/draco_maya_tests/res/dragon.obj
Normal file
File diff suppressed because it is too large
Load Diff
BIN
maya/draco_maya_tests/res/stormtrooper.drc
Normal file
BIN
maya/draco_maya_tests/res/stormtrooper.drc
Normal file
Binary file not shown.
17727
maya/draco_maya_tests/res/stormtrooper.obj
Normal file
17727
maya/draco_maya_tests/res/stormtrooper.obj
Normal file
File diff suppressed because it is too large
Load Diff
BIN
maya/draco_maya_tests/res/stormtrooper.png
Normal file
BIN
maya/draco_maya_tests/res/stormtrooper.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
BIN
maya/draco_maya_tests/res/trig.drc
Normal file
BIN
maya/draco_maya_tests/res/trig.drc
Normal file
Binary file not shown.
9
maya/draco_maya_tests/res/trig.obj
Normal file
9
maya/draco_maya_tests/res/trig.obj
Normal 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
|
248
src/draco/maya/draco_maya_plugin.cc
Normal file
248
src/draco/maya/draco_maya_plugin.cc
Normal 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
|
71
src/draco/maya/draco_maya_plugin.h
Normal file
71
src/draco/maya/draco_maya_plugin.h
Normal 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_
|
Loading…
x
Reference in New Issue
Block a user