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/io/alembic/exporter/abc_writer_nurbs.cc')
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_nurbs.cc186
1 files changed, 186 insertions, 0 deletions
diff --git a/source/blender/io/alembic/exporter/abc_writer_nurbs.cc b/source/blender/io/alembic/exporter/abc_writer_nurbs.cc
new file mode 100644
index 00000000000..1fd382214a6
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_nurbs.cc
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_nurbs.h"
+#include "intern/abc_axis_conversion.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_listbase.h"
+
+#include "BKE_curve.h"
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+using Alembic::Abc::OObject;
+using Alembic::AbcGeom::FloatArraySample;
+using Alembic::AbcGeom::OBoolProperty;
+using Alembic::AbcGeom::OCompoundProperty;
+using Alembic::AbcGeom::ONuPatch;
+using Alembic::AbcGeom::ONuPatchSchema;
+
+ABCNurbsWriter::ABCNurbsWriter(const ABCWriterConstructorArgs &args) : ABCAbstractWriter(args)
+{
+}
+
+void ABCNurbsWriter::create_alembic_objects(const HierarchyContext *context)
+{
+ Curve *curve = static_cast<Curve *>(context->object->data);
+ size_t num_nurbs = BLI_listbase_count(&curve->nurb);
+ OObject abc_parent = args_.abc_parent;
+ const char *abc_parent_path = abc_parent.getFullName().c_str();
+
+ for (size_t i = 0; i < num_nurbs; i++) {
+ std::stringstream patch_name_stream;
+ patch_name_stream << args_.abc_name << '_' << i;
+
+ while (abc_parent.getChildHeader(patch_name_stream.str())) {
+ patch_name_stream << "_";
+ }
+
+ std::string patch_name = patch_name_stream.str();
+ CLOG_INFO(&LOG, 2, "exporting %s/%s", abc_parent_path, patch_name.c_str());
+
+ ONuPatch nurbs(abc_parent, patch_name.c_str(), timesample_index_);
+ abc_nurbs_.push_back(nurbs);
+ abc_nurbs_schemas_.push_back(nurbs.getSchema());
+ }
+}
+
+const OObject ABCNurbsWriter::get_alembic_object() const
+{
+ if (abc_nurbs_.empty()) {
+ return OObject();
+ }
+ /* For parenting purposes within the Alembic file, all NURBS patches are equal, so just use the
+ * first one. */
+ return abc_nurbs_[0];
+}
+
+bool ABCNurbsWriter::check_is_animated(const HierarchyContext &context) const
+{
+ /* Check if object has shape keys. */
+ Curve *cu = static_cast<Curve *>(context.object->data);
+ return (cu->key != NULL);
+}
+
+bool ABCNurbsWriter::is_supported(const HierarchyContext *context) const
+{
+ return ELEM(context->object->type, OB_SURF, OB_CURVE);
+}
+
+static void get_knots(std::vector<float> &knots, const int num_knots, float *nu_knots)
+{
+ if (num_knots <= 1) {
+ return;
+ }
+
+ /* Add an extra knot at the beginning and end of the array since most apps
+ * require/expect them. */
+ knots.reserve(num_knots + 2);
+
+ knots.push_back(0.0f);
+
+ for (int i = 0; i < num_knots; i++) {
+ knots.push_back(nu_knots[i]);
+ }
+
+ knots[0] = 2.0f * knots[1] - knots[2];
+ knots.push_back(2.0f * knots[num_knots] - knots[num_knots - 1]);
+}
+
+void ABCNurbsWriter::do_write(HierarchyContext &context)
+{
+ Curve *curve = static_cast<Curve *>(context.object->data);
+ ListBase *nulb;
+
+ if (context.object->runtime.curve_cache->deformed_nurbs.first != NULL) {
+ nulb = &context.object->runtime.curve_cache->deformed_nurbs;
+ }
+ else {
+ nulb = BKE_curve_nurbs_get(curve);
+ }
+
+ size_t count = 0;
+ for (Nurb *nu = static_cast<Nurb *>(nulb->first); nu; nu = nu->next, count++) {
+ std::vector<float> knotsU;
+ get_knots(knotsU, KNOTSU(nu), nu->knotsu);
+
+ std::vector<float> knotsV;
+ get_knots(knotsV, KNOTSV(nu), nu->knotsv);
+
+ const int size = nu->pntsu * nu->pntsv;
+ std::vector<Imath::V3f> positions(size);
+ std::vector<float> weights(size);
+
+ const BPoint *bp = nu->bp;
+
+ for (int i = 0; i < size; i++, bp++) {
+ copy_yup_from_zup(positions[i].getValue(), bp->vec);
+ weights[i] = bp->vec[3];
+ }
+
+ ONuPatchSchema::Sample sample;
+ sample.setUOrder(nu->orderu + 1);
+ sample.setVOrder(nu->orderv + 1);
+ sample.setPositions(positions);
+ sample.setPositionWeights(weights);
+ sample.setUKnot(FloatArraySample(knotsU));
+ sample.setVKnot(FloatArraySample(knotsV));
+ sample.setNu(nu->pntsu);
+ sample.setNv(nu->pntsv);
+
+ /* TODO(kevin): to accommodate other software we should duplicate control
+ * points to indicate that a NURBS is cyclic. */
+ OCompoundProperty user_props = abc_nurbs_schemas_[count].getUserProperties();
+
+ if ((nu->flagu & CU_NURB_ENDPOINT) != 0) {
+ OBoolProperty prop(user_props, "endpoint_u");
+ prop.set(true);
+ }
+
+ if ((nu->flagv & CU_NURB_ENDPOINT) != 0) {
+ OBoolProperty prop(user_props, "endpoint_v");
+ prop.set(true);
+ }
+
+ if ((nu->flagu & CU_NURB_CYCLIC) != 0) {
+ OBoolProperty prop(user_props, "cyclic_u");
+ prop.set(true);
+ }
+
+ if ((nu->flagv & CU_NURB_CYCLIC) != 0) {
+ OBoolProperty prop(user_props, "cyclic_v");
+ prop.set(true);
+ }
+
+ abc_nurbs_schemas_[count].set(sample);
+ }
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender