2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2016 Kévin Dietrich.
19 * All rights reserved.
21 * ***** END GPL LICENSE BLOCK *****
25 #include "abc_points.h"
28 #include "abc_transform.h"
32 #include "DNA_mesh_types.h"
33 #include "DNA_object_types.h"
35 #include "BKE_cdderivedmesh.h"
36 #include "BKE_lattice.h"
38 #include "BKE_object.h"
39 #include "BKE_particle.h"
40 #include "BKE_scene.h"
45 using Alembic::AbcGeom::kVertexScope;
46 using Alembic::AbcGeom::kWrapExisting;
47 using Alembic::AbcGeom::P3fArraySamplePtr;
48 using Alembic::AbcGeom::N3fArraySamplePtr;
50 using Alembic::AbcGeom::ICompoundProperty;
51 using Alembic::AbcGeom::IN3fArrayProperty;
52 using Alembic::AbcGeom::IPoints;
53 using Alembic::AbcGeom::IPointsSchema;
54 using Alembic::AbcGeom::ISampleSelector;
56 using Alembic::AbcGeom::OPoints;
57 using Alembic::AbcGeom::OPointsSchema;
59 /* ************************************************************************** */
61 AbcPointsWriter::AbcPointsWriter(Scene *scene,
63 AbcTransformWriter *parent,
64 uint32_t time_sampling,
65 ExportSettings &settings,
67 : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
71 OPoints points(parent->alembicXform(), psys->name, m_time_sampling);
72 m_schema = points.getSchema();
75 void AbcPointsWriter::do_write()
81 std::vector<Imath::V3f> points;
82 std::vector<Imath::V3f> velocities;
83 std::vector<float> widths;
84 std::vector<uint64_t> ids;
88 ParticleSimulationData sim;
93 m_psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
96 for (int p = 0; p < m_psys->totpart; p++) {
99 if (m_psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
103 state.time = BKE_scene_frame_get(m_scene);
105 if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
110 mul_v3_m4v3(pos, m_object->imat, state.co);
113 sub_v3_v3v3(vel, state.co, m_psys->particles[p].prev_state.co);
115 /* Convert Z-up to Y-up. */
116 points.push_back(Imath::V3f(pos[0], pos[2], -pos[1]));
117 velocities.push_back(Imath::V3f(vel[0], vel[2], -vel[1]));
118 widths.push_back(m_psys->particles[p].size);
119 ids.push_back(index++);
122 if (m_psys->lattice_deform_data) {
123 end_latt_deform(m_psys->lattice_deform_data);
124 m_psys->lattice_deform_data = NULL;
127 Alembic::Abc::P3fArraySample psample(points);
128 Alembic::Abc::UInt64ArraySample idsample(ids);
129 Alembic::Abc::V3fArraySample vsample(velocities);
130 Alembic::Abc::FloatArraySample wsample_array(widths);
131 Alembic::AbcGeom::OFloatGeomParam::Sample wsample(wsample_array, kVertexScope);
133 m_sample = OPointsSchema::Sample(psample, idsample, vsample, wsample);
134 m_sample.setSelfBounds(bounds());
136 m_schema.set(m_sample);
139 /* ************************************************************************** */
141 AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
142 : AbcObjectReader(object, settings)
144 IPoints ipoints(m_iobject, kWrapExisting);
145 m_schema = ipoints.getSchema();
146 get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
149 bool AbcPointsReader::valid() const
151 return m_schema.valid();
154 void AbcPointsReader::readObjectData(Main *bmain, float time)
156 Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
158 DerivedMesh *dm = CDDM_from_mesh(mesh);
159 DerivedMesh *ndm = this->read_derivedmesh(dm, time, 0, NULL);
165 DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
167 if (m_settings->validate_meshes) {
168 BKE_mesh_validate(mesh, false, false);
171 m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
172 m_object->data = mesh;
174 if (has_animations(m_schema, m_settings)) {
179 void read_points_sample(const IPointsSchema &schema,
180 const ISampleSelector &selector,
181 CDStreamConfig &config,
184 Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
186 const P3fArraySamplePtr &positions = sample.getPositions();
188 ICompoundProperty prop = schema.getArbGeomParams();
189 N3fArraySamplePtr vnormals;
191 if (has_property(prop, "N")) {
192 const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(time);
193 const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", itime);
196 vnormals = normals_prop.getValue(selector);
200 read_mverts(config.mvert, positions, vnormals);
203 DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char ** /*err_str*/)
205 ISampleSelector sample_sel(time);
206 const IPointsSchema::Sample sample = m_schema.getValue(sample_sel);
208 const P3fArraySamplePtr &positions = sample.getPositions();
210 DerivedMesh *new_dm = NULL;
212 if (dm->getNumVerts(dm) != positions->size()) {
213 new_dm = CDDM_new(positions->size(), 0, 0, 0, 0);
216 CDStreamConfig config = get_config(new_dm ? new_dm : dm);
217 read_points_sample(m_schema, sample_sel, config, time);
219 return new_dm ? new_dm : dm;