Depsgraph: remove EvaluationContext, pass Depsgraph instead.
[blender.git] / source / blender / alembic / intern / abc_points.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2016 K√©vin Dietrich.
19  * All rights reserved.
20  *
21  * ***** END GPL LICENSE BLOCK *****
22  *
23  */
24
25 #include "abc_points.h"
26
27 #include "abc_mesh.h"
28 #include "abc_transform.h"
29 #include "abc_util.h"
30
31 extern "C" {
32 #include "DNA_mesh_types.h"
33 #include "DNA_object_types.h"
34
35 #include "BKE_cdderivedmesh.h"
36 #include "BKE_lattice.h"
37 #include "BKE_mesh.h"
38 #include "BKE_object.h"
39 #include "BKE_particle.h"
40 #include "BKE_scene.h"
41
42 #include "BLI_math.h"
43 }
44
45 using Alembic::AbcGeom::kVertexScope;
46 using Alembic::AbcGeom::kWrapExisting;
47 using Alembic::AbcGeom::P3fArraySamplePtr;
48 using Alembic::AbcGeom::N3fArraySamplePtr;
49
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;
55
56 using Alembic::AbcGeom::OPoints;
57 using Alembic::AbcGeom::OPointsSchema;
58
59 /* ************************************************************************** */
60
61 AbcPointsWriter::AbcPointsWriter(Depsgraph *depsgraph,
62                                  Scene *scene,
63                                  Object *ob,
64                                      AbcTransformWriter *parent,
65                                      uint32_t time_sampling,
66                                      ExportSettings &settings,
67                                      ParticleSystem *psys)
68     : AbcObjectWriter(depsgraph, scene, ob, time_sampling, settings, parent)
69 {
70         m_psys = psys;
71
72         OPoints points(parent->alembicXform(), psys->name, m_time_sampling);
73         m_schema = points.getSchema();
74 }
75
76 void AbcPointsWriter::do_write()
77 {
78         if (!m_psys) {
79                 return;
80         }
81
82         std::vector<Imath::V3f> points;
83         std::vector<Imath::V3f> velocities;
84         std::vector<float> widths;
85         std::vector<uint64_t> ids;
86
87         ParticleKey state;
88
89         ParticleSimulationData sim;
90         sim.depsgraph = m_depsgraph;
91         sim.scene = m_scene;
92         sim.ob = m_object;
93         sim.psys = m_psys;
94
95         m_psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
96
97         uint64_t index = 0;
98         for (int p = 0; p < m_psys->totpart; p++) {
99                 float pos[3], vel[3];
100
101                 if (m_psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
102                         continue;
103                 }
104
105                 state.time = BKE_scene_frame_get(m_scene);
106
107                 if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
108                         continue;
109                 }
110
111                 /* location */
112                 mul_v3_m4v3(pos, m_object->imat, state.co);
113
114                 /* velocity */
115                 sub_v3_v3v3(vel, state.co, m_psys->particles[p].prev_state.co);
116
117                 /* Convert Z-up to Y-up. */
118                 points.push_back(Imath::V3f(pos[0], pos[2], -pos[1]));
119                 velocities.push_back(Imath::V3f(vel[0], vel[2], -vel[1]));
120                 widths.push_back(m_psys->particles[p].size);
121                 ids.push_back(index++);
122         }
123
124         if (m_psys->lattice_deform_data) {
125                 end_latt_deform(m_psys->lattice_deform_data);
126                 m_psys->lattice_deform_data = NULL;
127         }
128
129         Alembic::Abc::P3fArraySample psample(points);
130         Alembic::Abc::UInt64ArraySample idsample(ids);
131         Alembic::Abc::V3fArraySample vsample(velocities);
132         Alembic::Abc::FloatArraySample wsample_array(widths);
133         Alembic::AbcGeom::OFloatGeomParam::Sample wsample(wsample_array, kVertexScope);
134
135         m_sample = OPointsSchema::Sample(psample, idsample, vsample, wsample);
136         m_sample.setSelfBounds(bounds());
137
138         m_schema.set(m_sample);
139 }
140
141 /* ************************************************************************** */
142
143 AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
144     : AbcObjectReader(object, settings)
145 {
146         IPoints ipoints(m_iobject, kWrapExisting);
147         m_schema = ipoints.getSchema();
148         get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
149 }
150
151 bool AbcPointsReader::valid() const
152 {
153         return m_schema.valid();
154 }
155
156 bool AbcPointsReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
157                                           const Object *const ob,
158                                           const char **err_str) const
159 {
160         if (!Alembic::AbcGeom::IPoints::matches(alembic_header)) {
161                 *err_str = "Object type mismatch, Alembic object path pointed to Points when importing, but not any more.";
162                 return false;
163         }
164
165         if (ob->type != OB_MESH) {
166                 *err_str = "Object type mismatch, Alembic object path points to Points.";
167                 return false;
168         }
169
170         return true;
171 }
172
173 void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
174 {
175         Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
176
177         DerivedMesh *dm = CDDM_from_mesh(mesh);
178         DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, 0, NULL);
179
180         if (ndm != dm) {
181                 dm->release(dm);
182         }
183
184         DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
185
186         if (m_settings->validate_meshes) {
187                 BKE_mesh_validate(mesh, false, false);
188         }
189
190         m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
191         m_object->data = mesh;
192
193         if (has_animations(m_schema, m_settings)) {
194                 addCacheModifier();
195         }
196 }
197
198 void read_points_sample(const IPointsSchema &schema,
199                         const ISampleSelector &selector,
200                         CDStreamConfig &config)
201 {
202         Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
203
204         const P3fArraySamplePtr &positions = sample.getPositions();
205
206         ICompoundProperty prop = schema.getArbGeomParams();
207         N3fArraySamplePtr vnormals;
208
209         if (has_property(prop, "N")) {
210                 const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(selector.getRequestedTime());
211                 const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", itime);
212
213                 if (normals_prop) {
214                         vnormals = normals_prop.getValue(selector);
215                 }
216         }
217
218         read_mverts(config.mvert, positions, vnormals);
219 }
220
221 DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm,
222                                                const ISampleSelector &sample_sel,
223                                                int /*read_flag*/,
224                                                const char ** /*err_str*/)
225 {
226         const IPointsSchema::Sample sample = m_schema.getValue(sample_sel);
227
228         const P3fArraySamplePtr &positions = sample.getPositions();
229
230         DerivedMesh *new_dm = NULL;
231
232         if (dm->getNumVerts(dm) != positions->size()) {
233                 new_dm = CDDM_new(positions->size(), 0, 0, 0, 0);
234         }
235
236         CDStreamConfig config = get_config(new_dm ? new_dm : dm);
237         read_points_sample(m_schema, sample_sel, config);
238
239         return new_dm ? new_dm : dm;
240 }