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) 2013 Blender Foundation.
19
* All rights reserved.
22
* Contributor(s): Blender Foundation
24
* ***** END GPL LICENSE BLOCK *****
27
/** \file blender/editors/sculpt_paint/paint_vertex_proj.c
30
* Utility functions for getting vertex locations while painting
31
* (since they may be instanced multiple times in a DerivedMesh)
34
#include "MEM_guardedalloc.h"
38
#include "DNA_mesh_types.h"
39
#include "DNA_object_types.h"
41
#include "BKE_DerivedMesh.h"
42
#include "BKE_context.h"
44
#include "ED_screen.h"
45
#include "ED_view3d.h"
47
#include "paint_intern.h" /* own include */
50
/* Opaque Structs for internal use */
52
/* stored while painting */
53
struct VertProjHandle {
65
/* only for passing to the callbacks */
66
struct VertProjUpdate {
67
struct VertProjHandle *vp_handle;
75
/* -------------------------------------------------------------------- */
78
static void vpaint_proj_dm_map_cosnos_init__map_cb(void *userData, int index, const float co[3],
79
const float no_f[3], const short no_s[3])
81
struct VertProjHandle *vp_handle = userData;
82
DMCoNo *co_no = &vp_handle->vcosnos[index];
84
/* check if we've been here before (normal should not be 0) */
85
if (!is_zero_v3(co_no->no)) {
86
/* remember that multiple dm verts share the same source vert */
87
vp_handle->use_update = true;
91
copy_v3_v3(co_no->co, co);
93
copy_v3_v3(co_no->no, no_f);
96
normal_short_to_float_v3(co_no->no, no_s);
100
static void vpaint_proj_dm_map_cosnos_init(Scene *scene, Object *ob,
101
struct VertProjHandle *vp_handle)
106
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
108
if (dm->foreachMappedVert) {
109
memset(vp_handle->vcosnos, 0, sizeof(DMCoNo) * me->totvert);
110
dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_init__map_cb, vp_handle);
113
DMCoNo *v_co_no = vp_handle->vcosnos;
115
for (a = 0; a < me->totvert; a++, v_co_no++) {
116
dm->getVertCo(dm, a, v_co_no->co);
117
dm->getVertNo(dm, a, v_co_no->no);
125
/* -------------------------------------------------------------------- */
126
/* Internal Update */
128
/* Same as init but take mouse location into account */
130
static void vpaint_proj_dm_map_cosnos_update__map_cb(void *userData, int index, const float co[3],
131
const float no_f[3], const short no_s[3])
133
struct VertProjUpdate *vp_update = userData;
134
struct VertProjHandle *vp_handle = vp_update->vp_handle;
136
DMCoNo *co_no = &vp_handle->vcosnos[index];
138
/* find closest vertex */
140
/* first find distance to this vertex */
141
float co_ss[2]; /* screenspace */
143
if (ED_view3d_project_float_object(vp_update->ar,
145
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
147
const float dist = len_squared_v2v2(vp_update->mval_fl, co_ss);
148
if (dist > vp_handle->dists[index]) {
153
vp_handle->dists[index] = dist;
156
/* continue with regular functionality */
158
copy_v3_v3(co_no->co, co);
160
copy_v3_v3(co_no->no, no_f);
163
normal_short_to_float_v3(co_no->no, no_s);
167
static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle,
168
ARegion *ar, const float mval_fl[2])
170
struct VertProjUpdate vp_update = {vp_handle, ar, mval_fl};
172
Scene *scene = vp_handle->scene;
173
Object *ob = vp_handle->ob;
177
/* quick sanity check - we shouldn't have to run this if there are no modifiers */
178
BLI_assert(ob->modifiers.first != NULL);
180
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
182
/* highly unlikely this will become unavailable once painting starts (perhaps with animated modifiers) */
183
if (LIKELY(dm->foreachMappedVert)) {
184
fill_vn_fl(vp_handle->dists, me->totvert, FLT_MAX);
186
dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update);
193
/* -------------------------------------------------------------------- */
194
/* Public Functions */
196
struct VertProjHandle *ED_vpaint_proj_handle_create(Scene *scene, Object *ob,
199
struct VertProjHandle *vp_handle = MEM_mallocN(sizeof(struct VertProjHandle), __func__);
202
/* setup the handle */
203
vp_handle->vcosnos = MEM_mallocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map");
204
vp_handle->use_update = false;
206
/* sets 'use_update' if needed */
207
vpaint_proj_dm_map_cosnos_init(scene, ob, vp_handle);
209
if (vp_handle->use_update) {
210
vp_handle->dists = MEM_mallocN(sizeof(float) * me->totvert, __func__);
213
vp_handle->scene = scene;
216
vp_handle->dists = NULL;
218
vp_handle->ob = NULL;
219
vp_handle->scene = NULL;
222
*r_vcosnos = vp_handle->vcosnos;
226
void ED_vpaint_proj_handle_update(struct VertProjHandle *vp_handle,
227
ARegion *ar, const float mval_fl[2])
229
if (vp_handle->use_update) {
230
vpaint_proj_dm_map_cosnos_update(vp_handle, ar, mval_fl);
234
void ED_vpaint_proj_handle_free(struct VertProjHandle *vp_handle)
236
if (vp_handle->use_update) {
237
MEM_freeN(vp_handle->dists);
240
MEM_freeN(vp_handle->vcosnos);
241
MEM_freeN(vp_handle);