diff --git a/CMakeLists.txt b/CMakeLists.txt index 95aa90d..c0a1def 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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,34 @@ else () set_target_properties(dracodec_unity PROPERTIES BUNDLE true) endif () endif () + + if (BUILD_MAYA_PLUGIN) + add_library(dracodec_maya + MODULE + ${draco_version_sources} + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $ + $) + # For Mac, we need to build a .bundle for plugin. + if (APPLE) + set_target_properties(dracodec_maya PROPERTIES BUNDLE true) + endif () + endif () + + + set(draco_header_only_targets draco_compression_attributes_pred_schemes_dec draco_dec_config @@ -883,6 +926,9 @@ else () set_target_properties(draco PROPERTIES SOVERSION 1) if (BUILD_UNITY_PLUGIN) set_target_properties(dracodec_unity PROPERTIES SOVERSION 1) + endif () + if (BUILD_MAYA_PLUGIN) + set_target_properties(dracodec_maya PROPERTIES SOVERSION 1) endif () endif () @@ -945,6 +991,11 @@ else () install(TARGETS dracodec_unity DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") endif () + if (BUILD_MAYA_PLUGIN) + install(TARGETS dracodec_maya + DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") + endif () + install(TARGETS draco_decoder draco_encoder DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") diff --git a/src/draco/maya/draco_maya_plugin.cc b/src/draco/maya/draco_maya_plugin.cc new file mode 100644 index 0000000..2a3b0e6 --- /dev/null +++ b/src/draco/maya/draco_maya_plugin.cc @@ -0,0 +1,232 @@ +// Copyright 2017 The Draco Authors. +// +// 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 &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 &drc_mesh, Drc2PyMesh* out_mesh) { + int num_vertices = drc_mesh->num_points(); + out_mesh->vertices = new float[num_vertices * 3]; + out_mesh->vertices_num = num_vertices; + + const auto pos_att = drc_mesh->GetNamedAttribute(draco::GeometryAttribute::POSITION); + 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(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]; + } + } + + + int hello() { + return 20; + } + + void fill_int(int *num) { + *num = 1982; + } + + MyStruct* fill_mystruct() { + MyStruct* my = new MyStruct(); + my->num_faces = 500; + return my; + } + + void fill_mystruct2(MyStruct** my) { + *my = new MyStruct(); + (*my)->num_faces = 900; + } + + void ReleaseMayaMesh(DracoToMayaMesh **mesh_ptr) { + DracoToMayaMesh *mesh = *mesh_ptr; + if (!mesh) + return; + if (mesh->indices) { + delete[] mesh->indices; + mesh->indices = nullptr; + } + if (mesh->position) { + delete[] mesh->position; + mesh->position = nullptr; + } + if (mesh->has_normal && mesh->normal) { + delete[] mesh->normal; + mesh->has_normal = false; + mesh->normal = nullptr; + } + if (mesh->has_texcoord && mesh->texcoord) { + delete[] mesh->texcoord; + mesh->has_texcoord = false; + mesh->texcoord = nullptr; + } + if (mesh->has_color && mesh->color) { + delete[] mesh->color; + mesh->has_color = false; + mesh->color = nullptr; + } + delete mesh; + *mesh_ptr = nullptr; + } + + int 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()) { + // TODO(zhafang): Use enum instead. + return -1; + } + const draco::EncodedGeometryType geom_type = type_statusor.value(); + if (geom_type != draco::TRIANGULAR_MESH) { + return -2; + } + + draco::Decoder decoder; + auto statusor = decoder.DecodeMeshFromBuffer(&buffer); + if (!statusor.ok()) { + return -3; + } + std::unique_ptr drc_mesh = std::move(statusor).value(); + + *res_mesh = new Drc2PyMesh(); + //(*res_mesh)->faces_num = drc_mesh->num_faces(); + //(*res_mesh)->vertices_num = drc_mesh->num_points(); + decode_faces(drc_mesh, *res_mesh); + decode_vertices(drc_mesh, *res_mesh); + + return 0; + } + + int DecodeMeshForMaya(char *data, unsigned int length, DracoToMayaMesh **tmp_mesh) { + draco::DecoderBuffer buffer; + buffer.Init(data, length); + auto type_statusor = draco::Decoder::GetEncodedGeometryType(&buffer); + if (!type_statusor.ok()) { + // TODO(zhafang): Use enum instead. + return -1; + } + const draco::EncodedGeometryType geom_type = type_statusor.value(); + if (geom_type != draco::TRIANGULAR_MESH) { + return -2; + } + + draco::Decoder decoder; + auto statusor = decoder.DecodeMeshFromBuffer(&buffer); + if (!statusor.ok()) { + return -3; + } + std::unique_ptr in_mesh = std::move(statusor).value(); + + *tmp_mesh = new DracoToMayaMesh(); + DracoToMayaMesh *unity_mesh = *tmp_mesh; + unity_mesh->num_faces = in_mesh->num_faces(); + unity_mesh->num_vertices = in_mesh->num_points(); + + unity_mesh->indices = new int[in_mesh->num_faces() * 3]; + for (draco::FaceIndex face_id(0); face_id < in_mesh->num_faces(); ++face_id) { + const Mesh::Face &face = in_mesh->face(draco::FaceIndex(face_id)); + memcpy(unity_mesh->indices + face_id.value() * 3, + reinterpret_cast(face.data()), sizeof(int) * 3); + } + + // TODO(zhafang): Add other attributes. + unity_mesh->position = new float[in_mesh->num_points() * 3]; + const auto pos_att = + in_mesh->GetNamedAttribute(draco::GeometryAttribute::POSITION); + for (draco::PointIndex i(0); i < in_mesh->num_points(); ++i) { + const draco::AttributeValueIndex val_index = pos_att->mapped_index(i); + if (!pos_att->ConvertValue( + val_index, unity_mesh->position + i.value() * 3)) { + ReleaseMayaMesh(&unity_mesh); + return -8; + } + } + // Get normal attributes. + const auto normal_att = + in_mesh->GetNamedAttribute(draco::GeometryAttribute::NORMAL); + if (normal_att != nullptr) { + unity_mesh->normal = new float[in_mesh->num_points() * 3]; + unity_mesh->has_normal = true; + for (draco::PointIndex i(0); i < in_mesh->num_points(); ++i) { + const draco::AttributeValueIndex val_index = normal_att->mapped_index(i); + if (!normal_att->ConvertValue( + val_index, unity_mesh->normal + i.value() * 3)) { + ReleaseMayaMesh(&unity_mesh); + return -8; + } + } + } + // Get color attributes. + const auto color_att = + in_mesh->GetNamedAttribute(draco::GeometryAttribute::COLOR); + if (color_att != nullptr) { + unity_mesh->color = new float[in_mesh->num_points() * 3]; + unity_mesh->has_color = true; + for (draco::PointIndex i(0); i < in_mesh->num_points(); ++i) { + const draco::AttributeValueIndex val_index = color_att->mapped_index(i); + if (!color_att->ConvertValue( + val_index, unity_mesh->color + i.value() * 3)) { + ReleaseMayaMesh(&unity_mesh); + return -8; + } + } + } + // 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( + val_index, unity_mesh->texcoord + i.value() * 3)) { + ReleaseMayaMesh(&unity_mesh); + return -8; + } + } + } + + return in_mesh->num_faces(); + } + +} // namespace maya + +} // namespace draco + +#endif // BUILD_MAYA_PLUGIN diff --git a/src/draco/maya/draco_maya_plugin.h b/src/draco/maya/draco_maya_plugin.h new file mode 100644 index 0000000..db2d051 --- /dev/null +++ b/src/draco/maya/draco_maya_plugin.h @@ -0,0 +1,102 @@ +// Copyright 2017 The Draco Authors. +// +// 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" + +#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 { + + extern "C" { + struct EXPORT_API DracoToMayaMesh { + DracoToMayaMesh() + : num_faces(0), + indices(nullptr), + num_vertices(0), + position(nullptr), + has_normal(false), + normal(nullptr), + has_texcoord(false), + texcoord(nullptr), + has_color(false), + color(nullptr) {} + + int num_faces; + int *indices; + int num_vertices; + float *position; + bool has_normal; + float *normal; + bool has_texcoord; + float *texcoord; + bool has_color; + float *color; + }; + + void ReleaseMayaMesh(DracoToMayaMesh **mesh_ptr); + + /* To use this function, you do not allocate memory for |tmp_mesh|, just + * define and pass a null pointer. Otherwise there will be memory leak. + */ + int EXPORT_API DecodeMeshForMaya(char *data, unsigned int length, DracoToMayaMesh **tmp_mesh); + + + struct EXPORT_API Drc2PyMesh { + Drc2PyMesh() + : faces_num(0), + vertices_num(0) {} + int faces_num; + int* faces; + int vertices_num; + float* vertices; + }; + + EXPORT_API int drc2py_decode(char *data, unsigned int length, Drc2PyMesh **res_mesh); + + + + struct EXPORT_API MyStruct { + MyStruct() + : num_faces(0) {} + //indices(nullptr) {} + int num_faces; + //int *indices; + }; + int EXPORT_API hello(); + void EXPORT_API fill_int(int *num); + + EXPORT_API MyStruct* fill_mystruct(); + EXPORT_API void fill_mystruct2(MyStruct** my); + + } // extern "C" + + } // namespace maya +} // namespace draco + +#endif // BUILD_MAYA_PLUGIN + +#endif // DRACO_MAYA_PLUGIN_H_