Welcome to mirror list, hosted at ThFree Co, Russian Federation.

overlay_metaball.c « overlay « engines « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 46076a7c88bb653621bf5918702433408e393c16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 * 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.
 *
 * Copyright 2019, Blender Foundation.
 */

/** \file
 * \ingroup draw_engine
 */

#include "DRW_render.h"

#include "DNA_meta_types.h"

#include "BKE_object.h"

#include "DEG_depsgraph_query.h"

#include "ED_mball.h"

#include "overlay_private.h"

void OVERLAY_metaball_cache_init(OVERLAY_Data *vedata)
{
  OVERLAY_PassList *psl = vedata->psl;
  OVERLAY_PrivateData *pd = vedata->stl->pd;

  OVERLAY_InstanceFormats *formats = OVERLAY_shader_instance_formats_get();

#define BUF_INSTANCE DRW_shgroup_call_buffer_instance

  for (int i = 0; i < 2; i++) {
    DRWState infront_state = (DRW_state_is_select() && (i == 1)) ? DRW_STATE_IN_FRONT_SELECT : 0;
    DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
    DRW_PASS_CREATE(psl->metaball_ps[i], state | pd->clipping_state | infront_state);

    /* Reuse armature shader as it's perfect to outline ellipsoids. */
    struct GPUVertFormat *format = formats->instance_bone;
    struct GPUShader *sh = OVERLAY_shader_armature_sphere(true);
    DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->metaball_ps[i]);
    DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
    pd->mball.handle[i] = BUF_INSTANCE(grp, format, DRW_cache_bone_point_wire_outline_get());
  }
}

static void metaball_instance_data_set(
    BoneInstanceData *data, Object *ob, const float *pos, const float radius, const float color[4])
{
  /* Bone point radius is 0.05. Compensate for that. */
  mul_v3_v3fl(data->mat[0], ob->obmat[0], radius / 0.05f);
  mul_v3_v3fl(data->mat[1], ob->obmat[1], radius / 0.05f);
  mul_v3_v3fl(data->mat[2], ob->obmat[2], radius / 0.05f);
  mul_v3_m4v3(data->mat[3], ob->obmat, pos);
  /* WATCH: Reminder, alpha is wire-size. */
  OVERLAY_bone_instance_data_set_color(data, color);
}

void OVERLAY_edit_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
  const bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
  const bool is_select = DRW_state_is_select();
  OVERLAY_PrivateData *pd = vedata->stl->pd;
  MetaBall *mb = ob->data;

  const float *color;
  const float *col_radius = G_draw.block.colorMballRadius;
  const float *col_radius_select = G_draw.block.colorMballRadiusSelect;
  const float *col_stiffness = G_draw.block.colorMballStiffness;
  const float *col_stiffness_select = G_draw.block.colorMballStiffnessSelect;

  int select_id = 0;
  if (is_select) {
    select_id = ob->runtime.select_id;
  }

  LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
    const bool is_selected = (ml->flag & SELECT) != 0;
    const bool is_scale_radius = (ml->flag & MB_SCALE_RAD) != 0;
    float stiffness_radius = ml->rad * atanf(ml->s) / (float)M_PI_2;
    BoneInstanceData instdata;

    if (is_select) {
      DRW_select_load_id(select_id | MBALLSEL_RADIUS);
    }
    color = (is_selected && is_scale_radius) ? col_radius_select : col_radius;
    metaball_instance_data_set(&instdata, ob, &ml->x, ml->rad, color);
    DRW_buffer_add_entry_struct(pd->mball.handle[do_in_front], &instdata);

    if (is_select) {
      DRW_select_load_id(select_id | MBALLSEL_STIFF);
    }
    color = (is_selected && !is_scale_radius) ? col_stiffness_select : col_stiffness;
    metaball_instance_data_set(&instdata, ob, &ml->x, stiffness_radius, color);
    DRW_buffer_add_entry_struct(pd->mball.handle[do_in_front], &instdata);

    select_id += 0x10000;
  }
}

void OVERLAY_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
  const bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
  OVERLAY_PrivateData *pd = vedata->stl->pd;
  MetaBall *mb = ob->data;
  const DRWContextState *draw_ctx = DRW_context_state_get();

  float *color;
  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);

  LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
    /* Draw radius only. */
    BoneInstanceData instdata;
    metaball_instance_data_set(&instdata, ob, &ml->x, ml->rad, color);
    DRW_buffer_add_entry_struct(pd->mball.handle[do_in_front], &instdata);
  }
}

void OVERLAY_metaball_draw(OVERLAY_Data *vedata)
{
  OVERLAY_PassList *psl = vedata->psl;

  DRW_draw_pass(psl->metaball_ps[0]);
}

void OVERLAY_metaball_in_front_draw(OVERLAY_Data *vedata)
{
  OVERLAY_PassList *psl = vedata->psl;

  DRW_draw_pass(psl->metaball_ps[1]);
}