Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/pointcache/alembic/abc_customdata.cpp')
-rw-r--r--source/blender/pointcache/alembic/abc_customdata.cpp804
1 files changed, 804 insertions, 0 deletions
diff --git a/source/blender/pointcache/alembic/abc_customdata.cpp b/source/blender/pointcache/alembic/abc_customdata.cpp
new file mode 100644
index 00000000000..77a9ea73a5b
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_customdata.cpp
@@ -0,0 +1,804 @@
+/*
+ * Copyright 2015, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <sstream>
+
+#include <Alembic/AbcGeom/IGeomParam.h>
+#include <Alembic/AbcGeom/OGeomParam.h>
+
+#include "abc_customdata.h"
+
+extern "C" {
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_customdata.h"
+}
+
+namespace PTC {
+
+using namespace Abc;
+using namespace AbcGeom;
+
+/* DEBUG */
+BLI_INLINE void print_writer_compound(OCompoundProperty &prop)
+{
+ CompoundPropertyWriterPtr ptr = prop.getPtr()->asCompoundPtr();
+ printf("compound %s: [%p] (%d)\n", ptr->getName().c_str(), ptr.get(), (int)ptr->getNumProperties());
+ for (int i = 0; i < ptr->getNumProperties(); ++i) {
+ printf(" %d: [%p]\n", i, prop.getProperty(i).getPtr().get());
+ printf(" %s\n", prop.getProperty(i).getName().c_str());
+ }
+}
+
+/* ========================================================================= */
+
+template <CustomDataType CDTYPE>
+static void write_sample(CustomDataWriter */*writer*/, OCompoundProperty &/*parent*/, const std::string &/*name*/, void */*data*/, int /*num_data*/)
+{
+ /* no implementation available, should not happen */
+ printf("ERROR: CustomData type %s has no write_sample implementation\n", CustomData_layertype_name((int)CDTYPE));
+}
+
+template <>
+void write_sample<CD_MDEFORMVERT>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OCompoundProperty prop = writer->add_compound_property<OCompoundProperty>(name, parent);
+
+ OInt32ArrayProperty totweight_prop = writer->add_array_property<OInt32ArrayProperty>(name + ":totweight", prop);
+ OInt32ArrayProperty flag_prop = writer->add_array_property<OInt32ArrayProperty>(name + ":flag", prop);
+ OInt32ArrayProperty def_nr_prop = writer->add_array_property<OInt32ArrayProperty>(name + ":def_nr", prop);
+ OFloatArrayProperty weight_prop = writer->add_array_property<OFloatArrayProperty>(name + ":weight", prop);
+
+ MDeformVert *mdef = (MDeformVert *)data;
+
+ /* sum all totweight for the sample size */
+ int num_mdefweight = 0;
+ for (int i = 0; i < num_data; ++i)
+ num_mdefweight += mdef[i].totweight;
+
+ std::vector<int32_t> totweight_data;
+ std::vector<int32_t> flag_data;
+ std::vector<int32_t> def_nr_data;
+ std::vector<float> weight_data;
+ totweight_data.reserve(num_data);
+ flag_data.reserve(num_data);
+ def_nr_data.reserve(num_mdefweight);
+ weight_data.reserve(num_mdefweight);
+
+ for (int i = 0; i < num_data; ++i) {
+ totweight_data.push_back(mdef->totweight);
+ flag_data.push_back(mdef->flag);
+
+ MDeformWeight *mw = mdef->dw;
+ for (int j = 0; j < mdef->totweight; ++j) {
+ def_nr_data.push_back(mw->def_nr);
+ weight_data.push_back(mw->weight);
+
+ ++mw;
+ }
+
+ ++mdef;
+ }
+
+ totweight_prop.set(Int32ArraySample(totweight_data));
+ flag_prop.set(Int32ArraySample(flag_data));
+ def_nr_prop.set(Int32ArraySample(def_nr_data));
+ weight_prop.set(FloatArraySample(weight_data));
+}
+
+template <>
+void write_sample<CD_MTFACE>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void */*data*/, int /*num_data*/)
+{
+ /* XXX this is a dummy layer, to have access to active render layers etc. */
+ writer->add_compound_property<OCompoundProperty>(name, parent);
+}
+
+template <>
+void write_sample<CD_MCOL>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OC4fArrayProperty prop = writer->add_array_property<OC4fArrayProperty>(name, parent);
+
+ MCol *mcol = (MCol *)data;
+
+ std::vector<C4f> mcol_data;
+ mcol_data.reserve(num_data);
+ for (int i = 0; i < num_data; ++i) {
+ unsigned char icol[4] = {mcol->r, mcol->g, mcol->b, mcol->a};
+ C4f fcol;
+ rgba_uchar_to_float(fcol.getValue(), icol);
+ mcol_data.push_back(fcol);
+
+ ++mcol;
+ }
+ prop.set(OC4fArrayProperty::sample_type(mcol_data));
+}
+
+template <>
+void write_sample<CD_ORIGINDEX>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OInt32ArrayProperty prop = writer->add_array_property<OInt32ArrayProperty>(name, parent);
+
+ prop.set(OInt32ArrayProperty::sample_type((int *)data, num_data));
+}
+
+template <>
+void write_sample<CD_NORMAL>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ ON3fArrayProperty prop = writer->add_array_property<ON3fArrayProperty>(name, parent);
+
+ prop.set(ON3fArrayProperty::sample_type((N3f *)data, num_data));
+}
+
+template <>
+void write_sample<CD_ORIGSPACE>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OCompoundProperty prop = writer->add_compound_property<OCompoundProperty>(name, parent);
+
+ OV2fArrayProperty uv_prop[4];
+ uv_prop[0] = writer->add_array_property<OV2fArrayProperty>(name + ":uv0", prop);
+ uv_prop[1] = writer->add_array_property<OV2fArrayProperty>(name + ":uv1", prop);
+ uv_prop[2] = writer->add_array_property<OV2fArrayProperty>(name + ":uv2", prop);
+ uv_prop[3] = writer->add_array_property<OV2fArrayProperty>(name + ":uv3", prop);
+
+ OrigSpaceFace *ospace = (OrigSpaceFace *)data;
+ std::vector<V2f> uv_data[4];
+ uv_data[0].reserve(num_data);
+ uv_data[1].reserve(num_data);
+ uv_data[2].reserve(num_data);
+ uv_data[3].reserve(num_data);
+ for (int i = 0; i < num_data; ++i) {
+ uv_data[0].push_back(V2f(ospace->uv[0][0], ospace->uv[0][1]));
+ uv_data[1].push_back(V2f(ospace->uv[1][0], ospace->uv[1][1]));
+ uv_data[2].push_back(V2f(ospace->uv[2][0], ospace->uv[2][1]));
+ uv_data[3].push_back(V2f(ospace->uv[3][0], ospace->uv[3][1]));
+
+ ++ospace;
+ }
+ uv_prop[0].set(V2fArraySample(uv_data[0]));
+ uv_prop[1].set(V2fArraySample(uv_data[1]));
+ uv_prop[2].set(V2fArraySample(uv_data[2]));
+ uv_prop[3].set(V2fArraySample(uv_data[3]));
+}
+
+template <>
+void write_sample<CD_ORCO>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OV3fArrayProperty prop = writer->add_array_property<OV3fArrayProperty>(name, parent);
+
+ prop.set(OV3fArrayProperty::sample_type((V3f *)data, num_data));
+}
+
+template <>
+void write_sample<CD_MTEXPOLY>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void */*data*/, int /*num_data*/)
+{
+ /* XXX this is a dummy layer, to have access to active render layers etc. */
+ writer->add_compound_property<OCompoundProperty>(name, parent);
+}
+
+template <>
+void write_sample<CD_MLOOPUV>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OCompoundProperty prop = writer->add_compound_property<OCompoundProperty>(name, parent);
+
+ OV2fArrayProperty prop_uv = writer->add_array_property<OV2fArrayProperty>(name + ":uv", prop);
+ OInt32ArrayProperty prop_flag = writer->add_array_property<OInt32ArrayProperty>(name + ":flag", prop);
+
+ MLoopUV *loop_uv = (MLoopUV *)data;
+ std::vector<V2f> uv_data;
+ std::vector<int32_t> flag_data;
+ uv_data.reserve(num_data);
+ flag_data.reserve(num_data);
+ for (int i = 0; i < num_data; ++i) {
+ uv_data.push_back(V2f(loop_uv->uv[0], loop_uv->uv[1]));
+ flag_data.push_back(loop_uv->flag);
+
+ ++loop_uv;
+ }
+ prop_uv.set(V2fArraySample(uv_data));
+ prop_flag.set(Int32ArraySample(flag_data));
+}
+
+template <>
+void write_sample<CD_MLOOPCOL>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OCompoundProperty prop = writer->add_compound_property<OCompoundProperty>(name, parent);
+
+ OC4fArrayProperty prop_col = writer->add_array_property<OC4fArrayProperty>(name + ":color", prop);
+
+ MLoopCol *loop_col = (MLoopCol *)data;
+ std::vector<C4f> col_data;
+ col_data.reserve(num_data);
+ for (int i = 0; i < num_data; ++i) {
+ col_data.push_back(C4f(loop_col->r, loop_col->g, loop_col->b, loop_col->a));
+
+ ++loop_col;
+ }
+ prop_col.set(C4fArraySample(col_data));
+}
+
+template <>
+void write_sample<CD_ORIGSPACE_MLOOP>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OCompoundProperty prop = writer->add_compound_property<OCompoundProperty>(name, parent);
+
+ OV2fArrayProperty prop_uv = writer->add_array_property<OV2fArrayProperty>(name + ":uv", prop);
+
+ OrigSpaceLoop *ospaceloop = (OrigSpaceLoop *)data;
+ std::vector<V2f> uv_data;
+ uv_data.reserve(num_data);
+ for (int i = 0; i < num_data; ++i) {
+ uv_data.push_back(V2f(ospaceloop->uv[0], ospaceloop->uv[1]));
+
+ ++ospaceloop;
+ }
+ prop_uv.set(V2fArraySample(uv_data));
+}
+
+template <>
+void write_sample<CD_MSURFACE_SAMPLE>(CustomDataWriter *writer, OCompoundProperty &parent, const std::string &name, void *data, int num_data)
+{
+ OCompoundProperty prop = writer->add_compound_property<OCompoundProperty>(name, parent);
+
+ OUInt32ArrayProperty prop_orig_verts = writer->add_array_property<OUInt32ArrayProperty>(name + ":orig_verts", prop);
+ OFloatArrayProperty prop_orig_weights = writer->add_array_property<OFloatArrayProperty>(name + ":orig_weights", prop);
+ OInt32ArrayProperty prop_orig_poly = writer->add_array_property<OInt32ArrayProperty>(name + ":orig_poly", prop);
+ OUInt32ArrayProperty prop_orig_loops = writer->add_array_property<OUInt32ArrayProperty>(name + ":orig_loops", prop);
+
+ MSurfaceSample *surf = (MSurfaceSample *)data;
+ std::vector<uint32_t> orig_verts_data;
+ std::vector<float32_t> orig_weights_data;
+ std::vector<int32_t> orig_poly_data;
+ std::vector<uint32_t> orig_loops_data;
+ orig_verts_data.reserve(num_data * 3);
+ orig_weights_data.reserve(num_data * 3);
+ orig_poly_data.reserve(num_data);
+ orig_loops_data.reserve(num_data * 3);
+ for (int i = 0; i < num_data; ++i) {
+ orig_verts_data.push_back(surf->orig_verts[0]);
+ orig_verts_data.push_back(surf->orig_verts[1]);
+ orig_verts_data.push_back(surf->orig_verts[2]);
+ orig_weights_data.push_back(surf->orig_weights[0]);
+ orig_weights_data.push_back(surf->orig_weights[1]);
+ orig_weights_data.push_back(surf->orig_weights[2]);
+ orig_poly_data.push_back(surf->orig_poly);
+ orig_loops_data.push_back(surf->orig_loops[0]);
+ orig_loops_data.push_back(surf->orig_loops[1]);
+ orig_loops_data.push_back(surf->orig_loops[2]);
+
+ ++surf;
+ }
+ prop_orig_verts.set(UInt32ArraySample(orig_verts_data));
+ prop_orig_weights.set(FloatArraySample(orig_weights_data));
+ prop_orig_poly.set(Int32ArraySample(orig_poly_data));
+ prop_orig_loops.set(UInt32ArraySample(orig_loops_data));
+}
+
+/* ------------------------------------------------------------------------- */
+
+template <CustomDataType CDTYPE>
+static PTCReadSampleResult read_sample(CustomDataReader */*reader*/, ICompoundProperty &/*parent*/, const ISampleSelector &/*ss*/, const std::string &/*name*/, void */*data*/, int /*num_data*/)
+{
+ /* no implementation available, should not happen */
+ printf("ERROR: CustomData type %s has no read_sample implementation\n", CustomData_layertype_name((int)CDTYPE));
+ return PTC_READ_SAMPLE_INVALID;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_MDEFORMVERT>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ ICompoundProperty prop = reader->add_compound_property<ICompoundProperty>(name, parent);
+
+ IInt32ArrayProperty totweight_prop = reader->add_array_property<IInt32ArrayProperty>(name + ":totweight", prop);
+ IInt32ArrayProperty flag_prop = reader->add_array_property<IInt32ArrayProperty>(name + ":flag", prop);
+ IInt32ArrayProperty def_nr_prop = reader->add_array_property<IInt32ArrayProperty>(name + ":def_nr", prop);
+ IFloatArrayProperty weight_prop = reader->add_array_property<IFloatArrayProperty>(name + ":weight", prop);
+
+ Int32ArraySamplePtr sample_totweight = totweight_prop.getValue(ss);
+ Int32ArraySamplePtr sample_flag = flag_prop.getValue(ss);
+ Int32ArraySamplePtr sample_def_nr = def_nr_prop.getValue(ss);
+ FloatArraySamplePtr sample_weight = weight_prop.getValue(ss);
+
+ if (sample_totweight->size() != num_data ||
+ sample_flag->size() != num_data)
+ {
+ return PTC_READ_SAMPLE_INVALID;
+ }
+
+ const int32_t *data_totweight = (const int32_t *)sample_totweight->getData();
+ const int32_t *data_flag = (const int32_t *)sample_flag->getData();
+ const int32_t *data_def_nr = (const int32_t *)sample_def_nr->getData();
+ const float *data_weight = (const float *)sample_weight->getData();
+
+ MDeformVert *mdef = (MDeformVert *)data;
+ for (int i = 0; i < num_data; ++i) {
+
+ mdef->totweight = *data_totweight;
+ mdef->flag = *data_flag;
+
+ MDeformWeight *mw = mdef->dw = (MDeformWeight *)MEM_mallocN(sizeof(MDeformWeight) * mdef->totweight, "deformWeight");
+ for (int j = 0; j < mdef->totweight; ++j) {
+ mw->def_nr = *data_def_nr;
+ mw->weight = *data_weight;
+
+ ++data_def_nr;
+ ++data_weight;
+ ++mw;
+ }
+
+ ++data_totweight;
+ ++data_flag;
+ ++mdef;
+ }
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_MTFACE>(CustomDataReader */*reader*/, ICompoundProperty &/*parent*/, const ISampleSelector &/*ss*/, const std::string &/*name*/, void */*data*/, int /*num_data*/)
+{
+ /* XXX this is a dummy layer, to have access to active render layers etc. */
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_MCOL>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ IC4fArrayProperty prop = reader->add_array_property<IC4fArrayProperty>(name, parent);
+
+ C4fArraySamplePtr sample = prop.getValue(ss);
+
+ if (sample->size() != num_data)
+ return PTC_READ_SAMPLE_INVALID;
+
+ MCol *mcol = (MCol *)data;
+ C4f *data_mcol = (C4f *)sample->getData();
+ for (int i = 0; i < num_data; ++i) {
+ unsigned char icol[4];
+ rgba_float_to_uchar(icol, data_mcol->getValue());
+ mcol->r = icol[0];
+ mcol->g = icol[1];
+ mcol->b = icol[2];
+ mcol->a = icol[3];
+
+ ++data_mcol;
+ ++mcol;
+ }
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_ORIGINDEX>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ IInt32ArrayProperty prop = reader->add_array_property<IInt32ArrayProperty>(name, parent);
+
+ Int32ArraySamplePtr sample = prop.getValue(ss);
+
+ if (sample->size() != num_data)
+ return PTC_READ_SAMPLE_INVALID;
+
+ memcpy(data, sample->getData(), sizeof(int32_t) * num_data);
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_NORMAL>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ IN3fArrayProperty prop = reader->add_array_property<IN3fArrayProperty>(name, parent);
+
+ N3fArraySamplePtr sample = prop.getValue(ss);
+
+ if (sample->size() != num_data)
+ return PTC_READ_SAMPLE_INVALID;
+
+ memcpy(data, sample->getData(), sizeof(N3f) * num_data);
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_ORIGSPACE>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ ICompoundProperty prop = reader->add_compound_property<ICompoundProperty>(name, parent);
+
+ IV2fArrayProperty uv_prop[4];
+ uv_prop[0] = reader->add_array_property<IV2fArrayProperty>(name + ":uv0", prop);
+ uv_prop[1] = reader->add_array_property<IV2fArrayProperty>(name + ":uv1", prop);
+ uv_prop[2] = reader->add_array_property<IV2fArrayProperty>(name + ":uv2", prop);
+ uv_prop[3] = reader->add_array_property<IV2fArrayProperty>(name + ":uv3", prop);
+
+ V2fArraySamplePtr sample0 = uv_prop[0].getValue(ss);
+ V2fArraySamplePtr sample1 = uv_prop[1].getValue(ss);
+ V2fArraySamplePtr sample2 = uv_prop[2].getValue(ss);
+ V2fArraySamplePtr sample3 = uv_prop[3].getValue(ss);
+
+ if (sample0->size() != num_data ||
+ sample1->size() != num_data ||
+ sample2->size() != num_data ||
+ sample3->size() != num_data)
+ {
+ return PTC_READ_SAMPLE_INVALID;
+ }
+
+ OrigSpaceFace *ospace = (OrigSpaceFace *)data;
+ const V2f *data0 = (const V2f *)sample0->getData();
+ const V2f *data1 = (const V2f *)sample1->getData();
+ const V2f *data2 = (const V2f *)sample2->getData();
+ const V2f *data3 = (const V2f *)sample3->getData();
+ for (int i = 0; i < num_data; ++i) {
+ copy_v2_v2(ospace->uv[0], data0->getValue());
+ copy_v2_v2(ospace->uv[1], data1->getValue());
+ copy_v2_v2(ospace->uv[2], data2->getValue());
+ copy_v2_v2(ospace->uv[3], data3->getValue());
+
+ ++data0;
+ ++data1;
+ ++data2;
+ ++data3;
+ ++ospace;
+ }
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_ORCO>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ IV3fArrayProperty prop = reader->add_array_property<IV3fArrayProperty>(name, parent);
+
+ V3fArraySamplePtr sample = prop.getValue(ss);
+
+ if (sample->size() != num_data)
+ return PTC_READ_SAMPLE_INVALID;
+
+ memcpy(data, sample->getData(), sizeof(V3f) * num_data);
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_MTEXPOLY>(CustomDataReader */*reader*/, ICompoundProperty &/*parent*/, const ISampleSelector &/*ss*/, const std::string &/*name*/, void */*data*/, int /*num_data*/)
+{
+ /* XXX this is a dummy layer, to have access to active render layers etc. */
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_MLOOPUV>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ ICompoundProperty prop = reader->add_compound_property<ICompoundProperty>(name, parent);
+
+ IV2fArrayProperty uv_prop = reader->add_array_property<IV2fArrayProperty>(name + ":uv", prop);
+ IInt32ArrayProperty flag_prop = reader->add_array_property<IInt32ArrayProperty>(name + ":flag", prop);
+
+ V2fArraySamplePtr uv_sample = uv_prop.getValue(ss);
+ Int32ArraySamplePtr flag_sample = flag_prop.getValue(ss);
+
+ if (uv_sample->size() != num_data || flag_sample->size() != num_data)
+ return PTC_READ_SAMPLE_INVALID;
+
+ MLoopUV *loop_uv = (MLoopUV *)data;
+ const V2f *uv_data = (const V2f *)uv_sample->getData();
+ const int32_t *flag_data = (const int32_t *)flag_sample->getData();
+ for (int i = 0; i < num_data; ++i) {
+ copy_v2_v2(loop_uv->uv, uv_data->getValue());
+ loop_uv->flag = *flag_data;
+
+ ++uv_data;
+ ++flag_data;
+ ++loop_uv;
+ }
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_MLOOPCOL>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ ICompoundProperty prop = reader->add_compound_property<ICompoundProperty>(name, parent);
+
+ IC4fArrayProperty col_prop = reader->add_array_property<IC4fArrayProperty>(name + ":color", prop);
+
+ C4fArraySamplePtr col_sample = col_prop.getValue(ss);
+
+ if (col_sample->size() != num_data)
+ return PTC_READ_SAMPLE_INVALID;
+
+ MLoopCol *loop_col = (MLoopCol *)data;
+ const C4f *col_data = (const C4f *)col_sample->getData();
+ for (int i = 0; i < num_data; ++i) {
+ loop_col->r = col_data->r;
+ loop_col->g = col_data->g;
+ loop_col->b = col_data->b;
+ loop_col->a = col_data->a;
+
+ ++col_data;
+ ++loop_col;
+ }
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_ORIGSPACE_MLOOP>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ ICompoundProperty prop = reader->add_compound_property<ICompoundProperty>(name, parent);
+
+ IV2fArrayProperty uv_prop = reader->add_array_property<IV2fArrayProperty>(name + ":uv", prop);
+
+ V2fArraySamplePtr sample = uv_prop.getValue(ss);
+
+ if (sample->size() != num_data)
+ return PTC_READ_SAMPLE_INVALID;
+
+ OrigSpaceLoop *ospace = (OrigSpaceLoop *)data;
+ const V2f *sample_data = (const V2f *)sample->getData();
+ for (int i = 0; i < num_data; ++i) {
+ copy_v2_v2(ospace->uv, sample_data->getValue());
+
+ ++sample_data;
+ ++ospace;
+ }
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+template <>
+PTCReadSampleResult read_sample<CD_MSURFACE_SAMPLE>(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, const std::string &name, void *data, int num_data)
+{
+ ICompoundProperty prop = reader->add_compound_property<ICompoundProperty>(name, parent);
+
+ IUInt32ArrayProperty orig_verts_prop = reader->add_array_property<IUInt32ArrayProperty>(name + ":orig_verts", prop);
+ IFloatArrayProperty orig_weights_prop = reader->add_array_property<IFloatArrayProperty>(name + ":orig_weights", prop);
+ IInt32ArrayProperty orig_poly_prop = reader->add_array_property<IInt32ArrayProperty>(name + ":orig_poly", prop);
+ IUInt32ArrayProperty orig_loops_prop = reader->add_array_property<IUInt32ArrayProperty>(name + ":orig_loops", prop);
+
+ UInt32ArraySamplePtr orig_verts_sample = orig_verts_prop.getValue(ss);
+ FloatArraySamplePtr orig_weights_sample = orig_weights_prop.getValue(ss);
+ Int32ArraySamplePtr orig_poly_sample = orig_poly_prop.getValue(ss);
+ UInt32ArraySamplePtr orig_loops_sample = orig_loops_prop.getValue(ss);
+
+ if (orig_verts_sample->size() != num_data*3 ||
+ orig_weights_sample->size() != num_data*3 ||
+ orig_poly_sample->size() != num_data ||
+ orig_loops_sample->size() != num_data*3)
+ return PTC_READ_SAMPLE_INVALID;
+
+ MSurfaceSample *surf = (MSurfaceSample *)data;
+ const uint32_t *orig_verts_data = (const uint32_t *)orig_verts_sample->getData();
+ const float32_t *orig_weights_data = (const float32_t *)orig_weights_sample->getData();
+ const int32_t *orig_poly_data = (const int32_t *)orig_poly_sample->getData();
+ const uint32_t *orig_loops_data = (const uint32_t *)orig_loops_sample->getData();
+ for (int i = 0; i < num_data; ++i) {
+ surf->orig_verts[0] = orig_verts_data[0];
+ surf->orig_verts[1] = orig_verts_data[1];
+ surf->orig_verts[2] = orig_verts_data[2];
+ surf->orig_weights[0] = orig_weights_data[0];
+ surf->orig_weights[1] = orig_weights_data[1];
+ surf->orig_weights[2] = orig_weights_data[2];
+ surf->orig_poly = *orig_poly_data;
+ surf->orig_loops[0] = orig_loops_data[0];
+ surf->orig_loops[1] = orig_loops_data[1];
+ surf->orig_loops[2] = orig_loops_data[2];
+
+ orig_verts_data += 3;
+ orig_weights_data += 3;
+ orig_poly_data += 1;
+ orig_loops_data += 3;
+ ++surf;
+ }
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+/* ========================================================================= */
+
+/* recursive template that handles dispatch by CD layer type */
+template <int CDTYPE>
+BLI_INLINE void write_sample_call(CustomDataWriter *writer, OCompoundProperty &parent, CustomDataType type, const std::string &name, void *data, int num_data)
+{
+ if (type == CDTYPE)
+ write_sample<(CustomDataType)CDTYPE>(writer, parent, name, data, num_data);
+ else
+ write_sample_call<CDTYPE + 1>(writer, parent, type, name, data, num_data);
+}
+
+/* terminator specialization */
+template <>
+void write_sample_call<CD_NUMTYPES>(CustomDataWriter */*writer*/, OCompoundProperty &/*parent*/, CustomDataType /*type*/, const std::string &/*name*/, void */*data*/, int /*num_data*/)
+{
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* recursive template that handles dispatch by CD layer type */
+template <int CDTYPE>
+BLI_INLINE PTCReadSampleResult read_sample_call(CustomDataReader *reader, ICompoundProperty &parent, const ISampleSelector &ss, CustomDataType type, const std::string &name, void *data, int num_data)
+{
+ if (type == CDTYPE)
+ return read_sample<(CustomDataType)CDTYPE>(reader, parent, ss, name, data, num_data);
+ else
+ return read_sample_call<CDTYPE + 1>(reader, parent, ss, type, name, data, num_data);
+}
+
+/* terminator specialization */
+template <>
+PTCReadSampleResult read_sample_call<CD_NUMTYPES>(CustomDataReader */*reader*/, ICompoundProperty &/*parent*/, const ISampleSelector &/*ss*/, CustomDataType /*type*/, const std::string &/*name*/, void */*data*/, int /*num_data*/)
+{
+ return PTC_READ_SAMPLE_INVALID;
+}
+
+/* ========================================================================= */
+
+CustomDataWriter::CustomDataWriter(const std::string &name, CustomDataMask cdmask) :
+ m_name(name),
+ m_cdmask(cdmask)
+{
+}
+
+CustomDataWriter::~CustomDataWriter()
+{
+ for (LayerPropsMap::iterator it = m_layer_props.begin(); it != m_layer_props.end(); ++it) {
+ BasePropertyWriterPtr prop = it->second;
+ if (prop)
+ prop.reset();
+ }
+}
+
+void CustomDataWriter::init(TimeSamplingPtr time_sampling)
+{
+ m_time_sampling = time_sampling;
+}
+
+/* unique property name based on either layer name or index */
+std::string CustomDataWriter::cdtype_to_name(CustomData *cdata, CustomDataType type, int n)
+{
+ const char *layertype_name = CustomData_layertype_name(type);
+ const char *layer_name = CustomData_get_layer_name(cdata, type, n);
+ std::string name;
+ if (layer_name && layer_name[0] != '\0') {
+ name = m_name + ":" + std::string(layertype_name) + ":S" + std::string(layer_name);
+ }
+ else {
+ std::stringstream ss; ss << n;
+ name = m_name + ":" + std::string(layertype_name) + ":N" + ss.str();
+ }
+ return name;
+}
+
+/* parse property name to CD layer name based on S or N prefix for named/unnamed layers */
+void CustomDataReader::cdtype_from_name(CustomData */*cdata*/, const std::string &name, int type, int *n, char *layer_name, int max_layer_name)
+{
+ const char *layertype_name = CustomData_layertype_name(type);
+ /* We can safely assume all properties in the compound share the correct prefix
+ * <m_name>:<layertype_name>:
+ * The layertype_name is only prepended to avoid name collisions
+ */
+ const size_t start = m_name.size() + 1 + strlen(layertype_name) + 1;
+
+ if (name.size() <= start) {
+ printf("ERROR: invalid CustomData layer property name '%s'\n", name.c_str());
+ *n = -1;
+ layer_name[0] = '\0';
+ }
+ else if (name[start] == 'S') {
+ /* named layer */
+ *n = -1;
+ BLI_strncpy(layer_name, name.c_str() + start + 1, max_layer_name);
+ }
+ else if (name[start] == 'N') {
+ /* unnamed layer */
+ std::istringstream ss(name.c_str() + start + 1);
+ ss >> (*n);
+ layer_name[0] = '\0';
+ }
+ else {
+ *n = -1;
+ layer_name[0] = '\0';
+ }
+}
+
+void CustomDataWriter::write_sample(CustomData *cdata, int num_data, OCompoundProperty &parent)
+{
+ /* compound property for all CD layers in the CustomData instance */
+ m_props = add_compound_property<OCompoundProperty>(m_name, parent);
+
+ for (int type = 0; type < CD_NUMTYPES; ++type) {
+ CustomDataMask mask = (1ull << type);
+ /* only use specified types */
+ if (!(mask & m_cdmask))
+ continue;
+
+ const char *layertype_name = CustomData_layertype_name(type);
+ int num = CustomData_number_of_layers(cdata, type);
+
+ bool has_props = false;
+ OCompoundProperty layertype_props;
+ for (int n = 0; n < num; ++n) {
+ /* compound for all CD layers of the same type */
+ if (!has_props) {
+ has_props = true;
+ layertype_props = add_compound_property<OCompoundProperty>(m_name + ":" + layertype_name, m_props);
+ }
+
+ std::string name = cdtype_to_name(cdata, (CustomDataType)type, n);
+ void *data = CustomData_get_layer_n(cdata, type, n);
+ write_sample_call<0>(this, layertype_props, (CustomDataType)type, name, data, num_data);
+ }
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+CustomDataReader::CustomDataReader(const std::string &name, CustomDataMask cdmask) :
+ m_name(name),
+ m_cdmask(cdmask)
+{
+}
+
+CustomDataReader::~CustomDataReader()
+{
+ for (LayerPropsMap::iterator it = m_layer_props.begin(); it != m_layer_props.end(); ++it) {
+ BasePropertyReaderPtr prop = it->second;
+ if (prop)
+ prop.reset();
+ }
+}
+
+PTCReadSampleResult CustomDataReader::read_sample(const ISampleSelector &ss, CustomData *cdata, int num_data, ICompoundProperty &parent)
+{
+ m_props = add_compound_property<ICompoundProperty>(m_name, parent);
+
+ for (int type = 0; type < CD_NUMTYPES; ++type) {
+ CustomDataMask mask = (1ull << type);
+ /* only use specified types */
+ if (!(mask & m_cdmask))
+ continue;
+
+ const char *layertype_name = CustomData_layertype_name(type);
+
+ BasePropertyReaderPtr ptr = m_props.getPtr()->asCompoundPtr()->getProperty(m_name + ":" + layertype_name);
+ if (!ptr) {
+ /* no layer of this type stored */
+ continue;
+ }
+ ICompoundProperty layertype_props(ptr->asCompoundPtr(), kWrapExisting);
+
+ for (int i = 0; i < layertype_props.getNumProperties(); ++i) {
+ const std::string &name = layertype_props.getPropertyHeader(i).getName();
+ char layer_name[MAX_CUSTOMDATA_LAYER_NAME];
+ int n;
+ void *data;
+
+ cdtype_from_name(cdata, name, type, &n, layer_name, sizeof(layer_name));
+ if (layer_name[0] == '\0')
+ data = CustomData_add_layer(cdata, type, CD_DEFAULT, NULL, num_data);
+ else
+ data = CustomData_add_layer_named(cdata, type, CD_DEFAULT, NULL, num_data, layer_name);
+
+ read_sample_call<0>(this, layertype_props, ss, (CustomDataType)type, name, data, num_data);
+ }
+ }
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+} /* namespace PTC */