Cleanup: let's try to avoid too much indirect header imports, makes things harder...
[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_lattice.h"
36 #include "BKE_mesh.h"
37 #include "BKE_object.h"
38 #include "BKE_particle.h"
39 #include "BKE_scene.h"
40
41 #include "BLI_math.h"
42 }
43
44 using Alembic::AbcGeom::kVertexScope;
45 using Alembic::AbcGeom::kWrapExisting;
46 using Alembic::AbcGeom::P3fArraySamplePtr;
47 using Alembic::AbcGeom::N3fArraySamplePtr;
48
49 using Alembic::AbcGeom::ICompoundProperty;
50 using Alembic::AbcGeom::IN3fArrayProperty;
51 using Alembic::AbcGeom::IPoints;
52 using Alembic::AbcGeom::IPointsSchema;
53 using Alembic::AbcGeom::ISampleSelector;
54
55 using Alembic::AbcGeom::OPoints;
56 using Alembic::AbcGeom::OPointsSchema;
57
58 /* ************************************************************************** */
59
60 AbcPointsWriter::AbcPointsWriter(Scene *scene,
61                                  Object *ob,
62                                      AbcTransformWriter *parent,
63                                      uint32_t time_sampling,
64                                      ExportSettings &settings,
65                                      ParticleSystem *psys)
66     : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
67 {
68         m_psys = psys;
69
70         OPoints points(parent->alembicXform(), m_name, m_time_sampling);
71         m_schema = points.getSchema();
72 }
73
74 void AbcPointsWriter::do_write()
75 {
76         if (!m_psys) {
77                 return;
78         }
79
80         std::vector<Imath::V3f> points;
81         std::vector<Imath::V3f> velocities;
82         std::vector<float> widths;
83         std::vector<uint64_t> ids;
84
85         ParticleKey state;
86
87         ParticleSimulationData sim;
88         sim.scene = m_scene;
89         sim.ob = m_object;
90         sim.psys = m_psys;
91
92         m_psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
93
94         uint64_t index = 0;
95         for (int p = 0; p < m_psys->totpart; p++) {
96                 float pos[3], vel[3];
97
98                 if (m_psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
99                         continue;
100                 }
101
102                 state.time = BKE_scene_frame_get(m_scene);
103
104                 if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
105                         continue;
106                 }
107
108                 /* location */
109                 mul_v3_m4v3(pos, m_object->imat, state.co);
110
111                 /* velocity */
112                 sub_v3_v3v3(vel, state.co, m_psys->particles[p].prev_state.co);
113
114                 /* Convert Z-up to Y-up. */
115                 points.push_back(Imath::V3f(pos[0], pos[2], -pos[1]));
116                 velocities.push_back(Imath::V3f(vel[0], vel[2], -vel[1]));
117                 widths.push_back(m_psys->particles[p].size);
118                 ids.push_back(index++);
119         }
120
121         if (m_psys->lattice_deform_data) {
122                 end_latt_deform(m_psys->lattice_deform_data);
123                 m_psys->lattice_deform_data = NULL;
124         }
125
126         Alembic::Abc::P3fArraySample psample(points);
127         Alembic::Abc::UInt64ArraySample idsample(ids);
128         Alembic::Abc::V3fArraySample vsample(velocities);
129         Alembic::Abc::FloatArraySample wsample_array(widths);
130         Alembic::AbcGeom::OFloatGeomParam::Sample wsample(wsample_array, kVertexScope);
131
132         m_sample = OPointsSchema::Sample(psample, idsample, vsample, wsample);
133         m_sample.setSelfBounds(bounds());
134
135         m_schema.set(m_sample);
136 }
137
138 /* ************************************************************************** */
139
140 AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
141     : AbcObjectReader(object, settings)
142 {
143         IPoints ipoints(m_iobject, kWrapExisting);
144         m_schema = ipoints.getSchema();
145         get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
146 }
147
148 bool AbcPointsReader::valid() const
149 {
150         return m_schema.valid();
151 }
152
153 void AbcPointsReader::readObjectData(Main *bmain, float time)
154 {
155         Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
156
157         const ISampleSelector sample_sel(time);
158         m_sample = m_schema.getValue(sample_sel);
159
160         const P3fArraySamplePtr &positions = m_sample.getPositions();
161         utils::mesh_add_verts(mesh, positions->size());
162
163         CDStreamConfig config = create_config(mesh);
164         read_points_sample(m_schema, sample_sel, config, time);
165
166         if (m_settings->validate_meshes) {
167                 BKE_mesh_validate(mesh, false, false);
168         }
169
170         m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
171         m_object->data = mesh;
172
173         if (has_animations(m_schema, m_settings)) {
174                 addCacheModifier();
175         }
176 }
177
178 void read_points_sample(const IPointsSchema &schema,
179                         const ISampleSelector &selector,
180                         CDStreamConfig &config,
181                         float time)
182 {
183         Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector);
184
185         const P3fArraySamplePtr &positions = sample.getPositions();
186
187         ICompoundProperty prop = schema.getArbGeomParams();
188         N3fArraySamplePtr vnormals;
189
190         if (has_property(prop, "N")) {
191                 const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", time);
192
193                 if (normals_prop) {
194                         vnormals = normals_prop.getValue(selector);
195                 }
196         }
197
198         read_mverts(config.mvert, positions, vnormals);
199 }