Added a encode feature on the c++ wrapper. Added more tests and some refactoring

This commit is contained in:
Federico De Felici 2018-05-13 09:52:45 +02:00
parent 676b05bd22
commit 96a1a3c276
17 changed files with 457535 additions and 145 deletions

View File

@ -884,27 +884,36 @@ else ()
endif () endif ()
if (BUILD_MAYA_PLUGIN) if (BUILD_MAYA_PLUGIN)
add_library(dracodec_maya add_library(draco_maya_wrapper
MODULE MODULE
${draco_version_sources} ${draco_version_sources}
$<TARGET_OBJECTS:draco_maya_plugin> $<TARGET_OBJECTS:draco_maya_plugin>
$<TARGET_OBJECTS:draco_compression_attributes_pred_schemes_enc>
$<TARGET_OBJECTS:draco_attributes> $<TARGET_OBJECTS:draco_attributes>
$<TARGET_OBJECTS:draco_compression_attributes_dec> $<TARGET_OBJECTS:draco_compression_attributes_dec>
$<TARGET_OBJECTS:draco_compression_decode> $<TARGET_OBJECTS:draco_compression_decode>
$<TARGET_OBJECTS:draco_compression_mesh_dec> $<TARGET_OBJECTS:draco_compression_mesh_dec>
$<TARGET_OBJECTS:draco_compression_point_cloud_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>
$<TARGET_OBJECTS:draco_core_bit_coders> $<TARGET_OBJECTS:draco_core_bit_coders>
$<TARGET_OBJECTS:draco_enc_config>
$<TARGET_OBJECTS:draco_dec_config> $<TARGET_OBJECTS:draco_dec_config>
$<TARGET_OBJECTS:draco_io> $<TARGET_OBJECTS:draco_io>
$<TARGET_OBJECTS:draco_mesh> $<TARGET_OBJECTS:draco_mesh>
$<TARGET_OBJECTS:draco_metadata> $<TARGET_OBJECTS:draco_metadata>
$<TARGET_OBJECTS:draco_metadata_dec> $<TARGET_OBJECTS:draco_metadata_dec>
$<TARGET_OBJECTS:draco_point_cloud> $<TARGET_OBJECTS:draco_point_cloud>
$<TARGET_OBJECTS:draco_points_dec>) $<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. # For Mac, we need to build a .bundle for plugin.
if (APPLE) if (APPLE)
set_target_properties(dracodec_maya PROPERTIES BUNDLE true) set_target_properties(draco_maya_wrapper PROPERTIES BUNDLE true)
endif () endif ()
endif () endif ()
@ -928,7 +937,7 @@ else ()
set_target_properties(dracodec_unity PROPERTIES SOVERSION 1) set_target_properties(dracodec_unity PROPERTIES SOVERSION 1)
endif () endif ()
if (BUILD_MAYA_PLUGIN) if (BUILD_MAYA_PLUGIN)
set_target_properties(dracodec_maya PROPERTIES SOVERSION 1) set_target_properties(draco_maya_wrapper PROPERTIES SOVERSION 1)
endif () endif ()
endif () endif ()
@ -992,7 +1001,7 @@ else ()
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
endif () endif ()
if (BUILD_MAYA_PLUGIN) if (BUILD_MAYA_PLUGIN)
install(TARGETS dracodec_maya install(TARGETS draco_maya_wrapper
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
endif () endif ()

View File

@ -1,6 +1,68 @@
Description # Description
=========== Plugin which add support for Draco files (.drc) in Autodesk Maya.
Plugin which add support for Draco files in Autodesk Maya. # Features
Currently is supported drc file import on Windows 64bit, from the import menu or by drag & drop The following feature are offered:
* Support .drc format: TRIANGULAR MESH (no POINT CLOUD)
* Import .drc file into Maya by Import menu
* Import .drc file into Maya by Drag & Drop
With the following contraints:
* Import attributes limited to: Vertices, Normals and Uvs
# Supported OS / Maya Version
Currently the plugin works on the following OS:
* Windows x64
and tested against Maya versions:
* Maya 2017
* Maya 2018
# Installation
[TODO]: Describe installation steps
# Usage
[TODO]: Describe usate steps
# 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]

Binary file not shown.

BIN
maya/draco_maya_wrapper.dll Normal file

Binary file not shown.

View File

@ -17,17 +17,39 @@ class Drc2PyMesh(ctypes.Structure):
("normals_num", ctypes.c_uint), ("normals_num", ctypes.c_uint),
("normals", ctypes.POINTER(ctypes.c_float)), ("normals", ctypes.POINTER(ctypes.c_float)),
("uvs_num", ctypes.c_uint), ("uvs_num", ctypes.c_uint),
("uvs_real_num", ctypes.c_uint),
("uvs", ctypes.POINTER(ctypes.c_float)) ("uvs", ctypes.POINTER(ctypes.c_float))
] ]
class DrcMesh:
def __init__(self):
self.faces = []
self.faces_len = 0
self.faces_num = 0
# TODO: Add integration for UNIX 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: class Draco:
def __init__(self): def __init__(self):
# Lib loading # Lib loading
dir_path = os.path.dirname(os.path.realpath(__file__)) dir_path = os.path.dirname(os.path.realpath(__file__))
lib_path = os.path.join(dir_path, 'dracodec_maya') lib_path = os.path.join(dir_path, 'draco_maya_wrapper')
self.drc_lib = ctypes.CDLL(lib_path) self.drc_lib = ctypes.CDLL(lib_path)
# Mapping free funct # Mapping decode funct
self.drc_decode = self.drc_lib.drc2py_decode 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.argtype = [ ctypes.POINTER(ctypes.c_char), ctypes.c_uint, ctypes.POINTER(ctypes.POINTER(Drc2PyMesh)) ]
self.drc_decode.restype = ctypes.c_uint self.drc_decode.restype = ctypes.c_uint
@ -35,6 +57,10 @@ class Draco:
self.drc_free = self.drc_lib.drc2py_free self.drc_free = self.drc_lib.drc2py_free
self.drc_free.argtype = ctypes.POINTER(ctypes.POINTER(Drc2PyMesh)) self.drc_free.argtype = ctypes.POINTER(ctypes.POINTER(Drc2PyMesh))
self.drc_free.restype = None 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): def decode(self, file_path):
# Open drc file # Open drc file
@ -77,3 +103,23 @@ class Draco:
self.drc_free(ctypes.byref(mesh_ptr)) self.drc_free(ctypes.byref(mesh_ptr))
mesh_ptr = None mesh_ptr = None
return result; return result;
def encode(self, mesh_data: DrcMesh, file: str):
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)
#self.string(ctypes.c_char_p(file.encode()))

View File

@ -1,21 +0,0 @@
from dracodec_maya import Draco
drc = Draco()
mesh = drc.decode('bunny.drc')
print("\n==== FACES ====")
print(mesh.faces_num)
print(mesh.faces_len)
print(mesh.faces[0:10])
print("\n==== VERTICES ====")
print(mesh.vertices_num)
print(mesh.vertices_len)
print(mesh.vertices[0:10])
print("\n==== NORMALS ====")
print(mesh.normals_num)
print(mesh.normals_len)
print(mesh.normals) #This mesh has no normals
print("\n==== UVS ====")
print(mesh.uvs_num)
print(mesh.uvs_len)
print(mesh.uvs) #This mesh has no uvs

Binary file not shown.

104285
maya/test/bunny.obj Normal file

File diff suppressed because it is too large Load Diff

BIN
maya/test/bunny_uv.drc Normal file

Binary file not shown.

352871
maya/test/bunny_uv.obj Normal file

File diff suppressed because it is too large Load Diff

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, '..')
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, '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, '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, '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,'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, 'stormtrooper.drc'))
# Step2: encode
file = os.path.join(dir_path,'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()

View File

@ -1,58 +0,0 @@
import unittest
import os
import sys
dir_path = os.path.dirname(os.path.realpath(__file__))
root_path = os.path.join(dir_path, '..')
sys.path.insert(0, root_path)
from dracodec_maya import Draco
class DracoTest(unittest.TestCase):
def setUp(self):
self.drc = Draco()
def test_valid_bunny_drc(self):
mesh = self.drc.decode(os.path.join(dir_path, '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_valid_trooper_drc(self):
mesh = self.drc.decode(os.path.join(dir_path, '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_unexistent_drc(self):
self.assertRaises(Exception, self.drc.decode, 'unexistent.drc')
if __name__ == '__main__':
unittest.main()

BIN
maya/test/trig.drc Normal file

Binary file not shown.

9
maya/test/trig.obj Normal file
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

Binary file not shown.

View File

@ -21,7 +21,6 @@ namespace draco {
int num_faces = drc_mesh->num_faces(); int num_faces = drc_mesh->num_faces();
out_mesh->faces = new int[num_faces*3]; out_mesh->faces = new int[num_faces*3];
out_mesh->faces_num = num_faces; out_mesh->faces_num = num_faces;
for (int i = 0; i < num_faces; i++) { for (int i = 0; i < num_faces; i++) {
const draco::Mesh::Face &face = drc_mesh->face(draco::FaceIndex(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 + 0] = face[0].value();
@ -30,25 +29,27 @@ namespace draco {
} }
} }
static void decode_vertices(std::unique_ptr<draco::Mesh> &drc_mesh, Drc2PyMesh* out_mesh) { 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(); int num_vertices = drc_mesh->num_points();
out_mesh->vertices = new float[num_vertices * 3]; out_mesh->vertices = new float[num_vertices * 3];
out_mesh->vertices_num = num_vertices; out_mesh->vertices_num = num_vertices;
const auto pos_att = drc_mesh->GetNamedAttribute(draco::GeometryAttribute::POSITION);
for (int i = 0; i < num_vertices; i++) { for (int i = 0; i < num_vertices; i++) {
draco::PointIndex pi(i); draco::PointIndex pi(i);
const draco::AttributeValueIndex val_index = pos_att->mapped_index(pi); const draco::AttributeValueIndex val_index = pos_att->mapped_index(pi);
float out_vertex[3]; float out_vertex[3];
bool is_ok = pos_att->ConvertValue<float, 3>(val_index, out_vertex); bool is_ok = pos_att->ConvertValue<float, 3>(val_index, out_vertex);
if (!is_ok) return; if (!is_ok) return;
out_mesh->vertices[i * 3 + 0] = out_vertex[0]; out_mesh->vertices[i * 3 + 0] = out_vertex[0];
out_mesh->vertices[i * 3 + 1] = out_vertex[1]; out_mesh->vertices[i * 3 + 1] = out_vertex[1];
out_mesh->vertices[i * 3 + 2] = out_vertex[2]; out_mesh->vertices[i * 3 + 2] = out_vertex[2];
} }
} }
static void decode_normals(std::unique_ptr<draco::Mesh> &drc_mesh, Drc2PyMesh* out_mesh) { static void decode_normals(std::unique_ptr<draco::Mesh> &drc_mesh, Drc2PyMesh* out_mesh) {
const auto normal_att = drc_mesh->GetNamedAttribute(draco::GeometryAttribute::NORMAL); const auto normal_att = drc_mesh->GetNamedAttribute(draco::GeometryAttribute::NORMAL);
if (normal_att == nullptr) { if (normal_att == nullptr) {
@ -56,7 +57,6 @@ namespace draco {
out_mesh->normals_num = 0; out_mesh->normals_num = 0;
return; return;
} }
int num_normals = drc_mesh->num_points(); int num_normals = drc_mesh->num_points();
out_mesh->normals = new float[num_normals * 3]; out_mesh->normals = new float[num_normals * 3];
out_mesh->normals_num = num_normals; out_mesh->normals_num = num_normals;
@ -64,41 +64,35 @@ namespace draco {
for (int i = 0; i < num_normals; i++) { for (int i = 0; i < num_normals; i++) {
draco::PointIndex pi(i); draco::PointIndex pi(i);
const draco::AttributeValueIndex val_index = normal_att->mapped_index(pi); const draco::AttributeValueIndex val_index = normal_att->mapped_index(pi);
float out_normal[3]; float out_normal[3];
bool is_ok = normal_att->ConvertValue<float, 3>(val_index, out_normal); bool is_ok = normal_att->ConvertValue<float, 3>(val_index, out_normal);
if (!is_ok) return; if (!is_ok) return;
out_mesh->normals[i * 3 + 0] = out_normal[0]; out_mesh->normals[i * 3 + 0] = out_normal[0];
out_mesh->normals[i * 3 + 1] = out_normal[1]; out_mesh->normals[i * 3 + 1] = out_normal[1];
out_mesh->normals[i * 3 + 2] = out_normal[2]; out_mesh->normals[i * 3 + 2] = out_normal[2];
} }
} }
static void decode_uvs(std::unique_ptr<draco::Mesh> &drc_mesh, Drc2PyMesh* out_mesh) { 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); const auto uv_att = drc_mesh->GetNamedAttribute(draco::GeometryAttribute::TEX_COORD);
if (uv_att == nullptr) { if (uv_att == nullptr) {
out_mesh->uvs = new float[0]; out_mesh->uvs = new float[0];
out_mesh->uvs_num = 0; out_mesh->uvs_num = 0;
out_mesh->uvs_real_num = 0;
return; return;
} }
int num_uvs = drc_mesh->num_points(); int num_uvs = drc_mesh->num_points();
out_mesh->uvs = new float[num_uvs * 2]; out_mesh->uvs = new float[num_uvs * 2];
out_mesh->uvs_num = num_uvs; out_mesh->uvs_num = num_uvs;
out_mesh->uvs_real_num = uv_att->size();
for (int i = 0; i < num_uvs; i++) { for (int i = 0; i < num_uvs; i++) {
draco::PointIndex pi(i); draco::PointIndex pi(i);
const draco::AttributeValueIndex val_index = uv_att->mapped_index(pi); const draco::AttributeValueIndex val_index = uv_att->mapped_index(pi);
float out_uv[2]; float out_uv[2];
//bool is_ok = uv_att->ConvertValue<float, 3>(val_index, out_uv);
bool is_ok = uv_att->ConvertValue<float, 2>(val_index, out_uv); bool is_ok = uv_att->ConvertValue<float, 2>(val_index, out_uv);
if (!is_ok) return; if (!is_ok) return;
out_mesh->uvs[i * 2 + 0] = out_uv[0]; out_mesh->uvs[i * 2 + 0] = out_uv[0];
out_mesh->uvs[i * 2 + 1] = out_uv[1]; out_mesh->uvs[i * 2 + 1] = out_uv[1];
//out_mesh->uvs[i * 3 + 2] = out_uv[2];
} }
} }
@ -129,22 +123,22 @@ namespace draco {
*mesh_ptr = nullptr; *mesh_ptr = nullptr;
} }
int drc2py_decode(char *data, unsigned int length, Drc2PyMesh **res_mesh) { DecodeResult drc2py_decode(char *data, unsigned int length, Drc2PyMesh **res_mesh) {
draco::DecoderBuffer buffer; draco::DecoderBuffer buffer;
buffer.Init(data, length); buffer.Init(data, length);
auto type_statusor = draco::Decoder::GetEncodedGeometryType(&buffer); auto type_statusor = draco::Decoder::GetEncodedGeometryType(&buffer);
if (!type_statusor.ok()) { if (!type_statusor.ok()) {
return -1; return DecodeResult::KO_GEOMETRY_TYPE_INVALID;
} }
const draco::EncodedGeometryType geom_type = type_statusor.value(); const draco::EncodedGeometryType geom_type = type_statusor.value();
if (geom_type != draco::TRIANGULAR_MESH) { if (geom_type != draco::TRIANGULAR_MESH) {
return -2; return DecodeResult::KO_TRIANGULAR_MESH_NOT_FOUND;
} }
draco::Decoder decoder; draco::Decoder decoder;
auto statusor = decoder.DecodeMeshFromBuffer(&buffer); auto statusor = decoder.DecodeMeshFromBuffer(&buffer);
if (!statusor.ok()) { if (!statusor.ok()) {
return -3; return DecodeResult::KO_MESH_DECODING;
} }
std::unique_ptr<draco::Mesh> drc_mesh = std::move(statusor).value(); std::unique_ptr<draco::Mesh> drc_mesh = std::move(statusor).value();
@ -153,41 +147,100 @@ namespace draco {
decode_vertices(drc_mesh, *res_mesh); decode_vertices(drc_mesh, *res_mesh);
decode_normals(drc_mesh, *res_mesh); decode_normals(drc_mesh, *res_mesh);
decode_uvs(drc_mesh, *res_mesh); decode_uvs(drc_mesh, *res_mesh);
return 0; return DecodeResult::OK;
} }
/*
// Get color attributes. //As encode refereces see https://github.com/google/draco/issues/116
const auto color_att = EncodeResult drc2py_encode(Drc2PyMesh *in_mesh, char* file_path) {
in_mesh->GetNamedAttribute(draco::GeometryAttribute::COLOR); if (in_mesh->faces_num == 0) return EncodeResult::KO_WRONG_INPUT;
if (color_att != nullptr) { if (in_mesh->vertices_num == 0) return EncodeResult::KO_WRONG_INPUT;
unity_mesh->color = new float[in_mesh->num_points() * 3]; // TODO: Add check to protect against quad faces. At the moment only Tringular faces are supported
unity_mesh->has_color = true;
for (draco::PointIndex i(0); i < in_mesh->num_points(); ++i) { std::unique_ptr<draco::Mesh> drc_mesh(new draco::Mesh());
const draco::AttributeValueIndex val_index = color_att->mapped_index(i);
if (!color_att->ConvertValue<float, 3>( // Marshall Faces
val_index, unity_mesh->color + i.value() * 3)) { int num_faces = in_mesh->faces_num;
ReleaseMayaMesh(&unity_mesh); drc_mesh->SetNumFaces(num_faces);
return -8; 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);
} }
// Get texture coordinates attributes.
const auto texcoord_att =
in_mesh->GetNamedAttribute(draco::GeometryAttribute::TEX_COORD);
if (texcoord_att != nullptr) {
unity_mesh->texcoord = new float[in_mesh->num_points() * 2];
unity_mesh->has_texcoord = true;
for (draco::PointIndex i(0); i < in_mesh->num_points(); ++i) {
const draco::AttributeValueIndex val_index =
texcoord_att->mapped_index(i);
if (!texcoord_att->ConvertValue<float, 3>(
val_index, unity_mesh->texcoord + i.value() * 3)) {
ReleaseMayaMesh(&unity_mesh);
return -8;
} }
// 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 maya
} // namespace draco } // namespace draco

View File

@ -13,8 +13,10 @@
#ifndef DRACO_MAYA_PLUGIN_H_ #ifndef DRACO_MAYA_PLUGIN_H_
#define DRACO_MAYA_PLUGIN_H_ #define DRACO_MAYA_PLUGIN_H_
#include "draco/compression/config/compression_shared.h" //#include "draco/compression/config/compression_shared.h"
#include "draco/compression/decode.h" #include "draco/compression/decode.h"
#include "draco/compression/encode.h"
#include <fstream>
#ifdef BUILD_MAYA_PLUGIN #ifdef BUILD_MAYA_PLUGIN
@ -28,6 +30,11 @@
namespace draco { namespace draco {
namespace maya { 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" { extern "C" {
struct EXPORT_API Drc2PyMesh { struct EXPORT_API Drc2PyMesh {
Drc2PyMesh() Drc2PyMesh()
@ -38,6 +45,7 @@ namespace draco {
normals_num(0), normals_num(0),
normals(nullptr), normals(nullptr),
uvs_num(0), uvs_num(0),
uvs_real_num(0),
uvs(nullptr) {} uvs(nullptr) {}
int faces_num; int faces_num;
int* faces; int* faces;
@ -46,11 +54,13 @@ namespace draco {
int normals_num; int normals_num;
float* normals; float* normals;
int uvs_num; int uvs_num;
int uvs_real_num;
float* uvs; float* uvs;
}; };
EXPORT_API int drc2py_decode(char *data, unsigned int length, Drc2PyMesh **res_mesh); EXPORT_API DecodeResult drc2py_decode(char *data, unsigned int length, Drc2PyMesh **res_mesh);
EXPORT_API void drc2py_free(Drc2PyMesh **res_mesh); EXPORT_API void drc2py_free(Drc2PyMesh **res_mesh);
EXPORT_API EncodeResult drc2py_encode(Drc2PyMesh *in_mesh, char* file_path);
} // extern "C" } // extern "C"
} // namespace maya } // namespace maya